//! \addtogroup Core
//! \{
//! \~\file pibase_macros.h
//! \brief
//! \~english Base macros
//! \~russian Базовые макросы
//! \details
//! \~english
//! This file declares basic useful macros for the PIP library including platform detection,
//! compiler-specific configurations, and utility macros for private data handling.
//! \~russian
//! Этот файл объявляет основные вспомогательные макросы для библиотеки PIP, включая обнаружение платформы,
//! конфигурации, специфичные для компилятора, и служебные макросы для работы с приватными данными.
//! \~\}
/*
    PIP - Platform Independent Primitives
    Base macros
    Ivan Pelipenko peri4ko@yandex.ru

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PIBASE_MACROS_H
#define PIBASE_MACROS_H

#include "pip_defs.h"
#include "pip_version.h"
#include "piplatform.h"

//! \~english
//! Meta-information section for any entity.
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
//! Contains sequence of key=value pairs, e.g.
//! \~russian
//! Секция метаинформации для любой сущности.
//! Парсится \a pip_cmg и доступна с помощью \a PICodeInfo.
//! Содержит набор пар ключ=значение, например
//! \~
//! PIMETA(id=12345,tag="my string")
#define PIMETA(...)

#ifdef DOXYGEN

//! \~english Major value of PIP version
//! \~russian Мажорная версия PIP
#  define PIP_VERSION_MAJOR

//! \~english Minor value of PIP version
//! \~russian Минорная версия PIP
#  define PIP_VERSION_MINOR

//! \~english Revision value of PIP version
//! \~russian Ревизия версии PIP
#  define PIP_VERSION_REVISION

//! \~english Suffix of PIP version
//! \~russian Суффикс версии PIP
#  define PIP_VERSION_SUFFIX

//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
#  define PIP_VERSION

//! \~english Macro is defined when compile-time debug is enabled
//! \~russian Макрос объявлен когда включена compile-time отладка
#  define PIP_DEBUG

//! \~english Macro is defined when operation system is any Windows
//! \~russian Макрос объявлен когда операционная система Windows
#  define WINDOWS

//! \~english Macro is defined when operation system is QNX or Blackberry
//! \~russian Макрос объявлен когда операционная система QNX или Blackberry
#  define QNX

//! \~english Macro is defined when operation system is Blackberry
//! \~russian Макрос объявлен когда операционная система Blackberry
#  define BLACKBERRY

//! \~english Macro is defined when operation system is FreeBSD
//! \~russian Макрос объявлен когда операционная система FreeBSD
#  define FREE_BSD

//! \~english Macro is defined when operation system is Mac OS
//! \~russian Макрос объявлен когда операционная система Mac OS
#  define MAC_OS

//! \~english Macro is defined when operation system is Android
//! \~russian Макрос объявлен когда операционная система Android
#  define ANDROID

//! \~english Macro is defined when operation system is any Linux
//! \~russian Макрос объявлен когда операционная система Linux
#  define LINUX

//! \~english Macro is defined when operation system is FreeRTOS
//! \~russian Макрос объявлен когда операционная система FreeRTOS
#  define FREERTOS

//! \~english Macro is defined when compiler is GCC or MinGW
//! \~russian Макрос объявлен когда компилятор GCC или MinGW
#  define CC_GCC

//! \~english Macro is defined when PIP is decided that host is support language
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
#  define HAS_LOCALE

//! \~english Macro is defined when PIP is building for embedded systems
//! \~russian Макрос объявлен когда PIP собирается для встраиваемых систем
#  define MICRO_PIP

//! \~english Macro is defined when compiler is Visual Studio
//! \~russian Макрос объявлен когда компилятор Visual Studio
#  define CC_VC

//! \~english Macro is defined when compiler is AVR GCC
//! \~russian Макрос объявлен когда компилятор AVR GCC
#  define CC_AVR_GCC

//! \~english Macro is defined when compiler is unknown
//! \~russian Макрос объявлен когда компилятор неизвестен
#  define CC_OTHER

//! \~english Macro to declare private section, "export" is optional
//! \~russian Макрос для объявления частной секции, "export" необязателен
#  define PRIVATE_DECLARATION(export)

//! \~english Macro to start definition of private section
//! \~russian Макрос для начала реализации частной секции
#  define PRIVATE_DEFINITION_START(Class)

//! \~english Macro to end definition of private section
//! \~russian Макрос для окончания реализации частной секции
#  define PRIVATE_DEFINITION_END(Class)

//! \~english Macro to access private section by pointer
//! \~russian Макрос для доступа к частной секции
#  define PRIVATE

//! \~english Macro to access private section by pointer without braces ()
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
#  define PRIVATEWB

//! \~english Macro to start static initializer
//! \~russian Макрос для начала статической инициализации
#  define STATIC_INITIALIZER_BEGIN

//! \~english Macro to end static initializer
//! \~russian Макрос для окончания статической инициализации
#  define STATIC_INITIALIZER_END

//! \~english Macro to remove class copy availability
//! \~russian Макрос для запрета копирования класса
#  define NO_COPY_CLASS(Class)

//! \~english Macro to supress compiler warning about unused variable
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
#  define NO_UNUSED(x)

#  undef MICRO_PIP
#  undef FREERTOS

#endif // DOXYGEN

#ifdef WINDOWS
#  ifdef CC_VC
#	define SHUT_RDWR 2
#	pragma comment(lib, "Ws2_32.lib")
#	pragma comment(lib, "Iphlpapi.lib")
#	pragma comment(lib, "Psapi.lib")
#	ifdef ARCH_BITS_32
#	  define _X86_
#	else
#	  define _IA64_
#	endif
#  else
#	define SHUT_RDWR SD_BOTH
#  endif
typedef int socklen_t;
extern long long __pi_perf_freq;
#endif

#ifndef DOXYGEN

#  ifdef ANDROID
// #  define tcdrain(fd) ioctl(fd, TCSBRK, 1)
// inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
// inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;}
#  endif

#  ifdef MAC_OS
#	define environ (*_NSGetEnviron())
typedef long time_t;
#  endif

#  ifdef LINUX
#	define environ __environ
#  endif

#  ifdef FREE_BSD
extern char ** environ;
#  endif

#  ifndef NO_UNUSED
#	define NO_UNUSED(x) (void)x
#  endif

#  ifndef assert
#	define assert(x)
#	define assertm(exp, msg)
#  else
#	define assertm(exp, msg) assert(((void)msg, exp))
#  endif

#  ifdef MICRO_PIP
#	define __PIP_TYPENAME__(T) "?"
#  else
#	define __PIP_TYPENAME__(T) typeid(T).name()
#  endif

#  ifdef CC_GCC
#	undef DEPRECATED
#	undef DEPRECATEDM
#	define DEPRECATED       __attribute__((deprecated))
#	define DEPRECATEDM(msg) __attribute__((deprecated(msg)))
#	if CC_GCC_VERSION > 0x025F // > 2.95
#	  pragma GCC diagnostic warning "-Wdeprecated-declarations"
#	  ifdef LINUX
#		define HAS_LOCALE
#	  endif
#	  ifdef MAC_OS
#		pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
#		pragma GCC diagnostic ignored "-Wc++11-extensions"
#	  endif
#	endif
#	ifdef ANDROID
#	  pragma GCC diagnostic ignored "-Wunused-parameter"
#	  pragma GCC diagnostic ignored "-Wextra"
#	  pragma GCC diagnostic ignored "-Wc++11-extensions"
#	  pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
// #    pragma GCC diagnostic ignored "-Wliteral-suffix"
#	endif
#  endif

#  ifdef CC_VC
#	undef DEPRECATED
#	undef DEPRECATEDM
#	define DEPRECATED       __declspec(deprecated)
#	define DEPRECATEDM(msg) __declspec(deprecated(msg))
#	pragma warning(disable: 4018)
#	pragma warning(disable: 4061)
#	pragma warning(disable: 4100)
#	pragma warning(disable: 4239)
#	pragma warning(disable: 4242)
#	pragma warning(disable: 4244)
#	pragma warning(disable: 4251)
#	pragma warning(disable: 4365)
#	pragma warning(disable: 4512)
#	pragma warning(disable: 4668)
#	pragma warning(disable: 4710)
#	pragma warning(disable: 4800)
#	pragma warning(disable: 4820)
#	pragma warning(disable: 4986)
#	pragma warning(disable: 4996)
#	ifdef ARCH_BITS_32
typedef long ssize_t;
#	else
typedef long long ssize_t;
#	endif
#  endif

#  ifdef CC_OTHER
#	undef DEPRECATED
#	undef DEPRECATEDM
#	define DEPRECATED
#	define DEPRECATEDM(msg)
#  endif

#endif // DOXYGEN


// Private data macros
#ifndef DOXYGEN

//! \~english Macro to declare private section, "export" is optional
//! \~russian Макрос для объявления частной секции, "export" необязателен
//! \~sa PRIVATE PRIVATEWB
#  define PRIVATE_DECLARATION(e)                                                \
	  struct __Private__;                                                       \
	  friend struct __Private__;                                                \
	  struct e __PrivateInitializer__ {                                         \
		  __PrivateInitializer__();                                             \
		  __PrivateInitializer__(const __PrivateInitializer__ & o);             \
		  ~__PrivateInitializer__();                                            \
		  __PrivateInitializer__ & operator=(const __PrivateInitializer__ & o); \
		  __Private__ * p = nullptr;                                            \
	  };                                                                        \
	  __PrivateInitializer__ __privateinitializer__;

//! \~english Macro to start definition of private section
//! \~russian Макрос для начала реализации частной секции
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
#  define PRIVATE_DEFINITION_START(c) struct c::__Private__ {
//! \~english Macro to end definition of private section without initialization
//! \~russian Макрос для окончания реализации частной секции без инициализации
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_START PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
#  define PRIVATE_DEFINITION_END_NO_INITIALIZE(c) \
	  }                                           \
	  ;

//! \~english Macro to initialize private section
//! \~russian Макрос для инициализации частной секции
//! \~sa PRIVATE_DEFINITION_END PRIVATE_DEFINITION_START PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE PRIVATEWB
#  define PRIVATE_DEFINITION_INITIALIZE(c)                                                                        \
	  c::__PrivateInitializer__::__PrivateInitializer__() {                                                       \
		  p = new c::__Private__();                                                                               \
	  }                                                                                                           \
	  c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ &) { /*if (p) delete p;*/ \
		  p = new c::__Private__();                                                                               \
	  }                                                                                                           \
	  c::__PrivateInitializer__::~__PrivateInitializer__() {                                                      \
		  piDeleteSafety(p);                                                                                      \
	  }                                                                                                           \
	  c::__PrivateInitializer__ & c::__PrivateInitializer__::operator=(const c::__PrivateInitializer__ &) {       \
		  piDeleteSafety(p);                                                                                      \
		  p = new c::__Private__();                                                                               \
		  return *this;                                                                                           \
	  }


