985 lines
30 KiB
C++
985 lines
30 KiB
C++
/*! \file piincludes.h
|
|
* \brief Global includes of PIP
|
|
*
|
|
* This file include all needed system headers, STL
|
|
* and declare many useful macros and functions
|
|
*/
|
|
/*
|
|
PIP - Platform Independent Primitives
|
|
Global includes
|
|
Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef PIINCLUDES_H
|
|
#define PIINCLUDES_H
|
|
|
|
//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
|
|
#define PIP_VERSION 0x000400
|
|
|
|
//! Major value of PIP version
|
|
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
|
|
|
|
//! Minor value of PIP version
|
|
#define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8
|
|
|
|
//! Revision value of PIP version
|
|
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF
|
|
|
|
//! Suffix of PIP version
|
|
#define PIP_VERSION_SUFFIX "_prealpha"
|
|
|
|
#ifdef DOXYGEN
|
|
|
|
//! 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
|
|
# define QNX
|
|
|
|
//! 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 use "rt" library for timers implementation
|
|
# define PIP_TIMER_RT
|
|
|
|
//! Define this macro to use STL implementation of containers, else PIP implementation will be used
|
|
# define PIP_CONTAINERS_STL
|
|
|
|
#endif
|
|
|
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
|
# define WINDOWS
|
|
# define ARCH_BITS_32
|
|
#endif
|
|
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
|
|
# define WINDOWS
|
|
# define ARCH_BITS_64
|
|
#endif
|
|
#if defined(__QNX__) || defined(__QNXNTO__)
|
|
# define QNX
|
|
#endif
|
|
#ifdef __FreeBSD__
|
|
# define FREE_BSD
|
|
#endif
|
|
#if defined(__APPLE__) || defined(__MACH__)
|
|
# define MAC_OS
|
|
#endif
|
|
#if defined(__ANDROID__) || defined(_ANDROID_) || defined(ANDROID)
|
|
# ifndef ANDROID
|
|
# define ANDROID
|
|
# endif
|
|
#endif
|
|
#ifndef WINDOWS
|
|
# ifndef QNX
|
|
# ifndef FREE_BSD
|
|
# ifndef MAC_OS
|
|
# ifndef ANDROID
|
|
# define LINUX
|
|
# endif
|
|
# endif
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef WINDOWS
|
|
# if defined(__LP64__) || defined(_LP64_) || defined(LP64)
|
|
# define ARCH_BITS_64
|
|
# else
|
|
# define ARCH_BITS_32
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef __GNUC__
|
|
# define CC_GCC
|
|
# define CC_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
|
|
# if CC_GCC_VERSION > 0x025F // > 2.95
|
|
# ifdef LINUX
|
|
# define HAS_LOCALE
|
|
# endif
|
|
# pragma GCC diagnostic ignored "-Wformat"
|
|
# pragma GCC diagnostic ignored "-Wformat-extra-args"
|
|
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
|
# endif
|
|
# ifdef ANDROID
|
|
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
# pragma GCC diagnostic ignored "-Wextra"
|
|
# pragma GCC diagnostic ignored "-Wliteral-suffix"
|
|
# endif
|
|
# define DEPRECATED __attribute__((deprecated))
|
|
#elif defined(_MSC_VER)
|
|
# define CC_VC
|
|
# 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)
|
|
# define DEPRECATED
|
|
# ifdef ARCH_BITS_32
|
|
typedef long ssize_t;
|
|
# else
|
|
typedef long long ssize_t;
|
|
# endif
|
|
#else
|
|
# define CC_OTHER
|
|
# define DEPRECATED
|
|
#endif
|
|
|
|
#ifdef WINDOWS
|
|
# ifdef CC_GCC
|
|
# define typeof __typeof
|
|
# endif
|
|
#else
|
|
# define typeof __typeof__
|
|
#endif
|
|
|
|
#include "pip_export.h"
|
|
#if defined(DOXYGEN) || defined(CC_GCC) || defined(PICODE)
|
|
# undef PIP_EXPORT
|
|
# define PIP_EXPORT
|
|
#endif
|
|
#include <iostream>
|
|
#ifdef CC_GCC
|
|
# include <unistd.h>
|
|
#endif
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#ifndef QNX
|
|
# include <cstdio>
|
|
# include <cstdlib>
|
|
# include <clocale>
|
|
#else
|
|
# include <stdio.h>
|
|
# include <locale.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <cctype>
|
|
#include <ctime>
|
|
#include <csignal>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
//#include <signal.h>
|
|
#include <typeinfo>
|
|
#include <algorithm>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <list>
|
|
#include <queue>
|
|
#include <deque>
|
|
#include <stack>
|
|
#include <set>
|
|
#include <map>
|
|
#ifdef WINDOWS
|
|
# include <conio.h>
|
|
# include <io.h>
|
|
# include <winsock2.h>
|
|
# ifdef CC_VC
|
|
# define SHUT_RDWR 2
|
|
# pragma comment(lib, "Ws2_32.lib")
|
|
# pragma comment(lib, "Iphlpapi.lib")
|
|
# else
|
|
# define SHUT_RDWR SD_BOTH
|
|
# endif
|
|
# include <windows.h>
|
|
# include <wincon.h>
|
|
# include <iphlpapi.h>
|
|
typedef int socklen_t;
|
|
typedef void(*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
|
|
extern FILETIME __pi_ftjan1970;
|
|
extern long long __pi_perf_freq;
|
|
extern PINtSetTimerResolution setTimerResolutionAddr;
|
|
inline long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
|
|
inline void __PISetTimerResolution() {if (setTimerResolutionAddr == NULL) return; ULONG ret; setTimerResolutionAddr(1, TRUE, &ret);}
|
|
#else
|
|
# include <netinet/in.h>
|
|
# include <arpa/inet.h>
|
|
# include <sys/socket.h>
|
|
# include <fcntl.h>
|
|
# include <sys/ioctl.h>
|
|
# include <net/if.h>
|
|
# include <pthread.h>
|
|
# ifndef ANDROID
|
|
# include <ifaddrs.h>
|
|
# endif
|
|
#endif
|
|
#ifdef ANDROID
|
|
//# include "ifaddrs_3rd.h"
|
|
# 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
|
|
# include <mach/mach_traps.h>
|
|
# include <mach/mach.h>
|
|
# include <mach/clock.h>
|
|
# include <crt_externs.h>
|
|
# define environ (*_NSGetEnviron())
|
|
typedef long time_t;
|
|
extern clock_serv_t __pi_mac_clock;
|
|
#endif
|
|
#ifdef LINUX
|
|
# define environ __environ
|
|
#endif
|
|
#if !defined(WINDOWS) && !defined(MAC_OS)
|
|
# define PIP_TIMER_RT
|
|
#endif
|
|
#ifdef FREE_BSD
|
|
extern char ** environ;
|
|
#endif
|
|
#if defined(DOXYGEN) || defined(PICODE)
|
|
# undef PIP_EXPORT
|
|
# define PIP_EXPORT
|
|
# undef DEPRECATED
|
|
# define DEPRECATED
|
|
#endif
|
|
|
|
#include "pimonitor.h"
|
|
|
|
extern PIMonitor piMonitor;
|
|
|
|
//! Macro used for infinite loop
|
|
#define FOREVER for (;;)
|
|
|
|
//! Macro used for infinite wait
|
|
#define FOREVER_WAIT FOREVER msleep(1);
|
|
|
|
//! Macro used for infinite wait
|
|
#define WAIT_FOREVER FOREVER msleep(1);
|
|
|
|
typedef long long llong;
|
|
typedef unsigned char uchar;
|
|
typedef unsigned short int ushort;
|
|
typedef unsigned int uint;
|
|
typedef unsigned long ulong;
|
|
typedef unsigned long long ullong;
|
|
typedef long double ldouble;
|
|
|
|
using std::cout;
|
|
using std::cin;
|
|
using std::endl;
|
|
using std::flush;
|
|
using std::vector;
|
|
using std::list;
|
|
using std::queue;
|
|
using std::deque;
|
|
using std::stack;
|
|
using std::set;
|
|
using std::map;
|
|
using std::multimap;
|
|
using std::string;
|
|
#ifndef QNX
|
|
using std::wstring;
|
|
#else
|
|
typedef std::basic_string<wchar_t> wstring;
|
|
#endif
|
|
|
|
/*! \brief Templated function for swap two values
|
|
* \details Example:\n \snippet piincludes.cpp swap */
|
|
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
|
|
|
|
/*! \brief Templated function for swap two values without "="
|
|
* \details Example:\n \snippet piincludes.cpp swapBinary */
|
|
template<typename T> inline void piSwapBinary(T & f, T & s) {
|
|
static size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
|
|
size_t i = 0;
|
|
for (i = 0; i < j; ++i) {
|
|
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
|
|
((size_t*)(&s))[i] ^= ((size_t*)(&f))[i];
|
|
((size_t*)(&f))[i] ^= ((size_t*)(&s))[i];
|
|
}
|
|
for (i = bs; i < bf; ++i) {
|
|
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
|
|
((uchar*)(&s))[i] ^= ((uchar*)(&f))[i];
|
|
((uchar*)(&f))[i] ^= ((uchar*)(&s))[i];
|
|
}
|
|
}
|
|
|
|
/*! \brief Templated function return round of float falue
|
|
* \details Round is the nearest integer value \n
|
|
* There are some macros:
|
|
* - \c piRoundf for "float"
|
|
* - \c piRoundd for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp round */
|
|
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
|
|
|
|
/*! \brief Templated function return floor of float falue
|
|
* \details Floor is the largest integer that is not greater than value \n
|
|
* There are some macros:
|
|
* - \c piFloorf for "float"
|
|
* - \c piFloord for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp floor */
|
|
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
|
|
|
|
/*! \brief Templated function return ceil of float falue
|
|
* \details Ceil is the smallest integer that is not less than value \n
|
|
* There are some macros:
|
|
* - \c piCeilf for "float"
|
|
* - \c piCeild for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp ceil */
|
|
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
|
|
|
|
/*! \brief Templated function return absolute of numeric falue
|
|
* \details Absolute is the positive or equal 0 value \n
|
|
* There are some macros:
|
|
* - \c piAbss for "short"
|
|
* - \c piAbsi for "int"
|
|
* - \c piAbsl for "long"
|
|
* - \c piAbsll for "llong"
|
|
* - \c piAbsf for "float"
|
|
* - \c piAbsd for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp abs */
|
|
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
|
|
|
|
/*! \brief Templated function return minimum of two values
|
|
* \details There are some macros:
|
|
* - \c piMins for "short"
|
|
* - \c piMini for "int"
|
|
* - \c piMinl for "long"
|
|
* - \c piMinll for "llong"
|
|
* - \c piMinf for "float"
|
|
* - \c piMind for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp min2 */
|
|
template<typename T> inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
|
|
|
|
/*! \brief Templated function return minimum of tree values
|
|
* \details There are some macros:
|
|
* - \c piMins for "short"
|
|
* - \c piMini for "int"
|
|
* - \c piMinl for "long"
|
|
* - \c piMinll for "llong"
|
|
* - \c piMinf for "float"
|
|
* - \c piMind for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp min3 */
|
|
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
|
|
|
|
/*! \brief Templated function return maximum of two values
|
|
* \details There are some macros:
|
|
* - \c piMaxs for "short"
|
|
* - \c piMaxi for "int"
|
|
* - \c piMaxl for "long"
|
|
* - \c piMaxll for "llong"
|
|
* - \c piMaxf for "float"
|
|
* - \c piMaxd for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp max2 */
|
|
template<typename T> inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
|
|
|
|
/*! \brief Templated function return maximum of tree values
|
|
* \details There are some macros:
|
|
* - \c piMaxs for "short"
|
|
* - \c piMaxi for "int"
|
|
* - \c piMaxl for "long"
|
|
* - \c piMaxll for "llong"
|
|
* - \c piMaxf for "float"
|
|
* - \c piMaxd for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp max3 */
|
|
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
|
|
|
|
/*! \brief Templated function return clamped value
|
|
* \details Clamped is the not greater than "max" and not lesser than "min" value \n
|
|
* There are some macros:
|
|
* - \c piClamps for "short"
|
|
* - \c piClampi for "int"
|
|
* - \c piClampl for "long"
|
|
* - \c piClampll for "llong"
|
|
* - \c piClampf for "float"
|
|
* - \c piClampd for "double"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp clamp */
|
|
template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
|
|
|
|
/// Function inverse byte order in memory block
|
|
inline void piLetobe(void * data, int size) {
|
|
for (int i = 0; i < size / 2; i++)
|
|
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
|
|
}
|
|
|
|
/// \brief Templated function that inverse byte order of value "v"
|
|
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
|
|
|
|
/*! \brief Templated function that returns "v" with inversed byte order
|
|
* \details This function used to convert values between little and big endian \n
|
|
* There are some macros:
|
|
* - \c piLetobes for "ushort"
|
|
* - \c piLetobei for "uint"
|
|
* - \c piLetobel for "ulong"
|
|
* - \c piLetobell for "ullong"
|
|
*
|
|
* Example:
|
|
* \snippet piincludes.cpp letobe */
|
|
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
|
|
|
|
// specialization
|
|
template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);}
|
|
template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
|
|
|
DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);}
|
|
DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
|
|
|
#ifdef DOXYGEN
|
|
|
|
/// \deprecated \brief Use \a piLetobe() instead of this function
|
|
ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);}
|
|
|
|
/// \deprecated \brief Use \a piLetobe() instead of this function
|
|
uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
|
|
|
|
#endif
|
|
|
|
#define piRoundf piRound<float>
|
|
#define piRoundd piRound<double>
|
|
#define piFloorf piFloor<float>
|
|
#define piFloord piFloor<double>
|
|
#define piCeilf piCeil<float>
|
|
#define piCeild piCeil<double>
|
|
#define piAbss piAbs<short>
|
|
#define piAbsi piAbs<int>
|
|
#define piAbsl piAbs<long>
|
|
#define piAbsll piAbs<llong>
|
|
#define piAbsf piAbs<float>
|
|
#define piAbsd piAbs<double>
|
|
#define piMins piMin<short>
|
|
#define piMini piMin<int>
|
|
#define piMinl piMin<long>
|
|
#define piMinll piMin<llong>
|
|
#define piMinf piMin<float>
|
|
#define piMind piMin<double>
|
|
#define piMaxs piMax<short>
|
|
#define piMaxi piMax<int>
|
|
#define piMaxl piMax<long>
|
|
#define piMaxll piMax<llong>
|
|
#define piMaxf piMax<float>
|
|
#define piMaxd piMax<double>
|
|
#define piClamps piClamp<short>
|
|
#define piClampi piClamp<int>
|
|
#define piClampl piClamp<long>
|
|
#define piClampll piClamp<llong>
|
|
#define piClampf piClamp<float>
|
|
#define piClampd piClamp<double>
|
|
#define piLetobes piLetobe<ushort>
|
|
#define piLetobei piLetobe<uint>
|
|
#define piLetobel piLetobe<ulong>
|
|
#define piLetobell piLetobe<ullong>
|
|
|
|
extern bool isPIInit;
|
|
|
|
//! global variable enabling output to piCout
|
|
extern PIP_EXPORT bool piDebug;
|
|
|
|
extern string ifconfigPath;
|
|
|
|
class PIInit {
|
|
public:
|
|
PIInit();
|
|
~PIInit();
|
|
private:
|
|
bool fileExists(const string & p) {FILE * f = fopen(p.c_str(), "r"); if (f == 0) return false; fclose(f); return true;}
|
|
#ifdef WINDOWS
|
|
HMODULE ntlib;
|
|
ULONG prev_res;
|
|
#endif
|
|
};
|
|
|
|
extern PIInit piInit;
|
|
extern lconv * currentLocale;
|
|
|
|
#ifdef WINDOWS
|
|
inline int random() {return rand();}
|
|
# ifdef CC_VC
|
|
inline double round(const double & v) {return floor(v + 0.5);}
|
|
# endif
|
|
#endif
|
|
inline bool atob(const string & str) {return str == "1" ? true : false;}
|
|
inline string btos(const bool num) {return num ? "0" : "1";}
|
|
inline string itos(const int num) {
|
|
char ch[256];
|
|
#ifndef CC_VC
|
|
sprintf(ch, "%d", num);
|
|
#else
|
|
sprintf_s(ch, 256, "%d", num);
|
|
#endif
|
|
return string(ch);}
|
|
inline string ltos(const long num) {
|
|
char ch[256];
|
|
#ifndef CC_VC
|
|
sprintf(ch, "%ld", num);
|
|
#else
|
|
sprintf_s(ch, 256, "%ld", num);
|
|
#endif
|
|
return string(ch);}
|
|
inline string uitos(const uint num) {
|
|
char ch[256];
|
|
#ifndef CC_VC
|
|
sprintf(ch, "%u", num);
|
|
#else
|
|
sprintf_s(ch, 256, "%u", num);
|
|
#endif
|
|
return string(ch);}
|
|
inline string ultos(const ulong num) {
|
|
char ch[256];
|
|
#ifndef CC_VC
|
|
sprintf(ch, "%lu", num);
|
|
#else
|
|
sprintf_s(ch, 256, "%lu", num);
|
|
#endif
|
|
return string(ch);}
|
|
inline string ftos(const float num) {
|
|
char ch[256];
|
|
#ifndef CC_VC
|
|
sprintf(ch, "%g", num);
|
|
#else
|
|
sprintf_s(ch, 256, "%g", num);
|
|
#endif
|
|
return string(ch);}
|
|
inline string dtos(const double num) {
|
|
char ch[256];
|
|
#ifndef CC_VC
|
|
sprintf(ch, "%g", num);
|
|
#else
|
|
sprintf_s(ch, 256, "%g", num);
|
|
#endif
|
|
return string(ch);}
|
|
|
|
/*! \fn errorString()
|
|
* \brief Return readable error description in format "code <number> - <description>" */
|
|
#ifdef WINDOWS
|
|
inline string errorString() {
|
|
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 " + itos(err) + " - " + string(msg);
|
|
}
|
|
#else
|
|
inline void errorClear() {errno = 0;}
|
|
inline string errorString() {int e = errno; return "code " + itos(e) + " - " + string(strerror(e));}
|
|
#endif
|
|
|
|
/// Return readable version of PIP
|
|
inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;}
|
|
|
|
/*! \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
|
|
void operator ==(const PIFlags & f) {flags == f.flags;}
|
|
//! compare operator
|
|
void operator ==(const Enum & e) {flags == e;}
|
|
//! compare operator
|
|
void operator ==(const int i) {flags == i;}
|
|
//! compare operator
|
|
void operator !=(const PIFlags & f) {flags != f.flags;}
|
|
//! compare operator
|
|
void operator !=(const Enum & e) {flags != e;}
|
|
//! compare operator
|
|
void operator !=(const int i) {flags != i;}
|
|
//! compare operator
|
|
void operator >(const PIFlags & f) {flags > f.flags;}
|
|
//! compare operator
|
|
void operator >(const Enum & e) {flags > e;}
|
|
//! compare operator
|
|
void operator >(const int i) {flags > i;}
|
|
//! compare operator
|
|
void operator <(const PIFlags & f) {flags < f.flags;}
|
|
//! compare operator
|
|
void operator <(const Enum & e) {flags < e;}
|
|
//! compare operator
|
|
void operator <(const int i) {flags < i;}
|
|
//! compare operator
|
|
void operator >=(const PIFlags & f) {flags >= f.flags;}
|
|
//! compare operator
|
|
void operator >=(const Enum & e) {flags >= e;}
|
|
//! compare operator
|
|
void operator >=(const int i) {flags >= i;}
|
|
//! compare operator
|
|
void operator <=(const PIFlags & f) {flags <= f.flags;}
|
|
//! compare operator
|
|
void operator <=(const Enum & e) {flags <= e;}
|
|
//! compare operator
|
|
void operator <=(const int i) {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;
|
|
};
|
|
|
|
#ifdef DOXYGEN
|
|
|
|
//! \brief Macro used for conditional (piDebug) output to PICout
|
|
# define piCout
|
|
|
|
//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject
|
|
# define piCoutObj
|
|
|
|
#else
|
|
# define piCout if (piDebug) PICout()
|
|
# define piCoutObj if (piDebug && debug()) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]")
|
|
#endif
|
|
|
|
class PIObject;
|
|
class PIMutex;
|
|
extern PIMutex __PICout_mutex__;
|
|
|
|
//! \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 */,
|
|
ClearScreen /*! Clear the screen */,
|
|
SaveContol /*! Save control flags, equivalent to \a saveControl() */,
|
|
RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */
|
|
};
|
|
|
|
//! \brief Enum contains control of PICout
|
|
enum PIP_EXPORT PICoutControl {
|
|
AddNone /*! No controls */ = 0x0,
|
|
AddSpaces /*! Spaces will be appear after each output */ = 0x1,
|
|
AddNewLine /*! New line will be appear after all output */ = 0x2,
|
|
AddQuotes /*! Each string will be quoted */ = 0x4,
|
|
AddAll /*! All controls */ = 0xFFFFFFFF
|
|
};
|
|
|
|
//! \brief Enum contains output format
|
|
enum PIP_EXPORT PICoutFormat {
|
|
Bin /*! Binary representation of integers */ = 0x01,
|
|
Oct /*! Octal representation of integers */ = 0x02,
|
|
Dec /*! Decimal representation of integers */ = 0x04,
|
|
Hex /*! Hexadecimal representation of integers */ = 0x08,
|
|
Bold /*! Bold */ = 0x10,
|
|
Faint /*! */ = 0x20,
|
|
Italic /*! */ = 0x40,
|
|
Underline /*! Underline */ = 0x80,
|
|
Blink /*! Blink */ = 0x100,
|
|
Black /*! Black font */ = 0x400,
|
|
Red /*! Red font */ = 0x800,
|
|
Green /*! Green font */ = 0x1000,
|
|
Blue /*! Blue font */ = 0x2000,
|
|
Yellow /*! Yellow font */ = 0x4000,
|
|
Magenta /*! Magenta font */ = 0x8000,
|
|
Cyan /*! Cyan font */ = 0x10000,
|
|
White /*! White font */ = 0x20000,
|
|
BackBlack /*! Black background */ = 0x40000,
|
|
BackRed /*! Red background */ = 0x80000,
|
|
BackGreen /*! Green background */ = 0x100000,
|
|
BackBlue /*! Blue background */ = 0x200000,
|
|
BackYellow /*! Yellow background */ = 0x400000,
|
|
BackMagenta /*! Magenta background */ = 0x800000,
|
|
BackCyan /*! Cyan background */ = 0x1000000,
|
|
BackWhite /*! White background */ = 0x2000000,
|
|
Default /*! Default format */ = 0x4000000
|
|
};
|
|
};
|
|
|
|
using namespace PICoutManipulators;
|
|
|
|
typedef PIFlags<PICoutControl> PICoutControls;
|
|
|
|
class PIP_EXPORT PICout {
|
|
public:
|
|
//! Default constructor with default features (AddSpaces and AddNewLine)
|
|
PICout(PIFlags<PICoutControl> controls = AddSpaces | AddNewLine);
|
|
|
|
PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), cnb_(other.cnb_), attr_(other.attr_), co_(other.co_) {;}
|
|
~PICout();
|
|
|
|
//! Output operator for strings with <tt>"const char * "</tt> type
|
|
PICout operator <<(const char * v) {space(); quote(); std::cout << v; quote(); return *this;}
|
|
|
|
//! Output operator for strings with <tt>"std::string"</tt> type
|
|
PICout operator <<(const string & v) {space(); quote(); std::cout << v; quote(); return *this;}
|
|
|
|
//! Output operator for boolean values
|
|
PICout operator <<(const bool v) {space(); std::cout << (v ? "true" : "false"); return *this;}
|
|
|
|
//! Output operator for <tt>"char"</tt> values
|
|
PICout operator <<(const char v) {space(); std::cout << v; return *this;}
|
|
|
|
//! 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 PICoutSpecialChar v) {
|
|
switch (v) {
|
|
case Null: std::cout << char(0); break;
|
|
case NewLine: std::cout << '\n'; fo_ = true; break;
|
|
case Tab: std::cout << '\t'; break;
|
|
case Esc:
|
|
#ifdef CC_VC
|
|
std::cout << char(27);
|
|
#else
|
|
std::cout << '\e';
|
|
#endif
|
|
break;
|
|
case Quote: std::cout << '"'; break;
|
|
};
|
|
return *this;
|
|
|
|
}
|
|
|
|
//! Output operator for \a PIFlags<PICoutFormat> values
|
|
PICout operator <<(const PIFlags<PICoutFormat> v) {
|
|
if (v[Bin]) cnb_ = 2;
|
|
if (v[Oct]) cnb_ = 8;
|
|
if (v[Dec]) cnb_ = 10;
|
|
if (v[Hex]) cnb_ = 16;
|
|
if (v[Bold]) applyFormat(Bold);
|
|
if (v[Faint]) applyFormat(Faint);
|
|
if (v[Italic]) applyFormat(Italic);
|
|
if (v[Underline]) applyFormat(Underline);
|
|
if (v[Blink]) applyFormat(Blink);
|
|
if (v[Black]) applyFormat(Black);
|
|
if (v[Red]) applyFormat(Red);
|
|
if (v[Green]) applyFormat(Green);
|
|
if (v[Blue]) applyFormat(Blue);
|
|
if (v[Yellow]) applyFormat(Yellow);
|
|
if (v[Magenta]) applyFormat(Magenta);
|
|
if (v[Cyan]) applyFormat(Cyan);
|
|
if (v[White]) applyFormat(White);
|
|
if (v[BackBlack]) applyFormat(BackBlack);
|
|
if (v[BackRed]) applyFormat(BackRed);
|
|
if (v[BackGreen]) applyFormat(BackGreen);
|
|
if (v[BackBlue]) applyFormat(BackBlue);
|
|
if (v[BackYellow]) applyFormat(BackYellow);
|
|
if (v[BackMagenta]) applyFormat(BackMagenta);
|
|
if (v[BackCyan]) applyFormat(BackCyan);
|
|
if (v[BackWhite]) applyFormat(BackWhite);
|
|
if (v[Default]) applyFormat(Default);
|
|
return *this;
|
|
}
|
|
|
|
//! Output operator for \a PICoutFormat values
|
|
PICout operator <<(const PICoutFormat v) {
|
|
switch (v) {
|
|
case Bin: cnb_ = 2; break;
|
|
case Oct: cnb_ = 8; break;
|
|
case Dec: cnb_ = 10; break;
|
|
case Hex: cnb_ = 16; break;
|
|
default: applyFormat(v);
|
|
};
|
|
return *this;
|
|
}
|
|
|
|
//! Do some action
|
|
PICout operator <<(const PICoutAction v);
|
|
|
|
//! Set control flag "c" is "on" state
|
|
PICout & setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;}
|
|
|
|
//! Set control flags "c" and if "save" exec \a saveControl()
|
|
PICout & setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;}
|
|
|
|
//! Save control flags to internal stack \sa \a restoreControl()
|
|
PICout & saveControl() {cos_.push(co_); return *this;}
|
|
|
|
//! Restore control flags from internal stack \sa \a saveControl()
|
|
PICout & restoreControl() {if (!cos_.empty()) {co_ = cos_.top(); cos_.pop();} return *this;}
|
|
|
|
/*! \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() */
|
|
inline PICout & space() {if (!fo_ && co_[AddSpaces]) std::cout << ' '; fo_ = false; return *this;}
|
|
|
|
/*! \brief Conditional put quote character to output
|
|
* \details If control \a AddQuotes is set
|
|
* quote character is put \sa \a space(), \a newLine() */
|
|
inline PICout & quote() {if (co_[AddQuotes]) std::cout << '"'; fo_ = false; return *this;}
|
|
|
|
/*! \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() */
|
|
inline PICout & newLine() {if (co_[AddNewLine]) std::cout << std::endl; fo_ = false; return *this;}
|
|
|
|
private:
|
|
void applyFormat(PICoutFormat f);
|
|
|
|
bool fo_, cc_, fc_;
|
|
int cnb_, attr_;
|
|
PICoutControls co_;
|
|
std::stack<PICoutControls> cos_;
|
|
#ifdef WINDOWS
|
|
static void * hOut;
|
|
static WORD dattr;
|
|
static DWORD smode;
|
|
#endif
|
|
};
|
|
|
|
#endif // PIINCLUDES_H
|