git-svn-id: svn://db.shs.com.ru/pip@400 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5

This commit is contained in:
2017-04-18 20:49:45 +00:00
parent b1b23bf89c
commit 95c1f34b45
192 changed files with 291 additions and 187 deletions

445
src_main/core/pibase.h Normal file
View File

@@ -0,0 +1,445 @@
/*! \file pibase.h
* \brief Base types and functions
*
* This file implements first layer above the system and
* declares some basic useful functions
*/
/*
PIP - Platform Independent Primitives
Base types and functions
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIBASE_H
#define PIBASE_H
#include "piversion.h"
#include "piplatform.h"
#include "pip_export.h"
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
#define PIP_VERSION ((PIP_VERSION_MAJOR << 16) | (PIP_VERSION_MINOR < 8) | PIP_VERSION_REVISION)
#ifdef DOXYGEN
//! Major value of PIP version
# define PIP_VERSION_MAJOR
//! Minor value of PIP version
# define PIP_VERSION_MINOR
//! Revision value of PIP version
# define PIP_VERSION_REVISION
//! Suffix of PIP version
# define PIP_VERSION_SUFFIX
//! Macro is defined when compile-time debug is enabled
# define PIP_DEBUG
//! Macro is defined when host is any Windows
# define WINDOWS
//! Macro is defined when host is QNX or Blackberry
# define QNX
//! Macro is defined when host is Blackberry
# define BLACKBERRY
//! Macro is defined when host is FreeBSD
# define FREE_BSD
//! Macro is defined when host is Mac OS
# define MAC_OS
//! Macro is defined when host is Android
# define ANDROID
//! Macro is defined when host is any Linux
# define LINUX
//! Macro is defined when compiler is GCC or MinGW
# define CC_GCC
//! Macro is defined when PIP is decided that host is support language
# define HAS_LOCALE
//! Macro is defined when compiler is Visual Studio
# define CC_VC
//! Macro is defined when compiler is unknown
# define CC_OTHER
//! Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation
# define PIP_TIMER_RT
//! Define this macro to use STL implementation of containers, else PIP implementation will be used
# define PIP_CONTAINERS_STL
#endif
#include <cstddef>
#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")
# else
# define SHUT_RDWR SD_BOTH
# endif
typedef int socklen_t;
extern long long __pi_perf_freq;
#endif
#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
#ifdef CC_GCC
# undef DEPRECATED
# define DEPRECATED __attribute__((deprecated))
# if CC_GCC_VERSION > 0x025F // > 2.95
# ifdef LINUX
# define HAS_LOCALE
# endif
# ifdef MAC_OS
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# endif
# endif
# ifdef ANDROID
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wextra"
# pragma GCC diagnostic ignored "-Wliteral-suffix"
# endif
#endif
#ifdef CC_VC
# undef DEPRECATED
# define DEPRECATED
# 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
# define DEPRECATED
#endif
// Private data macros
#define PRIVATE_DECLARATION \
struct __Private__; \
friend struct __Private__; \
struct __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__ & o) {if (p) delete p; p = new c::__Private__();} \
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & o) {if (p) delete p; p = new c::__Private__(); return *this;}
#define PRIVATE (__privateinitializer__.p)
//! Macro used for infinite loop
#define FOREVER for (;;)
//! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(1);
//! Macro used for infinite wait
#define WAIT_FOREVER FOREVER msleep(1);
//! global variable enabling output to piCout, default is true
extern PIP_EXPORT bool piDebug;
//! global variable that set minimum real update interval
//! for function PIInit::mountInfo(), default is 10000 ms
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 Templated function for swap two values
* \details Example:\n \snippet piincludes.cpp swap */
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
/*! \brief Templated function for swap two values without "="
* \details Example:\n \snippet piincludes.cpp swapBinary */
template<typename T> inline void piSwapBinary(T & f, T & s) {
static 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];
}
}
/*! \brief Templated function return round of float falue
* \details Round is the nearest integer value \n
* There are some macros:
* - \c piRoundf for "float"
* - \c piRoundd for "double"
*
* Example:
* \snippet piincludes.cpp round */
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
/*! \brief Templated function return floor of float falue
* \details Floor is the largest integer that is not greater than value \n
* There are some macros:
* - \c piFloorf for "float"
* - \c piFloord for "double"
*
* Example:
* \snippet piincludes.cpp floor */
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
/*! \brief Templated function return ceil of float falue
* \details Ceil is the smallest integer that is not less than value \n
* There are some macros:
* - \c piCeilf for "float"
* - \c piCeild for "double"
*
* Example:
* \snippet piincludes.cpp ceil */
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
/*! \brief Templated function return absolute of numeric falue
* \details 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 */
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
/*! \brief Templated function return minimum of two values
* \details 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 */
template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
/*! \brief Templated function return minimum of tree values
* \details 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 */
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
/*! \brief Templated function return maximum of two values
* \details 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 */
template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
/*! \brief Templated function return maximum of tree values
* \details 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 */
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
/*! \brief Templated function return clamped value
* \details 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 */
template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
/// Function inverse byte order in memory block
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 Templated function that inverse byte order of value "v"
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
/*! \brief Templated function that returns "v" with inversed byte order
* \details 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 */
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
// specialization
template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);}
template<> inline uint piLetobe(const uint & 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;
uint 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;
}
DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);}
DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
#ifdef DOXYGEN
/// \deprecated \brief Use \a piLetobe() instead of this function
ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
/// \deprecated \brief Use \a piLetobe() instead of this function
uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
#endif
#define piRoundf piRound<float>
#define piRoundd piRound<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

View File

@@ -0,0 +1,24 @@
#include "pibitarray.h"
#include "picout.h"
PICout operator <<(PICout s, const PIBitArray & ba) {
s.space();
s.setControl(0, true);
for (uint i = 0; i < ba.bitSize(); ++i) {
s << int(ba[i]);
if (i % 8 == 7) s << ' ';
}
s.restoreControl();
return s;
}
std::ostream &operator <<(std::ostream & s, const PIBitArray & ba) {
for (uint i = 0; i < ba.bitSize(); ++i) {
s << ba[i];
if (i % 8 == 7) s << ' ';
}
return s;
}

107
src_main/core/pibitarray.h Executable file
View File

@@ -0,0 +1,107 @@
/*
PIP - Platform Independent Primitives
Bit array
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIBITARRAY_H
#define PIBITARRAY_H
#include "pivector.h"
class PIP_EXPORT PIBitArray {
friend PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v);
friend PIByteArray & operator >>(PIByteArray & s, PIBitArray & v);
public:
PIBitArray(const int & size = 0) {resize(size);}
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(ulong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
PIBitArray(uchar * bytes, uint size) {resize(size * 8); memcpy(data(), bytes, size);}
uint bitSize() const {return size_;}
uint byteSize() const {return bytesInBits(size_);}
PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;}
PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;}
PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;}
PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;}
PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);}
PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;}
PIBitArray & push_back(const uchar & value) {return push_back(value > 0);}
PIBitArray & insert(const uint & index, const bool & value) {
resize(size_ + 1);
uint fi = byteSize() - 1, si = index / 8, ti = index % 8;
uchar c = data_[si];
for (uint i = fi; i > si; --i) {
data_[i] <<= 1;
if ((0x80 & data_[i - 1]) == 0x80) data_[i] |= 1;
else data_[i] &= 0xFE;}
data_[si] &= (0xFF >> (7 - ti));
data_[si] |= ((c << 1) & (0xFF << (ti)));
if (value) data_[si] |= (1 << ti);
else data_[si] &= ~(1 << ti);
return *this;}
PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);}
PIBitArray & push_front(const bool & value) {return insert(0, value);}
PIBitArray & push_front(const uchar & value) {return push_front(value > 0);}
PIBitArray & pop_back() {return resize(size_ - 1);}
PIBitArray & pop_front() {
if (size_ == 0) return *this;
uint fi = byteSize() - 1;
for (uint i = 0; i < fi; ++i) {
data_[i] >>= 1;
if ((1 & data_[i + 1]) == 1) data_[i] |= 0x80;
else data_[i] &= 0x7F;}
data_[fi] >>= 1;
resize(size_ - 1);
return *this;}
PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;}
uchar * data() {return data_.data();}
uchar toUChar() {if (size_ == 0) return 0; return data_[0];}
ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
uint toUInt() {uint t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
ulong toULong() {ulong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;}
bool operator [](const uint & index) const {return at(index);}
void operator +=(const PIBitArray & ba) {append(ba);}
bool operator ==(const PIBitArray & ba) const {if (bitSize() != ba.bitSize()) return false; for (uint i = 0; i < bitSize(); ++i) if (at(i) != ba[i]) return false; return true;}
bool operator !=(const PIBitArray & ba) const {return !(*this == ba);}
void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;}
void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
void operator =(const ulong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
void operator =(const ullong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
private:
static uint bytesInBits(const uint & bits) {return (bits + 7) / 8;}
PIVector<uchar> data_;
uint size_;
};
std::ostream & operator <<(std::ostream & s, const PIBitArray & ba);
inline PICout operator <<(PICout s, const PIBitArray & ba);
#endif // PIBITARRAY_H

372
src_main/core/pibytearray.cpp Executable file
View File

@@ -0,0 +1,372 @@
/*
PIP - Platform Independent Primitives
Byte array
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pibytearray.h"
#include "pistring.h"
#include <iostream>
/*! \class PIByteArray
* \brief Byte array
* \details This class based on PIDeque<uchar> and provide some handle function
* to manipulate it.
*
* \section PIByteArray_sec0 Usage
* %PIByteArray can be used to store custom data and manipulate it. There are many
* stream operators to store/restore common types to byte array. Store operators
* places data at the end of array, restore operators takes data from the beginning
* of array.
* In addition there are Base 64 convertions and checksums:
* * plain 8-bit
* * plain 32-bit
*
* One of the major usage of %PIByteArray is stream functions. You can form binary
* packet from many types (also dynamic types, e.g. PIVector) with one line:
* \snippet pibytearray.cpp 0
*
* Or you can descibe stream operator of your own type and store/restore vectors of
* your type:
* \snippet pibytearray.cpp 1
*
* For store/restore custom data blocks there is PIByteArray::RawData class. Stream
* operators of this class simply store/restore data block to/from byte array.
* \snippet pibytearray.cpp 2
*
* \section PIByteArray_sec1 Attention
* Stream operator of %PIByteArray store byte array as vector, not simply append
* content of byte array. This operators useful to transmit custom data as %PIByteArray
* packed into parent byte array, e.g. to form packet from %PIByteArray.
* To append one byte array to another use funtion \a append().
* \snippet pibytearray.cpp 3
*
*
*/
static const uchar base64Table[64] = {
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f};
static const uchar base64InvTable[256] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,
0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE,
0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
struct base64HelpStruct {
base64HelpStruct() {v = 0;}
inline void setBytes(const uchar * r, int size = 3) {
v = 0;
switch (size) {
case 3: v |= r[2];
case 2: v |= r[1] << 8;
case 1: v |= r[0] << 16;
}
}
inline void getBytes(uchar * r) {
r[0] = (v >> 16) & 0xFF;
r[1] = (v >> 8) & 0xFF;
r[2] = v & 0xFF;
}
inline void setAscii(const uchar * r, int size = 4) {
v = 0;
switch (size) {
case 4: v |= (base64InvTable[r[3]] & 0x3F);
case 3: v |= (base64InvTable[r[2]] & 0x3F) << 6;
case 2: v |= (base64InvTable[r[1]] & 0x3F) << 12;
case 1: v |= (base64InvTable[r[0]] & 0x3F) << 18;
}
}
inline void getAscii(uchar * r) {
r[0] = base64Table[(v >> 18) & 0x3F];
r[1] = base64Table[(v >> 12) & 0x3F];
r[2] = base64Table[(v >> 6) & 0x3F];
r[3] = base64Table[ v & 0x3F];
}
uint v;
};
PIByteArray &PIByteArray::convertToBase64() {
return *this = toBase64();
}
PIByteArray &PIByteArray::convertFromBase64() {
return *this = fromBase64(*this);
}
PIByteArray PIByteArray::toBase64() const {
if (isEmpty()) return PIByteArray();
base64HelpStruct hs;
PIByteArray ret;
int sz = (size_s() / 3) * 3, ri = -1;
uchar t[4];
ret.resize(((size_s() - 1) / 3 + 1) * 4);
for (int i = 0; i < sz; i += 3) {
hs.setBytes(data(i));
hs.getAscii(t);
ret[++ri] = (t[0]);
ret[++ri] = (t[1]);
ret[++ri] = (t[2]);
ret[++ri] = (t[3]);
}
int der = size_s() % 3;
switch (der) {
case 1:
hs.setBytes(data(sz), 1);
hs.getAscii(t);
ret[++ri] = (t[0]);
ret[++ri] = (t[1]);
ret[++ri] = ('=');
ret[++ri] = ('=');
break;
case 2:
hs.setBytes(data(sz), 2);
hs.getAscii(t);
ret[++ri] = (t[0]);
ret[++ri] = (t[1]);
ret[++ri] = (t[2]);
ret[++ri] = ('=');
break;
default: break;
}
return ret;
}
PIByteArray PIByteArray::fromBase64(const PIByteArray & base64) {
if (base64.isEmpty()) return PIByteArray();
base64HelpStruct hs;
PIByteArray ret;
int sz = base64.size_s(), ind = -1;
uchar t[4];
ret.resize(sz / 4 * 3);
for (int i = 0; i < sz; i += 4) {
hs.setAscii(base64.data(i));
hs.getBytes(t);
ret[++ind] = (t[0]);
ret[++ind] = (t[1]);
ret[++ind] = (t[2]);
}
if (base64.back() == '=') ret.pop_back();
if (sz > 1) if (base64[sz - 2] == '=') ret.pop_back();
return ret;
}
PIByteArray PIByteArray::fromBase64(const PIString & base64) {
return fromBase64(base64.toByteArray());
}
PIByteArray & PIByteArray::compressRLE(uchar threshold) {
PIByteArray t;
uchar fb, clen, mlen = 255 - threshold;
for (uint i = 0; i < size();) {
fb = at(i);
clen = 1;
while (at(++i) == fb) {
++clen;
if (clen == mlen)
break;
}
if (clen > 1) {
t.push_back(threshold + clen);
t.push_back(fb);
continue;
}
if (fb >= threshold) {
t.push_back(threshold + 1);
t.push_back(fb);
} else
t.push_back(fb);
}
*this = t;
return *this;
}
PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
PIByteArray t;
uchar fb, clen;
for (uint i = 0; i < size(); ++i) {
fb = at(i);
if (fb >= threshold) {
clen = fb - threshold;
fb = at(++i);
for (uint j = 0; j < clen; ++j)
t.push_back(fb);
continue;
} else
t.push_back(fb);
}
*this = t;
return *this;
}
uchar PIByteArray::checksumPlain8() const {
uchar c = 0;
int sz = size_s();
for (int i = 0; i < sz; ++i)
c += at(i);
c = ~(c + 1);
return c;
}
uint PIByteArray::checksumPlain32() const {
uint c = 0;
int sz = size_s();
for (int i = 0; i < sz; ++i)
c += at(i) * (i + 1);
c = ~(c + 1);
return c;
}
PIString PIByteArray::toString(int base) const {
PIString ret;
int sz = size_s();
for (int i = 0; i < sz; ++i) {
if (i > 0) ret += " ";
if (base == 2) ret += "b";
if (base == 8) ret += "0";
if (base == 16) ret += "0x";
ret += PIString::fromNumber(at(i), base);
}
return ret;
}
PIString PIByteArray::toHex() const {
PIByteArray hex(size() * 2);
uchar *hexData = hex.data();
const uchar *d = data();
for (int i = 0; i < size_s(); ++i) {
int j = (d[i] >> 4) & 0xf;
if (j <= 9) hexData[i*2] = (j + '0');
else hexData[i*2] = (j + 'a' - 10);
j = d[i] & 0xf;
if (j <= 9) hexData[i*2+1] = (j + '0');
else hexData[i*2+1] = (j + 'a' - 10);
}
return PIString(hex);
}
PIByteArray PIByteArray::fromString(PIString str) {
PIByteArray ret;
if (str.trim().isEmpty()) return ret;
str.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ");
PIStringList bl(str.split(" "));
bool ok(false);
piForeachC (PIString & b, bl) {
int bv = b.toInt(-1, &ok);
if (ok) ret << uchar(bv);
}
return ret;
}
PIByteArray PIByteArray::fromHex(PIString str) {
PIByteArray hexEncoded = str.toByteArray();
PIByteArray res((hexEncoded.size() + 1)/ 2);
uchar *result = res.data() + res.size();
bool odd_digit = true;
for (int i = hexEncoded.size() - 1; i >= 0; --i) {
int ch = hexEncoded.at(i);
int tmp;
if (ch >= '0' && ch <= '9') tmp = ch - '0';
else if (ch >= 'a' && ch <= 'f') tmp = ch - 'a' + 10;
else if (ch >= 'A' && ch <= 'F') tmp = ch - 'A' + 10;
else continue;
if (odd_digit) {
--result;
*result = tmp;
odd_digit = false;
} else {
*result |= tmp << 4;
odd_digit = true;
}
}
res.remove(0, result - res.data());
return res;
}
PICout operator <<(PICout s, const PIByteArray & ba) {
s.space();
s.setControl(0, true);
s << "{";
for (uint i = 0; i < ba.size(); ++i) {
s << ba[i];
if (i < ba.size() - 1) s << ", ";
}
s << "}";
s.restoreControl();
return s;
}
std::ostream &operator <<(std::ostream & s, const PIByteArray & ba) {
s << "{";
for (uint i = 0; i < ba.size(); ++i) {
s << ba[i];
if (i < ba.size() - 1) s << ", ";
}
s << "}";
return s;
}

279
src_main/core/pibytearray.h Executable file
View File

@@ -0,0 +1,279 @@
/*! \file pibytearray.h
* \brief Byte array
*/
/*
PIP - Platform Independent Primitives
Byte array
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIBYTEARRAY_H
#define PIBYTEARRAY_H
#ifdef DOXYGEN
//! This macro allow stream template operators for write and read any type from byte array. Use it with attention!
# define PIP_BYTEARRAY_STREAM_ANY_TYPE
#endif
#include "pichar.h"
#include "pibitarray.h"
#include "pimap.h"
__PICONTAINERS_SIMPLE_TYPE__(PIChar)
class PIString;
class PIByteArray;
class PIP_EXPORT PIByteArray: public PIDeque<uchar>
{
public:
//! Constructs an empty byte array
PIByteArray() {;}
//! Constructs 0-filled byte array with size "size"
PIByteArray(const uint size) {resize(size);}
//! Constructs byte array from data "data" and size "size"
PIByteArray(const void * data, const uint size): PIDeque<uchar>((const uchar*)data, size_t(size)) {/*for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);*/}
//! Help struct to store/restore custom blocks of data to/from PIByteArray
struct RawData {
friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
public:
//! Constructs data block
RawData(void * data = 0, int size = 0) {d = data; s = size;}
RawData(const RawData & o) {d = o.d; s = o.s;}
//! Constructs data block
RawData(const void * data, const int size) {d = const_cast<void * >(data); s = size;}
RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;}
private:
void * d;
int s;
};
//! Return resized byte array
PIByteArray resized(int new_size) const {PIByteArray tv(*this); tv.resize(new_size); return tv;}
//! Convert data to Base 64 and return this byte array
PIByteArray & convertToBase64();
//! Convert data from Base 64 and return this byte array
PIByteArray & convertFromBase64();
//! Return converted to Base 64 data
PIByteArray toBase64() const;
//! Return converted from Base 64 data
PIByteArray & compressRLE(uchar threshold = 192);
PIByteArray & decompressRLE(uchar threshold = 192);
PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;}
PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;}
PIString toString(int base = 16) const;
PIString toHex() const;
//! Add to the end data "data" with size "size"
PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
//! Add to the end byte array "data"
PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
/*PIByteArray & operator <<(short v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
PIByteArray & operator <<(ushort v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
PIByteArray & operator <<(int v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
PIByteArray & operator <<(uint v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
PIByteArray & operator <<(llong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}
PIByteArray & operator <<(ullong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}*/
//PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;}
//! Returns plain 8-bit checksum
uchar checksumPlain8() const;
//! Returns plain 32-bit checksum
uint checksumPlain32() const;
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
static PIByteArray fromString(PIString str);
static PIByteArray fromHex(PIString str);
static PIByteArray fromBase64(const PIByteArray & base64);
static PIByteArray fromBase64(const PIString & base64);
};
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {if (v0.size() == v1.size()) {for (uint i = 0; i < v0.size(); ++i) if (v0[i] != v1[i]) return v0[i] < v1[i]; return false;} return v0.size() < v1.size();}
//! \relatesalso PIByteArray \brief Output to std::ostream operator
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
//! \relatesalso PIByteArray \brief Output to PICout operator
PICout operator <<(PICout s, const PIByteArray & ba);
#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v));
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, bool v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, char v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const ldouble & v) {PBA_OPERATOR_TO return s;}
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;}
//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;}
#undef PBA_OPERATOR_TO
#define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v));
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, bool & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, char & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, ldouble & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); if (sz > 0) memcpy(v.data(), s.data(), v.size()); s.remove(0, v.size()); return s;}
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;}
template<typename Type0, typename Type1> inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v);
//! \relatesalso PIByteArray \brief Store operator
template<typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v);
//! \relatesalso PIByteArray \brief Store operator
template<typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v);
//! \relatesalso PIByteArray \brief Store operator
template <typename Key, typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v);
//! Write operator to \c PIByteArray
inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << v.ch; return s;}
//! \relatesalso PIByteArray \brief Restore operator
template<typename Type0, typename Type1> inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v);
//! \relatesalso PIByteArray \brief Restore operator
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v);
//! \relatesalso PIByteArray \brief Restore operator
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v);
//! \relatesalso PIByteArray \brief Restore operator
template <typename Key, typename T> inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v);
//! Read operator from \c PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {s >> v.ch; return s;}
//! \relatesalso PIByteArray \brief Store operator
inline PIByteArray & operator <<(PIByteArray & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
template<typename Type0, typename Type1>
inline PIByteArray & operator <<(PIByteArray & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
template<typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << int(v.size_s()); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
template<typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {s << int(v.size_s()); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
template <typename Key, typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIMap<Key, T> & v) {
s << int(v.pim_index.size_s());
for (uint i = 0; i < v.size(); ++i)
s << v.pim_index[i].index << v.pim_index[i].key;
s << v.pim_content;
return s;
}
//! \relatesalso PIByteArray \brief Restore operator
inline PIByteArray & operator >>(PIByteArray & s, PIBitArray & v) {assert(s.size_s() >= 8); s >> v.size_ >> v.data_; return s;}
template<typename Type0, typename Type1>
inline PIByteArray & operator >>(PIByteArray & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
template<typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
template<typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
template <typename Key, typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIMap<Key, T> & v) {
assert(s.size_s() >= 4);
int sz; s >> sz; v.pim_index.resize(sz);
for (int i = 0; i < sz; ++i)
s >> v.pim_index[i].index >> v.pim_index[i].key;
s >> v.pim_content;
return s;
}
#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE
template<typename T>
inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;}
#endif
#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE
template<typename T>
inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
#endif
#undef PBA_OPERATOR_FROM
//! \relatesalso PIByteArray \brief Byte arrays compare operator
inline bool operator ==(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return false; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return false; return true;}
//! \relatesalso PIByteArray \brief Byte arrays compare operator
inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return true; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return true; return false;}
#endif // PIBYTEARRAY_H

295
src_main/core/pichar.cpp Normal file
View File

@@ -0,0 +1,295 @@
/*! \file pichar.h
* \brief Unicode char
*/
/*
PIP - Platform Independent Primitives
Unicode char
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <string.h>
#include "pibytearray.h"
#ifdef PIP_ICU
# include "unicode/ucnv.h"
# include "unicode/ustring.h"
char * __syslocname__ = 0;
char * __sysoemname__ = 0;
#endif
#ifdef BLACKBERRY
# include <ctype.h>
#endif
/*! \class PIChar
* \brief Unicode char
* \details This class is wrapper around \c "uint".
* There are many contructors and information functions
*/
PIChar::PIChar(const char * c, int * bytes) {
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(__syslocname__, &e);
if (cc) {
UChar uc;
e = (UErrorCode)0;
int ret = ucnv_toUChars(cc, &uc, 1, c, 4, &e);
if (bytes) * bytes = ret;
ucnv_close(cc);
ch = uc;
return;
}
#endif
ch = *reinterpret_cast<const int * >(c);
}
PIChar PIChar::fromConsole(char c) {
PIChar ret;
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(__sysoemname__, &e);
if (cc) {
UChar uc;
e = (UErrorCode)0;
ucnv_toUChars(cc, &uc, 1, &c, 1, &e);
ucnv_close(cc);
ret.ch = uc;
return ret;
}
#endif
ret.ch = c;
return ret;
}
PIChar PIChar::fromSystem(char c) {
PIChar ret;
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(__syslocname__, &e);
if (cc) {
UChar uc;
e = (UErrorCode)0;
ucnv_toUChars(cc, &uc, 1, &c, 1, &e);
ucnv_close(cc);
ret.ch = uc;
return ret;
}
#endif
ret.ch = c;
return ret;
}
PIChar PIChar::fromUTF8(const char * c) {
PIChar ret;
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open("UTF-8", &e);
if (cc) {
UChar uc;
e = (UErrorCode)0;
ucnv_toUChars(cc, &uc, 1, c, 8, &e);
ucnv_close(cc);
ret.ch = uc;
return ret;
}
#endif
ret.ch = *(ushort*)c;
return ret;
}
bool PIChar::operator ==(const PIChar & o) const {
return ch == o.ch;
}
bool PIChar::operator >(const PIChar & o) const {
return
#ifdef PIP_ICU
u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) > 0;
#else
strcmp(toCharPtr(), o.toCharPtr()) > 0;
#endif
}
bool PIChar::operator <(const PIChar & o) const {
return
#ifdef PIP_ICU
u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) < 0;
#else
strcmp(toCharPtr(), o.toCharPtr()) < 0;
#endif
}
bool PIChar::operator >=(const PIChar & o) const {
return
#ifdef PIP_ICU
u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) >= 0;
#else
strcmp(toCharPtr(), o.toCharPtr()) >= 0;
#endif
}
bool PIChar::operator <=(const PIChar & o) const {
return
#ifdef PIP_ICU
u_strCompare((const UChar*)&(ch), 1, (const UChar*)&(o.ch), 1, FALSE) <= 0;
#else
strcmp(toCharPtr(), o.toCharPtr()) <= 0;
#endif
}
bool PIChar::isDigit() const {
return isdigit(ch) != 0;
}
bool PIChar::isHex() const {
return isxdigit(ch) != 0;
}
bool PIChar::isGraphical() const {
return isgraph(ch) != 0;
}
bool PIChar::isControl() const {
return iscntrl(ch) != 0;
}
bool PIChar::isLower() const {
return islower(ch) != 0;
}
bool PIChar::isUpper() const {
return isupper(ch) != 0;
}
bool PIChar::isPrint() const {
return isprint(ch) != 0;
}
bool PIChar::isSpace() const {
return isspace(ch) != 0;
}
bool PIChar::isAlpha() const {
return isalpha(ch) != 0;
}
bool PIChar::isAscii() const {
return isascii(ch) != 0;
}
const wchar_t * PIChar::toWCharPtr() const {
return reinterpret_cast<const wchar_t * >(&ch);
}
const char * PIChar::toCharPtr() const {
return reinterpret_cast<const char * >(&ch);
}
wchar_t PIChar::toWChar() const {
return wchar_t(ch);
}
char PIChar::toConcole1Byte() const {
if (ch < 0x80) return ch;
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(__sysoemname__, &e);
if (cc) {
char uc[8];
e = (UErrorCode)0;
ucnv_fromUChars(cc, uc, 8, (const UChar*)(&ch), 1, &e);
ucnv_close(cc);
return uc[0];
}
#endif
return toAscii();
}
PIChar PIChar::toUpper() const {
#ifdef PIP_ICU
UChar c(0);
UErrorCode e((UErrorCode)0);
u_strToUpper(&c, 1, (const UChar*)(&ch), 1, 0, &e);
return PIChar(c);
#else
return PIChar(toupper(ch));
#endif
}
PIChar PIChar::toLower() const {
#ifdef PIP_ICU
UChar c(0);
UErrorCode e((UErrorCode)0);
u_strToLower(&c, 1, (const UChar*)(&ch), 1, 0, &e);
return PIChar(c);
#else
return PIChar(tolower(ch));
#endif
}
std::ostream & operator <<(std::ostream & s, const PIChar & v) {
s << v.toCharPtr();
return s;
}
PICout operator <<(PICout s, const PIChar & v) {
s.space();
s.setControl(0, true);
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(PICout::isBufferActive() ? __syslocname__ : __sysoemname__, &e);
if (cc) {
char uc[8];
memset(uc, 0, 8);
e = (UErrorCode)0;
ucnv_fromUChars(cc, uc, 8, (const UChar*)(&v.ch), 1, &e);
ucnv_close(cc);
s << uc;
} else
#endif
s << v.toCharPtr();
s.restoreControl();
return s;
}

213
src_main/core/pichar.h Executable file
View File

