1016 lines
32 KiB
C++
1016 lines
32 KiB
C++
/*! \file pibase.h
|
||
* \ingroup Core
|
||
* \~\brief
|
||
* \~english Base types and functions
|
||
* \~russian Базовые типы и методы
|
||
*
|
||
* \~\details
|
||
* \~english
|
||
* This file implements first layer above the system and
|
||
* declares some basic useful functions
|
||
* \~russian
|
||
* Этот файл реализует первый слой после системы и объявляет
|
||
* несколько базовых полезных методов
|
||
*/
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
Base types and functions
|
||
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_H
|
||
#define PIBASE_H
|
||
|
||
#include "pip_defs.h"
|
||
#include "pip_export.h"
|
||
#include "pip_version.h"
|
||
#include "piplatform.h"
|
||
|
||
#include <string.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
|
||
|
||
//! \~\brief
|
||
//! \~english Major value of PIP version
|
||
//! \~russian Мажорная версия PIP
|
||
# define PIP_VERSION_MAJOR
|
||
|
||
//! \~\brief
|
||
//! \~english Minor value of PIP version
|
||
//! \~russian Минорная версия PIP
|
||
# define PIP_VERSION_MINOR
|
||
|
||
//! \~\brief
|
||
//! \~english Revision value of PIP version
|
||
//! \~russian Ревизия версии PIP
|
||
# define PIP_VERSION_REVISION
|
||
|
||
//! \~\brief
|
||
//! \~english Suffix of PIP version
|
||
//! \~russian Суффикс версии PIP
|
||
# define PIP_VERSION_SUFFIX
|
||
|
||
//! \~\brief
|
||
//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
|
||
# define PIP_VERSION
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when compile-time debug is enabled
|
||
//! \~russian Макрос объявлен когда включена compile-time отладка
|
||
# define PIP_DEBUG
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is any Windows
|
||
//! \~russian Макрос объявлен когда операционная система Windows
|
||
# define WINDOWS
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is QNX or Blackberry
|
||
//! \~russian Макрос объявлен когда операционная система QNX или Blackberry
|
||
# define QNX
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is Blackberry
|
||
//! \~russian Макрос объявлен когда операционная система Blackberry
|
||
# define BLACKBERRY
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is FreeBSD
|
||
//! \~russian Макрос объявлен когда операционная система FreeBSD
|
||
# define FREE_BSD
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is Mac OS
|
||
//! \~russian Макрос объявлен когда операционная система Mac OS
|
||
# define MAC_OS
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is Android
|
||
//! \~russian Макрос объявлен когда операционная система Android
|
||
# define ANDROID
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is any Linux
|
||
//! \~russian Макрос объявлен когда операционная система Linux
|
||
# define LINUX
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when operation system is FreeRTOS
|
||
//! \~russian Макрос объявлен когда операционная система FreeRTOS
|
||
# define FREERTOS
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when compiler is GCC or MinGW
|
||
//! \~russian Макрос объявлен когда компилятор GCC или MinGW
|
||
# define CC_GCC
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when PIP is decided that host is support language
|
||
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
|
||
# define HAS_LOCALE
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when PIP is building for embedded systems
|
||
//! \~russian Макрос объявлен когда PIP собирается для встраиваемых систем
|
||
# define MICRO_PIP
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when compiler is Visual Studio
|
||
//! \~russian Макрос объявлен когда компилятор Visual Studio
|
||
# define CC_VC
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when compiler is AVR GCC
|
||
//! \~russian Макрос объявлен когда компилятор AVR GCC
|
||
# define CC_AVR_GCC
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when compiler is unknown
|
||
//! \~russian Макрос объявлен когда компилятор неизвестен
|
||
# define CC_OTHER
|
||
|
||
//! \~\brief
|
||
//! \~english Macro is defined when PIP can use "rt" library for \a PITimer::ThreadRT timers implementation
|
||
//! \~russian Макрос объявлен когда PIP может использовать библиотеку "rt" для \a PITimer::ThreadRT реализации таймера
|
||
# define PIP_TIMER_RT
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to declare private section, "export" is optional
|
||
//! \~russian Макрос для объявления частной секции, "export" необязателен
|
||
# define PRIVATE_DECLARATION(export)
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to start definition of private section
|
||
//! \~russian Макрос для начала реализации частной секции
|
||
# define PRIVATE_DEFINITION_START(Class)
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to end definition of private section
|
||
//! \~russian Макрос для окончания реализации частной секции
|
||
# define PRIVATE_DEFINITION_END(Class)
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to access private section by pointer
|
||
//! \~russian Макрос для доступа к частной секции
|
||
# define PRIVATE
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to access private section by pointer without brakes ()
|
||
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
|
||
# define PRIVATEWB
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to start static initializer
|
||
//! \~russian Макрос для начала статической инициализации
|
||
# define STATIC_INITIALIZER_BEGIN
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to end static initializer
|
||
//! \~russian Макрос для окончания статической инициализации
|
||
# define STATIC_INITIALIZER_END
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to remove class copy availability
|
||
//! \~russian Макрос для запрета копирования класса
|
||
# define NO_COPY_CLASS(Class)
|
||
|
||
//! \~\brief
|
||
//! \~english Macro to supress compiler warning about unused variable
|
||
//! \~russian Макрос для подавления предупреждения компилятора о неиспользуемой переменной
|
||
# define NO_UNUSED(x)
|
||
|
||
# undef MICRO_PIP
|
||
# undef FREERTOS
|
||
#endif // DOXYGEN
|
||
|
||
#ifdef CC_AVR_GCC
|
||
# include <ArduinoSTL.h>
|
||
#endif
|
||
#include <atomic>
|
||
#include <cassert>
|
||
#include <cstddef>
|
||
#include <functional>
|
||
#include <limits>
|
||
|
||
#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
|
||
|
||
# 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; \
|
||
}; \
|
||
__PrivateInitializer__ __privateinitializer__;
|
||
|
||
# define PRIVATE_DEFINITION_START(c) struct c::__Private__ {
|
||
# define PRIVATE_DEFINITION_END(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__() { \
|
||
delete p; \
|
||
p = 0; \
|
||
} \
|
||
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator=(const c::__PrivateInitializer__ &) { \
|
||
if (p) delete p; \
|
||
p = new c::__Private__(); \
|
||
return *this; \
|
||
}
|
||
|
||
# define PRIVATE (__privateinitializer__.p)
|
||
# define PRIVATEWB __privateinitializer__.p
|
||
|
||
#endif // DOXYGEN
|
||
|
||
#define NO_COPY_CLASS(name) \
|
||
name(const name &) = delete; \
|
||
name & operator=(const name &) = delete;
|
||
|
||
|
||
#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__)
|
||
|
||
|
||
#define STATIC_INITIALIZER_BEGIN \
|
||
class { \
|
||
class _Initializer_ { \
|
||
public: \
|
||
_Initializer_() {
|
||
#define STATIC_INITIALIZER_END \
|
||
} \
|
||
} \
|
||
_initializer_; \
|
||
} \
|
||
_PIP_ADD_COUNTER(_pip_initializer_);
|
||
|
||
|
||
//! \~\brief
|
||
//! \~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мс.
|
||
#ifndef PIP_MIN_MSLEEP
|
||
# ifndef MICRO_PIP
|
||
# define PIP_MIN_MSLEEP 1.
|
||
# else
|
||
# define PIP_MIN_MSLEEP 10.
|
||
# endif
|
||
#endif
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Macro used for infinite loop
|
||
//! \~russian Макрос для бесконечного цикла
|
||
#define FOREVER for (;;)
|
||
|
||
//! \~\brief
|
||
//! \~english Macro used for infinite wait
|
||
//! \~russian Макрос для бесконечного ожидания
|
||
#define FOREVER_WAIT FOREVER piMinSleep();
|
||
|
||
//! \~\brief
|
||
//! \~english Macro used for infinite wait
|
||
//! \~russian Макрос для бесконечного ожидания
|
||
#define WAIT_FOREVER FOREVER piMinSleep();
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Global variable enabling output to piCout, default is true
|
||
//! \~russian Глобальная переменная, включающая вывод в piCout, при старте true
|
||
extern PIP_EXPORT bool piDebug;
|
||
|
||
//! \~\brief
|
||
//! \~english Global variable that set minimum real update interval
|
||
//! for function PIInit::mountInfo(), default is 10000 ms
|
||
//! \~russian Глобальная переменная минимального ожидания между реальным обновлением
|
||
//! в методе PIInit::mountInfo(), по умолчанию 10000 мс
|
||
extern PIP_EXPORT double piMountInfoRefreshIntervalMs;
|
||
|
||
typedef unsigned char uchar;
|
||
typedef unsigned short ushort;
|
||
typedef unsigned int uint;
|
||
typedef unsigned long ulong;
|
||
typedef unsigned long long ullong;
|
||
typedef long long llong;
|
||
typedef long double ldouble;
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function for swap two values
|
||
//! \~russian Шаблонный метод для перестановки двух значений
|
||
//! \~\details
|
||
//! \~english Example:\n \snippet piincludes.cpp swap
|
||
//! \~russian Пример:\n \snippet piincludes.cpp swap
|
||
template<typename T>
|
||
inline void piSwap(T & f, T & s) {
|
||
T t(std::move(f));
|
||
f = std::move(s);
|
||
s = std::move(t);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function for swap two values without "="
|
||
//! \~russian Шаблонный метод для перестановки двух значений без использования "="
|
||
//! \~\details
|
||
//! \~english Example:\n \snippet piincludes.cpp swapBinary
|
||
//! \~russian Пример:\n \snippet piincludes.cpp swapBinary
|
||
template<typename T>
|
||
inline void piSwapBinary(T & f, T & s) {
|
||
if ((size_t *)&f == (size_t *)&s) return;
|
||
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
|
||
size_t i = 0;
|
||
for (i = 0; i < j; ++i) {
|
||
((size_t *)(&f))[i] ^= ((size_t *)(&s))[i];
|
||
((size_t *)(&s))[i] ^= ((size_t *)(&f))[i];
|
||
((size_t *)(&f))[i] ^= ((size_t *)(&s))[i];
|
||
}
|
||
for (i = bs; i < bf; ++i) {
|
||
((uchar *)(&f))[i] ^= ((uchar *)(&s))[i];
|
||
((uchar *)(&s))[i] ^= ((uchar *)(&f))[i];
|
||
((uchar *)(&f))[i] ^= ((uchar *)(&s))[i];
|
||
}
|
||
}
|
||
|
||
template<>
|
||
inline void piSwapBinary(const void *& f, const void *& s) {
|
||
if ((size_t *)f == (size_t *)s) return;
|
||
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
|
||
size_t i = 0;
|
||
void *pf = const_cast<void *>(f), *ps = const_cast<void *>(s);
|
||
for (i = 0; i < j; ++i) {
|
||
((size_t *)(&pf))[i] ^= ((size_t *)(&ps))[i];
|
||
((size_t *)(&ps))[i] ^= ((size_t *)(&pf))[i];
|
||
((size_t *)(&pf))[i] ^= ((size_t *)(&ps))[i];
|
||
}
|
||
for (i = bs; i < bf; ++i) {
|
||
((uchar *)(&pf))[i] ^= ((uchar *)(&ps))[i];
|
||
((uchar *)(&ps))[i] ^= ((uchar *)(&pf))[i];
|
||
((uchar *)(&pf))[i] ^= ((uchar *)(&ps))[i];
|
||
}
|
||
}
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Function for compare two values without "==" by raw content
|
||
//! \~russian Метод для сравнения двух значений без использования "==" (по сырому содержимому)
|
||
//! \~\details
|
||
//! \~english Example:\n \snippet piincludes.cpp compareBinary
|
||
//! \~russian Пример:\n \snippet piincludes.cpp compareBinary
|
||
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
||
for (size_t i = 0; i < size; ++i)
|
||
if (((const uchar *)f)[i] != ((const uchar *)s)[i]) return false;
|
||
return true;
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return round of float falue
|
||
//! \~russian Шаблонный метод, возвращающий округленное значение
|
||
//! \~\details
|
||
//! \~english
|
||
//! Round is the nearest integer value \n
|
||
//! There are some macros:
|
||
//! - \c piRoundf for "float"
|
||
//! - \c piRoundd for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp round
|
||
//! \~russian
|
||
//! Округленное значение - это ближайшее целое число\n
|
||
//! Есть несколько макросов:
|
||
//! - \c piRoundf для "float"
|
||
//! - \c piRoundd для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp round
|
||
template<typename T>
|
||
inline constexpr int piRound(const T & v) {
|
||
return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return floor of float falue
|
||
//! \~russian Шаблонный метод, возвращающий floor значение
|
||
//! \~\details
|
||
//! \~english
|
||
//! Floor is the largest integer that is not greater than "v" \n
|
||
//! There are some macros:
|
||
//! - \c piFloorf for "float"
|
||
//! - \c piFloord for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp floor
|
||
//! \~russian
|
||
//! Floor значение - это наибольшее целое, не большее чем "v"\n
|
||
//! Есть несколько макросов:
|
||
//! - \c piFloorf для "float"
|
||
//! - \c piFloord для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp floor
|
||
template<typename T>
|
||
inline constexpr int piFloor(const T & v) {
|
||
return v < T(0) ? int(v) - 1 : int(v);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return ceil of float falue
|
||
//! \~russian Шаблонный метод, возвращающий ceil значение
|
||
//! \~\details
|
||
//! \~english
|
||
//! Ceil is the smallest integer that is not less than "v" \n
|
||
//! There are some macros:
|
||
//! - \c piCeilf for "float"
|
||
//! - \c piCeild for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp ceil
|
||
//! \~russian
|
||
//! Ceil значение - это наименьшее целое, не меньшее чем "v" \n
|
||
//! Есть несколько макросов:
|
||
//! - \c piCeilf для "float"
|
||
//! - \c piCeild для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp ceil
|
||
template<typename T>
|
||
inline constexpr int piCeil(const T & v) {
|
||
return v < T(0) ? int(v) : int(v) + 1;
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return absolute of numeric falue
|
||
//! \~russian Шаблонный метод, возвращающий модуль числового значения
|
||
//! \~\details
|
||
//! \~english
|
||
//! Absolute is the positive or equal 0 value \n
|
||
//! There are some macros:
|
||
//! - \c piAbss for "short"
|
||
//! - \c piAbsi for "int"
|
||
//! - \c piAbsl for "long"
|
||
//! - \c piAbsll for "llong"
|
||
//! - \c piAbsf for "float"
|
||
//! - \c piAbsd for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp abs
|
||
//! \~russian
|
||
//! Модуль числового значения всегда >= 0 \n
|
||
//! Есть несколько макросов:
|
||
//! - \c piAbss для "short"
|
||
//! - \c piAbsi для "int"
|
||
//! - \c piAbsl для "long"
|
||
//! - \c piAbsll для "llong"
|
||
//! - \c piAbsf для "float"
|
||
//! - \c piAbsd для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp abs
|
||
template<typename T>
|
||
inline constexpr T piAbs(const T & v) {
|
||
return (v >= T(0) ? v : -v);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return minimum of two values
|
||
//! \~russian Шаблонный метод, возвращающий минимум из двух значений
|
||
//! \~\details
|
||
//! \~english
|
||
//! There are some macros:
|
||
//! - \c piMins for "short"
|
||
//! - \c piMini for "int"
|
||
//! - \c piMinl for "long"
|
||
//! - \c piMinll for "llong"
|
||
//! - \c piMinf for "float"
|
||
//! - \c piMind for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp min2
|
||
//! \~russian
|
||
//! Есть несколько макросов:
|
||
//! - \c piMins для "short"
|
||
//! - \c piMini для "int"
|
||
//! - \c piMinl для "long"
|
||
//! - \c piMinll для "llong"
|
||
//! - \c piMinf для "float"
|
||
//! - \c piMind для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp min2
|
||
template<typename T>
|
||
inline constexpr T piMin(const T & f, const T & s) {
|
||
return ((f > s) ? s : f);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return minimum of tree values
|
||
//! \~russian Шаблонный метод, возвращающий минимум из трех значений
|
||
//! \~\details
|
||
//! \~english
|
||
//! There are some macros:
|
||
//! - \c piMins for "short"
|
||
//! - \c piMini for "int"
|
||
//! - \c piMinl for "long"
|
||
//! - \c piMinll for "llong"
|
||
//! - \c piMinf for "float"
|
||
//! - \c piMind for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp min3
|
||
//! \~russian
|
||
//! Есть несколько макросов:
|
||
//! - \c piMins для "short"
|
||
//! - \c piMini для "int"
|
||
//! - \c piMinl для "long"
|
||
//! - \c piMinll для "llong"
|
||
//! - \c piMinf для "float"
|
||
//! - \c piMind для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp min3
|
||
template<typename T>
|
||
inline constexpr T piMin(const T & f, const T & s, const T & t) {
|
||
return ((f < s && f < t) ? f : ((s < t) ? s : t));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return maximum of two values
|
||
//! \~russian Шаблонный метод, возвращающий максимум из двух значений
|
||
//! \~\details
|
||
//! \~english
|
||
//! There are some macros:
|
||
//! - \c piMaxs for "short"
|
||
//! - \c piMaxi for "int"
|
||
//! - \c piMaxl for "long"
|
||
//! - \c piMaxll for "llong"
|
||
//! - \c piMaxf for "float"
|
||
//! - \c piMaxd for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp max2
|
||
//! \~russian
|
||
//! Есть несколько макросов:
|
||
//! - \c piMaxs для "short"
|
||
//! - \c piMaxi для "int"
|
||
//! - \c piMaxl для "long"
|
||
//! - \c piMaxll для "llong"
|
||
//! - \c piMaxf для "float"
|
||
//! - \c piMaxd для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp max2
|
||
template<typename T>
|
||
inline constexpr T piMax(const T & f, const T & s) {
|
||
return ((f < s) ? s : f);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return maximum of tree values
|
||
//! \~russian Шаблонный метод, возвращающий максимум из трех значений
|
||
//! \~\details
|
||
//! \~english
|
||
//! There are some macros:
|
||
//! - \c piMaxs for "short"
|
||
//! - \c piMaxi for "int"
|
||
//! - \c piMaxl for "long"
|
||
//! - \c piMaxll for "llong"
|
||
//! - \c piMaxf for "float"
|
||
//! - \c piMaxd for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp max3
|
||
//! \~russian
|
||
//! Есть несколько макросов:
|
||
//! - \c piMaxs для "short"
|
||
//! - \c piMaxi для "int"
|
||
//! - \c piMaxl для "long"
|
||
//! - \c piMaxll для "llong"
|
||
//! - \c piMaxf для "float"
|
||
//! - \c piMaxd для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp max3
|
||
template<typename T>
|
||
inline constexpr T piMax(const T & f, const T & s, const T & t) {
|
||
return ((f > s && f > t) ? f : ((s > t) ? s : t));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return clamped value
|
||
//! \~russian Шаблонный метод, возвращающий ограниченное значение
|
||
//! \~\details
|
||
//! \~english
|
||
//! Clamped is the not greater than "max" and not lesser than "min" value \n
|
||
//! There are some macros:
|
||
//! - \c piClamps for "short"
|
||
//! - \c piClampi for "int"
|
||
//! - \c piClampl for "long"
|
||
//! - \c piClampll for "llong"
|
||
//! - \c piClampf for "float"
|
||
//! - \c piClampd for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp clamp
|
||
//! \~russian
|
||
//! Ограниченное значение - не больше чем "max" и не меньше чем "min"
|
||
//! Есть несколько макросов:
|
||
//! - \c piClamps для "short"
|
||
//! - \c piClampi для "int"
|
||
//! - \c piClampl для "long"
|
||
//! - \c piClampll для "llong"
|
||
//! - \c piClampf для "float"
|
||
//! - \c piClampd для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp clamp
|
||
template<typename T>
|
||
inline constexpr T piClamp(const T & v, const T & min, const T & max) {
|
||
return (v > max ? max : (v < min ? min : v));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
|
||
//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1])
|
||
inline void piLetobe(void * data, int size) {
|
||
for (int i = 0; i < size / 2; i++)
|
||
piSwap<uchar>(((uchar *)data)[size - i - 1], ((uchar *)data)[i]);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Function for compare two numeric values with epsilon
|
||
//! \~russian Метод для сравнения двух чисел с порогом
|
||
//! \~\details
|
||
//! \~english
|
||
//! There are some macros:
|
||
//! - \c piComparef for "float"
|
||
//! - \c piCompared for "double"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp compare
|
||
//! \~russian
|
||
//! Есть несколько макросов:
|
||
//! - \c piComparef для "float"
|
||
//! - \c piCompared для "double"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp compare
|
||
template<typename T>
|
||
inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric_limits<T>::epsilon()) {
|
||
return piAbs(a - b) <= epsilon;
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function that inverse byte order of value "v"
|
||
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
|
||
template<typename T>
|
||
inline void piLetobe(T * v) {
|
||
piLetobe(v, sizeof(T));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function that returns "v" with inversed byte order
|
||
//! \~russian Шаблонный метод, возвращающий переменную "v" с измененным порядком байт
|
||
//! \~\details
|
||
//! \~english
|
||
//! This function used to convert values between little and big endian \n
|
||
//! There are some macros:
|
||
//! - \c piLetobes for "ushort"
|
||
//! - \c piLetobei for "uint"
|
||
//! - \c piLetobel for "ulong"
|
||
//! - \c piLetobell for "ullong"
|
||
//!
|
||
//! Example:
|
||
//! \snippet piincludes.cpp letobe
|
||
//! \~russian
|
||
//! Этот метод используется для изменения порядка байт между little и big endian
|
||
//! Есть несколько макросов:
|
||
//! - \c piLetobes для "ushort"
|
||
//! - \c piLetobei для "uint"
|
||
//! - \c piLetobel для "ulong"
|
||
//! - \c piLetobell для "ullong"
|
||
//!
|
||
//! Пример:
|
||
//! \snippet piincludes.cpp letobe
|
||
template<typename T>
|
||
inline T piLetobe(const T & v) {
|
||
T tv(v);
|
||
piLetobe(&tv, sizeof(T));
|
||
return tv;
|
||
}
|
||
|
||
// specialization
|
||
template<>
|
||
inline uint16_t piLetobe(const uint16_t & v) {
|
||
return (v << 8) | (v >> 8);
|
||
}
|
||
template<>
|
||
inline uint32_t piLetobe(const uint32_t & v) {
|
||
return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);
|
||
}
|
||
template<>
|
||
inline float piLetobe(const float & v) {
|
||
union _pletobe_f {
|
||
_pletobe_f(const float & f_) { f = f_; }
|
||
float f;
|
||
uint32_t v;
|
||
};
|
||
_pletobe_f a(v);
|
||
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000);
|
||
return a.f;
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Generic hash function, implements murmur3/32 algorithm
|
||
//! \~russian Хэш-функция общего назначения, по алгоритму murmur3/32
|
||
inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
|
||
if (!data || len <= 0) return 0u;
|
||
uint h = seed;
|
||
if (len > 3) {
|
||
uint i = len >> 2;
|
||
do {
|
||
uint k;
|
||
memcpy(&k, data, sizeof(uint));
|
||
data += sizeof(uint);
|
||
k *= 0xcc9e2d51;
|
||
k = (k << 15) | (k >> 17);
|
||
k *= 0x1b873593;
|
||
h ^= k;
|
||
h = (h << 13) | (h >> 19);
|
||
h = h * 5 + 0xe6546b64;
|
||
} while (--i);
|
||
}
|
||
if (len & 3) {
|
||
uint i = len & 3;
|
||
uint k = 0;
|
||
do {
|
||
k <<= 8;
|
||
k |= data[i - 1];
|
||
} while (--i);
|
||
k *= 0xcc9e2d51;
|
||
k = (k << 15) | (k >> 17);
|
||
k *= 0x1b873593;
|
||
h ^= k;
|
||
}
|
||
h ^= len;
|
||
h ^= h >> 16;
|
||
h *= 0x85ebca6b;
|
||
h ^= h >> 13;
|
||
h *= 0xc2b2ae35;
|
||
h ^= h >> 16;
|
||
return h;
|
||
}
|
||
|
||
|
||
template<typename T>
|
||
inline uint piHash(const T & v) {
|
||
return 0;
|
||
}
|
||
|
||
template<>
|
||
inline uint piHash(const char & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const uchar & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const short & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const ushort & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const int & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const uint & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const llong & v) {
|
||
return piHashData((const uchar *)&v, sizeof(v));
|
||
}
|
||
template<>
|
||
inline uint piHash(const ullong & v) {
|
||
return piHashData((const uchar *)&v, sizeof(v));
|
||
}
|
||
template<>
|
||
inline uint piHash(const float & v) {
|
||
return (uint)v;
|
||
}
|
||
template<>
|
||
inline uint piHash(const double & v) {
|
||
return piHashData((const uchar *)&v, sizeof(v));
|
||
}
|
||
template<>
|
||
inline uint piHash(const ldouble & v) {
|
||
return piHashData((const uchar *)&v, sizeof(v));
|
||
}
|
||
|
||
template<typename T>
|
||
inline void piDeleteAll(T & container) {
|
||
for (auto i: container)
|
||
delete i;
|
||
}
|
||
template<typename T>
|
||
inline void piDeleteAllAndClear(T & container) {
|
||
piDeleteAll(container);
|
||
container.clear();
|
||
}
|
||
|
||
#define piRoundf piRound<float>
|
||
#define piRoundd piRound<double>
|
||
#define piComparef piCompare<float>
|
||
#define piCompared piCompare<double>
|
||
#define piFloorf piFloor<float>
|
||
#define piFloord piFloor<double>
|
||
#define piCeilf piCeil<float>
|
||
#define piCeild piCeil<double>
|
||
#define piAbss piAbs<short>
|
||
#define piAbsi piAbs<int>
|
||
#define piAbsl piAbs<long>
|
||
#define piAbsll piAbs<llong>
|
||
#define piAbsf piAbs<float>
|
||
#define piAbsd piAbs<double>
|
||
#define piMins piMin<short>
|
||
#define piMini piMin<int>
|
||
#define piMinl piMin<long>
|
||
#define piMinll piMin<llong>
|
||
#define piMinf piMin<float>
|
||
#define piMind piMin<double>
|
||
#define piMaxs piMax<short>
|
||
#define piMaxi piMax<int>
|
||
#define piMaxl piMax<long>
|
||
#define piMaxll piMax<llong>
|
||
#define piMaxf piMax<float>
|
||
#define piMaxd piMax<double>
|
||
#define piClamps piClamp<short>
|
||
#define piClampi piClamp<int>
|
||
#define piClampl piClamp<long>
|
||
#define piClampll piClamp<llong>
|
||
#define piClampf piClamp<float>
|
||
#define piClampd piClamp<double>
|
||
#define piLetobes piLetobe<ushort>
|
||
#define piLetobei piLetobe<uint>
|
||
#define piLetobel piLetobe<ulong>
|
||
#define piLetobell piLetobe<ullong>
|
||
#define piLetobef piLetobe<float>
|
||
|
||
|
||
#endif // PIBASE_H
|