/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef UA_CONFIG_H_
#define UA_CONFIG_H_

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Library Version
 * --------------- */
#define UA_OPEN62541_VER_MAJOR ${OPEN62541_VER_MAJOR}
#define UA_OPEN62541_VER_MINOR ${OPEN62541_VER_MINOR}
#define UA_OPEN62541_VER_PATCH ${OPEN62541_VER_PATCH}
#define UA_OPEN62541_VER_LABEL "${OPEN62541_VER_LABEL}" /* Release candidate label, etc. */
#define UA_OPEN62541_VER_COMMIT "${OPEN62541_VER_COMMIT}"

/**
 * Options
 * ------- */
#define UA_LOGLEVEL ${UA_LOGLEVEL}
#cmakedefine UA_ENABLE_METHODCALLS
#cmakedefine UA_ENABLE_NODEMANAGEMENT
#cmakedefine UA_ENABLE_SUBSCRIPTIONS
#cmakedefine UA_ENABLE_MULTITHREADING

/**
 * Advanced Options
 * ---------------- */
#cmakedefine UA_ENABLE_STATUSCODE_DESCRIPTIONS
#cmakedefine UA_ENABLE_TYPENAMES
#cmakedefine UA_ENABLE_EMBEDDED_LIBC
#cmakedefine UA_ENABLE_DETERMINISTIC_RNG
#cmakedefine UA_ENABLE_GENERATE_NAMESPACE0
#cmakedefine UA_ENABLE_NONSTANDARD_STATELESS
#cmakedefine UA_ENABLE_NONSTANDARD_UDP
#cmakedefine UA_ENABLE_DISCOVERY
#cmakedefine UA_ENABLE_DISCOVERY_MULTICAST
#cmakedefine UA_ENABLE_DISCOVERY_SEMAPHORE
#cmakedefine UA_DEBUG_DUMP_PKGS

/**
 * Standard Includes
 * ----------------- */
#ifndef _XOPEN_SOURCE
 #if defined(__QNX__) || defined(__QNXNTO__)
  # define _XOPEN_SOURCE 600
 #else
  # define _XOPEN_SOURCE 500
 #endif
#endif
#ifndef _DEFAULT_SOURCE
# define _DEFAULT_SOURCE
#endif
// On older systems we need to define _BSD_SOURCE
// _DEFAULT_SOURCE is an alias for that
#ifndef _BSD_SOURCE
# define _BSD_SOURCE
#endif

// Disable deprecation warnings for sprintf, strncpy, strerror
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
# define _CRT_SECURE_NO_WARNINGS
#endif

#include <stddef.h>

/* Include stdint.h or workaround for older Visual Studios */
#if !defined(_MSC_VER) || _MSC_VER >= 1600
# include <stdint.h>
#else
# include "ms_stdint.h"
#endif

#ifndef __cplusplus
# include <stdbool.h> /* C99 Boolean */
/* Manual Boolean:
typedef uint8_t bool;
#define true 1
#define false 0 */
#endif

#include <stdlib.h>

/**
 * Memory Management
 * ---------------
 * The default malloc implementation from ``stdlib.h`` is used internally.
 * Override if required. */
#if defined(_WIN32) && !defined(__clang__)
# include <malloc.h>
#endif

#define UA_free(ptr) free(ptr)
#define UA_malloc(size) malloc(size)
#define UA_calloc(num, size) calloc(num, size)
#define UA_realloc(ptr, size) realloc(ptr, size)

#if defined(__GNUC__) || defined(__clang__)
# define UA_alloca(size) __builtin_alloca (size)
#elif defined(_WIN32)
# define UA_alloca(SIZE) _alloca(SIZE)
#else
# include <alloca.h>
# define UA_alloca(SIZE) alloca(SIZE)
#endif

/**
 * Function Export
 * ---------------
 * On Win32: Define ``UA_DYNAMIC_LINKING`` and ``UA_DYNAMIC_LINKING_EXPORT`` in
 * order to export symbols for a DLL. Define ``UA_DYNAMIC_LINKING`` only to
 * import symbols from a DLL.*/
#cmakedefine UA_DYNAMIC_LINKING
#if defined(_WIN32) && defined(UA_DYNAMIC_LINKING)
# ifdef UA_DYNAMIC_LINKING_EXPORT /* export dll */
#  ifdef __GNUC__
#   define UA_EXPORT __attribute__ ((dllexport))
#  else
#   define UA_EXPORT __declspec(dllexport)
#  endif
# else /* import dll */
#  ifdef __GNUC__
#   define UA_EXPORT __attribute__ ((dllimport))
#  else
#   define UA_EXPORT __declspec(dllimport)
#  endif
# endif
#else /* non win32 */
# if __GNUC__ || __clang__
#  define UA_EXPORT __attribute__ ((visibility ("default")))
# endif
#endif
#ifndef UA_EXPORT
# define UA_EXPORT /* fallback to default */
#endif

/**
 * Inline Functions
 * ---------------- */