@@ -0,0 +1,213 @@
/*! \file pichar.h
* \brief Unicode char
*/
/*
PIP - Platform Independent Primitives
Unicode char
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICHAR_H
#define PICHAR_H
#include "piincludes.h"
#ifdef PIP_ICU
extern char * __syslocname__;
extern char * __sysoemname__;
#endif
class PIP_EXPORT PIChar
{
friend class PIString;
friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v);
friend PIByteArray & operator >>(PIByteArray & s, PIChar & v);
friend PICout operator <<(PICout s, const PIChar & v);
public:
//! Contructs ascii symbol
PIChar(const char c) {ch = c; ch &= 0xFF;}
//! Contructs 2-bytes symbol
PIChar(const short c) {ch = c;}
//! Contructs 4-bytes symbol
PIChar(const int c) {ch = c;}
//! Contructs ascii symbol
PIChar(const uchar c) {ch = c; ch &= 0xFF;}
//! Contructs 2-bytes symbol
PIChar(const ushort c) {ch = c;}
//! Default constructor. Contructs 4-bytes symbol
PIChar(const uint c = 0) {ch = c;}
//! Contructs symbol from no more than 4 bytes of string
PIChar(const char * c, int * bytes = 0);
//inline operator const int() {return static_cast<const int>(ch);}
//inline operator const char() {return toAscii();}
//! Copy operator
PIChar & operator =(const char v) {ch = v; return *this;}
/*inline PIChar & operator =(const short v) {ch = v; return *this;}
inline PIChar & operator =(const int v) {ch = v; return *this;}
inline PIChar & operator =(const uchar v) {ch = v; return *this;}
inline PIChar & operator =(const ushort v) {ch = v; return *this;}
inline PIChar & operator =(const uint v) {ch = v; return *this;}*/
//! Compare operator
bool operator ==(const PIChar & o) const;
/*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false;
if (isAscii()) return (o.toAscii() == toAscii());
return (o.toInt() == toInt());}
inline bool operator ==(const char o) const {return (PIChar(o) == *this);}
inline bool operator ==(const short o) const {return (PIChar(o) == *this);}
inline bool operator ==(const int o) const {return (PIChar(o) == *this);}
inline bool operator ==(const uchar o) const {return (PIChar(o) == *this);}
inline bool operator ==(const ushort o) const {return (PIChar(o) == *this);}
inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/
//! Compare operator
bool operator !=(const PIChar & o) const {return !(o == *this);}
/*inline bool operator !=(const char o) const {return (PIChar(o) != *this);}
inline bool operator !=(const short o) const {return (PIChar(o) != *this);}
inline bool operator !=(const int o) const {return (PIChar(o) != *this);}
inline bool operator !=(const uchar o) const {return (PIChar(o) != *this);}
inline bool operator !=(const ushort o) const {return (PIChar(o) != *this);}
inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/
//! Compare operator
bool operator >(const PIChar & o) const;
//! Compare operator
bool operator <(const PIChar & o) const;
//! Compare operator
bool operator >=(const PIChar & o) const;
//! Compare operator
bool operator <=(const PIChar & o) const;
//! Return \b true if symbol is digit ('0' to '9')
bool isDigit() const;
//! Return \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F')
bool isHex() const;
//! Return \b true if symbol is drawable (without space)
bool isGraphical() const;
//! Return \b true if symbol is control byte (< 32 or 127)
bool isControl() const;
//! Return \b true if symbol is in lower case
bool isLower() const;
//! Return \b true if symbol is in upper case
bool isUpper() const;
//! Return \b true if symbol is printable (with space)
bool isPrint() const;
//! Return \b true if symbol is space or tab
bool isSpace() const;
//! Return \b true if symbol is alphabetical letter
bool isAlpha() const;
//! Return \b true if symbol is ascii (< 128)
bool isAscii() const;
const wchar_t * toWCharPtr() const;
//! Return as <tt>"char * "</tt> string
const char * toCharPtr() const;
wchar_t toWChar() const;
char toAscii() const {return ch % 256;}
char toConcole1Byte() const;
ushort unicode16Code() const {return ch;}
//! Return symbol in upper case
PIChar toUpper() const;
//! Return symbol in lower case
PIChar toLower() const;
static PIChar fromConsole(char c);
static PIChar fromSystem(char c);
static PIChar fromUTF8(const char * c);
private:
ushort ch;
};
//! Output operator to \c std::ostream
std::ostream & operator <<(std::ostream & s, const PIChar & v);
//! Output operator to \a PICout
PICout operator <<(PICout s, const PIChar & v);
//! Compare operator
inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);}
//! Compare operator
inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);}
//! Compare operator
inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);}
//! Compare operator
inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);}
//! Compare operator
inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);}
//! Compare operator
inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);}
//! Compare operator
inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);}
//! Compare operator
inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);}
//! Compare operator
inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);}
//! Compare operator
inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);}
//! Compare operator
inline bool operator ==(const int v, const PIChar & c) {return (PIChar(v) == c);}
//! Compare operator
inline bool operator >(const int v, const PIChar & c) {return (PIChar(v) > c);}
//! Compare operator
inline bool operator <(const int v, const PIChar & c) {return (PIChar(v) < c);}
//! Compare operator
inline bool operator >=(const int v, const PIChar & c) {return (PIChar(v) >= c);}
//! Compare operator
inline bool operator <=(const int v, const PIChar & c) {return (PIChar(v) <= c);}
#endif // PICHAR_H

View File

@@ -0,0 +1,55 @@
#include "pichunkstream.h"
/*! \class PIChunkStream
* \brief Class for binary serialization
*
* \section PIChunkStream_sec0 Synopsis
* This class provides very handly mechanism to store and restore values to and from
* \a PIByteArray. The main advantage of using this class is that your binary data
* become independent from order and collection of your values.
*
* \section PIChunkStream_sec1 Mechanism
* %PIChunkStream works with items called "chunk". Chunk is an ID and any value that
* can be stored and restored to \a PIByteArray with stream operators << and >>.
* You can place chunks to stream and read chunks from stream.
*
* To construct %PIChunkStream for writing data use any constructor. Empty constructor
* creates internal empty buffer that can be accessed by function \a data().
* Non-empty constructor works with given byte array.
*
* To read chunks from byte array use function \a read() that returns ID of
* next chunk. Then you can get value of this chunk with function \a getData(),
* but you should definitely know type of this value. You can read from byte array
* while \a atEnd() if false.
*
* \section PIChunkStream_ex0 Example
* Prepare your structs to work with %PIChunkStream
* \snippet pichunkstream.cpp struct
* Writing to %PIChunkStream
* \snippet pichunkstream.cpp write
* Reading from %PIChunkStream
* \snippet pichunkstream.cpp read
*/
void PIChunkStream::setSource(const PIByteArray & data) {
data_ = const_cast<PIByteArray*>(&data);
_init();
}
void PIChunkStream::setSource(PIByteArray * data) {
data_ = (data ? data : &tmp_data);
_init();
}
PIChunkStream::~PIChunkStream() {
}
void PIChunkStream::_init() {
last_id = -1;
last_data.clear();
}

View File

@@ -0,0 +1,92 @@
/*! \file pichunkstream.h
* \brief Binary serializator
*/
/*
PIP - Platform Independent Primitives
Binary serializator
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICHUNKSTREAM_H
#define PICHUNKSTREAM_H
#include "pibytearray.h"
class PIChunkStream
{
public:
//! Contructs stream for read from "data"
PIChunkStream(const PIByteArray & data) {setSource(data);}
//! Contructs stream for read or write to/from "data", or empty stream for write
PIChunkStream(PIByteArray * data = 0) {setSource(data);}
~PIChunkStream();
template <typename T>
struct Chunk {
Chunk(int i, const T & d): id(i), data(d) {}
int id;
T data;
};
//! Returns chunk with ID "id" and value "data" for write to stream
template <typename T> static Chunk<T> chunk(int id, const T & data) {return Chunk<T>(id, data);}
void setSource(const PIByteArray & data);
void setSource(PIByteArray * data);
//! Returns internal buffer with written data
PIByteArray data() const {return tmp_data;}
//! Returns if there is end of stream
bool atEnd() const {return data_->isEmpty();}
//! Read one chunk from stream and returns its ID
int read() {(*data_) >> last_id >> last_data; return last_id;}
//! Returns last readed chunk ID
int getID() {return last_id;}
//! Returns value of last readed chunk
template <typename T>
T getData() const {T ret; PIByteArray s(last_data); s >> ret; return ret;}
//! Place value of last readed chunk into "v"
template <typename T>
void get(T & v) const {v = getData<T>();}
private:
void _init();
int last_id;
PIByteArray * data_, last_data, tmp_data;
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c);
};
template <typename T>
PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c) {
PIByteArray ba;
ba << c.data;
(*(s.data_)) << c.id << ba;
return s;
}
#endif // PICHUNKSTREAM_H

101
src_main/core/picli.cpp Executable file
View File

@@ -0,0 +1,101 @@
/*
PIP - Platform Independent Primitives
Command-Line Parser
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picli.h"
#include "pisysteminfo.h"
/*! \class PICLI
* \brief Command-line arguments parser
*
* \section PICLI_sec0 Synopsis
* This class provide handy parsing of command-line arguments. First you should add
* arguments to PICLI with function \a addArgument(). Then you can check if there
* is some argument in application command-line with function \a hasArgument();
* \section PICLI_sec1 Example
* \snippet picli.cpp main
*/
PICLI::PICLI(int argc, char * argv[]) {
setName("CLI");
needParse = true;
_prefix_short = "-";
_prefix_full = "--";
_count_opt = 0;
_count_mand = 0;
for (int i = 0; i < argc; ++i)
_args_raw << argv[i];
if (argc > 0)
PISystemInfo::instance()->execCommand = argv[0];
}
void PICLI::parse() {
if (!needParse) return;
PIString cra, full;
Argument * last = 0;
for (int i = 1; i < _args_raw.size_s(); ++i) {
cra = _args_raw[i];
if (cra.left(2) == _prefix_full) {
last = 0;
full = cra.right(cra.length() - 2);
piForeach (Argument & a, _args) {
if (a.full_key == full) {
a.found = true;
last = &a;
break;
}
}
} else {
if (cra.left(1) == _prefix_short) {
last = 0;
for (int j = 1; j < cra.length(); ++j) {
bool found = false;
piForeach (Argument & a, _args) {
if (a.short_key == cra[j]) {
a.found = true;
last = &a;
found = true;
break;
}
}
if (!found) break;
}
} else {
if (last == 0 ? true : !last->has_value) {
if (_args_mand.size_s() < _count_mand) {
_args_mand << cra;
continue;
}
if (_args_opt.size_s() < _count_opt || _count_opt < 0) {
_args_opt << cra;
continue;
}
piCoutObj << "[PICli] Arguments overflow, \"" << cra << "\" ignored";
}
if (last == 0 ? false : last->has_value) {
last->value = cra;
last = 0;
}
}
}
}
needParse = false;
}

101
src_main/core/picli.h Executable file
View File

@@ -0,0 +1,101 @@
/*! \file picli.h
* \brief Command-Line parser
*/
/*
PIP - Platform Independent Primitives
Command-Line Parser
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICLI_H
#define PICLI_H
#include "piobject.h"
class PIP_EXPORT PICLI: public PIObject
{
PIOBJECT_SUBCLASS(PICLI, PIObject)
public:
//! Constructor
PICLI(int argc, char * argv[]);
//! Add argument with name "name", short key = name first letter, full key = name
void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;}
//! Add argument with name "name", short key = "shortKey", full key = name
void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;}
//! Add argument with name "name", short key = "shortKey", full key = name
void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;}
//! Add argument with name "name", short key = "shortKey", full key = "fullKey"
void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;}
//! Add argument with name "name", short key = "shortKey", full key = "fullKey"
void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;}
//! Returns unparsed command-line argument by index "index". Index 0 is program execute command.
PIString rawArgument(int index) {parse(); return _args_raw[index];}
PIString mandatoryArgument(int index) {parse(); return _args_mand[index];}
PIString optionalArgument(int index) {parse(); return _args_opt[index];}
//! Returns unparsed command-line arguments
const PIStringList & rawArguments() {parse(); return _args_raw;}
const PIStringList & mandatoryArguments() {parse(); return _args_mand;}
const PIStringList & optionalArguments() {parse(); return _args_opt;}
//! Returns program execute command without arguments
PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();}
bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;}
PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();}
PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();}
PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();}
const PIString & shortKeyPrefix() const {return _prefix_short;}
const PIString & fullKeyPrefix() const {return _prefix_full;}
int mandatoryArgumentsCount() const {return _count_mand;}
int optionalArgumentsCount() const {return _count_opt;}
void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix; needParse = true;}
void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix; needParse = true;}
void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;}
void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;}
private:
struct Argument {
Argument() {has_value = found = false;}
Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {name = n; short_key = s; full_key = f; has_value = v; found = false;}
PIString name;
PIChar short_key;
PIString full_key;
PIString value;
bool has_value, found;
};
void parse();
PIString _prefix_short, _prefix_full;
PIStringList _args_raw, _args_mand, _args_opt;
PISet<PIString> keys_full, keys_short;
PIVector<Argument> _args;
int _count_mand, _count_opt;
bool needParse;
};
#endif // PICLI_H

57
src_main/core/picollection.cpp Executable file
View File

@@ -0,0 +1,57 @@
#include "picollection.h"
/** \class PICollection
* \brief Interface to discover element groups
* \details
* \section PICollection_sec0 Synopsis
* This class has only static functions so no need to create instance of the
* %PICollection. This class provide macros to add some classes or existing
* objects to global collection and access to them from any place of the code.
* \snippet picollection.cpp main
* */
PIStringList PICollection::groups() {
PIStringList sl;
piForeachC (Group & g, *_groups)
sl << g.name;
return sl;
}
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
piForeachC (Group & g, *_groups)
if (g.name == group)
return g.elements;
return PIVector<const PIObject * >();
}
void PICollection::addToGroup(const PIString & group, const PIObject * element) {
//piCout << "add to" << group << element;
PIString n = element->className();
piForeach (Group & g, *_groups)
if (g.name == group) {
for (int i = 0; i < g.elements.size_s(); ++i)
if (PIString(g.elements[i]->className()) == n)
return;
g.elements << element;
//piCout << "new group" << group << ", ok";
return;
}
*_groups << Group(group);
_groups->back().elements << element;
//piCout << "new group" << group << ", ok";
}
PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name) {
if (element == 0) return;
const_cast<PIObject * >(element)->setName(name);
PICollection::addToGroup(group, element);
}
bool __PICollectionInitializer::_inited_(false);
PIVector<PICollection::Group> * PICollection::_groups;

96
src_main/core/picollection.h Executable file
View File

@@ -0,0 +1,96 @@
/*! \file picollection.h
* \brief Custom elements collection
*/
/*
PIP - Platform Independent Primitives
Peer - named I/O ethernet node, forming self-organized peering network
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICOLLECTION_H
#define PICOLLECTION_H
#include "piobject.h"
#ifdef DOXYGEN
/** \brief Add existing element "object" in group with name "group"
* \relatesalso PICollection
* \details If there is no group with name "group" it will be created.
* Only one element of the class "object" can be in group "group". If
* this is already exists nothing be happens. \n "object" should to
* be pointer to object based on PIObject. */
# define ADD_TO_COLLECTION(group, object)
/** \brief Add new element of class "class" in group with name "group"
* \relatesalso PICollection
* \details If there is no group with name "group" it will be created.
* Only one element of the class "class" can be in group "group". If
* this is already exists nothing be happens. \n "class" should to
* be name of the any class based on PIObject. */
# define ADD_NEW_TO_COLLECTION(group, class)
#else
# define ADD_TO_COLLECTION(group, object) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object);
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object, #name);
# define ADD_NEW_TO_COLLECTION(group, class) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class());
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class(), #name);
#endif
class PIP_EXPORT PICollection
{
friend class __PICollectionInitializer;
public:
PICollection() {;}
//! \brief Returns all existing groups by their names
static PIStringList groups();
//! \brief Returns all elements of group "group"
static PIVector<const PIObject * > groupElements(const PIString & group);
static void addToGroup(const PIString & group, const PIObject * element);
class CollectionAdder {
public:
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString());
};
protected:
struct Group {
Group(const PIString & name_ = PIString()) {name = name_;}
//~Group() {piCout << "delete group" << name << this; piForeach (const PIObject * o, elements) delete o; elements.clear();}
PIString name;
PIVector<const PIObject * > elements;
};
static PIVector<Group> * _groups;
};
class PIP_EXPORT __PICollectionInitializer {
public:
__PICollectionInitializer() {
if (_inited_) return;
_inited_ = true;
PICollection::_groups = new PIVector<PICollection::Group>();
}
static bool _inited_;
};
static __PICollectionInitializer __picollectioninitializer;
#endif // PICOLLECTION_H

View File

@@ -0,0 +1,31 @@
/*
PIP - Platform Independent Primitives
Module includes
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICOREMODULE_H
#define PICOREMODULE_H
#include "picollection.h"
#include "piobject.h"
#include "pistatemachine.h"
#include "pitime.h"
#include "picli.h"
#include "pichunkstream.h"
#include "pipropertystorage.h"
#endif // PICOREMODULE_H

407
src_main/core/picout.cpp Normal file
View File

@@ -0,0 +1,407 @@
/*
PIP - Platform Independent Primitives
Universal output to console class
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "picout.h"
#include "piconsole.h"
#include "pibytearray.h"
#include "pistack.h"
#include "pistring_std.h"
#ifdef WINDOWS
# include <windows.h>
# include <wincon.h>
# define COMMON_LVB_UNDERSCORE 0x8000
#endif
/*! \class PICout
* \brief Class for formatted output similar std::cout
*
* \section PICout_sec0 Synopsis
* This class provide many stream operators for output with some features.
* Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
* threads.
*
* \section PICout_sec1 Features
* - insertion spaces between entries
* - insertion new line at the end of output
* - strings are quoted
* - custom output operator can be easily written
*
* \section PICout_ex0 Usage
* \snippet picout.cpp 0
*
* \section PICout_ex1 Writing your own output operator
* \snippet picout.cpp own
*/
PIMutex __PICout_mutex__;
PIString __PICout_string__;
using namespace PICoutManipulators;
bool PICout::buffer_ = false;
PRIVATE_DEFINITION_START(PICout)
PIStack<PICoutControls> cos_;
#ifdef WINDOWS
static void * hOut;
static WORD dattr;
static DWORD smode;
#endif
PRIVATE_DEFINITION_END(PICout)
#ifdef WINDOWS
void * PICout::__Private__::hOut = 0;
WORD PICout::__Private__::dattr = 0;
DWORD PICout::__Private__::smode = 0;
#endif
PICout::PICout(PIFlags<PICoutControl> controls): fo_(true), cc_(false), fc_(false), cnb_(10), co_(controls) {
#ifdef WINDOWS
if (__Private__::hOut == 0) {
__Private__::hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO sbi;
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
__Private__::dattr = sbi.wAttributes;
}
attr_ = __Private__::dattr;
#endif
__PICout_mutex__.lock();
}
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), cnb_(other.cnb_), attr_(other.attr_), co_(other.co_) {
}
PICout::~PICout() {
if (fc_) applyFormat(PICoutManipulators::Default);
if (cc_) return;
newLine();
__PICout_mutex__.unlock();
}
PICout PICout::operator <<(const PICoutAction v) {
#ifdef WINDOWS
CONSOLE_SCREEN_BUFFER_INFO sbi;
COORD coord;
CONSOLE_CURSOR_INFO curinfo;
#endif
switch (v) {
case PICoutManipulators::Flush:
if (!PICout::buffer_)
std::cout << std::flush;
break;
case PICoutManipulators::Backspace:
if (!PICout::buffer_) {
#ifdef WINDOWS
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
coord = sbi.dwCursorPosition;
coord.X = piMax<int>(0, int(coord.X) - 1);
SetConsoleCursorPosition(__Private__::hOut, coord);
printf(" ");
SetConsoleCursorPosition(__Private__::hOut, coord);
#else
printf("\e[1D \e[1D");
#endif
}
break;
case PICoutManipulators::ShowCursor:
if (!PICout::buffer_) {
#ifdef WINDOWS
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = true;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
#else
printf("\e[?25h");
#endif
}
break;
case PICoutManipulators::HideCursor:
if (!PICout::buffer_) {
#ifdef WINDOWS
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = false;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
#else
printf("\e[?25l");
#endif
}
break;
case PICoutManipulators::ClearLine:
if (!PICout::buffer_) {
#ifdef WINDOWS
GetConsoleScreenBufferInfo(__Private__::hOut, &sbi);
coord = sbi.dwCursorPosition;
int dx = coord.X;
coord.X = 0;
SetConsoleCursorPosition(__Private__::hOut, coord);
if (dx > 0) {
char * line = new char[dx + 1];
memset(line, ' ', dx);
line[dx] = 0;
printf("%s", line);
delete[] line;
}
SetConsoleCursorPosition(__Private__::hOut, coord);
#else
printf("\e[0G\e[K");
#endif
}
break;
case PICoutManipulators::ClearScreen:
if (!PICout::buffer_) {
#ifdef WINDOWS
/// TODO !!!
/*GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = false;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
SetConsoleCursorPosition(__Private__::hOut, ulcoord);
FillConsoleOutputAttribute(__Private__::hOut, __Private__::dattr, width * (height + 1), ulcoord, &written);
FillConsoleOutputCharacter(__Private__::hOut, ' ', width * (height + 1), ulcoord, &written);*/
#else
printf("\e[H\e[J");
#endif
}
break;
case PICoutManipulators::SaveContol: saveControl(); break;
case PICoutManipulators::RestoreControl: restoreControl(); break;
default: break;
};
return *this;
}
#define PICOUTTOTARGET(v) {if (PICout::buffer_) __PICout_string__ << (v); else std::cout << (v);}
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_))
PICout PICout::operator <<(const char * v) {if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
PICout PICout::operator <<(const std::string & v) {space(); quote(); if (PICout::buffer_) __PICout_string__ << StdString2PIString(v); else std::cout << (v); quote(); return *this;}
PICout PICout::operator <<(const bool v) {space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
PICout PICout::operator <<(const char v) {space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) return *this;}
PICout PICout::operator <<(const short int v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ushort v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const int v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const uint v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const long v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ulong v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const llong v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const ullong v) {space(); PINUMERICCOUT return *this;}
PICout PICout::operator <<(const float v) {space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const double v) {space(); PICOUTTOTARGET(v) return *this;}
PICout PICout::operator <<(const void * v) {space(); PICOUTTOTARGET("0x") PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) return *this;}
PICout PICout::operator <<(const PIObject * v) {
space();
if (v == 0) PICOUTTOTARGET("PIObject*(0x0)")
else {
PICOUTTOTARGET(v->className())
PICOUTTOTARGET("*(0x")
PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16))
PICOUTTOTARGET(", \"")
PICOUTTOTARGET(v->name())
PICOUTTOTARGET("\")")
}
return *this;
}
PICout PICout::operator <<(const PICoutSpecialChar v) {
switch (v) {
case Null:
if (PICout::buffer_) __PICout_string__ << PIChar(0);
else std::cout << char(0);
break;
case NewLine:
if (PICout::buffer_) __PICout_string__ << "\n";
else std::cout << '\n';
fo_ = true;
break;
case Tab:
if (PICout::buffer_) __PICout_string__ << "\t";
else std::cout << '\t';
break;
case Esc:
#ifdef CC_VC
if (PICout::buffer_) __PICout_string__ << PIChar(27);
else std::cout << char(27);
#else
if (PICout::buffer_) __PICout_string__ << "\e";
else std::cout << '\e';
#endif
break;
case Quote:
if (PICout::buffer_) __PICout_string__ << "\"";
else std::cout << '"';
break;
};
return *this;
}
PICout & PICout::saveControl() {
PRIVATE->cos_.push(co_);
return *this;
}
PICout & PICout::restoreControl() {
if (!PRIVATE->cos_.isEmpty()) {
co_ = PRIVATE->cos_.top();
PRIVATE->cos_.pop();
}
return *this;
}
#undef PICOUTTOTARGET
#undef PINUMERICCOUT
PICout & PICout::space() {
if (!fo_ && co_[AddSpaces]) {
if (PICout::buffer_) __PICout_string__ << " ";
else std::cout << ' ';
}
fo_ = false;
return *this;
}
PICout & PICout::quote() {
if (co_[AddQuotes]) {
if (PICout::buffer_) __PICout_string__ << "\"";
else std::cout << '"';
}
fo_ = false;
return *this;
}
PICout & PICout::newLine() {
if (co_[AddNewLine]) {
if (PICout::buffer_) __PICout_string__ << "\n";
else std::cout << std::endl;
}
fo_ = false;
return *this;
}
void PICout::applyFormat(PICoutFormat f) {
if (PICout::buffer_) return;
fc_ = true;
#ifdef WINDOWS
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
switch (f) {
case Bin: case Oct: case Dec: case Hex: break;
case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break;
case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break;
case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break;
case PICoutManipulators::Red: attr_ = (attr_ & mask_fore) | FOREGROUND_RED; break;
case PICoutManipulators::Green: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN; break;
case PICoutManipulators::Blue: attr_ = (attr_ & mask_fore) | FOREGROUND_BLUE; break;
case PICoutManipulators::Yellow: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN; break;
case PICoutManipulators::Magenta: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_BLUE; break;
case PICoutManipulators::Cyan: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case PICoutManipulators::White: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
case PICoutManipulators::BackBlack: attr_ = (attr_ & mask_back); break;
case PICoutManipulators::BackRed: attr_ = (attr_ & mask_back) | BACKGROUND_RED; break;
case PICoutManipulators::BackGreen: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN; break;
case PICoutManipulators::BackBlue: attr_ = (attr_ & mask_back) | BACKGROUND_BLUE; break;
case PICoutManipulators::BackYellow: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN; break;
case PICoutManipulators::BackMagenta: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_BLUE; break;
case PICoutManipulators::BackCyan: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
case PICoutManipulators::BackWhite: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break;
case PICoutManipulators::Default: attr_ = __Private__::dattr; break;
default: break;
}
SetConsoleTextAttribute(__Private__::hOut, attr_);
#else
switch (f) {
case Bin: case Oct: case Dec: case Hex: break;
case PICoutManipulators::Bold: printf("\e[1m"); break;
case PICoutManipulators::Faint: printf("\e[2m"); break;
case PICoutManipulators::Italic: printf("\e[3m"); break;
case PICoutManipulators::Underline: printf("\e[4m"); break;
case PICoutManipulators::Blink: printf("\e[5m"); break;
case PICoutManipulators::Black: printf("\e[30m"); break;
case PICoutManipulators::Red: printf("\e[31m"); break;
case PICoutManipulators::Green: printf("\e[32m"); break;
case PICoutManipulators::Blue: printf("\e[34m"); break;
case PICoutManipulators::Yellow: printf("\e[33m"); break;
case PICoutManipulators::Magenta: printf("\e[35m"); break;
case PICoutManipulators::Cyan: printf("\e[36m"); break;
case PICoutManipulators::White: printf("\e[37m"); break;
case PICoutManipulators::BackBlack: printf("\e[40m"); break;
case PICoutManipulators::BackRed: printf("\e[41m"); break;
case PICoutManipulators::BackGreen: printf("\e[42m"); break;
case PICoutManipulators::BackBlue: printf("\e[44m"); break;
case PICoutManipulators::BackYellow: printf("\e[43m"); break;
case PICoutManipulators::BackMagenta: printf("\e[45m"); break;
case PICoutManipulators::BackCyan: printf("\e[46m"); break;
case PICoutManipulators::BackWhite: printf("\e[47m"); break;
case PICoutManipulators::Default: printf("\e[0m"); break;
default: break;
}
#endif
}
bool PICout::setBufferActive(bool on, bool clear) {
PIMutexLocker ml(__PICout_mutex__);
bool ret = PICout::buffer_;
if (clear) __PICout_string__.clear();
PICout::buffer_ = on;
return ret;
}
bool PICout::isBufferActive() {
return PICout::buffer_;
}
PIString PICout::buffer(bool clear) {
PIMutexLocker ml(__PICout_mutex__);
PIString ret = __PICout_string__;
if (clear) __PICout_string__.clear();
return ret;
}
void PICout::clearBuffer() {
PIMutexLocker ml(__PICout_mutex__);
__PICout_string__.clear();
}

264
src_main/core/picout.h Normal file
View File

