/*
 * Copyright (C) 2011-2020 Gary Kramlich <grim@reaperworld.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
 */

#if !defined(GPLUGIN_GLOBAL_HEADER_INSIDE) && !defined(GPLUGIN_COMPILATION)
#error "only <gplugin.h> may be included directly"
#endif

#ifndef GPLUGIN_VERSION_H
#define GPLUGIN_VERSION_H

#include <glib.h>

#include <gplugin/gplugin-version-defs.h>

/* clang-format tries to remove the space after 'if', which confuses
 * gobject-introspection, so turn it off temporarily. */
/* clang-format off */
#if (defined(_WIN32) || defined(__CYGWIN__)) && \
	!defined(GPLUGIN_STATIC_COMPILATION)
/* clang-format on */
#define _GPLUGIN_EXPORT __declspec(dllexport)
#define _GPLUGIN_IMPORT __declspec(dllimport)
#elif __GNUC__ >= 4
#define _GPLUGIN_EXPORT __attribute__((visibility("default")))
#define _GPLUGIN_IMPORT
#else
#define _GPLUGIN_EXPORT
#define _GPLUGIN_IMPORT
#endif
#ifdef GPLUGIN_COMPILATION
#define _GPLUGIN_API _GPLUGIN_EXPORT
#else
#define _GPLUGIN_API _GPLUGIN_IMPORT
#endif

#define _GPLUGIN_EXTERN _GPLUGIN_API extern

#ifdef GPLUGIN_DISABLE_DEPRECATION_WARNINGS
#define GPLUGIN_DEPRECATED _GPLUGIN_EXTERN
#define GPLUGIN_DEPRECATED_FOR(f) _GPLUGIN_EXTERN
#define GPLUGIN_UNAVAILABLE(maj, min) _GPLUGIN_EXTERN
#define GPLUGIN_UNAVAILABLE_MACRO(maj, min)
#define GPLUGIN_UNAVAILABLE_STATIC_INLINE(maj, min)
#define GPLUGIN_UNAVAILABLE_TYPE(maj, min)
#else
#define GPLUGIN_DEPRECATED G_DEPRECATED _GPLUGIN_EXTERN
#define GPLUGIN_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _GPLUGIN_EXTERN
#define GPLUGIN_UNAVAILABLE(maj, min) G_UNAVAILABLE(maj, min) _GPLUGIN_EXTERN
#define GPLUGIN_UNAVAILABLE_MACRO(maj, min) G_UNAVAILABLE_MACRO(maj, min)
#define GPLUGIN_UNAVAILABLE_STATIC_INLINE(maj, min) G_UNAVAILABLE(maj, min)
#define GPLUGIN_UNAVAILABLE_TYPE(maj, min) G_UNAVAILABLE(maj, min)
#endif

/**
 * GPLUGIN_VERSION_MIN_REQUIRED:
 *
 * A macro that should be defined by the user prior to including the
 * `gplugin.h` header.
 *
 * The definition should be one of the predefined GPlugin version macros:
 * %GPLUGIN_VERSION_0_42, %GPLUGIN_VERSION_0_43, ...
 *
 * This macro defines the earliest version of GPlugin that the package is
 * required to be able to compile against.
 *
 * If the compiler is configured to warn about the use of deprecated functions,
 * then using functions that were deprecated in version
 * %GPLUGIN_VERSION_MIN_REQUIRED or earlier will cause warnings (but using
 * functions deprecated in later releases will not).
 *
 * Since: 0.42
 */

/**
 * GPLUGIN_VERSION_CUR_STABLE:
 *
 * A macro that evaluates to the current stable version of GPlugin, in a format
 * that can be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_CUR_STABLE \
	(G_ENCODE_VERSION(GPLUGIN_MAJOR_VERSION, GPLUGIN_MINOR_VERSION))

/* If the package sets GPLUGIN_VERSION_MIN_REQUIRED to some future
 * GPLUGIN_VERSION_X_Y value that we don't know about, it will compare as 0 in
 * preprocessor tests.
 */
