version 1.22.0
source tree changed detached PIConsole and PIScreen* in "pip_console" library
This commit is contained in:
557
lib/main/core/pibase.h
Normal file
557
lib/main/core/pibase.h
Normal file
@@ -0,0 +1,557 @@
|
||||
/*! \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
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIBASE_H
|
||||
#define PIBASE_H
|
||||
|
||||
#include "piversion.h"
|
||||
#include "piplatform.h"
|
||||
#include "pip_export.h"
|
||||
#include "pip_defs.h"
|
||||
#include "string.h"
|
||||
|
||||
//! Meta-information section for any entity.
|
||||
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
|
||||
//! Contains sequence of key=value pairs, e.g.
|
||||
//! PIMETA(id=12345,tag="my string")
|
||||
#define PIMETA(...)
|
||||
|
||||
#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
|
||||
|
||||
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
||||
# define PIP_VERSION
|
||||
|
||||
//! 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
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
# include <functional>
|
||||
#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")
|
||||
# ifdef ARCH_BITS_32
|
||||
# define _X86_
|
||||
# else
|
||||
# define _IA64_
|
||||
# endif
|
||||
# else
|
||||
# define SHUT_RDWR SD_BOTH
|
||||
# endif
|
||||
typedef int socklen_t;
|
||||
extern long long __pi_perf_freq;
|
||||
#endif
|
||||
|
||||
#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"
|
||||
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
||||
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
||||
# endif
|
||||
# endif
|
||||
# ifdef ANDROID
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
# pragma GCC diagnostic ignored "-Wextra"
|
||||
# pragma GCC diagnostic ignored "-Wc++11-extensions"
|
||||
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
|
||||
//# pragma GCC diagnostic ignored "-Wliteral-suffix"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CC_VC
|
||||
# undef DEPRECATED
|
||||
# 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__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \
|
||||
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
|
||||
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;}
|
||||
|
||||
#define PRIVATE (__privateinitializer__.p)
|
||||
#define PRIVATEWB __privateinitializer__.p
|
||||
|
||||
#define NO_COPY_CLASS(name) \
|
||||
explicit name(const name & ); \
|
||||
void operator =(const name & );
|
||||
|
||||
#ifdef FREERTOS
|
||||
# define PIP_MIN_MSLEEP 10.
|
||||
#else
|
||||
# define PIP_MIN_MSLEEP 1.
|
||||
#endif
|
||||
|
||||
|
||||
//! Macro used for infinite loop
|
||||
#define FOREVER for (;;)
|
||||
|
||||
//! Macro used for infinite wait
|
||||
#define FOREVER_WAIT FOREVER msleep(PIP_MIN_MSLEEP);
|
||||
|
||||
//! Macro used for infinite wait
|
||||
#define WAIT_FOREVER FOREVER msleep(PIP_MIN_MSLEEP);
|
||||
|
||||
|
||||
//! 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) {
|
||||
if ((size_t*)&f == (size_t*)&s) return;
|
||||
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
|
||||
size_t i = 0;
|
||||
for (i = 0; i < j; ++i) {
|
||||
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
|
||||
((size_t*)(&s))[i] ^= ((size_t*)(&f))[i];
|
||||
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
|
||||
}
|
||||
for (i = bs; i < bf; ++i) {
|
||||
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
|
||||
((uchar*)(&s))[i] ^= ((uchar*)(&f))[i];
|
||||
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<> inline void piSwapBinary(const void *& f, const void *& s) {
|
||||
if ((size_t*)f == (size_t*)s) return;
|
||||
size_t j = (sizeof(void *) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(void *);
|
||||
size_t i = 0;
|
||||
void * pf = const_cast<void*>(f), * ps = const_cast<void*>(s);
|
||||
for (i = 0; i < j; ++i) {
|
||||
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
|
||||
((size_t*)(&ps))[i] ^= ((size_t*)(&pf))[i];
|
||||
((size_t*)(&pf))[i] ^= ((size_t*)(&ps))[i];
|
||||
}
|
||||
for (i = bs; i < bf; ++i) {
|
||||
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
|
||||
((uchar*)(&ps))[i] ^= ((uchar*)(&pf))[i];
|
||||
((uchar*)(&pf))[i] ^= ((uchar*)(&ps))[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Function for compare two values without "=" by raw content
|
||||
* \details Example:\n \snippet piincludes.cpp compareBinary */
|
||||
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (((const uchar*)f)[i] != ((const uchar*)s)[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief 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
|
||||
|
||||
/// \brief Generic hash function, impements murmur3/32 algorithm
|
||||
inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
|
||||
if (!data || len <= 0) return 0u;
|
||||
uint h = seed;
|
||||
if (len > 3) {
|
||||
uint i = len >> 2;
|
||||
do {
|
||||
uint k;
|
||||
memcpy(&k, data, sizeof(uint));
|
||||
data += sizeof(uint);
|
||||
k *= 0xcc9e2d51;
|
||||
k = (k << 15) | (k >> 17);
|
||||
k *= 0x1b873593;
|
||||
h ^= k;
|
||||
h = (h << 13) | (h >> 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
} while (--i);
|
||||
}
|
||||
if (len & 3) {
|
||||
uint i = len & 3;
|
||||
uint k = 0;
|
||||
do {
|
||||
k <<= 8;
|
||||
k |= data[i - 1];
|
||||
} while (--i);
|
||||
k *= 0xcc9e2d51;
|
||||
k = (k << 15) | (k >> 17);
|
||||
k *= 0x1b873593;
|
||||
h ^= k;
|
||||
}
|
||||
h ^= len;
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
template<typename T> inline uint piHash(const T & v) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<> inline uint piHash(const char & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const uchar & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const short & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const ushort & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const int & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const uint & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const llong & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||
template<> inline uint piHash(const ullong & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||
template<> inline uint piHash(const float & v) {return (uint)v;}
|
||||
template<> inline uint piHash(const double & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||
template<> inline uint piHash(const ldouble & v) {return piHashData((const uchar *)&v, sizeof(v));}
|
||||
|
||||
#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
|
||||
44
lib/main/core/pibitarray.cpp
Normal file
44
lib/main/core/pibitarray.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Bit array
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
112
lib/main/core/pibitarray.h
Normal file
112
lib/main/core/pibitarray.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*! \file pibitarray.h
|
||||
* \brief Bit array
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Bit array
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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(const 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_;
|
||||
|
||||
};
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
//std::ostream & operator <<(std::ostream & s, const PIBitArray & ba);
|
||||
#endif
|
||||
|
||||
PICout operator <<(PICout s, const PIBitArray & ba);
|
||||
|
||||
#endif // PIBITARRAY_H
|
||||
403
lib/main/core/pibytearray.cpp
Normal file
403
lib/main/core/pibytearray.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Byte array
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pibytearray.h"
|
||||
#include "pistringlist.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;
|
||||
}
|
||||
|
||||
|
||||
uint PIByteArray::hash() const {
|
||||
return piHashData(data(), size_s());
|
||||
}
|
||||
|
||||
|
||||
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::fromUserInput(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;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {
|
||||
if (s.size_s() < 4) {
|
||||
s.clear();
|
||||
v.clear();
|
||||
return s;
|
||||
}
|
||||
assert(s.size_s() >= 4);
|
||||
int sz = 0;
|
||||
s >> sz;
|
||||
if (sz > s.size_s()) {
|
||||
piCout << "[PIByteArray] Warning: operator >> wants too much data, discard!" << sz << s.size_s();
|
||||
s.clear();
|
||||
v.clear();
|
||||
return s;
|
||||
}
|
||||
v.resize(sz);
|
||||
if (sz > 0) {
|
||||
memcpy(v.data(), s.data(), v.size());
|
||||
s.remove(0, v.size());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
321
lib/main/core/pibytearray.h
Normal file
321
lib/main/core/pibytearray.h
Normal file
@@ -0,0 +1,321 @@
|
||||
/*! \file pibytearray.h
|
||||
* \brief Byte array
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Byte array
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIBYTEARRAY_H
|
||||
#define PIBYTEARRAY_H
|
||||
|
||||
#include "pichar.h"
|
||||
#include "pibitarray.h"
|
||||
#include "pimap.h"
|
||||
#include "pivector2d.h"
|
||||
|
||||
__PICONTAINERS_SIMPLE_TYPE__(PIChar)
|
||||
|
||||
#define __PIBYTEARRAY_SIMPLE_TYPE__(T) \
|
||||
template<> \
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v._resizeRaw(sz); if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & v) {s << int(v.size_s()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {assert(s.size_s() >= 4); int sz; s >> sz; v._resizeRaw(sz); if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {s << int(v.rows()) << int(v.cols()); int os = s.size_s(); s.enlarge(v.size_s()*sizeof(T)); memcpy(s.data(os), v.data(), v.size_s()*sizeof(T)); return s;} \
|
||||
template<> \
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {assert(s.size_s() >= 8); int r, c; s >> r >> c; v._resizeRaw(r, c); int sz = r*c; if (sz > 0) memcpy(v.data(), s.data(), sz*sizeof(T)); s.remove(0, sz*sizeof(T)); return s;}
|
||||
|
||||
|
||||
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)) {}
|
||||
|
||||
//! Constructs byte array with size "size" filled by "t"
|
||||
PIByteArray(const uint size, uchar t): PIDeque<uchar>(size, t) {}
|
||||
|
||||
|
||||
//! 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(uint new_size) const {PIByteArray ret(new_size); memcpy(ret.data(), data(), new_size); return ret;}
|
||||
|
||||
//! 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;}
|
||||
|
||||
//! Add to the end "t"
|
||||
PIByteArray & append(uchar t) {push_back(t); return *this;}
|
||||
|
||||
//! Returns plain 8-bit checksum
|
||||
uchar checksumPlain8() const;
|
||||
|
||||
//! Returns plain 32-bit checksum
|
||||
uint checksumPlain32() const;
|
||||
|
||||
//! Returns hash
|
||||
uint hash() const;
|
||||
|
||||
void operator =(const PIDeque<uchar> & d) {resize(d.size()); memcpy(data(), d.data(), d.size());}
|
||||
|
||||
static PIByteArray fromUserInput(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();}
|
||||
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
//! \relatesalso PIByteArray \brief Output to std::ostream operator
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba);
|
||||
#endif
|
||||
|
||||
//! \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
|
||||
template<typename T> inline PIByteArray & operator <<(PIByteArray & s, const PIFlags<T> & 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((void*)(&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
|
||||
template<typename T> inline PIByteArray & operator >>(PIByteArray & s, PIFlags<T> & v) {PBA_OPERATOR_FROM return s;}
|
||||
//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details
|
||||
PIByteArray & operator >>(PIByteArray & s, PIByteArray & v);
|
||||
//! \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((void*)(v.d), s.data(), v.s); s.remove(0, v.s); return s;}
|
||||
|
||||
#undef PBA_OPERATOR_FROM
|
||||
|
||||
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 << int(v.pim_index[i].index) << v.pim_index[i].key;
|
||||
s << v.pim_content;
|
||||
return s;
|
||||
}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVector2D<T> & v) {s << int(v.rows()) << int(v.cols()) << v.toPlainVector(); 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);
|
||||
int ind = 0;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
s >> ind >> v.pim_index[i].key;
|
||||
v.pim_index[i].index = ind;
|
||||
}
|
||||
s >> v.pim_content;
|
||||
if (v.pim_content.size_s() != v.pim_index.size_s()) {
|
||||
piCout << "Warning: loaded invalid PIMap, clear";
|
||||
v.clear();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVector2D<T> & v) {assert(s.size_s() >= 8); int r,c; PIVector<T> tmp; s >> r >> c >> tmp; v = PIVector2D<T>(r, c, tmp); return s;}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const T & ) {piCout << "[PIByteArray] Warning: using undeclared operator <<!"; return s;}
|
||||
template<typename T>
|
||||
inline PIByteArray & operator >>(PIByteArray & s, T & ) {piCout << "[PIByteArray] Warning: using undeclared operator >>!"; return s;}
|
||||
|
||||
|
||||
//! \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;}
|
||||
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(bool)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(char)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(short)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ushort)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(int)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(uint)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(long)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ulong)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(llong)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ullong)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(float)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(double)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(ldouble)
|
||||
__PIBYTEARRAY_SIMPLE_TYPE__(PIChar)
|
||||
|
||||
|
||||
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
|
||||
|
||||
|
||||
#endif // PIBYTEARRAY_H
|
||||
393
lib/main/core/pichar.cpp
Normal file
393
lib/main/core/pichar.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
/*! \file pichar.h
|
||||
* \brief Unicode char
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Unicode char
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "pibytearray.h"
|
||||
#ifdef PIP_ICU
|
||||
# define U_NOEXCEPT
|
||||
# include "unicode/ucnv.h"
|
||||
# include "unicode/ustring.h"
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
# include <stringapiset.h>
|
||||
# include <winnls.h>
|
||||
#endif
|
||||
char * __syslocname__ = 0;
|
||||
char * __sysoemname__ = 0;
|
||||
char * __utf8name__ = 0;
|
||||
#ifdef BLACKBERRY
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
#ifdef ANDROID
|
||||
# if __ANDROID_API__ < 21
|
||||
# define wctomb(s, wc) wcrtomb(s, wc, NULL)
|
||||
# define mbtowc(pwc, s, n) mbrtowc(pwc, s, n, NULL)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*! \class PIChar
|
||||
* \brief Unicode char
|
||||
* \details This class is wrapper around \c "uint".
|
||||
* There are many contructors and information functions
|
||||
*/
|
||||
|
||||
|
||||
ushort charFromCodepage(const char * c, int size, const char * codepage, int * taken = 0) {
|
||||
if (!c || size <= 0) return 0;
|
||||
if (uchar(c[0]) < 0x80) return c[0];
|
||||
int ret;
|
||||
#ifdef PIP_ICU
|
||||
UErrorCode e((UErrorCode)0);
|
||||
UConverter * cc = ucnv_open(codepage, &e);
|
||||
if (cc) {
|
||||
UChar uc(0);
|
||||
e = (UErrorCode)0;
|
||||
ret = ucnv_toUChars(cc, &uc, 1, c, size, &e);
|
||||
//printf("PIChar %d -> %d\n", c[0], uc);
|
||||
if (taken) *taken = ret;
|
||||
ucnv_close(cc);
|
||||
return ushort(uc);
|
||||
}
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
wchar_t buffer;
|
||||
ret = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, size, &buffer, 1);
|
||||
if (ret <= 0) return 0;
|
||||
if (taken) *taken = ret;
|
||||
return buffer;
|
||||
# else
|
||||
wchar_t wc(0);
|
||||
mbtowc(0, 0, 0); // reset mbtowc
|
||||
ret = mbtowc(&wc, c, size);
|
||||
//printf("mbtowc = %d\n", ret);
|
||||
if (ret < 1) return 0;
|
||||
return ushort(int(wc));
|
||||
# endif
|
||||
#endif
|
||||
return ushort(c[0]);
|
||||
}
|
||||
|
||||
|
||||
int charCompare(const PIChar & f, const PIChar & s) {
|
||||
if (f.isAscii() && s.isAscii())
|
||||
return strncmp(f.toCharPtr(), s.toCharPtr(), 1);
|
||||
return
|
||||
#ifdef PIP_ICU
|
||||
u_strCompare((const UChar*)f.toWCharPtr(), 1, (const UChar*)s.toWCharPtr(), 1, FALSE);
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
CompareStringW(LOCALE_USER_DEFAULT, 0, (PCNZWCH)f.toWCharPtr(), 1, (PCNZWCH)s.toWCharPtr(), 1) - 2;
|
||||
# else
|
||||
wcsncmp((const wchar_t *)f.toWCharPtr(), (const wchar_t *)s.toWCharPtr(), 1);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool winIsCharType(const ushort * ch, int type) {
|
||||
#ifdef WINDOWS
|
||||
WORD attr = 0;
|
||||
if (GetStringTypeW(CT_CTYPE1, (LPCWCH)ch, 1, &attr) == 0) return false;
|
||||
return ((attr & type) == type);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIChar::PIChar(const char * c, int * bytes) {
|
||||
ch = charFromCodepage(c, 4, __syslocname__, bytes);
|
||||
}
|
||||
|
||||
|
||||
PIChar PIChar::fromConsole(char c) {
|
||||
PIChar ret;
|
||||
ret.ch = charFromCodepage(&c, 1, __sysoemname__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIChar PIChar::fromSystem(char c) {
|
||||
PIChar ret;
|
||||
ret.ch = charFromCodepage(&c, 1, __syslocname__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIChar PIChar::fromUTF8(const char * c) {
|
||||
PIChar ret;
|
||||
int l = 0;
|
||||
while (c[l] != '\0') ++l;
|
||||
ret.ch = charFromCodepage(c, l, __utf8name__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::operator ==(const PIChar & o) const {
|
||||
return ch == o.ch;
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::operator >(const PIChar & o) const {
|
||||
return charCompare(*this, o) > 0;
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::operator <(const PIChar & o) const {
|
||||
return charCompare(*this, o) < 0;
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::operator >=(const PIChar & o) const {
|
||||
return charCompare(*this, o) >= 0;
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::operator <=(const PIChar & o) const {
|
||||
return charCompare(*this, o) <= 0;
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isDigit() const {
|
||||
if (isAscii()) return isdigit(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_DIGIT);
|
||||
#else
|
||||
return iswdigit(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isHex() const {
|
||||
if (isAscii()) return isxdigit(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_XDIGIT);
|
||||
#else
|
||||
return iswxdigit(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isGraphical() const {
|
||||
if (isAscii()) return isgraph(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return !winIsCharType(&ch, C1_CNTRL);
|
||||
#else
|
||||
return iswgraph(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isControl() const {
|
||||
if (isAscii()) return iscntrl(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_CNTRL);
|
||||
#else
|
||||
return iswcntrl(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isLower() const {
|
||||
if (isAscii()) return islower(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_LOWER);
|
||||
#else
|
||||
return iswlower(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isUpper() const {
|
||||
if (isAscii()) return isupper(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_UPPER);
|
||||
#else
|
||||
return iswupper(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isPrint() const {
|
||||
if (isAscii()) return isprint(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return !winIsCharType(&ch, C1_CNTRL);
|
||||
#else
|
||||
return iswprint(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isSpace() const {
|
||||
if (isAscii()) return isspace(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_SPACE);
|
||||
#else
|
||||
return iswspace(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PIChar::isAlpha() const {
|
||||
if (isAscii()) return isalpha(ch) != 0;
|
||||
#ifdef WINDOWS
|
||||
return winIsCharType(&ch, C1_ALPHA);
|
||||
#else
|
||||
return iswalpha(ch) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
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::toConsole1Byte() 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
|
||||
#ifdef WINDOWS
|
||||
char ret[4] = {0,0,0,0};
|
||||
WideCharToMultiByte(CP_OEMCP, 0, (LPCWCH)&ch, 1, ret, 4, NULL, NULL);
|
||||
return ret[0];
|
||||
#endif
|
||||
return toAscii();
|
||||
}
|
||||
|
||||
|
||||
char PIChar::toSystem() const {
|
||||
if (ch < 0x80) return ch;
|
||||
#ifdef PIP_ICU
|
||||
UErrorCode e((UErrorCode)0);
|
||||
UConverter * cc = ucnv_open(__syslocname__, &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
|
||||
#ifdef WINDOWS
|
||||
char ret[4] = {0,0,0,0};
|
||||
WideCharToMultiByte(CP_ACP, 0, (LPCWCH)&ch, 1, ret, 4, NULL, NULL);
|
||||
return ret[0];
|
||||
#endif
|
||||
return toAscii();
|
||||
}
|
||||
|
||||
|
||||
PIChar PIChar::toUpper() const {
|
||||
if (isAscii()) return PIChar(toupper(ch));
|
||||
#ifdef PIP_ICU
|
||||
UChar c(0);
|
||||
UErrorCode e((UErrorCode)0);
|
||||
u_strToUpper(&c, 1, (const UChar*)(&ch), 1, 0, &e);
|
||||
return PIChar(c);
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
ushort wc = 0;
|
||||
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1)
|
||||
return PIChar(wc);
|
||||
# endif
|
||||
#endif
|
||||
return PIChar(towupper(ch));
|
||||
}
|
||||
|
||||
|
||||
PIChar PIChar::toLower() const {
|
||||
if (isAscii()) return PIChar(tolower(ch));
|
||||
#ifdef PIP_ICU
|
||||
UChar c(0);
|
||||
UErrorCode e((UErrorCode)0);
|
||||
u_strToLower(&c, 1, (const UChar*)(&ch), 1, 0, &e);
|
||||
return PIChar(c);
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
ushort wc = 0;
|
||||
if (LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, (LPCWSTR)&ch, 1, (LPWSTR)&wc, 1) == 1)
|
||||
return PIChar(wc);
|
||||
# endif
|
||||
#endif
|
||||
return PIChar(towlower(ch));
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIChar & v) {
|
||||
s.space();
|
||||
s.setControl(0, true);
|
||||
if (v.isAscii()) s << char(v.ch);
|
||||
else {
|
||||
#ifdef PIP_ICU
|
||||
UErrorCode e((UErrorCode)0);
|
||||
UConverter * cc = ucnv_open(__syslocname__, &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
|
||||
#ifdef WINDOWS
|
||||
s << v.toSystem();
|
||||
#else
|
||||
{
|
||||
char tc[8];
|
||||
wctomb(0, 0);
|
||||
int sz = wctomb(tc, v.ch);
|
||||
for (int b = 0; b < sz; ++b)
|
||||
s << tc[b];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
s.restoreControl();
|
||||
return s;
|
||||
}
|
||||
187
lib/main/core/pichar.h
Normal file
187
lib/main/core/pichar.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/*! \file pichar.h
|
||||
* \brief Unicode char
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Unicode char
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PICHAR_H
|
||||
#define PICHAR_H
|
||||
|
||||
#include "piincludes.h"
|
||||
|
||||
extern char * __syslocname__;
|
||||
extern char * __sysoemname__;
|
||||
extern char * __utf8name__;
|
||||
|
||||
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);
|
||||
|
||||
//! Copy operator
|
||||
PIChar & operator =(const char v) {ch = v; return *this;}
|
||||
|
||||
//! Compare operator
|
||||
bool operator ==(const PIChar & o) const;
|
||||
|
||||
//! Compare operator
|
||||
bool operator !=(const PIChar & o) const {return !(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 toConsole1Byte() const;
|
||||
char toSystem() 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 \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
|
||||
148
lib/main/core/pichunkstream.cpp
Normal file
148
lib/main/core/pichunkstream.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Binary markup serializator
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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();
|
||||
}
|
||||
|
||||
|
||||
int PIChunkStream::read() {
|
||||
switch (version_) {
|
||||
case Version_1:
|
||||
(*data_) >> last_id >> last_data;
|
||||
break;
|
||||
case Version_2:
|
||||
last_id = readVInt(*data_);
|
||||
last_data.resize(readVInt(*data_));
|
||||
//piCout << last_id << last_data.size();
|
||||
(*data_) >> PIByteArray::RawData(last_data.data(), last_data.size_s());
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return last_id;
|
||||
}
|
||||
|
||||
|
||||
void PIChunkStream::readAll() {
|
||||
data_map.clear();
|
||||
while (!atEnd()) {
|
||||
read();
|
||||
data_map[last_id] = last_data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PIChunkStream::~PIChunkStream() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PIChunkStream::_init() {
|
||||
last_id = -1;
|
||||
last_data.clear();
|
||||
if (!data_->isEmpty()) {
|
||||
uchar v = data_->at(0);
|
||||
if ((v & 0x80) == 0x80) {
|
||||
v &= 0x7f;
|
||||
switch (v) {
|
||||
case 2: version_ = (uchar)Version_2; data_->pop_front(); break;
|
||||
default: version_ = Version_1; break;
|
||||
}
|
||||
} else
|
||||
version_ = Version_1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint PIChunkStream::readVInt(PIByteArray & s) {
|
||||
if (s.isEmpty()) return 0;
|
||||
uchar bytes[4]; s >> bytes[0];
|
||||
uchar abc = 0;
|
||||
for (abc = 0; abc < 3; ++abc) {
|
||||
uchar mask = (0x80 >> abc);
|
||||
if ((bytes[0] & mask) == mask) {
|
||||
bytes[0] &= (mask - 1);
|
||||
s >> bytes[abc + 1];
|
||||
} else break;
|
||||
}
|
||||
uint ret = 0;
|
||||
for (int i = 0; i <= abc; ++i) {
|
||||
ret += (bytes[i] << (8 * ((int)abc - i)));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PIChunkStream::writeVInt(PIByteArray & s, uint val) {
|
||||
if (val > 0xfffffff) return;
|
||||
if (val <= 0x7f) {
|
||||
s << uchar(val);
|
||||
return;
|
||||
}
|
||||
if (val <= 0x3fff) {
|
||||
s << uchar((val >> 8) | 0x80) << uchar(val & 0xff);
|
||||
return;
|
||||
}
|
||||
if (val <= 0x1fffff) {
|
||||
s << uchar((val >> 16) | 0xc0) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
||||
return;
|
||||
}
|
||||
s << uchar((val >> 24) | 0xe0) << uchar((val >> 16) & 0xff) << uchar((val >> 8) & 0xff) << uchar(val & 0xff);
|
||||
}
|
||||
137
lib/main/core/pichunkstream.h
Normal file
137
lib/main/core/pichunkstream.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*! \file pichunkstream.h
|
||||
* \brief Binary markup serializator
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Binary markup serializator
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PICHUNKSTREAM_H
|
||||
#define PICHUNKSTREAM_H
|
||||
|
||||
#include "pibytearray.h"
|
||||
|
||||
|
||||
class PIP_EXPORT PIChunkStream
|
||||
{
|
||||
public:
|
||||
|
||||
//! Version of data packing. Read-access %PIChunkStream automatic detect version, but write-access
|
||||
//! %PIChunkStream by default write in new version, be careful!
|
||||
enum Version {
|
||||
Version_1 /*! First, old version */,
|
||||
Version_2 /*! Second, more optimized version */ = 2,
|
||||
};
|
||||
|
||||
//! Contructs stream for read from "data"
|
||||
PIChunkStream(const PIByteArray & data): version_(Version_2) {setSource(data);}
|
||||
|
||||
//! Contructs stream for read or write to/from "data", or empty stream for write
|
||||
PIChunkStream(PIByteArray * data = 0, Version v = Version_2): version_(v) {setSource(data);}
|
||||
|
||||
//! Contructs empty stream for write with version \"v\"
|
||||
PIChunkStream(Version v): version_(v) {setSource(0);}
|
||||
|
||||
~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);}
|
||||
|
||||
//! Add data to this chunk strean with ID "id" and value "data"
|
||||
template <typename T> PIChunkStream & add(int id, const T & data) {*this << Chunk<T>(id, data); return *this;}
|
||||
|
||||
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_->size_s() <= 1;}
|
||||
|
||||
//! Returns stream version
|
||||
Version version() const {return (Version)version_;}
|
||||
|
||||
|
||||
//! Read one chunk from stream and returns its ID
|
||||
int read();
|
||||
|
||||
//! Read all chunks from stream
|
||||
void readAll();
|
||||
|
||||
//! 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>();}
|
||||
|
||||
//! Place value of chunk with id \"id\" into \"v\". You should call \a readAll() before using this function!
|
||||
template <typename T>
|
||||
const PIChunkStream & get(int id, T & v) const {
|
||||
PIByteArray ba = data_map.value(id);
|
||||
if (!ba.isEmpty())
|
||||
ba >> v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void _init();
|
||||
|
||||
static uint readVInt(PIByteArray & s);
|
||||
static void writeVInt(PIByteArray & s, uint val);
|
||||
|
||||
int last_id;
|
||||
uchar version_;
|
||||
PIByteArray * data_, last_data, tmp_data;
|
||||
PIMap<int, PIByteArray> data_map;
|
||||
|
||||
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;
|
||||
switch (s.version_) {
|
||||
case PIChunkStream::Version_1:
|
||||
(*(s.data_)) << c.id << ba;
|
||||
break;
|
||||
case PIChunkStream::Version_2:
|
||||
if (s.data_->isEmpty())
|
||||
(*(s.data_)) << uchar(uchar(s.version_) | 0x80);
|
||||
PIChunkStream::writeVInt(*(s.data_), c.id);
|
||||
PIChunkStream::writeVInt(*(s.data_), ba.size());
|
||||
s.data_->append(ba);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // PICHUNKSTREAM_H
|
||||
101
lib/main/core/picli.cpp
Normal file
101
lib/main/core/picli.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Command-Line Parser
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 != '\0') && (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
lib/main/core/picli.h
Normal file
101
lib/main/core/picli.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*! \file picli.h
|
||||
* \brief Command-Line parser
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Command-Line Parser
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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
|
||||
84
lib/main/core/picollection.cpp
Normal file
84
lib/main/core/picollection.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Peer - named I/O ethernet node, forming self-organized peering network
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
PIVector<PICollection::Group> & cg(_groups());
|
||||
piForeachC (Group & g, cg)
|
||||
sl << g.name;
|
||||
return sl;
|
||||
}
|
||||
|
||||
|
||||
PIVector<const PIObject * > PICollection::groupElements(const PIString & group) {
|
||||
PIVector<PICollection::Group> & cg(_groups());
|
||||
piForeachC (Group & g, cg)
|
||||
if (g.name == group)
|
||||
return g.elements;
|
||||
return PIVector<const PIObject * >();
|
||||
}
|
||||
|
||||
|
||||
bool PICollection::addToGroup(const PIString & group, const PIObject * element) {
|
||||
//piCout << "add to" << group << element;
|
||||
PIString n = PIStringAscii(element->className());
|
||||
PIVector<PICollection::Group> & cg(_groups());
|
||||
piForeach (Group & g, cg)
|
||||
if (g.name == group) {
|
||||
for (int i = 0; i < g.elements.size_s(); ++i)
|
||||
if (PIString(g.elements[i]->className()) == n)
|
||||
return false;
|
||||
g.elements << element;
|
||||
//piCout << "new group" << group << ", ok";
|
||||
return true;
|
||||
}
|
||||
_groups() << Group(group);
|
||||
_groups().back().elements << element;
|
||||
//piCout << "new group" << group << ", ok";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PIVector<PICollection::Group> & PICollection::_groups() {
|
||||
static PIVector<PICollection::Group> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name, bool own) {
|
||||
if (!element) return;
|
||||
const_cast<PIObject * >(element)->setName(name);
|
||||
bool added = PICollection::addToGroup(group, element);
|
||||
if (!added && own)
|
||||
delete element;
|
||||
}
|
||||
83
lib/main/core/picollection.h
Normal file
83
lib/main/core/picollection.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*! \file picollection.h
|
||||
* \brief Custom elements collection
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Peer - named I/O ethernet node, forming self-organized peering network
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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, false);
|
||||
# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object, #name, false);
|
||||
# define ADD_NEW_TO_COLLECTION(group, class) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class(), true);
|
||||
# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class(), #name, true);
|
||||
#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 bool addToGroup(const PIString & group, const PIObject * element);
|
||||
|
||||
class CollectionAdder {
|
||||
public:
|
||||
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false);
|
||||
};
|
||||
|
||||
protected:
|
||||
struct Group {
|
||||
Group(const PIString & name_ = PIString()) {name = name_;}
|
||||
PIString name;
|
||||
PIVector<const PIObject * > elements;
|
||||
};
|
||||
|
||||
static PIVector<Group> & _groups();
|
||||
|
||||
};
|
||||
|
||||
#endif // PICOLLECTION_H
|
||||
30
lib/main/core/picoremodule.h
Normal file
30
lib/main/core/picoremodule.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Module includes
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PICOREMODULE_H
|
||||
#define PICOREMODULE_H
|
||||
|
||||
#include "picollection.h"
|
||||
#include "piobject.h"
|
||||
#include "pitime.h"
|
||||
#include "picli.h"
|
||||
#include "pichunkstream.h"
|
||||
#include "pipropertystorage.h"
|
||||
|
||||
#endif // PICOREMODULE_H
|
||||
548
lib/main/core/picout.cpp
Normal file
548
lib/main/core/picout.cpp
Normal file
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Universal output to console class
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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
|
||||
*/
|
||||
|
||||
|
||||
/*! \class PICout::Notifier
|
||||
* \brief Class for emit notifications of PICout
|
||||
*
|
||||
* \section PICout_sec0 Synopsis
|
||||
* This class used as PICout events emitter. When
|
||||
* PICout constructs with external PIString* buffer
|
||||
* and some id, last copy of this PICout on delete
|
||||
* emit event "finished()" on object Notifier::object().
|
||||
* Sample:
|
||||
* \snippet picout.cpp notifier
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
class NotifierObject: public PIObject {
|
||||
PIOBJECT(NotifierObject)
|
||||
public:
|
||||
NotifierObject() {}
|
||||
EVENT2(finished, int, id, PIString*, buffer)
|
||||
};
|
||||
|
||||
|
||||
|
||||
PICout::Notifier::Notifier() {
|
||||
o = new NotifierObject();
|
||||
}
|
||||
|
||||
|
||||
PICout::Notifier * PICout::Notifier::instance() {
|
||||
static PICout::Notifier * ret = new PICout::Notifier();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIObject * PICout::Notifier::object() {
|
||||
return instance()->o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
PIMutex & PICout::__mutex__() {static PIMutex * ret = new PIMutex(); return *ret;}
|
||||
PIString & PICout::__string__() {static PIString * ret = new PIString(); return *ret;}
|
||||
|
||||
PICout::OutputDevices PICout::devs = PICout::StdOut;
|
||||
|
||||
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), act_(true), cnb_(10), co_(controls) {
|
||||
init();
|
||||
}
|
||||
|
||||
PICout::PICout(PICoutControl control): fo_(true), cc_(false), fc_(false), act_(true), cnb_(10), co_(control) {
|
||||
init();
|
||||
}
|
||||
|
||||
PICout::PICout(bool active): fo_(true), cc_(false), fc_(false), act_(active), cnb_(10), co_(PICoutManipulators::DefaultControls) {
|
||||
if (act_)
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
PICout::PICout(PIString * buffer, int id, PIFlags<PICoutManipulators::PICoutControl> controls): fo_(true), cc_(false),
|
||||
fc_(false), act_(true), cnb_(10), co_(controls) {
|
||||
init();
|
||||
buffer_ = buffer;
|
||||
id_ = id;
|
||||
}
|
||||
|
||||
|
||||
PICout::PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), act_(other.act_), cnb_(other.cnb_), attr_(other.attr_),
|
||||
id_(other.id_), buffer_(other.buffer_), co_(other.co_) {
|
||||
}
|
||||
|
||||
|
||||
PICout::~PICout() {
|
||||
if (!act_) return;
|
||||
if (fc_) applyFormat(PICoutManipulators::Default);
|
||||
if (cc_) return;
|
||||
newLine();
|
||||
if ((co_ & NoLock) != NoLock)
|
||||
PICout::__mutex__().unlock();
|
||||
if (buffer_)
|
||||
((NotifierObject*)Notifier::object())->finished(id_, buffer_);
|
||||
}
|
||||
|
||||
|
||||
PICout PICout::operator <<(const PICoutAction v) {
|
||||
if (!act_) return *this;
|
||||
#ifdef WINDOWS
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||
COORD coord;
|
||||
CONSOLE_CURSOR_INFO curinfo;
|
||||
#endif
|
||||
switch (v) {
|
||||
case PICoutManipulators::Flush:
|
||||
if (!buffer_ && isOutputDeviceActive(StdOut))
|
||||
std::cout << std::flush;
|
||||
break;
|
||||
case PICoutManipulators::Backspace:
|
||||
if (isOutputDeviceActive(StdOut)) {
|
||||
#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 (isOutputDeviceActive(StdOut)) {
|
||||
#ifdef WINDOWS
|
||||
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
curinfo.bVisible = true;
|
||||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
#else
|
||||
printf("\e[?25h");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PICoutManipulators::HideCursor:
|
||||
if (isOutputDeviceActive(StdOut)) {
|
||||
#ifdef WINDOWS
|
||||
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
curinfo.bVisible = false;
|
||||
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
|
||||
#else
|
||||
printf("\e[?25l");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PICoutManipulators::ClearLine:
|
||||
if (isOutputDeviceActive(StdOut)) {
|
||||
#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 (isOutputDeviceActive(StdOut)) {
|
||||
#ifdef WINDOWS
|
||||
/// TODO : wondows ClearScreen !!!
|
||||
#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 (buffer_) {\
|
||||
(*buffer_) << (v);\
|
||||
} else {\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v);\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
}\
|
||||
}
|
||||
#define PICOUTTOTARGETS(v) { \
|
||||
if (buffer_) {\
|
||||
(*buffer_) << (v);\
|
||||
} else {\
|
||||
if (PICout::isOutputDeviceActive(PICout::StdOut)) std::cout << (v).dataConsole();\
|
||||
if (PICout::isOutputDeviceActive(PICout::Buffer)) PICout::__string__() << (v);\
|
||||
}\
|
||||
}
|
||||
#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGETS(PIString::fromNumber(v, cnb_))
|
||||
|
||||
|
||||
PICout PICout::operator <<(const char * v) {if (!act_) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
|
||||
|
||||
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}
|
||||
|
||||
PICout PICout::operator <<(const char v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const uchar v) {if (!act_) return *this; space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGETS(PIString::fromNumber(v, cnb_)) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const short int v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const ushort v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const int v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const uint v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const long v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const ulong v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const llong v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const ullong v) {if (!act_) return *this; space(); PINUMERICCOUT return *this;}
|
||||
|
||||
PICout PICout::operator <<(const float v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const double v) {if (!act_) return *this; space(); PICOUTTOTARGET(v) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const void * v) {if (!act_) return *this; space(); PICOUTTOTARGET("0x") PICOUTTOTARGETS(PIString::fromNumber(ullong(v), 16)) return *this;}
|
||||
|
||||
PICout PICout::operator <<(const PIObject * v) {
|
||||
if (!act_) return *this;
|
||||
space();
|
||||
if (v == 0) PICOUTTOTARGET("PIObject*(0x0)")
|
||||
else {
|
||||
PICOUTTOTARGET(v->className())
|
||||
PICOUTTOTARGET("*(0x")
|
||||
PICOUTTOTARGETS(PIString::fromNumber(ullong(v), 16))
|
||||
PICOUTTOTARGET(", \"")
|
||||
PICOUTTOTARGET(v->name())
|
||||
PICOUTTOTARGET("\")")
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
PICout PICout::operator <<(const PICoutSpecialChar v) {
|
||||
if (!act_) return *this;
|
||||
switch (v) {
|
||||
case Null:
|
||||
if (buffer_) {
|
||||
(*buffer_) << PIChar(0);
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << char(0);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar(0);
|
||||
}
|
||||
break;
|
||||
case NewLine:
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\n";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '\n';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
|
||||
}
|
||||
fo_ = true;
|
||||
break;
|
||||
case Tab:
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\t";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '\t';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\t";
|
||||
}
|
||||
break;
|
||||
case Esc:
|
||||
#ifdef CC_VC
|
||||
if (buffer_) {
|
||||
(*buffer_) << PIChar(27);
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << char(27);
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << PIChar(27);
|
||||
}
|
||||
#else
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\e";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '\e';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\e";
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case Quote:
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\"";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
|
||||
}
|
||||
break;
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PICout & PICout::saveControl() {
|
||||
if (!act_) return *this;
|
||||
PRIVATE->cos_.push(co_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PICout & PICout::restoreControl() {
|
||||
if (!act_) return *this;
|
||||
if (!PRIVATE->cos_.isEmpty()) {
|
||||
co_ = PRIVATE->cos_.top();
|
||||
PRIVATE->cos_.pop();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#undef PICOUTTOTARGET
|
||||
#undef PINUMERICCOUT
|
||||
|
||||
PICout & PICout::space() {
|
||||
if (!act_) return *this;
|
||||
if (!fo_ && co_[AddSpaces]) {
|
||||
if (buffer_) {
|
||||
(*buffer_) << " ";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << ' ';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << " ";
|
||||
}
|
||||
}
|
||||
fo_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PICout & PICout::quote() {
|
||||
if (!act_) return *this;
|
||||
if (co_[AddQuotes]) {
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\"";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << '"';
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\"";
|
||||
}
|
||||
}
|
||||
fo_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PICout & PICout::newLine() {
|
||||
if (!act_) return *this;
|
||||
if (co_[AddNewLine]) {
|
||||
if (buffer_) {
|
||||
(*buffer_) << "\n";
|
||||
} else {
|
||||
if (isOutputDeviceActive(StdOut)) std::cout << std::endl;
|
||||
if (isOutputDeviceActive(Buffer)) PICout::__string__() << "\n";
|
||||
}
|
||||
}
|
||||
fo_ = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void PICout::init() {
|
||||
#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
|
||||
buffer_ = 0;
|
||||
id_ = 0;
|
||||
if ((co_ & NoLock) != NoLock)
|
||||
PICout::__mutex__().lock();
|
||||
}
|
||||
|
||||
|
||||
void PICout::applyFormat(PICoutFormat f) {
|
||||
if (!act_) return;
|
||||
if (buffer_ || !isOutputDeviceActive(StdOut)) 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 = isBufferActive();
|
||||
if (clear) PICout::__string__().clear();
|
||||
setOutputDevice(Buffer, on);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool PICout::isBufferActive() {
|
||||
return isOutputDeviceActive(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();
|
||||
}
|
||||
|
||||
|
||||
bool PICout::setOutputDevice(PICout::OutputDevice d, bool on) {
|
||||
bool ret = devs[d];
|
||||
devs.setFlag(d, on);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PICout::setOutputDevices(PICout::OutputDevices d) {
|
||||
devs = d;
|
||||
}
|
||||
|
||||
|
||||
bool PICout::isOutputDeviceActive(PICout::OutputDevice d) {
|
||||
return devs[d];
|
||||
}
|
||||
301
lib/main/core/picout.h
Normal file
301
lib/main/core/picout.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/*! \file picout.h
|
||||
* \brief Universal output to console class
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Universal output to console class
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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 PICout(piDebug)
|
||||
# define piCoutObj PICout(piDebug && debug()) << (PIStringAscii("[") + className() + PIStringAscii(" \"") + name() + PIStringAscii("\"]"))
|
||||
#endif
|
||||
|
||||
|
||||
class PIObject;
|
||||
|
||||
|
||||
//! \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,
|
||||
DefaultControls /*! Default controls */ = AddSpaces | AddNewLine,
|
||||
AddAll /*! All controls */ = 0xFF,
|
||||
NoLock /*! Don`t use mutex for output */ = 0x100,
|
||||
};
|
||||
|
||||
//! \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)
|
||||
PICout(PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::DefaultControls);
|
||||
PICout(PICoutManipulators::PICoutControl control = PICoutManipulators::DefaultControls);
|
||||
|
||||
//! Construct with default features (AddSpaces and AddNewLine), but if \"active\" is false does nothing
|
||||
PICout(bool active);
|
||||
|
||||
//! Construct with external buffer and id "id". See \a Notifier for details
|
||||
PICout(PIString * buffer, int id = 0, PIFlags<PICoutManipulators::PICoutControl> controls = PICoutManipulators::AddSpaces | PICoutManipulators::AddNewLine);
|
||||
|
||||
PICout(const PICout & other);
|
||||
|
||||
~PICout();
|
||||
|
||||
class Notifier {
|
||||
public:
|
||||
static Notifier * instance();
|
||||
static PIObject * object();
|
||||
private:
|
||||
Notifier();
|
||||
PIObject * o;
|
||||
};
|
||||
|
||||
//! \brief Enum contains output devices of PICout
|
||||
enum OutputDevice {
|
||||
NoDevices /** PICout is disabled */ = 0x0,
|
||||
StdOut /** Standard console output */ = 0x1,
|
||||
Buffer /** Internal buffer */ = 0x2,
|
||||
AllDevices /** All */ = 0xFFFF,
|
||||
};
|
||||
|
||||
typedef PIFlags<OutputDevice> OutputDevices;
|
||||
|
||||
//! 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();
|
||||
|
||||
static bool setOutputDevice(OutputDevice d, bool on = true);
|
||||
static void setOutputDevices(OutputDevices d);
|
||||
static bool isOutputDeviceActive(OutputDevice d);
|
||||
|
||||
static PIMutex & __mutex__();
|
||||
static PIString & __string__();
|
||||
|
||||
private:
|
||||
void init();
|
||||
void applyFormat(PICoutManipulators::PICoutFormat f);
|
||||
|
||||
static OutputDevices devs;
|
||||
PRIVATE_DECLARATION
|
||||
bool fo_, cc_, fc_, act_;
|
||||
int cnb_, attr_, id_;
|
||||
PIString * buffer_;
|
||||
PICoutManipulators::PICoutControls co_;
|
||||
};
|
||||
|
||||
#endif // PICOUT_H
|
||||
137
lib/main/core/piflags.h
Normal file
137
lib/main/core/piflags.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*! \file piflags.h
|
||||
* \brief General flags class
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
General flags class
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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
|
||||
266
lib/main/core/piincludes.cpp
Normal file
266
lib/main/core/piincludes.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Global includes
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
PINtQueryTimerResolution getTimerResolutionAddr = 0;
|
||||
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 = PIStringAscii(PIP_VERSION_NAME);
|
||||
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)
|
||||
* * multithreading
|
||||
* * thread (\a PIThread)
|
||||
* * executor (\a PIThreadPoolExecutor)
|
||||
* * blocking dequeue (\a PIBlockingDequeue)
|
||||
* * 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();
|
||||
}
|
||||
|
||||
56
lib/main/core/piincludes.h
Normal file
56
lib/main/core/piincludes.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Minimal PIP includes
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIINCLUDES_H
|
||||
#define PIINCLUDES_H
|
||||
|
||||
#include "pibase.h"
|
||||
#include "piflags.h"
|
||||
#include <sys/types.h>
|
||||
#ifdef PIP_STD_IOSTREAM
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
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>" */
|
||||
PIP_EXPORT PIString errorString();
|
||||
|
||||
PIP_EXPORT void errorClear();
|
||||
|
||||
PIP_EXPORT void piqsort(void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
|
||||
|
||||
PIP_EXPORT void randomize();
|
||||
PIP_EXPORT int randomi();
|
||||
|
||||
/// Return readable version of PIP
|
||||
PIP_EXPORT PIString PIPVersion();
|
||||
|
||||
#endif // PIINCLUDES_H
|
||||
45
lib/main/core/piincludes_p.h
Normal file
45
lib/main/core/piincludes_p.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Private PIP includes
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PIINCLUDES_P_H
|
||||
#define PIINCLUDES_P_H
|
||||
|
||||
|
||||
#include "picout.h"
|
||||
#ifdef WINDOWS
|
||||
# include <stdarg.h>
|
||||
# include <windef.h>
|
||||
# include <winbase.h>
|
||||
typedef LONG(NTAPI*PINtQueryTimerResolution)(PULONG, PULONG, PULONG);
|
||||
typedef LONG(NTAPI*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
|
||||
417
lib/main/core/piinit.cpp
Normal file
417
lib/main/core/piinit.cpp
Normal file
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Initialization
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "piinit.h"
|
||||
#include "pitime.h"
|
||||
#include "pisignals.h"
|
||||
#include "piobject.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "piresourcesstorage.h"
|
||||
#include "pidir.h"
|
||||
#ifndef FREERTOS
|
||||
# include "piprocess.h"
|
||||
#endif
|
||||
#ifdef ESP_PLATFORM
|
||||
# include "esp_system.h"
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
# include <winsock2.h>
|
||||
extern FILETIME __pi_ftjan1970;
|
||||
extern PINtQueryTimerResolution getTimerResolutionAddr;
|
||||
extern PINtSetTimerResolution setTimerResolutionAddr;
|
||||
void __PISetTimerResolution() {
|
||||
if (setTimerResolutionAddr == NULL || getTimerResolutionAddr == NULL)
|
||||
return;
|
||||
ULONG _max(0), _min(0), _cur(0);
|
||||
//printf("getTimerResolution ...\n");
|
||||
LONG q = getTimerResolutionAddr(&_max, &_min, &_cur);
|
||||
//printf("getTimerResolution %d %lu %lu %lu\n", q, _min, _max, _cur);
|
||||
if (q == 0)
|
||||
setTimerResolutionAddr(_min, TRUE, &_cur);
|
||||
//printf("setTimerResolution %lu\n", cur);
|
||||
}
|
||||
#else
|
||||
# include <pwd.h>
|
||||
# ifndef FREERTOS
|
||||
# include <sys/utsname.h>
|
||||
# endif
|
||||
# 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>
|
||||
extern clock_serv_t __pi_mac_clock;
|
||||
#endif
|
||||
#ifdef PIP_ICU
|
||||
# define U_NOEXCEPT
|
||||
# include <unicode/uclean.h>
|
||||
# include <unicode/ucnv.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAS_LOCALE
|
||||
static locale_t currentLocale_t = 0;
|
||||
#endif
|
||||
|
||||
PRIVATE_DEFINITION_START(PIInit)
|
||||
#ifdef WINDOWS
|
||||
HMODULE ntlib;
|
||||
ULONG prev_res;
|
||||
#endif
|
||||
bool delete_locs;
|
||||
PRIVATE_DEFINITION_END(PIInit)
|
||||
|
||||
#ifndef FREERTOS
|
||||
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()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#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 FREERTOS
|
||||
#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) {
|
||||
getTimerResolutionAddr = (PINtQueryTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtQueryTimerResolution");
|
||||
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
|
||||
__PISetTimerResolution();
|
||||
}
|
||||
# endif
|
||||
# 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
|
||||
PRIVATE->delete_locs = false;
|
||||
__syslocname__ = __sysoemname__ = 0;
|
||||
__utf8name__ = const_cast<char*>("UTF-8");
|
||||
#ifdef PIP_ICU
|
||||
UErrorCode e((UErrorCode)0);
|
||||
u_init(&e);
|
||||
# ifdef WINDOWS
|
||||
PRIVATE->delete_locs = true;
|
||||
CPINFOEX cpinfo;
|
||||
int l = 0;
|
||||
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);
|
||||
# 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__;
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
__syslocname__ = (char *)CP_ACP;
|
||||
__sysoemname__ = (char *)CP_OEMCP;
|
||||
__utf8name__ = (char *)CP_UTF8;
|
||||
# endif
|
||||
#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("x86_64"); 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
|
||||
#endif
|
||||
#ifdef ESP_PLATFORM
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
sinfo->processorsCount = chip_info.cores;
|
||||
sinfo->architecture = "Xtensa LX6";
|
||||
//printf("silicon revision %d, ", chip_info.revision);
|
||||
sinfo->OS_version = esp_get_idf_version();
|
||||
#endif
|
||||
sinfo->OS_name =
|
||||
#ifdef WINDOWS
|
||||
PIStringAscii("Windows");
|
||||
#elif defined(QNX)
|
||||
PIStringAscii("QNX");
|
||||
#elif defined(MAC_OS)
|
||||
PIStringAscii("MacOS");
|
||||
#elif defined(ANDROID)
|
||||
PIStringAscii("Android");
|
||||
#elif defined(FREE_BSD)
|
||||
PIStringAscii("FreeBSD");
|
||||
#elif defined(FREERTOS)
|
||||
PIStringAscii("FreeRTOS");
|
||||
#else
|
||||
uns.sysname;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PIInit::~PIInit() {
|
||||
if (file_charset) delete file_charset;
|
||||
file_charset = 0;
|
||||
PIResourcesStorage::instance()->clear();
|
||||
#ifdef WINDOWS
|
||||
WSACleanup();
|
||||
if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib);
|
||||
PRIVATE->ntlib = 0;
|
||||
#endif
|
||||
#ifdef MAC_OS
|
||||
mach_port_deallocate(mach_task_self(), __pi_mac_clock);
|
||||
#endif
|
||||
if (PRIVATE->delete_locs) {
|
||||
if (__syslocname__) delete __syslocname__;
|
||||
if (__sysoemname__) delete __sysoemname__;
|
||||
}
|
||||
#ifdef PIP_ICU
|
||||
u_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
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 Crypt: return
|
||||
#ifdef PIP_CRYPT
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Introspection: return
|
||||
#ifdef PIP_INTROSPECTION
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case FFTW: return
|
||||
#ifdef PIP_FFTW
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Compress: return
|
||||
#ifdef PIP_COMPRESS
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case OpenCL: return
|
||||
#ifdef PIP_OPENCL
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
case Cloud: return
|
||||
#ifdef PIP_CLOUD
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
default: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PIStringList PIInit::buildOptions() {
|
||||
PIStringList ret;
|
||||
if (isBuildOptionEnabled(ICU)) ret << "ICU";
|
||||
if (isBuildOptionEnabled(USB)) ret << "USB";
|
||||
if (isBuildOptionEnabled(Crypt)) ret << "Crypt";
|
||||
if (isBuildOptionEnabled(Introspection)) ret << "Introspection";
|
||||
if (isBuildOptionEnabled(FFTW)) ret << "FFTW";
|
||||
if (isBuildOptionEnabled(Compress)) ret << "Compress";
|
||||
if (isBuildOptionEnabled(OpenCL)) ret << "OpenCL";
|
||||
if (isBuildOptionEnabled(Cloud)) ret << "Cloud";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
73
lib/main/core/piinit.h
Normal file
73
lib/main/core/piinit.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*! \file piinit.h
|
||||
* \brief Initialization
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Initialization
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIINIT_H
|
||||
#define PIINIT_H
|
||||
|
||||
#include "piincludes.h"
|
||||
|
||||
|
||||
class PIFile;
|
||||
class PIStringList;
|
||||
|
||||
|
||||
class PIP_EXPORT __PIInit_Initializer__ {
|
||||
public:
|
||||
__PIInit_Initializer__();
|
||||
~__PIInit_Initializer__();
|
||||
static int count_;
|
||||
static PIInit * __instance__;
|
||||
};
|
||||
|
||||
|
||||
class PIP_EXPORT PIInit {
|
||||
friend class __PIInit_Initializer__;
|
||||
friend class PIFile;
|
||||
public:
|
||||
~PIInit();
|
||||
|
||||
//! \brief Build options which PIP library was built
|
||||
enum BuildOption {
|
||||
ICU /*! Unicode support */ = 0x01,
|
||||
USB /*! USB support */ = 0x02,
|
||||
Crypt /*! Crypt support */ = 0x08,
|
||||
Introspection /*! Introspection */ = 0x010,
|
||||
FFTW /*! FFTW3 support */ = 0x40,
|
||||
Compress /*! Zlib compression support */ = 0x80,
|
||||
OpenCL /*! OpenCL support */ = 0x100,
|
||||
Cloud /*! Cloud transport support */ = 0x200,
|
||||
};
|
||||
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
|
||||
static bool isBuildOptionEnabled(BuildOption o);
|
||||
static PIStringList buildOptions();
|
||||
private:
|
||||
explicit PIInit();
|
||||
void setFileCharset(const char *charset);
|
||||
bool fileExists(const PIString & p);
|
||||
PRIVATE_DECLARATION
|
||||
char * file_charset;
|
||||
};
|
||||
|
||||
static __PIInit_Initializer__ __piinit_initializer__;
|
||||
|
||||
|
||||
#endif // PIINIT_H
|
||||
676
lib/main/core/piobject.cpp
Normal file
676
lib/main/core/piobject.cpp
Normal file
@@ -0,0 +1,676 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piobject.h"
|
||||
#include "pisysteminfo.h"
|
||||
#ifndef FREERTOS
|
||||
# include "pifile.h"
|
||||
#endif
|
||||
|
||||
/** \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
|
||||
*/
|
||||
|
||||
|
||||
PIString PIObject::__MetaFunc::arguments() const {
|
||||
return types.join(",");
|
||||
}
|
||||
|
||||
|
||||
PIString PIObject::__MetaFunc::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), proc_event_queue(false) {
|
||||
setName(name);
|
||||
setDebug(true);
|
||||
mutexObjects().lock();
|
||||
objects() << this;
|
||||
mutexObjects().unlock();
|
||||
//piCout << "new" << this;
|
||||
}
|
||||
|
||||
|
||||
PIObject::~PIObject() {
|
||||
//piCout << "delete" << this;
|
||||
mutexObjects().lock();
|
||||
objects().removeAll(this);
|
||||
mutexObjects().unlock();
|
||||
piDisconnect(this);
|
||||
}
|
||||
|
||||
PIMap<PIString, PIVariant> PIObject::properties() const {
|
||||
PIMap<PIString, PIVariant> ret;
|
||||
piForeachC (PropertyHash p, properties_)
|
||||
ret[p.second.first] = p.second.second;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool PIObject::execute(const PIString & method, const PIVector<PIVariant> & vl) {
|
||||
if (method.isEmpty()) return false;
|
||||
if (!isPIObject()) {
|
||||
piCout << "Error: \"execute(" << method << ")\":" << (void*)this << "is not PIObject!";
|
||||
return false;
|
||||
}
|
||||
int ac = 0;
|
||||
__MetaFunc func;
|
||||
bool ok = findSuitableMethodV(method, vl.size_s(), ac, func);
|
||||
if (!ok)
|
||||
return false;
|
||||
callAddrV(func.addrV, toThis(), ac, vl);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl) {
|
||||
if (!isPIObject()) {
|
||||
piCout << "Error: \"executeQueued(" << method << ")\": this(" << (void*)this << ") is not PIObject!";
|
||||
return false;
|
||||
}
|
||||
if (!performer->isPIObject()) {
|
||||
piCout << "Error: \"executeQueued(" << method << ")\": performer(" << (void*)performer << ") is not PIObject!";
|
||||
return false;
|
||||
}
|
||||
int ac = 0;
|
||||
__MetaFunc func;
|
||||
bool ok = findSuitableMethodV(method, vl.size_s(), ac, func);
|
||||
if (!ok)
|
||||
return false;
|
||||
performer->postQueuedEvent(__QueuedEvent(func.addrV, toThis(), this, performer, vl));
|
||||
performer->proc_event_queue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
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::scopeList() const {
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
return __meta_data()[classNameID()].scope_list;
|
||||
}
|
||||
|
||||
|
||||
PIStringList PIObject::methodsEH() const {
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
PIStringList ret;
|
||||
__MetaData & ehd(__meta_data()[classNameID()]);
|
||||
piForeachC (__EHPair & eh, ehd.eh_func)
|
||||
ret << eh.second.fullFormat();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::isMethodEHContains(const PIString & name) const {
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
__MetaData & ehd(__meta_data()[classNameID()]);
|
||||
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(__meta_mutex());
|
||||
__MetaData & ehd(__meta_data()[classNameID()]);
|
||||
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(__meta_mutex());
|
||||
__MetaData & ehd(__meta_data()[classNameID()]);
|
||||
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::__MetaFunc> PIObject::findEH(const PIString & name) const {
|
||||
PIVector<__MetaFunc> ret;
|
||||
__MetaData & ehd(__meta_data()[classNameID()]);
|
||||
piForeachC (__EHPair & eh, ehd.eh_func)
|
||||
if (eh.second.func_name == name)
|
||||
ret << eh.second;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIObject::__MetaFunc PIObject::methodEH(const void * addr) const {
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
return __meta_data()[classNameID()].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 & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) {
|
||||
if (src == 0 || dest_o == 0 || dest == 0) return false;
|
||||
if (!src->isPIObject()) {
|
||||
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")";
|
||||
return false;
|
||||
}
|
||||
if (!dest_o->isPIObject()) {
|
||||
piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")";
|
||||
return false;
|
||||
}
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
PIMutexLocker mls(src->mutex_connect);
|
||||
PIMutexLocker mld(dest_o->mutex_connect, src != dest_o);
|
||||
PIVector<__MetaFunc> m_src = src->findEH(sig), m_dest = dest_o->findEH(hname);
|
||||
if (m_src.isEmpty()) {
|
||||
piCout << "[piConnectU] Error: can`t find event \"" << sig << "\" 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);
|
||||
bool que = (performer != 0);
|
||||
piForeachC (__MetaFunc & fs, m_src) {
|
||||
if (addr_src != 0) break;
|
||||
piForeachC (__MetaFunc & fd, m_dest) {
|
||||
if (addr_src != 0) break;
|
||||
if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) {
|
||||
addr_src = fs.addr;
|
||||
addr_dest = que ? fd.addrV : fd.addr;
|
||||
args = fd.names.size_s();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addr_src == 0) {
|
||||
piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << sig << "\" in class \"" << src->className()
|
||||
<< "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")";
|
||||
return false;
|
||||
}
|
||||
src->connections << PIObject::__Connection(addr_dest, addr_src, sig, dest_o, dest, args, performer);
|
||||
if (que) performer->proc_event_queue = true;
|
||||
dest_o->connectors << src;
|
||||
//piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc) {
|
||||
if (src == 0) {
|
||||
delete f;
|
||||
return false;
|
||||
}
|
||||
if (!src->isPIObject()) {
|
||||
piCout << "[piConnectLS] \"" << sig << "\" -> [lambda] error: source object is not PIObject! (" << loc << ")";
|
||||
delete f;
|
||||
return false;
|
||||
}
|
||||
PIMutexLocker ml(__meta_mutex());
|
||||
PIMutexLocker mls(src->mutex_connect);
|
||||
//piCout << "locked";
|
||||
PIVector<__MetaFunc> m_src = src->findEH(sig);
|
||||
if (m_src.isEmpty()) {
|
||||
piCout << "[piConnectLS] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
|
||||
delete f;
|
||||
return false;
|
||||
}
|
||||
if (m_src.size() != 1) {
|
||||
piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")";
|
||||
delete f;
|
||||
return false;
|
||||
}
|
||||
PIObject::__Connection conn(0, m_src[0].addr, sig);
|
||||
//piCout << "found";
|
||||
conn.functor = f;
|
||||
src->connections << conn;
|
||||
//piCout << "finished";
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
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[i].destroy();
|
||||
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[i].destroy();
|
||||
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;
|
||||
if (!dest) {
|
||||
src->connections[i].destroy();
|
||||
src->connections.remove(i);
|
||||
i--;
|
||||
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS)
|
||||
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) {
|
||||
//piCout << "disconnect"<< src->className()<< o->className();
|
||||
if (!o || (o == src)) continue;
|
||||
if (!o->isPIObject()) continue;
|
||||
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS)
|
||||
PIMutexLocker _mld(o->mutex_connect, src != o);
|
||||
#endif
|
||||
PIVector<__Connection> & oc(o->connections);
|
||||
for (int i = 0; i < oc.size_s(); ++i) {
|
||||
if (oc[i].functor) continue;
|
||||
//piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src);
|
||||
if (oc[i].dest_o == src) {
|
||||
oc[i].destroy();
|
||||
oc.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
piForeachC (PIObject::__Connection & c, src->connections) {
|
||||
if (c.functor) continue;
|
||||
if (!c.dest_o) continue;
|
||||
if (!c.dest_o->isPIObject()) continue;
|
||||
c.dest_o->connectors.remove(src);
|
||||
}
|
||||
for (int i = 0; i < src->connections.size_s(); ++i)
|
||||
src->connections[i].destroy();
|
||||
src->connections.clear();
|
||||
}
|
||||
|
||||
|
||||
void PIObject::updateConnectors() {
|
||||
//piCout << "*** updateConnectors" << this;
|
||||
connectors.clear();
|
||||
PIMutexLocker _ml(mutexObjects());
|
||||
piForeach (PIObject * o, objects()) {
|
||||
if (o == this) continue;
|
||||
PIVector<__Connection> & oc(o->connections);
|
||||
piForeach (__Connection & c, oc)
|
||||
if (c.dest == this)
|
||||
connectors << o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIObject::postQueuedEvent(const PIObject::__QueuedEvent & e) {
|
||||
mutex_queue.lock();
|
||||
events_queue << e;
|
||||
mutex_queue.unlock();
|
||||
}
|
||||
|
||||
|
||||
void * PIObject::toThis() const {
|
||||
//piCout << ptrOffset() << (void*)this << (void*)((char*)this - ptrOffset());
|
||||
return (void*)((char*)this - ptrOffset());
|
||||
}
|
||||
|
||||
|
||||
PIMutex & PIObject::__meta_mutex() {
|
||||
static PIMutex ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIMap<uint, PIObject::__MetaData> & PIObject::__meta_data() {
|
||||
static PIMap<uint, PIObject::__MetaData> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PIObject::callQueuedEvents() {
|
||||
mutex_queue.lock();
|
||||
PIVector<__QueuedEvent> qe = events_queue;
|
||||
events_queue.clear();
|
||||
mutex_queue.unlock();
|
||||
piForeachC (__QueuedEvent & e, qe) {
|
||||
if (e.dest_o->thread_safe_) e.dest_o->mutex_.lock();
|
||||
e.dest_o->emitter_ = e.src;
|
||||
callAddrV(e.slot, e.dest, e.values.size_s(), e.values);
|
||||
e.dest_o->emitter_ = 0;
|
||||
if (e.dest_o->thread_safe_) e.dest_o->mutex_.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_args, PIObject::__MetaFunc & ret) {
|
||||
PIVector<__MetaFunc> ml = findEH(method);
|
||||
if (ml.isEmpty()) {
|
||||
piCoutObj << "Error: no such method \"" << method << "\"!";
|
||||
return false;
|
||||
}
|
||||
int mfi = -1, ac = -1, mac = -1;
|
||||
for (int i = 0; i < ml.size_s(); ++i) {
|
||||
__MetaFunc & m(ml[i]);
|
||||
int j = m.names.size_s();
|
||||
if (mac < 0 || mac > j) mac = j;
|
||||
if ((j <= args) && (ac < j)) {
|
||||
ac = j;
|
||||
mfi = i;
|
||||
}
|
||||
}
|
||||
if (mfi < 0) {
|
||||
piCoutObj << "Error: no such suitable method \"" << method << "\", need at least" << mac << "arguments!";
|
||||
return false;
|
||||
}
|
||||
ret_args = ac;
|
||||
ret = ml[mfi];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PIVector<PIObject * > & PIObject::objects() {
|
||||
static PIVector<PIObject * > * ret = new PIVector<PIObject * >();
|
||||
return *ret;
|
||||
}
|
||||
|
||||
|
||||
PIMutex & PIObject::mutexObjects() {
|
||||
static PIMutex ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVariant> & vl) {
|
||||
args = piMini(args, vl.size_s());
|
||||
switch (args) {
|
||||
case 0: ((void(*)(void *))slot)(obj); break;
|
||||
case 1: ((void(*)(void * , const PIVariant & ))slot)(obj, vl[0]); break;
|
||||
case 2: ((void(*)(void * , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1]); break;
|
||||
case 3: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1], vl[2]); break;
|
||||
case 4: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & , const PIVariant & ))slot)(obj, vl[0], vl[1], vl[2], vl[3]); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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::isPIObject(const PIObject * o) {
|
||||
if (!o) return false;
|
||||
return o->_signature_ == __PIOBJECT_SIGNATURE__;
|
||||
}
|
||||
|
||||
|
||||
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 << " scope: " << scopeList().join(" -> ");
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " properties {";
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " count: " << properties_.size_s();
|
||||
//printf("dump %d properties\n", properties_.size());
|
||||
piForeachC (PropertyHash p, properties_)
|
||||
if (p.first != PIString("name").hash())
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << p.second.first << ": " << p.second.second;
|
||||
//printf("dump %d properties ok\n", properties_.size());
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " methods {";
|
||||
__MetaData & ehd(__meta_data()[classNameID()]);
|
||||
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;
|
||||
__MetaFunc ef = methodEH(c.signal);
|
||||
PIString src(c.event);
|
||||
if (!ef.func_name.isEmpty())
|
||||
src = ef.func_name + "(" + ef.arguments() + ")";
|
||||
if (dst) {
|
||||
__MetaFunc hf = dst->methodEH(c.slot);
|
||||
if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]";
|
||||
else hf.func_name += "(" + hf.arguments() + ")";
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name;
|
||||
} else {
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]";
|
||||
}
|
||||
}
|
||||
//printf("dump %d connections ok\n",connections.size());
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << " }";
|
||||
PICout(PICoutManipulators::AddNewLine) << line_prefix << "}";
|
||||
}
|
||||
|
||||
|
||||
void dumpApplication() {
|
||||
PIMutexLocker _ml(PIObject::mutexObjects());
|
||||
//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) << " OS name: \"" << pi->OS_name << "\"";
|
||||
PICout(PICoutManipulators::AddNewLine) << " OS version: \"" << pi->OS_version << "\"";
|
||||
PICout(PICoutManipulators::AddNewLine) << " processors: " << pi->processorsCount;
|
||||
PICout(PICoutManipulators::AddNewLine) << " architecture: \"" << pi->architecture << "\"";
|
||||
PICout(PICoutManipulators::AddNewLine) << " hostname: \"" << pi->hostname << "\"";
|
||||
PICout(PICoutManipulators::AddNewLine) << " username: \"" << pi->user << "\"";
|
||||
PICout(PICoutManipulators::AddNewLine) << " exec command: \"" << pi->execCommand << "\"";
|
||||
PICout(PICoutManipulators::AddNewLine) << " started: " << pi->execDateTime.toString();
|
||||
PICout(PICoutManipulators::AddNewLine) << " uptime: " << PITime::fromSystemTime(cd.toSystemTime() - pi->execDateTime.toSystemTime()).toString();
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
#ifndef FREERTOS
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void PIObject::__MetaData::addScope(const PIString & s, uint shash) {
|
||||
if (!scope_id.contains(shash)) {
|
||||
scope_list << s;
|
||||
scope_id << shash;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIObject::__Connection::destroy() {
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
if (functor) delete functor;
|
||||
functor = nullptr;
|
||||
#endif
|
||||
}
|
||||
955
lib/main/core/piobject.h
Normal file
955
lib/main/core/piobject.h
Normal file
@@ -0,0 +1,955 @@
|
||||
/*! \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
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIOBJECT_H
|
||||
#define PIOBJECT_H
|
||||
|
||||
#include "piinit.h"
|
||||
#include "pivariant.h"
|
||||
#include "pimutex.h"
|
||||
#include "piset.h"
|
||||
#include "piqueue.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, and \a scopeList()
|
||||
#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\".
|
||||
/// Event handler will be executed by \"performer\". \"Event\" and \"handler\" must has equal argument lists.
|
||||
#define CONNECTU_QUEUED(src, event, dest, handler, performer)
|
||||
|
||||
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to lambda-expression \"functor\". \"Event\" and \"functor\" must has equal argument lists.
|
||||
#define CONNECTL(src, event, functor)
|
||||
|
||||
/// \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__)
|
||||
#ifdef CC_GCC
|
||||
# define __PTYPE(t) typename __PIVariantTypeInfo__<t>::PureType
|
||||
#else
|
||||
# define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
|
||||
#endif
|
||||
#define __VVALUE(t, v) v.value< __PTYPE(t) >()
|
||||
|
||||
//printf("base_init %s id=%d (%d) pid=%d (%d) ...\n", #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
|
||||
//printf("base_init %s id=%d (%d) pid=%d (%d) ok\n", #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
|
||||
//printf("parent_init %s::%s id=%d (%d) pid=%d (%d) ...\n", __classNameS().dataAscii(), #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
|
||||
//printf("parent_init %s::%s id=%d (%d) pid=%d (%d) ok\n", __classNameS().dataAscii(), #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
|
||||
|
||||
#define PIOBJECT(name) \
|
||||
protected: \
|
||||
typedef name __PIObject__; \
|
||||
public: \
|
||||
static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \
|
||||
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
|
||||
virtual const char * className() const {return #name;} \
|
||||
virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
|
||||
private: \
|
||||
virtual int ptrOffset() const {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \
|
||||
class __BaseInitializer__ { \
|
||||
public: \
|
||||
__BaseInitializer__() { \
|
||||
uint pid = PIObject::__classNameIDS(); \
|
||||
if (pid == 0) return; \
|
||||
uint id = __classNameIDS(); \
|
||||
PIMutexLocker ml(__meta_mutex()); \
|
||||
if (__meta_data().contains(id)) return; \
|
||||
__meta_data()[pid]; \
|
||||
__meta_data()[id]; \
|
||||
__MetaData & ehp(__meta_data()[pid]); \
|
||||
__MetaData & eh(__meta_data()[id]); \
|
||||
eh.eh_set << ehp.eh_set; \
|
||||
eh.eh_func << ehp.eh_func; \
|
||||
eh.addScope(__classNameS(), id); \
|
||||
} \
|
||||
}; \
|
||||
__BaseInitializer__ __base_init__;
|
||||
|
||||
#define PIOBJECT_PARENT(name) \
|
||||
class __ParentInitializer__ { \
|
||||
public: \
|
||||
__ParentInitializer__() { \
|
||||
uint pid = name::__classNameIDS(); \
|
||||
if (pid == 0) return; \
|
||||
uint id = __classNameIDS(); \
|
||||
PIMutexLocker ml(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[id]); \
|
||||
if (eh.scope_id.contains(pid)) return; \
|
||||
__MetaData ehp(__meta_data().value(pid)); \
|
||||
eh.eh_set << ehp.eh_set; \
|
||||
eh.eh_func << ehp.eh_func; \
|
||||
eh.scope_id = ehp.scope_id; \
|
||||
eh.scope_list = ehp.scope_list; \
|
||||
eh.addScope(__classNameS(), id); \
|
||||
} \
|
||||
}; \
|
||||
__ParentInitializer__ __parent_init__; \
|
||||
public: \
|
||||
virtual const char * parentClassName() const {return #name;} \
|
||||
typedef name __Parent__; \
|
||||
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(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
|
||||
void * fpV = fp; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
f.scope = __classNameS(); \
|
||||
f.func_name = PIStringAscii(#name); \
|
||||
f.addr = fp; \
|
||||
f.addrV = fpV; \
|
||||
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(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
f.scope = __classNameS(); \
|
||||
f.func_name = PIStringAscii(#name); \
|
||||
f.addr = fp; \
|
||||
f.addrV = fpV; \
|
||||
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(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
f.scope = __classNameS(); \
|
||||
f.func_name = PIStringAscii(#name); \
|
||||
f.addr = fp; \
|
||||
f.addrV = fpV; \
|
||||
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(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
f.scope = __classNameS(); \
|
||||
f.func_name = PIStringAscii(#name); \
|
||||
f.addr = fp; \
|
||||
f.addrV = fpV; \
|
||||
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(__meta_mutex()); \
|
||||
__MetaData & eh(__meta_data()[__classNameIDS()]); \
|
||||
void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
|
||||
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
|
||||
if (eh.eh_set[fp]) return; \
|
||||
eh.eh_set << fp; \
|
||||
__MetaFunc & f(eh.eh_func[fp]); \
|
||||
f.scope = __classNameS(); \
|
||||
f.func_name = PIStringAscii(#name); \
|
||||
f.addr = fp; \
|
||||
f.addrV = fpV; \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
return ((__PIObject__*)__o__)->name(tv0);} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
|
||||
return ((__PIObject__*)__o__)->name(tv0, tv1);} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
|
||||
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
|
||||
return ((__PIObject__*)__o__)->name(tv0, tv1, tv2);} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) { \
|
||||
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
|
||||
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
|
||||
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
|
||||
__PTYPE(a3) tv3 = __VVALUE(a3, v3); \
|
||||
return ((__PIObject__*)__o__)->name(tv0, tv1, tv2, tv3);} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \
|
||||
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);} \
|
||||
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \
|
||||
virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
|
||||
|
||||
#define EVENT_VHANDLER EVENT_VHANDLER0
|
||||
|
||||
|
||||
#define EVENT0(name) EVENT_HANDLER0(void, name) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);}
|
||||
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);}
|
||||
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);}
|
||||
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, 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) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, 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 CONNECTU_QUEUED(src, event, dest, handler, performer) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
# define CONNECTL(src, event, functor) PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);
|
||||
#endif
|
||||
|
||||
#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__;
|
||||
typedef void __Parent__;
|
||||
friend class PIIntrospection;
|
||||
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";}
|
||||
|
||||
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
|
||||
|
||||
static const PIString __classNameS() {return PIStringAscii("PIObject");}
|
||||
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
|
||||
|
||||
//! Returns parent object class name
|
||||
virtual const char * parentClassName() 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
|
||||
PIMap<PIString, PIVariant> properties() const;
|
||||
|
||||
//! Returns properties count of the object
|
||||
int propertiesCount() const {return properties_.size_s();}
|
||||
|
||||
//! Returns property with name "name"
|
||||
PIVariant property(const PIString & name) const {return properties_.value(name.hash(), Property(PIString(), PIVariant())).second;}
|
||||
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.hash()] = Property(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.hash());}
|
||||
bool isPropertyExists(const char * name) const {return isPropertyExists(PIStringAscii(name));}
|
||||
|
||||
void setThreadSafe(bool yes) {thread_safe_ = yes;}
|
||||
bool isThreadSafe() const {return thread_safe_;}
|
||||
|
||||
bool execute(const PIString & method, const PIVector<PIVariant> & vl);
|
||||
bool execute(const PIString & method) {return execute(method, PIVector<PIVariant>());}
|
||||
bool execute(const PIString & method, const PIVariant & v0) {return execute(method, PIVector<PIVariant>() << v0);}
|
||||
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(method, PIVector<PIVariant>() << v0 << v1);}
|
||||
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl);
|
||||
bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector<PIVariant>());}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(performer, method, PIVector<PIVariant>() << v0);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariant> & vl) {return o->execute(method, vl);}
|
||||
static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector<PIVariant>());}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0) {return execute(o, method, PIVector<PIVariant>() << v0);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(o, method, PIVector<PIVariant>() << v0 << v1);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(o, method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(o, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl) {return o->executeQueued(performer, method, vl);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector<PIVariant>());}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1 << v2);}
|
||||
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
|
||||
|
||||
void dump(const PIString & line_prefix = PIString()) const;
|
||||
|
||||
|
||||
PIStringList scopeList() const;
|
||||
PIStringList methodsEH() const;
|
||||
bool isMethodEHContains(const PIString & name) const;
|
||||
PIString methodEHArguments(const PIString & name) const;
|
||||
PIString methodEHFullFormat(const PIString & name) const;
|
||||
PIString methodEHFromAddr(const void * addr) const;
|
||||
|
||||
// / 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 & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
static bool piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
|
||||
template <typename INPUT, typename... TYPES>
|
||||
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,TYPES...), INPUT functor) {
|
||||
return (std::function<void()>*)(new std::function<void(TYPES...)>(functor));
|
||||
}
|
||||
#endif
|
||||
|
||||
// / 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 uint eventID) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
if (i.functor) {
|
||||
(*(i.functor))();
|
||||
} else {
|
||||
#endif
|
||||
if (i.performer) {
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
if (ts) i.dest_o->mutex_.lock();
|
||||
i.dest_o->emitter_ = sender;
|
||||
((void( *)(void * ))i.slot)(i.dest);
|
||||
if (i.dest_o->isPIObject()) {
|
||||
i.dest_o->emitter_ = 0;
|
||||
if (ts) i.dest_o->mutex_.unlock();
|
||||
}
|
||||
}
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (!sender->isPIObject()) break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T0>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) {
|
||||
for (int j = 0; j < sender->connections.size_s(); ++j) {
|
||||
__Connection i(sender->connections[j]);
|
||||
if (i.eventID != eventID) continue;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0)>*)i.functor))(v0);
|
||||
} else {
|
||||
#endif
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
if (ts) 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);
|
||||
if (i.dest_o->isPIObject()) {
|
||||
i.dest_o->emitter_ = 0;
|
||||
if (ts) i.dest_o->mutex_.unlock();
|
||||
}
|
||||
}
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (!sender->isPIObject()) break;
|
||||
}
|
||||
}
|
||||
template <typename T0, typename T1>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, 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.eventID != eventID) continue;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0, T1)>*)i.functor))(v0, v1);
|
||||
} else {
|
||||
#endif
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
if (ts) 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;
|
||||
}
|
||||
if (i.dest_o->isPIObject()) {
|
||||
i.dest_o->emitter_ = 0;
|
||||
if (ts) i.dest_o->mutex_.unlock();
|
||||
}
|
||||
}
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (!sender->isPIObject()) break;
|
||||
}
|
||||
}
|
||||
template <typename T0, typename T1, typename T2>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, 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.eventID != eventID) continue;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2);
|
||||
} else {
|
||||
#endif
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
|
||||
if (i.args_count > 2) vl << PIVariant::fromValue(v2);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
if (ts) 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;
|
||||
}
|
||||
if (i.dest_o->isPIObject()) {
|
||||
i.dest_o->emitter_ = 0;
|
||||
if (ts) i.dest_o->mutex_.unlock();
|
||||
}
|
||||
}
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (!sender->isPIObject()) break;
|
||||
}
|
||||
}
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
static void raiseEvent(PIObject * sender, const uint eventID, 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.eventID != eventID) continue;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
if (i.functor) {
|
||||
(*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3);
|
||||
} else {
|
||||
#endif
|
||||
if (i.performer) {
|
||||
PIVector<PIVariant> vl;
|
||||
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
|
||||
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
|
||||
if (i.args_count > 2) vl << PIVariant::fromValue(v2);
|
||||
if (i.args_count > 3) vl << PIVariant::fromValue(v3);
|
||||
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
|
||||
} else {
|
||||
bool ts = sender->thread_safe_;
|
||||
if (ts) 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;
|
||||
}
|
||||
if (i.dest_o->isPIObject()) {
|
||||
i.dest_o->emitter_ = 0;
|
||||
if (ts) i.dest_o->mutex_.unlock();
|
||||
}
|
||||
}
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
}
|
||||
#endif
|
||||
if (!sender->isPIObject()) break;
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns PIObject* with name "name" or 0, if there is no object found
|
||||
static PIObject * findByName(const PIString & name) {
|
||||
PIMutexLocker _ml(mutexObjects());
|
||||
piForeach (PIObject * i, PIObject::objects()) {
|
||||
if (i->name() != name) continue;
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isPIObject() const {return isPIObject(this);}
|
||||
template<typename T>
|
||||
bool isTypeOf() const {
|
||||
if (!isPIObject()) return false;
|
||||
return scopeList().contains(T::__classNameS());
|
||||
}
|
||||
template<typename T>
|
||||
T * cast() const {
|
||||
if (!isTypeOf<T>()) return (T*)0;
|
||||
return (T*)this;
|
||||
}
|
||||
|
||||
static bool isPIObject(const PIObject * o);
|
||||
static bool isPIObject(const void * o) {return isPIObject((PIObject*)o);}
|
||||
template<typename T>
|
||||
static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();}
|
||||
template<typename T>
|
||||
static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);}
|
||||
static PIString simplifyType(const char * a);
|
||||
|
||||
struct __MetaFunc {
|
||||
__MetaFunc(): addr(0), addrV(0) {;}
|
||||
bool isNull() const {return addr == 0;}
|
||||
PIString arguments() const;
|
||||
PIString fullFormat() const;
|
||||
void * addr;
|
||||
void * addrV;
|
||||
PIString func_name;
|
||||
PIString type_ret;
|
||||
PIString scope;
|
||||
PIStringList types;
|
||||
PIStringList names;
|
||||
};
|
||||
struct __MetaData {
|
||||
__MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();}
|
||||
void addScope(const PIString & s, uint shash);
|
||||
PIStringList scope_list;
|
||||
PISet<uint> scope_id;
|
||||
PISet<const void * > eh_set;
|
||||
PIMap<const void * , __MetaFunc> eh_func;
|
||||
};
|
||||
typedef PIPair<const void * , __MetaFunc> __EHPair;
|
||||
|
||||
static PIMutex & __meta_mutex();
|
||||
static PIMap<uint, __MetaData> & __meta_data(); // [hash(classname)]=__MetaData
|
||||
|
||||
//! \brief Execute all posted events from CONNECTU_QUEUED connections
|
||||
void callQueuedEvents();
|
||||
|
||||
//! \brief Check if any CONNECTU_QUEUED connections to this object and execute them.
|
||||
//! \details This function is more optimized than \a callQueuedEvents() for objects that doesn`t
|
||||
//! appears as \"performer\" target at CONNECTU_QUEUED
|
||||
bool maybeCallQueuedEvents() {if (proc_event_queue) callQueuedEvents(); return proc_event_queue;}
|
||||
|
||||
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) {}
|
||||
|
||||
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, PIObject * p = 0) {
|
||||
slot = sl;
|
||||
signal = si;
|
||||
event = e;
|
||||
eventID = e.hash();
|
||||
dest_o = d_o;
|
||||
dest = d;
|
||||
args_count = ac;
|
||||
performer = p;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
functor = 0;
|
||||
#endif
|
||||
}
|
||||
void destroy();
|
||||
void * slot;
|
||||
void * signal;
|
||||
#ifdef PIP_CXX11_SUPPORT
|
||||
std::function<void()> * functor;
|
||||
#endif
|
||||
PIString event;
|
||||
uint eventID;
|
||||
PIObject * dest_o;
|
||||
PIObject * performer;
|
||||
void * dest;
|
||||
int args_count;
|
||||
};
|
||||
struct __QueuedEvent {
|
||||
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariant> & v = PIVector<PIVariant>()) {
|
||||
slot = sl;
|
||||
dest = d;
|
||||
dest_o = d_o;
|
||||
src = s;
|
||||
values = v;
|
||||
}
|
||||
void * slot;
|
||||
void * dest;
|
||||
PIObject * dest_o;
|
||||
PIObject * src;
|
||||
PIVector<PIVariant> values;
|
||||
};
|
||||
typedef PIPair<PIString, PIVariant> Property;
|
||||
typedef PIPair<uint, PIPair<PIString, PIVariant> > PropertyHash;
|
||||
|
||||
bool findSuitableMethodV(const PIString & method, int args, int & ret_args, __MetaFunc & ret);
|
||||
PIVector<__MetaFunc> findEH(const PIString & name) const;
|
||||
__MetaFunc methodEH(const void * addr) const;
|
||||
void updateConnectors();
|
||||
void postQueuedEvent(const __QueuedEvent & e);
|
||||
void * toThis() const;
|
||||
virtual int ptrOffset() const {return 0;}
|
||||
|
||||
static PIVector<PIObject * > & objects();
|
||||
static PIMutex & mutexObjects();
|
||||
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariant> & vl);
|
||||
|
||||
|
||||
PIVector<__Connection> connections;
|
||||
PIMap<uint, PIPair<PIString, PIVariant> > properties_;
|
||||
PISet<PIObject * > connectors;
|
||||
PIVector<__QueuedEvent> events_queue;
|
||||
PIMutex mutex_, mutex_connect, mutex_queue;
|
||||
PIObject * emitter_;
|
||||
bool thread_safe_, proc_event_queue;
|
||||
|
||||
};
|
||||
|
||||
|
||||
void dumpApplication();
|
||||
bool dumpApplicationToFile(const PIString & path);
|
||||
|
||||
#endif // PIOBJECT_H
|
||||
133
lib/main/core/pipropertystorage.cpp
Normal file
133
lib/main/core/pipropertystorage.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Storage of properties for GUI usage
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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();
|
||||
}
|
||||
172
lib/main/core/pipropertystorage.h
Normal file
172
lib/main/core/pipropertystorage.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*! \file pipropertystorage.h
|
||||
* \brief Storage of properties for GUI usage
|
||||
*
|
||||
* This file declare PIPropertyStorage
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Storage of properties for GUI usage
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIPROPERTYSTORAGE_H
|
||||
#define PIPROPERTYSTORAGE_H
|
||||
|
||||
#include "pivariant.h"
|
||||
|
||||
/**
|
||||
* @brief Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
|
||||
* contains unique name and you can identify property by name with propertyValueByName(), propertyByName().
|
||||
* You can add property using addProperty(const Property&), addProperty(const PIString&, const PIVariant&, const PIString&, int).
|
||||
*/
|
||||
class PIPropertyStorage {
|
||||
public:
|
||||
PIPropertyStorage() {}
|
||||
|
||||
/**
|
||||
* @brief PIPropertyStorage element.
|
||||
*/
|
||||
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) {}
|
||||
|
||||
bool toBool() const {return value.toBool();}
|
||||
int toInt() const {return value.toInt();}
|
||||
float toFloat() const {return value.toFloat();}
|
||||
double toDouble() const {return value.toDouble();}
|
||||
PIString toString() const {return value.toString();}
|
||||
|
||||
/*! Uniqueue id of property */
|
||||
PIString name;
|
||||
|
||||
/*! Optional description of property */
|
||||
PIString comment;
|
||||
|
||||
/*! Custom value of property */
|
||||
PIVariant value;
|
||||
|
||||
/*! Abstract flags which may be used for user needs */
|
||||
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();}
|
||||
|
||||
/**
|
||||
* @brief Add property if name isn't present in storage, otherwrise update existing property with same name.
|
||||
*
|
||||
* @param p to copy in storage
|
||||
*/
|
||||
void addProperty(const Property & p);
|
||||
|
||||
/**
|
||||
* @brief First of all construct Property with method params. After then add property if name isn't present
|
||||
* in storage, otherwrise update existing property with same name.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Search property by name and return it.
|
||||
*
|
||||
* @param name of property
|
||||
* @return property value or default constructed Property
|
||||
*/
|
||||
Property propertyByName(const PIString & name) const;
|
||||
|
||||
/**
|
||||
* @brief Search property by name and return property value.
|
||||
*
|
||||
* @param name of property
|
||||
* @return property value or invalid PIVariant if name unknown
|
||||
*/
|
||||
PIVariant propertyValueByName(const PIString & name) const;
|
||||
|
||||
/**
|
||||
* @brief Set value of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set value
|
||||
* @param value to set
|
||||
*/
|
||||
void setPropertyValue(const PIString & name, const PIVariant & value);
|
||||
|
||||
/**
|
||||
* @brief Set comment of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set comment
|
||||
* @param comment to set
|
||||
*/
|
||||
void setPropertyComment(const PIString & name, const PIString & comment);
|
||||
|
||||
/**
|
||||
* @brief Set flags of property with specific name if name is present in storage.
|
||||
*
|
||||
* @param name of property to set flags
|
||||
* @param flags to set
|
||||
*/
|
||||
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
|
||||
1225
lib/main/core/pistring.cpp
Normal file
1225
lib/main/core/pistring.cpp
Normal file
@@ -0,0 +1,1225 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
String
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#include "pistring.h"
|
||||
#include "pistringlist.h"
|
||||
#ifdef PIP_ICU
|
||||
# define U_NOEXCEPT
|
||||
# include "unicode/ucnv.h"
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
# include <stringapiset.h>
|
||||
#endif
|
||||
#include <wchar.h>
|
||||
#ifdef ANDROID
|
||||
# if __ANDROID_API__ < 21
|
||||
# define wctomb(s, wc) wcrtomb(s, wc, NULL)
|
||||
# define mbtowc(pwc, s, n) mbrtowc(pwc, s, n, NULL)
|
||||
# endif
|
||||
#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().
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*! \fn int versionCompare(const PIString & v0, const PIString & v1, int components = 6)
|
||||
* \relatesalso PIString
|
||||
* \brief Compare two version strings in free notation and returns 0, -1 or 1
|
||||
* \details This function parse version to number codes and labels. Then it
|
||||
* compare no more than "components" codes. If there is no difference, compare
|
||||
* labels. Each label has corresponding integer value, so
|
||||
* "prealpha" < "alpha" < "prebeta" < "beta" < "rcN" < "" < "rN".
|
||||
* Example:
|
||||
* \code
|
||||
* piCout << versionCompare("1.0.0_rc2-999", "1.0.1_rc2-999"); // -1
|
||||
* piCout << versionCompare("1.0.0", "0.9.2"); // 1
|
||||
* piCout << versionCompare("1.0.0_r1", "1.0.0"); // 1
|
||||
* piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0
|
||||
* piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0
|
||||
* piCout << versionCompare(".2-alpha", "0.2_alpha"); // 0
|
||||
* piCout << versionCompare("1_prebeta", "1.0_alpha"); // 1
|
||||
* \endcode
|
||||
* \return
|
||||
* * 0 - equal
|
||||
* * 1 - v0 > v1
|
||||
* * -1 - v0 < v1
|
||||
*
|
||||
*
|
||||
* \fn PIString versionNormalize(const PIString & v)
|
||||
* \relatesalso PIString
|
||||
* \brief Converts version string in free notation to classic view
|
||||
* \details Parse version as described in \a versionCompare() and
|
||||
* returns classic view of codes and labels: major.minor.revision[-build][_label].
|
||||
* Example:
|
||||
* \code
|
||||
* piCout << versionNormalize(""); // 0.0.0
|
||||
* piCout << versionNormalize("1"); // 1.0.0
|
||||
* piCout << versionNormalize("1.2"); // 1.2.0
|
||||
* piCout << versionNormalize("1.2.3"); // 1.2.3
|
||||
* piCout << versionNormalize("1.2+rc1.99"); // 1.2.99_rc1
|
||||
* piCout << versionNormalize("1.2-alpha"); // 1.2.0_alpha
|
||||
* piCout << versionNormalize("1..4_rc2-999"); // 1.0.4-999_rc2
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
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};
|
||||
|
||||
const float PIString::ElideLeft = 0.f;
|
||||
const float PIString::ElideCenter = .5f;
|
||||
const float PIString::ElideRight = 1.f;
|
||||
|
||||
|
||||
#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, char format, int precision) {
|
||||
char f[8] = "%.";
|
||||
int wr = sprintf(&(f[2]), "%d", precision);
|
||||
f[2 + wr] = format;
|
||||
f[3 + wr] = 0;
|
||||
pisprintf(f, num);
|
||||
return PIString(ch);
|
||||
}
|
||||
PIString PIString::dtos(const double num, char format, int precision) {
|
||||
char f[8] = "%.";
|
||||
int wr = sprintf(&(f[2]), "%d", precision);
|
||||
f[2 + wr] = format;
|
||||
f[3 + wr] = 0;
|
||||
pisprintf(f, num);
|
||||
return PIString(ch);
|
||||
}
|
||||
#undef pisprintf
|
||||
|
||||
|
||||
|
||||
PIString PIString::fromNumberBaseS(const llong value, int base, bool * ok) {
|
||||
if (value == 0LL) 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;
|
||||
}
|
||||
|
||||
PIString PIString::fromNumberBaseU(const ullong value, int base, bool * ok) {
|
||||
if (value == 0ULL) 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;
|
||||
}
|
||||
|
||||
|
||||
llong PIString::toNumberBase(const PIString & value, int base, bool * ok) {
|
||||
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;}
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void PIString::appendFromChars(const char * c, int s, const char * codepage) {
|
||||
if (s <= 0) return;
|
||||
int sz;
|
||||
#ifdef PIP_ICU
|
||||
UErrorCode e((UErrorCode)0);
|
||||
UConverter * cc = ucnv_open(codepage, &e);
|
||||
if (cc) {
|
||||
UChar * ucs = new UChar[s];
|
||||
memset(ucs, 0, s * sizeof(UChar));
|
||||
e = (UErrorCode)0;
|
||||
int sz = ucnv_toUChars(cc, ucs, s, c, s, &e);
|
||||
//printf("appendFromChars %d -> %d\n", s, sz);
|
||||
//printf("PIString %d -> %d\n", c[0], ucs[0]);
|
||||
for (int i = 0; i < sz; ++i)
|
||||
push_back(PIChar(ucs[i]));
|
||||
delete[] ucs;
|
||||
ucnv_close(cc);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0);
|
||||
if (sz <= 0) return;
|
||||
wchar_t * buffer = new wchar_t[sz];
|
||||
MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, buffer, sz);
|
||||
for (int i = 0; i < sz; ++i)
|
||||
push_back(PIChar((ushort)buffer[i]));
|
||||
delete[] buffer;
|
||||
return;
|
||||
//printf("request %d\n", sz);
|
||||
# else
|
||||
wchar_t wc;
|
||||
mbtowc(0,0,0); // reset mbtowc
|
||||
//qDebug() << "FromChars ...";
|
||||
while (s>0) {
|
||||
//qDebug() << "0" << s;
|
||||
sz = mbtowc(&wc, c, s);
|
||||
//qDebug() << "1" << sz;
|
||||
if (sz < 1) break;
|
||||
push_back(PIChar(int(wc)));
|
||||
c += sz; s -= sz;
|
||||
//qDebug() << "2" << c;
|
||||
}
|
||||
//qDebug() << "FromChars done" << size();
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromConsole(const char * s) {
|
||||
int l = 0;
|
||||
while (s[l] != '\0') ++l;
|
||||
PIString ret;
|
||||
if (l > 0) ret.appendFromChars(s, l, __sysoemname__);
|
||||
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, __syslocname__);
|
||||
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, __utf8name__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::fromUTF8(const PIByteArray & ba) {
|
||||
PIString ret;
|
||||
if (ba.isEmpty()) return ret;
|
||||
ret.appendFromChars((const char*)ba.data(), ba.size(), __utf8name__);
|
||||
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
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
, __utf8name__
|
||||
# endif
|
||||
#endif
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIString::readableSize(llong bytes) {
|
||||
PIString s;
|
||||
s.setReadableSize(bytes);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void PIString::buildData(const char * cp) const {
|
||||
data_.clear();
|
||||
int sz = 0;
|
||||
#ifdef PIP_ICU
|
||||
UErrorCode e((UErrorCode)0);
|
||||
UConverter * cc = ucnv_open(cp, &e);
|
||||
if (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;
|
||||
sz = ucnv_fromUChars(cc, uc, 8, (const UChar*)(PIDeque<PIChar>::data(i)), 1, &e);
|
||||
for (int j = 0; j < sz; ++j)
|
||||
data_.push_back(uc[j]);
|
||||
}
|
||||
}
|
||||
ucnv_close(cc);
|
||||
data_.push_back('\0');
|
||||
return;
|
||||
}
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
sz = WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque<PIChar>::data(), PIDeque<PIChar>::size_s(), 0, 0, NULL, NULL);
|
||||
//printf("WideCharToMultiByte %d %d\n", (uint)(uintptr_t)cp, sz);
|
||||
if (sz <= 0) {
|
||||
//printf("WideCharToMultiByte erro %d\n", GetLastError());
|
||||
data_.push_back(uchar('\0'));
|
||||
return;
|
||||
}
|
||||
data_.resize(sz);
|
||||
WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)PIDeque<PIChar>::data(), PIDeque<PIChar>::size_s(), (LPSTR)data_.data(), data_.size_s(), NULL, NULL);
|
||||
data_.push_back(uchar('\0'));
|
||||
return;
|
||||
# else
|
||||
wchar_t wc;
|
||||
char tc[8];
|
||||
wctomb(0, 0);
|
||||
for (int i = 0; i < size_s(); ++i) {
|
||||
if (at(i).isAscii()) {
|
||||
data_.push_back(uchar(at(i).toAscii()));
|
||||
continue;
|
||||
}
|
||||
wc = at(i).toWChar();
|
||||
sz = wctomb(tc, wc);
|
||||
for (int b = 0; b < sz; ++b)
|
||||
data_.push_back(uchar(tc[b]));
|
||||
}
|
||||
data_.push_back(uchar('\0'));
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
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) && at(i) != uchar(0))
|
||||
{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) && at(i) != uchar(0))
|
||||
{fn = i; break;}
|
||||
}
|
||||
|
||||
|
||||
const char * PIString::dataConsole() const {
|
||||
buildData(__sysoemname__ );
|
||||
return (const char *)(data_.data());
|
||||
}
|
||||
|
||||
|
||||
const char * PIString::dataUTF8() const {
|
||||
buildData(__utf8name__);
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
uint PIString::hash() const {
|
||||
return piHashData((const uchar*)PIDeque<PIChar>::data(), size() * sizeof(PIChar));
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PIString::toUTF8() const {
|
||||
if (isEmpty()) return data_.resized(0);
|
||||
buildData(__utf8name__);
|
||||
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
|
||||
#else
|
||||
# ifdef WINDOWS
|
||||
__utf8name__
|
||||
# endif
|
||||
#endif
|
||||
);
|
||||
return data_.resized(data_.size_s() - 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PIString & PIString::operator +=(const char * str) {
|
||||
if (!str) return *this;
|
||||
int l = 0;
|
||||
while (str[l] != '\0') ++l;
|
||||
appendFromChars(str, l, __syslocname__);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIString & PIString::operator +=(const wchar_t * str) {
|
||||
if (!str) return *this;
|
||||
int i = -1;
|
||||
while (str[++i])
|
||||
push_back(PIChar(ushort(str[i])));
|
||||
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 (at(i) == str[i]) continue;
|
||||
if (at(i) < str[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 (at(i) == str[i]) continue;
|
||||
if (at(i) < str[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;
|
||||
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) {
|
||||
PIDeque<PIChar>::insert(index, *((const PIDeque<PIChar>*)&str));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIString & PIString::elide(int size, float pos) {
|
||||
if (length() <= size) return *this;
|
||||
if (length() <= 2) {
|
||||
fill(".");
|
||||
return *this;
|
||||
}
|
||||
pos = piClampf(pos, 0.f, 1.f);
|
||||
int ns = size - 2;
|
||||
int ls = piRoundf(ns * pos);
|
||||
remove(ls, length() - ns);
|
||||
insert(ls, "..");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int PIString::findRange(const PIChar & start, const PIChar & end, const PIChar & shield, const int start_index, int * len) const {
|
||||
if (len) *len = 0;
|
||||
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 = start_index; 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 -1;
|
||||
if (len) *len = le - ls - 1;
|
||||
return ls + 1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::findAny(const PIString & str, const int start) const {
|
||||
for (int i = start; i < length(); ++i)
|
||||
if (str.contains(at(i)))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::findAnyLast(const PIString & str, const int start) const {
|
||||
for (int i = length() - 1; i >= start; --i)
|
||||
if (str.contains(at(i)))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int PIString::entries(const PIChar & c) const {
|
||||
int sz = size_s(), ret = 0;
|
||||
for (int i = 0; i < sz; ++i)
|
||||
if (at(i) == c) ++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
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';
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
inline char chrLwr(char c) {
|
||||
if (c >= 'A' && c <= 'Z') return c + 'a' - 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
const static PIString _versionDelims_ = PIStringAscii("._-+");
|
||||
|
||||
|
||||
void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
|
||||
s.trim();
|
||||
if (s.isEmpty()) {
|
||||
codes.resize(3, 0);
|
||||
return;
|
||||
}
|
||||
int mccnt = 2 - s.entries('.');
|
||||
if (mccnt > 0) {
|
||||
int ind = s.findLast(".") + 1;
|
||||
while (!_versionDelims_.contains(s[ind])) {
|
||||
++ind;
|
||||
if (ind > s.size_s() - 1)
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < mccnt; ++i)
|
||||
s.insert(ind, ".0");
|
||||
}
|
||||
PIStringList comps;
|
||||
while (!s.isEmpty()) {
|
||||
int ind = s.findAny(_versionDelims_);
|
||||
if (ind >= 0) {
|
||||
comps << s.takeLeft(ind);
|
||||
s.cutLeft(1).trim();
|
||||
} else {
|
||||
comps << s;
|
||||
s.clear();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < comps.size_s(); ++i) {
|
||||
if (comps[i].isEmpty())
|
||||
comps[i] = "0";
|
||||
bool ok = false;
|
||||
int val = comps[i].toInt(-1, &ok);
|
||||
if (ok) {
|
||||
codes << val;
|
||||
} else {
|
||||
strs << comps[i];
|
||||
}
|
||||
}
|
||||
//piCout << codes << strs;
|
||||
}
|
||||
|
||||
|
||||
int versionLabelValue(PIString s) {
|
||||
int ret = -10000;
|
||||
if (s.isEmpty()) return 0;
|
||||
if (s.startsWith("pre")) {
|
||||
s.cutLeft(3);
|
||||
ret -= 1;
|
||||
}
|
||||
if (s.startsWith("rc")) {
|
||||
s.cutLeft(2);
|
||||
ret += s.toInt();
|
||||
}
|
||||
if (s.startsWith("r")) {
|
||||
s.cutLeft(1);
|
||||
ret += 10000 + s.toInt();
|
||||
}
|
||||
if (s == "alpha") ret -= 4;
|
||||
if (s == "beta" ) ret -= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int versionCompare(const PIString & v0, const PIString & v1, int components) {
|
||||
PIStringList strs[2]; PIVector<int> codes[2];
|
||||
parseVersion(v0.toLowerCase(), codes[0], strs[0]);
|
||||
parseVersion(v1.toLowerCase(), codes[1], strs[1]);
|
||||
//piCout << codes[0] << strs[0];
|
||||
int mc = piMaxi(codes[0].size_s(), codes[1].size_s());
|
||||
if (codes[0].size_s() < mc) codes[0].resize(mc, 0);
|
||||
if (codes[1].size_s() < mc) codes[1].resize(mc, 0);
|
||||
mc = piMaxi(strs[0].size_s(), strs[1].size_s());
|
||||
if (strs[0].size_s() < mc) strs[0].resize(mc, "");
|
||||
if (strs[1].size_s() < mc) strs[1].resize(mc, "");
|
||||
int comps = piMini(components, codes[0].size_s(), codes[1].size_s());
|
||||
if (comps < 1) return (v0 == v1 ? 0 : (v0 > v1 ? 1 : -1));
|
||||
for (int c = 0; c < comps; ++c) {
|
||||
if (codes[0][c] > codes[1][c]) return 1;
|
||||
if (codes[0][c] < codes[1][c]) return -1;
|
||||
}
|
||||
mc = piClampi(mc, 0, components - comps);
|
||||
for (int c = 0; c < mc; ++c) {
|
||||
int lv0 = versionLabelValue(strs[0][c]);
|
||||
int lv1 = versionLabelValue(strs[1][c]);
|
||||
if (lv0 > lv1) return 1;
|
||||
if (lv0 < lv1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PIString versionNormalize(const PIString & v) {
|
||||
PIStringList strs; PIVector<int> codes;
|
||||
parseVersion(v.toLowerCase(), codes, strs);
|
||||
PIString ret;
|
||||
for (int i = 0; i < codes.size_s(); ++i) {
|
||||
if (i > 0) {
|
||||
if (i < 3) ret += ".";
|
||||
else ret += "-";
|
||||
}
|
||||
ret += PIString::fromNumber(codes[i]);
|
||||
}
|
||||
for (int i = 0; i < strs.size_s(); ++i) {
|
||||
ret += "_";
|
||||
ret += strs[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PICout operator <<(PICout s, const PIString & v) {
|
||||
s.space();
|
||||
s.quote();
|
||||
s.setControl(0, true);
|
||||
s << v.data();
|
||||
s.restoreControl();
|
||||
s.quote();
|
||||
return s;
|
||||
}
|
||||
|
||||
774
lib/main/core/pistring.h
Normal file
774
lib/main/core/pistring.h
Normal file
@@ -0,0 +1,774 @@
|
||||
/*! \file pistring.h
|
||||
* \brief String
|
||||
*
|
||||
* This file declare string and string list classes
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
String
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef 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>() {}
|
||||
|
||||
static const float ElideLeft ;
|
||||
static const float ElideCenter;
|
||||
static const float ElideRight ;
|
||||
|
||||
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(), __utf8name__); return *this;}
|
||||
PIString & operator +=(const PIString & str);
|
||||
|
||||
PIString(const PIString & o): PIDeque<PIChar>() {*this += o;}
|
||||
|
||||
|
||||
//! Contructs string with single symbol "c"
|
||||
PIString(const PIChar & c): PIDeque<PIChar>() {*this += c;}
|
||||
PIString(const char c): PIDeque<PIChar>() {*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>() {*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>() {*this += str;}
|
||||
|
||||
//! Contructs string from byte array "ba"
|
||||
PIString(const PIByteArray & ba): PIDeque<PIChar>() {*this += ba;}
|
||||
|
||||
//! \brief Contructs string from "len" characters of buffer "str"
|
||||
PIString(const PIChar * str, const int len): PIDeque<PIChar>(str, size_t(len)) {}
|
||||
|
||||
/*! \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>() {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>() {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>() {for (int i = 0; i < len; ++i) push_back(c);}
|
||||
|
||||
~PIString() {}
|
||||
|
||||
|
||||
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);}
|
||||
|
||||
//! 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);}
|
||||
|
||||
//! 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);}
|
||||
|
||||
//! 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);}
|
||||
|
||||
//! 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);}
|
||||
|
||||
//! 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);}
|
||||
|
||||
//! Compare operator
|
||||
bool operator >=(const char * str) const {return *this >= PIString(str);}
|
||||
|
||||
/*! \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;}
|
||||
|
||||
/*! \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 sub-string of string from symbol at index "start" and maximum length "len" */
|
||||
PIString subString(const int start, const int len = -1) const {return mid(start, len);}
|
||||
|
||||
/*! \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 Add "c" symbols at the beginning and end of the string, and return this string
|
||||
* \sa \a quoted() */
|
||||
PIString & quote(PIChar c = PIChar('"')) {insert(0, c); *this += c; return *this;}
|
||||
|
||||
/*! \brief Return quoted copy of this string
|
||||
* \sa \a quote() */
|
||||
PIString quoted(PIChar c = PIChar('"')) {return PIString(*this).quote(c);}
|
||||
|
||||
/*! \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 Elide string to maximum size \"size\" and return this string
|
||||
* \sa \a elided() */
|
||||
PIString & elide(int size, float pos = ElideCenter);
|
||||
|
||||
/*! \brief Elide copy of this string to maximum size \"size\" and return it
|
||||
* \details Example: \snippet pistring.cpp PIString::elided
|
||||
* \sa \a elide() */
|
||||
PIString elided(int size, float pos = ElideCenter) const {PIString str(*this); str.elide(size, pos); 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(__syslocname__); 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(__syslocname__); 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;
|
||||
|
||||
//! Returns hash
|
||||
uint hash() const;
|
||||
|
||||
//! \brief Return \a PIByteArray contains \a data() of this string without terminating null-char
|
||||
PIByteArray toByteArray() const {buildData(__utf8name__); 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 Returns if string contains "str"
|
||||
bool contains(const char str) const {return contains(PIString(str));}
|
||||
|
||||
//! \brief Returns if string contains "str"
|
||||
bool contains(const PIChar str) const {return contains(PIString(str));}
|
||||
|
||||
//! \brief Returns if string contains "str"
|
||||
bool contains(const char * str) const {return contains(PIString(str));}
|
||||
|
||||
//! \brief Returns if string contains "str"
|
||||
bool contains(const PIString & str) const {return find(str) >= 0;}
|
||||
|
||||
|
||||
//! \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 Search range between "start" and "end" symbols at index "start_index" and return first occur position.
|
||||
//! \details Example: \snippet pistring.cpp PIString::findRange
|
||||
int findRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\', const int start_index = 0, int * len = 0) const;
|
||||
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAny
|
||||
int findAny(const PIString & str, const int start = 0) const;
|
||||
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAny
|
||||
int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);}
|
||||
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
|
||||
int findAnyLast(const PIString & str, const int start = 0) const;
|
||||
|
||||
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
|
||||
int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);}
|
||||
|
||||
//! \brief Returns number of occurrences of symbol "c"
|
||||
int entries(const PIChar & c) const;
|
||||
|
||||
//! \brief Returns number of occurrences of symbol "c"
|
||||
int entries(char c) const {return entries(PIChar(c));}
|
||||
|
||||
//! \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;
|
||||
|
||||
//! \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, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
|
||||
|
||||
//! \brief Set string content to numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setFloat
|
||||
PIString & setNumber(const double & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); return *this;}
|
||||
|
||||
//! \brief Set string content to numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::setFloat
|
||||
PIString & setNumber(const ldouble & value, char format = 'f', int precision = 8) {clear(); *this += PIString::fromNumber(value, format, precision); 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);
|
||||
|
||||
//! \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, char format = 'f', int precision = 8) {return ftos(value, format, precision);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromFloat
|
||||
static PIString fromNumber(const double & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
|
||||
|
||||
//! \brief Return string contains numeric representation of "value"
|
||||
//! \details Example: \snippet pistring.cpp PIString::fromFloat
|
||||
static PIString fromNumber(const ldouble & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
|
||||
|
||||
//! \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 UTF-8
|
||||
static PIString fromUTF8(const PIByteArray &ba);
|
||||
|
||||
//! \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 & 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, char format = 'f', int precision = 8);
|
||||
static PIString dtos(const double num, char format = 'f', int precision = 8);
|
||||
static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0);
|
||||
static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0);
|
||||
static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0);
|
||||
void appendFromChars(const char * c, int s, const char * cp = __syslocname__);
|
||||
void buildData(const char * cp = __syslocname__) const;
|
||||
void trimsubstr(int &st, int &fn) const;
|
||||
mutable PIByteArray data_;
|
||||
};
|
||||
|
||||
|
||||
//! \relatesalso PIString \relatesalso PICout \brief Output operator to PICout
|
||||
PIP_EXPORT 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) {v.clear(); 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;}
|
||||
|
||||
//! \relatesalso PIString \brief Return concatenated string
|
||||
inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;}
|
||||
|
||||
//! \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);
|
||||
|
||||
|
||||
int versionCompare(const PIString & v0, const PIString & v1, int components = 6);
|
||||
|
||||
PIString versionNormalize(const PIString & v);
|
||||
|
||||
|
||||
|
||||
template<> inline uint piHash(const PIString & s) {return s.hash();}
|
||||
|
||||
#endif // PISTRING_H
|
||||
100
lib/main/core/pistring_std.h
Normal file
100
lib/main/core/pistring_std.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*! \file pistring.h
|
||||
* \brief String
|
||||
*
|
||||
* This file declare std operators and string conversions
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
STD for PIString
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PISTRING_STD_H
|
||||
#define PISTRING_STD_H
|
||||
#include <string>
|
||||
#ifdef QNX
|
||||
typedef std::basic_string<wchar_t> wstring;
|
||||
#endif
|
||||
|
||||
#include "pistringlist.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 PIChar \brief Output operator to \c std::ostream
|
||||
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;}
|
||||
|
||||
//! \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
|
||||
42
lib/main/core/pistringlist.cpp
Normal file
42
lib/main/core/pistringlist.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Strings array class
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pistringlist.h"
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
100
lib/main/core/pistringlist.h
Normal file
100
lib/main/core/pistringlist.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*! \brief Strings array class
|
||||
* \details This class is based on \a PIDeque<PIString> and
|
||||
* expand it functionality. */
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Strings array class
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PISTRINGLIST_H
|
||||
#define PISTRINGLIST_H
|
||||
|
||||
#include "pistring.h"
|
||||
|
||||
|
||||
class PIP_EXPORT PIStringList: public PIDeque<PIString>
|
||||
{
|
||||
public:
|
||||
|
||||
//! Contructs empty strings list
|
||||
PIStringList() {;}
|
||||
|
||||
~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) {PIDeque<PIString>::operator=(o); return *this;}
|
||||
|
||||
PIStringList & operator <<(const PIString & str) {append(str); return *this;}
|
||||
PIStringList & operator <<(const PIStringList & sl) {append(sl); 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 // PISTRINGLIST_H
|
||||
474
lib/main/core/pitime.cpp
Normal file
474
lib/main/core/pitime.cpp
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Timer
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
#ifdef FREERTOS
|
||||
# include "freertos/FreeRTOS.h"
|
||||
# include "freertos/task.h"
|
||||
#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
|
||||
//printf("Sleep %d\n", usecs / 1000);
|
||||
if (usecs > 0) Sleep(usecs / 1000);
|
||||
//printf("Sleep end");
|
||||
#else
|
||||
# ifdef FREERTOS
|
||||
vTaskDelay(usecs / 1000 / portTICK_PERIOD_MS);
|
||||
# else
|
||||
usecs -= PISystemTests::usleep_offset_us;
|
||||
if (usecs > 0) usleep(usecs);
|
||||
# endif
|
||||
#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);
|
||||
}
|
||||
#else
|
||||
# ifdef MAC_OS
|
||||
mach_timespec_t t_cur;
|
||||
clock_get_time(__pi_mac_clock, &t_cur);
|
||||
# else
|
||||
# ifdef FREERTOS
|
||||
timespec t_cur;
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
gettimeofday(&tv, NULL);
|
||||
t_cur.tv_sec = tv.tv_sec;
|
||||
t_cur.tv_nsec = tv.tv_usec * 1000;
|
||||
# else
|
||||
timespec t_cur;
|
||||
clock_gettime(0, &t_cur);
|
||||
# endif
|
||||
# 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
|
||||
# ifdef FREERTOS
|
||||
void msleep(int msecs) {vTaskDelay(msecs / portTICK_PERIOD_MS);}
|
||||
# else
|
||||
void msleep(int msecs) {usleep(msecs * 1000);}
|
||||
# endif
|
||||
#endif
|
||||
333
lib/main/core/pitime.h
Normal file
333
lib/main/core/pitime.h
Normal file
@@ -0,0 +1,333 @@
|
||||
/*! \file pitime.h
|
||||
* \brief Time structs
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Time structs
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PITIME_H
|
||||
#define PITIME_H
|
||||
|
||||
|
||||
#include "pistring.h"
|
||||
#include <ctime>
|
||||
#ifdef QNX
|
||||
# include <time.h>
|
||||
#endif
|
||||
//! \brief Sleep for "msecs" milliseconds
|
||||
PIP_EXPORT 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. */
|
||||
PIP_EXPORT 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
|
||||
PIP_EXPORT 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
|
||||
PIP_EXPORT 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
|
||||
PIP_EXPORT PICout operator <<(PICout s, const PIDateTime & v);
|
||||
|
||||
|
||||
|
||||
|
||||
class PIP_EXPORT 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
|
||||
87
lib/main/core/pitime_win.h
Normal file
87
lib/main/core/pitime_win.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*! \file pitime_win.h
|
||||
* \brief PITime conversions for Windows
|
||||
*
|
||||
* This file declare time conversions for Windows
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PITime conversions for Windows
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PITIME_WIN_H
|
||||
#define PITIME_WIN_H
|
||||
|
||||
#include "pibase.h"
|
||||
#ifdef WINDOWS
|
||||
|
||||
#include "pitime.h"
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
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, <);
|
||||
FileTimeToSystemTime(<, &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, <);
|
||||
LocalFileTimeToFileTime(<, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // WINDOWS
|
||||
#endif // PITIME_WIN_H
|
||||
620
lib/main/core/pivariant.cpp
Normal file
620
lib/main/core/pivariant.cpp
Normal file
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Variant type
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
|
||||
void PIVariant::setValueFromString(const PIString & v) {
|
||||
switch (_type) {
|
||||
case PIVariant::pivBool: {setValue(v.toBool());} break;
|
||||
case PIVariant::pivChar: {setValue(v.toChar());} break;
|
||||
case PIVariant::pivUChar: {setValue((uchar)v.toChar());} break;
|
||||
case PIVariant::pivShort: {setValue(v.toShort());} break;
|
||||
case PIVariant::pivUShort: {setValue(v.toUShort());} break;
|
||||
case PIVariant::pivInt: {setValue(v.toInt());} break;
|
||||
case PIVariant::pivUInt: {setValue(v.toUInt());} break;
|
||||
case PIVariant::pivLLong: {setValue(v.toLLong());} break;
|
||||
case PIVariant::pivULLong: {setValue(v.toULLong());} break;
|
||||
case PIVariant::pivFloat: {setValue(v.toFloat());} break;
|
||||
case PIVariant::pivDouble: {setValue(v.toDouble());} break;
|
||||
case PIVariant::pivLDouble: {setValue(v.toLDouble());} break;
|
||||
case PIVariant::pivTime: {} break; // TODO
|
||||
case PIVariant::pivDate: {} break; // TODO
|
||||
case PIVariant::pivDateTime: {} break; // TODO
|
||||
case PIVariant::pivString: {setValue(v);} break;
|
||||
case PIVariant::pivStringList: {setValue(v.split("%|%"));} break;
|
||||
case PIVariant::pivEnum: {PIVariantTypes::Enum r = toEnum(); r.selectName(v); setValue(r);} break;
|
||||
case PIVariant::pivFile: {PIVariantTypes::File r = toFile(); r.file = v; setValue(r);} break;
|
||||
case PIVariant::pivDir: {PIVariantTypes::Dir r = toDir(); r.dir = v; setValue(r);} break;
|
||||
case PIVariant::pivColor: {setValue(PIVariantTypes::Color(v.mid(1).toUInt(16)));} break;
|
||||
case PIVariant::pivIODevice: {setValue(PIVariantTypes::IODevice());} break; // TODO
|
||||
case PIVariant::pivCustom: {} break; // TODO;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
if (s == "color") return PIVariant::pivColor;
|
||||
if (s == "point") return PIVariant::pivPoint;
|
||||
if (s == "rect") return PIVariant::pivRect;
|
||||
if (s == "vector") return PIVariant::pivMathVector;
|
||||
if (s == "matrix") return PIVariant::pivMathMatrix;
|
||||
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::pivColor: return "Color";
|
||||
case PIVariant::pivPoint: return "Point";
|
||||
case PIVariant::pivRect: return "Rect";
|
||||
case PIVariant::pivMathVector: return "Vector";
|
||||
case PIVariant::pivMathMatrix: return "Matrix";
|
||||
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::pivColor: {PIVariantTypes::Color r; ba >> r; return (int)r.rgba;}
|
||||
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.join(";");}
|
||||
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::pivColor: {PIVariantTypes::Color r; ba >> r; return "#" + PIString::fromNumber(r.rgba, 16);}
|
||||
case PIVariant::pivIODevice: {PIVariantTypes::IODevice r; ba >> r; return "IODevice";} // TODO
|
||||
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 File. */
|
||||
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 String returns Dir with string value path. \n
|
||||
* In case of other types returns empty Dir. */
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns variant content as color
|
||||
* \details In case of Color type returns color value. \n
|
||||
* In case of int returns color with int value. \n
|
||||
* In case of other types returns empty Color. */
|
||||
PIVariantTypes::Color PIVariant::toColor() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivColor) {PIVariantTypes::Color r; ba >> r; return r;}
|
||||
if (_type == PIVariant::pivInt) {int v; ba >> v; return PIVariantTypes::Color(v);}
|
||||
if (_type == PIVariant::pivCustom) {return getAsValue<PIVariantTypes::Color>(*this);}
|
||||
return PIVariantTypes::Color();
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns variant content as IODevice
|
||||
* \details In case of IODevice type returns IODevice value. \n
|
||||
* In case of other types returns empty IODevice. */
|
||||
PIVariantTypes::IODevice PIVariant::toIODevice() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivIODevice) {PIVariantTypes::IODevice r; ba >> r; return r;}
|
||||
return PIVariantTypes::IODevice();
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns variant content as point
|
||||
* \details In case of PIPointd type returns point value. \n
|
||||
* In case of other types returns empty PIPointd. */
|
||||
PIPointd PIVariant::toPoint() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivPoint) {PIPointd r; ba >> r; return r;}
|
||||
return PIPointd();
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns variant content as rect
|
||||
* \details In case of PIRectd type returns rect value. \n
|
||||
* In case of other types returns empty PIRectd. */
|
||||
PIRectd PIVariant::toRect() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivRect) {PIRectd r; ba >> r; return r;}
|
||||
return PIRectd();
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns variant content as math vector
|
||||
* \details In case of PIMathVectord type returns rect value. \n
|
||||
* In case of other types returns empty PIMathVectord. */
|
||||
PIMathVectord PIVariant::toMathVector() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivMathVector) {PIMathVectord r; ba >> r; return r;}
|
||||
return PIMathVectord();
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns variant content as math matrix
|
||||
* \details In case of PIMathMatrixd type returns rect value. \n
|
||||
* In case of other types returns empty PIMathMatrixd. */
|
||||
PIMathMatrixd PIVariant::toMathMatrix() const {
|
||||
PIByteArray ba(_content);
|
||||
if (_type == PIVariant::pivMathMatrix) {PIMathMatrixd r; ba >> r; return r;}
|
||||
return PIMathMatrixd();
|
||||
}
|
||||
|
||||
787
lib/main/core/pivariant.h
Normal file
787
lib/main/core/pivariant.h
Normal file
@@ -0,0 +1,787 @@
|
||||
/*! \file pivariant.h
|
||||
* \brief Variant type
|
||||
*
|
||||
* This file declares PIVariant
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Variant type
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIVARIANT_H
|
||||
#define PIVARIANT_H
|
||||
|
||||
#include "pivarianttypes.h"
|
||||
#include "pitime.h"
|
||||
#include "pigeometry.h"
|
||||
#include "pimathmatrix.h"
|
||||
|
||||
|
||||
#ifndef QNX
|
||||
# define CUSTOM_PIVARIANT
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_PIVARIANT
|
||||
|
||||
|
||||
template<typename T>
|
||||
class PIP_EXPORT __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 PIP_EXPORT __PIVariantInfo__ {
|
||||
__PIVariantInfo__() {
|
||||
simple = false;
|
||||
}
|
||||
typedef PIByteArray(*castHelperFunc)(PIByteArray);
|
||||
PIMap<PIString, castHelperFunc> cast;
|
||||
PIString typeName;
|
||||
bool simple;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct PIP_EXPORT __PIVariantTypeInfo__ {
|
||||
typedef T PureType;
|
||||
typedef const T ConstPureType;
|
||||
typedef T * PointerType;
|
||||
typedef const T * ConstPointerType;
|
||||
typedef T & ReferenceType;
|
||||
typedef const T & ConstReferenceType;
|
||||
};
|
||||
|
||||
#define __TYPEINFO_SINGLE(PT, T) \
|
||||
template<> struct __PIVariantTypeInfo__<T> { \
|
||||
typedef PT PureType; \
|
||||
typedef const PT ConstPureType; \
|
||||
typedef PT * PointerType; \
|
||||
typedef const PT * ConstPointerType; \
|
||||
typedef PT & ReferenceType; \
|
||||
typedef const PT & ConstReferenceType; \
|
||||
};
|
||||
|
||||
#define REGISTER_VARIANT_TYPEINFO(T) \
|
||||
__TYPEINFO_SINGLE(T, T &) \
|
||||
__TYPEINFO_SINGLE(T, const T) \
|
||||
__TYPEINFO_SINGLE(T, const T &)
|
||||
|
||||
|
||||
class PIP_EXPORT __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;} \
|
||||
REGISTER_VARIANT_TYPEINFO(classname)
|
||||
|
||||
#define REGISTER_NS_VARIANT_H(ns, classname) \
|
||||
template<> inline PIString __PIVariantFunctions__< ns::classname >::typeNameHelper() {static PIString tn = PIStringAscii(#ns"::"#classname); return tn;} \
|
||||
REGISTER_VARIANT_TYPEINFO(ns::classname)
|
||||
|
||||
#define REGISTER_VARIANT_CPP(classname) \
|
||||
template <typename T> \
|
||||
class PIP_EXPORT __##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 PIP_EXPORT __##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 PIP_EXPORT __##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_TYPEINFO(classname)
|
||||
#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 PIP_EXPORT 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 */ ,
|
||||
pivColor /** PIVariantTypes::Color */ ,
|
||||
pivPoint /** PIPoint */ ,
|
||||
pivRect /** PIRect */ ,
|
||||
pivIODevice /** PIVariantTypes::IODevice */ ,
|
||||
pivMathVector /** PIMathVectord */ ,
|
||||
pivMathMatrix /** PIMathMatrixd */ ,
|
||||
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);}
|
||||
|
||||
//! Constructs variant from color
|
||||
PIVariant(const PIVariantTypes::Color & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from IODevice
|
||||
PIVariant(const PIVariantTypes::IODevice & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from point
|
||||
PIVariant(const PIPointd & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from rect
|
||||
PIVariant(const PIRectd & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from MathVector
|
||||
PIVariant(const PIMathVectord & v) {initType(v);}
|
||||
|
||||
//! Constructs variant from MathMatrix
|
||||
PIVariant(const PIMathMatrixd & 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);}
|
||||
|
||||
//! Set variant content and type to color
|
||||
void setValue(const PIVariantTypes::Color & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to IODevice
|
||||
void setValue(const PIVariantTypes::IODevice & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to point
|
||||
void setValue(const PIPointd & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to rect
|
||||
void setValue(const PIRectd & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to math vector
|
||||
void setValue(const PIMathVectord & v) {initType(v);}
|
||||
|
||||
//! Set variant content and type to math matrix
|
||||
void setValue(const PIMathMatrixd & v) {initType(v);}
|
||||
|
||||
|
||||
//! Set current value from string without change type
|
||||
void setValueFromString(const PIString & 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;
|
||||
PIVariantTypes::Color toColor() const;
|
||||
PIVariantTypes::IODevice toIODevice() const;
|
||||
PIPointd toPoint() const;
|
||||
PIRectd toRect() const;
|
||||
PIMathVectord toMathVector() const;
|
||||
PIMathMatrixd toMathMatrix() 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);}
|
||||
|
||||
//! 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;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIVariantTypes::Color & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIVariantTypes::IODevice & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIPointd & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;}
|
||||
//! Assign operator
|
||||
PIVariant & operator =(const PIMathMatrixd & 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;
|
||||
PIVariant::Type t = typeFromName(type);
|
||||
if (t == pivInvalid) {
|
||||
#ifdef CUSTOM_PIVARIANT
|
||||
ret._info = __PIVariantInfoStorage__::get()->map->value(type, 0);
|
||||
if (ret._info) {
|
||||
t = pivCustom;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
piCout << "Can`t initialize PIVariant from unregistered type \"" << type << "\"!";
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret._type = t;
|
||||
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 PIVariantTypes::Color PIVariant::value() const {return toColor();}
|
||||
template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();}
|
||||
template<> inline PIPointd PIVariant::value() const {return toPoint();}
|
||||
template<> inline PIRectd PIVariant::value() const {return toRect();}
|
||||
|
||||
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 PIVariant::fromValue(const PIVariantTypes::Color & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::IODevice & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);}
|
||||
template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & 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;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::Color>() {return PIVariant::pivColor;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIVariantTypes::IODevice>() {return PIVariant::pivIODevice;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIPointd>() {return PIVariant::pivPoint;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIRectd>() {return PIVariant::pivRect;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIMathVectord>() {return PIVariant::pivMathVector;}
|
||||
template<> inline PIVariant::Type PIVariant::getType<PIMathMatrixd>() {return PIVariant::pivMathMatrix;}
|
||||
|
||||
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)
|
||||
REGISTER_NS_VARIANT(PIVariantTypes, Color)
|
||||
REGISTER_NS_VARIANT(PIVariantTypes, IODevice)
|
||||
REGISTER_VARIANT(PIPointd)
|
||||
REGISTER_VARIANT(PIRectd)
|
||||
REGISTER_VARIANT(PIMathVectord)
|
||||
REGISTER_VARIANT(PIMathMatrixd)
|
||||
|
||||
|
||||
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
|
||||
152
lib/main/core/pivarianttypes.cpp
Normal file
152
lib/main/core/pivarianttypes.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Variant types
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pivarianttypes.h"
|
||||
#include "pipropertystorage.h"
|
||||
#include "piiodevice.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::IODevice::IODevice() {
|
||||
mode = PIIODevice::ReadWrite;
|
||||
options = 0;
|
||||
}
|
||||
|
||||
|
||||
void PIVariantTypes::IODevice::set(const PIPropertyStorage & ps) {
|
||||
props.clear();
|
||||
props << ps;
|
||||
}
|
||||
|
||||
|
||||
PIPropertyStorage PIVariantTypes::IODevice::get() const {
|
||||
PIPropertyStorage ret;
|
||||
PIByteArray ba = props;
|
||||
if (!ba.isEmpty()) ba >> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString PIVariantTypes::IODevice::toPICout() const {
|
||||
PIString s;
|
||||
s << "IODevice(" << prefix << ", mode=";
|
||||
int rwc = 0;
|
||||
if (mode & 1) {s << "r"; ++rwc;}
|
||||
if (mode & 2) {s << "w"; ++rwc;}
|
||||
if (rwc == 1) s << "o";
|
||||
s << ", flags=";
|
||||
if (options != 0) {
|
||||
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead])
|
||||
s << " br";
|
||||
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite])
|
||||
s << " bw";
|
||||
}
|
||||
PIPropertyStorage ps = get();
|
||||
piForeachC (PIPropertyStorage::Property & p, ps) {
|
||||
s << ", " << p.name << "=\"" << p.value.toString() << "\"";
|
||||
}
|
||||
s << ")";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIVariantTypes::Enumerator & v) {
|
||||
enum_list << v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIString & v) {
|
||||
if (enum_list.isEmpty()) {
|
||||
enum_list << Enumerator(0, v);
|
||||
} else {
|
||||
enum_list << Enumerator(enum_list.back().value+1, v);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIStringList & v) {
|
||||
piForeachC (PIString & s, v)
|
||||
(*this) << s;
|
||||
return *this;
|
||||
}
|
||||
182
lib/main/core/pivarianttypes.h
Normal file
182
lib/main/core/pivarianttypes.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/*! \file pivarianttypes.h
|
||||
* \brief Variant type
|
||||
*
|
||||
* This file declares PIVariant
|
||||
*/
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Variant types
|
||||
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 Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PIVARIANTYPES_H
|
||||
#define PIVARIANTYPES_H
|
||||
|
||||
#include "pistringlist.h"
|
||||
|
||||
|
||||
class PIPropertyStorage;
|
||||
|
||||
|
||||
namespace PIVariantTypes {
|
||||
|
||||
/**
|
||||
* @brief name-value pair
|
||||
*/
|
||||
struct PIP_EXPORT Enumerator {
|
||||
Enumerator(int v = 0, const PIString & n = PIString()): value(v), name(n) {}
|
||||
int value;
|
||||
PIString name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Collection of PIVariantTypes::Enumerator. It's replace classic c-style enum.
|
||||
* Contains elements with unique name and not uniqueue values.
|
||||
*/
|
||||
struct PIP_EXPORT Enum {
|
||||
Enum(const PIString & n = PIString()): enum_name(n) {}
|
||||
PIString toString() const {return selected;} // obsolete
|
||||
|
||||
/**
|
||||
* @brief Find selected value.
|
||||
* @return selected value, otherwrise 0
|
||||
*/
|
||||
int selectedValue() const;
|
||||
|
||||
/**
|
||||
* @brief Get selected name
|
||||
* @return selected name, otherwrise empty PIString
|
||||
*/
|
||||
PIString selectedName() const {return selected;}
|
||||
|
||||
/**
|
||||
* @brief Select value if exists in Enum. If Enum contains several PIVariantTypes::Enumerator with same values,
|
||||
* first PIVariantTypes::Enumerator will selected
|
||||
* @param v value for selection
|
||||
* @return true if value exists in Enum, false otherwrise
|
||||
*/
|
||||
bool selectValue(int v);
|
||||
|
||||
/**
|
||||
* @brief Select name if exists in enum
|
||||
* @param n name for selection
|
||||
* @return true if name exists in Enum, false otherwrise
|
||||
*/
|
||||
bool selectName(const PIString & n);
|
||||
|
||||
/**
|
||||
* @brief Find PIVariantTypes::Enumerator with specific name and return it value
|
||||
* @param n name for search
|
||||
* @return value of founded PIVariantTypes::Enumerator, 0 otherwrise
|
||||
*/
|
||||
int value(const PIString & n) const;
|
||||
|
||||
/**
|
||||
* @brief Find first PIVariantTypes::Enumerator with specific value and return it name
|
||||
* @param v value for search
|
||||
* @return name of founded PIVariantTypes::Enumerator, empty string otherwrise
|
||||
*/
|
||||
PIString name(int v) const;
|
||||
|
||||
/**
|
||||
* @brief Make vector of Enum values
|
||||
*/
|
||||
PIVector<int> values() const;
|
||||
|
||||
/**
|
||||
* @brief Make vector of Enum names
|
||||
*/
|
||||
PIStringList names() const;
|
||||
PIString enum_name;
|
||||
PIString selected;
|
||||
PIVector<Enumerator> enum_list;
|
||||
|
||||
/**
|
||||
* @brief Add PIVariantTypes::Enumerator to Enum
|
||||
*/
|
||||
Enum & operator <<(const Enumerator & v);
|
||||
|
||||
/**
|
||||
* @brief Add PIVariantTypes::Enumerator element to Enum. Element contains specific name and value more per
|
||||
* unit then last element. If the is no elements, contains zero value.
|
||||
* @param v name for new PIVariantTypes::Enumerator element
|
||||
*/
|
||||
Enum & operator <<(const PIString & v);
|
||||
|
||||
/**
|
||||
* @brief Add PIVariantTypes::Enumerator element for each name in vector
|
||||
*/
|
||||
Enum & operator <<(const PIStringList & v);
|
||||
};
|
||||
|
||||
struct PIP_EXPORT 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 PIP_EXPORT Dir {
|
||||
Dir(const PIString & d = PIString(), bool abs = false): dir(d), is_abs(abs) {}
|
||||
PIString toString() const {return dir;}
|
||||
PIString dir;
|
||||
bool is_abs;
|
||||
};
|
||||
|
||||
struct PIP_EXPORT Color {
|
||||
Color(uint v = 0) {rgba = v;}
|
||||
uint rgba;
|
||||
};
|
||||
|
||||
struct PIP_EXPORT IODevice {
|
||||
IODevice();
|
||||
void set(const PIPropertyStorage & ps);
|
||||
PIPropertyStorage get() const;
|
||||
PIString toPICout() const;
|
||||
PIString prefix;
|
||||
int mode; // PIIODevice::DeviceMode
|
||||
int options; // PIIODevice::DeviceOptions
|
||||
PIByteArray props;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::Color & v) {s << v.rgba; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::Color & v) {s >> v.rgba; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::Color & v) {s.saveControl(); s << PICoutManipulators::Hex << "Color(#" << v.rgba << ")"; s.restoreControl(); return s;}
|
||||
|
||||
inline PIByteArray & operator <<(PIByteArray & s, const PIVariantTypes::IODevice & v) {s << v.prefix << v.mode << v.options << v.props; return s;}
|
||||
inline PIByteArray & operator >>(PIByteArray & s, PIVariantTypes::IODevice & v) {s >> v.prefix >> v.mode >> v.options >> v.props; return s;}
|
||||
inline PICout operator <<(PICout s, const PIVariantTypes::IODevice & v) {s << v.toPICout(); return s;}
|
||||
|
||||
#endif // PIVARIANTYPES_H
|
||||
Reference in New Issue
Block a user