@@ -0,0 +1,264 @@
/*! \file picout.h
* \brief Universal output to console class
*/
/*
PIP - Platform Independent Primitives
Universal output to console class
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICOUT_H
#define PICOUT_H
#include "piincludes.h"
#ifdef DOXYGEN
//! \brief Macro used for conditional (piDebug) output to PICout
# define piCout
//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
# define piCoutObj
#else
# define piCout if (piDebug) PICout()
# define piCoutObj if (piDebug && debug()) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]")
#endif
extern PIMutex __PICout_mutex__;
extern PIString __PICout_string__;
//! \brief Namespace contains enums controlled PICout
namespace PICoutManipulators {
//! \brief Enum contains special characters
enum PIP_EXPORT PICoutSpecialChar {
Null /*! Null-character, '\\0' */,
NewLine /*! New line character, '\\n' */,
Tab /*! Tab character, '\\t' */,
Esc /*! Escape character, '\\e' */,
Quote /*! Quote character, '"' */
};
//! \brief Enum contains immediate action
enum PIP_EXPORT PICoutAction {
Flush /*! Flush the output */,
Backspace /*! Remove last symbol */,
ShowCursor /*! Show cursor */,
HideCursor /*! Hide cursor */,
ClearLine /*! Clear current line */,
ClearScreen /*! Clear the screen */,
SaveContol /*! Save control flags, equivalent to \a saveControl() */,
RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */
};
//! \brief Enum contains control of PICout
enum PIP_EXPORT PICoutControl {
AddNone /*! No controls */ = 0x0,
AddSpaces /*! Spaces will be appear after each output */ = 0x1,
AddNewLine /*! New line will be appear after all output */ = 0x2,
AddQuotes /*! Each string will be quoted */ = 0x4,
AddAll /*! All controls */ = 0xFFFFFFFF
};
//! \brief Enum contains output format
enum PIP_EXPORT PICoutFormat {
Bin /*! Binary representation of integers */ = 0x01,
Oct /*! Octal representation of integers */ = 0x02,
Dec /*! Decimal representation of integers */ = 0x04,
Hex /*! Hexadecimal representation of integers */ = 0x08,
Bold /*! Bold */ = 0x10,
Faint /*! */ = 0x20,
Italic /*! */ = 0x40,
Underline /*! Underline */ = 0x80,
Blink /*! Blink */ = 0x100,
Black /*! Black font */ = 0x400,
Red /*! Red font */ = 0x800,
Green /*! Green font */ = 0x1000,
Blue /*! Blue font */ = 0x2000,
Yellow /*! Yellow font */ = 0x4000,
Magenta /*! Magenta font */ = 0x8000,
Cyan /*! Cyan font */ = 0x10000,
White /*! White font */ = 0x20000,
BackBlack /*! Black background */ = 0x40000,
BackRed /*! Red background */ = 0x80000,
BackGreen /*! Green background */ = 0x100000,
BackBlue /*! Blue background */ = 0x200000,
BackYellow /*! Yellow background */ = 0x400000,
BackMagenta /*! Magenta background */ = 0x800000,
BackCyan /*! Cyan background */ = 0x1000000,
BackWhite /*! White background */ = 0x2000000,
Default /*! Default format */ = 0x4000000
};
typedef PIFlags<PICoutControl> PICoutControls;
};
class PIP_EXPORT PICout {
public:
//! Default constructor with default features (AddSpaces and AddNewLine)
explicit PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
PICout(const PICout & other);
~PICout();
//! Output operator for strings with <tt>"const char * "</tt> type
PICout operator <<(const char * v);
//! Output operator for strings with <tt>"std::string"</tt> type
PICout operator <<(const std::string & v);
//! Output operator for boolean values
PICout operator <<(const bool v);
//! Output operator for <tt>"char"</tt> values
PICout operator <<(const char v);
//! Output operator for <tt>"unsigned char"</tt> values
PICout operator <<(const uchar v);
//! Output operator for <tt>"short"</tt> values
PICout operator <<(const short v);
//! Output operator for <tt>"unsigned short"</tt> values
PICout operator <<(const ushort v);
//! Output operator for <tt>"int"</tt> values
PICout operator <<(const int v);
//! Output operator for <tt>"unsigned int"</tt> values
PICout operator <<(const uint v);
//! Output operator for <tt>"long"</tt> values
PICout operator <<(const long v);
//! Output operator for <tt>"unsigned long"</tt> values
PICout operator <<(const ulong v);
//! Output operator for <tt>"long long"</tt> values
PICout operator <<(const llong v);
//! Output operator for <tt>"unsigned long long"</tt> values
PICout operator <<(const ullong v);
//! Output operator for <tt>"float"</tt> values
PICout operator <<(const float v);
//! Output operator for <tt>"double"</tt> values
PICout operator <<(const double v);
//! Output operator for pointers
PICout operator <<(const void * v);
//! Output operator for PIObject and ancestors
PICout operator <<(const PIObject * v);
//! Output operator for \a PICoutSpecialChar values
PICout operator <<(const PICoutManipulators::PICoutSpecialChar v);
//! Output operator for \a PIFlags<PICoutFormat> values
PICout operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v) {
if (v[PICoutManipulators::Bin]) cnb_ = 2;
if (v[PICoutManipulators::Oct]) cnb_ = 8;
if (v[PICoutManipulators::Dec]) cnb_ = 10;
if (v[PICoutManipulators::Hex]) cnb_ = 16;
if (v[PICoutManipulators::Bold]) applyFormat(PICoutManipulators::Bold);
if (v[PICoutManipulators::Faint]) applyFormat(PICoutManipulators::Faint);
if (v[PICoutManipulators::Italic]) applyFormat(PICoutManipulators::Italic);
if (v[PICoutManipulators::Underline]) applyFormat(PICoutManipulators::Underline);
if (v[PICoutManipulators::Blink]) applyFormat(PICoutManipulators::Blink);
if (v[PICoutManipulators::Black]) applyFormat(PICoutManipulators::Black);
if (v[PICoutManipulators::Red]) applyFormat(PICoutManipulators::Red);
if (v[PICoutManipulators::Green]) applyFormat(PICoutManipulators::Green);
if (v[PICoutManipulators::Blue]) applyFormat(PICoutManipulators::Blue);
if (v[PICoutManipulators::Yellow]) applyFormat(PICoutManipulators::Yellow);
if (v[PICoutManipulators::Magenta]) applyFormat(PICoutManipulators::Magenta);
if (v[PICoutManipulators::Cyan]) applyFormat(PICoutManipulators::Cyan);
if (v[PICoutManipulators::White]) applyFormat(PICoutManipulators::White);
if (v[PICoutManipulators::BackBlack]) applyFormat(PICoutManipulators::BackBlack);
if (v[PICoutManipulators::BackRed]) applyFormat(PICoutManipulators::BackRed);
if (v[PICoutManipulators::BackGreen]) applyFormat(PICoutManipulators::BackGreen);
if (v[PICoutManipulators::BackBlue]) applyFormat(PICoutManipulators::BackBlue);
if (v[PICoutManipulators::BackYellow]) applyFormat(PICoutManipulators::BackYellow);
if (v[PICoutManipulators::BackMagenta]) applyFormat(PICoutManipulators::BackMagenta);
if (v[PICoutManipulators::BackCyan]) applyFormat(PICoutManipulators::BackCyan);
if (v[PICoutManipulators::BackWhite]) applyFormat(PICoutManipulators::BackWhite);
if (v[PICoutManipulators::Default]) applyFormat(PICoutManipulators::Default);
return *this;
}
//! Output operator for \a PICoutFormat values
PICout operator <<(const PICoutManipulators::PICoutFormat v) {
switch (v) {
case PICoutManipulators::Bin: cnb_ = 2; break;
case PICoutManipulators::Oct: cnb_ = 8; break;
case PICoutManipulators::Dec: cnb_ = 10; break;
case PICoutManipulators::Hex: cnb_ = 16; break;
default: applyFormat(v);
};
return *this;
}
//! Do some action
PICout operator <<(const PICoutManipulators::PICoutAction v);
//! Set control flag "c" is "on" state
PICout & setControl(PICoutManipulators::PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
//! Set control flags "c" and if "save" exec \a saveControl()
PICout & setControl(PICoutManipulators::PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
//! Save control flags to internal stack \sa \a restoreControl()
PICout & saveControl();
//! Restore control flags from internal stack \sa \a saveControl()
PICout & restoreControl();
/*! \brief Conditional put space character to output
* \details If it is not a first output and control \a AddSpaces is set
* space character is put \sa \a quote(), \a newLine() */
PICout & space();
/*! \brief Conditional put quote character to output
* \details If control \a AddQuotes is set
* quote character is put \sa \a space(), \a newLine() */
PICout & quote();
/*! \brief Conditional put new line character to output
* \details If control \a AddNewLine is set
* new line character is put \sa \a space(), \a quote() */
PICout & newLine();
static bool setBufferActive(bool on, bool clear = false);
static bool isBufferActive();
static PIString buffer(bool clear = false);
static void clearBuffer();
private:
void applyFormat(PICoutManipulators::PICoutFormat f);
static bool buffer_;
PRIVATE_DECLARATION
bool fo_, cc_, fc_;
int cnb_, attr_;
PICoutManipulators::PICoutControls co_;
};
#endif // PICOUT_H

137
src_main/core/piflags.h Normal file
View File

@@ -0,0 +1,137 @@
/*! \file piflags.h
* \brief General flags class
*/
/*
PIP - Platform Independent Primitives
General flags class
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIFLAGS_H
#define PIFLAGS_H
#include "pip_export.h"
/*! \brief This class used as container for bit flags
* \details PIFlags is wrapper around \c "int". There are many
* bit-wise operators, native conversion to int and function
* to test flag. \n Example:
* \snippet piincludes.cpp flags
*/
template<typename Enum>
class PIP_EXPORT PIFlags {
public:
//! Constructor with flags = 0
PIFlags(): flags(0) {;}
//! Constructor with flags = Enum "e"
PIFlags(Enum e): flags(e) {;}
//! Constructor with flags = PIFlags "f"
PIFlags(const PIFlags & f): flags(f.flags) {;}
//! Constructor with flags = int "i"
PIFlags(const int i): flags(i) {;}
//! Set flags "f" to value "on"
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
//! Set flag "e" to value "on"
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
//! Set flag "i" to value "on"
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
//! copy operator
void operator =(const PIFlags & f) {flags = f.flags;}
//! copy operator
void operator =(const Enum & e) {flags = e;}
//! copy operator
void operator =(const int & i) {flags = i;}
//! compare operator
bool operator ==(const PIFlags & f) {return flags == f.flags;}
//! compare operator
bool operator ==(const Enum & e) {return flags == e;}
//! compare operator
bool operator ==(const int i) {return flags == i;}
//! compare operator
bool operator !=(const PIFlags & f) {return flags != f.flags;}
//! compare operator
bool operator !=(const Enum & e) {return flags != e;}
//! compare operator
bool operator !=(const int i) {return flags != i;}
//! compare operator
bool operator >(const PIFlags & f) {return flags > f.flags;}
//! compare operator
bool operator >(const Enum & e) {return flags > e;}
//! compare operator
bool operator >(const int i) {return flags > i;}
//! compare operator
bool operator <(const PIFlags & f) {return flags < f.flags;}
//! compare operator
bool operator <(const Enum & e) {return flags < e;}
//! compare operator
bool operator <(const int i) {return flags < i;}
//! compare operator
bool operator >=(const PIFlags & f) {return flags >= f.flags;}
//! compare operator
bool operator >=(const Enum & e) {return flags >= e;}
//! compare operator
bool operator >=(const int i) {return flags >= i;}
//! compare operator
bool operator <=(const PIFlags & f) {return flags <= f.flags;}
//! compare operator
bool operator <=(const Enum & e) {return flags <= e;}
//! compare operator
bool operator <=(const int i) {return flags <= i;}
//! Bit-wise AND operator
void operator &=(const PIFlags & f) {flags &= f.flags;}
//! Bit-wise AND operator
void operator &=(const Enum & e) {flags &= e;}
//! Bit-wise AND operator
void operator &=(const int i) {flags &= i;}
//! Bit-wise OR operator
void operator |=(const PIFlags & f) {flags |= f.flags;}
//! Bit-wise OR operator
void operator |=(const Enum & e) {flags |= e;}
//! Bit-wise OR operator
void operator |=(const int i) {flags |= i;}
//! Bit-wise XOR operator
void operator ^=(const PIFlags & f) {flags ^= f.flags;}
//! Bit-wise XOR operator
void operator ^=(const Enum & e) {flags ^= e;}
//! Bit-wise XOR operator
void operator ^=(const int i) {flags ^= i;}
//! Bit-wise AND operator
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
//! Bit-wise AND operator
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
//! Bit-wise AND operator
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
//! Bit-wise OR operator
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
//! Bit-wise OR operator
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
//! Bit-wise OR operator
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
//! Bit-wise XOR operator
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
//! Bit-wise XOR operator
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
//! Bit-wise XOR operator
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
//! Test flag operator
bool operator [](Enum e) const {return (flags & e) == e;}
//! Implicity conversion to \c int
operator int() const {return flags;}
private:
int flags;
};
#endif // PIFLAGS_H

265
src_main/core/piincludes.cpp Executable file
View File

@@ -0,0 +1,265 @@
/*
PIP - Platform Independent Primitives
Global includes
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes.h"
#include "piincludes_p.h"
#include "piconsole.h"
#include "pitime.h"
#ifndef QNX
# include <clocale>
#else
# include <locale.h>
#endif
#ifdef MAC_OS
//# include <mach/mach_traps.h>
//# include <mach/mach.h>
# include <mach/clock.h>
//# include <crt_externs.h>
#endif
#include <errno.h>
bool piDebug = true;
double piMountInfoRefreshIntervalMs = 10000.;
lconv * currentLocale =
#ifdef ANDROID
0;
#else
std::localeconv();
#endif
#ifdef MAC_OS
clock_serv_t __pi_mac_clock;
#endif
#ifdef WINDOWS
FILETIME __pi_ftjan1970;
long long __pi_perf_freq = -1;
PINtSetTimerResolution setTimerResolutionAddr = 0;
#endif
void errorClear() {
#ifdef WINDOWS
SetLastError(0);
#else
errno = 0;
#endif
}
PIString errorString() {
#ifdef WINDOWS
char * msg;
int err = GetLastError();
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
return "code " + PIString::fromNumber(err) + " - " + PIString(msg);
#else
int e = errno;
return PIString("code ") + PIString::fromNumber(e) + " - " + PIString(strerror(e));
#endif
}
PIString PIPVersion() {
static PIString ret(PIString::fromNumber(PIP_VERSION_MAJOR) + "." +
PIString::fromNumber(PIP_VERSION_MINOR) + "." +
PIString::fromNumber(PIP_VERSION_REVISION) +
PIP_VERSION_SUFFIX);
return ret;
}
/*! \class PICout
* \brief Class for formatted output similar std::cout
*
* \section PICout_sec0 Synopsis
* This class provide many stream operators for output with some features.
* Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel
* threads.
*
* \section PICout_sec1 Features
* - insertion spaces between entries
* - insertion new line at the end of output
* - strings are quoted
* - custom output operator can be easily written
*
* \section PICout_ex0 Usage
* \snippet picout.cpp 0
*
* \section PICout_ex1 Writing your own output operator
* \snippet picout.cpp own
*/
/*! \mainpage What is PIP
* PIP - Platform-Independent Primitives - is crossplatform library for C++ developers.
* It is wrap around STL and pure C++. This library can help developers write non-GUI
* projects much more quickly, efficiently and customizable than on pure C++.
* Library contains many classes, some of them are pure abstract, some classes
* can be used as they are, some classes should be inherited to new classes.
* PIP provide classes:
* * direct output to console (\a PICout)
* * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack)
* * byte array (\a PIByteArray)
* * string (\a PIString, \a PIStringList)
* * base object (events and handlers) (\a PIObject)
* * thread (\a PIThread)
* * timer (\a PITimer)
* * console (information output) (\a PIConsole)
* * stand-alone
* * server
* * client
* * I/O devices
* * base class (\a PIIODevice)
* * file (\a PIFile)
* * serial port (\a PISerial)
* * ethernet (\a PIEthernet)
* * USB (\a PIUSB)
* * packets extractor (\a PIPacketExtractor)
* * binary log (\a PIBinaryLog)
* * complex I/O point (\a PIConnection)
* * connection quality diagnotic (\a PIDiagnostics)
* * command-line arguments parser (\a PICLI)
* * math evaluator (\a PIEvaluator)
* * peering net node (\a PIPeer)
* * process (\a PIProcess)
* * state machine (\a PIStateMachine)
* \n \n Basic using of PIP described at page \ref using_basic */
/*! \page using_basic Getting started
* Many novice programmers are solved many common task with system integrity: output to console,
* keyboard buttons press detecting, working with serial ports, ethernet or files, and many other.
* These tasks can solve this library, and code, based only on PIP will be compile and work
* similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX.
* Typical application on PIP looks like this: \n
\code{.cpp}
#include <pip.h>
// declare key press handler
void key_event(char key, void * );
PIConsole console(false, key_event); // don`t start now, key handler is "key_event"
// some vars
int i = 2, j = 3;
// implicit key press handler
void key_event(char key, void * ) {
switch (key) {
case '-':
i--;
break;
case '+':
i++;
break;
case '(':
j--;
break;
case ')':
j++;
break;
};
};
class MainClass: public PITimer {
PIOBJECT(MainClass)
public:
MainClass() {}
protected:
void tick(void * data, int delimiter) {
piCout << "timer tick";
// timer tick
}
};
MainClass main_class;
int main(int argc, char * argv[]) {
// enabling auto-detection of exit button press, by default 'Q' (shift+q)
console.enableExitCapture();
// if we want to parse command-line arguments
PICLI cli(argc, argv);
cli.addArgument("console"); // "-c" or "--console"
cli.addArgument("debug"); // "-d" or "--debug"
// enabling or disabling global debug flag
piDebug = cli.hasArgument("debug");
// configure console
console.addTab("first tab", '1');
console.addString("PIP console", 1, PIConsole::Bold);
console.addVariable("int var (i)", &i, 1);
console.addVariable("int green var (j)", &j, 1, PIConsole::Green);
console.addString("'-' - i--", 2);
console.addString("'+' - i++", 2);
console.addString("'(' - j--", 2);
console.addString("')' - j++", 2);
console.addTab("second tab", '2');
console.addString("col 1", 1);
console.addString("col 2", 2);
console.addString("col 3", 3);
console.setTab("first tab");
// start output to console if "console" argument exists
if (cli.hasArgument("console"))
console.start();
// start main class, e.g. 40 Hz
main_class.start(25.);
// wait for 'Q' press, independently if console is started or not
console.waitForFinish();
return 0;
};
\endcode
* This code demonstrates simple interactive configurable program, which can be started with console
* display or not, and with debug or not. \b MainClass is central class that also can be inherited from
* \a PIThread and reimplement \a run() function.
* \n Many PIP classes has events and event handlers, which can be connected one to another.
* Details you can see at \a PIObject reference page (\ref PIObject_sec0).
* \n To configure your program from file use \a PIConfig.
* \n If you want more information see \ref using_advanced */
/*! \page using_advanced Advanced using
* Sorry, creativity crysis xD
*/
void piqsort(void * base, size_t num, size_t size, int (*compar)(const void *, const void *)) {
qsort(base, num, size, compar);
}
void randomize() {
srand(PISystemTime::current(true).nanoseconds);
}
int randomi() {
return rand();
}

60
src_main/core/piincludes.h Executable file
View File

@@ -0,0 +1,60 @@
/*
PIP - Platform Independent Primitives
Minimal PIP includes
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINCLUDES_H
#define PIINCLUDES_H
#include "pibase.h"
#include "piflags.h"
#include "pimonitor.h"
#ifdef PIP_STD_IOSTREAM
# include <iostream>
#else
# include <iosfwd>
#endif
extern PIMonitor piMonitor;
class PIObject;
class PIMutex;
class PIString;
class PIByteArray;
class PIInit;
class PIChar;
class PICout;
struct lconv;
extern lconv * currentLocale;
/*! \fn errorString()
* \brief Return readable error description in format "code <number> - <description>" */
PIString errorString();
void errorClear();
void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
void randomize();
int randomi();
/// Return readable version of PIP
PIString PIPVersion();
#endif // PIINCLUDES_H

View File

@@ -0,0 +1,43 @@
/*
PIP - Platform Independent Primitives
Initialization
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINCLUDES_P_H
#define PIINCLUDES_P_H
#include "pibase.h"
#ifdef WINDOWS
# include <stdarg.h>
# include <windef.h>
# include <winbase.h>
typedef void(*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#endif
#ifdef CC_GCC
# include <unistd.h>
#endif
#include <string.h>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <cstdlib>
#include <stdio.h>
#include <cstdio>
#include <iostream>
#endif // PIINCLUDES_P_H

371
src_main/core/piinit.cpp Normal file
View File

@@ -0,0 +1,371 @@
/*
PIP - Platform Independent Primitives
Initialization
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "piinit.h"
#include "pitime.h"
#include "pisignals.h"
#include "piobject.h"
#include "pisysteminfo.h"
#include "pidir.h"
#include "piprocess.h"
#ifdef WINDOWS
# include <winsock2.h>
extern FILETIME __pi_ftjan1970;
extern PINtSetTimerResolution setTimerResolutionAddr;
#else
# include <pwd.h>
# include <sys/utsname.h>
# include <pthread.h>
# ifdef BLACKBERRY
# include <signal.h>
# else
# include <csignal>
# endif
#endif
#ifdef MAC_OS
# include <mach/mach_traps.h>
# include <mach/mach.h>
# include <mach/clock.h>
//# include <crt_externs.h>
extern clock_serv_t __pi_mac_clock;
#endif
#ifdef PIP_ICU
# include <unicode/uclean.h>
# include <unicode/ucnv.h>
#endif
/*
#ifdef WINDOWS
# include <conio.h>
# include <io.h>
# include <windows.h>
# include <wincon.h>
#else
# include <fcntl.h>
# include <sys/ioctl.h>
# include <pthread.h>
#endif*/
#ifdef HAS_LOCALE
static locale_t currentLocale_t = 0;
#endif
PRIVATE_DEFINITION_START(PIInit)
#ifdef WINDOWS
HMODULE ntlib;
ULONG prev_res;
#endif
PRIVATE_DEFINITION_END(PIInit)
void __sighandler__(PISignals::Signal s) {
//piCout << Hex << int(s);
if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput)
piMSleep(10);
if (s == PISignals::UserDefined1)
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID()));
}
#ifdef ANDROID
void android_thread_exit_handler(int sig) {
pthread_exit(0);
}
#endif
PIInit::PIInit() {
file_charset = 0;
PISystemInfo * sinfo = PISystemInfo::instance();
sinfo->execDateTime = PIDateTime::current();
setFileCharset("UTF-8");
#ifndef ANDROID
PISignals::setSlot(__sighandler__);
PISignals::grabSignals(PISignals::UserDefined1);
# ifndef WINDOWS
PISignals::grabSignals(PISignals::StopTTYInput | PISignals::StopTTYOutput);
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGALRM);
sigprocmask(SIG_BLOCK, &ss, 0);
pthread_sigmask(SIG_BLOCK, &ss, 0);
signal(SIGPIPE, SIG_IGN);
PIStringList ifpathes;
ifpathes << PIStringAscii("/bin/ifconfig") << PIStringAscii("/sbin/ifconfig")
<< PIStringAscii("/usr/bin/ifconfig") << PIStringAscii("/usr/sbin/ifconfig");
piForeachC (PIString & i, ifpathes)
if (fileExists(i)) {
sinfo->ifconfigPath = i;
piBreak;
}
# else
// OS version
DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
sinfo->OS_version = PIString::fromNumber(dwMajorVersion) + "." + PIString::fromNumber(dwMinorVersion);
// WinSock inint
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Timers init
SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 0, 0, 0};
SystemTimeToFileTime(&jan1970, &__pi_ftjan1970);
LARGE_INTEGER pf;
pf.QuadPart = -1;
if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart;
if (__pi_perf_freq == 0) __pi_perf_freq = -1;
// Sleep precision init
PRIVATE->ntlib = LoadLibrary("ntdll.dll");
if (PRIVATE->ntlib) setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
/*if (setTimerResolution) setTimerResolutionAddr(1, TRUE, &(PRIVATE->prev_res));*/
# endif
//piDebug = true;
# ifdef HAS_LOCALE
//cout << "has locale" << endl;
if (currentLocale_t != 0) {
freelocale(currentLocale_t);
currentLocale_t = 0;
}
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0);
# else
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
# endif
#else
struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = android_thread_exit_handler;
sigaction(SIGTERM, &actions, 0);
#endif
#ifdef PIP_ICU
__syslocname__ = __sysoemname__ = 0;
//__syslocname__ = new char[256];
//memset(__syslocname__, 0, 256);
UErrorCode e((UErrorCode)0);
u_init(&e);
# ifdef WINDOWS
CPINFOEX cpinfo;
int l = 0;
/*GetCPInfoEx(CP_ACP, 0, &cpinfo);
for (l = 0; l < MAX_PATH; ++l)
if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ')
break;
memcpy(__syslocname__, "windows-", 8);
memcpy(&(__syslocname__[8]), cpinfo.CodePageName, l);*/
GetCPInfoEx(CP_OEMCP, 0, &cpinfo);
for (l = 0; l < MAX_PATH; ++l)
if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ')
break;
__sysoemname__ = new char[256];
memset(__sysoemname__, 0, 256);
memcpy(__sysoemname__, "ibm-", 4);
memcpy(&(__sysoemname__[4]), cpinfo.CodePageName, l);
//piCout << cpinfo.CodePageName;
# else
/*PIString en(getenv("LANG"));
if (!en.isEmpty())
en = en.mid(en.find(".") + 1);
PIByteArray enba = en.toByteArray();
memcpy(__syslocname__, enba.data(), enba.size_s());*/
# endif
//piCout << __syslocname__;
//piCout << __sysoemname__;
#endif
#ifdef MAC_OS
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
#endif
char cbuff[1024];
memset(cbuff, 0, 1024);
if (gethostname(cbuff, 1023) == 0)
sinfo->hostname = cbuff;
#ifdef WINDOWS
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
sinfo->processorsCount = sysinfo.dwNumberOfProcessors;
switch (sysinfo.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64: sinfo->architecture = PIStringAscii("x64"); break;
case PROCESSOR_ARCHITECTURE_ARM: sinfo->architecture = PIStringAscii("ARM"); break;
case PROCESSOR_ARCHITECTURE_IA64: sinfo->architecture = PIStringAscii("Intel Itanium-based"); break;
case PROCESSOR_ARCHITECTURE_INTEL: sinfo->architecture = PIStringAscii("x86"); break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default: sinfo->architecture = PIStringAscii("unknown"); break;
}
int argc_(0);
wchar_t ** argv_ = CommandLineToArgvW(GetCommandLineW(), &argc_);
if (argc_ > 0 && argv_ != 0)
sinfo->execCommand = argv_[0];
LocalFree(argv_);
memset(cbuff, 0, 1024);
ulong unlen = 1023;
if (GetUserName(cbuff, &unlen) != 0)
sinfo->user = cbuff;
#else
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
passwd * ps = getpwuid(getuid());
if (ps)
sinfo->user = ps->pw_name;
else {
memset(cbuff, 0, 1024);
char * l = getlogin();
if (l)
sinfo->user = l;
}
struct utsname uns;
if (uname(&uns) == 0) {
sinfo->OS_version = uns.release;
sinfo->architecture = uns.machine;
}
#endif
sinfo->OS_name =
#ifdef WINDOWS
PIStringAscii("Windows");
#else
# ifdef QNX
PIStringAscii("QNX");
# else
# ifdef MAC_OS
PIStringAscii("MacOS");
# else
# ifdef ANDROID
PIStringAscii("Android");
# else
# ifdef FREE_BSD
PIStringAscii("FreeBSD");
# else
uns.sysname;
# endif
# endif
# endif
# endif
#endif
}
PIInit::~PIInit() {
if (file_charset) delete file_charset;
file_charset = 0;
#ifdef WINDOWS
WSACleanup();
//if (setTimerResolution) setTimerResolutionAddr(PRIVATE->prev_res, TRUE, &(PRIVATE->prev_res));
if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib);
PRIVATE->ntlib = 0;
#endif
#ifdef MAC_OS
mach_port_deallocate(mach_task_self(), __pi_mac_clock);
#endif
#ifdef PIP_ICU
if (__syslocname__) delete __syslocname__;
if (__sysoemname__) delete __sysoemname__;
u_cleanup();
#endif
//if (currentLocale_t != 0) freelocale(currentLocale_t);
}
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
switch (o) {
case ICU: return
#ifdef PIP_ICU
true;
#else
false;
#endif
case USB: return
#ifdef PIP_USB
true;
#else
false;
#endif
case STL: return
#ifdef PIP_CONTAINERS_STL
true;
#else
false;
#endif
case Crypt: return
#ifdef PIP_CRYPT
true;
#else
false;
#endif
case IntrospectionContainers: return
#ifdef PIP_INTROSPECTION_CONTAINERS
true;
#else
false;
#endif
case IntrospectionThreads: return
#ifdef PIP_INTROSPECTION_THREADS
true;
#else
false;
#endif
default: return false;
}
return false;
}
void PIInit::setFileCharset(const char *charset) {
if (file_charset) delete file_charset;
file_charset = 0;
if (charset) {
file_charset = new char[1024];
memset(file_charset, 0, 1024);
strcpy(file_charset, charset);
}
}
bool PIInit::fileExists(const PIString & p) {
FILE * f = fopen(p.data(), "r");
if (f == 0)
return false;
fclose(f);
return true;
}
int __PIInit_Initializer__::count_(0);
PIInit * __PIInit_Initializer__::__instance__(0);
__PIInit_Initializer__::__PIInit_Initializer__() {
count_++;
if (count_ > 1) return;
//piCout << "create PIInit";
__instance__ = new PIInit();
}
__PIInit_Initializer__::~__PIInit_Initializer__() {
count_--;
if (count_ > 0) return;
//piCout << "delete PIInit";
if (__instance__ != 0) {
delete __instance__;
__instance__ = 0;
}
}

70
src_main/core/piinit.h Normal file
View File

@@ -0,0 +1,70 @@
/*! \file piinit.h
* \brief Initialization
*
*
*/
/*
PIP - Platform Independent Primitives
Initialization
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIINIT_H
#define PIINIT_H
#include "piincludes.h"
class PIFile;
class __PIInit_Initializer__ {
public:
__PIInit_Initializer__();
~__PIInit_Initializer__();
static int count_;
static PIInit * __instance__;
};
class PIInit {
friend class PIFile;
public:
PIInit();
~PIInit();
//! \brief Build options which PIP library was built
enum BuildOption {
ICU /*! Unicode support */ = 0x01,
USB /*! USB support */ = 0x02,
STL /*! STL containers implementation */ = 0x04,
Crypt /*! Crypt support */ = 0x08,
IntrospectionContainers /*! Containers introspection */ = 0x010,
IntrospectionThreads /*! Threads introspection */ = 0x20
};
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
static bool isBuildOptionEnabled(BuildOption o);
private:
void setFileCharset(const char *charset);
bool fileExists(const PIString & p);
PRIVATE_DECLARATION
char * file_charset;
};
static __PIInit_Initializer__ __piinit_initializer__;
#endif // PIINIT_H

480
src_main/core/piobject.cpp Executable file
View File