//! \~english Macro to end definition of private section with initialization
//! \~russian Макрос для окончания реализации частной секции с инициализацией
//! \~sa PRIVATE_DEFINITION_END_NO_INITIALIZE PRIVATE_DEFINITION_START PRIVATE_DEFINITION_INITIALIZE PRIVATE PRIVATEWB
#  define PRIVATE_DEFINITION_END(c)        \
	  PRIVATE_DEFINITION_END_NO_INITIALIZE \
	  (c) PRIVATE_DEFINITION_INITIALIZE(c)

//! \~english Macro to access private section by pointer
//! \~russian Макрос для доступа к частной секции
//! \~sa PRIVATEWB
#  define PRIVATE   (__privateinitializer__.p)

//! \~english Macro to access private section by pointer without braces ()
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
//! \~sa PRIVATE
#  define PRIVATEWB __privateinitializer__.p

#endif // DOXYGEN

//! \~english Macro to remove class copy availability
//! \~russian Макрос для запрета копирования класса
#define NO_COPY_CLASS(name)                  \
	name(const name &)             = delete; \
	name & operator=(const name &) = delete;

//! \~english Counter macro for unique identifier generation
//! \~russian Макрос счетчика для генерации уникальных идентификаторов
#define _PIP_ADD_COUNTER_WS(a, cnt, line) a##cnt##_##line
#define _PIP_ADD_COUNTER_WF(a, cnt, line) _PIP_ADD_COUNTER_WS(a, cnt, line)
#define _PIP_ADD_COUNTER(a)               _PIP_ADD_COUNTER_WF(a, __COUNTER__, __LINE__)