#ifndef GPLUGIN_VERSION_MIN_REQUIRED
#define GPLUGIN_VERSION_MIN_REQUIRED (GPLUGIN_VERSION_CUR_STABLE)
#elif GPLUGIN_VERSION_MIN_REQUIRED == 0
#undef GPLUGIN_VERSION_MIN_REQUIRED
#define GPLUGIN_VERSION_MIN_REQUIRED (GPLUGIN_VERSION_CUR_STABLE + 1)
#endif /* GPLUGIN_VERSION_MIN_REQUIRED */

#if !defined(GPLUGIN_VERSION_MAX_ALLOWED) || (GPLUGIN_VERSION_MAX_ALLOWED == 0)
#undef GPLUGIN_VERSION_MAX_ALLOWED
#define GPLUGIN_VERSION_MAX_ALLOWED (GPLUGIN_VERSION_CUR_STABLE)
#endif /* GPLUGIN_VERSION_MAX_ALLOWED */

/* sanity checks */
#if GPLUGIN_VERSION_MIN_REQUIRED > GPLUGIN_VERSION_CUR_STABLE
#error "GPLUGIN_VERSION_MIN_REQUIRED must be <= GPLUGIN_VERSION_CUR_STABLE"
#endif
#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_MIN_REQUIRED
#error "GPLUGIN_VERSION_MAX_ALLOWED must be >= GPLUGIN_VERSION_MIN_REQUIRED"
#endif
#if GPLUGIN_VERSION_MIN_REQUIRED < G_ENCODE_VERSION(0, 38)
#error "GPLUGIN_VERSION_MIN_REQUIRED must be >= GPLUGIN_VERSION_0_38"
#endif

#define GPLUGIN_AVAILABLE_IN_ALL _GPLUGIN_EXTERN

/**
 * GPLUGIN_VERSION_0_31:
 *
 * A macro that evaluates to the 0.31 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_31 (G_ENCODE_VERSION(0, 31))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_31
#define GPLUGIN_AVAILABLE_MACRO_IN_0_31 GPLUGIN_UNAVAILABLE_MACRO(0, 31)
#else
#define GPLUGIN_AVAILABLE_MACRO_IN_0_31
#endif

/**
 * GPLUGIN_VERSION_0_32:
 *
 * A macro that evaluates to the 0.32 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_32 (G_ENCODE_VERSION(0, 32))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_32
#define GPLUGIN_AVAILABLE_IN_0_32 GPLUGIN_UNAVAILABLE(0, 32)
#else
#define GPLUGIN_AVAILABLE_IN_0_32 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_33:
 *
 * A macro that evaluates to the 0.33 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_33 (G_ENCODE_VERSION(0, 33))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_33
#define GPLUGIN_AVAILABLE_IN_0_33 GPLUGIN_UNAVAILABLE(0, 33)
#else
#define GPLUGIN_AVAILABLE_IN_0_33 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_34:
 *
 * A macro that evaluates to the 0.34 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_34 (G_ENCODE_VERSION(0, 34))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_34
#define GPLUGIN_AVAILABLE_IN_0_34 GPLUGIN_UNAVAILABLE(0, 34)
#else
#define GPLUGIN_AVAILABLE_IN_0_34 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_35:
 *
 * A macro that evaluates to the 0.35 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_35 (G_ENCODE_VERSION(0, 35))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_35
#define GPLUGIN_AVAILABLE_IN_0_35 GPLUGIN_UNAVAILABLE(0, 35)
#else
#define GPLUGIN_AVAILABLE_IN_0_35 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_36:
 *
 * A macro that evaluates to the 0.36 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_36 (G_ENCODE_VERSION(0, 36))

/**
 * GPLUGIN_VERSION_0_37:
 *
 * A macro that evaluates to the 0.37 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_37 (G_ENCODE_VERSION(0, 37))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_37
#define GPLUGIN_AVAILABLE_IN_0_37 GPLUGIN_UNAVAILABLE(0, 37)
#else
#define GPLUGIN_AVAILABLE_IN_0_37 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_38:
 *
 * A macro that evaluates to the 0.38 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_38 (G_ENCODE_VERSION(0, 38))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_38
#define GPLUGIN_AVAILABLE_IN_0_38 GPLUGIN_UNAVAILABLE(0, 38)
#else
#define GPLUGIN_AVAILABLE_IN_0_38 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_39:
 *
 * A macro that evaluates to the 0.39 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_39 (G_ENCODE_VERSION(0, 39))

#if GPLUGIN_VERSION_MIN_REQUIRED >= GPLUGIN_VERSION_0_39
#define GPLUGIN_DEPRECATED_IN_0_39_FOR(f) GPLUGIN_DEPRECATED_FOR(f)
#else
#define GPLUGIN_DEPRECATED_IN_0_39_FOR(f) _GPLUGIN_EXTERN
#endif

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_39
#define GPLUGIN_AVAILABLE_IN_0_39 GPLUGIN_UNAVAILABLE(0, 39)
#else
#define GPLUGIN_AVAILABLE_IN_0_39 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_40:
 *
 * A macro that evaluates to the 0.40 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_40 (G_ENCODE_VERSION(0, 40))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_40
#define GPLUGIN_AVAILABLE_IN_0_40 GPLUGIN_UNAVAILABLE(0, 40)
#else
#define GPLUGIN_AVAILABLE_IN_0_40 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_41:
 *
 * A macro that evaluates to the 0.41 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_41 (G_ENCODE_VERSION(0, 41))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_41
#define GPLUGIN_AVAILABLE_IN_0_41 GPLUGIN_UNAVAILABLE(0, 41)
#else
#define GPLUGIN_AVAILABLE_IN_0_41 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_42:
 *
 * A macro that evaluates to the 0.42 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.42
 */