@@ -0,0 +1,480 @@
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piobject.h"
#include "pifile.h"
#include "pisysteminfo.h"
/** \class PIObject
* \brief This is base class for any classes which use events -> handlers mechanism.
* \details
* \section PIObject_sec0 Events and Event handlers
* %PIObject provide notification mechanism similar Qt but implemented
* on language capabilities without any special preprocessors or compilers.
* Any class inherits PIObject should use macro \a PIOBJECT() immediate
* after declaration to proper compile.
*
* Event is a some abstract event that can be raised at any time.
* Event is a function but declared with special macro \a EVENT().
* To raise event simply execute event function.
*
* Event handler is a function but declared with special macro
* \a EVENT_HANDLER(). You can use event handlers as ordinary functions.
*
* Main goal of this mechanism is perform abstract connections between
* various objects. This functionality provide macro \a CONNECT() which
* connect some event of first object to some event handler or event of
* second object. Each event can be connected any times to any event handlers.
*
* \image html events_handlers.png
*
* Example: \snippet piobject.cpp main
* Result:
\code{.cpp}
handler B: 2 , 0.5
handler A: event to handler
handler A: event to event
\endcode
*/
PIVector<PIObject * > PIObject::objects;
PIMap<PIString, PIObject::__EHData> PIObject::__eh_data;
PIString PIObject::__EHFunc::arguments() const {
return types.join(",");
}
PIString PIObject::__EHFunc::fullFormat() const {
PIString ret = type_ret + " " + scope + "::" + func_name +"(";
for (int i = 0; i < types.size_s(); ++i) {
if (i > 0) ret += ", ";
ret += types[i] + " " + names[i];
}
ret += ")";
return ret;
}
PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false) {
piMonitor.objects++;
//__PIVariantInitBuiltin__();
setName(name);
setDebug(true);
objects << this;
//piCout << "new" << this;
}
PIObject::~PIObject() {
//piCout << "delete" << this;
piMonitor.objects--;
objects.removeAll(this);
piDisconnect(this);
}
void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) {
PIObject * o = findByName(src);
if (o == 0) {
piCout << "[PIObject] Can`t find object with name \"" << src << "\"!";
return;
}
PIMutexLocker _ml(o->mutex_connect);
PIMutexLocker _mld(((PIObject*)dest)->mutex_connect, ((PIObject*)dest) != o);
o->connections << Connection(ev_h, 0, sig, (PIObject*)dest, dest);
((PIObject*)dest)->connectors << o;
}
void PIObject::piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h) {
PIObject * o = findByName(dest);
if (o == 0) {
piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!";
return;
}
PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(o->mutex_connect, src != o);
src->connections << Connection(ev_h, 0, sig, o, o);
((PIObject*)o)->connectors << src;
}
void PIObject::piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h) {
PIObject * s = findByName(src);
if (s == 0) {
piCout << "[PIObject] Can`t find object with name \"" << src << "\"!";
return;
}
PIObject * d = findByName(dest);
if (d == 0) {
piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!";
return;
}
PIMutexLocker _ml(s->mutex_connect);
PIMutexLocker _mld(d->mutex_connect, s != d);
s->connections << Connection(ev_h, 0, sig, d, d);
d->connectors << s;
}
/*
PIStringList PIObject::events() {
PIStringList l;
for (PIMap<NamedFunction, PIString>::const_iterator i = signals_.begin(); i != signals_.end(); i++)
l << (*i).first;
return l;
}
*/
PIStringList PIObject::methodsEH() {
PIMutexLocker ml(__eh_mutex());
PIStringList ret;
__EHData & ehd(__eh_data[className()]);
piForeachC (__EHPair & eh, ehd.eh_func)
ret << eh.second.fullFormat();
return ret;
}
bool PIObject::isMethodEHContains(const PIString & name) const {
PIMutexLocker ml(__eh_mutex());
__EHData & ehd(__eh_data[className()]);
piForeachC (__EHPair & eh, ehd.eh_func)
if (eh.second.func_name == name)
return true;
return false;
}
PIString PIObject::methodEHArguments(const PIString & name) const {
PIMutexLocker ml(__eh_mutex());
__EHData & ehd(__eh_data[className()]);
piForeachC (__EHPair & eh, ehd.eh_func)
if (eh.second.func_name == name)
return eh.second.arguments();
return PIString();
}
PIString PIObject::methodEHFullFormat(const PIString & name) const {
PIMutexLocker ml(__eh_mutex());
__EHData & ehd(__eh_data[className()]);
piForeachC (__EHPair & eh, ehd.eh_func)
if (eh.second.func_name == name)
return eh.second.fullFormat();
return PIString();
}
PIString PIObject::methodEHFromAddr(const void * addr) const {
return methodEH(addr).func_name;
}
PIVector<PIObject::__EHFunc> PIObject::findEH(const PIString & name) const {
PIVector<__EHFunc> ret;
__EHData & ehd(__eh_data[className()]);
piForeachC (__EHPair & eh, ehd.eh_func)
if (eh.second.func_name == name)
ret << eh.second;
return ret;
}
PIObject::__EHFunc PIObject::methodEH(const void * addr) const {
PIMutexLocker ml(__eh_mutex());
return __eh_data[className()].eh_func.value(addr);
}
void PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc) {
//piCout << "piConnect ...";
//piCout << "piConnect" << src << (void*)(dest) << sig;
//piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className();
PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest_o->mutex_connect, src != dest_o);
src->connections << Connection(ev_h, e_h, sig, dest_o, dest, args);
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "...";
//piCout << "addConnector" << dest_o << src;
dest_o->connectors << src;
//piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s();
//piCout << "piConnect ok";
}
bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname, const char * loc) {
if (src == 0 || dest_o == 0 || dest == 0) return false;
if (!src->isPIObject()) {
piCout << "[piConnectU] \"" << ename << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")";
return false;
}
if (!dest_o->isPIObject()) {
piCout << "[piConnectU] \"" << ename << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")";
return false;
}
PIMutexLocker ml(__eh_mutex());
PIMutexLocker mls(src->mutex_connect);
PIMutexLocker mld(dest_o->mutex_connect, src != dest_o);
PIVector<__EHFunc> m_src = src->findEH(ename), m_dest = dest_o->findEH(hname);
if (m_src.isEmpty()) {
piCout << "[piConnectU] Error: can`t find event \"" << ename << "\" in class \"" << src->className() << "\"! (" << loc << ")";
return false;
}
if (m_dest.isEmpty()) {
piCout << "[piConnectU] Error: can`t find handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
return false;
}
void * addr_src(0), * addr_dest(0);
int args(0);
piForeachC (__EHFunc & fs, m_src) {
if (addr_src != 0) break;
piForeachC (__EHFunc & fd, m_dest) {
if (addr_src != 0) break;
if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) {
addr_src = fs.addr;
addr_dest = fd.addr;
args = fd.names.size_s();
}
}
}
if (addr_src == 0) {
piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << ename << "\" in class \"" << src->className()
<< "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
return false;
}
//piCout << "connect" << ename << "->" << hname << "with" << args << "args";
src->connections << PIObject::Connection(addr_dest, addr_src, ename, dest_o, dest, args);
dest_o->connectors << src;
return true;
}
void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h) {
PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest->mutex_connect, src != dest);
for (int i = 0; i < src->connections.size_s(); ++i) {
Connection & cc(src->connections[i]);
if (cc.event == sig && cc.dest_o == dest && cc.slot == ev_h) {
src->connections.remove(i);
i--;
}
}
dest->updateConnectors();
}
void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * dest) {
PIMutexLocker _ml(src->mutex_connect);
PIMutexLocker _mld(dest->mutex_connect, src != dest);
for (int i = 0; i < src->connections.size_s(); ++i) {
Connection & cc(src->connections[i]);
if (cc.event == sig && cc.dest_o == dest) {
src->connections.remove(i);
i--;
}
}
dest->updateConnectors();
}
void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
PIMutexLocker _ml(src->mutex_connect);
for (int i = 0; i < src->connections.size_s(); ++i) {
Connection & cc(src->connections[i]);
if (cc.event == sig) {
PIObject * dest = cc.dest_o;
src->connections.remove(i);
i--;
#ifndef ANDROID
PIMutexLocker _mld(dest->mutex_connect, src != dest);
#endif
dest->updateConnectors();
}
}
}
void PIObject::piDisconnect(PIObject * src) {
src->deleted();
PIMutexLocker _ml(src->mutex_connect);
PIVector<PIObject * > cv = src->connectors.toVector();
piForeach (PIObject * o, cv) {
if (o == src) continue;
#ifndef ANDROID
PIMutexLocker _mld(o->mutex_connect, src != o);
#endif
PIVector<Connection> & oc(o->connections);
for (int i = 0; i < oc.size_s(); ++i) {
//piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src);
if (oc[i].dest_o == src) {
oc.remove(i);
--i;
}
}
}
piForeachC (PIObject::Connection & c, src->connections)
c.dest_o->connectors.remove(src);
src->connections.clear();
}
void PIObject::updateConnectors() {
//piCout << "*** updateConnectors" << this;
connectors.clear();
piForeach (PIObject * o, objects) {
if (o == this) continue;
PIVector<Connection> & oc(o->connections);
piForeach (Connection & c, oc)
if (c.dest == this)
connectors << o;
}
}
PIMutex & PIObject::__eh_mutex() {
static PIMutex ret;
return ret;
}
PIString PIObject::simplifyType(const char * a) {
PIString ret = PIStringAscii(a).trim();
int white = -1;
for (int i = 0; i < ret.size_s(); ++i) {
bool iw = ret[i] == ' ' || ret[i] == '\t' || ret[i] == '\r' || ret[i] == '\n';
//piCout << i << iw << white;
if (white < 0) {
if (iw) {
white = i;
continue;
}
} else {
if (!iw) {
ret.replace(white, i - white, " ");
i = white;
white = -1;
//piCout << i;
}
}
}
ret.replaceAll(" &", "&");
ret.replaceAll(" *", "*");
if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim();
return ret;
}
bool PIObject::execute(const PIString & method) {
if (method.isEmpty()) return false;
PIVector<__EHFunc> ml = findEH(method);
piForeachC (__EHFunc & m, ml) {
if (!m.names.isEmpty()) continue;
((void(*)(void*))m.addr)(this);
return true;
}
piCoutObj << "Error: can`t find event or handler \"" << (method + "()") << "\" to execute!";
return false;
}
void PIObject::dump(const PIString & line_prefix) const {
//printf("dump %s \"%s\"\n", className(), name().data());
PICout(PICoutManipulators::AddNewLine) << line_prefix << "class " << className() << " (" << (const void*)this << ", \"" << name() << "\") {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " properties {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << properties_.size_s();
//printf("dump %d properties\n", properties_.size());
piForeachC (Property p, properties_)
if (p.first != "name")
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << p.first << ": " << p.second;
//printf("dump %d properties ok\n", properties_.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " methodsEH {";
__EHData & ehd(__eh_data[className()]);
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << ehd.eh_func.size_s();
//printf("dump %d methods\n", ehd.eh_func.size());
piForeachC (__EHPair & eh, ehd.eh_func) {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << eh.second.fullFormat();
}
//printf("dump %d methods ok\n", ehd.eh_func.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " connections {";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << connections.size_s();
//printf("dump %d connections\n",connections.size());
piForeachC (Connection & c, connections) {
PIObject * dst = c.dest_o;
__EHFunc hf = dst->methodEH(c.slot);
__EHFunc ef = methodEH(c.signal);
if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]";
else hf.func_name += "(" + hf.arguments() + ")";
PIString src(c.event);
if (!ef.func_name.isEmpty())
src = ef.func_name + "(" + ef.arguments() + ")";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name;
}
//printf("dump %d connections ok\n",connections.size());
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
PICout(PICoutManipulators::AddNewLine) << line_prefix << "}";
}
void dumpApplication() {
//printf("dump application ...\n");
PIDateTime cd = PIDateTime::current();
PISystemInfo * pi = PISystemInfo::instance();
PICout(PICoutManipulators::AddNewLine) << "application {";
PICout(PICoutManipulators::AddNewLine) << " PIP version: " << PIPVersion();
PICout(PICoutManipulators::AddNewLine) << " processors: " << pi->processorsCount;
PICout(PICoutManipulators::AddNewLine) << " hostname: \"" << pi->hostname << "\"";
PICout(PICoutManipulators::AddNewLine) << " user: \"" << pi->user << "\"";
PICout(PICoutManipulators::AddNewLine) << " exec command: \"" << pi->execCommand << "\"";
PICout(PICoutManipulators::AddNewLine) << " started: " << pi->execDateTime.toString();
PICout(PICoutManipulators::AddNewLine) << " uptime, s: " << (cd.toSystemTime() - pi->execDateTime.toSystemTime()).toSeconds();
PICout(PICoutManipulators::AddNewLine) << " PIObjects {";
PICout(PICoutManipulators::AddNewLine) << " count: " << PIObject::objects.size_s();
piForeachC (PIObject * o, PIObject::objects)
o->dump(" ");
PICout(PICoutManipulators::AddNewLine) << " }";
PICout(PICoutManipulators::AddNewLine) << "}";
//printf("dump application done\n");
}
bool dumpApplicationToFile(const PIString & path) {
PIFile f(path + "_tmp");
f.setName("__S__DumpFile");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) return false;
bool ba = PICout::isBufferActive();
PICout::setBufferActive(true, true);
dumpApplication();
f << PICout::buffer();
f.close();
PICout::setBufferActive(ba, true);
PIFile::rename(path + "_tmp", path);
return true;
}

761
src_main/core/piobject.h Executable file
View File

@@ -0,0 +1,761 @@
/*! \file piobject.h
* \brief Base object
*
* This file declare PIObject class and associated macros
*/
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIOBJECT_H
#define PIOBJECT_H
#include "piinit.h"
#include "pivariant.h"
#include "pimutex.h"
#include "piset.h"
#ifdef DOXYGEN
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
#define PIOBJECT(name)
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class
#define PIOBJECT_SUBCLASS(name, parent)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name()
#define EVENT_HANDLER0(ret, name) ret name()
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0)
#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1)
#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3)
/// \relatesalso PIObject \brief EVENT_HANDLER is synonym of EVENT_HANDLER0
#define EVENT_HANDLER EVENT_HANDLER0
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name()
#define EVENT_VHANDLER0(ret, name) virtual ret name()
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0)
#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1)
#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
/// \relatesalso PIObject \brief EVENT_VHANDLER is synonym of EVENT_VHANDLER0
#define EVENT_VHANDLER EVENT_VHANDLER0
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name();
#define EVENT0(name) void name();
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0);
#define EVENT1(name, type0, var0) void name(type0 var0);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1);
#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2);
#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
/// \relatesalso PIObject \brief EVENT is synonym of EVENT0
#define EVENT EVENT0
#define RAISE_EVENT0(src, event)
#define RAISE_EVENT1(src, event, v0)
#define RAISE_EVENT2(src, event, v0, v1)
#define RAISE_EVENT3(src, event, v0, v1, v2)
#define RAISE_EVENT4(src, event, v0, v1, v2, v3)
#define RAISE_EVENT RAISE_EVENT0
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\". \"Event\" and \"handler\" must has equal argument lists.
#define CONNECTU(src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief CONNECT is synonym of CONNECT0
#define CONNECT CONNECT0
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief WEAK_CONNECT is synonym of WEAK_CONNECT0
#define WEAK_CONNECT WEAK_CONNECT0
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief DISCONNECT is synonym of DISCONNECT0
#define DISCONNECT DISCONNECT0
/// \relatesalso PIObject \brief Returns pointer to events handler \"handler\"
#define HANDLER(handler)
#define PIOBJECT(name)
#define PIOBJECT_SUBCLASS(name)
#else
#define _PI_STR(x) #x
#define _PI_SSTR(x) _PI_STR(x)
#define LOCATION __FILE__ ":" _PI_SSTR(__LINE__)
#define PIOBJECT(name) \
protected: \
typedef name __PIObject__; \
static const PIString __classNameS() {return PIStringAscii(#name);} \
public: \
virtual const char * className() const {return #name;} \
private:
#define PIOBJECT_PARENT(name) \
class __##name##_ParentInitializer__ { \
public: \
__##name##_ParentInitializer__() { \
PIString pn(name::__classNameS()); \
if (pn.isEmpty()) return; \
PIMutexLocker ml(__eh_mutex()); \
if (__eh_data.contains(__classNameS())) return; \
__eh_data[pn]; \
__eh_data[__classNameS()]; \
__EHData & ehp(__eh_data[pn]); \
__EHData & eh(__eh_data[__classNameS()]); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
} \
}; \
__##name##_ParentInitializer__ __##name##_parent_init__; \
public: \
virtual const char * superClassName() const {return #name;} \
private:
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
#define EH_INIT0(ret, name) \
class __##name##0_Initializer__ { \
public: \
__##name##0_Initializer__() { \
PIMutexLocker ml(__eh_mutex()); \
__EHData & eh(__eh_data[__classNameS()]); \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__EHFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.type_ret = PIStringAscii(#ret); \
} \
}; \
__##name##0_Initializer__ __##name##0_init__; \
#define EH_INIT1(ret, name, a0, n0) \
class __##name##1##n0##_Initializer__ { \
public: \
__##name##1##n0##_Initializer__() { \
PIMutexLocker ml(__eh_mutex()); \
__EHData & eh(__eh_data[__classNameS()]); \
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__EHFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0); \
f.names << PIStringAscii(#n0); \
} \
}; \
__##name##1##n0##_Initializer__ __##name##1##n0##_init__; \
#define EH_INIT2(ret, name, a0, n0, a1, n1) \
class __##name##2##n0##n1##_Initializer__ { \
public: \
__##name##2##n0##n1##_Initializer__() { \
PIMutexLocker ml(__eh_mutex()); \
__EHData & eh(__eh_data[__classNameS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__EHFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1); \
} \
}; \
__##name##2##n0##n1##_Initializer__ __##name##2##n0##n1##_init__; \
#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
class __##name##3##n0##n1##n2##_Initializer__ { \
public: \
__##name##3##n0##n1##n2##_Initializer__() { \
PIMutexLocker ml(__eh_mutex()); \
__EHData & eh(__eh_data[__classNameS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__EHFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2); \
} \
}; \
__##name##3##n0##n1##n2##_Initializer__ __##name##3##n0##n1##n2##_init__; \
#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
class __##name##4##n0##n1##n2##n3##_Initializer__ { \
public: \
__##name##4##n0##n1##n2##n3##_Initializer__() { \
PIMutexLocker ml(__eh_mutex()); \
__EHData & eh(__eh_data[__classNameS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__EHFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2) << PIObject::simplifyType(#a3); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2) << PIStringAscii(#n3); \
} \
}; \
__##name##4##n0##n1##n2##n3##_Initializer__ __##name##4##n0##n1##n2##n3##_init__; \
#define EVENT_HANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \
ret name()
#define EVENT_HANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
ret name(a0 n0)
#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
ret name(a0 n0, a1 n1)
#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_HANDLER EVENT_HANDLER0
#define EVENT_VHANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \
virtual ret name()
#define EVENT_VHANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
virtual ret name(a0 n0)
#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
virtual ret name(a0 n0, a1 n1)
#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
virtual ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_VHANDLER EVENT_VHANDLER0
#define EVENT0(name) EVENT_HANDLER0(void, name) {PIObject::raiseEvent(this, PIStringAscii(#name));}
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {PIObject::raiseEvent(this, PIStringAscii(#name), n0);}
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, PIStringAscii(#name), n0, n1);}
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, PIStringAscii(#name), n0, n1, n2);}
#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, PIStringAscii(#name), n0, n1, n2, n3);}
#define EVENT EVENT0
#define RAISE_EVENT0(src, event) (src)->event();
#define RAISE_EVENT1(src, event, v0) (src)->event(v0);
#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2);
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
#define RAISE_EVENT RAISE_EVENT0
#define CONNECTU(src, event, dest, handler) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);
#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION);
#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION);
#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION);
#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION);
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION);
#define CONNECT CONNECT0
#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION);
#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION);
#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION);
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION);
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION);
#define WEAK_CONNECT WEAK_CONNECT0
#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT DISCONNECT0
#define HANDLER(handler) __stat_eh_##handler##__
#define __PIOBJECT_SIGNATURE__ 0xabcdbadc
#endif
typedef void (*Handler)(void * );
class PIP_EXPORT PIObject
{
friend class PIObjectManager;
friend void dumpApplication();
typedef PIObject __PIObject__;
public:
//! Contructs PIObject with name "name"
explicit PIObject(const PIString & name = PIString());
virtual ~PIObject();
private:
explicit PIObject(const PIObject & );
void operator =(const PIObject & );
uint _signature_;
public:
//! Returns object name
PIString name() const {return property(PIStringAscii("name")).toString();}
//! Returns object class name
virtual const char * className() const {return "PIObject";}
//! Returns object superclass name
virtual const char * superClassName() const {return "";}
//! Return if debug of this object is active
bool debug() const {return property(PIStringAscii("debug")).toBool();}
//! Set object name
void setName(const PIString & name) {setProperty(PIStringAscii("name"), name);}
void setName(const char * name) {setName(PIStringAscii(name));}
//! Set object debug active
void setDebug(bool debug) {setProperty(PIStringAscii("debug"), debug);}
//! Returns properties of the object
const PIMap<PIString, PIVariant> & properties() const {return properties_;}
//! Returns properties count of the object
int propertiesCount() const {return properties_.size_s();}
//! Returns property with name "name"
PIVariant property(const PIString & name) const {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);}
PIVariant property(const char * name) const {return property(PIStringAscii(name));}
//! Set property with name "name" to "value". If there is no such property in object it will be added
void setProperty(const PIString & name, const PIVariant & value) {properties_[name] = value; propertyChanged(name);}
void setProperty(const char * name, const PIVariant & value) {setProperty(PIStringAscii(name), value);}
//! Returns if property with name "name" exists
bool isPropertyExists(const PIString & name) const {return properties_.contains(name);}
bool isPropertyExists(const char * name) const {return isPropertyExists(PIStringAscii(name));}
void setThreadSafe(bool yes) {thread_safe_ = yes;}
bool isThreadSafe() const {return thread_safe_;}
void dump(const PIString & line_prefix = PIString()) const;
PIStringList methodsEH();
bool isMethodEHContains(const PIString & name) const;
PIString methodEHArguments(const PIString & name) const;
PIString methodEHFullFormat(const PIString & name) const;
PIString methodEHFromAddr(const void * addr) const;
/*
template <typename RS, typename RD>
static void piConnectU(PIObject * src, RS(*sig)(void*), PIObject * dest, RD(*slt)(void*), PIString signame) {
src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest);
}
template <typename RS, typename RD, typename A0>
static void piConnectU(PIObject * src, RS(*sig)(void*,A0), PIObject * dest, RD(*slt)(void*,A0), PIString signame) {
src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest);
}
template <typename RS, typename RD, typename A0, typename A1>
static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1), PIObject * dest, RD(*slt)(void*,A0,A1), PIString signame) {
src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest);
}
template <typename RS, typename RD, typename A0, typename A1, typename A2>
static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1,A2), PIObject * dest, RD(*slt)(void*,A0,A1,A2), PIString signame) {
src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest);
}
template <typename RS, typename RD, typename A0, typename A1, typename A2, typename A3>
static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1,A2,A3), PIObject * dest, RD(*slt)(void*,A0,A1,A2,A3), PIString signame) {
src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest);
}
template <typename RS, typename RD, typename A0, typename A1, typename A2, typename A3, typename A4>
static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1,A2,A3,A4), PIObject * dest, RD(*slt)(void*,A0,A1,A2,A3,A4), PIString signame) {
src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest);
}
*/
// / Direct connect
static void piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
static bool piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname, const char * loc);
// / Through names and mixed
static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h);
static void piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h);
static void piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h);
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h);
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest);
//! Disconnect object "src" from all connections with event name "sig"
static void piDisconnect(PIObject * src, const PIString & sig);
//! Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter
static void piDisconnect(PIObject * src);
// / Raise events
static void raiseEvent(PIObject * sender, const PIString & event) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
//piCout << uint(i.dest) << uint(i.dest_o);
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
((void( *)(void * ))i.slot)(i.dest);
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
template <typename T0>
static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
if (i.args_count == 0) ((void(*)(void *))i.slot)(i.dest);
else ((void(*)(void * , T0))i.slot)(i.dest, v0);
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
template <typename T0, typename T1>
static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
default: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
template <typename T0, typename T1, typename T2>
static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
default: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
template <typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
case 3: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
default: ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); break;
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
/*
// / Raise events through manager
static void raiseEvent(const PIString & destObject, const PIString & name) {
PIObject * dest = findByName(destObject);
if (dest == 0) {
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
return;
}
raiseEvent(dest, name);
}
template <typename T0>
static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) {
PIObject * dest = findByName(destObject);
if (dest == 0) {
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
return;
}
raiseEvent<T0>(dest, name, v0);
}
template <typename T0, typename T1>
static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) {
PIObject * dest = findByName(destObject);
if (dest == 0) {
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
return;
}
raiseEvent<T0, T1>(dest, name, v0, v1);
}
template <typename T0, typename T1, typename T2>
static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
PIObject * dest = findByName(destObject);
if (dest == 0) {
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
return;
}
raiseEvent<T0, T1, T2>(name, dest, v0, v1, v2);
}
template <typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) {
PIObject * dest = findByName(destObject);
if (dest == 0) {
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
return;
}
raiseEvent<T0, T1, T2, T3>(name,dest , v0, v1, v2, v3);
}
*/
//! Returns PIObject* with name "name" or 0, if there is no object found
static PIObject * findByName(const PIString & name) {
piForeach (PIObject * i, PIObject::objects) {
if (i->name() != name) continue;
return i;
}
return 0;
}
bool isPIObject() const {return isPIObject(this);}
bool execute(const PIString & method);
static bool isPIObject(const PIObject * o) {return o->_signature_ == __PIOBJECT_SIGNATURE__;}
static bool isPIObject(const void * o) {return isPIObject((PIObject*)o);}
static bool execute(PIObject * o, const PIString & method) {return o->execute(method);}
static bool execute(void * o, const PIString & method) {return ((PIObject*)o)->execute(method);}
static PIString simplifyType(const char * a);
static PIMutex & __eh_mutex();
struct __EHFunc {
__EHFunc(): addr(0) {;}
bool isNull() const {return addr == 0;}
PIString arguments() const;
PIString fullFormat() const;
void * addr;
PIString func_name;
PIString type_ret;
PIString scope;
PIStringList types;
PIStringList names;
};
struct __EHData {
PISet<const void * > eh_set;
PIMap<const void * , __EHFunc> eh_func;
};
typedef PIPair<const void * , __EHFunc> __EHPair;
static PIMap<PIString, __EHData> __eh_data;
protected:
//! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler
PIObject * emitter() const {return emitter_;}
//! Virtual function executes after property with name "name" has been changed
virtual void propertyChanged(const PIString & name) {}
static const PIString __classNameS() {return PIStringAscii("PIObject");}
EVENT(deleted)
//! \events
//! \{
/** \fn void deleted()
* \brief Raise before object delete
* \note This event raised from destructor, so use only emitter() value,
* don`t try to cast deleted object to some subclass! */
//! \}
private:
struct Connection {
Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), PIObject * d_o = 0, void * d = 0, int ac = 0) {
slot = sl;
signal = si;
event = e;
dest_o = d_o;
dest = d;
args_count = ac;
}
void * slot;
void * signal;
PIString event;
PIObject * dest_o;
void * dest;
int args_count;
};
PIVector<__EHFunc> findEH(const PIString & name) const;
__EHFunc methodEH(const void * addr) const;
void updateConnectors();
PIVector<Connection> connections;
typedef PIPair<PIString, PIVariant> Property;
PIMap<PIString, PIVariant> properties_;
static PIVector<PIObject * > objects;
PISet<PIObject * > connectors;
PIMutex mutex_, mutex_connect;
PIObject * emitter_;
bool thread_safe_;
};
void dumpApplication();
bool dumpApplicationToFile(const PIString & path);
#endif // PIOBJECT_H

View File

@@ -0,0 +1,114 @@
#include "pipropertystorage.h"
bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == _name)
return true;
return false;
}
void PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == p.name) {
props[i] = p;
return;
}
props << p;
}
void PIPropertyStorage::removeProperty(const PIString & _name) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == _name) {
props.remove(i);
return;
}
}
void PIPropertyStorage::removePropertiesByFlag(int flag) {
for (int i = 0; i < props.size_s(); ++i)
if ((props[i].flags & flag) == flag) {
props.remove(i);
--i;
}
}
void PIPropertyStorage::updateProperties(const PIVector<PIPropertyStorage::Property> & properties_, int flag_ignore) {
PIMap<PIString, PIVariant> values;
piForeachC(Property & p, props)
if (((p.flags & flag_ignore) != flag_ignore) || (flag_ignore == 0))
values[p.name] = p.value;
props = properties_;
for (uint i = 0; i < props.size(); ++i) {
Property & p(props[i]);
if (values.contains(p.name)) {
PIVariant pv = values[p.name];
if (pv.type() == p.value.type())
p.value = pv;
}
}
}
PIPropertyStorage::Property PIPropertyStorage::propertyByName(const PIString & name) const {
piForeachC(Property & p, props)
if (p.name == name)
return p;
return Property();
}
PIVariant PIPropertyStorage::propertyValueByName(const PIString & name) const {
piForeachC(Property & p, props)
if (p.name == name)
return p.value;
return PIVariant();
}
void PIPropertyStorage::setPropertyValue(const PIString & name, const PIVariant & value) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == name) {
props[i].value = value;
return;
}
}
void PIPropertyStorage::setPropertyComment(const PIString & name, const PIString & comment) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == name) {
props[i].comment = comment;
return;
}
}
void PIPropertyStorage::setPropertyFlags(const PIString & name, int flags) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == name) {
props[i].flags = flags;
return;
}
}
PIPropertyStorage::Property & PIPropertyStorage::operator[](const PIString & name) {
piForeach (Property & p, props)
if (p.name == name)
return p;
addProperty(name, "");
return props.back();
}
const PIPropertyStorage::Property PIPropertyStorage::operator[](const PIString & name) const {
piForeachC (Property & p, props)
if (p.name == name)
return p;
return Property();
}

View File

@@ -0,0 +1,80 @@
#ifndef PIPROPERTYSTORAGE_H
#define PIPROPERTYSTORAGE_H
#include "pivariant.h"
class PIPropertyStorage {
public:
PIPropertyStorage() {}
struct Property {
Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0):
name(n), comment(c), value(v), flags(f) {}
PIString name;
PIString comment;
PIVariant value;
int flags;
};
PIPropertyStorage(const PIVector<Property> & pl) {props = pl;}
typedef PIVector<Property>::const_iterator const_iterator;
typedef PIVector<Property>::iterator iterator;
typedef Property value_type;
iterator begin() {return props.begin();}
const_iterator begin() const {return props.begin();}
iterator end() {return props.end();}
const_iterator end() const {return props.end();}
int length() const {return props.length();}
int size() const {return props.size();}
bool isEmpty() const {return props.isEmpty();}
Property & front() {return props.front();}
const Property & front() const {return props.front();}
Property & back() {return props.back();}
const Property & back() const {return props.back();}
void removeAt(int i) {props.remove(i);}
void clear() {props.clear();}
PIPropertyStorage copy() const {return PIPropertyStorage(*this);}
int propertiesCount() const {return props.size();}
PIVector<Property> & properties() {return props;}
const PIVector<Property> & properties() const {return props;}
const PIPropertyStorage & propertyStorage() const {return *this;}
bool isPropertyExists(const PIString & _name) const;
void clearProperties() {props.clear();}
void addProperty(const Property & p);
void addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0) {addProperty(Property(_name, _comment, _def_value, _flags));}
void removeProperty(const PIString & _name);
void removePropertiesByFlag(int flag);
void updateProperties(const PIVector<Property> & properties_, int flag_ignore = 0);
Property propertyByName(const PIString & name) const;
PIVariant propertyValueByName(const PIString & name) const;
void setPropertyValue(const PIString & name, const PIVariant & value);
void setPropertyComment(const PIString & name, const PIString & comment);
void setPropertyFlags(const PIString & name, int flags);
PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;}
PIPropertyStorage & operator <<(const PIVector<Property> & p) {props << p; return *this;}
PIPropertyStorage & operator <<(const PIPropertyStorage & p) {props << p.props; return *this;}
Property & operator[](int i) {return props[i];}
const Property & operator[](int i) const {return props[i];}
Property & operator[](const PIString & name);
const Property operator[](const PIString & name) const;
static Property parsePropertyLine(PIString l);
protected:
PIVector<Property> props;
};
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage::Property & v) {s << v.name << v.value << v.comment << v.flags; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage::Property & v) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIPropertyStorage & v) {s << v.properties(); return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIPropertyStorage & v) {s >> v.properties(); return s;}
#endif // PIPROPERTYSTORAGE_H

334
src_main/core/pistatemachine.h Executable file
View File