//! \~english Macro to start static initializer
//! \~russian Макрос для начала статической инициализации
//! \~sa STATIC_INITIALIZER_END
#define STATIC_INITIALIZER_BEGIN \
	class {                      \
		class _Initializer_ {    \
		public:                  \
			_Initializer_() {
//! \~english Macro to end static initializer
//! \~russian Макрос для окончания статической инициализации
//! \~sa STATIC_INITIALIZER_BEGIN
#define STATIC_INITIALIZER_END \
	}                          \
	}                          \
	_initializer_;             \
	}                          \
	_PIP_ADD_COUNTER(_pip_initializer_);


//! \~english Minimal sleep in milliseconds for internal PIP using
//! \~russian Минимальное значание задержки в милисекундах для внутреннего использования в библиотеке PIP
//! \~\details
//! \~english Using in \a piMinSleep(), \a PIThread, \a PITimer::Pool. By default 1ms.
//! \~russian Используется в \a piMinSleep(), \a PIThread, \a PITimer::Pool. По умолчанию равна 1мс.
//! \~\sa PIP_MIN_MSLEEP
#ifndef PIP_MIN_MSLEEP
#  ifndef MICRO_PIP
#	define PIP_MIN_MSLEEP 1.
#  else
#	define PIP_MIN_MSLEEP 10.
#  endif
#endif


//! \~english Macro used for infinite loop
//! \~russian Макрос для бесконечного цикла
//! \~\details
//! \~english Expands to \c for(;;) infinite loop construct
//! \~russian Раскрывается в конструкцию бесконечного цикла \c for(;;)
#define FOREVER      for (;;)

//! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания
//! \~\details
//! \~english Expands to infinite loop with periodic sleep calls for CPU-friendly waiting
//! \~russian Раскрывается в бесконечный цикл с периодическими вызовами sleep для экономии ресурсов CPU
#define FOREVER_WAIT FOREVER piMinSleep();

//! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания
//! \~\details
//! \~english Expands to infinite loop with periodic sleep calls for CPU-friendly waiting
//! \~russian Раскрывается в бесконечный цикл с периодическими вызовами sleep для экономии ресурсов CPU
//! \~\sa FOREVER_WAIT
#define WAIT_FOREVER FOREVER piMinSleep();


#endif // PIBASE_MACROS_H