#define GPLUGIN_VERSION_0_42 (G_ENCODE_VERSION(0, 42))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_42
#define GPLUGIN_AVAILABLE_IN_0_42 GPLUGIN_UNAVAILABLE(0, 42)
#else
#define GPLUGIN_AVAILABLE_IN_0_42 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_43:
 *
 * A macro that evaluates to the 0.43 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.43.0
 */
#define GPLUGIN_VERSION_0_43 (G_ENCODE_VERSION(0, 43))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_43
#define GPLUGIN_AVAILABLE_IN_0_43 GPLUGIN_UNAVAILABLE(0, 43)
#else
#define GPLUGIN_AVAILABLE_IN_0_43 _GPLUGIN_EXTERN
#endif

/**
 * GPLUGIN_VERSION_0_44:
 *
 * A macro that evaluates to the 0.44 version of GPlugin, in a format that can
 * be used by the C pre-processor.
 *
 * Since: 0.44.0
 */
#define GPLUGIN_VERSION_0_44 (G_ENCODE_VERSION(0, 44))

#if GPLUGIN_VERSION_MAX_ALLOWED < GPLUGIN_VERSION_0_44
#define GPLUGIN_AVAILABLE_IN_0_44 GPLUGIN_UNAVAILABLE(0, 44)
#else
#define GPLUGIN_AVAILABLE_IN_0_44 _GPLUGIN_EXTERN
#endif

#define GPLUGIN_VERSION_CHECK(major, minor, micro) \
	((major) == GPLUGIN_MAJOR_VERSION && \
	 ((minor) < GPLUGIN_MINOR_VERSION || \
	  ((minor) == GPLUGIN_MINOR_VERSION && (micro) <= GPLUGIN_MICRO_VERSION)))

G_BEGIN_DECLS

GPLUGIN_AVAILABLE_IN_ALL
const char *gplugin_version_check(guint major, guint minor, guint micro);

GPLUGIN_AVAILABLE_IN_ALL
int gplugin_version_compare(const char *v1, const char *v2);

G_END_DECLS

#endif /* GPLUGIN_VERSION_H */
