Merge branch 'master' of https://git.shs.tools/SHS/pip into doxygen-ru

This commit is contained in:
Andrey
2022-03-14 12:31:51 +03:00
50 changed files with 623 additions and 353 deletions
+144 -141
View File
@@ -1,15 +1,15 @@
/*! @file pibase.h
* \brief
* \~english Base types and functions
* \~russian Базовые типы и методы
* \~russian Áàçîâûå òèïû è ìåòîäû
*
* \details
* \~english
* This file implements first layer above the system and
* declares some basic useful functions
* \~russian
* Этот файл реализует первый слой после системы и объявляет
* несколько базовых полезных методов
* Ýòîò ôàéë ðåàëèçóåò ïåðâûé ñëîé ïîñëå ñèñòåìû è îáúÿâëÿåò
* íåñêîëüêî áàçîâûõ ïîëåçíûõ ìåòîäîâ
*/
/*
PIP - Platform Independent Primitives
@@ -38,16 +38,14 @@
#include "pip_export.h"
#include "pip_defs.h"
#include "string.h"
#include <limits>
//! \~english
//! Meta-information section for any entity.
//! Parsing by \a pip_cmg and can be accessed by \a PICodeInfo.
//! Contains sequence of key=value pairs, e.g.
//! \~russian
//! Секция метаинформации для любой сущности.
//! Парсится \a pip_cmg и доступна с помощью \a PICodeInfo.
//! Содержит набор пар ключ=значение, например
//! Ñåêöèÿ ìåòàèíôîðìàöèè äëÿ ëþáîé ñóùíîñòè.
//! Ïàðñèòñÿ \a pip_cmg è äîñòóïíà ñ ïîìîùüþ \a PICodeInfo.
//! Ñîäåðæèò íàáîð ïàð êëþ÷=çíà÷åíèå, íàïðèìåð
//! \~
//! PIMETA(id=12345,tag="my string")
#define PIMETA(...)
@@ -56,135 +54,141 @@
//! \brief
//! \~english Major value of PIP version
//! \~russian Мажорная версия PIP
//! \~russian Ìàæîðíàÿ âåðñèÿ PIP
# define PIP_VERSION_MAJOR
//! \brief
//! \~english Minor value of PIP version
//! \~russian Минорная версия PIP
//! \~russian Ìèíîðíàÿ âåðñèÿ PIP
# define PIP_VERSION_MINOR
//! \brief
//! \~english Revision value of PIP version
//! \~russian Ревизия версии PIP
//! \~russian Ðåâèçèÿ âåðñèè PIP
# define PIP_VERSION_REVISION
//! \brief
//! \~english Suffix of PIP version
//! \~russian Суффикс версии PIP
//! \~russian Ñóôôèêñ âåðñèè PIP
# define PIP_VERSION_SUFFIX
//! \brief
//! \~english Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
//! \~russian Версия PIP в hex - 0x##(Major)##(Minor)##(Revision)
//! \~russian Âåðñèÿ PIP â hex - 0x##(Major)##(Minor)##(Revision)
# define PIP_VERSION
//! \brief
//! \~english Macro is defined when compile-time debug is enabled
//! \~russian Макрос объявлен когда включена compile-time отладка
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà âêëþ÷åíà compile-time îòëàäêà
# define PIP_DEBUG
//! \brief
//! \~english Macro is defined when host is any Windows
//! \~russian Макрос объявлен когда система Windows
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà Windows
# define WINDOWS
//! \brief
//! \~english Macro is defined when host is QNX or Blackberry
//! \~russian Макрос объявлен когда система QNX или Blackberry
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà QNX èëè Blackberry
# define QNX
//! \brief
//! \~english Macro is defined when host is Blackberry
//! \~russian Макрос объявлен когда система Blackberry
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà Blackberry
# define BLACKBERRY
//! \brief
//! \~english Macro is defined when host is FreeBSD
//! \~russian Макрос объявлен когда система FreeBSD
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà FreeBSD
# define FREE_BSD
//! \brief
//! \~english Macro is defined when host is Mac OS
//! \~russian Макрос объявлен когда система Mac OS
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà Mac OS
# define MAC_OS
//! \brief
//! \~english Macro is defined when host is Android
//! \~russian Макрос объявлен когда система Android
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà Android
# define ANDROID
//! \brief
//! \~english Macro is defined when host is any Linux
//! \~russian Макрос объявлен когда система Linux
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà ñèñòåìà Linux
# define LINUX
//! \brief
//! \~english Macro is defined when compiler is GCC or MinGW
//! \~russian Макрос объявлен когда компилятор GCC или MinGW
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà êîìïèëÿòîð GCC èëè MinGW
# define CC_GCC
//! \brief
//! \~english Macro is defined when PIP is decided that host is support language
//! \~russian Макрос объявлен когда PIP решил что система поддерживает локализацию
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà PIP ðåøèë ÷òî ñèñòåìà ïîääåðæèâàåò ëîêàëèçàöèþ
# define HAS_LOCALE
//! \brief
//! \~english Macro is defined when compiler is Visual Studio
//! \~russian Макрос объявлен когда компилятор Visual Studio
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà êîìïèëÿòîð Visual Studio
# define CC_VC
//! \brief
//! \~english Macro is defined when compiler is unknown
//! \~russian Макрос объявлен когда компилятор неизвестен
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà êîìïèëÿòîð íåèçâåñòåí
# define CC_OTHER
//! \brief
//! \~english Macro is defined when PIP can use "rt" library for "PITimer::ThreadRT" timers implementation
//! \~russian Макрос объявлен когда PIP может использовать библиотеку "rt" для "PITimer::ThreadRT" реализации таймера
//! \~russian Ìàêðîñ îáúÿâëåí êîãäà PIP ìîæåò èñïîëüçîâàòü áèáëèîòåêó "rt" äëÿ "PITimer::ThreadRT" ðåàëèçàöèè òàéìåðà
# define PIP_TIMER_RT
//! \brief
//! \~english Macro to declare private section, "export" is optional
//! \~russian Макрос для объявления частной секции, "export" необязателен
//! \~russian Ìàêðîñ äëÿ îáúÿâëåíèÿ ÷àñòíîé ñåêöèè, "export" íåîáÿçàòåëåí
# define PRIVATE_DECLARATION(export)
//! \brief
//! \~english Macro to start definition of private section
//! \~russian Макрос для начала реализации частной секции
//! \~russian Ìàêðîñ äëÿ íà÷àëà ðåàëèçàöèè ÷àñòíîé ñåêöèè
# define PRIVATE_DEFINITION_START(Class)
//! \brief
//! \~english Macro to end definition of private section
//! \~russian Макрос для окончания реализации частной секции
//! \~russian Ìàêðîñ äëÿ îêîí÷àíèÿ ðåàëèçàöèè ÷àñòíîé ñåêöèè
# define PRIVATE_DEFINITION_END(Class)
//! \brief
//! \~english Macro to access private section by pointer
//! \~russian Макрос для доступа к частной секции
//! \~russian Ìàêðîñ äëÿ äîñòóïà ê ÷àñòíîé ñåêöèè
# define PRIVATE
//! \brief
//! \~english Macro to access private section by pointer without brakes ()
//! \~russian Макрос для доступа к частной секции без обрамляющих скобок ()
//! \~russian Ìàêðîñ äëÿ äîñòóïà ê ÷àñòíîé ñåêöèè áåç îáðàìëÿþùèõ ñêîáîê ()
# define PRIVATEWB
//! \brief
//! \~english Macro to start static initializer
//! \~russian Макрос для начала статической инициализации
//! \~russian Ìàêðîñ äëÿ íà÷àëà ñòàòè÷åñêîé èíèöèàëèçàöèè
# define STATIC_INITIALIZER_BEGIN
//! \brief
//! \~english Macro to end static initializer
//! \~russian Макрос для окончания статической инициализации
//! \~russian Ìàêðîñ äëÿ îêîí÷àíèÿ ñòàòè÷åñêîé èíèöèàëèçàöèè
# define STATIC_INITIALIZER_END
#endif //DOXYGEN
#ifdef CC_AVR_GCC
# include <ArduinoSTL.h>
#endif
#include <functional>
#include <cstddef>
#include <cassert>
#include <limits>
#include <atomic>
#ifdef WINDOWS
# ifdef CC_VC
# define SHUT_RDWR 2
@@ -227,7 +231,6 @@
#ifdef NDEBUG
# undef NDEBUG
#endif
#include <cassert>
#ifndef assert
# define assert(x)
# define assertm(exp, msg)
@@ -340,7 +343,7 @@
} _PIP_ADD_COUNTER(_pip_initializer_);
#ifdef FREERTOS
#ifdef MICRO_PIP
# define PIP_MIN_MSLEEP 10.
#else
# define PIP_MIN_MSLEEP 1.
@@ -349,30 +352,30 @@
//! \brief
//! \~english Macro used for infinite loop
//! \~russian Макрос для бесконечного цикла
//! \~russian Ìàêðîñ äëÿ áåñêîíå÷íîãî öèêëà
#define FOREVER for (;;)
//! \brief
//! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания
//! \~russian Ìàêðîñ äëÿ áåñêîíå÷íîãî îæèäàíèÿ
#define FOREVER_WAIT FOREVER piMinSleep;
//! \brief
//! \~english Macro used for infinite wait
//! \~russian Макрос для бесконечного ожидания
//! \~russian Ìàêðîñ äëÿ áåñêîíå÷íîãî îæèäàíèÿ
#define WAIT_FOREVER FOREVER piMinSleep;
//! \brief
//! \~english Global variable enabling output to piCout, default is true
//! \~russian Глобальная переменная, включающая вывод в piCout, при старте true
//! \~russian Ãëîáàëüíàÿ ïåðåìåííàÿ, âêëþ÷àþùàÿ âûâîä â piCout, ïðè ñòàðòå true
extern PIP_EXPORT bool piDebug;
//! \brief
//! \~english Global variable that set minimum real update interval
//! for function PIInit::mountInfo(), default is 10000 ms
//! \~russian Глобальная переменная минимального ожидания между реальным обновлением
//! в методе PIInit::mountInfo(), по умолчанию 10000 мс
//! \~russian Ãëîáàëüíàÿ ïåðåìåííàÿ ìèíèìàëüíîãî îæèäàíèÿ ìåæäó ðåàëüíûì îáíîâëåíèåì
//! â ìåòîäå PIInit::mountInfo(), ïî óìîë÷àíèþ 10000 ìñ
extern PIP_EXPORT double piMountInfoRefreshIntervalMs;
typedef unsigned char uchar;
@@ -385,18 +388,18 @@ typedef long double ldouble;
//! \brief
//! \~english Templated function for swap two values
//! \~russian Шаблонный метод для перестановки двух значений
//! \~russian Øàáëîííûé ìåòîä äëÿ ïåðåñòàíîâêè äâóõ çíà÷åíèé
//! \details
//! \~english Example:\n \snippet piincludes.cpp swap
//! \~russian Пример:\n \snippet piincludes.cpp swap
//! \~russian Ïðèìåð:\n \snippet piincludes.cpp swap
template<typename T> inline void piSwap(T & f, T & s) {T t(std::move(f)); f = std::move(s); s = std::move(t);}
//! \brief
//! \~english Templated function for swap two values without "="
//! \~russian Шаблонный метод для перестановки двух значений без использования "="
//! \~russian Øàáëîííûé ìåòîä äëÿ ïåðåñòàíîâêè äâóõ çíà÷åíèé áåç èñïîëüçîâàíèÿ "="
//! \details
//! \~english Example:\n \snippet piincludes.cpp swapBinary
//! \~russian Пример:\n \snippet piincludes.cpp swapBinary
//! \~russian Ïðèìåð:\n \snippet piincludes.cpp swapBinary
template<typename T> inline void piSwapBinary(T & f, T & s) {
if ((size_t*)&f == (size_t*)&s) return;
size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T);
@@ -433,10 +436,10 @@ template<> inline void piSwapBinary(const void *& f, const void *& s) {
//! \brief
//! \~english Function for compare two values without "==" by raw content
//! \~russian Метод для сравнения двух значений без использования "==" (по сырому содержимому)
//! \~russian Ìåòîä äëÿ ñðàâíåíèÿ äâóõ çíà÷åíèé áåç èñïîëüçîâàíèÿ "==" (ïî ñûðîìó ñîäåðæèìîìó)
//! \details
//! \~english Example:\n \snippet piincludes.cpp compareBinary
//! \~russian Пример:\n \snippet piincludes.cpp compareBinary
//! \~russian Ïðèìåð:\n \snippet piincludes.cpp compareBinary
inline bool piCompareBinary(const void * f, const void * s, size_t size) {
for (size_t i = 0; i < size; ++i)
if (((const uchar*)f)[i] != ((const uchar*)s)[i])
@@ -446,7 +449,7 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) {
//! \brief
//! \~english Templated function return round of float falue
//! \~russian Шаблонный метод, возвращающий округленное значение
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé îêðóãëåííîå çíà÷åíèå
//! \details
//! \~english
//! Round is the nearest integer value \n
@@ -457,18 +460,18 @@ inline bool piCompareBinary(const void * f, const void * s, size_t size) {
//! Example:
//! \snippet piincludes.cpp round
//! \~russian
//! Округленное значение - это ближайшее целое число\n
//! Есть несколько макросов:
//! - \c piRoundf для "float"
//! - \c piRoundd для "double"
//! Îêðóãëåííîå çíà÷åíèå - ýòî áëèæàéøåå öåëîå ÷èñëî\n
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piRoundf äëÿ "float"
//! - \c piRoundd äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp round
template<typename T> inline constexpr int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
//! \brief
//! \~english Templated function return floor of float falue
//! \~russian Шаблонный метод, возвращающий floor значение
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé floor çíà÷åíèå
//! \details
//! \~english
//! Floor is the largest integer that is not greater than "v" \n
@@ -479,18 +482,18 @@ template<typename T> inline constexpr int piRound(const T & v) {return int(v >=
//! Example:
//! \snippet piincludes.cpp floor
//! \~russian
//! Floor значение - это наибольшее целое, не большее чем "v"\n
//! Есть несколько макросов:
//! - \c piFloorf для "float"
//! - \c piFloord для "double"
//! Floor çíà÷åíèå - ýòî íàèáîëüøåå öåëîå, íå áîëüøåå ÷åì "v"\n
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piFloorf äëÿ "float"
//! - \c piFloord äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp floor
template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
//! \brief
//! \~english Templated function return ceil of float falue
//! \~russian Шаблонный метод, возвращающий ceil значение
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ceil çíà÷åíèå
//! \details
//! \~english
//! Ceil is the smallest integer that is not less than "v" \n
@@ -501,18 +504,18 @@ template<typename T> inline constexpr int piFloor(const T & v) {return v < T(0)
//! Example:
//! \snippet piincludes.cpp ceil
//! \~russian
//! Ceil значение - это наименьшее целое, не меньшее чем "v" \n
//! Есть несколько макросов:
//! - \c piCeilf для "float"
//! - \c piCeild для "double"
//! Ceil çíà÷åíèå - ýòî íàèìåíüøåå öåëîå, íå ìåíüøåå ÷åì "v" \n
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piCeilf äëÿ "float"
//! - \c piCeild äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp ceil
template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
//! \brief
//! \~english Templated function return absolute of numeric falue
//! \~russian Шаблонный метод, возвращающий модуль числового значения
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ìîäóëü ÷èñëîâîãî çíà÷åíèÿ
//! \details
//! \~english
//! Absolute is the positive or equal 0 value \n
@@ -527,22 +530,22 @@ template<typename T> inline constexpr int piCeil(const T & v) {return v < T(0) ?
//! Example:
//! \snippet piincludes.cpp abs
//! \~russian
//! Модуль числового значения всегда >= 0 \n
//! Есть несколько макросов:
//! - \c piAbss для "short"
//! - \c piAbsi для "int"
//! - \c piAbsl для "long"
//! - \c piAbsll для "llong"
//! - \c piAbsf для "float"
//! - \c piAbsd для "double"
//! Ìîäóëü ÷èñëîâîãî çíà÷åíèÿ âñåãäà >= 0 \n
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piAbss äëÿ "short"
//! - \c piAbsi äëÿ "int"
//! - \c piAbsl äëÿ "long"
//! - \c piAbsll äëÿ "llong"
//! - \c piAbsf äëÿ "float"
//! - \c piAbsd äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp abs
template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
//! \brief
//! \~english Templated function return minimum of two values
//! \~russian Шаблонный метод, возвращающий минимум из двух значений
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ìèíèìóì èç äâóõ çíà÷åíèé
//! \details
//! \~english
//! There are some macros:
@@ -556,21 +559,21 @@ template<typename T> inline constexpr T piAbs(const T & v) {return (v >= T(0) ?
//! Example:
//! \snippet piincludes.cpp min2
//! \~russian
//! Есть несколько макросов:
//! - \c piMins для "short"
//! - \c piMini для "int"
//! - \c piMinl для "long"
//! - \c piMinll для "llong"
//! - \c piMinf для "float"
//! - \c piMind для "double"
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piMins äëÿ "short"
//! - \c piMini äëÿ "int"
//! - \c piMinl äëÿ "long"
//! - \c piMinll äëÿ "llong"
//! - \c piMinf äëÿ "float"
//! - \c piMind äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp min2
template<typename T> inline constexpr T piMin(const T & f, const T & s) {return ((f > s) ? s : f);}
//! \brief
//! \~english Templated function return minimum of tree values
//! \~russian Шаблонный метод, возвращающий минимум из трех значений
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ìèíèìóì èç òðåõ çíà÷åíèé
//! \details
//! \~english
//! There are some macros:
@@ -584,21 +587,21 @@ template<typename T> inline constexpr T piMin(const T & f, const T & s) {return
//! Example:
//! \snippet piincludes.cpp min3
//! \~russian
//! Есть несколько макросов:
//! - \c piMins для "short"
//! - \c piMini для "int"
//! - \c piMinl для "long"
//! - \c piMinll для "llong"
//! - \c piMinf для "float"
//! - \c piMind для "double"
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piMins äëÿ "short"
//! - \c piMini äëÿ "int"
//! - \c piMinl äëÿ "long"
//! - \c piMinll äëÿ "llong"
//! - \c piMinf äëÿ "float"
//! - \c piMind äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp min3
template<typename T> inline constexpr T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));}
//! \brief
//! \~english Templated function return maximum of two values
//! \~russian Шаблонный метод, возвращающий максимум из двух значений
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ìàêñèìóì èç äâóõ çíà÷åíèé
//! \details
//! \~english
//! There are some macros:
@@ -612,21 +615,21 @@ template<typename T> inline constexpr T piMin(const T & f, const T & s, const T
//! Example:
//! \snippet piincludes.cpp max2
//! \~russian
//! Есть несколько макросов:
//! - \c piMaxs для "short"
//! - \c piMaxi для "int"
//! - \c piMaxl для "long"
//! - \c piMaxll для "llong"
//! - \c piMaxf для "float"
//! - \c piMaxd для "double"
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piMaxs äëÿ "short"
//! - \c piMaxi äëÿ "int"
//! - \c piMaxl äëÿ "long"
//! - \c piMaxll äëÿ "llong"
//! - \c piMaxf äëÿ "float"
//! - \c piMaxd äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp max2
template<typename T> inline constexpr T piMax(const T & f, const T & s) {return ((f < s) ? s : f);}
//! \brief
//! \~english Templated function return maximum of tree values
//! \~russian Шаблонный метод, возвращающий максимум из трех значений
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ìàêñèìóì èç òðåõ çíà÷åíèé
//! \details
//! \~english
//! There are some macros:
@@ -640,21 +643,21 @@ template<typename T> inline constexpr T piMax(const T & f, const T & s) {return
//! Example:
//! \snippet piincludes.cpp max3
//! \~russian
//! Есть несколько макросов:
//! - \c piMaxs для "short"
//! - \c piMaxi для "int"
//! - \c piMaxl для "long"
//! - \c piMaxll для "llong"
//! - \c piMaxf для "float"
//! - \c piMaxd для "double"
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piMaxs äëÿ "short"
//! - \c piMaxi äëÿ "int"
//! - \c piMaxl äëÿ "long"
//! - \c piMaxll äëÿ "llong"
//! - \c piMaxf äëÿ "float"
//! - \c piMaxd äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp max3
template<typename T> inline constexpr T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));}
//! \brief
//! \~english Templated function return clamped value
//! \~russian Шаблонный метод, возвращающий ограниченное значение
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé îãðàíè÷åííîå çíà÷åíèå
//! \details
//! \~english
//! Clamped is the not greater than "max" and not lesser than "min" value \n
@@ -669,22 +672,22 @@ template<typename T> inline constexpr T piMax(const T & f, const T & s, const T
//! Example:
//! \snippet piincludes.cpp clamp
//! \~russian
//! Ограниченное значение - не больше чем "max" и не меньше чем "min"
//! Есть несколько макросов:
//! - \c piClamps для "short"
//! - \c piClampi для "int"
//! - \c piClampl для "long"
//! - \c piClampll для "llong"
//! - \c piClampf для "float"
//! - \c piClampd для "double"
//! Îãðàíè÷åííîå çíà÷åíèå - íå áîëüøå ÷åì "max" è íå ìåíüøå ÷åì "min"
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piClamps äëÿ "short"
//! - \c piClampi äëÿ "int"
//! - \c piClampl äëÿ "long"
//! - \c piClampll äëÿ "llong"
//! - \c piClampf äëÿ "float"
//! - \c piClampd äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp clamp
template<typename T> inline constexpr T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
//! \brief
//! \~english Function inverse byte order in memory block ([1..N] -> [N..1])
//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1])
//! \~russian Ìåòîä äëÿ ñìåíû ïîðÿäêà áàéò â áëîêå ïàìÿòè ([1..N] -> [N..1])
inline void piLetobe(void * data, int size) {
for (int i = 0; i < size / 2; i++)
piSwap<uchar>(((uchar*)data)[size - i - 1], ((uchar*)data)[i]);
@@ -692,7 +695,7 @@ inline void piLetobe(void * data, int size) {
//! \brief
//! \~english Function for compare two numeric values with epsilon
//! \~russian Метод для сравнения двух чисел с порогом
//! \~russian Ìåòîä äëÿ ñðàâíåíèÿ äâóõ ÷èñåë ñ ïîðîãîì
//! \details
//! \~english
//! There are some macros:
@@ -702,11 +705,11 @@ inline void piLetobe(void * data, int size) {
//! Example:
//! \snippet piincludes.cpp compare
//! \~russian
//! Есть несколько макросов:
//! - \c piComparef для "float"
//! - \c piCompared для "double"
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piComparef äëÿ "float"
//! - \c piCompared äëÿ "double"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp compare
template<typename T>
inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric_limits<T>::epsilon()) {
@@ -715,12 +718,12 @@ inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric
//! \brief
//! \~english Templated function that inverse byte order of value "v"
//! \~russian Шаблонный метод, меняющий порядок байт в переменной "v"
//! \~russian Øàáëîííûé ìåòîä, ìåíÿþùèé ïîðÿäîê áàéò â ïåðåìåííîé "v"
template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
//! \brief
//! \~english Templated function that returns "v" with inversed byte order
//! \~russian Шаблонный метод, возвращающий переменную "v" с измененным порядком байт
//! \~russian Øàáëîííûé ìåòîä, âîçâðàùàþùèé ïåðåìåííóþ "v" ñ èçìåíåííûì ïîðÿäêîì áàéò
//! \details
//! \~english
//! This function used to convert values between little and big endian \n
@@ -733,25 +736,25 @@ template<typename T> inline void piLetobe(T * v) {piLetobe(v, sizeof(T));}
//! Example:
//! \snippet piincludes.cpp letobe
//! \~russian
//! Этот метод используется для изменения порядка байт между little и big endian
//! Есть несколько макросов:
//! - \c piLetobes для "ushort"
//! - \c piLetobei для "uint"
//! - \c piLetobel для "ulong"
//! - \c piLetobell для "ullong"
//! Ýòîò ìåòîä èñïîëüçóåòñÿ äëÿ èçìåíåíèÿ ïîðÿäêà áàéò ìåæäó little è big endian
//! Åñòü íåñêîëüêî ìàêðîñîâ:
//! - \c piLetobes äëÿ "ushort"
//! - \c piLetobei äëÿ "uint"
//! - \c piLetobel äëÿ "ulong"
//! - \c piLetobell äëÿ "ullong"
//!
//! Пример:
//! Ïðèìåð:
//! \snippet piincludes.cpp letobe
template<typename T> inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;}
// specialization
template<> inline 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 uint16_t piLetobe(const uint16_t & v) {return (v << 8) | (v >> 8);}
template<> inline uint32_t piLetobe(const uint32_t & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);}
template<> inline float piLetobe(const float & v) {
union _pletobe_f {
_pletobe_f(const float &f_) {f = f_;}
float f;
uint v;
uint32_t v;
};
_pletobe_f a(v);
a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000);
@@ -760,7 +763,7 @@ template<> inline float piLetobe(const float & v) {
//! \brief
//! \~english Generic hash function, implements murmur3/32 algorithm
//! \~russian Хэш-функция общего назначения, по алгоритму murmur3/32
//! \~russian Õýø-ôóíêöèÿ îáùåãî íàçíà÷åíèÿ, ïî àëãîðèòìó murmur3/32
inline uint piHashData(const uchar * data, uint len, uint seed = 0) {
if (!data || len <= 0) return 0u;
uint h = seed;
+1 -1
View File
@@ -29,7 +29,7 @@
#include "pivector2d.h"
#include <stdio.h>
#ifdef FREERTOS
#ifdef MICRO_PIP
# define _TYPENAME_(T) "?"
#else
# define _TYPENAME_(T) typeid(T).name()
+2 -2
View File
@@ -26,15 +26,15 @@
#ifdef PIP_STD_IOSTREAM
# include <iostream>
#endif
#include <atomic>
class PIMutex;
class PIMutexLocker;
class PIObject;
class PIString;
class PIByteArray;
#ifndef MICRO_PIP
class PIInit;
#endif
class PIChar;
class PICout;
+9
View File
@@ -40,6 +40,15 @@ typedef LONG(NTAPI*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#include <cstdio>
#include <iostream>
#ifdef FREERTOS
# ifdef ESP_PLATFORM
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
# endif
# ifdef ARDUINO_ARCH_STM32
# include <STM32FreeRTOS.h>
# endif
#endif
#endif // PIINCLUDES_P_H
+36 -36
View File
@@ -19,15 +19,15 @@
#include "piincludes_p.h"
#include "piinit.h"
#ifndef MICRO_PIP
#include "pitime.h"
#include "pisignals.h"
#include "piobject.h"
#include "pisysteminfo.h"
#include "piresourcesstorage.h"
#include "pidir.h"
#ifndef FREERTOS
# include "piprocess.h"
#endif
#include "piprocess.h"
#ifdef ESP_PLATFORM
# include "esp_system.h"
#endif
@@ -49,9 +49,7 @@ void __PISetTimerResolution() {
}
#else
# include <pwd.h>
# ifndef FREERTOS
# include <sys/utsname.h>
# endif
# include <sys/utsname.h>
# include <pthread.h>
# ifdef BLACKBERRY
# include <signal.h>
@@ -84,7 +82,6 @@ ULONG prev_res;
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)
@@ -92,7 +89,6 @@ void __sighandler__(PISignals::Signal s) {
if (s == PISignals::UserDefined1)
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID()));
}
#endif
#ifdef ANDROID
@@ -107,7 +103,6 @@ PIInit::PIInit() {
PISystemInfo * sinfo = PISystemInfo::instance();
sinfo->execDateTime = PIDateTime::current();
setFileCharset("UTF-8");
#ifndef FREERTOS
#ifndef ANDROID
PISignals::setSlot(__sighandler__);
PISignals::grabSignals(PISignals::UserDefined1);
@@ -128,7 +123,7 @@ PIInit::PIInit() {
break;
}
}
# else
# else //WINDOWS
// OS version
DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
@@ -154,7 +149,7 @@ PIInit::PIInit() {
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
__PISetTimerResolution();
}
# endif
# endif //WINDOWS
# ifdef HAS_LOCALE
//cout << "has locale" << endl;
if (currentLocale_t != 0) {
@@ -162,18 +157,18 @@ PIInit::PIInit() {
currentLocale_t = 0;
}
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0);
# else
# else //HAS_LOCALE
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
# endif
#else
# endif //HAS_LOCALE
#else //ANDROID
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
#endif //ANDROID
PRIVATE->delete_locs = false;
__syslocname__ = __sysoemname__ = 0;
__utf8name__ = const_cast<char*>("UTF-8");
@@ -201,13 +196,13 @@ PIInit::PIInit() {
# endif
//piCout << __syslocname__;
//piCout << __sysoemname__;
#else
#else //PIP_ICU
# ifdef WINDOWS
__syslocname__ = (char *)CP_ACP;
__sysoemname__ = (char *)CP_OEMCP;
__utf8name__ = (char *)CP_UTF8;
# endif
#endif
#endif //PIP_ICU
#ifdef MAC_OS
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
#endif
@@ -236,7 +231,7 @@ PIInit::PIInit() {
ulong unlen = 1023;
if (GetUserName(cbuff, &unlen) != 0)
sinfo->user = cbuff;
#else
#else //WINDOWS
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
passwd * ps = getpwuid(getuid());
if (ps)
@@ -252,8 +247,8 @@ PIInit::PIInit() {
sinfo->OS_version = uns.release;
sinfo->architecture = uns.machine;
}
# endif
#endif
#endif //WINDOWS
#ifdef ESP_PLATFORM
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
@@ -275,6 +270,8 @@ PIInit::PIInit() {
PIStringAscii("FreeBSD");
#elif defined(FREERTOS)
PIStringAscii("FreeRTOS");
#elif defined(MICRO_PIP)
PIStringAscii("MicroPIP");
#else
uns.sysname;
#endif
@@ -305,49 +302,49 @@ PIInit::~PIInit() {
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
switch (o) {
case ICU: return
case boICU: return
#ifdef PIP_ICU
true;
#else
false;
#endif
case USB: return
case boUSB: return
#ifdef PIP_USB
true;
#else
false;
#endif
case Crypt: return
case boCrypt: return
#ifdef PIP_CRYPT
true;
#else
false;
#endif
case Introspection: return
case boIntrospection: return
#ifdef PIP_INTROSPECTION
true;
#else
false;
#endif
case FFTW: return
case boFFTW: return
#ifdef PIP_FFTW
true;
#else
false;
#endif
case Compress: return
case boCompress: return
#ifdef PIP_COMPRESS
true;
#else
false;
#endif
case OpenCL: return
case boOpenCL: return
#ifdef PIP_OPENCL
true;
#else
false;
#endif
case Cloud: return
case boCloud: return
#ifdef PIP_CLOUD
true;
#else
@@ -361,14 +358,14 @@ bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
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";
if (isBuildOptionEnabled(boICU)) ret << "ICU";
if (isBuildOptionEnabled(boUSB)) ret << "USB";
if (isBuildOptionEnabled(boCrypt)) ret << "Crypt";
if (isBuildOptionEnabled(boIntrospection)) ret << "Introspection";
if (isBuildOptionEnabled(boFFTW)) ret << "FFTW";
if (isBuildOptionEnabled(boCompress)) ret << "Compress";
if (isBuildOptionEnabled(boOpenCL)) ret << "OpenCL";
if (isBuildOptionEnabled(boCloud)) ret << "Cloud";
return ret;
}
@@ -415,3 +412,6 @@ __PIInit_Initializer__::~__PIInit_Initializer__() {
__instance__ = 0;
}
}
#endif // MICRO_PIP
+13 -8
View File
@@ -23,6 +23,10 @@
#ifndef PIINIT_H
#define PIINIT_H
#include "pibase.h"
#ifndef MICRO_PIP
#include "piincludes.h"
@@ -49,14 +53,14 @@ public:
//! @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,
boICU /*! Unicode support */ = 0x01,
boUSB /*! USB support */ = 0x02,
boCrypt /*! Crypt support */ = 0x08,
boIntrospection /*! Introspection */ = 0x010,
boFFTW /*! FFTW3 support */ = 0x40,
boCompress /*! Zlib compression support */ = 0x80,
boOpenCL /*! OpenCL support */ = 0x100,
boCloud /*! Cloud transport support */ = 0x200,
};
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
static bool isBuildOptionEnabled(BuildOption o);
@@ -70,4 +74,5 @@ private:
};
#endif // MICRO_PIP
#endif // PIINIT_H
+5 -5
View File
@@ -18,10 +18,10 @@
*/
#include "piobject.h"
#include "pisysteminfo.h"
#include "pithread.h"
#include "piconditionvar.h"
#ifndef FREERTOS
#ifndef MICRO_PIP
# include "pisysteminfo.h"
# include "pifile.h"
#endif
@@ -355,7 +355,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig) {
src->connections.remove(i);
i--;
if (dest) {
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS)
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
PIMutexLocker _mld(dest->mutex_connect, src != dest);
#endif
dest->updateConnectors();
@@ -373,7 +373,7 @@ void PIObject::piDisconnectAll() {
// piCout << "disconnect"<< src << o;
if (!o || (o == this)) continue;
if (!o->isPIObject()) continue;
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS)
#if !defined(ANDROID) && !defined(MAC_OS) && !defined(MICRO_PIP)
PIMutexLocker _mld(o->mutex_connect, this != o);
#endif
PIVector<Connection> & oc(o->connections);
@@ -589,6 +589,7 @@ void PIObject::dump(const PIString & line_prefix) const {
}
#ifndef MICRO_PIP
void dumpApplication() {
PIMutexLocker _ml(PIObject::mutexObjects());
//printf("dump application ...\n");
@@ -615,7 +616,6 @@ void dumpApplication() {
}
#ifndef FREERTOS
bool dumpApplicationToFile(const PIString & path) {
PIFile f(path + "_tmp");
f.setName("__S__DumpFile");
+8 -5
View File
@@ -37,11 +37,13 @@
typedef void (*Handler)(void * );
class PIP_EXPORT PIObject {
#ifndef MICRO_PIP
friend class PIObjectManager;
friend void dumpApplication();
friend class PIIntrospection;
#endif
typedef PIObject __PIObject__;
typedef void __Parent__;
friend class PIIntrospection;
public:
NO_COPY_CLASS(PIObject)
@@ -192,9 +194,9 @@ public:
static PIObject::Connection piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
static PIObject::Connection piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
static PIObject::Connection 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));
template <typename PIINPUT, typename... PITYPES>
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,PITYPES...), PIINPUT functor) {
return (std::function<void()>*)(new std::function<void(PITYPES...)>(functor));
}
@@ -539,8 +541,9 @@ private:
};
#ifndef MICRO_PIP
PIP_EXPORT void dumpApplication();
PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
#endif
#endif // PIOBJECT_H
+39 -15
View File
@@ -19,7 +19,11 @@
#include "piincludes_p.h"
#include "pitime.h"
#include "pisystemtests.h"
#ifndef MICRO_PIP
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include <Arduino.h>
#endif
#ifdef WINDOWS
extern FILETIME __pi_ftjan1970;
long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;}
@@ -31,9 +35,8 @@
//# include <crt_externs.h>
extern clock_serv_t __pi_mac_clock;
#endif
#ifdef FREERTOS
# include "freertos/FreeRTOS.h"
# include "freertos/task.h"
#ifdef MICRO_PIP
# include <sys/time.h>
#endif
/*! \class PISystemTime
@@ -252,24 +255,29 @@ PISystemTime PISystemTime::current(bool precise_but_not_system) {
ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime);
return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U);
}
#else
# ifdef MAC_OS
#elif defined(MAC_OS)
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
# else
# ifdef FREERTOS
#elif defined(MICRO_PIP)
timespec t_cur;
# ifdef ARDUINO
static const uint32_t offSetSinceEpoch_s = 1581897605UL;
uint32_t mt = millis();
t_cur.tv_sec = offSetSinceEpoch_s + (mt / 1000);
t_cur.tv_nsec = (mt - (mt / 1000)) * 1000000UL;
# else
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
# endif
#else
timespec t_cur;
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
# endif
# endif
#endif
#ifndef WINDOWS
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
#endif
}
@@ -407,22 +415,38 @@ PITimeMeasurer::PITimeMeasurer() {
double PITimeMeasurer::elapsed_n() const {
return (PISystemTime::current(true) - t_st).toNanoseconds() - PISystemTests::time_elapsed_ns;
return (PISystemTime::current(true) - t_st).toNanoseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns
#endif
;
}
double PITimeMeasurer::elapsed_u() const {
return (PISystemTime::current(true) - t_st).toMicroseconds() - PISystemTests::time_elapsed_ns / 1.E+3;
return (PISystemTime::current(true) - t_st).toMicroseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+3
#endif
;
}
double PITimeMeasurer::elapsed_m() const {
return (PISystemTime::current(true) - t_st).toMilliseconds() - PISystemTests::time_elapsed_ns / 1.E+6;
return (PISystemTime::current(true) - t_st).toMilliseconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+6
#endif
;
}
double PITimeMeasurer::elapsed_s() const {
return (PISystemTime::current(true) - t_st).toSeconds() - PISystemTests::time_elapsed_ns / 1.E+9;
return (PISystemTime::current(true) - t_st).toSeconds()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+9
#endif
;
}
+2 -2
View File
@@ -27,7 +27,7 @@
#include "pistring.h"
#include <typeinfo>
#ifdef PIP_FREERTOS
#ifdef MICRO_PIP
#include "pivariant.h"
#endif
@@ -48,7 +48,7 @@ template<typename T>
class __VariantFunctions__: public __VariantFunctionsBase__ {
public:
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;}
#ifdef PIP_FREERTOS
#ifdef MICRO_PIP
PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;}
#else
PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;}
+9 -4
View File
@@ -19,8 +19,9 @@
#include "pivarianttypes.h"
#include "pipropertystorage.h"
#include "piiodevice.h"
#ifndef MICRO_PIP
# include "piiodevice.h"
#endif
int PIVariantTypes::Enum::selectedValue() const {
piForeachC (Enumerator & e, enum_list)
@@ -83,9 +84,12 @@ PIStringList PIVariantTypes::Enum::names() const {
PIVariantTypes::IODevice::IODevice() {
#ifndef MICRO_PIP
mode = PIIODevice::ReadWrite;
#else
mode = 0; // TODO: PIIODevice for MICRO PIP
#endif // MICRO_PIP
options = 0;
}
@@ -112,12 +116,14 @@ PIString PIVariantTypes::IODevice::toPICout() const {
if (mode & 2) {s << "w"; ++rwc;}
if (rwc == 1) s << "o";
s << ", flags=";
#ifndef MICRO_PIP // TODO: PIIODevice for MICRO PIP
if (options != 0) {
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingRead])
s << " br";
if (((PIIODevice::DeviceOptions)options)[PIIODevice::BlockingWrite])
s << " bw";
}
#endif // MICRO_PIP
PIPropertyStorage ps = get();
piForeachC (PIPropertyStorage::Property & p, ps) {
s << ", " << p.name << "=\"" << p.value.toString() << "\"";
@@ -128,7 +134,6 @@ PIString PIVariantTypes::IODevice::toPICout() const {
PIVariantTypes::Enum & PIVariantTypes::Enum::operator <<(const PIVariantTypes::Enumerator & v) {
enum_list << v;
return *this;