@@ -0,0 +1,334 @@
/*! \file pistatemachine.h
* \brief Base class for custom state machine
*/
/*
PIP - Platform Independent Primitives
State machine
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISTATEMACHINE_H
#define PISTATEMACHINE_H
#include "piobject.h"
/*! \brief Base class for custom state machine
*
* \section PIStateMachine_synopsis Synopsis
* This class provide functionality of state machine.
* You should inherit from this class, implement \a execution()
* and \a transition() functions, set rules and periodically
* call \a tick() function to proper work of machine.
*
* \section PIStateMachine_prepare Prepare for work
* %State machine operates with "state", "rule" and "condition".
* * "State" is some class (by default \c int), associated name and
* optional "handler" - pointer to function executed on every \a tick();
* * "Rule" define rule of transition from one machine state to other.
* It is also has optional "handler";
* * "Condition" is a part of rule and define possibility of transition.
*
* First of all you should define states of your machine by function
* \a addState(). Then you should define transition rules for machine
* by function \a addRule(). Finally you can set initial state by function
* \a setInitialState() and provide periodically execution of function
* \a tick().
*
* \section PIStateMachine_principle Principle of work
* At any time the state machine is in some state. You can ask machine
* to enter in new state by function \a switchToState(). If all conditions
* done machine switch it state immediately, else machine remember request
* and will be try switch to the new state every tick. Successfull state
* switching execute function \a transition(), every tick execute
* function \a execution() with current state. On successfull transition
* if rule "handler" is not null it execute. Every \a tick() if current
* state "handler" is not null it execute.
*
* \section PIStateMachine_conditions Conditions
* Each rule has transition condition. Condition is array of pairs
* (string, number). It means that every condition by name "string"
* should be performed as least "number" times. Empty condition always
* permits transition.
*
* %State machine have current performed conditions. You can read this
* conditions by function \a currentConditions() and perform new
* conditions by functions \a performCondition() and \a performConditions().
* Currend conditions can de erased by function \a resetConditions().
*
* \section PIStateMachine_example Example
* This is simple example demonstrates all features:
* \snippet pistatemachine.cpp main
*/
template <typename Type = int>
class PIP_EXPORT PIStateMachine: public PIObject
{
PIOBJECT_SUBCLASS(PIStateMachine, PIObject)
public:
//! Constructs an empty state machine
PIStateMachine(void * _parent = 0) {if (_parent == 0) parent_ = this; else parent_ = _parent; resetConditions();}
~PIStateMachine() {;}
//! %Condition is a pair (string, number)
typedef PIPair<PIString, int> Condition;
//! %Rule of transition between states of machine
struct Rule {
//! Constuctor
Rule() {handler = 0; from = to = Type(); autoTransition = resetAllConditions = false;}
//! Constuctor
Rule(Type f, Type t, const PIStringList & c = PIStringList(), Handler h = 0, bool at = false, bool rac = false) {
from = f;
to = t;
for (int i = 0; i < c.size_s(); ++i)
conditions << Condition(c[i], 1);
autoTransition = at;
resetAllConditions = rac;
handler = h;
}
//! Source state
Type from;
//! Destination state
Type to;
//! %Conditions of transition
PIVector<Condition> conditions;
//! Automatic transition
bool autoTransition;
//! Reset or not all performed conditions of machine on transition
bool resetAllConditions;
//! Pointer to function executed on transition
Handler handler;
//! Add condition of transition
void addCondition(const PIString & name, int times = 1) {if (times > 0) conditions << Condition(name, times);}
bool operator ==(const Rule & other) const {return (from == other.from) && (to == other.to);}
bool operator !=(const Rule & other) const {return (from != other.from) || (to != other.to);}
};
//! %State of machine
struct State {
//! Constuctor
State() {handler = 0; value = Type();}
//! Constuctor
State(Type v, const PIString & n = "", Handler h = 0) {value = v; name = n; handler = h;}
//! %State value
Type value;
//! %State name
PIString name;
//! Pointer to function executed on tick
Handler handler;
bool operator ==(const State & other) const {return value == other.value;}
bool operator !=(const State & other) const {return value != other.value;}
};
void * parent() const {return parent_;}
void setParent(void * parent) {parent_ = parent;}
//! Add state of machine
void addState(Type value, const PIString & name = "", Handler handler = 0) {if (states_.contains(State(value, name))) return; states_ << State(value, name, handler);}
//! States count
int statesCount() const {return states_.size_s();}
//! Remove all states
void clearStates() {states_.clear();}
//! Add rule of transition
void addRule(Type from, Type to, const PIString & condition, Handler handler = 0, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(condition), handler, autoTransition, resetAllConditions);}
//! Add rule of transition
void addRule(Type from, Type to, Handler handler, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(), handler, autoTransition, resetAllConditions);}
//! Add rule of transition
void addRule(Type from, Type to, const PIStringList & conditions = PIStringList(), Handler handler = 0, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, conditions, handler, autoTransition, resetAllConditions);}
//! Add rule of transition
void addRule(const Rule & rule) {if (rules_.contains(rule)) return; rules_ << rule;}
//! Rules count
int rulesCount() const {return rules_.size_s();}
//! Remove all rules
void clearRules() {rules_.clear();}
//! Setup initial state. \a reset() will set machine state to "value"
void setInitialState(Type value) {
for (int i = 0; i < states_.size_s(); ++i)
if (states_[i].value == value) {
init_ = state_ = states_[i];
return;
}
}
/** \brief Try to switch machine state to state "to"
* \details If there is rule of transition exists and this rule conditions
* is performed then machine switched to new state immediately. Otherwise machine
* will be try to enter to new state every \a tick().
* \return \c true if state switched immediately, otherwise \c false */
bool switchToState(Type to) {
switch_to = to;
for (int i = 0; i < rules_.size_s(); ++i) {
Rule & r(rules_[i]);
if ((r.from != state_.value) || (r.to != to)) continue;
if (!checkConditions(r)) continue;
State ts = findState(to);
if (r.handler != 0 && parent_ != 0) r.handler(parent_);
transition(state_, ts);
state_ = ts;
resetConditions(r);
return true;
}
return false;
}
//! Reset machine state to initial and clear all conditions
void reset() {state_ = init_; resetConditions();}
//! Returns current state of machine
const State & currentState() const {return state_;}
//! Reset all performed conditions
void resetConditions() {cond.clear(); cond_count = 0;}
//! Reset performed condition with name "name"
void resetCondition(const PIString & name) {
for (int i = 0; i < cond.size_s(); ++i)
if (cond[i].first == name) {
cond.remove(i);
i--;
}
}
//! Perform condition with name "name" "times" times.
void performCondition(const PIString & name, int times = 1) {
if (times <= 0) return;
for (int i = 0; i < cond.size_s(); ++i)
if (cond[i].first == name) {
cond[i].second += times;
return;
}
cond << Condition(name, times);
}
//! Perform every condition with name from "names" one time.
void performConditions(const PIStringList & names) {
bool ok;
for (int n = 0; n < names.size_s(); ++n) {
ok = false;
for (int i = 0; i < cond.size_s(); ++i) {
if (cond[i].first == names[n]) {
cond[i].second++;
ok = true;
break;
}
}
if (ok) continue;
cond << Condition(names[n], 1);
}
}
//! Returns all current performed conditions
const PIVector<Condition> & currentConditions() const {return cond;}
Type * currentState_ptr() {return &state_.value;}
int * conditionsCount_ptr() {cond_count = cond.size_s(); return &cond_count;}
//! \handlers
//! \{
//! \fn void tick()
//! \brief Main function of machine. Execute \a execution() and check if need to switch state
//! \fn void tick(void * data, int delim)
//! \brief Main function of machine. Execute \a execution() and check if need to switch state
//! \}
EVENT_HANDLER(void, tick) {tick(0, 0);}
EVENT_HANDLER2(void, tick, void * , data, int, delim) {
execution(state_);
if (state_.handler != 0 && parent_ != 0) state_.handler(parent_);
if (switch_to != state_.value) switchToState(switch_to);
else {
piForeachC (Rule & r, rules_) {
if (!r.autoTransition || r.from != state_.value) continue;
if (checkConditions(r)) {
switchToState(r.to);
break;
}
}
}
}
protected:
//! Reimplement this function to process current state of machine
virtual void execution(const State & state) {;}
//! Reimplement this function to process switching current state of machine
virtual void transition(const State & from, const State & to) {;}
private:
State findState(Type value) {
for (int i = 0; i < states_.size_s(); ++i)
if (states_[i].value == value)
return states_[i];
return State();
}
bool checkConditions(const Rule & rule) {
//if (cond.size_s() < rule.conditions.size_s()) return false;
int oc = 0;
for (int i = 0; i < cond.size_s(); ++i) {
PIString & rn(cond[i].first);
for (int j = 0; j < rule.conditions.size_s(); ++j) {
if (rn != rule.conditions[j].first) continue;
if (cond[i].second < rule.conditions[j].second) return false;
oc++;
}
}
return (rule.conditions.size_s() == oc);
}
void resetConditions(const Rule & rule) {
if (rule.resetAllConditions) {
cond.clear();
return;
}
for (int i = 0; i < cond.size_s(); ++i) {
PIString & rn(cond[i].first);
for (int j = 0; j < rule.conditions.size_s(); ++j) {
if (rn != rule.conditions[j].first) continue;
cond[i].second -= rule.conditions[j].second;
if (cond[i].second <= 0) {
cond.remove(i);
i--;
}
}
}
}
PIVector<State> states_;
PIVector<Rule> rules_;
State init_, state_;
Type switch_to;
void * parent_;
int cond_count;
PIVector<Condition> cond;
};
#endif // PISTATEMACHINE_H

970
src_main/core/pistring.cpp Executable file
View File

@@ -0,0 +1,970 @@
/*
PIP - Platform Independent Primitives
String
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pistring.h"
#ifdef PIP_ICU
# include "unicode/ucnv.h"
#endif
/*! \class PIString
* \brief String class
* \details PIP use this class for use string information.
*
* \section PIString_sec0 Synopsis
* This class based on \a PIVector to store information.
* String is a sequence of \a PIChar and can contain multibyte
* symbols. Therefore real memory size of string is symbols count * 4.
* String can be constucted from many types of data and can be converted
* to many types. There are man operators and handly functions to use
* string as you wish.
*
* \section PIString_sec1 To/from data convertions
* Most common constructor is \a PIString(const char * str), where "str"
* is null-terminated string, e.g. \c "string". This is 7 chars with last char = 0.
* Also you can constructs \a PIString from single \a PIChar, \a PIByteArray,
* other \a PIString or sequency of the same characters with custom length.\n \n
* This class has implicit conversions to <tt>const char * </tt> and
* \c std::string. Also there are functions to make same convertions:
* * \a data() - to <tt>const char * </tt>,
* * \a stdString() - to \c std::string,
* * \a toByteArray() - to \a PIByteArray.
*
* \section PIString_sec2 Numeric operations
* You can get symbolic representation of any numeric value with function
* \a setNumber(any integer value, int base = 10, bool * ok = 0). Default
* arguments are set for decimal base system, but you can choose any system
* from 2 to 40. There are the same static functions \a fromNumber(), that
* returns \a PIString. \n
* Also there is function \a setReadableSize() which is set human-readable
* size in bytes, Kb, Mb, Gb or Pb. Static analog is \a readableSize().
*
*/
const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'};
const int PIString::fromBaseN[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
#ifndef CC_VC
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf(ch, f, v);
#else
# define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); sprintf_s(ch, 256, f, v);
#endif
#ifdef ANDROID
int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;}
#endif
PIString PIString::itos(const int num) {pisprintf("%d", num); return PIString(ch);}
PIString PIString::ltos(const long num) {pisprintf("%ld", num); return PIString(ch);}
PIString PIString::lltos(const llong num) {pisprintf("%lld", num); return PIString(ch);}
PIString PIString::uitos(const uint num) {pisprintf("%u", num); return PIString(ch);}
PIString PIString::ultos(const ulong num) {pisprintf("%lu", num); return PIString(ch);}
PIString PIString::ulltos(const ullong num) {pisprintf("%llu", num); return PIString(ch);}
PIString PIString::ftos(const float num) {pisprintf("%.8f", num); return PIString(ch);}
PIString PIString::dtos(const double num) {pisprintf("%.8f", num); return PIString(ch);}
#undef pisprintf
void PIString::appendFromChars(const char * c, int s, const char * cp) {
if (s <= 0) return;
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(cp, &e);
if (cc) {
UChar * ucs = new UChar[s];
memset(ucs, 0, s * sizeof(UChar));
e = (UErrorCode)0;
int rs = ucnv_toUChars(cc, ucs, s, c, s, &e);
//printf("appendFromChars %d -> %d\n", s, rs);
for (int i = 0; i < rs; ++i)
push_back(PIChar(ucs[i]));
delete[] ucs;
ucnv_close(cc);
return;
}
#endif
int sz;
wchar_t wc;
for (int i = 0; i < s; ++i) {
if (/*isascii(c[i])*/c[i] >= 0) {
push_back(PIChar(c[i]));
continue;
}
sz = mbtowc(&wc, &(c[i]), 4);
//cout << sz << endl;
switch (sz) {
case 4:
push_back(PIChar(*(int*)&(c[i])));
i += 3;
continue;
case 3:
push_back(PIChar(*(int*)&(c[i])));
back().ch &= 0xFFFFFF;
i += 2;
continue;
case 2:
push_back(PIChar(*(short * )&(c[i])));
++i;
continue;
default:
push_back(PIChar(c[i]));
break;
}
}
}
PIString PIString::fromConsole(const char * s) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret;
if (l > 0) ret.appendFromChars(s, l
#ifdef PIP_ICU
, __sysoemname__
#endif
);
return ret;
}
PIString PIString::fromSystem(const char * s) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret;
if (l > 0) ret.appendFromChars(s, l);
return ret;
}
PIString PIString::fromUTF8(const char * s) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret;
if (l > 0) ret.appendFromChars(s, l
#ifdef PIP_ICU
, "UTF-8"
#endif
);
return ret;
}
PIString PIString::fromAscii(const char * s) {
PIString ret;
int l = 0;
while (s[l] != '\0') {
ret.push_back(PIChar(short(s[l])));
++l;
}
return ret;
}
PIString PIString::fromCodepage(const char * s, const char * c) {
int l = 0;
while (s[l] != '\0') ++l;
PIString ret;
if (l > 0) ret.appendFromChars(s, l
#ifdef PIP_ICU
, c
#endif
);
return ret;
}
void PIString::buildData(const char * cp) const {
data_.clear();
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(cp, &e);
if (cc) {
int rs = 0;//, ol = UCNV_GET_MAX_BYTES_FOR_STRING(size_s(), ucnv_getMaxCharSize(cc));
char uc[8];
for (int i = 0; i < size_s(); ++i) {
if (at(i).isAscii())
data_.push_back(uchar(at(i).unicode16Code()));
else {
e = (UErrorCode)0;
rs = ucnv_fromUChars(cc, uc, 8, (const UChar*)(PIDeque<PIChar>::data(i)), 1, &e);
//printf("conv %d\n", rs);
for (int j = 0; j < rs; ++j)
data_.push_back(uc[j]);
}
}
//printf("buildData %d -> %d\n", size_s(), data_.size_s());
ucnv_close(cc);
data_.push_back('\0');
return;
}
#endif
uint wc;
uchar tc;
//printf("PIString::data %d\n", size_s());
for (int i = 0, j = 0; i < size_s(); ++i) {
wc = uint(at(i).unicode16Code());
//printf("__%d_%d\n", i, wc);
tc = wc & 0xFF;
while (tc) {
data_.push_back(uchar(tc)); ++j;
wc >>= 8;
tc = wc & 0xFF;
//printf("____%d\n", wc);
}
/*if (at(i).isAscii())
data_.push_back(uchar(at(i).toAscii()));
else {
data_.push_back((at(i).toCharPtr()[0])); ++j;
data_.push_back((at(i).toCharPtr()[1]));
}*/
}
data_.push_back(uchar('\0'));
}
void PIString::trimsubstr(int &st, int &fn) const {
for (int i = 0; i < length(); ++i)
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12))
{st = i; break;}
if (st < 0) return;
for (int i = length() - 1; i >= 0; --i)
if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12))
{fn = i; break;}
}
const char * PIString::dataConsole() const {
buildData(
#ifdef PIP_ICU
__sysoemname__
#endif
);
return (const char *)(data_.data());
}
const char * PIString::dataUTF8() const {
buildData(
#ifdef PIP_ICU
"UTF-8"
#endif
);
return (const char *)(data_.data());
}
const char * PIString::dataAscii() const {
data_.clear();
for (int i = 0; i < size_s(); ++i)
data_.push_back(uchar(at(i).ch));
data_.push_back(uchar('\0'));
return (const char *)data_.data();
}
PIByteArray PIString::toUTF8() const {
if (isEmpty()) return data_.resized(0);
buildData(
#ifdef PIP_ICU
"UTF-8"
#endif
);
return data_.resized(data_.size_s() - 1);
}
PIByteArray PIString::toCharset(const char * c) const {
if (isEmpty()) return data_.resized(0);
buildData(
#ifdef PIP_ICU
c
#endif
);
return data_.resized(data_.size_s() - 1);
}
PIString & PIString::operator +=(const char * str) {
int l = 0;
while (str[l] != '\0') ++l;
appendFromChars(str, l);
return *this;
}
PIString & PIString::operator +=(const wchar_t * str) {
//cout << "wc" << endl;
int l = 0, sz;
char * c = new char[MB_CUR_MAX];
while (str[l] != 0) ++l;
for (int i = 0; i < l; ++i) {
sz = wctomb(c, str[i]);
switch (sz) {
case 4:
push_back(PIChar(*(int*)c));
continue;
case 3:
push_back(PIChar(*(int*)c));
back().ch &= 0xFFFFFF;
continue;
case 2:
push_back(PIChar(*(short * )c));
continue;
default:
push_back(PIChar(c[0]));
break;
}
}
delete[] c;
return *this;
}
PIString & PIString::operator +=(const PIString & str) {
*((PIDeque<PIChar>*)this) << *((PIDeque<PIChar>*)&str);
return *this;
}
bool PIString::operator ==(const PIString & str) const {
uint l = str.size();
if (size() != l) return false;
for (uint i = 0; i < l; ++i)
if (str[i] != at(i))
return false;
return true;
}
bool PIString::operator !=(const PIString & str) const {
uint l = str.size();
if (size() != l) return true;
for (uint i = 0; i < l; ++i)
if (str[i] != at(i))
return true;
return false;
}
bool PIString::operator <(const PIString & str) const {
uint l = str.size();
if (size() < l) return true;
if (size() > l) return false;
for (uint i = 0; i < l; ++i) {
if (str[i] == at(i)) continue;
if (str[i] < at(i)) return true;
else return false;
}
return false;
}
bool PIString::operator >(const PIString & str) const {
uint l = str.size();
if (size() < l) return false;
if (size() > l) return true;
for (uint i = 0; i < l; ++i) {
if (str[i] == at(i)) continue;
if (str[i] < at(i)) return false;
else return true;
}
return false;
}
PIString PIString::mid(const int start, const int len) const {
//PIString str;
int s = start, l = len;
if (l == 0 || s >= length()) return PIString();
if (s < 0) {
l += s;
s = 0;
}
if (l < 0) {
return PIString(&(at(s)), size_s() - s);
} else {
if (l > length() - s)
l = length() - s;
//for (int i = s; i < s + l; ++i)
// str += at(i);
// std::cout << "mid " << s << " " << l << " " << size_s() << " " << start << " " << len << "\n";
return PIString(&(at(s)), l);
}
return PIString();
}
PIString & PIString::cutMid(const int start, const int len) {
int s = start, l = len;
if (l == 0) return *this;
if (s < 0) {
l += s;
s = 0;
}
if (l < 0)
remove(s, size() - s);
else {
if (l > length() - s)
l = length() - s;
remove(s, l);
}
return *this;
}
PIString & PIString::trim() {
int st = -1, fn = 0;
trimsubstr(st, fn);
if (st < 0) {
clear();
return *this;
}
if (fn < size_s() - 1) cutRight(size_s() - fn - 1);
if (st > 0) cutLeft(st);
return *this;
}
PIString PIString::trimmed() const {
int st = -1, fn = 0;
trimsubstr(st, fn);
if (st < 0) return PIString();
return mid(st, fn - st + 1);
}
PIString & PIString::replace(int from, int count, const PIString & with) {
if (count < length() - from) remove(from, count);
else remove(from, length() - from);
uint c = with.length();
for (uint i = 0; i < c; ++i) insert(from + i, with[i]);
return *this;
}
PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) {
//piCout << "replace" << what << with;
if (what.isEmpty()) {
if (ok != 0) *ok = false;
return *this;
}
int s = find(what);
if (s >= 0) replace(s, what.length(), with);
if (ok != 0) *ok = (s >= 0);
return *this;
}
PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
if (what.isEmpty() || what == with) return *this;
bool ok = true;
while (ok) replace(what, with, &ok);
return *this;
}
PIString & PIString::insert(int index, const PIString & str) {
//uint c = str.length();
//for (uint i = 0; i < c; ++i) insert(index + i, str[i]);
PIDeque<PIChar>::insert(index, *((const PIDeque<PIChar>*)&str));
return *this;
}
PIStringList PIString::split(const PIString & delim) const {
PIStringList sl;
if (isEmpty() || delim.isEmpty()) return sl;
PIString ts(*this);
int ci = ts.find(delim);
while (ci >= 0) {
sl << ts.left(ci);
ts.cutLeft(ci + delim.length());
ci = ts.find(delim);
}
if (ts.length() > 0) sl << ts;
return sl;
}
int PIString::find(const char str, const int start) const {
for (int i = start; i < length(); ++i)
if (at(i) == str)
return i;
return -1;
}
int PIString::find(const PIString & str, const int start) const {
int l = str.length();
for (int i = start; i < length() - l + 1; ++i)
if (mid(i, l) == str)
return i;
return -1;
}
int PIString::findLast(const char str, const int start) const {
for (int i = length() - 1; i >= start; --i)
if (at(i) == str)
return i;
return -1;
}
int PIString::findLast(const PIString & str, const int start) const {
int l = str.length();
for (int i = length() - l; i >= start; --i)
if (mid(i, l) == str)
return i;
return -1;
}
int PIString::findWord(const PIString & word, const int start) const {
int f = start - 1, tl = length(), wl = word.length();
while ((f = find(word, f + 1)) >= 0) {
bool ok = true;
PIChar c;
if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}}
if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}}
if (ok) return f;
}
return -1;
}
int PIString::findCWord(const PIString & word, const int start) const {
int f = start - 1, tl = length(), wl = word.length();
while ((f = find(word, f + 1)) >= 0) {
bool ok = true;
PIChar c;
if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}}
if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}}
if (ok) return f;
}
return -1;
}
bool PIString::startsWith(const PIString & str) const {
if (size() < str.size()) return false;
return str == left(str.size());
}
bool PIString::endsWith(const PIString & str) const {
if (size() < str.size()) return false;
return str == right(str.size());
}
bool PIString::toBool() const {
PIString s(*this);
s = s.trimmed().toLowerCase();
if ( atof(s.toNativeDecimalPoints().data()) > 0. || s == "true" || s == "yes" || s == "on" || s == "ok") return true;
return false;
}
PIString PIString::takeSymbol() {
PIString ret;
int sz = size_s(), ss = -1;
for (int i = 0; i < sz; ++i) {
PIChar c = at(i);
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue;
ss = i;
break;
}
if (ss < 0) return ret;
ret = mid(ss, 1);
cutLeft(ss + 1);
return ret;
}
PIString PIString::takeWord() {
int sz = size_s(), ws = -1, we = -1;
for (int i = 0; i < sz; ++i) {
PIChar c = at(i);
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
if (we < 0 && ws >= 0) {
we = i;
break;
}
} else {
if (ws < 0) ws = i;
if (we >= 0) break;
}
}
PIString ret = mid(ws, we - ws);
cutLeft(we < 0 ? sz : we);
return ret;
}
PIString PIString::takeCWord() {
PIString ret;
int sz = size_s(), ws = -1, we = -1;
for (int i = 0; i < sz; ++i) {
PIChar c = at(i);
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
if (we < 0 && ws >= 0) {
we = i;
break;
}
} else {
if (ws < 0) {
if (c.isAlpha() || c == '_')
ws = i;
else
return ret;
} else {
if (!c.isAlpha() && !c.isDigit() && c != '_') {
we = i;
break;
}
}
if (we >= 0) break;
}
}
ret = mid(ws, we - ws);
cutLeft(we < 0 ? sz : we);
return ret;
}
PIString PIString::takeLine() {
int sz = size_s(), le = -1;
for (int i = 0; i < sz; ++i) {
PIChar c = at(i);
if (c == '\n') {
le = i;
break;
}
}
PIString ret = left(le);
if (!ret.isEmpty())
if (ret.back() == '\r')
ret.cutRight(1);
cutLeft(le < 0 ? sz : le + 1);
return ret;
}
PIString PIString::takeNumber() {
PIString ret;
int sz = size_s(), ls = -1, le = -1, phase = 0;
for (int i = 0; i < sz; ++i) {
if (phase > 7) break;
PIChar c = at(i);
//piCout << "char " << c << "phase" << phase;
switch (phase) {
case 0: // trim
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue;
phase = 7;
case 7: // sign
if (c == '-' || c == '+') {ls = i; phase = 1; break;}
case 1: // search start
if (c >= '0' && c <= '9') {le = i; if (ls < 0) ls = i; phase = 2; break;}
if (c == '.') {le = i; if (ls < 0) ls = i; phase = 3; break;}
phase = 9;
break;
case 2: // integer
if (c == '.') {le = i; phase = 3; break;}
if (c == 'e' || c == 'E') {le = i; phase = 4; break;}
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == 'x') {le = i; break;}
phase = 6;
break;
case 3: // point
if (c == 'e' || c == 'E') {le = i; phase = 4; break;}
if (c >= '0' && c <= '9') {le = i; break;}
phase = 6;
break;
case 4: // exp
if ((c >= '0' && c <= '9') || c == '-' || c == '+') {le = i; phase = 5; break;}
phase = 6;
break;
case 5: // power
if (c >= '0' && c <= '9') {le = i; break;}
phase = 6;
break;
case 6: // suffix
if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') {le = i; break;}
phase = 9;
break;
}
if (phase == 6) {
if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') le = i;
else phase = 9;
}
}
//piCout << ls << le;
if (le < ls) return ret;
ret = mid(ls, le - ls + 1);
cutLeft(le + 1);
return ret;
}
PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIChar & shield) {
PIString ret;
bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end);
int sz = size_s(), ls = -1, le = -1, cnt = 0;
for (int i = 0; i < sz; ++i) {
PIChar c = at(i);
if (c == shield) {++i; continue;}
if (trim_) {
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
continue;
trim_ = false;
}
if (eq) {
if (c == start) {
if (cnt == 0) ls = i;
else {le = i; cnt = 0; break;}
cnt++;
}
} else {
if (c == start) {
if (cnt == 0) ls = i;
cnt++;
}
if (c == end) {
cnt--;
if (cnt == 0) le = i;
}
}
if (cnt <= 0) break;
}
//piCout << ls << le << cnt;
if (le < ls || ls < 0 || le < 0 || cnt != 0) return ret;
ret = mid(ls + 1, le - ls - 1);
cutLeft(le + 1);
return ret;
}
PIString PIString::inBrackets(const PIChar &start, const PIChar &end) const {
int slen = length();
int st = -1, bcnt = 0;
PIChar cc;
for (int i = 0; i < slen; i++) {
cc = at(i);
if (cc == start) {
if (bcnt == 0) st = i;
bcnt++;
}
if (cc == end && st >= 0) {
bcnt--;
if (bcnt == 0) return mid(st+1, i-st-1);
}
}
return PIString();
}
PIString PIString::toUpperCase() const {
PIString str(*this);
int l = str.size();
for (int i = 0; i < l; ++i) str[i] = str[i].toUpper();
return str;
}
PIString PIString::toLowerCase() const {
PIString str(*this);
int l = str.size();
for (int i = 0; i < l; ++i) str[i] = str[i].toLower();
return str;
}
PIString PIString::toNativeDecimalPoints() const {
#ifdef HAS_LOCALE
PIString s(*this);
if (currentLocale == 0) return s;
return s.replaceAll(".", currentLocale->decimal_point).replaceAll(",", currentLocale->decimal_point);
#else
return PIString(*this).replaceAll(",", ".");
#endif
}
char PIString::toChar() const {
PIString s(toNativeDecimalPoints());
char v;
sscanf(s.data(), "%c", &v);
return v;
}
float PIString::toFloat() const {
return (float)atof(toNativeDecimalPoints().data());
}
double PIString::toDouble() const {
return atof(toNativeDecimalPoints().data());
}
ldouble PIString::toLDouble() const {
return atof(toNativeDecimalPoints().data());
}
/*
short PIString::toShort() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
short v;
if (s.left(2) == "0x") {sscanf(s.data(), "%hx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%ho", &v); return v;}
sscanf(s.data(), "%hd", &v);
return v;
}
int PIString::toInt() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
int v;
if (s.left(2) == "0x") {sscanf(s.data(), "%x", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%o", &v); return v;}
sscanf(s.data(), "%d", &v);
return v;
}
long PIString::toLong() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
long v;
if (s.left(2) == "0x") {sscanf(s.data(), "%lx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%lo", &v); return v;}
sscanf(s.data(), "%ld", &v);
return v;
}
llong PIString::toLLong() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
llong v;
if (s.left(2) == "0x") {sscanf(s.data(), "%llx", &v); return v;}
if (s.left(1) == "0") {sscanf(s.data(), "%llo", &v); return v;}
sscanf(s.data(), "%lld", &v);
return v;
}
*/
PIString & PIString::setReadableSize(llong bytes) {
clear();
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;}
double fres = bytes / 1024.;
llong res = bytes / 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " kB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " MB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " TB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " PB");
return *this;
}
inline char chrUpr(char c) {
if (c >= 'a' && c <= 'z') return c + 'A' - 'a';
//if (c >= 'а' && c <= 'я') return c + 'А' - 'а';
return c;
}
inline char chrLwr(char c) {
if (c >= 'A' && c <= 'Z') return c + 'a' - 'A';
//if (c >= 'А' && c <= 'Я') return c + 'а' - 'А';
return c;
}
PICout operator <<(PICout s, const PIString & v) {
s.space();
s.quote();
s.setControl(0, true);
if (PICout::isBufferActive())
s << v.data();
else
s << v.dataConsole();
s.restoreControl();
s.quote();
return s;
}
PIStringList& PIStringList::removeDuplicates() {
PIStringList l;
PIString s;
bool ae;
for (int i = 0; i < size_s(); ++i) {
ae = false;
s = at(i);
for (int j = 0; j < l.size_s(); ++j) {
if (s != l[j]) continue;
ae = true; break;
}
if (!ae) {
l << s;
continue;
}
remove(i);
--i;
}
return *this;
}

890
src_main/core/pistring.h Executable file
View File

