move toStdFunction() to pibase.h refactor PIParseHelper, now it much more abstract and useful fix PIIODevice::createFromFullPath() when whitespaces at start or end are presence PIStreamPacker add events for start and end packet receive PIClientServer::ClientBase add virtual methods for start and end packet receive. also one can enable diagnostics with enableDiagnostics() method PICout now call flush() on each end of output add PIString::entries(const PIString & str)
740 lines
22 KiB
C++
740 lines
22 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 "pibase_macros.h"
|
||
#include "pimemoryblock.h"
|
||
#include "pip_export.h"
|
||
|
||
#include <string.h>
|
||
|
||
#ifdef CC_AVR_GCC
|
||
# include <ArduinoSTL.h>
|
||
#endif
|
||
#include <atomic>
|
||
#include <cassert>
|
||
#include <cstddef>
|
||
#include <functional>
|
||
#include <initializer_list>
|
||
#include <limits>
|
||
|
||
//! \~\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);
|
||
}
|
||
|
||
|
||
template<typename T>
|
||
constexpr T piMin(const T & f, const T & s) {
|
||
return ((f > s) ? s : f);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return minimum of several 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, typename... Args>
|
||
constexpr T piMin(const T & f, const T & s, const Args &... args) {
|
||
return piMin<T>(piMin<T>(f, s), args...);
|
||
}
|
||
|
||
|
||
template<typename T>
|
||
constexpr T piMax(const T & f, const T & s) {
|
||
return ((f < s) ? s : f);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function return maximum of several 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, typename... Args>
|
||
constexpr T piMax(const T & f, const T & s, const Args &... args) {
|
||
return piMax<T>(piMax<T>(f, s), args...);
|
||
}
|
||
|
||
|
||
//! \~\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 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;
|
||
}
|
||
|
||
|
||
// Endians
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
|
||
//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1])
|
||
inline void piChangeEndianBinary(void * data, size_t size) {
|
||
auto hs = size / 2;
|
||
for (size_t i = 0; i < hs; i++)
|
||
piSwap<uchar>(((uchar *)data)[size - i - 1], ((uchar *)data)[i]);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
|
||
//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1])
|
||
inline void piChangeEndianBinary(PIMemoryBlock mem_blk) {
|
||
if (mem_blk.isNull()) return;
|
||
piChangeEndianBinary(mem_blk.data(), mem_blk.size());
|
||
}
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function that inverse byte order of value "v"
|
||
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
|
||
template<typename T>
|
||
inline void piChangeEndian(T & v);
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Templated function that returns value "v" with inversed byte order
|
||
//! \~russian Шаблонный метод, возвращающий значение "v" с измененным порядком байт
|
||
template<typename T>
|
||
inline T piChangedEndian(const T & v);
|
||
|
||
|
||
template<typename T>
|
||
inline void piChangeEndian(T & v) {
|
||
piChangeEndianBinary(&v, sizeof(T));
|
||
}
|
||
|
||
template<typename T>
|
||
inline T piChangedEndian(const T & v) {
|
||
T ret = v;
|
||
piChangeEndianBinary(&ret, sizeof(T));
|
||
return ret;
|
||
}
|
||
template<>
|
||
inline uint16_t piChangedEndian(const uint16_t & v) {
|
||
return (v << 8) | (v >> 8);
|
||
}
|
||
template<>
|
||
inline uint32_t piChangedEndian(const uint32_t & v) {
|
||
return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);
|
||
}
|
||
template<>
|
||
inline float piChangedEndian(const float & v) {
|
||
union {
|
||
float f;
|
||
uint32_t i;
|
||
} u;
|
||
u.f = v;
|
||
u.i = piChangedEndian(u.i);
|
||
return u.f;
|
||
}
|
||
|
||
template<>
|
||
inline void piChangeEndian(uint16_t & v) {
|
||
v = piChangedEndian(v);
|
||
}
|
||
template<>
|
||
inline void piChangeEndian(uint32_t & v) {
|
||
v = piChangedEndian(v);
|
||
}
|
||
template<>
|
||
inline void piChangeEndian(float & v) {
|
||
v = piChangedEndian(v);
|
||
}
|
||
|
||
|
||
DEPRECATEDM("use piChangeEndianBinary()")
|
||
inline void piLetobe(void * data, int size) {
|
||
piChangeEndianBinary(data, size);
|
||
}
|
||
|
||
template<typename T>
|
||
DEPRECATEDM("use piChangedEndian()")
|
||
inline T piLetobe(const T & v) {
|
||
return piChangedEndian(v);
|
||
}
|
||
|
||
|
||
//! \~\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));
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Call \b delete on each "container" element.
|
||
//! \~russian Вызывает \b delete на каждый элемент "container".
|
||
template<typename T>
|
||
inline void piDeleteAll(const T & container) {
|
||
for (auto i: container) {
|
||
delete i;
|
||
}
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Call \b delete on each element of
|
||
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
|
||
//! \~russian Вызывает \b delete на каждый элемент
|
||
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
|
||
template<typename T>
|
||
inline void piDeleteAll(std::initializer_list<T> container) {
|
||
for (auto i: container) {
|
||
delete i;
|
||
}
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Call \b delete on each "container" element and clear container.
|
||
//! \~russian Вызывает \b delete на каждый элемент "container" и очищает контейнер.
|
||
template<typename T>
|
||
inline void piDeleteAllAndClear(T & container) {
|
||
piDeleteAll(container);
|
||
container.clear();
|
||
}
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Call \b delete if "pointer" is not null and set it to null. Returns if deleted.
|
||
//! \~russian Вызывает \b delete на "pointer" если он не нулевой и устанавливает его в ноль. Возвращает было ли удаление.
|
||
template<typename T>
|
||
inline bool piDeleteSafety(T *& pointer) {
|
||
if (!pointer) return false;
|
||
delete pointer;
|
||
pointer = nullptr;
|
||
return true;
|
||
}
|
||
|
||
#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>
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Class for executing a function upon scope exit
|
||
//! \~russian Класс для выполнения функции при выходе из области видимости
|
||
//! \~\details
|
||
//! \~english Example
|
||
//! \~russian Пример
|
||
//! \~\code
|
||
//! bool yourFunc() {
|
||
//! PIScopeExitCall error_call([]() { piCout << "Error!"; });
|
||
//! ...
|
||
//! if (!good0) {
|
||
//! ...
|
||
//! return false;
|
||
//! }
|
||
//! if (!good1) {
|
||
//! ...
|
||
//! return false;
|
||
//! }
|
||
//! ...
|
||
//! error_call.cancel();
|
||
//! return true;
|
||
//! }
|
||
//! \endcode
|
||
//! \~english In this example "Error!" will be printed on every \b false function return.
|
||
//! \~russian В данном примере будет выведен "Error!" при каждом \b false возврате из функции.
|
||
class PIP_EXPORT PIScopeExitCall {
|
||
public:
|
||
//! \~\brief
|
||
//! \~english Constructor that takes a function to execute
|
||
//! \~russian Конструктор, который принимает функцию для выполнения
|
||
explicit PIScopeExitCall(std::function<void()> f): func(f) {}
|
||
|
||
//! \~\brief
|
||
//! \~english Destructor that executes the function if it exists
|
||
//! \~russian Деструктор, который выполняет функцию, если она существует
|
||
~PIScopeExitCall() { call(); }
|
||
|
||
//! \~\brief
|
||
//! \~english Method for canceling the function
|
||
//! \~russian Метод для отмены функции
|
||
void cancel() { func = nullptr; }
|
||
|
||
//! \~\brief
|
||
//! \~english Method for call the function
|
||
//! \~russian Метод для вызова функции
|
||
void call() {
|
||
if (func) func();
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Method for call and canceling the function
|
||
//! \~russian Метод для вызова и отмены функции
|
||
void callAndCancel() {
|
||
call();
|
||
cancel();
|
||
}
|
||
|
||
private:
|
||
NO_COPY_CLASS(PIScopeExitCall)
|
||
|
||
std::function<void()> func;
|
||
};
|
||
|
||
|
||
//! \~\brief
|
||
//! \~english Inherit from this class to make your class non-trivially copyable.
|
||
//! \~russian Наследуйтесь от этого класса чтобы сделать свой класс нетривиально копируемым.
|
||
struct PIP_EXPORT PINonTriviallyCopyable {
|
||
PINonTriviallyCopyable() noexcept = default;
|
||
PINonTriviallyCopyable(const PINonTriviallyCopyable &) noexcept = default;
|
||
PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept;
|
||
PINonTriviallyCopyable & operator=(const PINonTriviallyCopyable &) noexcept = default;
|
||
PINonTriviallyCopyable & operator=(PINonTriviallyCopyable &&) noexcept = default;
|
||
~PINonTriviallyCopyable() = default;
|
||
};
|
||
inline PINonTriviallyCopyable::PINonTriviallyCopyable(PINonTriviallyCopyable &&) noexcept = default;
|
||
|
||
|
||
template<typename T>
|
||
struct FunctionType {
|
||
using Type = void;
|
||
};
|
||
|
||
template<typename Ret, typename Class, typename... Args>
|
||
struct FunctionType<Ret (Class::*)(Args...) const> {
|
||
using Type = std::function<Ret(Args...)>;
|
||
};
|
||
|
||
template<typename L>
|
||
typename FunctionType<decltype(&L::operator())>::Type toStdFunction(L const & func) {
|
||
return func;
|
||
}
|
||
|
||
|
||
#endif // PIBASE_H
|