#ifdef _MSC_VER
# define UA_INLINE __inline
#else
# define UA_INLINE inline
#endif

/**
 * Non-aliasing pointers
 * -------------------- */
#ifdef _MSC_VER
# define UA_RESTRICT __restrict
#elif defined(__GNUC__)
# define UA_RESTRICT __restrict__
#else
# define UA_RESTRICT restrict
#endif

/**
 * Function attributes
 * ------------------- */
#ifdef __GNUC__
# define UA_FUNC_ATTR_MALLOC __attribute__((malloc))
# define UA_FUNC_ATTR_PURE __attribute__ ((pure))
# define UA_FUNC_ATTR_CONST __attribute__((const))
# define UA_FUNC_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
# define UA_FORMAT(X,Y) __attribute__ ((format (printf, X, Y)))
#else
# define UA_FUNC_ATTR_MALLOC
# define UA_FUNC_ATTR_PURE
# define UA_FUNC_ATTR_CONST
# define UA_FUNC_ATTR_WARN_UNUSED_RESULT
# define UA_FORMAT(X,Y)
#endif

#ifdef __GNUC__
# define UA_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
# define UA_DEPRECATED __declspec(deprecated)
#else
# define UA_DEPRECATED
#endif

/**
 * String Manipulation
 * -------------------
 * The header ``string.h`` is defined in the C-standard. If no libc is provided
 * (e.g. on some embedded target), use the following definitions and the
 * implementation in ``/deps/libc_string.c`` */
#ifndef UA_ENABLE_EMBEDDED_LIBC
# include <string.h>
#else
  void *memcpy(void *UA_RESTRICT dest, const void *UA_RESTRICT src, size_t n);
  void *memset(void *dest, int c, size_t n);
  size_t strlen(const char *s);
  int memcmp(const void *vl, const void *vr, size_t n);
#endif

/**
 * Binary Encoding Overlays
 * ------------------------
 * Integers and floating point numbers are transmitted in little-endian (IEEE 754
 * for floating point) encoding. If the target architecture uses the same
 * format, numeral datatypes can be memcpy'd (overlayed) on the binary stream.
 * This speeds up encoding.
 *
 * Integer Endianness
 * ^^^^^^^^^^^^^^^^^^
 * The definition ``UA_BINARY_OVERLAYABLE_INTEGER`` is true when the integer
 * representation of the target architecture is little-endian. */
#if defined(_WIN32) || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
                        (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
# define UA_BINARY_OVERLAYABLE_INTEGER 1
#elif defined(__ANDROID__) /* Andoid */
# include <endian.h>
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define UA_BINARY_OVERLAYABLE_INTEGER 1
# endif
#elif defined(__linux__) /* Linux */
# include <endian.h>
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define UA_BINARY_OVERLAYABLE_INTEGER 1
# endif
# if __FLOAT_BYTE_ORDER == __LITTLE_ENDIAN
#  define UA_BINARY_OVERLAYABLE_FLOAT 1
# endif
#elif defined(__OpenBSD__) /* OpenBSD */
# include <sys/endian.h>
# if BYTE_ORDER == LITTLE_ENDIAN
#  define UA_BINARY_OVERLAYABLE_INTEGER 1
# endif
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) /* Other BSD */
# include <sys/endian.h>
# if _BYTE_ORDER == _LITTLE_ENDIAN
#  define UA_BINARY_OVERLAYABLE_INTEGER 1
# endif
#elif defined(__APPLE__) /* Apple (MacOS, iOS) */
# include <libkern/OSByteOrder.h>
# if defined(__LITTLE_ENDIAN__)
#  define UA_BINARY_OVERLAYABLE_INTEGER 1
# endif
#elif defined(__QNX__) || defined(__QNXNTO__) /* QNX */
# include <gulliver.h>
# if defined(__LITTLEENDIAN__)
#  define UA_BINARY_OVERLAYABLE_INTEGER 1
# endif
#endif

#ifndef UA_BINARY_OVERLAYABLE_INTEGER
# define UA_BINARY_OVERLAYABLE_INTEGER 0
#endif

/**
 * Float Endianness
 * ^^^^^^^^^^^^^^^^
 * The definition ``UA_BINARY_OVERLAYABLE_FLOAT`` is true when the floating
 * point number representation of the target architecture is IEEE 754. Note that
 * this cannot be reliable detected with macros for the clang compiler
 * (beginning of 2017). Just override if necessary. */
#if defined(_WIN32)
# define UA_BINARY_OVERLAYABLE_FLOAT 1
#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
    (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__) /* Defined only in GCC */
# define UA_BINARY_OVERLAYABLE_FLOAT 1
#elif defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && \
    (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) /* Defined only in GCC */
# define UA_BINARY_OVERLAYABLE_FLOAT 1
#endif

#ifndef UA_BINARY_OVERLAYABLE_FLOAT
# define UA_BINARY_OVERLAYABLE_FLOAT 0
#endif

#ifdef __cplusplus
} // extern "C"
#endif

#endif /* UA_CONFIG_H_ */