@@ -0,0 +1,890 @@
/*! \file pistring.h
* \brief String
*
* This file declare string and string list classes
*/
/*
PIP - Platform Independent Primitives
String
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PISTRING_H
#define PISTRING_H
#include "pibytearray.h"
#define PIStringAscii PIString::fromAscii
class PIStringList;
class PIP_EXPORT PIString: public PIDeque<PIChar>
{
friend PIByteArray & operator >>(PIByteArray & s, PIString & v);
public:
//! Contructs an empty string
PIString(): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--;}
//inline PIString & operator +=(const char c) {push_back(c); return *this;}
PIString & operator +=(const PIChar & c) {push_back(c); return *this;}
PIString & operator +=(const char * str);
PIString & operator +=(const wchar_t * str);
PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s()); return *this;}
PIString & operator +=(const PIString & str);
//PIString(const char c) {*this += c;}
PIString(const PIString & o): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this += o;}
//! Contructs string with single symbol "c"
PIString(const PIChar & c): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this += c;}
PIString(const char c): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);}
/*! \brief Contructs string from c-string "str"
* \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(char * ) */
PIString(const char * str): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this += str;}
/*! \brief Contructs string from \c wchar_t c-string "str"
* \details "str" should be null-terminated\n
* Example: \snippet pistring.cpp PIString(wchar_t * ) */
PIString(const wchar_t * str): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this += str;}
//! Contructs string from byte array "ba"
PIString(const PIByteArray & ba): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this += ba;}
//! \brief Contructs string from "len" characters of buffer "str"
PIString(const PIChar * str, const int len): PIDeque<PIChar>(str, size_t(len)) {/*reserve(4); */piMonitor.strings++; piMonitor.containers--;}
/*! \brief Contructs string from "len" characters of buffer "str"
* \details Example: \snippet pistring.cpp PIString(char * , int) */
PIString(const char * str, const int len): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; appendFromChars(str, len);}
/*! \brief Contructs string as sequence of characters "c" of buffer with length "len"
* \details Example: \snippet pistring.cpp PIString(int, char) */
PIString(const int len, const char c): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
/*! \brief Contructs string as sequence of symbols "c" of buffer with length "len"
* \details Example: \snippet pistring.cpp PIString(int, PIChar) */
PIString(const int len, const PIChar & c): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
PIString(const short & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ushort & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const int & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const uint & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const long & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ulong & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const llong & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const ullong & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const float & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
PIString(const double & value): PIDeque<PIChar>() {/*reserve(4); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);}
//~PIString() {piMonitor.strings--; piMonitor.containers++;}
PIString & operator =(const PIString & o) {if (this == &o) return *this; clear(); *this += o; return *this;}
/*! \brief Return c-string representation of string
* \details Converts content of string to c-string and return
* pointer to first char. This buffer is valid until new convertion
* or execution \a data() or \a toByteArray().\n
* Example: \snippet pistring.cpp PIString::char* */
operator const char*() {return data();}
//! Return symbol at index "pos"
PIChar operator [](const int pos) const {return at(pos);}
//! Return reference to symbol at index "pos"
PIChar & operator [](const int pos) {return at(pos);}
//! Compare operator
bool operator ==(const PIString & str) const;
//! Compare operator
bool operator ==(const PIChar c) const {return *this == PIString(c);}
//inline bool operator ==(const char c) const {return *this == PIString(c);}
//! Compare operator
bool operator ==(const char * str) const {return *this == PIString(str);}
//! Compare operator
bool operator !=(const PIString & str) const;
//! Compare operator
bool operator !=(const PIChar c) const {return *this != PIString(c);}
//inline bool operator !=(const char c) const {return *this != PIString(c);}
//! Compare operator
bool operator !=(const char * str) const {return *this != PIString(str);}
//! Compare operator
bool operator <(const PIString & str) const;
//! Compare operator
bool operator <(const PIChar c) const {return *this < PIString(c);}
//inline bool operator <(const char c) const {return *this < PIString(c);}
//! Compare operator
bool operator <(const char * str) const {return *this < PIString(str);}
//! Compare operator
bool operator >(const PIString & str) const;
//! Compare operator
bool operator >(const PIChar c) const {return *this > PIString(c);}
//inline bool operator >(const char c) const {return *this > PIString(c);}
//! Compare operator
bool operator >(const char * str) const {return *this > PIString(str);}
//! Compare operator
bool operator <=(const PIString & str) const {return !(*this > str);}
//! Compare operator
bool operator <=(const PIChar c) const {return *this <= PIString(c);}
//inline bool operator <=(const char c) const {return *this <= PIString(c);}
//! Compare operator
bool operator <=(const char * str) const {return *this <= PIString(str);}
//! Compare operator
bool operator >=(const PIString & str) const {return !(*this < str);}
//! Compare operator
bool operator >=(const PIChar c) const {return *this >= PIString(c);}
//inline bool operator >=(const char c) const {return *this >= PIString(c);}
//! Compare operator
bool operator >=(const char * str) const {return *this >= PIString(str);}
operator bool() const {return toBool();}
operator short() const {return toShort();}
operator ushort() const {return toUShort();}
operator int() const {return toInt();}
operator uint() const {return toUInt();}
operator long() const {return toLong();}
operator ulong() const {return toULong();}
operator llong() const {return toLLong();}
operator ullong() const {return toULLong();}
operator float() const {return toFloat();}
operator double() const {return toDouble();}
/*! \brief Append string "str" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(PIString) */
PIString & operator <<(const PIString & str) {*this += str; return *this;}
//inline PIString & operator <<(const char c) {*this += c; return *this;}
/*! \brief Append symbol "c" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(PIChar) */
PIString & operator <<(const PIChar & c) {*this += c; return *this;}
/*! \brief Append c-string "str" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(char * ) */
PIString & operator <<(const char * str) {*this += str; return *this;}
/*! \brief Append \c wchar_t c-string "str" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(wchar_t * ) */
PIString & operator <<(const wchar_t * str) {*this += str; return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ushort & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;}
PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;}
/*! \brief Append string representation of "num" at the end of string
* \details Example: \snippet pistring.cpp PIString::<<(int) */
PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;}
//! \brief Insert string "str" at the begin of string
PIString & prepend(const PIString & str) {insert(0, str); return *this;}
//! \brief Insert string "str" at the end of string
PIString & append(const PIString & str) {*this += str; return *this;}
/*! \brief Return part of string from symbol at index "start" and maximum length "len"
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid
* \sa \a left(), \a right() */
PIString mid(const int start, const int len = -1) const;
/*! \brief Return part of string from left and maximum length "len"
* \details Example: \snippet pistring.cpp PIString::left
* \sa \a mid(), \a right() */
PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);}
/*! \brief Return part of string from right and maximum length "len"
* \details Example: \snippet pistring.cpp PIString::right
* \sa \a mid(), \a left() */
PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);}
/*! \brief Remove part of string from symbol as index "start" and maximum length "len"
* and return this string
* \details All variants demonstrated in example: \snippet pistring.cpp PIString::cutMid
* \sa \a cutLeft(), \a cutRight() */
PIString & cutMid(const int start, const int len);
/*! \brief Remove part of string from left and maximum length "len" and return this string
* \details Example: \snippet pistring.cpp PIString::cutLeft
* \sa \a cutMid(), \a cutRight() */
PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);}
/*! \brief Remove part of string from right and maximum length "len" and return this string
* \details Example: \snippet pistring.cpp PIString::cutRight
* \sa \a cutMid(), \a cutLeft() */
PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);}
/*! \brief Remove spaces at the start and at the end of string and return this string
* \details Example: \snippet pistring.cpp PIString::trim
* \sa \a trimmed() */
PIString & trim();
/*! \brief Return copy of this string without spaces at the start and at the end
* \details Example: \snippet pistring.cpp PIString::trimmed
* \sa \a trim() */
PIString trimmed() const;
/*! \brief Replace part of string from index "from" and maximum length "len"
* with string "with" and return this string
* \details Example: \snippet pistring.cpp PIString::replace_0
* \sa \a replaced(), \a replaceAll() */
PIString & replace(const int from, const int count, const PIString & with);
/*! \brief Replace part copy of this string from index "from" and maximum length "len"
* with string "with" and return copied string
* \details Example: \snippet pistring.cpp PIString::replaced_0
* \sa \a replace(), \a replaceAll() */
PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;}
/*! \brief Replace first founded substring "what" with string "with" and return this string
* \details If "ok" is not null, it set to "true" if something was replaced\n
* Example: \snippet pistring.cpp PIString::replace_1
* \sa \a replaced(), \a replaceAll() */
PIString & replace(const PIString & what, const PIString & with, bool * ok = 0);
/*! \brief Replace first founded substring "what" with string "with" and return copied string
* \details If "ok" is not null, it set to "true" if something was replaced\n
* Example: \snippet pistring.cpp PIString::replaced_1
* \sa \a replaced(), \a replaceAll() */
PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;}
/*! \brief Replace all founded substrings "what" with strings "with" and return this string
* \details Example: \snippet pistring.cpp PIString::replaceAll
* \sa \a replace(), \a replaced() */
PIString & replaceAll(const PIString & what, const PIString & with);
PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;}
/*! \brief Repeat content of string "times" times and return this string
* \details Example: \snippet pistring.cpp PIString::repeat */
PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;}
/*! \brief Returns repeated "times" times string
* \details Example: \snippet pistring.cpp PIString::repeated */
PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);}
/*! \brief Insert symbol "c" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_0 */
PIString & insert(const int index, const PIChar & c) {PIDeque<PIChar>::insert(index, c); return *this;}
/*! \brief Insert symbol "c" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_1 */
PIString & insert(const int index, const char & c) {return insert(index, PIChar(c));}
/*! \brief Insert string "str" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_2 */
PIString & insert(const int index, const PIString & str);
/*! \brief Insert string "str" after index "index" and return this string
* \details Example: \snippet pistring.cpp PIString::insert_2 */
PIString & insert(const int index, const char * c) {return insert(index, PIString(c));}
/*! \brief Enlarge string to length "len" by addition sequence of symbols
* "c" at the end of string, and return this string
* \details Example: \snippet pistring.cpp PIString::expandRightTo
* \sa \a expandLeftTo() */
PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;}
/*! \brief Enlarge string to length "len" by addition sequence of symbols
* "c" at the beginning of string, and return this string
* \details Example: \snippet pistring.cpp PIString::expandLeftTo
* \sa \a expandRightTo() */
PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;}
/*! \brief Reverse string and return this string
* \details Example: \snippet pistring.cpp PIString::reverse
* \sa \a reversed() */
PIString & reverse() {PIString str(*this); clear(); piForeachR (const PIChar & c, str) push_back(c); return *this;}
/*! \brief Reverse copy of this string and return it
* \details Example: \snippet pistring.cpp PIString::reversed
* \sa \a reverse() */
PIString reversed() const {PIString str(*this); str.reverse(); return str;}
/*! \brief Take a part of string from symbol at index "start" and maximum length "len" and return it
* \details Example: \snippet pistring.cpp PIString::takeMid
* \sa \a takeLeft, \a takeRight() */
PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;}
/*! \brief Take a part from the begin of string with maximum length "len" and return it
* \details Example: \snippet pistring.cpp PIString::takeLeft
* \sa \a takeMid(), \a takeRight() */
PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;}
/*! \brief Take a part from the end of string with maximum length "len" and return it
* \details Example: \snippet pistring.cpp PIString::takeRight
* \sa \a takeMid(), \a takeLeft() */
PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;}
/*! \brief Take a symbol from the begin of this string and return it
* \details Example: \snippet pistring.cpp PIString::takeSymbol
* \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
PIString takeSymbol();
/*! \brief Take a word from the begin of this string and return it
* \details Example: \snippet pistring.cpp PIString::takeWord
* \sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
PIString takeWord();
/*! \brief Take a word with letters, numbers and '_' symbols from the
* begin of this string and return it
* \details Example: \snippet pistring.cpp PIString::takeCWord
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange() */
PIString takeCWord();
/*! \brief Take a line from the begin of this string and return it
* \details Example: \snippet pistring.cpp PIString::takeLine
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange() */
PIString takeLine();
/*! \brief Take a number with C-format from the begin of this string and return it
* \details Example: \snippet pistring.cpp PIString::takeNumber
* \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange() */
PIString takeNumber();
/*! \brief Take a range between "start" and "end" symbols from the begin of this
* string and return it.
* \details "Shield" symbol prevent analysis of the next symbol.
* Example: \snippet pistring.cpp PIString::takeRange
* \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber() */
PIString takeRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\');
/*! \brief Return a string in brackets "start" and "end" symbols from the begin of this
* string and return it.
* \details Example: string = "a(b(c)d)e"; inBrackets('(', ')') = "b(c)d"; */
PIString inBrackets(const PIChar & start, const PIChar & end) const;
/*! \brief Return real bytes count of this string
* \details It`s equivalent length of char sequence
* returned by function \a data() - 1, without terminating null-char \n
* Example: \snippet pistring.cpp PIString::lengthAscii
* \sa \a data() */
int lengthAscii() const {buildData(); return data_.size_s() - 1;}
/*! \brief Return \c char * representation of this string in system codepage
* \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* Example: \snippet pistring.cpp PIString::data
* \sa \a dataConsole(), \a dataUTF8() */
const char * data() const {buildData(); return (const char *)(data_.data());}
/*! \brief Return \c char * representation of this string in terminal codepage
* \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* \sa \a data(), \a dataUTF8() */
const char * dataConsole() const;
/*! \brief Return \c char * representation of this string in UTF-8
* \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n
* \sa \a data(), \a dataConsole() */
const char * dataUTF8() const;
/*! \brief Return \c char * representation of this string in ASCII
* \details This function fill buffer by sequence
* of chars. Minimum length of this buffer is count
* of symbols. Returned \c char * is valid until next
* execution of this function.\n */
const char * dataAscii() const;
//! \brief Return \a PIByteArray contains \a data() of this string without terminating null-char
PIByteArray toByteArray() const {buildData(); return data_.resized(data_.size_s() - 1);}
//! \brief Return \a PIByteArray contains UTF-8 \a data() of this string without terminating null-char
PIByteArray toUTF8() const;
//! \brief Return \a PIByteArray contains custom charset representation of this string without terminating null-char
PIByteArray toCharset(const char * c) const;
/*! \brief Split string with delimiter "delim" to \a PIStringList and return it
* \details Example: \snippet pistring.cpp PIString::split */
PIStringList split(const PIString & delim) const;
//! \brief Convert each symbol in copyed string to upper case and return it
PIString toUpperCase() const;
//! \brief Convert each symbol in copyed string to lower case and return it
PIString toLowerCase() const;
PIString toNativeDecimalPoints() const;
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const char str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const PIString & str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return first occur position
//! \details Example: \snippet pistring.cpp PIString::find
int find(const char * str, const int start = 0) const {return find(PIString(str), start);}
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const char str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const PIString & str, const int start = 0) const;
//! \brief Search substring "str" from symbol at index "start" and return last occur position
//! \details Example: \snippet pistring.cpp PIString::findLast
int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);}
//! \brief Search word "word" from symbol at index "start" and return first occur position.
//! \details Example: \snippet pistring.cpp PIString::findWord
int findWord(const PIString & word, const int start = 0) const;
//! \brief Search C-style word "word" from symbol at index "start" and return first occur position.
//! \details Example: \snippet pistring.cpp PIString::findCWord
int findCWord(const PIString & word, const int start = 0) const;
//! \brief Return if string starts with "str"
bool startsWith(const PIString & str) const;
//! \brief Return if string ends with "str"
bool endsWith(const PIString & str) const;
//! \brief Return symbols length of string
int length() const {return size();}
//! \brief Return \c true if string is empty, i.e. length = 0
bool isEmpty() const {return (size() == 0 || *this == "");}
//! \brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value
bool toBool() const;
//! \brief Return \c char numeric value of string
char toChar() const;
//! \brief Return \c short numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));}
//! \brief Return \c ushort numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));}
//! \brief Return \c int numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));}
//! \brief Return \c uint numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));}
//! \brief Return \c long numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));}
//! \brief Return \c ulong numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));}
//! \brief Return \c llong numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);}
//! \brief Return \c ullong numeric value of string in base "base"
//! \details Example: \snippet pistring.cpp PIString::toNumber
ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));}
//! \brief Return \c float numeric value of string
//! \details Example: \snippet pistring.cpp PIString::toFloat
float toFloat() const;
//! \brief Return \c double numeric value of string
//! \details Example: \snippet pistring.cpp PIString::toFloat
double toDouble() const;
//! \brief Return \c ldouble numeric value of string
//! \details Example: \snippet pistring.cpp PIString::toFloat
ldouble toLDouble() const;
//inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::setNumber
PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
//! \brief Set string content to numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::setFloat
PIString & setNumber(const float value) {clear(); *this += PIString::fromNumber(value); return *this;}
//! \brief Set string content to numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::setFloat
PIString & setNumber(const double & value) {clear(); *this += PIString::fromNumber(value); return *this;}
//! \brief Set string content to numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::setFloat
PIString & setNumber(const ldouble & value) {clear(); *this += PIString::fromNumber(value); return *this;}
//! \brief Set string content to human readable size in B/kB/MB/GB/TB
//! \details Example: \snippet pistring.cpp PIString::setReadableSize
PIString & setReadableSize(llong bytes);
//inline static PIString fromNumber(const char value) {return PIString(itos(value));}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);}
//! \brief Return string contains numeric representation of "value" in base "base"
//! \details Example: \snippet pistring.cpp PIString::fromNumber
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);}
//! \brief Return string contains numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::fromFloat
static PIString fromNumber(const float value) {return ftos(value);}
//! \brief Return string contains numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::fromFloat
static PIString fromNumber(const double & value) {return ftos(value);}
//! \brief Return string contains numeric representation of "value"
//! \details Example: \snippet pistring.cpp PIString::fromFloat
static PIString fromNumber(const ldouble & value) {return ftos(value);}
//! \brief Return "true" or "false"
static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");}
//! \brief Return string constructed from terminal codepage
static PIString fromConsole(const char * s);
//! \brief Return string constructed from system codepage
static PIString fromSystem(const char * s);
//! \brief Return string constructed from UTF-8
static PIString fromUTF8(const char * s);
//! \brief Return string constructed from ASCII
static PIString fromAscii(const char * s);
//! \brief Return string constructed from "c" codepage
static PIString fromCodepage(const char * s, const char * c);
//! \brief Return string contains human readable size in B/kB/MB/GB/TB
//! \details Example: \snippet pistring.cpp PIString::readableSize
static PIString readableSize(llong bytes) {PIString s; s.setReadableSize(bytes); return s;}
PIString & removeAll(char v) {replaceAll(v, ""); return *this;}
PIString & removeAll(const PIString & v) {replaceAll(v, ""); return *this;}
private:
static const char toBaseN[];
static const int fromBaseN[];
static PIString itos(const int num);
static PIString ltos(const long num);
static PIString lltos(const llong num);
static PIString uitos(const uint num);
static PIString ultos(const ulong num);
static PIString ulltos(const ullong num);
static PIString ftos(const float num);
static PIString dtos(const double num);
static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0) {
if (value == 0) return PIString("0");
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
if (ok != 0) *ok = true;
if (base == 10) return lltos(value);
PIString ret;
llong v = value < 0 ? -value : value, cn;
int b = base;
while (v >= llong(base)) {
cn = v % b;
v /= b;
//cout << int(cn) << ", " << int(v) << endl;
ret.push_front(PIChar(toBaseN[cn]));
}
if (v > 0) ret.push_front(PIChar(toBaseN[v]));
if (value < 0) ret.push_front('-');
return ret;
}
static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0) {
if (value == 0) return PIString("0");
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();}
if (ok != 0) *ok = true;
if (base == 10) return ulltos(value);
PIString ret;
ullong v = value, cn;
int b = base;
while (v >= ullong(base)) {
cn = v % b;
v /= b;
//cout << int(cn) << ", " << int(v) << endl;
ret.push_front(PIChar(toBaseN[cn]));
}
if (v > 0) ret.push_front(PIChar(toBaseN[v]));
return ret;
}
static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0) {
PIString v = value.trimmed();
if (base < 0) {
int ind = v.find("0x");
if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;}
else base = 10;
} else
if (base < 2 || base > 40) {if (ok != 0) *ok = false; return 0;}
//v.reverse();
if (ok) *ok = true;
PIVector<int> digits;
llong ret = 0, m = 1;
bool neg = false;
int cs;
for (int i = 0; i < v.size_s(); ++i) {
if (v[i] == PIChar('-')) {neg = !neg; continue;}
cs = fromBaseN[int(v[i].toAscii())];
if (cs < 0 || cs >= base) {
if (ok) *ok = false;
break;
}
digits << cs;
}
for (int i = digits.size_s() - 1; i >= 0; --i) {
ret += digits[i] * m;
m *= base;
}
if (neg) ret = -ret;
/*piForeachC (PIChar & i, v) {
if (i == PIChar('-')) {ret = -ret; continue;}
cs = fromBaseN[int(i.toAscii())];
cout << i << " = " << cs << endl;
if (cs < 0 || cs >= base) return ret;
ret += cs * m;
m *= base;
}*/
return ret;
}
void appendFromChars(const char * c, int s, const char * cp = 0);
void buildData(const char * cp = 0) const;
void trimsubstr(int &st, int &fn) const;
mutable PIByteArray data_;
};
//! \relatesalso PIString \relatesalso PICout \brief Output operator to PICout
PICout operator <<(PICout s, const PIString & v);
//! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray
inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << *(PIDeque<PIChar>*)&v; return s;}
//! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {s >> *(PIDeque<PIChar>*)&v; return s;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;}
//inline PIString operator +(const PIString & f, const char c) {PIString s(f); s.push_back(c); return s;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;}
//inline PIString operator +(const char c, const PIString & f) {return PIString(c) + f;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;}
inline char chrUpr(char c);
inline char chrLwr(char c);
/*!\brief Strings array class
* \details This class is based on \a PIDeque<PIString> and
* expand it functionality. */
class PIP_EXPORT PIStringList: public PIDeque<PIString>
{
public:
//! Contructs empty strings list
PIStringList() {;}
//! Contructs strings list with one string "str"
PIStringList(const PIString & str) {push_back(str);}
//! Contructs empty strings list with strings "s0" and "s1"
PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);}
//! Contructs empty strings list with strings "s0", "s1" and "s2"
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);}
//! Contructs empty strings list with strings "s0", "s1", "s2" and "s3"
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);}
PIStringList(const PIStringList & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
PIStringList(const PIVector<PIString> & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
PIStringList(const PIDeque<PIString> & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
//! \brief Join all strings in one with delimiter "delim" and return it
//! \details Example: \snippet pistring.cpp PIStringList::join
PIString join(const PIString & delim) const {PIString s; for (uint i = 0; i < size(); ++i) {s += at(i); if (i < size() - 1) s += delim;} return s;}
//! \brief Remove all strings equal "value" and return this
//! \details Example: \snippet pistring.cpp PIStringList::removeStrings
PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;}
PIStringList & remove(uint num) {PIDeque<PIString>::remove(num); return *this;}
PIStringList & remove(uint num, uint count) {PIDeque<PIString>::remove(num, count); return *this;}
//! \brief Remove duplicated strings and return this
//! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates
PIStringList & removeDuplicates();
//! \brief Trim all strings
//! \details Example: \snippet pistring.cpp PIStringList::trim
PIStringList & trim() {for (uint i = 0; i < size(); ++i) at(i).trim(); return *this;}
//! Return sum of lengths of all strings
uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;}
//! Compare operator
bool operator ==(const PIStringList & o) const {if (size() != o.size()) return false; for (size_t i = 0; i < size(); ++i) if (o[i] != (*this)[i]) return false; return true;}
//! Compare operator
bool operator !=(const PIStringList & o) const {return !(o == (*this));}
PIStringList & operator =(const PIStringList & o) {clear(); for (uint i = 0; i < o.size(); ++i) *this << o[i]; return *this;}
PIStringList & operator <<(const PIString & str) {push_back(str); return *this;}
PIStringList & operator <<(const PIStringList & sl) {piForeachC (PIString & i, sl) push_back(i); return *this;}
//inline PIStringList & operator <<(const char c) {push_back(PIString(c)); return *this;}
PIStringList & operator <<(const char * str) {push_back(PIString(str)); return *this;}
PIStringList & operator <<(const int & num) {push_back(PIString::fromNumber(num)); return *this;}
PIStringList & operator <<(const short & num) {push_back(PIString::fromNumber(num)); return *this;}
PIStringList & operator <<(const long & num) {push_back(PIString::fromNumber(num)); return *this;}
PIStringList & operator <<(const float & num) {push_back(PIString::fromNumber(num)); return *this;}
PIStringList & operator <<(const double & num) {push_back(PIString::fromNumber(num)); return *this;}
};
//! \relatesalso PIStringList \relatesalso PIByteArray \brief Output operator to PIByteArray
inline PIByteArray & operator <<(PIByteArray & s, const PIStringList & v) {s << int(v.size_s()); for (int i = 0; i < v.size_s(); ++i) s << v[i]; return s;}
//! \relatesalso PIStringList \relatesalso PIByteArray \brief Input operator from PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIStringList & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
//! \relatesalso PIStringList \relatesalso PICout \brief Output operator to PICout
inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << "\"" << v[i] << "\""; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;}
#endif // PISTRING_H

View File

@@ -0,0 +1,81 @@
#ifndef PISTRING_STD_H
#define PISTRING_STD_H
#include <string>
#ifdef QNX
typedef std::basic_string<wchar_t> wstring;
#endif
#include "pistring.h"
inline std::string PIString2StdString(const PIString & v) {
std::string s;
uint wc;
uchar tc;
if (v.size() > 0) {
for (int i = 0; i < v.length(); ++i) {
wc = uint(v.at(i).unicode16Code());
while (tc = wc & 0xFF, tc) {
s.push_back(char(tc));
wc >>= 8;
}
/*if (at(i).isAscii())
s.push_back(at(i).toAscii());
else {
s.push_back(at(i).toCharPtr()[0]);
s.push_back(at(i).toCharPtr()[1]);
}*/
}
}
return s;
}
inline PIString StdString2PIString(const std::string & v) {
return PIString(v.c_str(), v.length());
}
#ifdef HAS_LOCALE
inline std::wstring PIString2StdWString(const PIString & v) {
std::wstring s;
for (int i = 0; i < v.length(); ++i)
s.push_back(v.at(i).toWChar());
return s;
}
inline PIString StdWString2PIString(const std::wstring & v) {
PIString s;
uint l = v.size();
for (uint i = 0; i < l; ++i) s.push_back(v[i]);
return s;
}
#endif
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const PIString & f, const std::string & str) {PIString s(f); s += StdString2PIString(str); return s;}
//! \relatesalso PIString \brief Return concatenated string
inline PIString operator +(const std::string & str, const PIString & f) {return StdString2PIString(str) + f;}
//! \relatesalso PIString \brief Output operator to std::ostream (cout)
inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
//! \relatesalso PIString \brief Input operator from std::istream (cin)
inline std::istream & operator >>(std::istream & s, PIString & v) {std::string ss; s >> ss; v = StdString2PIString(ss); return s;}
//! \relatesalso PIStringList \brief Output operator to std::ostream (cout)
inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {
s << PIChar("{");
for (uint i = 0; i < v.size(); ++i) {
s << PIChar("\"") << v[i] << PIChar("\"");
if (i < v.size() - 1) s << PIStringAscii(", ");
}
s << PIChar("}");
return s;
}
#endif // PISTRING_STD_H

452
src_main/core/pitime.cpp Executable file
View File

@@ -0,0 +1,452 @@
/*
PIP - Platform Independent Primitives
Timer
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#include "pitime.h"
#include "pisystemtests.h"
#ifdef WINDOWS
extern FILETIME __pi_ftjan1970;
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
#endif
#ifdef MAC_OS
//# include <mach/mach_traps.h>
//# include <mach/mach.h>
# include <mach/clock.h>
//# include <crt_externs.h>
extern clock_serv_t __pi_mac_clock;
#endif
/*! \class PISystemTime
* \brief System time
*
* \section PISystemTime_sec0 Synopsis
* This class provide arithmetic functions for POSIX system time.
* This time represents as seconds and nanosecons in integer formats.
* You can take current system time with function \a PISystemTime::current(),
* compare times, sum or subtract two times, convert time to/from
* seconds, milliseconds, microseconds or nanoseconds.
* \section PISystemTime_sec1 Example
* \snippet pitimer.cpp system_time
*/
/*! \class PITimeMeasurer
* \brief Time measurements
*
* \section PITimeMeasurer_sec0 Synopsis
* Function \a reset() set time mark to current
* system time, then functions double elapsed_*() returns time elapsed from this mark.
* These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m"
* and "s"
*/
void piUSleep(int usecs) {
if (usecs <= 0) return;
#ifdef WINDOWS
if (usecs > 0) Sleep(usecs / 1000);
#else
usecs -= PISystemTests::usleep_offset_us;
if (usecs > 0) usleep(usecs);
#endif
}
bool operator ==(const PITime & t0, const PITime & t1) {
return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
}
bool operator <(const PITime & t0, const PITime & t1) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds < t1.seconds;
} else return t0.minutes < t1.minutes;
} else return t0.hours < t1.hours;
}
bool operator >(const PITime & t0, const PITime & t1) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds > t1.seconds;
} else return t0.minutes > t1.minutes;
} else return t0.hours > t1.hours;
}
bool operator ==(const PIDate & t0, const PIDate & t1) {
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day);
}
bool operator <(const PIDate & t0, const PIDate & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
return t0.day < t1.day;
} else return t0.month < t1.month;
} else return t0.year < t1.year;
}
bool operator >(const PIDate & t0, const PIDate & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
return t0.day > t1.day;
} else return t0.month > t1.month;
} else return t0.year > t1.year;
}
bool operator ==(const PIDateTime & t0, const PIDateTime & t1) {
return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day &&
t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds);
}
bool operator <(const PIDateTime & t0, const PIDateTime & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
if (t0.day == t1.day) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds < t1.seconds;
} else return t0.minutes < t1.minutes;
} else return t0.hours < t1.hours;
} else return t0.day < t1.day;
} else return t0.month < t1.month;
} else return t0.year < t1.year;
}
bool operator >(const PIDateTime & t0, const PIDateTime & t1) {
if (t0.year == t1.year) {
if (t0.month == t1.month) {
if (t0.day == t1.day) {
if (t0.hours == t1.hours) {
if (t0.minutes == t1.minutes) {
return t0.seconds > t1.seconds;
} else return t0.minutes > t1.minutes;
} else return t0.hours > t1.hours;
} else return t0.day > t1.day;
} else return t0.month > t1.month;
} else return t0.year > t1.year;
}
PISystemTime PITime::toSystemTime() const {
return PISystemTime((hours * 60. + minutes) * 60. + seconds, milliseconds * 1000.);
}
PITime PITime::current() {
time_t rt = ::time(0);
tm * pt = localtime(&rt);
PITime t;
t.seconds = pt->tm_sec;
t.minutes = pt->tm_min;
t.hours = pt->tm_hour;
return t;
}
PITime PITime::fromSystemTime(const PISystemTime & st) {
double s = st.toSeconds();
int v = s;
PITime ret;
ret.milliseconds = (s - v) * 1000;
ret.seconds = v % 60; v = (v - ret.seconds) / 60;
ret.minutes = v % 60; v = (v - ret.minutes) / 60;
ret.hours = v;
return ret;
}
PIDate PIDate::current() {
time_t rt = ::time(0);
tm * pt = localtime(&rt);
PIDate d;
d.day = pt->tm_mday;
d.month = pt->tm_mon + 1;
d.year = pt->tm_year + 1900;
return d;
}
PIDateTime PIDateTime::current() {
time_t rt = ::time(0);
tm * pt = localtime(&rt);
PIDateTime dt;
dt.milliseconds = 0;
dt.seconds = pt->tm_sec;
dt.minutes = pt->tm_min;
dt.hours = pt->tm_hour;
dt.day = pt->tm_mday;
dt.month = pt->tm_mon + 1;
dt.year = pt->tm_year + 1900;
return dt;
}
PISystemTime PISystemTime::abs() const {
if (seconds < 0)
return PISystemTime(piAbsl(seconds) - 1, 1000000000l - piAbsl(nanoseconds));
else
return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds));
}
PISystemTime PISystemTime::current(bool precise_but_not_system) {
#ifdef WINDOWS
if (precise_but_not_system) {
llong qpc(0);
if (__pi_perf_freq > 0) {
qpc = __PIQueryPerformanceCounter();
return PISystemTime::fromSeconds(qpc / double(__pi_perf_freq));
}
return PISystemTime();
} else {
FILETIME ft, sft;
# if (_WIN32_WINNT >= 0x0602)
GetSystemTimePreciseAsFileTime(&ft);
# else
GetSystemTimeAsFileTime(&ft);
# endif
sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime;
if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) {
sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime);
sft.dwHighDateTime--;
} else
sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime;
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
}
//long t_cur = GetCurrentTime();
//return PISystemTime(t_cur / 1000, (t_cur % 1000) * 1000000);
#else
# ifdef MAC_OS
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
# else
timespec t_cur;
clock_gettime(0, &t_cur);
# endif
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
#endif
}
PIString PITime::toString(const PIString & format) const {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(hours));
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(minutes));
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(seconds));
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
ts.replace("z", PIString::fromNumber(milliseconds));
return ts;
}
PIString PIDate::toString(const PIString & format) const {
PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).right(2));
ts.replace("y", PIString::fromNumber(year).right(1));
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
ts.replace("M", PIString::fromNumber(month));
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(day));
return ts;
}
PIString PIDateTime::toString(const PIString & format) const {
PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).right(2));
ts.replace("y", PIString::fromNumber(year).right(1));
ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
ts.replace("M", PIString::fromNumber(month));
ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(day));
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(hours));
ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(minutes));
ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(seconds));
ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0'));
ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0'));
ts.replace("z", PIString::fromNumber(milliseconds));
return ts;
}
time_t PIDateTime::toSecondSinceEpoch() const {
tm pt;
memset(&pt, 0, sizeof(pt));
pt.tm_sec = seconds;
pt.tm_min = minutes;
pt.tm_hour = hours;
pt.tm_mday = day;
pt.tm_mon = month - 1;
#ifdef WINDOWS
pt.tm_year = piMaxi(year - 1900, 70);
#else
pt.tm_year = piMaxi(year - 1900, 0);
#endif
return mktime(&pt);
}
PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) {
tm * pt = localtime(&sec);
PIDateTime dt;
dt.seconds = pt->tm_sec;
dt.minutes = pt->tm_min;
dt.hours = pt->tm_hour;
dt.day = pt->tm_mday;
dt.month = pt->tm_mon + 1;
dt.year = pt->tm_year + 1900;
return dt;
}
PIString time2string(const PITime & time, const PIString & format) {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(time.hours));
ts.replace("mm", PIString::fromNumber(time.minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(time.minutes));
ts.replace("ss", PIString::fromNumber(time.seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(time.seconds));
return ts;
}
PIString date2string(const PIDate & date, const PIString & format) {
PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(date.year).right(2));
ts.replace("y", PIString::fromNumber(date.year).right(1));
ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
ts.replace("M", PIString::fromNumber(date.month));
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(date.day));
return ts;
}
PIString datetime2string(const PIDateTime & date, const PIString & format) {
PIString ts = format;
ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0'));
ts.replace("h", PIString::fromNumber(date.hours));
ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(date.minutes));
ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0'));
ts.replace("s", PIString::fromNumber(date.seconds));
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(date.year).right(2));
ts.replace("y", PIString::fromNumber(date.year).right(1));
ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
ts.replace("M", PIString::fromNumber(date.month));
ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(date.day));
return ts;
}
PITimeMeasurer::PITimeMeasurer() {
reset();
}
double PITimeMeasurer::elapsed_n() const {
return (PISystemTime::current(true) - t_st).toNanoseconds() - PISystemTests::time_elapsed_ns;
}
double PITimeMeasurer::elapsed_u() const {
return (PISystemTime::current(true) - t_st).toMicroseconds() - PISystemTests::time_elapsed_ns / 1.E+3;
}
double PITimeMeasurer::elapsed_m() const {
return (PISystemTime::current(true) - t_st).toMilliseconds() - PISystemTests::time_elapsed_ns / 1.E+6;
}
double PITimeMeasurer::elapsed_s() const {
return (PISystemTime::current(true) - t_st).toSeconds() - PISystemTests::time_elapsed_ns / 1.E+9;
}
PISystemTime PITimeMeasurer::elapsed() const {
return (PISystemTime::current(true) - t_st);
}
PICout operator <<(PICout s, const PITime & v) {
s.space();
s.setControl(0, true);
s << "PITime(" << v.hours << ":";
s << PIString::fromNumber(v.minutes).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.seconds).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.milliseconds).expandLeftTo(3, '0') << ")";
s.restoreControl();
return s;
}
PICout operator <<(PICout s, const PIDate & v) {
s.space();
s.setControl(0, true);
s << "PIDate(" << v.day << "-";
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
s << v.year << ")";
s.restoreControl();
return s;
}
PICout operator <<(PICout s, const PIDateTime & v) {
s.space();
s.setControl(0, true);
s << "PIDateTime(";
s << v.day << "-";
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
s << v.year << " ";
s << v.hours << ":";
s << PIString::fromNumber(v.minutes).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.seconds).expandLeftTo(2, '0') << ":";
s << PIString::fromNumber(v.milliseconds).expandLeftTo(3, '0') << ")";
s.restoreControl();
return s;
}
#ifdef WINDOWS
void msleep(int msecs) {Sleep(msecs);}
#else
void msleep(int msecs) {usleep(msecs * 1000);}
#endif

334
src_main/core/pitime.h Executable file
View File

@@ -0,0 +1,334 @@
/*! \file pitime.h
* \brief Time structs
*/
/*
PIP - Platform Independent Primitives
Time structs
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PITIME_H
#define PITIME_H
#include "pistring.h"
#include <ctime>
#ifdef QNX
# include <time.h>
#endif
//! \brief Sleep for "msecs" milliseconds
void msleep(int msecs);
/*! \brief Precise sleep for "usecs" microseconds
* \details This function consider \c "usleep" offset
* on QNX/Linux/Mac, which is calculated with
* \a pip_sys_test program. If there is correct
* offset value in system config, this function
* wait \b exactly "usecs" microseconds. */
void piUSleep(int usecs); // on !Windows consider constant "usleep" offset
/*! \brief Precise sleep for "msecs" milliseconds
* \details This function exec \a piUSleep (msecs * 1000). */
inline void piMSleep(double msecs) {piUSleep(int(msecs * 1000.));} // on !Windows consider constant "usleep" offset
/*! \brief Precise sleep for "secs" seconds
* \details This function exec \a piUSleep (msecs * 1000000). */
inline void piSleep(double secs) {piUSleep(int(secs * 1000000.));} // on !Windows consider constant "usleep" offset
class PIP_EXPORT PISystemTime {
public:
//! Contructs system time with s = ns = 0
PISystemTime() {seconds = nanoseconds = 0;}
//! Contructs system time with s = "s" and ns = "ns"
PISystemTime(int s, int ns) {seconds = s; nanoseconds = ns; checkOverflows();}
//! Contructs system time from another
PISystemTime(const PISystemTime & t) {seconds = t.seconds; nanoseconds = t.nanoseconds;}
//! Returns stored system time value in seconds
double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;}
//! Returns stored system time value in milliseconds
double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;}
//! Returns stored system time value in microseconds
double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;}
//! Returns stored system time value in nanoseconds
double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);}
//! Add to stored system time "v" seconds
PISystemTime & addSeconds(double v) {*this += fromSeconds(v); return *this;}
//! Add to stored system time "v" milliseconds
PISystemTime & addMilliseconds(double v) {*this += fromMilliseconds(v); return *this;}
//! Add to stored system time "v" microseconds
PISystemTime & addMicroseconds(double v) {*this += fromMicroseconds(v); return *this;}
//! Add to stored system time "v" nanoseconds
PISystemTime & addNanoseconds(double v) {*this += fromNanoseconds(v); return *this;}
//! Sleep for stored value. \warning Use this function to sleep for difference of system times or constructs system time.
//! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever.
void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0)
//! Returns copy of this system time with absolutely values of s and ns
PISystemTime abs() const;
//! Returns sum of this system time with "t"
PISystemTime operator +(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;}
//! Returns difference between this system time and "t"
PISystemTime operator -(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;}
//! Returns multiplication between this system time and "t"
PISystemTime operator *(const double & v) const {return fromMilliseconds(toMilliseconds() * v);}
//! Returns division between this system time and "t"
PISystemTime operator /(const double & v) const {return fromMilliseconds(toMilliseconds() / v);}
//! Add to stored value system time "t"
PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;}
//! Subtract from stored value system time "t"
PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;}
//! Multiply stored value system time by "v"
PISystemTime & operator *=(const double & v) {*this = fromMilliseconds(toMilliseconds() * v); return *this;}
//! Divide stored value system time by "v"
PISystemTime & operator /=(const double & v) {*this = fromMilliseconds(toMilliseconds() / v); return *this;}
//! Compare system times
bool operator ==(const PISystemTime & t) const {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));}
//! Compare system times
bool operator !=(const PISystemTime & t) const {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));}
//! Compare system times
bool operator >(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;}
//! Compare system times
bool operator <(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;}
//! Compare system times
bool operator >=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;}
//! Compare system times
bool operator <=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;}
//! Contructs system time from seconds "v"
static PISystemTime fromSeconds(double v) {int s = piFloord(v); return PISystemTime(s, int((v - s) * 1000000000.));}
//! Contructs system time from milliseconds "v"
static PISystemTime fromMilliseconds(double v) {int s = piFloord(v / 1000.); return PISystemTime(s, int((v / 1000. - s) * 1000000000.));}
//! Contructs system time from microseconds "v"
static PISystemTime fromMicroseconds(double v) {int s = piFloord(v / 1000000.); return PISystemTime(s, int((v / 1000000. - s) * 1000000000.));}
//! Contructs system time from nanoseconds "v"
static PISystemTime fromNanoseconds(double v) {int s = piFloord(v / 1000000000.); return PISystemTime(s, int((v / 1000000000. - s) * 1000000000.));}
//! Returns current system time
static PISystemTime current(bool precise_but_not_system = false);
//! Seconds of stored system time
int seconds;
//! Nanoseconds of stored system time
int nanoseconds;
private:
void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}}
};
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setControl(0, true); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;}
//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Output operator to PIByteArray
inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;}
//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Input operator from PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;}
struct PIP_EXPORT PITime {
PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;}
int hours;
int minutes;
int seconds;
int milliseconds;
PIString toString(const PIString & format = "h:mm:ss") const;
PISystemTime toSystemTime() const;
static PITime current();
static PITime fromSystemTime(const PISystemTime & st);
};
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
inline PIByteArray & operator <<(PIByteArray & s, const PITime & v) {s << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PITime & v) {s >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;}
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
PICout operator <<(PICout s, const PITime & v);
struct PIP_EXPORT PIDate {
PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;}
int year;
int month;
int day;
PIString toString(const PIString & format = "d.MM.yyyy") const;
static PIDate current();
};
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
inline PIByteArray & operator <<(PIByteArray & s, const PIDate & v) {s << v.year << v.month << v.day; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIDate & v) {s >> v.year >> v.month >> v.day; return s;}
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
PICout operator <<(PICout s, const PIDate & v);
struct PIP_EXPORT PIDateTime {
PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;}
PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;}
PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
int year;
int month;
int day;
int hours;
int minutes;
int seconds;
int milliseconds;
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
void normalize() {*this = normalized();}
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
time_t toSecondSinceEpoch() const;
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
PIDate date() const {return PIDate(year, month, day);}
PITime time() const {return PITime(hours, minutes, seconds, milliseconds);}
void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;}
void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;}
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
static PIDateTime fromSecondSinceEpoch(const time_t sec);
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
static PIDateTime current();
};
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1);
PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1);
PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1);
inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);}
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIDateTime & v) {s >> v.year >> v.month >> v.day >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;}
//! \relatesalso PICout \relatesalso PICout \brief Output operator to PICout
PICout operator <<(PICout s, const PIDateTime & v);
class PITimeMeasurer {
public:
PITimeMeasurer();
/** \brief Set internal time mark to current system time
* \details This function used for set start time mark. Later
* you can find out elapsed time from this time mark to any
* moment of time with \a elapsed_s(), \a elapsed_m(),
* \a elapsed_u() or \a elapsed_n() functions.
* \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */
void reset() {t_st = PISystemTime::current(true);}
//! \brief Returns nanoseconds elapsed from last \a reset() execution or from timer measurer creation.
double elapsed_n() const;
//! \brief Returns microseconds elapsed from last \a reset() execution or from timer measurer creation.
double elapsed_u() const;
//! \brief Returns milliseconds elapsed from last \a reset() execution or from timer measurer creation.
double elapsed_m() const;
//! \brief Returns seconds elapsed from last \a reset() execution or from timer measurer creation.
double elapsed_s() const;
//! \brief Returns PISystemTime elapsed from last \a reset() execution or from timer measurer creation.
PISystemTime elapsed() const;
double reset_time_n() const {return t_st.toNanoseconds();}
double reset_time_u() const {return t_st.toMicroseconds();}
double reset_time_m() const {return t_st.toMilliseconds();}
double reset_time_s() const {return t_st.toSeconds();}
//! \brief Returns time mark of last \a reset() execution or timer measurer creation.
PISystemTime reset_time() {return t_st;}
//! \brief Returns nanoseconds representation of current system time.
static double elapsed_system_n() {return PISystemTime::current(true).toNanoseconds();}
//! \brief Returns microseconds representation of current system time.
static double elapsed_system_u() {return PISystemTime::current(true).toMicroseconds();}
//! \brief Returns milliseconds representation of current system time.
static double elapsed_system_m() {return PISystemTime::current(true).toMilliseconds();}
//! \brief Returns seconds representation of current system time.
static double elapsed_system_s() {return PISystemTime::current(true).toSeconds();}
//! \brief Returns time mark of current system time.
static PISystemTime elapsed_system() {return PISystemTime::current(true);}
private:
PISystemTime t_st, t_cur;
};
#endif // PITIME_H

View File

@@ -0,0 +1,69 @@
#ifndef PITIME_WIN_H
#define PITIME_WIN_H
#include "pibase.h"
#ifdef WINDOWS
#include "pitime.h"
#include <windows.h>
//inline PISystemTime SYSTEMTIME2PISystemTime(SYSTEMTIME &t) {
// PISystemTime st;
//}
inline PISystemTime FILETIME2PISystemTime(const FILETIME &t) {
PISystemTime st;
ullong lt = ullong(t.dwHighDateTime) * 0x100000000U + ullong(t.dwLowDateTime);
st.seconds = lt / 10000000U;
st.nanoseconds = (lt % 10000000U) * 100U;
return st;
}
inline PIDateTime SYSTEMTIME2PIDateTime(const SYSTEMTIME &t) {
PIDateTime dt;
dt.year = t.wYear;
dt.month = t.wMonth;
dt.day = t.wDay;
dt.hours = t.wHour;
dt.minutes = t.wMinute;
dt.seconds = t.wSecond;
dt.milliseconds = t.wMilliseconds;
return dt;
}
inline PIDateTime FILETIME2PIDateTime(const FILETIME &t) {
FILETIME lt;
SYSTEMTIME st;
FileTimeToLocalFileTime(&t, &lt);
FileTimeToSystemTime(&lt, &st);
return SYSTEMTIME2PIDateTime(st);
}
inline SYSTEMTIME PIDateTime2SYSTEMTIME(const PIDateTime &dt) {
SYSTEMTIME st;
st.wYear = dt.year;
st.wMonth = dt.month;
st.wDay = dt.day;
st.wHour = dt.hours;
st.wMinute = dt.minutes;
st.wSecond = dt.seconds;
st.wMilliseconds = dt.milliseconds;
return st;
}
inline FILETIME PIDateTime2FILETIME(const PIDateTime &dt) {
FILETIME lt, ret;
SYSTEMTIME st = PIDateTime2SYSTEMTIME(dt);
SystemTimeToFileTime(&st, &lt);
LocalFileTimeToFileTime(&lt, &ret);
return ret;
}
#endif // WINDOWS
#endif // PITIME_WIN_H

513
src_main/core/pivariant.cpp Executable file
View File

@@ -0,0 +1,513 @@
/*
PIP - Platform Independent Primitives
Variant type
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pivariant.h"
/** \class PIVariant
* \brief Variant type
* \details
* \section PIVariant_sec0 Synopsis
* This class provides general type that can contains all standard types, some
* PIP types or custom type. In case of standard types this class also provides
* convertions between them.
*
* \section PIVariant_sec1 Usage
* %PIVariant useful if you want pass many variables with different types in
* single array, e.g.:
* \code{cpp}
* PIVector<PIVariant> array;
* array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
* piCout << array;
* piForeachC (PIVariant & i, array)
* piCout << i.toInt();
* \endcode
* Result:
* \code{cpp}
* {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
* 10
* 1
* 1
* 255
* \endcode
* */
#ifdef CUSTOM_PIVARIANT
PIMap<PIString, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = 0;
#endif
PIVariant::PIVariant() {
_type = PIVariant::pivInvalid;
_info = 0;
}
PIVariant::PIVariant(const PIVariant &v) {
_type = v._type;
_content = v._content;
#ifdef CUSTOM_PIVARIANT
_info = v._info;
#endif
}
PIVariant & PIVariant::operator =(const PIVariant & v) {
_type = v._type;
_content = v._content;
#ifdef CUSTOM_PIVARIANT
_info = v._info;
#endif
return *this;
}
bool PIVariant::operator ==(const PIVariant & v) const {
return (_type == v._type) && (_content == v._content);
}
PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
PIString s = tname.trimmed().toLowerCase().replaceAll(" ", "");
if (s == "bool" || s == "boolean") return PIVariant::pivBool;
if (s == "char" || s == "sbyte") return PIVariant::pivChar;
if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword") return PIVariant::pivShort;
if (s == "int" || s == "signed" || s == "signedint") return PIVariant::pivInt;
if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::pivInt;
if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword") return PIVariant::pivLLong;
if (s == "uchar" || s == "byte") return PIVariant::pivUChar;
if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word") return PIVariant::pivUShort;
if (s == "uint" || s == "unsigned" || s == "unsignedint") return PIVariant::pivUInt;
if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::pivUInt;
if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword") return PIVariant::pivULLong;
if (s == "float") return PIVariant::pivFloat;
if (s == "double" || s == "real") return PIVariant::pivDouble;
if (s == "ldouble" || s == "longdouble") return PIVariant::pivLDouble;
if (s == "complexd" || s == "complex<double>") return PIVariant::pivComplexd;
if (s == "complexld" || s == "complex<ldouble>" || s == "complex<longdouble>") return PIVariant::pivComplexld;
if (s == "pibitarray" || s == "bitarray") return PIVariant::pivBitArray;
if (s == "pibytearray" || s == "bytearray" || s == "vector<uchar>" || s == "pivector<uchar>" || s == "vector<unsignedchar>" || s == "pivector<unsignedchar>" ||
s == "vector<char>" || s == "pivector<char>") return PIVariant::pivByteArray;
if (s == "pistring" || s == "string") return PIVariant::pivString;
if (s == "pistringlist" || s == "stringlist" || s == "vector<string>" || s == "vector<pistring>" || s == "pivector<string>" || s == "pivector<pistring>") return PIVariant::pivStringList;
if (s == "pitime" || s == "time") return PIVariant::pivTime;
if (s == "pidate" || s == "date") return PIVariant::pivDate;
if (s == "pidatetime" || s == "datetime") return PIVariant::pivDateTime;
if (s == "pisystemtime" || s == "systemtime") return PIVariant::pivSystemTime;
if (s == "enum") return PIVariant::pivEnum;
if (s == "file" || s == "path") return PIVariant::pivFile;
if (s == "dir" || s == "directory") return PIVariant::pivDir;
return PIVariant::pivInvalid;
}
PIString PIVariant::typeName() const {
#ifdef CUSTOM_PIVARIANT
if ((_type == pivCustom) && _info)
return _info->typeName;
#endif
return typeName(_type);
}
PIString PIVariant::typeName(PIVariant::Type type) {
switch (type) {
case PIVariant::pivBool: return "Bool";
case PIVariant::pivChar: return "Char";
case PIVariant::pivUChar: return "UChar";
case PIVariant::pivShort: return "Short";
case PIVariant::pivUShort: return "UShort";
case PIVariant::pivInt: return "Int";
case PIVariant::pivUInt: return "UInt";
case PIVariant::pivLLong: return "LLong";
case PIVariant::pivULLong: return "ULLong";
case PIVariant::pivFloat: return "Float";
case PIVariant::pivDouble: return "Double";
case PIVariant::pivLDouble: return "LDouble";
case PIVariant::pivComplexd: return "Complexd";
case PIVariant::pivComplexld: return "Complexld";
case PIVariant::pivBitArray: return "BitArray";
case PIVariant::pivByteArray: return "ByteArray";
case PIVariant::pivString: return "String";
case PIVariant::pivStringList: return "StringList";
case PIVariant::pivTime: return "Time";
case PIVariant::pivDate: return "Date";
case PIVariant::pivDateTime: return "DateTime";
case PIVariant::pivSystemTime: return "SystemTime";
case PIVariant::pivEnum: return "Enum";
case PIVariant::pivFile: return "File";
case PIVariant::pivDir: return "Dir";
case PIVariant::pivCustom: return "Custom";
default: break;
}
return "Invalid";
}
/** \brief Returns variant content as boolean
* \details In case of numeric types returns \b true if value != 0. \n
* In case of String type returns \a PIString::toBool(). \n
* In case of StringList type returns \b false if string list is empty,
* otherwise returns \a PIString::toBool() of first string. \n
* In case of other types returns \b false. */
bool PIVariant::toBool() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return r;}
case PIVariant::pivChar: {char r; ba >> r; return r != 0;}
case PIVariant::pivUChar: {uchar r; ba >> r; return r != 0;}
case PIVariant::pivShort: {short r; ba >> r; return r != 0;}
case PIVariant::pivUShort: {ushort r; ba >> r; return r != 0;}
case PIVariant::pivInt: {int r; ba >> r; return r != 0;}
case PIVariant::pivUInt: {uint r; ba >> r; return r != 0;}
case PIVariant::pivLLong: {llong r; ba >> r; return r != 0;}
case PIVariant::pivULLong: {ullong r; ba >> r; return r != 0;}
case PIVariant::pivFloat: {float r; ba >> r; return r > 0.f;}
case PIVariant::pivDouble: {double r; ba >> r; return r > 0.;}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return r > 0.;}
case PIVariant::pivString: {PIString r; ba >> r; return r.toBool();}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return false; return r.front().toBool();}
case PIVariant::pivCustom: return getAsValue<bool>(*this);
default: break;
}
return false;
}
/** \brief Returns variant content as int
* \details In case of numeric types returns integer value. \n
* In case of String type returns \a PIString::toInt(). \n
* In case of StringList type returns \b 0 if string list is empty,
* otherwise returns \a PIString::toInt() of first string. \n
* In case of other types returns \b 0. */
int PIVariant::toInt() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return r;}
case PIVariant::pivChar: {char r; ba >> r; return r;}
case PIVariant::pivUChar: {uchar r; ba >> r; return r;}
case PIVariant::pivShort: {short r; ba >> r; return r;}
case PIVariant::pivUShort: {ushort r; ba >> r; return r;}
case PIVariant::pivInt: {int r; ba >> r; return r;}
case PIVariant::pivUInt: {uint r; ba >> r; return r;}
case PIVariant::pivLLong: {llong r; ba >> r; return r;}
case PIVariant::pivULLong: {ullong r; ba >> r; return r;}
case PIVariant::pivFloat: {float r; ba >> r; return r;}
case PIVariant::pivDouble: {double r; ba >> r; return r;}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return r;}
case PIVariant::pivString: {PIString r; ba >> r; return r.toInt();}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0; return r.front().toInt();}
case PIVariant::pivEnum: {PIVariantTypes::Enum r; ba >> r; return r.selectedValue();}
case PIVariant::pivCustom: return getAsValue<int>(*this);
default: break;
}
return 0;
}
/** \brief Returns variant content as long long
* \details In case of numeric types returns integer value. \n
* In case of String type returns \a PIString::toLLong(). \n
* In case of StringList type returns \b 0L if string list is empty,
* otherwise returns \a PIString::toLLong() of first string. \n
* In case of other types returns \b 0L. */
llong PIVariant::toLLong() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return r;}
case PIVariant::pivChar: {char r; ba >> r; return r;}
case PIVariant::pivUChar: {uchar r; ba >> r; return r;}
case PIVariant::pivShort: {short r; ba >> r; return r;}
case PIVariant::pivUShort: {ushort r; ba >> r; return r;}
case PIVariant::pivInt: {int r; ba >> r; return r;}
case PIVariant::pivUInt: {uint r; ba >> r; return r;}
case PIVariant::pivLLong: {llong r; ba >> r; return r;}
case PIVariant::pivULLong: {ullong r; ba >> r; return r;}
case PIVariant::pivFloat: {float r; ba >> r; return r;}
case PIVariant::pivDouble: {double r; ba >> r; return r;}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return r;}
case PIVariant::pivString: {PIString r; ba >> r; return r.toLLong();}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0L; return r.front().toLLong();}
case PIVariant::pivEnum: {PIVariantTypes::Enum r; ba >> r; return llong(r.selectedValue());}
case PIVariant::pivCustom: return getAsValue<llong>(*this);
default: break;
}
return 0L;
}
/** \brief Returns variant content as float
* \details In case of numeric types returns float value. \n
* In case of String type returns \a PIString::toFloat(). \n
* In case of StringList type returns \b 0.f if string list is empty,
* otherwise returns \a PIString::toFloat() of first string. \n
* In case of other types returns \b 0.f. */
float PIVariant::toFloat() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return r;}
case PIVariant::pivChar: {char r; ba >> r; return r;}
case PIVariant::pivUChar: {uchar r; ba >> r; return r;}
case PIVariant::pivShort: {short r; ba >> r; return r;}
case PIVariant::pivUShort: {ushort r; ba >> r; return r;}
case PIVariant::pivInt: {int r; ba >> r; return r;}
case PIVariant::pivUInt: {uint r; ba >> r; return r;}
case PIVariant::pivLLong: {llong r; ba >> r; return r;}
case PIVariant::pivULLong: {ullong r; ba >> r; return r;}
case PIVariant::pivFloat: {float r; ba >> r; return r;}
case PIVariant::pivDouble: {double r; ba >> r; return r;}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return r;}
case PIVariant::pivString: {PIString r; ba >> r; return r.toFloat();}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0.f; return r.front().toFloat();}
case PIVariant::pivEnum: {PIVariantTypes::Enum r; ba >> r; return float(r.selectedValue());}
case PIVariant::pivCustom: return getAsValue<float>(*this);
default: break;
}
return 0.f;
}
/** \brief Returns variant content as double
* \details In case of numeric types returns double value. \n
* In case of String type returns \a PIString::toDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toDouble() of first string. \n
* In case of other types returns \b 0.. */
double PIVariant::toDouble() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return r;}
case PIVariant::pivChar: {char r; ba >> r; return r;}
case PIVariant::pivUChar: {uchar r; ba >> r; return r;}
case PIVariant::pivShort: {short r; ba >> r; return r;}
case PIVariant::pivUShort: {ushort r; ba >> r; return r;}
case PIVariant::pivInt: {int r; ba >> r; return r;}
case PIVariant::pivUInt: {uint r; ba >> r; return r;}
case PIVariant::pivLLong: {llong r; ba >> r; return r;}
case PIVariant::pivULLong: {ullong r; ba >> r; return r;}
case PIVariant::pivFloat: {float r; ba >> r; return r;}
case PIVariant::pivDouble: {double r; ba >> r; return r;}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return r;}
case PIVariant::pivString: {PIString r; ba >> r; return r.toDouble();}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0.; return r.front().toDouble();}
case PIVariant::pivEnum: {PIVariantTypes::Enum r; ba >> r; return double(r.selectedValue());}
case PIVariant::pivCustom: return getAsValue<double>(*this);
default: break;
}
return 0.;
}
/** \brief Returns variant content as long double
* \details In case of numeric types returns long double value. \n
* In case of String type returns \a PIString::toLDouble(). \n
* In case of StringList type returns \b 0. if string list is empty,
* otherwise returns \a PIString::toLDouble() of first string. \n
* In case of other types returns \b 0.. */
ldouble PIVariant::toLDouble() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return r;}
case PIVariant::pivChar: {char r; ba >> r; return r;}
case PIVariant::pivUChar: {uchar r; ba >> r; return r;}
case PIVariant::pivShort: {short r; ba >> r; return r;}
case PIVariant::pivUShort: {ushort r; ba >> r; return r;}
case PIVariant::pivInt: {int r; ba >> r; return r;}
case PIVariant::pivUInt: {uint r; ba >> r; return r;}
case PIVariant::pivLLong: {llong r; ba >> r; return r;}
case PIVariant::pivULLong: {ullong r; ba >> r; return r;}
case PIVariant::pivFloat: {float r; ba >> r; return r;}
case PIVariant::pivDouble: {double r; ba >> r; return r;}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return r;}
case PIVariant::pivString: {PIString r; ba >> r; return r.toLDouble();}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0.; return r.front().toLDouble();}
case PIVariant::pivEnum: {PIVariantTypes::Enum r; ba >> r; return ldouble(r.selectedValue());}
case PIVariant::pivCustom: return getAsValue<float>(*this);
default: break;
}
return 0.;
}
/** \brief Returns variant content as time
* \details In case of Time type returns time value. \n
* In case of DateTime type returns time part of value. \n
* In case of other types returns \a PITime(). */
PITime PIVariant::toTime() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivTime) {PITime r; ba >> r; return r;}
if (_type == PIVariant::pivDateTime) {PIDateTime r; ba >> r; return r.time();}
if (_type == PIVariant::pivCustom) {return getAsValue<PITime>(*this);}
return PITime();
}
/** \brief Returns variant content as date
* \details In case of Date type returns date value. \n
* In case of DateTime type returns date part of value. \n
* In case of other types returns \a PIDate(). */
PIDate PIVariant::toDate() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivDate) {PIDate r; ba >> r; return r;}
if (_type == PIVariant::pivDateTime) {PIDateTime r; ba >> r; return r.date();}
if (_type == PIVariant::pivCustom) {return getAsValue<PIDate>(*this);}
return PIDate();
}
/** \brief Returns variant content as date and time
* \details In case of Time type returns time value with null date. \n
* In case of Date type returns date value with null time. \n
* In case of DateTime type returns date and time. \n
* In case of other types returns \a PIDateTime(). */
PIDateTime PIVariant::toDateTime() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivTime) {PITime r; ba >> r; return PIDateTime(r);}
if (_type == PIVariant::pivDate) {PIDate r; ba >> r; return PIDateTime(r);}
if (_type == PIVariant::pivDateTime) {PIDateTime r; ba >> r; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PIDateTime>(*this);}
return PIDateTime();
}
/** \brief Returns variant content as system time
* \details In case of SystemTime type returns system time. \n
* In case of other types returns \a PISystemTime::fromSeconds() from
* double value of variant content. */
PISystemTime PIVariant::toSystemTime() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivSystemTime) {PISystemTime r; ba >> r; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PISystemTime>(*this);}
return PISystemTime::fromSeconds(toDouble());
}
/** \brief Returns variant content as string
* \details In case of numeric types returns \a PIString::fromNumber(). \n
* In case of String type returns string value. \n
* In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n
* In case of BitArray or ByteArray types returns number of bits/bytes. \n
* In case of Time, Date or DateTime types returns toString() of this values. \n
* In case of SystemTime types returns second and nanoseconds of time
* ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
* In case of other types returns \b "". */
PIString PIVariant::toString() const {
PIByteArray ba(_content);
switch (_type) {
case PIVariant::pivBool: {bool r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivChar: {char r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivUChar: {uchar r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivShort: {short r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivUShort: {ushort r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivInt: {int r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivUInt: {uint r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivLLong: {llong r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivULLong: {ullong r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivFloat: {float r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivDouble: {double r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivLDouble: {ldouble r; ba >> r; return PIString::fromNumber(r);}
case PIVariant::pivTime: {PITime r; ba >> r; return r.toString();}
case PIVariant::pivDate: {PIDate r; ba >> r; return r.toString();}
case PIVariant::pivDateTime: {PIDateTime r; ba >> r; return r.toString();}
case PIVariant::pivString: {PIString r; ba >> r; return r;}
case PIVariant::pivStringList: {PIStringList r; ba >> r; if (r.isEmpty()) return PIString(); return r.front();}
case PIVariant::pivEnum: {PIVariantTypes::Enum r; ba >> r; return r.selectedName();}
case PIVariant::pivFile: {PIVariantTypes::File r; ba >> r; return r.file;}
case PIVariant::pivDir: {PIVariantTypes::Dir r; ba >> r; return r.dir;}
case PIVariant::pivCustom: return getAsValue<PIString>(*this);
default: break;
}
return PIString();
}
/** \brief Returns variant content as strings list
* \details In case of StringList type returns strings list value. \n
* In case of other types returns \a PIStringList with one string value of variant content. */
PIStringList PIVariant::toStringList() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivStringList) {PIStringList r; ba >> r; return r;}
if (_type == PIVariant::pivEnum) {PIVariantTypes::Enum r; ba >> r; return r.names();}
if (_type == PIVariant::pivCustom) {return getAsValue<PIStringList>(*this);}
return PIStringList(toString());
}
/** \brief Returns variant content as bit array
* \details In case of BitArray type returns bit array value. \n
* In case of other types returns \a PIBitArray from \a toLLong() value. */
PIBitArray PIVariant::toBitArray() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivBitArray) {PIBitArray r; ba >> r; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PIBitArray>(*this);}
return PIBitArray(ullong(toLLong()));
}
/** \brief Returns variant content as byte array
* \details In case of ByteArray type returns byte array value. \n
* In case of other types returns empty \a PIByteArray. */
PIByteArray PIVariant::toByteArray() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivByteArray) {PIByteArray r; ba >> r; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PIByteArray>(*this);}
return PIByteArray();
}
/** \brief Returns variant content as enum
* \details In case of Enum type returns enum value. \n
* In case of String returns Enum with one member. \n
* In case of StringList returns Enum with corresponding members. \n
* In case of other types returns empty Enum. */
PIVariantTypes::Enum PIVariant::toEnum() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivEnum) {PIVariantTypes::Enum r; ba >> r; return r;}
if (_type == PIVariant::pivString) {PIString v; ba >> v; PIVariantTypes::Enum r; r << v; return r;}
if (_type == PIVariant::pivStringList) {PIStringList v; ba >> v; PIVariantTypes::Enum r; r << v; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PIVariantTypes::Enum>(*this);}
return PIVariantTypes::Enum();
}
/** \brief Returns variant content as file
* \details In case of File type returns file value. \n
* In case of String returns File with string value path. \n
* In case of other types returns empty Enum. */
PIVariantTypes::File PIVariant::toFile() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivFile) {PIVariantTypes::File r; ba >> r; return r;}
if (_type == PIVariant::pivString) {PIString v; ba >> v; PIVariantTypes::File r; r.file = v; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PIVariantTypes::File>(*this);}
return PIVariantTypes::File();
}
/** \brief Returns variant content as dir
* \details In case of Dir type returns dir value. \n
* In case of Dir returns Dir with string value path. \n
* In case of other types returns empty Enum. */
PIVariantTypes::Dir PIVariant::toDir() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivDir) {PIVariantTypes::Dir r; ba >> r; return r;}
if (_type == PIVariant::pivString) {PIString v; ba >> v; PIVariantTypes::Dir r; r.dir = v; return r;}
if (_type == PIVariant::pivCustom) {return getAsValue<PIVariantTypes::Dir>(*this);}
return PIVariantTypes::Dir();
}

693
src_main/core/pivariant.h Executable file
View File

@@ -0,0 +1,693 @@
/*! \file pivariant.h
* \brief Variant type
*
* This file declares PIVariant
*/
/*
PIP - Platform Independent Primitives
Variant type
Copyright (C) 2016 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIVARIANT_H
#define PIVARIANT_H
#include "pivarianttypes.h"
#include "pitime.h"
#ifndef QNX
# define CUSTOM_PIVARIANT
#endif
#ifdef CUSTOM_PIVARIANT
template<typename T>
class __PIVariantFunctions__ {
public:
static PIString typeNameHelper() {return PIStringAscii("");}
static bool isSimpleHelper() {return false;}
template<typename C> static PIByteArray castHelper(PIByteArray ba) {return PIByteArray();}
template<typename C> static C castVariant(const T & v) {return C();}
};
struct __PIVariantInfo__ {
__PIVariantInfo__() {
simple = false;
}
typedef PIByteArray(*castHelperFunc)(PIByteArray);
PIMap<PIString, castHelperFunc> cast;
PIString typeName;
bool simple;
};
class __PIVariantInfoStorage__ {
public:
__PIVariantInfoStorage__() {if (!map) map = new PIMap<PIString, __PIVariantInfo__ * >();}
static __PIVariantInfoStorage__ * get() {static __PIVariantInfoStorage__ * r = new __PIVariantInfoStorage__(); return r;}
static PIMap<PIString, __PIVariantInfo__ * > * map;
};
#define REGISTER_VARIANT_H(classname) \
template<> inline PIString __PIVariantFunctions__< classname >::typeNameHelper() {static PIString tn = PIStringAscii(#classname); return tn;}
#define REGISTER_NS_VARIANT_H(ns, classname) \
template<> inline PIString __PIVariantFunctions__< ns::classname >::typeNameHelper() {static PIString tn = PIStringAscii(#ns"::"#classname); return tn;}
#define REGISTER_VARIANT_CPP(classname) \
template <typename T> \
class __##classname##_PIVariantInitializer__ { \
public: \
__##classname##_PIVariantInitializer__(const PIString & name) { \
if (__PIVariantInfoStorage__::get()->map->contains(name)) \
return; \
__PIVariantInfo__ * vi = new __PIVariantInfo__(); \
vi->typeName = name; \
(*(__PIVariantInfoStorage__::get()->map))[name] = vi; \
} \
};
#define REGISTER_NS_VARIANT_CPP(ns, classname) \
template <typename T> \
class __##ns##classname##_PIVariantInitializer__ { \
public: \
__##ns##classname##_PIVariantInitializer__(const PIString & name) { \
if (__PIVariantInfoStorage__::get()->map->contains(name)) \
return; \
__PIVariantInfo__ * vi = new __PIVariantInfo__(); \
vi->typeName = name; \
(*(__PIVariantInfoStorage__::get()->map))[name] = vi; \
} \
};
#define INIT_VARIANT(classname) \
__##classname##_PIVariantInitializer__< classname > __##classname##_pivariant_initializer__(#classname);
#define INIT_NS_VARIANT(ns, classname) \
__##ns##classname##_PIVariantInitializer__< ns::classname > __##ns##classname##_pivariant_initializer__(#ns"::"#classname);
#define REGISTER_VARIANT(classname) \
REGISTER_VARIANT_H(classname) \
REGISTER_VARIANT_CPP(classname) \
static INIT_VARIANT(classname)
#define REGISTER_NS_VARIANT(ns, classname) \
REGISTER_NS_VARIANT_H(ns, classname) \
REGISTER_NS_VARIANT_CPP(ns, classname) \
static INIT_NS_VARIANT(ns, classname)
#define REGISTER_VARIANT_CAST_H(classname_from, classname_to) \
template<> template<> inline \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v);
#define REGISTER_VARIANT_CAST_CPP(classname_from, classname_to) \
template<> template<> inline \
PIByteArray __PIVariantFunctions__<classname_from>::castHelper<classname_to>(PIByteArray v) { \
classname_from f; v >> f; \
classname_to t = __PIVariantFunctions__<classname_from>::castVariant<classname_to>(f); \
PIByteArray ret; ret << t; \
return ret;} \
template <typename T, typename C> \
class __##classname_from##_##classname_to##_PIVariantCastInitializer__ { \
public: \
__##classname_from##_##classname_to##_PIVariantCastInitializer__(const PIString & name, const PIString & cname) { \
__PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(name, 0)); \
if (!vi) { \
piCout << "Warning! Using REGISTER_VARIANT_CAST("#classname_from", "#classname_to") before REGISTER_VARIANT("#classname_from"), ignore."; \
return; \
} \
vi->cast[cname] = __PIVariantFunctions__<classname_from>::castHelper<classname_to>; \
} \
}; \
static __##classname_from##_##classname_to##_PIVariantCastInitializer__< classname_from, classname_to > __##classname_from##_##classname_to##_pivariant_cast_initializer__(#classname_from, #classname_to); \
template<> template<> \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v)
#define REGISTER_VARIANT_CAST(classname_from, classname_to) \
REGISTER_VARIANT_CAST_H(classname_from, classname_to) \
REGISTER_VARIANT_CAST_CPP(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE(classname_from, classname_to) REGISTER_VARIANT_CAST(classname_from, classname_to) {return classname_to(v);}
#define REGISTER_VARIANT_CAST_SIMPLE_H(classname_from, classname_to) REGISTER_VARIANT_CAST_H(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE_CPP(classname_from, classname_to) REGISTER_VARIANT_CAST_CPP(classname_from, classname_to) {return classname_to(v);}
#else
#define REGISTER_VARIANT_H(classname)
#define REGISTER_VARIANT_CPP(classname)
#define INIT_VARIANT(classname)
#define REGISTER_VARIANT(classname)
#define REGISTER_NS_VARIANT_H(ns, classname)
#define REGISTER_NS_VARIANT_CPP(ns, classname)
#define INIT_NS_VARIANT(ns, classname)
#define REGISTER_NS_VARIANT(ns, classname)
#define REGISTER_VARIANT_CAST_H(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_CPP(classname_from, classname_to)
#define REGISTER_VARIANT_CAST(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE_H(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE_CPP(classname_from, classname_to)
#endif
class PIP_EXPORT PIVariant {
friend PICout operator <<(PICout s, const PIVariant & v);
friend PIByteArray & operator <<(PIByteArray & s, const PIVariant & v);
friend PIByteArray & operator >>(PIByteArray & s, PIVariant & v);
public:
//! Type of %PIVariant content
enum Type {
pivInvalid /** Invalid type , default type of empty contructor */ = 0 ,
pivBool /** bool */ ,
pivChar /** char */ ,
pivUChar /** uchar */ ,
pivShort /** short */ ,
pivUShort /** ushort */ ,
pivInt /** int */ ,
pivUInt /** uint */ ,
pivLLong /** llong */ ,
pivULLong /** ullong */ ,
pivFloat /** float */ ,
pivDouble /** double */ ,
pivLDouble /** ldouble */ ,
pivComplexd /** complexd */ ,
pivComplexld /** complexld */ ,
pivBitArray /** PIBitArray */ ,
pivByteArray /** PIByteArray */ ,
pivString /** PIString */ ,
pivStringList /** PIStringList */ ,
pivTime /** PITime */ ,
pivDate /** PIDate */ ,
pivDateTime /** PIDateTime */ ,
pivSystemTime /** PISystemTime */ ,
pivEnum /** PIVariantTypes::Enum */ ,
pivFile /** PIVariantTypes::File */ ,
pivDir /** PIVariantTypes::Dir */ ,
pivCustom /** Custom */ = 0xFF
};
//! Empty constructor, \a type() will be set to \a Invalid
PIVariant();
PIVariant(const PIVariant & v);
//! Constructs variant from string
PIVariant(const char * v) {initType(PIString(v));}
//! Constructs variant from boolean
PIVariant(const bool v) {initType(v);}
//! Constructs variant from char
PIVariant(const char v) {initType(v);}
//! Constructs variant from integer
PIVariant(const uchar v) {initType(v);}
//! Constructs variant from integer
PIVariant(const short v) {initType(v);}
//! Constructs variant from integer
PIVariant(const ushort v) {initType(v);}
//! Constructs variant from integer
PIVariant(const int & v) {initType(v);}
//! Constructs variant from integer
PIVariant(const uint & v) {initType(v);}
//! Constructs variant from integer
PIVariant(const llong & v) {initType(v);}
//! Constructs variant from integer
PIVariant(const ullong & v) {initType(v);}
//! Constructs variant from float
PIVariant(const float & v) {initType(v);}
//! Constructs variant from double
PIVariant(const double & v) {initType(v);}
//! Constructs variant from long double
PIVariant(const ldouble & v) {initType(v);}
//! Constructs variant from bit array
PIVariant(const PIBitArray & v) {initType(v);}
//! Constructs variant from byte array
PIVariant(const PIByteArray & v) {initType(v);}
//! Constructs variant from string
PIVariant(const PIString & v) {initType(v);}
//! Constructs variant from strings list
PIVariant(const PIStringList & v) {initType(v);}
//! Constructs variant from time
PIVariant(const PITime & v) {initType(v);}
//! Constructs variant from date
PIVariant(const PIDate & v) {initType(v);}
//! Constructs variant from date and time
PIVariant(const PIDateTime & v) {initType(v);}
//! Constructs variant from system time
PIVariant(const PISystemTime & v) {initType(v);}
//! Constructs variant from enum
PIVariant(const PIVariantTypes::Enum & v) {initType(v);}
//! Constructs variant from file
PIVariant(const PIVariantTypes::File & v) {initType(v);}
//! Constructs variant from dir
PIVariant(const PIVariantTypes::Dir & v) {initType(v);}
//! Set variant content and type to string
void setValue(const char * v) {setValue(PIString(v));}
//! Set variant content and type to boolean
void setValue(const bool v) {initType(v);}
//! Set variant content and type to char
void setValue(const char v) {initType(v);}
//! Set variant content and type to integer
void setValue(const uchar v) {initType(v);}
//! Set variant content and type to integer
void setValue(const short v) {initType(v);}
//! Set variant content and type to integer
void setValue(const ushort v) {initType(v);}
//! Set variant content and type to integer
void setValue(const int & v) {initType(v);}
//! Set variant content and type to integer
void setValue(const uint & v) {initType(v);}
//! Set variant content and type to integer
void setValue(const llong & v) {initType(v);}
//! Set variant content and type to integer
void setValue(const ullong & v) {initType(v);}
//! Set variant content and type to float
void setValue(const float & v) {initType(v);}
//! Set variant content and type to double
void setValue(const double & v) {initType(v);}
//! Set variant content and type to long double
void setValue(const ldouble & v) {initType(v);}
//! Set variant content and type to bit array
void setValue(const PIBitArray & v) {initType(v);}
//! Set variant content and type to byte array
void setValue(const PIByteArray & v) {initType(v);}
//! Set variant content and type to string
void setValue(const PIString & v) {initType(v);}
//! Set variant content and type to strings list
void setValue(const PIStringList & v) {initType(v);}
//! Set variant content and type to time
void setValue(const PITime & v) {initType(v);}
//! Set variant content and type to date
void setValue(const PIDate & v) {initType(v);}
//! Set variant content and type to date and time
void setValue(const PIDateTime & v) {initType(v);}
//! Set variant content and type to system time
void setValue(const PISystemTime & v) {initType(v);}
//! Set variant content and type to enum
void setValue(const PIVariantTypes::Enum & v) {initType(v);}
//! Set variant content and type to file
void setValue(const PIVariantTypes::File & v) {initType(v);}
//! Set variant content and type to dir
void setValue(const PIVariantTypes::Dir & v) {initType(v);}
bool toBool() const;
int toInt() const;
llong toLLong() const;
float toFloat() const;
double toDouble() const;
ldouble toLDouble() const;
PITime toTime() const;
PIDate toDate() const;
PIDateTime toDateTime() const;
PISystemTime toSystemTime() const;
PIString toString() const;
PIStringList toStringList() const;
PIBitArray toBitArray() const;
PIByteArray toByteArray() const;
PIVariantTypes::Enum toEnum() const;
PIVariantTypes::File toFile() const;
PIVariantTypes::Dir toDir() const;
/** \brief Returns variant content as custom type
* \details In case of known types this function equivalent \a to<Type> function. \n
* Otherwise returns content as type T. */
template<typename T>
T value() const {return getAsValue<T>(*this);}
/*
operator bool() const {return toBool();}
operator char() const {return toInt();}
operator uchar() const {return toInt();}
operator short() const {return toInt();}
operator ushort() const {return toInt();}
operator int() const {return toInt();}
operator uint() const {return toInt();}
operator long() const {return toInt();}
operator ulong() const {return toInt();}
operator llong() const {return toLLong();}
operator ullong() const {return (ullong)toLLong();}
operator float() const {return toFloat();}
operator double() const {return toDouble();}
operator ldouble() const {return toLDouble();}
operator PITime() const {return toTime();}
operator PIDate() const {return toDate();}
operator PIDateTime() const {return toDateTime();}
operator PIString() const {return toString();}
operator PIStringList() const {return toStringList();}
operator PIBitArray() const {return toBitArray();}
operator PIByteArray() const {return toByteArray();}
operator const char*() const {return toString().data();}
operator void*() const {return (void*)(toLLong());}
*/
//! Assign operator
PIVariant & operator =(const PIVariant & v);
//! Assign operator
PIVariant & operator =(const char * v) {setValue(PIString(v)); return *this;}
//! Assign operator
PIVariant & operator =(const bool v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const char v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const uchar v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const short v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ushort v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const int & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const uint & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const llong & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ullong & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const float & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const double & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const ldouble & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIBitArray & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIByteArray & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIString & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIStringList & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PITime & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIDate & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIDateTime & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PISystemTime & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIVariantTypes::Enum & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIVariantTypes::File & v) {setValue(v); return *this;}
//! Assign operator
PIVariant & operator =(const PIVariantTypes::Dir & v) {setValue(v); return *this;}
//! Compare operator
bool operator ==(const PIVariant & v) const;
//! Compare operator
bool operator !=(const PIVariant & v) const {return !(*this == v);}
//! Returns type of variant content
PIVariant::Type type() const {return _type;}
//! Returns type name of variant content
PIString typeName() const;
//! Returns \b true if type is not Invalid
bool isValid() const {return _type != PIVariant::pivInvalid;}
/** \brief Returns new variant from custom type
* \details In case of known types this function equivalent \a PIVariant(T) constructors. \n
* Otherwise returns variant with content \a v and type Custom. */
template <typename T>
static PIVariant fromValue(const T & v) {
PIVariant ret;
ret.initType<T>(v);
return ret;
}
static PIVariant fromValue(const PIByteArray & c, const PIString & type) {
PIVariant ret;
#ifdef CUSTOM_PIVARIANT
ret._info = __PIVariantInfoStorage__::get()->map->value(type, 0);
if (!ret._info) {
#endif
PIVariant::Type t = typeFromName(type);
if (t == pivInvalid) {
piCout << "Can`t initialize PIVariant from unregistered type \"" << type << "\"!";
return ret;
}
ret._type = t;
#ifdef CUSTOM_PIVARIANT
} else
ret._type = pivCustom;
#endif
ret._content = c;
return ret;
}
//! Returns type from name
static PIVariant::Type typeFromName(const PIString & tname);
//! Returns type name
static PIString typeName(PIVariant::Type type);
private:
void destroy() {_content.clear();}
template <typename T> inline static Type getType() {return pivCustom;}
template <typename T> inline void initType(const T & v) {
_content.clear();
_content << v;
_type = getType<T>();
#ifdef CUSTOM_PIVARIANT
if (_type == pivCustom) {
_info = __PIVariantInfoStorage__::get()->map->value(__PIVariantFunctions__<T>::typeNameHelper(), 0);
if (!_info)
piCout << "Can`t initialize PIVariant from unregistered type!";
} else
_info = 0;
#endif
}
template<typename T> inline static T getAsValue(const PIVariant & v) {
#ifdef CUSTOM_PIVARIANT
if (v._content.isEmpty() || !v._info) return T();
PIString cn = __PIVariantFunctions__<T>::typeNameHelper();
//piCout << "gav" << cn;
PIByteArray ba;
if (cn == v._info->typeName) {
ba = v._content;
} else {
__PIVariantInfo__::castHelperFunc cf = v._info->cast.value(cn);
//piCout << "gav cast" << cf;
if (!cf) return T();
ba = cf(v._content);
}
T ret; ba >> ret;
return ret;
#else
return T();
#endif
}
PIByteArray _content;
PIVariant::Type _type;
#ifdef CUSTOM_PIVARIANT
__PIVariantInfo__ * _info;
#endif
};
template<> inline bool PIVariant::value() const {return toBool();}
template<> inline char PIVariant::value() const {return (char)toInt();}
template<> inline uchar PIVariant::value() const {return (uchar)toInt();}
template<> inline short PIVariant::value() const {return (short)toInt();}
template<> inline ushort PIVariant::value() const {return (ushort)toInt();}
template<> inline int PIVariant::value() const {return toInt();}
template<> inline uint PIVariant::value() const {return (uint)toInt();}
template<> inline llong PIVariant::value() const {return toLLong();}
template<> inline ullong PIVariant::value() const {return (ullong)toLLong();}
template<> inline float PIVariant::value() const {return toFloat();}
template<> inline double PIVariant::value() const {return toDouble();}
template<> inline ldouble PIVariant::value() const {return toLDouble();}
template<> inline void* PIVariant::value() const {return (void*)toLLong();}
template<> inline const char* PIVariant::value() const {return toString().data();}
template<> inline PITime PIVariant::value() const {return toTime();}
template<> inline PIDate PIVariant::value() const {return toDate();}
template<> inline PIDateTime PIVariant::value() const {return toDateTime();}
template<> inline PIString PIVariant::value() const {return toString();}
template<> inline PIStringList PIVariant::value() const {return toStringList();}
template<> inline PIBitArray PIVariant::value() const {return toBitArray();}
template<> inline PIByteArray PIVariant::value() const {return toByteArray();}
template<> inline PIVariantTypes::Enum PIVariant::value() const {return toEnum();}
template<> inline PIVariantTypes::File PIVariant::value() const {return toFile();}
template<> inline PIVariantTypes::Dir PIVariant::value() const {return toDir();}
//template<> inline PIVariant PIVariant::fromValue(const char * v) {return PIVariant(PIString(v));}
template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const char & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const uchar & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const short & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const ushort & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const int & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const uint & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const llong & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const ullong & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const float & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const double & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const ldouble & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIBitArray & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIByteArray & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIString & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIStringList & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PITime & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIDate & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIDateTime & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PISystemTime & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::Enum & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::File & v) {return PIVariant(v);}
template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::Dir & v) {return PIVariant(v);}
template<> inline PIVariant::Type PIVariant::getType<bool>() {return PIVariant::pivBool;}
template<> inline PIVariant::Type PIVariant::getType<char>() {return PIVariant::pivChar;}
template<> inline PIVariant::Type PIVariant::getType<uchar>() {return PIVariant::pivUChar;}
template<> inline PIVariant::Type PIVariant::getType<short>() {return PIVariant::pivShort;}
template<> inline PIVariant::Type PIVariant::getType<ushort>() {return PIVariant::pivUShort;}
template<> inline PIVariant::Type PIVariant::getType<int>() {return PIVariant::pivInt;}
template<> inline PIVariant::Type PIVariant::getType<uint>() {return PIVariant::pivUInt;}
template<> inline PIVariant::Type PIVariant::getType<llong>() {return PIVariant::pivLLong;}
template<> inline PIVariant::Type PIVariant::getType<ullong>() {return PIVariant::pivULLong;}
template<> inline PIVariant::Type PIVariant::getType<float>() {return PIVariant::pivFloat;}
template<> inline PIVariant::Type PIVariant::getType<double>() {return PIVariant::pivDouble;}
template<> inline PIVariant::Type PIVariant::getType<ldouble>() {return PIVariant::pivLDouble;}
template<> inline PIVariant::Type PIVariant::getType<PIBitArray>() {return PIVariant::pivBitArray;}
template<> inline PIVariant::Type PIVariant::getType<PIByteArray>() {return PIVariant::pivByteArray;}
template<> inline PIVariant::Type PIVariant::getType<PIString>() {return PIVariant::pivString;}
template<> inline PIVariant::Type PIVariant::getType<PIStringList>() {return PIVariant::pivStringList;}
template<> inline PIVariant::Type PIVariant::getType<PITime>() {return PIVariant::pivTime;}
template<> inline PIVariant::Type PIVariant::getType<PIDate>() {return PIVariant::pivDate;}
template<> inline PIVariant::Type PIVariant::getType<PIDateTime>() {return PIVariant::pivDateTime;}
template<> inline PIVariant::Type PIVariant::getType<PISystemTime>() {return PIVariant::pivSystemTime;}
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::Enum>() {return PIVariant::pivEnum;}
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::File>() {return PIVariant::pivFile;}
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::Dir>() {return PIVariant::pivDir;}
REGISTER_VARIANT(bool)
REGISTER_VARIANT(char)
REGISTER_VARIANT(uchar)
REGISTER_VARIANT(short)
REGISTER_VARIANT(ushort)
REGISTER_VARIANT(int)
REGISTER_VARIANT(uint)
REGISTER_VARIANT(llong)
REGISTER_VARIANT(ullong)
REGISTER_VARIANT(float)
REGISTER_VARIANT(double)
REGISTER_VARIANT(ldouble)
REGISTER_VARIANT(PIBitArray)
REGISTER_VARIANT(PIByteArray)
REGISTER_VARIANT(PIString)
REGISTER_VARIANT(PIStringList)
REGISTER_VARIANT(PITime)
REGISTER_VARIANT(PIDate)
REGISTER_VARIANT(PIDateTime)
REGISTER_VARIANT(PISystemTime)
REGISTER_NS_VARIANT(PIVariantTypes, Enum)
REGISTER_NS_VARIANT(PIVariantTypes, File)
REGISTER_NS_VARIANT(PIVariantTypes, Dir)
inline PIByteArray & operator <<(PIByteArray & s, const PIVariant & v) {
s << v._content << int(v._type);
if (v._type == PIVariant::pivCustom) {
#ifdef CUSTOM_PIVARIANT
if (v._info) {
s << v._info->typeName;
} else {
s << PIStringAscii("");
}
#else
s << PIStringAscii("");
#endif
}
return s;
}
inline PIByteArray & operator >>(PIByteArray & s, PIVariant & v) {
int t(0);
s >> v._content >> t;
v._type = (PIVariant::Type)t;
if (v._type == PIVariant::pivCustom) {
PIString tn;
s >> tn;
#ifdef CUSTOM_PIVARIANT
PIByteArray vc = v._content;
v = PIVariant::fromValue(vc, tn);
#endif
}
return s;
}
inline PICout operator <<(PICout s, const PIVariant & v) {
s.space(); s.setControl(0, true);
s << "PIVariant(" << v.typeName() << ", " << v.toString() << ")";
s.restoreControl(); return s;
}
#endif // PIVARIANT_H

View File

@@ -0,0 +1,99 @@
/*
PIP - Platform Independent Primitives
Variant types
Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pivarianttypes.h"
int PIVariantTypes::Enum::selectedValue() const {
piForeachC (Enumerator & e, enum_list)
if (e.name == selected)
return e.value;
return 0;
}
bool PIVariantTypes::Enum::selectValue(int v) {
piForeachC (Enumerator & e, enum_list)
if (e.value == v) {
selected = e.name;
return true;
}
return false;
}
bool PIVariantTypes::Enum::selectName(const PIString & n) {
piForeachC (Enumerator & e, enum_list)
if (e.name == n) {
selected = e.name;
return true;
}
return false;
}
int PIVariantTypes::Enum::value(const PIString & n) const {
piForeachC (Enumerator & e, enum_list)
if (e.name == n)
return e.value;
return 0;
}
PIString PIVariantTypes::Enum::name(int v) const {
piForeachC (Enumerator & e, enum_list)
if (e.value == v)
return e.name;
return PIString();
}
PIVector<int> PIVariantTypes::Enum::values() const {
PIVector<int> ret;
piForeachC (Enumerator & e, enum_list)
ret << e.value;
return ret;
}
PIStringList PIVariantTypes::Enum::names() const {
PIStringList ret;
piForeachC (Enumerator & e, enum_list)
ret << e.name;
return ret;
}
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIVariantTypes::Enumerator & v) {
enum_list << v;
return *this;
}
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIString & v) {
enum_list << Enumerator(enum_list.size(), v);
return *this;
}
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIStringList & v) {
piForeachC (PIString & s, v)
(*this) << s;
return *this;
}

View File

@@ -0,0 +1,92 @@
/*! \file pivarianttypes.h
* \brief Variant type
*
* This file declares PIVariant
*/
/*
PIP - Platform Independent Primitives
Variant types
Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIVARIANTYPES_H
#define PIVARIANTYPES_H
#include "pistring.h"
namespace PIVariantTypes {
struct Enumerator {
Enumerator(int v = 0, const PIString & n = PIString()): value(v), name(n) {}
int value;
PIString name;
};
struct Enum {
Enum(const PIString & n = PIString()): enum_name(n) {}
PIString toString() const {return selected;} // obsolete
int selectedValue() const;
PIString selectedName() const {return selected;}
bool selectValue(int v);
bool selectName(const PIString & n);
int value(const PIString & n) const;
PIString name(int v) const;
PIVector<int> values() const;
PIStringList names() const;
PIString enum_name;
PIString selected;
PIVector<Enumerator> enum_list;
Enum & operator <<(const Enumerator & v);
Enum & operator <<(const PIString & v);
Enum & operator <<(const PIStringList & v);
};
struct File {
File(const PIString & p = PIString(), const PIString & f = PIString(), bool abs = false): file(p), filter(f), is_abs(abs) {}
PIString toString() const {return file;}
PIString file;
PIString filter;
bool is_abs;
};
struct Dir {
Dir(const PIString & d = PIString(), bool abs = false): dir(d), is_abs(abs) {}
PIString toString() const {return dir;}
PIString dir;
bool is_abs;
};
}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Enumerator & v) {s << v.value << v.name; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Enumerator & v) {s >> v.value >> v.name; return s;}
inline PICout operator <<(PICout s, const PIVariantTypes::Enumerator & v) {s << v.name << "(" << v.value << ")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Enum & v) {s << v.enum_name << v.selected << v.enum_list; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Enum & v) {s >> v.enum_name >> v.selected >> v.enum_list; return s;}
inline PICout operator <<(PICout s, const PIVariantTypes::Enum & v) {s << "Enum(" << v.selectedValue() << "=" << v.selectedName() << ")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::File & v) {s << v.file << v.filter << v.is_abs; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::File & v) {s >> v.file >> v.filter >> v.is_abs; return s;}
inline PICout operator <<(PICout s, const PIVariantTypes::File & v) {s << "File(\"" << v.file << "\")"; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Dir & v) {s << v.dir << v.is_abs; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Dir & v) {s >> v.dir >> v.is_abs; return s;}
inline PICout operator <<(PICout s, const PIVariantTypes::Dir & v) {s << "Dir(\"" << v.dir << "\")"; return s;}
#endif // PIVARIANTYPES_H