This commit is contained in:
2022-11-25 21:35:39 +03:00
parent a2256a3872
commit dc6fbbf7ec
37 changed files with 1498 additions and 1321 deletions

View File

@@ -1,534 +0,0 @@
/*! \file pibinarystream.h
* \ingroup Core
* \~\brief
* \~english Binary serialization interface
* \~russian Интерфейс бинарной сериализации
*/
/*
PIP - Platform Independent Primitives
Binary serialization interface
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 PIBINARYSTREAM_H
#define PIBINARYSTREAM_H
#include "pimemoryblock.h"
#include "pibitarray.h"
#include "pimap.h"
#include "pivector2d.h"
#define PIP_BINARY_STREAM
#define BINARY_STREAM_FRIEND(T) \
template<typename P> friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v); \
template<typename P> friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v);
#define BINARY_STREAM_WRITE(T) \
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v)
#define BINARY_STREAM_READ(T) \
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v)
//! \ingroup Core
//! \~\brief
//! \~english Binary serialization interface.
//! \~russian Интерфейс бинарной сериализации.
//! \~\details
//! \~english In your class you should implement this methods:
//! \~russian В производном классе вы должны реализовать следующие методы:
//! \~\code
//! bool binaryStreamAppendImp (const void * d, size_t s);
//! bool binaryStreamTakeImp (void * d, size_t s);
//! ssize_t binaryStreamSizeImp () const;
//! \endcode
//! \~english Function binaryStreamSizeImp should return -1 if size unknown.
//! \~russian Функция binaryStreamSizeImp должна возвращать -1 если нет информации о размере.
//! \~english See details \ref iostream.
//! \~russian Подробнее \ref iostream.
template<typename P>
class PIBinaryStream {
public:
//! \~russian Записать данные
bool binaryStreamAppend(const void * d, size_t s) {
if (!static_cast<P*>(this)->binaryStreamAppendImp(d, s)) {
return false;
printf("[PIBinaryStream] binaryStreamAppend() error\n");
}
return true;
}
//! \~russian Прочитать данные
bool binaryStreamTake(void * d, size_t s) {
if (!static_cast<P*>(this)->binaryStreamTakeImp(d, s)) {
return false;
printf("[PIBinaryStream] binaryStreamTake() error\n");
}
return true;
}
//! \~russian Узнать оставшийся размер
//!\~\details
//!\~russian Возвращает -1 если нет информации о размере
ssize_t binaryStreamSize() const {
return static_cast<const P*>(this)->binaryStreamSizeImp();
}
//! \~russian Записать данные
template<typename T>
void binaryStreamAppend(T v) {binaryStreamAppend(&v, sizeof(v));}
//! \~russian Прочитать int
int binaryStreamTakeInt() {
int r = 0;
binaryStreamTake(&r, sizeof(r));
return r;
}
};
// helper class to detect default operators
template<typename P>
class PIBinaryStreamTrivialRef {
public:
PIBinaryStreamTrivialRef(PIBinaryStream<P> & s): p(s) {}
PIBinaryStream<P> & p;
};
template<typename P, typename T> inline PIBinaryStream<P> & operator <<(PIBinaryStreamTrivialRef<P> s, const T & v) {
s.p << v;
return s.p;
}
template<typename P, typename T> inline PIBinaryStream<P> & operator >>(PIBinaryStreamTrivialRef<P> s, T & v) {
s.p >> v;
return s.p;
}
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStreamTrivialRef<P> s, const PIMemoryBlock v) {
s.p << v;
return s.p;
}
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStreamTrivialRef<P> s, PIMemoryBlock v) {
s.p >> v;
return s.p;
}
// specify types
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const bool v) {
s.binaryStreamAppend((uchar)v);
return s;
}
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, bool & v) {
uchar c;
s.binaryStreamTake(&c, sizeof(c));
v = c;
return s;
}
template<typename P> inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMemoryBlock v) {
s.binaryStreamAppend(v.data(), v.size());
return s;
}
template<typename P> inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMemoryBlock v) {
s.binaryStreamTake(v.data(), v.size());
return s;
}
// store simple types
template<typename P, typename T,
typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & v) {
//piCout << "<< enum";
s.binaryStreamAppend((int)v);
return s;
}
template<typename P, typename T,
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStreamTrivialRef<P> operator <<(PIBinaryStream<P> & s, const T & v) {
s.binaryStreamAppend(&v, sizeof(v));
return s;
}
//! \~english Store operator for PIVector of any trivial copyable type
//! \~russian Оператор сохранения для PIVector тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
//piCout << "<< vector trivial default";
s.binaryStreamAppend((int)v.size());
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
//piCout << "<< vector trivial custom";
s.binaryStreamAppend((int)v.size());
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIDeque of any trivial copyable type
//! \~russian Оператор сохранения для PIDeque тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
//piCout << "<< deque trivial default";
s.binaryStreamAppend((int)v.size());
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
//piCout << "<< deque trivial custom";
s.binaryStreamAppend((int)v.size());
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIVector2D of any trivial copyable type
//! \~russian Оператор сохранения для PIVector2D тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
//piCout << "<< vector2d trivial default";
s.binaryStreamAppend((int)v.rows());
s.binaryStreamAppend((int)v.cols());
s.binaryStreamAppend(v.data(), v.size() * sizeof(T));
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() << std::declval<const T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
//piCout << "<< vector2d trivial custom";
s.binaryStreamAppend((int)v.rows());
s.binaryStreamAppend((int)v.cols());
s << v.toPlainVector();
return s;
}
//! \~english Store operator
//! \~russian Оператор сохранения
template<typename P>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v) {s << v.size_ << v.data_; return s;}
//! \~english Store operator
//! \~russian Оператор сохранения
template<typename P, typename Type0, typename Type1>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIPair<Type0, Type1> & v) {s << v.first << v.second; return s;}
// restore simple types
template<typename P, typename T,
typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & v) {
//piCout << ">> enum";
v = (T)s.binaryStreamTakeInt();
return s;
}
template<typename P, typename T,
typename std::enable_if<!std::is_enum<T>::value, int>::type = 0,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStreamTrivialRef<P> operator >>(PIBinaryStream<P> & s, T & v) {
if (!s.binaryStreamTake(&v, sizeof(v))) {
printf("error with %s\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
//! \~english Restore operator for PIVector of any trivial copyable type
//! \~russian Оператор извлечения для PIVector тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
//piCout << ">> vector trivial default";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
//piCout << ">> vector trivial custom";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIDeque of any trivial copyable type
//! \~russian Оператор извлечения для PIDeque тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//piCout << ">> deque trivial default";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
if (!s.binaryStreamTake(v.data(), sz * sizeof(T))) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//piCout << ">> deque trivial custom";
int sz = s.binaryStreamTakeInt();
v._resizeRaw(sz);
for (int i = 0; i < sz; ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIVector2D of any trivial copyable type
//! \~russian Оператор извлечения для PIVector2D тривиальных типов
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if< std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
//piCout << ">> vector2d trivial default";
int r, c;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
v._resizeRaw(r, c);
if (!s.binaryStreamTake(v.data(), v.size() * sizeof(T))) {
printf("error with PIVector2D<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
return s;
}
template<typename P, typename T,
typename std::enable_if< std::is_trivially_copyable<T>::value, int>::type = 0,
typename std::enable_if<!std::is_same<decltype(std::declval<PIBinaryStream<P>&>() >> std::declval<T &>()), PIBinaryStreamTrivialRef<P>>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
//piCout << ">> vector2d trivial custom";
int r, c;
PIVector<T> tmp;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
s >> tmp;
v = PIVector2D<T>(r, c, tmp);
return s;
}
//! \~english Restore operator
//! \~russian Оператор извлечения
template<typename P>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v) {s >> v.size_ >> v.data_; return s;}
//! \~english Restore operator
//! \~russian Оператор извлечения
template<typename P, typename Type0, typename Type1>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIPair<Type0, Type1> & v) {s >> v.first >> v.second; return s;}
// store complex types
//! \~english Store operator for PIVector of any compound type
//! \~russian Оператор сохранения для PIVector сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector<T> & v) {
//piCout << "<< vector complex";
s.binaryStreamAppend(int(v.size_s()));
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIDeque of any compound type
//! \~russian Оператор сохранения для PIDeque сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIDeque<T> & v) {
//piCout << "<< deque complex";
s.binaryStreamAppend(int(v.size_s()));
for (size_t i = 0; i < v.size(); ++i) s << v[i];
return s;
}
//! \~english Store operator for PIVector2D of any compound type
//! \~russian Оператор сохранения для PIVector2D сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIVector2D<T> & v) {
//piCout << "<< vector2d complex";
s.binaryStreamAppend(int(v.rows()));
s.binaryStreamAppend(int(v.cols()));
s << v.toPlainVector();
return s;
}
// restore complex types
//! \~english Restore operator for PIVector of any compound type
//! \~russian Оператор извлечения для PIVector сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector<T> & v) {
//piCout << ">> vector complex";
/*if (s.size_s() < 4) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
v.resize(s.binaryStreamTakeInt());
for (size_t i = 0; i < v.size(); ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIDeque of any compound type
//! \~russian Оператор извлечения для PIDeque сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIDeque<T> & v) {
//piCout << ">> deque complex";
/*if (s.size_s() < 4) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
v.resize(s.binaryStreamTakeInt());
for (size_t i = 0; i < v.size(); ++i) s >> v[i];
return s;
}
//! \~english Restore operator for PIVector2D of any compound type
//! \~russian Оператор извлечения для PIVector2D сложных типов
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIVector2D<T> & v) {
//piCout << ">> vector2d complex";
/*if (s.size_s() < 8) {
printf("error with PIVecto2Dr<%s>\n", __PIP_TYPENAME__(T));
assert(s.size_s() >= 8);
}*/
int r, c;
PIVector<T> tmp;
r = s.binaryStreamTakeInt();
c = s.binaryStreamTakeInt();
s >> tmp;
v = PIVector2D<T>(r, c, tmp);
return s;
}
// other types
//! \~english Store operator
//! \~russian Оператор сохранения
template <typename P, typename Key, typename T>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIMap<Key, T> & v) {
s.binaryStreamAppend((int)v.pim_index.size_s());
for (uint i = 0; i < v.size(); ++i) {
s.binaryStreamAppend((int)v.pim_index[i].index);
s << v.pim_index[i].key;
}
s << v.pim_content;
return s;
}
//! \~english Restore operator
//! \~russian Оператор извлечения
template <typename P, typename Key, typename T>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIMap<Key, T> & v) {
/*if (s.size_s() < 4) {
printf("error with PIMap<%s, %s>\n", __PIP_TYPENAME__(Key), __PIP_TYPENAME__(T));
assert(s.size_s() >= 4);
}*/
int sz = s.binaryStreamTakeInt(); v.pim_index.resize(sz);
int ind = 0;
for (int i = 0; i < sz; ++i) {
ind = s.binaryStreamTakeInt();
s >> 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;
}
// non-defined complex types
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIBinaryStream] Error: using undeclared operator << for complex type!");
return s;
}
template<typename P, typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, int>::type = 0>
inline PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, T & ) {
static_assert(std::is_trivially_copyable<T>::value, "[PIBinaryStream] Error: using undeclared operator >> for complex type!");
return s;
}
#endif

View File

@@ -1,44 +0,0 @@
/*
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.saveAndSetControls(0);
for (uint i = 0; i < ba.bitSize(); ++i) {
s << int(ba[i]);
if (i % 8 == 7) s << ' ';
}
s.restoreControls();
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

View File

@@ -1,229 +0,0 @@
/*! \file pibitarray.h
* \~\brief
* \~english Bit array
* \~russian Битовый массив
*/
/*
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"
//! \ingroup Core
//! \~\brief
//! \~english The %PIBitArray class provides an space-efficient array of bits.
//! \~russian Класс %PIBitArray представляет собой компактный массив битов.
class PIP_EXPORT PIBitArray {
template <typename P>
friend PIBinaryStream<P> & operator >>(PIBinaryStream<P> & s, PIBitArray & v);
template <typename P>
friend PIBinaryStream<P> & operator <<(PIBinaryStream<P> & s, const PIBitArray & v);
public:
//! \~english Constructs bit array with "size" size.
//! \~russian Создает битовый массив с размером "size".
PIBitArray(const int & size = 0) {resize(size);}
//! \~english Constructs bit array with size 8 and values from "val".
//! \~russian Создает битовый массив с размером 8 и значениями из "val".
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
//! \~english Constructs bit array with size 16 and values from "val".
//! \~russian Создает битовый массив с размером 16 и значениями из "val".
PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Constructs bit array with size 32 and values from "val".
//! \~russian Создает битовый массив с размером 32 и значениями из "val".
PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Constructs bit array with size 64 and values from "val".
//! \~russian Создает битовый массив с размером 64 и значениями из "val".
PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Constructs bit array with size "bytes * 8" and values from "data".
//! \~russian Создает битовый массив с размером "bytes * 8" и значениями из "data".
PIBitArray(const uchar * data, uint bytes) {resize(bytes * 8); memcpy(this->data(), data, bytes);}
//! \~english Returns a size in bits.
//! \~russian Возвращает размер в битах.
uint bitSize() const {return size_;}
//! \~english Returns a size in bytes.
//! \~russian Возвращает размер в байтах.
uint byteSize() const {return bytesInBits(size_);}
//! \~english Resize this array to "size" bits.
//! \~russian Изменяет размер массива до "size" битов.
PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;}
//! \~english Set bit with index "index" to 0.
//! \~russian Устанавливает бит с индексом "index" в 0.
PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;}
//! \~english Set bit with index "index" to 1.
//! \~russian Устанавливает бит с индексом "index" в 1.
PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;}
//! \~english Set bit with index "index" to "value".
//! \~russian Устанавливает бит с индексом "index" в "value".
PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;}
//! \~english Set bit with index "index" to "value".
//! \~russian Устанавливает бит с индексом "index" в "value".
PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);}
//! \~english Add bit with value "value" to the end of array.
//! \~russian Добавляет бит со значением "value" в конец массива.
PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;}
//! \~english Add bit with value "value" to the end of array.
//! \~russian Добавляет бит со значением "value" в конец массива.
PIBitArray & push_back(const uchar & value) {return push_back(value > 0);}
//! \~english Insert bit with value "value" after "index" position.
//! \~russian Вставляет бит со значением "value" после положения "index".
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;}
//! \~english Insert bit with value "value" after "index" position.
//! \~russian Вставляет бит со значением "value" после положения "index".
PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);}
//! \~english Add bit with value "value" to the beginning of array.
//! \~russian Добавляет бит со значением "value" в начало массива.
PIBitArray & push_front(const bool & value) {return insert(0, value);}
//! \~english Add bit with value "value" to the beginning of array.
//! \~russian Добавляет бит со значением "value" в начало массива.
PIBitArray & push_front(const uchar & value) {return push_front(value > 0);}
//! \~english Remove one bit from the end of array.
//! \~russian Удаляет один бит с конца массива.
PIBitArray & pop_back() {return resize(size_ - 1);}
//! \~english Remove one bit from the beginning of array.
//! \~russian Удаляет один бит с начала массива.
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;}
//! \~english Add bits "ba" to the end of array.
//! \~russian Добавляет биты "ba" в конец массива.
PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;}
//! \~english Returns pointer to bytes data of array.
//! \~russian Возвращает указатель на байтовое содержимое массива.
uchar * data() {return data_.data();}
//! \~english Returns data of array as \b uchar.
//! \~russian Возвращает байтовое содержимое массива как \b uchar.
uchar toUChar() {if (size_ == 0) return 0; return data_[0];}
//! \~english Returns data of array as \b ushort.
//! \~russian Возвращает байтовое содержимое массива как \b ushort.
ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
//! \~english Returns data of array as \b uint.
//! \~russian Возвращает байтовое содержимое массива как \b uint.
uint toUInt() {uint t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
//! \~english Returns data of array as \b ullong.
//! \~russian Возвращает байтовое содержимое массива как \b ullong.
ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin<uint>(byteSize(), sizeof(t))); return t;}
//! \~english Returns bit value at index "index".
//! \~russian Возвращает значение бита с индексом "index".
bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;}
//! \~english Returns bit value at index "index".
//! \~russian Возвращает значение бита с индексом "index".
bool operator [](const uint & index) const {return at(index);}
//! \~english Similar to \a append().
//! \~russian Аналог \a append().
void operator +=(const PIBitArray & ba) {append(ba);}
//! \~english Returns if two bit arrays are similar.
//! \~russian Возвращает равны ли для битовых массива.
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;}
//! \~english Returns if two bit arrays are not similar.
//! \~russian Возвращает не равны ли для битовых массива.
bool operator !=(const PIBitArray & ba) const {return !(*this == ba);}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "val".
void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));}
//! \~english Resize and set values from "val".
//! \~russian Изменяет размер и устанавливает значения из "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
//! \relatesalso PIByteArray
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
PICout operator <<(PICout s, const PIBitArray & ba);
#endif // PIBITARRAY_H

View File

@@ -1,431 +0,0 @@
/*
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>
#include "picrc.h"
//! \class PIByteArray pibytearray.h
//! \~\details
//! \~english
//! %PIByteArray used to store raw bytes.
//! It can be constructed from any data and size.
//! You can use %PIByteArray as binary stream
//! to serialize/deserialize any objects and data.
//! See details \ref iostream.
//! This class use PIDeque<uchar> and provide some handle function
//! to manipulate it.
//! \~russian
//! %PIByteArray используется для хранения байтов.
//! Он может быть сконструирован из любых даных.
//! Можно использовать %PIByteArray как потоковый объект
//! для сериализации/десериализации любых типов и данных.
//! Подробнее \ref iostream.
//! Этот класс использует PIDeque<uchar> и предоставляет набор
//! удобных методов для работы с байтами.
//!
//! \~english \section PIByteArray_sec0 Usage
//! \~russian \section PIByteArray_sec0 Использование
//! \~english
//! %PIByteArray subclass PIBinaryStream and can be used to store custom data and manipulate it.
//! Store operators places data at the end of array, restore operators takes data from the beginning
//! of array.
//! In addition there are Hex and Base64 convertions.
//! \~russian
//! %PIByteArray наследован от PIBinaryStream и может быть использован для сохранения любых данных и работы с ними.
//! Операторы сохранения добавляют данные в конец массива, а операторы извлечения
//! берут данные из его начала.
//! Также есть методы для преобразования в Hex и Base64.
//!
//! \~english \section PIByteArray_sec1 Attention
//! \~russian \section PIByteArray_sec1 Внимание
//! \~english
//! 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().
//! \~russian
//! Потоковый оператор для типа %PIByteArray сохраняет его как контейнер,
//! а не просто добавляет его содержимое в конец. Этот оператор полезен для управляемой
//! упаковки произвольных данных в виде %PIByteArray.
//! Для добавления содержимого одного байтового массива к другому используется
//! метод \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;
}
//! \~\details
//! \~english
//! This is simple sum of all bytes, if "inverse" then add 1 and inverse.
//! Pseudocode:
//! \~russian
//! Это простая сумма всех байтов, если "inverse", то ещё добавляется 1 и инвертируется результат.
//! Псевдокод:
//! \~\code
//! for (i)
//! sum += at(i);
//! if (inverse) return ~(sum + 1);
//! else return sum;
//! \endcode
uchar PIByteArray::checksumPlain8(bool inverse) const {
uchar c = 0;
int sz = size_s();
for (int i = 0; i < sz; ++i)
c += at(i);
if (inverse) c = ~(c + 1);
return c;
}
uchar PIByteArray::checksumCRC8() const {
return standardCRC_8().calculate(data(), size());
}
ushort PIByteArray::checksumCRC16() const {
return standardCRC_16().calculate(data(), size());
}
uint PIByteArray::checksumCRC32() const {
return standardCRC_32().calculate(data(), size());
}
//! \~\details
//! \~english
//! This is sum of all bytes multiplied by index+1, if inverse then add 1 and inverse.
//! Pseudocode:
//! \~russian
//! Это простая сумма всех байтов, умноженных на индекс+1, если "inverse", то ещё добавляется 1 и инвертируется результат.
//! Псевдокод:
//! \~\code
//! for (i)
//! sum += at(i) * (i + 1);
//! if (inverse) return ~(sum + 1);
//! else return sum;
//! \endcode
uint PIByteArray::checksumPlain32(bool inverse) const {
uint c = 0;
int sz = size_s();
for (int i = 0; i < sz; ++i)
c += at(i) * (i + 1);
if (inverse) 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.saveAndSetControls(0);
s << "{";
for (uint i = 0; i < ba.size(); ++i) {
s << ba[i];
if (i < ba.size() - 1) s << ", ";
}
s << "}";
s.restoreControls();
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

View File

@@ -1,1272 +0,0 @@
/*! \file pibytearray.h
* \ingroup Core
* \~\brief
* \~english Byte array
* \~russian Байтовый массив
*/
/*
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 "pibinarystream.h"
#include <stdio.h>
class PIString;
class PIByteArray;
//! \ingroup Core
//! \~\brief
//! \~english The %PIByteArray class provides an array of bytes.
//! \~russian Класс %PIByteArray представляет собой массив байтов.
class PIP_EXPORT PIByteArray: public PIBinaryStream<PIByteArray>
{
public:
typedef ::PIMemoryBlock RawData DEPRECATEDM("use PIMemoryBlock instead");
//! \~english Constructs an empty byte array
//! \~russian Создает пустой байтовый массив
PIByteArray() {}
//! \~english Constructs copy of byte array "o"
//! \~russian Создает копию байтового массива "o"
PIByteArray(const PIByteArray & o): d(o.d) {}
//! \~english Constructs copy of byte array "o"
//! \~russian Создает копию байтового массива "o"
PIByteArray(const PIDeque<uchar> & o): d(o) {}
PIByteArray(PIByteArray && o): d(std::move(o.d)) {}
//! \~english Constructs 0-filled byte array with size "size"
//! \~russian Создает заполненный "0" байтовый массив размером "size"
PIByteArray(const uint size) {resize(size);}
//! \~english Constructs byte array from data "data" and size "size"
//! \~russian Создает байтовый массив из данных по указателю "data" размером "size"
PIByteArray(const void * data, const uint size): d((const uchar*)data, size_t(size)) {}
//! \~english Constructs byte array with size "size" filled by "t"
//! \~russian Создает заполненный "t" байтовый массив размером "size"
PIByteArray(const uint size, uchar t): d(size, t) {}
//! \~english Contructs array from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Создает массив из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\details
//! \~\code
//! PIByteArray v{1,2,3};
//! piCout << v; // {1, 2, 3}
//! \endcode
PIByteArray(std::initializer_list<uchar> init_list) : d(init_list) {}
//! \~english Swaps array `v` other with this array.
//! \~russian Меняет местами массив `v` с этим массивом.
//! \~\details
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
inline void swap(PIByteArray & other) {
d.swap(other.d);
}
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
//! \~\details ![begin, end](doc/images/pivector_begin.png)
//!
//! \~english If the array is empty, the returned iterator is equal to \a end().
//! \~russian Если массив - пуст, возвращаемый итератор будет равен \a end().
//! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend()
inline PIDeque<uchar>::iterator begin() {return d.begin();}
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
//! \~\details ![begin, end](doc/images/pivector_begin.png)
//!
//! \~english This element acts as a placeholder;
//! attempting to access it results in undefined behavior.
//! \~russian Этот элемент существует лишь условно,
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline PIDeque<uchar>::iterator end() {return d.end();}
inline PIDeque<uchar>::const_iterator begin() const {return d.begin();}
inline PIDeque<uchar>::const_iterator end() const {return d.end();}
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//!
//! \~english It corresponds to the last element of the non-reversed array.
//! If the array is empty, the returned iterator is equal to \a rend().
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на последний элемент.
//! Если массив пустой, то совпадает с итератором \a rend().
//! \~\return \ref stl_iterators
//! \~\sa \a rend(), \a begin(), \a end()
inline PIDeque<uchar>::reverse_iterator rbegin() {return d.rbegin();}
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
//! \~\details ![rbegin, rend](doc/images/pivector_rbegin.png)
//!
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
//! This element acts as a placeholder, attempting to access it results in undefined behavior.
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на элемент, предшествующий первому элементу.
//! Этот элемент существует лишь условно,
//! попытка доступа к нему приведёт к выходу за разрешенную память.
//! \~\return \ref stl_iterators
//! \~\sa \a rbegin(), \a begin(), \a end()
inline PIDeque<uchar>::reverse_iterator rend() {return d.rend();}
inline PIDeque<uchar>::const_reverse_iterator rbegin() const {return d.rbegin();}
inline PIDeque<uchar>::const_reverse_iterator rend() const {return d.rend();}
//! \~english Number of elements in the container.
//! \~russian Количество элементов массива.
//! \~\sa \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t size() const {return d.size();}
//! \~english Number of elements in the container as signed value.
//! \~russian Количество элементов массива в виде знакового числа.
//! \~\sa \a size(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline ssize_t size_s() const {return d.size_s();}
//! \~english Same as \a size().
//! \~russian Синоним \a size().
//! \~\sa \a size(), \a size_s(), \a capacity(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline size_t length() const {return d.length();}
//! \~english Number of elements that the container has currently allocated space for.
//! \~russian Количество элементов, для которого сейчас выделена память массивом.
//! \~\details
//! \~english To find out the actual number of items, use the function \a size().
//! \~russian Чтобы узнать фактическое количество элементов используйте функцию \a size().
//! \~\sa \a reserve(), \a size(), \a size_s()
inline size_t capacity() const {return d.capacity();}
//! \~english Checks if the container has no elements.
//! \~russian Проверяет пуст ли массив.
//! \~\return
//! \~english **true** if the container is empty, **false** otherwise
//! \~russian **true** если массив пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isEmpty() const {return d.isEmpty();}
//! \~english Checks if the container has elements.
//! \~russian Проверяет не пуст ли массив.
//! \~\return
//! \~english **true** if the container is not empty, **false** otherwise
//! \~russian **true** если массив не пуст, **false** иначе.
//! \~\sa \a size(), \a size_s(), \a isEmpty(), \a isNotEmpty(), \a resize(), \a reserve()
inline bool isNotEmpty() const {return d.isNotEmpty();}
//! \~english Tests whether at least one element in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяет ли какой-либо элемент массива условию,
//! заданному в передаваемой функции `test`.
//! \~\return
//! \~english **true** if, in the array,
//! it finds an element for which the provided function returns **true**;
//! otherwise it returns **false**. Always returns **false** if is empty.
//! \~russian **true** если хотя бы для одного элемента
//! передаваемая функция возвращает **true**, в остальных случаях **false**.
//! Метод возвращает **false** при любом условии для пустого массива.
//! \~\details
//! \~\sa \a every(), \a contains(), \a entries(), \a forEach()
inline bool any(std::function<bool(uchar e)> test) const {
return d.any(test);
}
//! \~english Tests whether all elements in the array passes the test
//! implemented by the provided function `test`.
//! \~russian Проверяет, удовлетворяют ли все элементы массива условию,
//! заданному в передаваемой функции `test`.
//! \~\return
//! \~english **true** if, in the array,
//! it finds an element for which the provided function returns **true**;
//! otherwise it returns **false**. Always returns **true** if is empty.
//! \~russian **true** если для всех элементов передаваемая функция возвращает **true**,
//! в остальных случаях **false**.
//! Метод возвращает **true** при любом условии для пустого массива.
//! \~\details
//! \~\sa \a any(), \a contains(), \a entries(), \a forEach()
inline bool every(std::function<bool(uchar e)> test) const {
return d.every(test);
}
//! \~english Full access to element by `index`.
//! \~russian Полный доступ к элементу по индексу `index`.
//! \~\details
//! \~english Element index starts from `0`.
//! Element index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
//! \~\sa \a at()
inline uchar & operator [](size_t index) {return d[index];}
inline uchar operator [](size_t index) const {return d[index];}
//! \~english Read only access to element by `index`.
//! \~russian Доступ исключительно на чтение к элементу по индексу `index`.
//! \~\details
//! \~english Element index starts from `0`.
//! Element index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс элемента должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline uchar at(size_t index) const {return d.at(index);}
//! \~english Last element.
//! \~russian Последний элемент массива.
//! \~\details
//! \~english Returns a reference to the last item in the array.
//! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на последний элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline uchar & back() {return d.back();}
inline uchar back() const {return d.back();}
//! \~english Last element.
//! \~russian Первый элемент массива.
//! \~\details
//! \~english Returns a reference to the last item in the array.
//! This function assumes that the array isn't empty.
//! Otherwise will be undefined behavior.
//! \~russian Возвращает ссылку на пенрвый элемент в массиве.
//! Эта функция предполагает, что массив не пустой.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline uchar & front() {return d.front();}
inline uchar front() const {return d.front();}
//! \~english Tests if element `e` exists in the array.
//! \~russian Проверяет наличие элемента `e` в массиве.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! **false** is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается **false**, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIByteArray v{1, 2, 3, 4};
//! piCout << v.contains(3); // true
//! piCout << v.contains(5); // false
//! piCout << v.contains(3, 3); // false
//! piCout << v.contains(3, -2); // true
//! piCout << v.contains(3, -99); // true
//! \endcode
//! \~\return
//! \~english **true** if the array contains an occurrence of element `e`,
//! otherwise it returns **false**.
//! \~russian **true** если элемент `e` присутствует в массиве,
//! в остальных случаях **false**.
//! \~\sa \a every(), \a any(), \a entries()
inline bool contains(uchar e, ssize_t start = 0) const {
return d.contains(e, start);
}
//! \~english Count elements equal `e` in the array.
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! 0 is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\sa \a every(), \a any(), \a contains(), \a indexOf()
inline int entries(uchar e, ssize_t start = 0) const {
return d.entries(e, start);
}
//! \~english Count elements in the array passes the test implemented by the provided function `test`.
//! \~russian Подсчитывает количество элементов в массиве,
//! проходящих по условию, заданному в передаваемой функции `test`.
//! \~\details
//! \~english Overloaded function.
//! Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! 0 is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Перегруженная функция.
//! Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается 0, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\sa \a every(), \a any(), \a contains(), \a indexWhere()
inline int entries(std::function<bool(uchar e)> test, ssize_t start = 0) const {
return d.entries(test, start);
}
//! \~english Returns the first index at which a given element `e`
//! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает первый индекс, по которому данный элемент `e`
//! может быть найден в массиве или `-1`, если такого индекса нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! `-1` is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIByteArray v{2, 5, 9};
//! piCout << v.indexOf(2); // 0
//! piCout << v.indexOf(7); // -1
//! piCout << v.indexOf(9, 2); // 2
//! piCout << v.indexOf(2, -1); // -1
//! piCout << v.indexOf(2, -3); // 0
//! \endcode
//! \~\sa \a indexWhere(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
inline ssize_t indexOf(const uchar & e, ssize_t start = 0) const {
return d.indexOf(e, start);
}
//! \~english Returns the first index passes the test implemented by the provided function `test`,
//! or `-1` if it is not present.
//! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает первый индекс элемента проходящего по условию,
//! заданному в передаваемой функции `test`, или `-1`, если таких элементов нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array at which to begin searching.
//! If the index is greater than or equal to the array's size,
//! `-1` is returned, which means the array will not be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Note: if the provided index is negative,
//! the array is still searched from front to back.
//! Default: 0 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс в массиве, откуда будет начинаться поиск.
//! Если индекс больше или равен длине массива,
//! возвращается `-1`, что означает, что массив даже не просматривается.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Если рассчитанный индекс все равно оказывается меньше 0, просматривается весь массив.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от начала к концу.
//! Значение по умолчанию равно 0, что означает, что просматривается весь массив.
//! \~\code
//! PIByteArray v{2, 5, 9};
//! piCout << v.indexWhere([](const uchar & s){return s > 3;}); // 1
//! piCout << v.indexWhere([](const uchar & s){return s > 3;}, 2); // 2
//! piCout << v.indexWhere([](const uchar & s){return s > 10;}); // -1
//! \endcode
//! \~\sa \a indexOf(), \a lastIndexOf(), \a lastIndexWhere(), \a contains()
inline ssize_t indexWhere(std::function<bool(const uchar & e)> test, ssize_t start = 0) const {
return d.indexWhere(test, start);
}
//! \~english Returns the last index at which a given element `e`
//! can be found in the array, or `-1` if it is not present.
//! \~russian Возвращает последний индекс, по которому данный элемент `e`
//! может быть найден в массиве или `-1`, если такого индекса нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array
//! at which to start searching backwards.
//! If the index is greater than or equal to the array's size,
//! causes the whole array to be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Therefore, if calculated index less than 0,
//! the array is not searched, and the method returns `-1`.
//! Note: if the provided index is negative,
//! the array is still searched from back to front.
//! Default: -1 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
//! \~\code
//! PIByteArray v{2, 5, 9, 2};
//! piCout << v.lastIndexOf(2); // 3
//! piCout << v.lastIndexOf(7); // -1
//! piCout << v.lastIndexOf(2, 2); // 0
//! piCout << v.lastIndexOf(2, -3); // 0
//! piCout << v.lastIndexOf(2, -300); // -1
//! piCout << v.lastIndexOf(2, 300); // 3
//! \endcode
//! \~\sa \a indexOf(), \a indexWhere(), \a lastIndexWhere(), \a contains()
inline ssize_t lastIndexOf(const uchar & e, ssize_t start = -1) const {
return d.lastIndexOf(e, start);
}
//! \~english Returns the last index passes the test implemented by the provided function `test`,
//! or `-1` if it is not present.
//! \~russian Возвращает последний индекс элемента проходящего по условию,
//! заданному в передаваемой функции `test`, или `-1`, если таких элементов нет.
//! \~\details
//! \~english Optional argument `start` - the position in this array
//! at which to start searching backwards.
//! If the index is greater than or equal to the array's size,
//! causes the whole array to be searched.
//! If the provided index value is a negative number,
//! it is taken as the offset from the end of the array.
//! Therefore, if calculated index less than 0,
//! the array is not searched, and the method returns `-1`.
//! Note: if the provided index is negative,
//! the array is still searched from back to front.
//! Default: -1 (entire array is searched).
//! \~russian Опциональный аргумент `start` указывает на индекс
//! c которого начинать поиск в обратном направлении.
//! Если индекс больше или равен длине массива, просматривается весь массив.
//! Если индекс является отрицательным числом, он трактуется как смещение с конца массива.
//! Обратите внимание: если индекс отрицателен, массив всё равно просматривается от конца к началу.
//! Если рассчитанный индекс оказывается меньше 0, массив даже не просматривается.
//! Значение по умолчанию равно `-1`, что равно индексу последнего элемента
//! и означает, что просматривается весь массив.
//! \~\sa \a indexOf(), \a lastIndexOf(), \a indexWhere(), \a contains()
inline ssize_t lastIndexWhere(std::function<bool(const uchar & e)> test, ssize_t start = -1) const {
return d.lastIndexWhere(test, start);
}
//! \~english Pointer to array
//! \~russian Указатель на память массива
//! \~\details
//! \~english Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
inline uchar * data(size_t index = 0) {return d.data(index);}
//! \~english Read only pointer to array
//! \~russian Указатель на память массива только для чтения.
//! \~\details
//! \~english The pointer can be used to access and modify the items in the array.
//! The pointer remains valid as long as the array isn't reallocated.
//! Optional argument `index` the position in this array,
//! where is pointer. Default: start of array.
//! \~russian Указатель можно использовать для доступа и изменения элементов в массиве.
//! Указатель остается действительным только до тех пор, пока массив не будет перераспределен.
//! Опциональный аргумент `index` указывает на индекс c которого брать указатель.
//! По умолчанию указывает на начало массива.
inline const uchar * data(size_t index = 0) const {return d.data(index);}
//! \~english Clear array, remove all elements.
//! \~russian Очищает массив, удаляет все элементы.
//! \~\details
//! \~\note
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
inline PIByteArray & clear() {
resize(0);
return *this;
}
//! \~english Assigns element 'e' to all items in the array.
//! \~russian Заполняет весь массив копиями элемента 'e'.
//! \~\details
//! \~\sa \a resize()
inline PIByteArray & fill(uchar e = 0) {
d.fill(e);
return *this;
}
//! \~english Assigns result of function 'f(size_t i)' to all items in the array.
//! \~russian Заполняет весь массив результатом вызова функции 'f(size_t i)'.
//! \~\details
//! \~\sa \a resize()
inline PIByteArray & fill(std::function<uchar(size_t i)> f) {
d.fill(f);
return *this;
}
//! \~english Same as \a fill().
//! \~russian Тоже самое что и \a fill().
//! \~\sa \a fill(), \a resize()
inline PIByteArray & assign(uchar e = 0) {return fill(e);}
//! \~english First does `resize(new_size)` then `fill(e)`.
//! \~russian Сначала делает `resize(new_size)`, затем `fill(e)`.
//! \~\sa \a fill(), \a resize()
inline PIByteArray & assign(size_t new_size, uchar e) {
resize(new_size);
return fill(e);
}
//! \~english Sets size of the array, new elements are copied from `e`.
//! \~russian Устанавливает размер массива, новые элементы копируются из `e`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements are initialized from `e`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и создаются из `e`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIByteArray & resize(size_t new_size, uchar e = 0) {
d.resize(new_size, e);
return *this;
}
//! \~english Sets size of the array, new elements created by function `f(size_t i)`.
//! \~russian Устанавливает размер массива, новые элементы создаются функцией `f(size_t i)`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! elements are added to the end; the new elements created by function `f(size_t i)`.
//! If `new_size` is less than the current \a size(), elements are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер массива \a size(),
//! новые элементы добавляются в конец массива и функцией `f(size_t i)`.
//! Если `new_size` меньше чем текущий размер массива \a size(),
//! лишние элементы удаляются с конца массива.
//! \~\sa \a size(), \a clear()
inline PIByteArray & resize(size_t new_size, std::function<uchar(size_t i)> f) {
d.resize(new_size, f);
return *this;
}
//! \~english Return resized byte array
//! \~russian Возвращает копию байтового массива с измененным размером
PIByteArray resized(uint new_size) const {
PIByteArray ret(new_size);
memcpy(ret.data(), data(), new_size);
return ret;
}
//! \~english Attempts to allocate memory for at least `new_size` elements.
//! \~russian Резервируется память под как минимум `new_size` элементов.
//! \~\details
//! \~english If you know in advance how large the array will be,
//! you should call this function to prevent reallocations and memory fragmentation.
//! If `new_size` is greater than the current \a capacity(),
//! new storage is allocated, otherwise the function does nothing.
//! This function does not change the \a size() of the array.
//! \~russian Если вы заранее знаете, насколько велик будет массив,
//! вы можете вызвать эту функцию, чтобы предотвратить перераспределение и фрагментацию памяти.
//! Если размер `new_size` больше чем выделенная память \a capacity(),
//! то произойдёт выделение новой памяти и перераспределение массива.
//! Эта функция не изменяет количество элементов в массиве \a size().
//! \~\sa \a size(), \a capacity(), \a resize()
inline PIByteArray & reserve(size_t new_size) {
d.reserve(new_size);
return *this;
}
//! \~english Inserts value `e` at `index` position in the array.
//! \~russian Вставляет значение `e` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше 0 и меньше или равен \a size().
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIByteArray & insert(size_t index, uchar e = 0) {
d.insert(index, e);
return *this;
}
//! \~english Inserts array `v` at `index` position in the array.
//! \~russian Вставляет массив `v` в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIByteArray & insert(size_t index, const PIByteArray & v) {
d.insert(index, v.d);
return *this;
}
//! \~english Inserts the given elements at `index` position in the array.
//! \~russian Вставляет элементы в позицию `index` в массиве.
//! \~\details
//! \~english The index must be greater than or equal to 0 and less than or equal to \a size().
//! Inserts the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Индекс должен быть больше или равен 0 и меньше или равен \a size().
//! Вставляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append(), \a prepend(), \a remove()
inline PIByteArray & insert(size_t index, std::initializer_list<uchar> init_list) {
d.insert(index, init_list);
return *this;
}
//! \~english Removes `count` elements from the middle of the array, starting at `index` position.
//! \~russian Удаляет элементы из массива, начиная с позиции `index` в количестве `count`.
//! \~\details
//! \~\sa \a resize(), \a insert(), \a removeOne(), \a removeAll(), \a removeWhere()
inline PIByteArray & remove(size_t index, size_t count = 1) {
d.remove(index, count);
return *this;
}
//! \~english Return sub-array starts from "index" and has "count" or less bytes
//! \~russian Возвращает подмассив с данными от индекса "index" и размером не более "count"
PIByteArray getRange(size_t index, size_t count) const {
return d.getRange(index, count);
}
//! \~english Reverses this array.
//! \~russian Обращает порядок следования элементов этого массива.
//! \~\details
//! \~english This method reverses an array [in place](https://en.wikipedia.org/wiki/In-place_algorithm).
//! The first array element becomes the last, and the last array element becomes the first.
//! The reverse method transposes the elements of the calling array object in place,
//! mutating the array, and returning a reference to the array.
//! \~russian Метод reverse() на месте переставляет элементы массива,
//! на котором он был вызван, изменяет массив и возвращает ссылку на него.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\sa \a reversed()
inline PIByteArray & reverse() {
d.reverse();
return *this;
}
//! \~english Returns reversed array.
//! \~russian Возвращает перевернутый массив.
//! \~\details
//! \~english Returns a copy of the array with elements in reverse order.
//! The first array element becomes the last, and the last array element becomes the first.
//! \~russian Возвращает копию массива с элементами в обратном порядке.
//! Первый элемент массива становится последним, а последний — первым.
//! \~\sa \a reverse()
inline PIByteArray reversed() const {
PIByteArray ret(*this);
return ret.reverse();
}
//! \~english Increases or decreases the size of the array by `add_size` elements.
//! \~russian Увеличивает или уменьшает размер массива на `add_size` элементов.
//! \~\details
//! \~english If `add_size > 0` then elements are added to the end of the array.
//! If `add_size < 0` then elements are removed from the end of the array.
//! If `add_size < 0` and there are fewer elements in the array than specified, then the array becomes empty.
//! \~russian Если `add_size > 0`, то в конец массива добавляются элементы.
//! Если `add_size < 0`, то с конца массива удаляются элементы.
//! Если `add_size < 0` и в массиве меньше элементов чем указано, то массив становится пустым.
//! \~\sa \a resize()
inline PIByteArray & enlarge(ssize_t add_size, uchar e = 0) {
d.enlarge(add_size, e);
return *this;
}
//! \~english Remove no more than one element equal `e`.
//! \~russian Удаляет первый элемент, который равен элементу `e`.
//! \~\details
//! \~\sa \a remove(), \a removeAll(), \a removeWhere()
inline PIByteArray & removeOne(uchar e) {
d.removeOne(e);
return *this;
}
//! \~english Remove all elements equal `e`.
//! \~russian Удаляет все элементы, равные элементу `e`.
//! \~\details
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIByteArray & removeAll(uchar e) {
d.removeAll(e);
return *this;
}
//! \~english Remove all elements in the array
//! passes the test implemented by the provided function `test`.
//! \~russian Удаляет все элементы, удовлетворяющие условию,
//! заданному в передаваемой функции `test`.
//! \~\details
//! \~\sa \a remove(), \a removeOne(), \a removeWhere()
inline PIByteArray & removeWhere(std::function<bool(uchar e)> test) {
d.removeWhere(test);
return *this;
}
//! \~english Appends the given element `e` to the end of the array.
//! \~russian Добавляет элемент `e` в конец массива.
//! \~\details
//! \~english If size() is less than capacity(), which is most often
//! then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If the new size() is greater than capacity()
//! then all iterators and references
//! (including the past-the-end iterator) are invalidated.
//! Otherwise only the past-the-end iterator is invalidated.
//! \~russian Если size() меньше capacity(), что часто бывает,
//! то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если новый size() больше, чем capacity(),
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов, указывающих на конец массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_front(), \a append(), \a prepend(), \a insert()
inline PIByteArray & push_back(uchar e) {
d.push_back(e);
return *this;
}
//! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a push_back()
inline PIByteArray & push_back(std::initializer_list<uchar> init_list) {
d.push_back(init_list);
return *this;
}
//! \~english Appends the given array `v` to the end of the array.
//! \~russian Добавляет массив `v` в конец массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_back()
inline PIByteArray & push_back(const PIByteArray & v) {
d.push_back(v.d);
return *this;
}
//! \~english Add to the end data "data" with size "size"
//! \~russian Добавляет в конец массива данные по указателю "data" размером "size"
PIByteArray & push_back(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english If there is free space at the beginning of the array,
//! which is most often, then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If there is no free space at the beginning of the array
//! then all iterators and references
//! (including the past-the-begin iterator) are invalidated.
//! Otherwise only the past-the-begin iterator is invalidated.
//! \~russian Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIByteArray & push_front(uchar e) {
d.push_front(e);
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a push_front()
inline PIByteArray & push_front(const PIByteArray & v) {
d.push_front(v.d);
return *this;
}
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIByteArray & push_front(std::initializer_list<uchar> init_list) {
d.push_front(init_list);
return *this;
}
//! \~english Appends the given element `e` to the begin of the array.
//! \~russian Добавляет элемент `e` в начало массива.
//! \~\details
//! \~english If there is free space at the beginning of the array,
//! which is most often, then the addition will be very fast.
//! In any case, the addition is fast and does not depend on the size of the array.
//! If there is no free space at the beginning of the array
//! then all iterators and references
//! (including the past-the-begin iterator) are invalidated.
//! Otherwise only the past-the-begin iterator is invalidated.
//! \~russian Если в начале массива имеется свободное место,
//! что часто бывает, то добавление будет очень быстрым.
//! В любом случае добавление быстрое и не зависит от размера массива.
//! Если в начале массива нет свободного места,
//! то все итераторы и указатели становятся нерабочими.
//! В противном случае все, кроме итераторов указывающих, на начало массива,
//! остаются в рабочем состоянии.
//! \~\sa \a push_back(), \a append(), \a prepend(), \a insert()
inline PIByteArray & prepend(uchar e) {
d.prepend(e);
return *this;
}
//! \~english Appends the given array `v` to the begin of the array.
//! \~russian Добавляет массив `v` в начало массива.
//! \~\details
//! \~english Overloaded function.
//! \~russian Перегруженая функция.
//! \~\sa \a prepend()
inline PIByteArray & prepend(const PIByteArray & v) {
d.prepend(v.d);
return *this;
}
//! \~english Appends the given elements to the begin of the array.
//! \~russian Добавляет элементы в начало массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a append()
inline PIByteArray & prepend(std::initializer_list<uchar> init_list) {
d.prepend(init_list);
return *this;
}
//! \~english Remove one element from the end of the array.
//! \~russian Удаляет один элемент с конца массива.
//! \~\details
//! \~english Deleting an element from the end is very fast
//! and does not depend on the size of the array.
//! \~russian Удаление элемента с конца выполняется очень быстро
//! и не зависит от размера массива.
//! \~\sa \a pop_front(), \a take_back(), \a take_front()
inline PIByteArray & pop_back() {
d.pop_back();
return *this;
}
//! \~english Remove one element from the begining of the array.
//! \~russian Удаляет один элемент с начала массива.
//! \~\details
//! \~english Removing an element from the beginning takes longer than from the end.
//! This time is directly proportional to the size of the array.
//! All iterators and references are invalidated.
//! \~russian Удаление элемента с начала выполняется дольше, чем с конца.
//! Это время прямопропорционально размеру массива.
//! При удалении элемента все итераторы и указатели становятся нерабочими.
//! \~\sa \a pop_back(), \a take_back(), \a take_front()
inline PIByteArray & pop_front() {
d.pop_front();
return *this;
}
//! \~english Remove one element from the end of the array and return it.
//! \~russian Удаляет один элемент с начала массива и возвращает его.
//! \~\details
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline uchar take_back() {
return d.take_back();
}
//! \~english Remove one element from the begining of the array and return it.
//! \~russian Удаляет один элемент с конца массива и возвращает его.
//! \~\details
//! \~\sa \a take_front(), \a pop_back(), \a pop_front()
inline uchar take_front() {
return d.take_front();
}
//! \~english Returns a new array with all elements
//! that pass the test implemented by the provided function `test`.
//! \~russian Возвращает новый массив со всеми элементами,
//! прошедшими проверку, задаваемую в передаваемой функции `test`.
//! \~\details
//! \~\code
//! PIByteArray v{3, 2, 5, 2, 7};
//! PIByteArray v2 = v.filter([](const uchar & i){return i > 2;});
//! piCout << v2; // {3, 5, 7}
//! \endcode
//! \~\sa \a map(), \a any(), \a every()
inline PIByteArray filter(std::function<bool(const uchar & e)> test) const {
return PIByteArray(d.filter(test));
}
//! \~english Execute function `void f(const uchar & e)` for every element in array.
//! \~russian Выполняет функцию `void f(const uchar & e)` для каждого элемента массива.
//! \~\details
//! \~russian Не позволяет изменять элементы массива.
//! Для редактирования элементов используйте функцию вида `void f(uchar & e)`.
//! \~english Does not allow changing array elements.
//! To edit elements, use the function like `void f(T & e)`
//! \~\code
//! PIByteArray v{1, 2, 3, 4, 5};
//! int s = 0;
//! v.forEach([&s](const uchar & e){s += e;});
//! piCout << s; // 15
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline void forEach(std::function<void(const uchar & e)> f) const {
d.forEach(f);
}
//! \~english Execute function `void f(uchar & e)` for every element in array.
//! \~russian Выполняет функцию `void f(uchar & e)` для каждого элемента массива.
//! \~\details
//! \~english Overloaded function.
//! Allows you to change the elements of the array.
//! \~russian Перегруженая функция.
//! Позволяет изменять элементы массива.
//! \~\code
//! PIByteArray v{1, 2, 3, 4, 5};
//! v.forEach([](uchar & e){e++;});
//! piCout << v; // {2, 3, 4, 5, 6}
//! \endcode
//! \~\sa \a filter(), \a map(), \a reduce(), \a any(), \a every()
inline PIByteArray & forEach(std::function<void(uchar & e)> f) {
d.forEach(f);
return *this;
}
//! \~english Сreates a new array populated with the results
//! of calling a provided function `ST f(const uchar & e)` on every element in the calling array.
//! \~russian Создаёт новый массив с результатом вызова указанной функции
//! `ST f(const T & e)` для каждого элемента массива.
//! \~\details
//! \~english Calls a provided function`ST f(const uchar & e)`
//! once for each element in an array, in order,
//! and constructs a new array from the results.
//! \~russian Метод `map` вызывает переданную функцию `ST f(const uchar & e)`
//! один раз для каждого элемента в порядке их появления
//! и конструирует новый массив из результатов её вызова.
//! \~\code
//! PIByteArray v{0x31, 0x0A, 0xFF};
//! PIStringList sl = v.map<PIString>([](const uchar & i){return PIString::fromNumber(i, 16);});
//! piCout << sl; {"31", "A", "FF"}
//! \endcode
//! \~\sa \a forEach(), \a reduce()
template <typename ST>
inline PIDeque<ST> map(std::function<ST(const uchar & e)> f) const {
return d.map<ST>(f);
}
//! \~english Applies the function `ST f(const uchar & e, const ST & acc)`
//! to each element of the array (from left to right), returns one value.
//! \~russian Применяет функцию `ST f(const uchar & e, const ST & acc)`
//! к каждому элементу массива (слева-направо), возвращает одно значение.
//! \~\details
//! \~english The reduce() method performs the `f` function
//! once for each element in the array.
//! If the `initial` argument is passed when calling reduce(),
//! then when the function `f` is called for the first time,
//! the value of `acc` will be assigned to `initial`.
//! If the array is empty, the value `initial` will be returned.
//! \param f is a function like `ST f(const uchar & e, const ST & acc)`,
//! executed for each element of the array. It takes two arguments:
//! * **e** - current element of the array
//! * **acc** - accumulator accumulating the value
//! which this function returns after visiting the next element
//!
//! \param initial _optional_ Object used as the second argument
//! when the `f` function is first called.
//! \~russian Метод reduce() выполняет функцию `f`
//! один раз для каждого элемента, присутствующего в массиве.
//! Если при вызове reduce() передан аргумент `initial`,
//! то при первом вызове функции `f` значение `acc`
//! будет равным значению `initial`.
//! Если массив пустой то будет возвращено значение `initial`.
//! \param f Функция, вида `ST f(const uchar & e, const ST & acc)`,
//! выполняющаяся для каждого элемента массива.
//! Она принимает два аргумента:
//! * **e** - текущий элемент массива
//! * **acc** - аккумулятор, аккумулирующий значение
//! которое возвращает эта функция после посещения очередного элемента
//!
//! \param initial _опциональный_ Объект,
//! используемый в качестве второго аргумента при первом вызове функции `f`.
//!
//! \~\code
//! PIByteArray v{1, 2, 3, 4, 5};
//! PIString s = v.reduce<PIString>([](const uchar & e, const PIString & acc){return acc + PIString::fromNumber(e);});
//! piCout << s; // "12345"
//! \endcode
//! \~\sa \a forEach(), \a map()
template <typename ST>
inline ST reduce(std::function<ST(const uchar & e, const ST & acc)> f, const ST & initial = ST()) const {
return d.reduce<ST>(f, initial);
}
//! \~english Convert data to Base 64 and return this byte array
//! \~russian Преобразует данные в Base 64 и возвращает текущий массив
PIByteArray & convertToBase64();
//! \~english Convert data from Base 64 and return this byte array
//! \~russian Преобразует данные из Base 64 и возвращает текущий массив
PIByteArray & convertFromBase64();
//! \~english Return converted to Base 64 data
//! \~russian Возвращает копию байтового массива, преобразованного в Base 64
PIByteArray toBase64() const;
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;}
//! \~english Return string representation of data, each byte in "base" base, separated by spaces
//! \~russian Возвращает текстовое представление байтового массива, каждый байт в "base" системе, с пробелами
PIString toString(int base = 16) const;
//! \~english
//! Returns a hex encoded copy of the byte array, without spaces.
//! The hex encoding uses the numbers 0-9 and the letters a-f.
//! \~russian
//! Возвращает шестнадцатеричное представление массива, без пробелов.
//! Оно использует цифры 0-9 и буквы a-f.
PIString toHex() const;
//! \~english Add to the end data "data" with size "size"
//! \~russian Добавляет в конец массива данные по указателю "data" размером "size"
PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;}
//! \~english Add to the end byte array "data"
//! \~russian Добавляет в конец массива содержимое массива "data"
PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;}
//! \~english Add to the end "t"
//! \~russian Добавляет в конец массива байт "t"
PIByteArray & append(uchar t) {push_back(t); return *this;}
//! \~english Appends the given elements to the end of the array.
//! \~russian Добавляет элементы в конец массива.
//! \~\details
//! \~english Overloaded function.
//! Appends the given elements from
//! [C++11 initializer list](https://en.cppreference.com/w/cpp/utility/initializer_list).
//! \~russian Перегруженая функция.
//! Добавляет элементы из
//! [списка инициализации C++11](https://ru.cppreference.com/w/cpp/utility/initializer_list).
//! \~\sa \a push_back()
inline PIByteArray & append(std::initializer_list<uchar> init_list) {
d.append(init_list);
return *this;
}
//! \~english Returns 8-bit checksum
//! \~russian Возвращает 8-битную контрольную сумму
uchar checksumPlain8(bool inverse = true) const;
//! \~english Returns 32-bit checksum
//! \~russian Возвращает 32-битную контрольную сумму
uint checksumPlain32(bool inverse = true) const;
//! \~english Returns 8-bit checksum CRC-8
//! \~russian Возвращает 8-битную контрольную сумму CRC-8
uchar checksumCRC8() const;
//! \~english Returns 16-bit checksum CRC-16
//! \~russian Возвращает 16-битную контрольную сумму CRC-16
ushort checksumCRC16() const;
//! \~english Returns 32-bit checksum CRC-32
//! \~russian Возвращает 32-битную контрольную сумму CRC-32
uint checksumCRC32() const;
//! \~english Returns hash of content
//! \~russian Возвращает хэш содержимого
uint hash() const;
void operator =(const PIDeque<uchar> & o) {resize(o.size()); memcpy(data(), o.data(), o.size());}
PIByteArray & operator =(const PIByteArray & o) {if (this == &o) return *this; clear(); append(o); return *this;}
PIByteArray & operator =(PIByteArray && o) {swap(o); return *this;}
static PIByteArray fromUserInput(PIString str);
static PIByteArray fromHex(PIString str);
//! \~english Return converted from Base 64 data
//! \~russian Возвращает массив из Base 64 представления
static PIByteArray fromBase64(const PIByteArray & base64);
static PIByteArray fromBase64(const PIString & base64);
bool binaryStreamAppendImp(const void * d_, size_t s) {
append(d_, s);
return true;
}
bool binaryStreamTakeImp(void * d_, size_t s) {
size_t rs = size();
if (rs > s) rs = s;
memcpy(d_, data(), rs);
remove(0, rs);
return rs == s;
}
ssize_t binaryStreamSizeImp() const {return size();}
private:
PIDeque<uchar> d;
};
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) < 0;
}
return v0.size() < v1.size();
}
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator >(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) > 0;
}
return v0.size() > v1.size();
}
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator ==(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return true;
return memcmp(v0.data(), v1.data(), v0.size()) == 0;
}
return false;
}
//! \relatesalso PIByteArray
//! \~english Byte arrays compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PIByteArray & v0, const PIByteArray & v1) {
if (v0.size() == v1.size()) {
if (v0.isEmpty()) return false;
return memcmp(v0.data(), v1.data(), v0.size()) != 0;
}
return true;
}
#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
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
PIP_EXPORT PICout operator <<(PICout s, const PIByteArray & ba);
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIByteArray) {
s.binaryStreamAppend((int)v.size_s());
s.binaryStreamAppend(v.data(), v.size());
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIByteArray) {
v.resize(s.binaryStreamTakeInt());
s.binaryStreamTake(v.data(), v.size());
return s;
}
//! \relatesalso PIByteArray
//! \~english Returns PIByteArray::hash() of "ba"
//! \~russian Возвращает PIByteArray::hash() от "ba"
template<> inline uint piHash(const PIByteArray & ba) {return ba.hash();}
//! \relatesalso PIByteArray
//! \~english Swap contents betwee "f" and "s"
//! \~russian Меняет содержимое массивов "f" и "s"
template<> inline void piSwap(PIByteArray & f, PIByteArray & s) {f.swap(s);}
//! \relatesalso PIByteArray
//! \~english Store "value" to bytearray and returns it
//! \~russian Сохраняет "value" в байтовый массив и возвращает его
template <typename T> PIByteArray piSerialize(const T & value) {
PIByteArray ret;
ret << value;
return ret;
}
//! \relatesalso PIByteArray
//! \~english Restore type "T" from bytearray "data" and returns it
//! \~russian Извлекает тип "T" из байтового массива "data" и возвращает его
template <typename T> T piDeserialize(const PIByteArray & data) {
T ret;
if (!data.isEmpty()) {
PIByteArray ba(data);
ba >> ret;
}
return ret;
}
#endif // PIBYTEARRAY_H

View File

@@ -1,385 +0,0 @@
/*
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 "pistring.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>
//! \class PIChar pichar.h
//! \~\details
//! \~english
//! This class is wrapper around UTF16.
//! There are many contructors and information functions
//!
//! \~russian
//! %PIChar хранит один сивол в UTF16. Имеет много контрукторов, геттеров в различные
//! кодировки (системную, консольную, UTF8) и информационных функций.
//!
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
mbstate_t state;
memset(&state, 0, sizeof(state));
wchar_t wc;
ret = mbrtowc(&wc, c, size, &state);
//printf("mbtowc = %d\n", ret);
//piCout << errorString();
if (ret < 1) return 0;
return ushort(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((ushort)toupper(ch));
#ifdef PIP_ICU
UChar c(0);
UErrorCode e((UErrorCode)0);
u_strToUpper(&c, 1, (const UChar*)(&ch), 1, 0, &e);
return PIChar((ushort)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((ushort)towupper(ch));
}
PIChar PIChar::toLower() const {
if (isAscii()) return PIChar((ushort)tolower(ch));
#ifdef PIP_ICU
UChar c(0);
UErrorCode e((UErrorCode)0);
u_strToLower(&c, 1, (const UChar*)(&ch), 1, 0, &e);
return PIChar((ushort)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((ushort)towlower(ch));
}
PICout operator <<(PICout s, const PIChar & v) {
s.space();
s.saveAndSetControls(0);
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
s << PIString(v);
#endif
}
s.restoreControls();
return s;
}

View File

@@ -1,265 +0,0 @@
/*! \file pichar.h
* \ingroup Core
* \~\brief
* \~english Single string character
* \~russian Один символ строки
*/
/*
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 PIP_EXPORT char * __syslocname__;
extern PIP_EXPORT char * __sysoemname__;
extern PIP_EXPORT char * __utf8name__;
//! \ingroup Core
//! \~\brief
//! \~english %PIChar represents a single character.
//! \~russian %PIChar представляет собой один символ строки.
class PIP_EXPORT PIChar
{
friend class PIString;
friend PICout operator <<(PICout s, const PIChar & v);
public:
//! \~english Contructs Ascii symbol
//! \~russian Создает символ Ascii
PIChar(char c) {ch = c;}
//! \~english Contructs ascii symbol
//! \~russian Создает символ Ascii
PIChar(uchar c) {ch = c;}
//! \~english Contructs 2-bytes symbol
//! \~russian Создает 2-байтный символ
PIChar(ushort c = 0) {ch = c;}
//! \~english Contructs 2-bytes symbol from `wchar_t`
//! \~russian Создает 2-байтный символ из `wchar_t`
PIChar(wchar_t c) {ch = c;}
//! \~english Contructs symbol from system locale and no more than 4 bytes of string
//! \~russian Создает символ из системной локали не более 4 байт длины
PIChar(const char * c, int * bytes = 0);
//! \~english Copy operator
//! \~russian Оператор присваивания
PIChar & operator =(const char v) {ch = v; return *this;}
//! \~english Copy operator
//! \~russian Оператор присваивания
PIChar & operator =(const wchar_t v) {ch = v; return *this;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const PIChar & o) const;
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const PIChar & o) const {return !(o == *this);}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >(const PIChar & o) const;
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <(const PIChar & o) const;
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >=(const PIChar & o) const;
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <=(const PIChar & o) const;
//! \~english Returns \b true if symbol is digit ('0' to '9')
//! \~russian Возвращает \b true если символ является
bool isDigit() const;
//! \~english Returns \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F')
//! \~russian Возвращает \b true если символ является HEX цифрой ('0' до '9', 'a' до 'f', 'A' до 'F')
bool isHex() const;
//! \~english Returns \b true if symbol is drawable (without space)
//! \~russian Возвращает \b true если символ является графическим (исключая пробельные)
bool isGraphical() const;
//! \~english Returns \b true if symbol is control byte (< 32 or 127)
//! \~russian Возвращает \b true если символ является контрольным (< 32 or 127)
bool isControl() const;
//! \~english Returns \b true if symbol is in lower case
//! \~russian Возвращает \b true если символ в нижнем регистре
bool isLower() const;
//! \~english Returns \b true if symbol is in upper case
//! \~russian Возвращает \b true если символ в верхнем регистре
bool isUpper() const;
//! \~english Returns \b true if symbol is printable (with space)
//! \~russian Возвращает \b true если символ является печатным (включая пробельные)
bool isPrint() const;
//! \~english Returns \b true if symbol is space or tab
//! \~russian Возвращает \b true если символ является пробельным или табуляцией
bool isSpace() const;
//! \~english Returns \b true if symbol is alphabetical letter
//! \~russian Возвращает \b true если символ является алфавитной буквой
bool isAlpha() const;
//! \~english Returns \b true if symbol is Ascii (< 128)
//! \~russian Возвращает \b true если символ является Ascii (< 128)
bool isAscii() const;
const wchar_t * toWCharPtr() const;
//! \~english Returns as `char *` string
//! \~russian Возвращает символ как указатель на `char *`
const char * toCharPtr() const;
wchar_t toWChar() const;
//! \~english Returns symbol as Ascii
//! \~russian Возвращает символ в Ascii
char toAscii() const {return ch % 256;}
//! \~english Returns symbol as console codepage
//! \~russian Возвращает символ в консольной кодировке
char toConsole1Byte() const;
//! \~english Returns symbol as system codepage
//! \~russian Возвращает символ в системной кодировке
char toSystem() const;
ushort unicode16Code() const {return ch;}
//! \~english Returns symbol in upper case
//! \~russian Возвращает символ в нижнем регистре
PIChar toUpper() const;
//! \~english Returns symbol in lower case
//! \~russian Возвращает символ в верхнем регистре
PIChar toLower() const;
//! \~english Returns symbol from console codepage
//! \~russian Возвращает символ из консольной кодировки
static PIChar fromConsole(char c);
//! \~english Returns symbol from system codepage
//! \~russian Возвращает символ из системной кодировки
static PIChar fromSystem(char c);
//! \~english Returns symbol from UTF8 codepage
//! \~russian Возвращает символ из UTF8 кодировки
static PIChar fromUTF8(const char * c);
private:
ushort ch;
};
//! \relatesalso PIChar
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
PIP_EXPORT PICout operator <<(PICout s, const PIChar & v);
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator ==(const int v, const PIChar & c) {return (PIChar((ushort)v) == c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >(const int v, const PIChar & c) {return (PIChar((ushort)v) > c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <(const int v, const PIChar & c) {return (PIChar((ushort)v) < c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const int v, const PIChar & c) {return (PIChar((ushort)v) >= c);}
//! \relatesalso PIChar
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const int v, const PIChar & c) {return (PIChar((ushort)v) <= c);}
#endif // PICHAR_H

View File

@@ -1,263 +0,0 @@
/*
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 pichunkstream.h
//! \details
//! \~english \section PIChunkStream_sec0 Synopsis
//! \~russian \section PIChunkStream_sec0 Краткий обзор
//! \~english
//! 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.
//!
//! \~russian
//! Этот класс предоставляет очень удобный механизм для сохранения и извлечения значений
//! в/из \a PIByteArray. Главным плюсом является то, что данные не будут зависеть от порядка
//! и наличия значений.
//!
//! \~english \section PIChunkStream_sec1 Mechanism
//! \~russian \section PIChunkStream_sec1 Механизм
//! \~english
//! %PIChunkStream works with items called "chunk". Chunk is an ID, size and any value that
//! can be stored and restored to/from %PIChunkStream with stream operators << and >>.
//!
//! To construct %PIChunkStream for writing data use any non-default constructor. Empty constructor
//! creates internal 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
//! readed chunk. Then you can get value of this chunk with functions \a getData() or \a get(),
//! but you should definitely know type of this value. You can read from byte array
//! while \a atEnd() if false.
//!
//! \~russian
//! %PIChunkStream работает с элементами под названием "чанк". Чанк имеет ID, размер и значение,
//! и может быть записан или прочитан в/из %PIChunkStream с помощью операторов << и >>.
//!
//! Для создания потока на запись используется любой не-умолчальный конструктор. Пустой конструктор
//! создает внутренний буфер, который можно получить с помощью метода \a data().
//! Непустой конструктор работает с переданным байтовым массивом.
//!
//! Для чтения чанков из байтового массива используется метод \a read(), который возвращает
//! ID прочитанного чанка. Получить значение этого чанка далее можно с помощью методов \a getData() или get(),
//! но тип значения должен быть известен. Читать из потока можно пока метод \a atEnd() возвращает ложь.
//!
//! \~english \section PIChunkStream_sec2 Examples
//! \~russian \section PIChunkStream_sec2 Пример
//!
//! \~english Using simple operator and cascade serialization:
//! \~russian Использование простого оператора и каскадная сериализация:
//!
//! \~english Prepare your structs to work with %PIChunkStream:
//! \~russian Подготовка своей структуры для работы с %PIChunkStream:
//! \~\snippet pichunkstream.cpp struct
//! \~english Old-style writing to %PIChunkStream:
//! \~russian Старый стиль использования %PIChunkStream:
//! \~\snippet pichunkstream.cpp write
//! \~english Fastest reading from %PIChunkStream:
//! \~russian Самое быстрое чтение из %PIChunkStream:
//! \~\snippet pichunkstream.cpp read
//!
//! \~english And next code show how to serialize your struct with %PIChunkStream:
//! \~russian Следующий код показывает, как сериализовать свою структуру в %PIChunkStream:
//! \~\snippet pichunkstream.cpp write_new
//!
//! \~english ... and deserialize:
//! \~russian ... и десериализовать:
//! \~\snippet pichunkstream.cpp read_new
//!
void PIChunkStream::setSource(const PIByteArray & data) {
data_ = const_cast<PIByteArray*>(&data);
_init();
}
void PIChunkStream::setSource(PIByteArray * data) {
data_ = (data ? data : &tmp_data);
_init();
}
PIByteArray PIChunkStream::data() const {
if (first_byte_taken) {
PIByteArray ret(*data_);
ret.prepend((uchar)(0x80 | version_));
return ret;
}
return *data_;
}
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_) >> PIMemoryBlock(last_data.data(), last_data.size_s());
break;
default: break;
}
return last_id;
}
int PIChunkStream::peekVInt(Version version_, uchar * data_, int sz, uint & ret) {
switch (version_) {
case Version_1:
memcpy(&ret, data_, 4);
return 4;
case Version_2: {
PIByteArray hdr(data_, piMini(4, sz));
hdr.resize(4);
uchar hsz = 0;
ret = readVInt(hdr, &hsz);
return hsz;
}
default: break;
}
return 0;
}
void PIChunkStream::replaceChunk(int id, const PIByteArray & v) {
if (!data_map.contains(id)) return;
auto & pos(data_map[id]);
PIByteArray nsba;
writeVInt(nsba, v.size());
int size_mod = (v.size_s() + nsba.size_s()) - (pos.length + pos.size_bytes);
pos.length = v.size_s();
if (size_mod != 0) {
auto it = data_map.makeIterator();
while (it.next()) {
if (it.value().start > pos.start) {
it.value().start += size_mod;
}
}
if (size_mod > 0) {
data_->insert(pos.start, PIByteArray(size_mod));
} else {
data_->remove(pos.start, -size_mod);
}
}
memcpy(data_->data(pos.start - pos.size_bytes), nsba.data(), nsba.size());
pos.start += nsba.size_s() - pos.size_bytes;
memcpy(data_->data(pos.start), v.data(), pos.length);
}
void PIChunkStream::readAll() {
data_map.clear();
if (!data_) return;
int pos = 0, sz = data_->size_s(), hsz = 0;
uint csz = 0, cid = 0;
while (pos < sz) {
pos += peekVInt((Version)version_, data_->data(pos), data_->size_s() - pos, cid);
hsz = peekVInt((Version)version_, data_->data(pos), data_->size_s() - pos, csz);
pos += hsz;
data_map[cid] = CacheEntry(pos, csz, hsz);
pos += csz;
}
}
PIChunkStream::~PIChunkStream() {
}
bool PIChunkStream::extract(PIByteArray & data, bool read_all) {
if (data.size_s() < 4) return false;
data >> tmp_data;
if (tmp_data.size_s() < 4) return false;
data_ = &tmp_data;
_init();
if (read_all) readAll();
return true;
}
void PIChunkStream::_init() {
first_byte_taken = false;
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();
first_byte_taken = true;
break;
default:
version_ = Version_1;
break;
}
} else {
version_ = Version_1;
}
}
}
uint PIChunkStream::readVInt(PIByteArray & s, uchar * bytes_cnt) {
if (s.isEmpty()) return 0;
uchar bytes[4];
uchar abc;
s >> bytes[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;
}
if (bytes_cnt) *bytes_cnt = (abc + 1);
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);
}

View File

@@ -1,220 +0,0 @@
/*! \file pichunkstream.h
* \ingroup Core
* \~\brief
* \~english Binary markup de/serializator stream
* \~russian Бинарный поток для де/сериализации с разметкой
*/
/*
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"
//! \ingroup Core
//! \~\brief
//! \~english Class for binary de/serialization.
//! \~russian Класс для бинарной де/сериализации.
class PIP_EXPORT PIChunkStream
{
public:
//! \~english
//! Version of data packing. Read-access %PIChunkStream automatic detect version, but write-access
//! %PIChunkStream by default write in new version, be careful!
//! \~russian
//! Версия хранения данных. %PIChunkStream на чтение автоматически определяет версию, но для записи
//! использует по умолчанию новую, осторожно!
enum Version {
Version_1 /*! \~english First, old version \~russian Первая, старая версия */,
Version_2 /*! \~english Second, more optimized version \~russian Вторая, более оптимизированная версия */ = 2,
};
//! \~english Contructs stream for read from "data"
//! \~russian Создает поток на чтение из "data"
PIChunkStream(const PIByteArray & data): version_(Version_2) {setSource(data);}
//! \~english Contructs stream for read or write to/from "data", or empty stream for write if "data" = 0
//! \~russian Создает поток на чтение или запись из/в "data", или пустой поток на запись если "data" = 0
PIChunkStream(PIByteArray * data = 0, Version v = Version_2): version_(v) {setSource(data);}
//! \~english Contructs empty stream for write with version \"v\"
//! \~russian Создает пустой поток на запись с версией \"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;
};
template <typename T>
struct ChunkConst {
ChunkConst(int i, const T & d): id(i), data(d) {}
int id;
const T & data;
};
//! \~english Returns chunk with ID "id" and value "data" for write to stream
//! \~russian Возвращает чанк с ID "id" и значением "data" для записи в поток
template <typename T> static ChunkConst<T> chunk(int id, const T & data) {return ChunkConst<T>(id, data);}
//! \~english Add to this stream chunk with ID "id" and value "data"
//! \~russian Добавляет в этот поток чанк с ID "id" и значением "data"
template <typename T> PIChunkStream & add(int id, const T & data) {*this << ChunkConst<T>(id, data); return *this;}
//! \~english
//! Extract %PIByteArray from "data" and set it current stream.
//! If "read_all" then call \a readAll() after extract.
//! Returns if has data to read.
//! \~russian
//! Извлекает %PIByteArray из "data" и инициализирует им поток.
//! Если указан "read_all", то вызывает \a readAll() после инициализации.
//! Возвращает если ли данные для чтения.
bool extract(PIByteArray & data, bool read_all = false);
void setSource(const PIByteArray & data);
void setSource(PIByteArray * data);
//! \~english Returns internal buffer with written data
//! \~russian Возвращает внутренний буфер с записанными данными
PIByteArray data() const;
//! \~english Returns if there is end of stream
//! \~russian Возвращает достигнут ли конец потока
bool atEnd() const {return data_->size_s() <= 1;}
//! \~english Returns stream version
//! \~russian Возвращает версию потока
Version version() const {return (Version)version_;}
//! \~english Read one chunk from stream and returns its ID
//! \~russian Читает один чанк из потока и возвращает его ID
int read();
//! \~english Read all chunks from stream. This function just index input data
//! \~russian Читает все чанки из потока. Данный метод лишь индексирует данные
void readAll();
//! \~english Returns last readed chunk ID
//! \~russian Возвращает ID последнего прочитанного чанка
int getID() {return last_id;}
//! \~english Returns value of last readed chunk
//! \~russian Возвращает значение последнего прочитанного чанка
template <typename T>
T getData() const {T ret{}; PIByteArray s(last_data); s >> ret; return ret;}
//! \~english Place value of last readed chunk into \"v\"
//! \~russian Записывает значение последнего прочитанного чанка в \"v\"
template <typename T>
void get(T & v) const {v = getData<T>();}
//! \~english Place value of chunk with ID \"id\" into \"v\". You should call \a readAll() before using this function!
//! \~russian Записывает значение чанка с ID \"id\" в \"v\". Необходимо вызвать \a readAll() перед использованием этого метода!
template <typename T>
const PIChunkStream & get(int id, T & v) const {
CacheEntry pos = data_map.value(id);
if (pos.start < 0 || pos.length == 0) return *this;
PIByteArray ba(data_->data(pos.start), pos.length);
if (!ba.isEmpty())
ba >> v;
return *this;
}
//! \~english Replace value of chunk with ID \"id\" to \"v\". You should call \a readAll() before using this function!
//! \~russian Заменяет значение чанка с ID \"id\" на \"v\". Необходимо вызвать \a readAll() перед использованием этого метода!
template <typename T>
PIChunkStream & set(int id, const T & v) {
PIByteArray ba;
ba << v;
replaceChunk(id, ba);
return *this;
}
private:
void _init();
struct CacheEntry {
CacheEntry(int s = 0, int l = 0, int b = 0): start(s), length(l), size_bytes(b) {}
int start;
int length;
int size_bytes;
};
static uint readVInt(PIByteArray & s, uchar * bytes = 0);
static void writeVInt(PIByteArray & s, uint val);
static int peekVInt(Version version_, uchar * data_, int sz, uint & ret);
void replaceChunk(int id, const PIByteArray & v);
int last_id;
uchar version_;
mutable PIByteArray * data_, last_data, tmp_data;
PIMap<int, CacheEntry> data_map;
bool first_byte_taken;
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::Chunk<T> & c);
template <typename T> friend PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst<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;
}
template <typename T>
PIChunkStream & operator <<(PIChunkStream & s, const PIChunkStream::ChunkConst<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

View File

@@ -1,171 +0,0 @@
/*
PIP - Platform Independent Primitives
C-String 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 "piconstchars.h"
#include "pistring.h"
//! \~\class PIConstChars piconstchars.h
//! \~\details
//! \~english \section PIConstChars_sec0 Synopsis
//! \~russian \section PIConstChars_sec0 Краткий обзор
//! \~english
//! This is wrapper around \c const char * string. %PIConstChars doesn`t
//! copy string, just save pointer and size.
//!
//! Provides API similar to string, with information and compare methods.
//!
//! Used to more handly works with ordinary C-strings.
//!
//! \~russian
//! Это обертка вокруг \c const char * строки. %PIConstChars не скопирует
//! строку, а хранит только указатель и размер.
//!
//! Предоставляет API схожий с обычной строкой, с методами сравнения и информационными.
//!
//! Используется для более удобной работы с обычными C-строками.
//!
bool PIConstChars::contains(char c) const {
for (int i = 0; i < (int)len; ++i)
if (str[i] == c) return true;
return false;
}
bool PIConstChars::startsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == left(str.size());
}
bool PIConstChars::startsWith(const char c) const {
if (size() < 1) return false;
return str[0] == c;
}
bool PIConstChars::endsWith(const PIConstChars & str) const {
if (size() < str.size()) return false;
return str == right(str.size());
}
bool PIConstChars::endsWith(const char c) const {
if (size() < 1) return false;
return str[len - 1] == c;
}
PIConstChars PIConstChars::mid(const int start, const int len) const {
int s = start, l = len;
if (l == 0 || s >= (int)size() || isEmpty()) return PIConstChars("");
if (s < 0) {
l += s;
s = 0;
}
if (l < 0) {
return PIConstChars(str + s, (int)size() - s);
} else {
if (l > (int)size() - s)
l = (int)size() - s;
return PIConstChars(str + s, l);
}
return PIConstChars("");
}
PIConstChars PIConstChars::left(const int l) const {
if (l <= 0) return PIConstChars("");
return mid(0, l);
}
PIConstChars PIConstChars::right(const int l) const {
if (l <= 0) return PIConstChars("");
return mid((int)size() - l, l);
}
PIConstChars & PIConstChars::cutLeft(const int l) {
if (l <= 0) return *this;
if (l >= (int)size())
*this = PIConstChars("");
else {
str += l;
len -= l;
}
return *this;
}
PIConstChars & PIConstChars::cutRight(const int l) {
if (l <= 0) return *this;
if (l >= (int)size())
*this = PIConstChars("");
else {
len -= l;
}
return *this;
}
PIConstChars PIConstChars::takeLeft(const int len) {
PIConstChars ret(left(len));
cutLeft(len);
return ret;
}
PIConstChars PIConstChars::takeRight(const int len) {
PIConstChars ret(right(len));
cutRight(len);
return ret;
}
PIConstChars & PIConstChars::trim() {
if (isEmpty()) return *this;
int st = -1, fn = 0;
for (int i = 0; i < (int)len; ++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) {
*this = PIConstChars("");
return *this;
}
for (int i = (int)len - 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;
}
}
if (fn < (int)len - 1) cutRight((int)len - fn - 1);
if (st > 0) cutLeft(st);
return *this;
}
PIString PIConstChars::toString() const {
if (isEmpty()) return PIString();
return PIString::fromAscii(str, len);
}

View File

@@ -1,266 +0,0 @@
/*! \file piconstchars.h
* \ingroup Core
* \brief
* \~english C-String class
* \~russian Класс C-строки
*/
/*
PIP - Platform Independent Primitives
C-String 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 PICONSTCHARS_H
#define PICONSTCHARS_H
#include "picout.h"
//! \ingroup Core
//! \~\brief
//! \~english C-String class.
//! \~russian Класс C-строки.
class PIP_EXPORT PIConstChars {
public:
//! \~english Contructs an null string.
//! \~russian Создает нулевую строку.
PIConstChars() {}
//! \~english Contructs string from C-string "string".
//! \~russian Создает строку из C-строки "string".
PIConstChars(const char * string) {
str = string;
len = strlen(string);
}
//! \~english Contructs string from "size" characters of buffer "data".
//! \~russian Создает строку из "size" символов массива "data".
PIConstChars(const char * data, size_t size) {
str = data;
len = size;
}
//! \~english Contructs a copy of string.
//! \~russian Создает копию строки.
PIConstChars(const PIConstChars & o) {
str = o.str;
len = o.len;
}
//! \~english Read-only access to character by `index`.
//! \~russian Доступ на чтение к символу по индексу `index`.
inline char operator [](size_t index) const {return str[index];}
//! \~english Read-only access to character by `index`.
//! \~russian Доступ на чтение к символу по индексу `index`.
inline char at(size_t index) const {return str[index];}
//! \~english Returns \c char * string pointer.
//! \~russian Возвращает \c char * указатель строки.
inline const char * data() const {return str;}
//! \~english Returns \c true if string doesn`t have any data.
//! \~russian Возвращает \c true если строка не имеет данных.
inline bool isNull() const {return !str;}
//! \~english Returns \c true if string is empty, i.e. length = 0, or null.
//! \~russian Возвращает \c true если строка пустая, т.е. длина = 0, или нулевая.
inline bool isEmpty() const {return len == 0;}
//! \~english Returns \c true if string is not empty, i.e. length > 0.
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
inline bool isNotEmpty() const {return len > 0;}
//! \~english Returns \c true if string contains character "c".
//! \~russian Возвращает \c true если строка содержит символ "c".
bool contains(char c) const;
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline size_t length() const {return len;}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline size_t size() const {return len;}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
inline ssize_t size_s() const {return len;}
//! \~english Returns if string starts with "str".
//! \~russian Возвращает начинается ли строка со "str".
bool startsWith(const PIConstChars & str) const;
//! \~english Returns if string starts with "c".
//! \~russian Возвращает начинается ли строка с "c".
bool startsWith(const char c) const;
//! \~english Returns if string ends with "str".
//! \~russian Возвращает оканчивается ли строка на "str".
bool endsWith(const PIConstChars & str) const;
//! \~english Returns if string ends with "c".
//! \~russian Возвращает оканчивается ли строка "c".
bool endsWith(const char c) const;
//! \~english Returns part of string from character at index "start" and maximum length "len".
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len".
//! \~\sa \a left(), \a right()
PIConstChars mid(const int start, const int len = -1) const;
//! \~english Returns part of string from start and maximum length "len".
//! \~russian Возвращает подстроку от начала и максимальной длиной "len".
//! \~\sa \a mid(), \a right()
PIConstChars left(const int len) const;
//! \~english Returns part of string at end and maximum length "len".
//! \~russian Возвращает подстроку максимальной длиной "len" и до конца.
//! \~\sa \a mid(), \a left()
PIConstChars right(const int len) const;
//! \~english Remove part of string from start and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку.
//! \~\sa \a cutRight()
PIConstChars & cutLeft(const int len);
//! \~english Remove part of string at end and maximum length "len" and return this string.
//! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку.
//! \~\sa \a cutLeft()
PIConstChars & cutRight(const int len);
//! \~english Take a part from the begin of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки от начала максимальной длины "len" и возвращает её.
//! \~\sa \a takeRight()
PIConstChars takeLeft(const int len);
//! \~english Take a part from the end of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки с конца максимальной длины "len" и возвращает её.
//! \~\sa \a takeLeft()
PIConstChars takeRight(const int len);
//! \~english Remove spaces at the start and at the end of string and return this string.
//! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку.
//! \~\sa \a trimmed()
PIConstChars & trim();
//! \~english Returns copy of this string without spaces at the start and at the end.
//! \~russian Возвращает копию этой строки без пробельных символов с начала и конца.
//! \~\sa \a trim()
PIConstChars trimmed() const {return PIConstChars(*this).trim();}
//! \~english Returns as PIString.
//! \~russian Возвращает как PIString.
PIString toString() const;
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIConstChars & operator =(const PIConstChars & s) {
if (this == &s) return *this;
len = s.len;
str = s.str;
return *this;
}
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
inline PIConstChars & operator =(PIConstChars && s) {
swap(s);
return *this;
}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
inline PIConstChars & operator =(const char * s) {
str = s;
len = strlen(s);
return *this;
}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator ==(const PIConstChars & s) const {
if (isNull() && s.isNull()) return true;
if (isNull() xor s.isNull()) return false;
if (size() != s.size()) return false;
return strcmp(str, s.str) == 0;
}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator !=(const PIConstChars & s) const {return !(*this == s);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator <(const PIConstChars & s) const {
if ( isNull() && s.isNull()) return false;
if ( isNull() && !s.isNull()) return true ;
if (!isNull() && s.isNull()) return false;
if (size() == s.size())
return strcmp(str, s.str) < 0;
return size() < s.size();
}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
inline bool operator >(const PIConstChars & s) const {
if ( isNull() && s.isNull()) return false;
if ( isNull() && !s.isNull()) return false;
if (!isNull() && s.isNull()) return true ;
if (size() == s.size())
return strcmp(str, s.str) > 0;
return size() > s.size();
}
//! \~english Returns hash of string content.
//! \~russian Возвращает хэш содержимого строки.
inline uint hash() const {
if (isEmpty()) return 0;
return piHashData((const uchar *)str, len);
}
inline void swap(PIConstChars& v) {
piSwap<const char *>(str, v.str);
piSwap<size_t>(len, v.len);
}
private:
const char * str = nullptr;
size_t len = 0;
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout.
//! \~russian Оператор вывода в \a PICout.
inline PICout operator <<(PICout s, const PIConstChars & v) {
s.space();
if (v.isNull())
s.write("(null)");
else {
s.quote();
s.write(v.data(), v.size());
s.quote();
}
return s;
}
template<> inline uint piHash(const PIConstChars & s) {return s.hash();}
#endif // PICONSTCHARS_H

View File

@@ -1,350 +0,0 @@
/*
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 "pidatetime.h"
#include <ctime>
#ifdef ARDUINO
# include <Arduino.h>
#endif
#ifdef MAC_OS
//# include <mach/mach_traps.h>
//# include <mach/mach.h>
# include <mach/clock.h>
//# include <crt_externs.h>
#endif
#ifdef MICRO_PIP
# include <sys/time.h>
#endif
//! \addtogroup Core
//! \{
//!
//! \~\class PITime pidatetime.h
//!
//! \~\class PIDate pidatetime.h
//!
//! \~\class PIDateTime pidatetime.h
//!
//! \}
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;
}
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;
}
PICout operator <<(PICout s, const PITime & v) {
s.space();
s.saveAndSetControls(0);
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.restoreControls();
return s;
}
PICout operator <<(PICout s, const PIDate & v) {
s.space();
s.saveAndSetControls(0);
s << "PIDate(" << v.day << "-";
s << PIString::fromNumber(v.month).expandLeftTo(2, '0') << "-";
s << v.year << ")";
s.restoreControls();
return s;
}
PICout operator <<(PICout s, const PIDateTime & v) {
s.space();
s.saveAndSetControls(0);
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.restoreControls();
return s;
}

View File

@@ -1,320 +0,0 @@
/*! \file pidatetime.h
* \ingroup Core
* \~\brief
* \~english Time and date structs
* \~russian Типы времени и даты
*/
/*
PIP - Platform Independent Primitives
Time and date 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 PIDATETIME_H
#define PIDATETIME_H
#include "pisystemtime.h"
//! \ingroup Core
//! \~\brief
//! \~english Calendar time.
//! \~russian Календарное время.
class PIP_EXPORT PITime {
public:
//! \~english Construct %PITime from hours, minutes, seconds and milliseconds
//! \~russian Создает %PITime из часов, минут, секунд и миллисекунд
PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;}
//! \~english Returns string representation
//! \~russian Возвращает строковое представление
PIString toString(const PIString & format = "h:mm:ss") const;
//! \~english Returns time as %PISystemTime
//! \~russian Возвращает время как %PISystemTime
PISystemTime toSystemTime() const;
//! \~english Returns current time
//! \~russian Возвращает текущее время
static PITime current();
//! \~english Construct %PITime from %PISystemTime
//! \~russian Создает %PITime из %PISystemTime
static PITime fromSystemTime(const PISystemTime & st);
//! \~english Hour, 0-23
//! \~russian Час, 0-23
int hours;
//! \~english Minutes, 0-59
//! \~russian Минуты, 0-59
int minutes;
//! \~english Seconds, 0-59
//! \~russian Секунды, 0-59
int seconds;
//! \~english Milliseconds, 0-999
//! \~russian Миллисекунды, 0-999
int milliseconds;
};
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);}
//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout
PIP_EXPORT PICout operator <<(PICout s, const PITime & v);
//! \ingroup Core
//! \~\brief
//! \~english Calendar date.
//! \~russian Календарная дата.
class PIP_EXPORT PIDate {
public:
//! \~english Construct %PIDate from year, month and day
//! \~russian Создает %PIDate из года, месяца и дня
PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;}
//! \~english Returns string representation
//! \~russian Возвращает строковое представление
PIString toString(const PIString & format = "d.MM.yyyy") const;
//! \~english Returns current date
//! \~russian Возвращает текущую дату
static PIDate current();
//! \~english Year
//! \~russian Год
int year;
//! \~english Month, 1-12
//! \~russian Месяц, 1-12
int month;
//! \~english Day, 1-31
//! \~russian День, 1-31
int day;
};
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);}
//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout
PIP_EXPORT PICout operator <<(PICout s, const PIDate & v);
//! \ingroup Core
//! \~\brief
//! \~english Calendar date and time.
//! \~russian Календарное дата и время.
class PIP_EXPORT PIDateTime {
public:
//! \~english Construct null %PIDateTime
//! \~russian Создает нулевой %PIDateTime
PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;}
//! \~english Construct %PIDateTime from %PITime and null %PIDate
//! \~russian Создает %PIDateTime из %PITime и нулевого %PIDate
PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;}
//! \~english Construct %PIDateTime from %PIDate and null %PITime
//! \~russian Создает %PIDateTime из %PIDate и нулевого %PITime
PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;}
//! \~english Construct %PIDateTime from %PIDate and %PITime
//! \~russian Создает %PIDateTime из %PIDate и %PITime
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;}
//! \~english Returns normalized %PIDateTime
//! \~russian Возвращает нормализованный %PIDateTime
PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());}
//! \~english Normalize all fields
//! \~russian Нормализует все поля
void normalize() {*this = normalized();}
//! \~english Returns string representation
//! \~russian Возвращает строковое представление
PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const;
//! \~english Returns seconds since 1 Jan 1970
//! \~russian Возвращает секунды от 1 Янв 1970
time_t toSecondSinceEpoch() const;
//! \~english Returns time as %PISystemTime
//! \~russian Возвращает время как %PISystemTime
PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);}
//! \~english Returns date part
//! \~russian Возвращает дату
PIDate date() const {return PIDate(year, month, day);}
//! \~english Returns time part
//! \~russian Возвращает время
PITime time() const {return PITime(hours, minutes, seconds, milliseconds);}
//! \~english Set date part
//! \~russian Устанавливает дату
void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;}
//! \~english Set time part
//! \~russian Устанавливает время
void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;}
//! \~english Sum operator
//! \~russian Оператор сложения
void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();}
//! \~english Subtract operator
//! \~russian Оператор вычитания
void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();}
//! \~english Construct %PIDateTime from seconds since 1 Jan 1970
//! \~russian Создает %PIDateTime из секунд от 1 Янв 1970
static PIDateTime fromSecondSinceEpoch(const time_t sec);
//! \~english Construct %PIDateTime from %PISystemTime
//! \~russian Создает %PIDateTime из %PISystemTime
static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;}
//! \~english Returns current date and time
//! \~russian Возвращает текущую дату и время
static PIDateTime current();
//! \~english Year
//! \~russian Год
int year;
//! \~english Month, 1-12
//! \~russian Месяц, 1-12
int month;
//! \~english Day, 1-31
//! \~russian День, 1-31
int day;
//! \~english Hour, 0-23
//! \~russian Час, 0-23
int hours;
//! \~english Minutes, 0-59
//! \~russian Минуты, 0-59
int minutes;
//! \~english Seconds, 0-59
//! \~russian Секунды, 0-59
int seconds;
//! \~english Milliseconds, 0-999
//! \~russian Миллисекунды, 0-999
int milliseconds;
};
//! \~english Sum operator
//! \~russian Оператор сложения
inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();}
//! \~english Subtract operator
//! \~russian Оператор вычитания
inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();}
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1);
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);}
//! \~english Compare operator
//! \~russian Оператор сравнения
inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);}
//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout
PIP_EXPORT PICout operator <<(PICout s, const PIDateTime & v);
#endif // PIDATETIME_H

View File

@@ -1,247 +0,0 @@
/*! \file piflags.h
* \ingroup Core
* \~\brief
* \~english General flags class
* \~russian Универсальные флаги
*/
/*
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"
//! \addtogroup Core
//! \{
//! \~\class PIFlags piflags.h
//! \~\brief
//! \~english Container for bit flags
//! \~russian Контейнер для битовых полей (флагов)
//!
//! \~\details
//! \~english
//! %PIFlags is wrapper around \c "int". One can use it as native \c "int".
//! There are manybit-wise operators,
//! native conversion to "int" and function
//! to test flag. \n Example:
//!
//! \~russian
//! %PIFlags по сути обертка вокруг \c "int". Можно использовать его как обычный \c "int".
//! Имеет много битовых операторов,
//! неявное преобразование в "int" и методы для проверки
//! флагов. \n Пример:
//!
//! \~\snippet piincludes.cpp flags
//!
//! \}
template<typename Enum>
class PIFlags {
public:
//! \~english Constructor with flags = 0
//! \~russian Создает нулевые флаги
PIFlags(): flags(0) {;}
//! \~english Constructor with flags = Enum "e"
//! \~russian Создает флаги со значением = Enum "e"
PIFlags(Enum e): flags(e) {;}
//! \~english Constructor with flags = int "i"
//! \~russian Создает флаги со значением = int "i"
PIFlags(const int i): flags(i) {;}
//! \~english Set flags on positions "f" to value "on"
//! \~russian Устанавливает флаги по позициям "f" в "on"
PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
//! \~english Set flag "e" to value "on"
//! \~russian Устанавливает флаг "e" в "on"
PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
//! \~english Set flag "i" to value "on"
//! \~russian Устанавливает флаг "i" в "on"
PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
//! \~english Assign operator
//! \~russian Оператор присваивания
void operator =(const Enum & e) {flags = e;}
//! \~english Assign operator
//! \~russian Оператор присваивания
void operator =(const int & i) {flags = i;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const PIFlags & f) {return flags == f.flags;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const Enum & e) {return flags == e;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const int i) {return flags == i;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const PIFlags & f) {return flags != f.flags;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const Enum & e) {return flags != e;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const int i) {return flags != i;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >(const PIFlags & f) {return flags > f.flags;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >(const Enum & e) {return flags > e;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >(const int i) {return flags > i;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <(const PIFlags & f) {return flags < f.flags;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <(const Enum & e) {return flags < e;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <(const int i) {return flags < i;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >=(const PIFlags & f) {return flags >= f.flags;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >=(const Enum & e) {return flags >= e;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >=(const int i) {return flags >= i;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <=(const PIFlags & f) {return flags <= f.flags;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <=(const Enum & e) {return flags <= e;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <=(const int i) {return flags <= i;}
//! \~english Bit-wise AND operator
//! \~russian Оператор побитового И
void operator &=(const PIFlags & f) {flags &= f.flags;}
//! \~english Bit-wise AND operator
//! \~russian Оператор побитового И
void operator &=(const Enum & e) {flags &= e;}
//! \~english Bit-wise AND operator
//! \~russian Оператор побитового И
void operator &=(const int i) {flags &= i;}
//! \~english Bit-wise OR operator
//! \~russian Оператор побитового ИЛИ
void operator |=(const PIFlags & f) {flags |= f.flags;}
//! \~english Bit-wise OR operator
//! \~russian Оператор побитового ИЛИ
void operator |=(const Enum & e) {flags |= e;}
//! \~english Bit-wise OR operator
//! \~russian Оператор побитового ИЛИ
void operator |=(const int i) {flags |= i;}
//! \~english Bit-wise XOR operator
//! \~russian Оператор побитового исключающего ИЛИ
void operator ^=(const PIFlags & f) {flags ^= f.flags;}
//! \~english Bit-wise XOR operator
//! \~russian Оператор побитового исключающего ИЛИ
void operator ^=(const Enum & e) {flags ^= e;}
//! \~english Bit-wise XOR operator
//! \~russian Оператор побитового исключающего ИЛИ
void operator ^=(const int i) {flags ^= i;}
//! \~english Bit-wise AND operator
//! \~russian Оператор побитового И
PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
//! \~english Bit-wise AND operator
//! \~russian Оператор побитового И
PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
//! \~english Bit-wise AND operator
//! \~russian Оператор побитового И
PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
//! \~english Bit-wise OR operator
//! \~russian Оператор побитового ИЛИ
PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
//! \~english Bit-wise OR operator
//! \~russian Оператор побитового ИЛИ
PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
//! \~english Bit-wise OR operator
//! \~russian Оператор побитового ИЛИ
PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
//! \~english Bit-wise XOR operator
//! \~russian Оператор побитового исключающего ИЛИ
PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
//! \~english Bit-wise XOR operator
//! \~russian Оператор побитового исключающего ИЛИ
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
//! \~english Bit-wise XOR operator
//! \~russian Оператор побитового исключающего ИЛИ
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
//! \~english Test flag operator
//! \~russian Оператор проверки флага
bool operator [](Enum e) const {return (flags & e) == e;}
//! \~english Implicity conversion to \c int
//! \~russian Оператор неявного преобразования в \c int
operator int() const {return flags;}
private:
int flags;
};
#endif // PIFLAGS_H

View File

@@ -1,567 +0,0 @@
/*
PIP - Platform Independent Primitives
JSON 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 "pijson.h"
//! \~\class PIJSON pijson.h
//! \~\details
//! \~english \section PIJSON_sec0 Synopsis
//! \~russian \section PIJSON_sec0 Краткий обзор
//! \~english
//!
//! \~russian
//! JSON - это древовидная структура, каждый элемент которой может быть либо
//! парой имя:значение, либо массивом, либо объектом, т.е. именованным
//! списком элементов. Корневой элемент JSON может быть либо массивом,
//! либо объектом.
//!
//! Массивы заключены в квадратные скобки [], их элементы не имеют имени
//! и разделяются запятыми.
//!
//! Объекты заключены в фигурные скобки {}, их элементы имеют имя
//! и разделяются запятыми.
//!
//!
//! \~english \section PIJSON_sec1 PIJSON tree
//! \~russian \section PIJSON_sec1 Дерево PIJSON
//! \~english
//!
//! \~russian
//! %PIJSON представляет собой элемент дерева JSON. Каждый элемент имеет тип (\a type())
//! и может иметь имя (\a name()). Если это конечный элемент,то он будет иметь значение,
//! доступное через \a value(), \a toBool(), \a toInt(), \a toDouble() или \a toString().
//!
//! Если элемент преставляет собой массив, то его размер доступен через \a size(),
//! а элементы массива через целочисленный оператор []. Весь массив доступен через \a array().
//!
//! Если элемент преставляет собой объект, то его размер доступен через \a size(),
//! а элементы объекта через строковый оператор []. Проверить наличие элемента по имени можно
//! с помощью \a contains(). Весь объект доступен через \a object().
//!
//! Создать дерево из текстового представления JSON можно с помощью \a fromJSON(), а
//! преобразовать в текст с помощью \a toJSON().
//!
//!
//! \~english \section PIJSON_sec2 PIJSON creation
//! \~russian \section PIJSON_sec2 Создание PIJSON
//! \~english
//!
//! \~russian
//! Для создания нового дерева необходимо лишь создать пустой корневой PIJSON и заполнить его
//! значениями, массивами или объектами с помощью целочисленного или строкового оператора [].
//! В зависимости от типа аргумента элемент преобразуется либо в массив, либо в объект.
//!
//! При приравнивании PIJSON к какому-либо значению, его тип автоматически установится в нужный.
//! При обращении на запись целочисленным оператором [] размер массива автоматически увеличится
//! при необходимости.
//!
//!
//! \~english \section PIJSON_sec3 Mask/unmask
//! \~russian \section PIJSON_sec3 Маскирование/размаскирование
//! \~english
//!
//! \~russian
//! Строковые значения в стандарте JSON могут иметь в явном виде только печатные символы,
//! спецсимволы и юникод должны быть преобразованы маскированием, т.е., например, вместо
//! символа новой строки должно быть "\n", а не-ASCII символы должны быть в виде "\uXXXX".
//!
//! Оператор вывода в PICout не выполняет маскирования строк.
//!
//! Методы \a toJSON() и \a fromJSON() маскируют и размаскируют строковые поля.
//!
//!
//! \~english \section PIJSON_sec4 Examples
//! \~russian \section PIJSON_sec4 Примеры
//! \~english
//!
//! \~russian
//! Чтение:
//! \~\code
//! PIJSON json = PIJSON::fromJSON(
//! "["
//! " true,"
//! " 10,"
//! " {"
//! " \"num\":1.E-2,"
//! " \"str\":\"text\""
//! " },"
//! "]");
//! piCout << json;
//! piCout << json.toJSON();
//! \endcode
//! \~\code
//! [
//! true,
//! 10,
//! {
//! "num": 1.e-2,
//! "str": "text"
//! }
//! ]
//!
//! [true,10,{"num":1.e-2,"str":"text"}]
//! \endcode
//! Разбор:
//! \~\code
//! PIJSON json = PIJSON::fromJSON(
//! "["
//! " true,"
//! " 10,"
//! " {"
//! " \"num\":1.E-2,"
//! " \"str\":\"text\""
//! " },"
//! "]");
//! piCout << "top-level:";
//! for (const auto & i: json.array())
//! piCout << i.value();
//! piCout << "[2][\"str\"]:";
//! piCout << json[2]["str"].toString();
//! \endcode
//! \~\code
//! top-level:
//! PIVariant(Bool, 1)
//! PIVariant(String, 10)
//! PIVariant(Invalid)
//! [2]["str"]:
//! text
//! \endcode
//!
//! Создание:\n
//! Простой массив
//! \~\code
//! PIJSON json;
//! json[0] = -1;
//! json[1] = "text";
//! json[3] = false;
//! piCout << json.toJSON();
//! \endcode
//! \~\code
//! [-1,"text","",false]
//! \endcode
//!
//! Массив объектов
//! \~\code
//! struct {
//! PIString name;
//! PIString surname;
//! PIString email;
//! } persons[] = {
//! {"Ivan", "Ivanov", "ivan@pip.ru"},
//! {"Igor", "Igorevich", "igor@pip.ru"},
//! {"Andrey", "Andreevich", "andrey@pip.ru"}
//! };
//! PIJSON obj;
//! PIJSON json;
//! int index = 0;
//! for (const auto & p: persons) {
//! obj["index"] = index++;
//! obj["name"] = p.name;
//! obj["surname"] = p.surname;
//! obj["email"] = p.email;
//! json << obj;
//! }
//! piCout << json;
//! \endcode
//! \~\code
//! [
//! {
//! "name": "Ivan",
//! "email": "ivan@pip.ru",
//! "index": 0,
//! "surname": "Ivanov"
//! },
//! {
//! "name": "Igor",
//! "email": "igor@pip.ru",
//! "index": 1,
//! "surname": "Igorevich"
//! },
//! {
//! "name": "Andrey",
//! "email": "andrey@pip.ru",
//! "index": 2,
//! "surname": "Andreevich"
//! }
//! ]
//! \endcode
//!
PIJSON PIJSON::newObject() {
PIJSON ret;
ret.c_type = Object;
return ret;
}
PIJSON PIJSON::newArray() {
PIJSON ret;
ret.c_type = Array;
return ret;
}
PIJSON PIJSON::newString(const PIString & v) {
PIJSON ret;
ret = v;
return ret;
}
const PIVector<PIJSON> & PIJSON::array() const {
if (!isArray()) {
return nullEntry().c_array;
} else {
return c_array;
}
}
const PIMap<PIString, PIJSON> & PIJSON::object() const {
if (!isObject()) {
return nullEntry().c_object;
} else {
return c_object;
}
}
//! \details
//! \~english
//! If "v" type is boolean set type to \a PIJSON::Boolean.\n
//! If "v" type is any numeric set type to \a PIJSON::Number.\n
//! If "v" type is string set type to \a PIJSON::String.\n
//! In case of any other type set element type to \a PIJSON::Invalid.
//! \~russian
//! Если тип "v" логический, то устанавливает тип в \a PIJSON::Boolean.\n
//! Если тип "v" любой численный, то устанавливает тип в \a PIJSON::Number.\n
//! Если тип "v" строковый, то устанавливает тип в \a PIJSON::String.\n
//! Если тип "v" любой другой, то устанавливает тип в \a PIJSON::Invalid.
void PIJSON::setValue(const PIVariant & v) {
c_value = v;
switch (v.type()) {
case PIVariant::pivBool: c_type = Boolean; break;
case PIVariant::pivUChar:
case PIVariant::pivShort:
case PIVariant::pivUShort:
case PIVariant::pivInt:
case PIVariant::pivUInt:
case PIVariant::pivLLong:
case PIVariant::pivULLong:
case PIVariant::pivFloat:
case PIVariant::pivDouble:
case PIVariant::pivLDouble: c_type = Number; break;
case PIVariant::pivString: c_type = String; break;
default: c_type = Invalid; break;
}
}
void PIJSON::clear() {
c_type = Invalid;
c_value = PIVariant();
c_name.clear();
c_object.clear();
c_array.clear();
}
int PIJSON::size() const {
if (isArray()) return c_array.size_s();
if (isObject()) return c_object.size_s();
return 0;
}
bool PIJSON::contains(const PIString & key) const {
if (!isObject()) return false;
return c_object.contains(key);
}
void PIJSON::resize(int new_size) {
c_type = Array;
c_array.resize(new_size, newString());
}
const PIJSON & PIJSON::operator[](int index) const {
if (!isArray()) return nullEntry();
return c_array[index];
}
PIJSON & PIJSON::operator[](int index) {
c_type = Array;
if (index >= c_array.size_s()) {
c_array.resize(index + 1, newString());
}
PIJSON & ret(c_array[index]);
return ret;
}
PIJSON & PIJSON::operator<<(const PIJSON & element) {
c_type = Array;
c_array << element;
return *this;
}
PIJSON & PIJSON::operator=(const PIJSON & v) {
c_type = v.c_type;
c_value = v.c_value;
c_object = v.c_object;
c_array = v.c_array;
return *this;
}
PIJSON PIJSON::operator[](const PIString & key) const {
if (!isObject()) return nullEntry();
if (!c_object.contains(key)) return nullEntry();
return c_object.value(key);
}
PIJSON & PIJSON::operator[](const PIString & key) {
c_type = Object;
PIJSON & ret(c_object[key]);
ret.c_name = key;
return ret;
}
PIString PIJSON::toJSON(PrintType print_type) const {
PIString ret;
print(ret, *this, "", print_type == Tree, true);
return ret;
}
PIJSON PIJSON::fromJSON(PIString str) {
return parseValue(str);
}
PIJSON & PIJSON::nullEntry() {
static PIJSON ret;
ret.clear();
return ret;
}
PIString PIJSON::parseName(PIString & s) {
//piCout << "\n\n\n parseName" << s;
PIString ret;
ret = s.takeRange('"', '"');
s.trim();
if (s.isEmpty()) return PIString();
if (s[0] != ':') return PIString();
s.remove(0).trim();
return PIJSON::stringUnmask(ret);
}
PIJSON PIJSON::parseValue(PIString & s) {
PIJSON ret;
//piCout << "\n\n\n parseValue" << s;
s.trim();
if (s.isEmpty()) return ret;
if (s[0] == '{') {
ret = parseObject(s.takeRange('{', '}'));
} else if (s[0] == '[') {
ret = parseArray(s.takeRange('[', ']'));
} else {
s.trim();
if (s.startsWith('"')) {
ret.c_type = PIJSON::String;
ret.c_value = PIJSON::stringUnmask(s.takeRange('"', '"'));
} else {
PIString value;
int ind = s.find(',');
if (ind >= 0) {
value = s.takeLeft(ind).trim().toLowerCase();
} else {
value = s;
s.clear();
}
//piCout << "\n\n\n parseValue value = \"" << value << "\"";
if (value == "null") {
ret.c_type = PIJSON::Null;
} else if (value == "true") {
ret.c_type = PIJSON::Boolean;
ret.c_value = true;
} else if (value == "false") {
ret.c_type = PIJSON::Boolean;
ret.c_value = false;
} else {
ret.c_type = PIJSON::Number;
ret.c_value = value;
}
}
}
return ret;
}
PIJSON PIJSON::parseObject(PIString s) {
//piCout << "\n\n\n parseObject" << s;
PIJSON ret;
ret.c_type = PIJSON::Object;
while (s.isNotEmpty()) {
PIString name = PIJSON::stringUnmask(parseName(s));
PIJSON value = parseValue(s);
auto & child(ret.c_object[name]);
child = value;
child.c_name = name;
s.trim();
if (s.isEmpty()) break;
if (s[0] != ',') break;
s.remove(0);
}
return ret;
}
PIJSON PIJSON::parseArray(PIString s) {
//piCout << "\n\n\n parseArray" << s;
PIJSON ret;
ret.c_type = PIJSON::Array;
while (s.isNotEmpty()) {
PIJSON value = parseValue(s);
ret.c_array << value;
s.trim();
if (s.isEmpty()) break;
if (s[0] != ',') break;
s.remove(0);
}
return ret;
}
PIString PIJSON::stringMask(const PIString & s) {
PIString ret;
for (auto c: s) {
if (!c.isAscii()) {
ret += "\\u" + PIString::fromNumber(c.unicode16Code(), 16).expandLeftTo(4, '0');
} else {
char ca = c.toAscii();
switch (ca) {
case '"' : ret += "\\\""; break;
case '\\': ret += "\\\\"; break;
case '/' : ret += "\\/" ; break;
case '\b': ret += "\\b" ; break;
case '\f': ret += "\\f" ; break;
case '\n': ret += "\\n" ; break;
case '\r': ret += "\\r" ; break;
case '\t': ret += "\\t" ; break;
default: ret += ca;
}
}
}
return ret;
}
PIString PIJSON::stringUnmask(const PIString & s) {
PIString ret;
for (int i = 0; i < s.size_s(); ++i) {
char ca = s[i].toAscii();
if (ca == '\\') {
if (i == s.size_s() - 1) continue;
++i;
char na = s[i].toAscii();
switch (na) {
case '"' : ret += '\"'; break;
case '\\': ret += '\\'; break;
case '/' : ret += '/' ; break;
case 'b' : ret += '\b'; break;
case 'f' : ret += '\f'; break;
case 'n' : ret += '\n'; break;
case 'r' : ret += '\r'; break;
case 't' : ret += '\t'; break;
case 'u' :
ret += PIChar(s.mid(i + 1, 4).toUShort(16));
i += 4;
break;
default: break;
}
} else {
ret += s[i];
}
}
return ret;
}
void PIJSON::print(PIString & s, const PIJSON & v, PIString tab, bool spaces, bool transform, bool comma) {
if (spaces) s += tab;
/*
switch (v.c_type) {
case JSONEntry::Invalid: s << "(Invalid)"; break;
case JSONEntry::Null: s << "(Null)"; break;
case JSONEntry::Boolean: s << "(Boolean)"; break;
case JSONEntry::Number: s << "(Number)"; break;
case JSONEntry::String: s << "(String)"; break;
case JSONEntry::Object: s << "(Object)"; break;
case JSONEntry::Array: s << "(Array)"; break;
}
*/
if (v.name().isNotEmpty()) {
s += '"' + (transform ? stringMask(v.name()) : v.name()) + "\":";
if (spaces) s += ' ';
}
switch (v.c_type) {
case PIJSON::Invalid: break;
case PIJSON::Null: s += "null"; break;
case PIJSON::Boolean: s += PIString::fromBool(v.c_value.toBool()); break;
case PIJSON::Number: s += v.c_value.toString(); break;
case PIJSON::String: s += '"' + (transform ? stringMask(v.c_value.toString()) : v.c_value.toString()) + '"'; break;
case PIJSON::Object:
s += "{";
if (spaces) s += '\n';
{
PIString ntab = tab + " ";
auto it = v.c_object.makeIterator();
int cnt = 0;
while (it.next()) {
print(s, it.value(), ntab, spaces, transform, ++cnt < v.c_object.size_s());
}
}
if (spaces) s += tab;
s += "}";
break;
case PIJSON::Array:
s += "[";
if (spaces) s += '\n';
{
PIString ntab = tab + " ";
for (int i = 0; i < v.c_array.size_s(); ++i) {
print(s, v.c_array[i], ntab, spaces, transform, i < v.c_array.size_s() - 1);
}
}
if (spaces) s += tab;
s += "]";
break;
}
if (comma) s += ',';
if (spaces) s += "\n";
}

View File

@@ -1,215 +0,0 @@
/*! \file pijson.h
* \ingroup Core
* \brief
* \~english JSON class
* \~russian Класс JSON
*/
/*
PIP - Platform Independent Primitives
JSON 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 PIJSON_H
#define PIJSON_H
#include "pivariant.h"
//! \ingroup Core
//! \~\brief
//! \~english JSON class.
//! \~russian Класс JSON.
class PIP_EXPORT PIJSON {
friend PICout operator <<(PICout s, const PIJSON & v);
public:
//! \~english
//! Type of JSON tree element
//! \~russian
//! Тип элемента дерева JSON
enum Type {
Invalid /*! \~english Invalid type \~russian Недействительный тип */,
Null /*! \~english Without value, null \~russian Без значения, null */,
Boolean /*! \~english Boolean, /b true or /b false \~russian Логическое, /b true или /b false */,
Number /*! \~english Integer or floating-point number \~russian Целое либо число с плавающей точкой */,
String /*! \~english Text \~russian Текст */,
Object /*! \~english Object, {} \~russian Объект, {} */,
Array /*! \~english Array, [] \~russian Массив, [] */
};
//! \~english
//! Generate JSON variant
//! \~russian
//! Вариант генерации JSON
enum PrintType {
Compact /*! \~english Without spaces, minimum size \~russian Без пробелов, минимальный размер */,
Tree /*! \~english With spaces and new-lines, human-readable \~russian С пробелами и новыми строками, читаемый человеком */
};
//! \~english Contructs invalid %PIJSON.
//! \~russian Создает недействительный %PIJSON.
PIJSON() {}
PIJSON(const PIJSON & o) = default;
//! \~english Returns name of element, or empty string if it doesn`t have name.
//! \~russian Возвращает имя элемента, либо пустую строку, если имени нет.
const PIString & name() const {return c_name;}
//! \~english Returns elements array of this element, or empty array if element is not \a PIJSON::Array.
//! \~russian Возвращает массив элементов этого элемента, либо пустой массив, если тип элемента не \a PIJSON::Array.
const PIVector<PIJSON> & array() const;
//! \~english Returns elements map of this element, or empty map if element is not \a PIJSON::Object.
//! \~russian Возвращает словарь элементов этого элемента, либо пустой словарь, если тип элемента не \a PIJSON::Object.
const PIMap<PIString, PIJSON> & object() const;
//! \~english Returns element value.
//! \~russian Возвращает значение элемента.
const PIVariant & value() const {return c_value;}
//! \~english Returns element value as bool.
//! \~russian Возвращает значение элемента как логическое.
bool toBool() const {return c_value.toBool();}
//! \~english Returns element value as integer number.
//! \~russian Возвращает значение элемента как целое число.
int toInt() const {return c_value.toInt();}
//! \~english Returns element value as floating-point number.
//! \~russian Возвращает значение элемента как число с плавающей точкой.
double toDouble() const {return c_value.toDouble();}
//! \~english Returns element value as string, valid for all types.
//! \~russian Возвращает значение элемента как строка, действительно для всех типов.
PIString toString() const {return c_value.toString();}
//! \~english Returns element type.
//! \~russian Возвращает тип элемента.
Type type() const {return c_type;}
//! \~english Returns if element is valid.
//! \~russian Возвращает действителен ли элемент.
bool isValid() const {return c_type != Invalid;}
//! \~english Returns if element is \a PIJSON::Object.
//! \~russian Возвращает является ли элемент \a PIJSON::Object.
bool isObject() const {return c_type == Object;}
//! \~english Returns if element is \a PIJSON::Array.
//! \~russian Возвращает является ли элемент \a PIJSON::Array.
bool isArray() const {return c_type == Array;}
//! \~english Set value and type of element from "v".
//! \~russian Устанавливает значение и тип элемента из "v".
void setValue(const PIVariant & v);
//! \~english Clear element and set it to \a PIJSON::Invalid.
//! \~russian Очищает элемент и устанавливает его в \a PIJSON::Invalid.
void clear();
//! \~english Returns size of elements array if type is \a PIJSON::Array, size of elements map if type is \a PIJSON::Object, otherwise returns 0.
//! \~russian Возвращает размер массива элементов если тип \a PIJSON::Array, размер словаря элементов если тип \a PIJSON::Object, иначе возвращает 0.
int size() const;
//! \~english Returns if elements map contains key "key" if type is \a PIJSON::Object, otherwise returns \b false.
//! \~russian Возвращает содержит ли словарь элементов ключ "key" если тип \a PIJSON::Object, иначе возвращает \b false.
bool contains(const PIString & key) const;
//! \~english Set element type to \a PIJSON::Array and resize elements array to "new_size".
//! \~russian Устанавливает тип элемента в \a PIJSON::Array и изменяет размер массива элементов на "new_size".
void resize(int new_size);
//! \~english Synonim of \a setValue().
//! \~russian Аналог \a setValue().
PIJSON & operator=(const PIVariant & v) {setValue(v); return *this;}
PIJSON & operator=(const PIJSON & v);
//! \~english Returns element from array with index "index" if type is \a PIJSON::Array, otherwise returns invalid %PIJSON.
//! \~russian Возвращает элемент из массива по индексу "index" если тип \a PIJSON::Array, иначе возвращает недействительный %PIJSON.
const PIJSON & operator[](int index) const;
//! \~english Set element type to \a PIJSON::Array, resize if necessary and returns element from array with index "index".
//! \~russian Устанавливает тип элемента в \a PIJSON::Array, изменяет размер массива при неоходимости и возвращает элемент из массива по индексу "index".
PIJSON & operator[](int index);
//! \~english Set element type to \a PIJSON::Array and add element to the end of array.
//! \~russian Устанавливает тип элемента в \a PIJSON::Array и добавляет элемент в массив.
PIJSON & operator <<(const PIJSON & element);
//! \~english Returns element from map with key "key" if type is \a PIJSON::Object, otherwise returns invalid %PIJSON.
//! \~russian Возвращает элемент из словаря по ключу "key" если тип \a PIJSON::Object, иначе возвращает недействительный %PIJSON.
PIJSON operator[](const PIString & key) const;
//! \~english Set element type to \a PIJSON::Object and returns element from map with key "key". If element with this key doesn`t exists, it will be created.
//! \~russian Устанавливает тип элемента в \a PIJSON::Object и возвращает элемент из словаря по ключу "key". Если элемента с таким ключом не существует, он будет создан.
PIJSON & operator[](const PIString & key);
PIJSON operator[](const char * key) const {return (*this)[PIString::fromUTF8(key)];}
PIJSON & operator[](const char * key) {return (*this)[PIString::fromUTF8(key)];}
//! \~english Returns text representation of JSON tree.
//! \~russian Возвращает текстовое представление дерева JSON.
PIString toJSON(PrintType print_type = Compact) const;
//! \~english Parse text representation of JSON "str" and returns it root element.
//! \~russian Разбирает текстовое представление JSON "str" и возвращает его корневой элемент.
static PIJSON fromJSON(PIString str);
static PIJSON newObject();
static PIJSON newArray();
static PIJSON newString(const PIString & v = PIString());
private:
static PIJSON & nullEntry();
static PIString parseName(PIString & s);
static PIJSON parseValue(PIString & s);
static PIJSON parseObject(PIString s);
static PIJSON parseArray(PIString s);
static PIString stringMask(const PIString & s);
static PIString stringUnmask(const PIString & s);
static void print(PIString & s, const PIJSON & v, PIString tab, bool spaces, bool transform = false, bool comma = false);
PIString c_name;
PIVariant c_value;
PIVector<PIJSON> c_array;
PIMap<PIString, PIJSON> c_object;
Type c_type = Invalid;
};
//! \relatesalso PICout
//! \~english Output operator to \a PICout.
//! \~russian Оператор вывода в \a PICout.
inline PICout operator <<(PICout s, const PIJSON & v) {
s.space();
s.saveAndSetControls(0);
PIString str;
PIJSON::print(str, v, "", true);
s << str;
s.restoreControls();
return s;
}
#endif // PICONSTCHARS_H

View File

@@ -1,201 +0,0 @@
/*
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"
//! \~\class PIPropertyStorage pipropertystorage.h
//! \~\details
//! \~english \section PIPropertyStorage_sec0 Synopsis
//! \~russian \section PIPropertyStorage_sec0 Краткий обзор
//!
//! \~english
//! Key-value storage, based on PIVector with PIPropertyStorage::Property elements. Each element in vector
//! contains unique name. You can access property by name with \a propertyValueByName() or \a propertyByName().
//! You can add or replace property by \a addProperty(const Property&) or \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
//!
//! \~russian
//! Хранилище свойств ключ-значние, основанный на PIVector с элементами PIPropertyStorage::Property.
//! Каждый элемент имеет уникальное имя. Доступ к свойствам через \a propertyValueByName() или \a propertyByName().
//! Добавление и перезапись свойств через \a addProperty(const Property&) или \a addProperty(const PIString&, const PIVariant&, const PIString&, int).
//!
//! \~english Example:
//! \~russian Пример:
//! \~\code{.cpp}
//! \endcode
//!
//! \~\class PIPropertyStorage::Property pipropertystorage.h
//! \~\details
//!
bool PIPropertyStorage::isPropertyExists(const PIString & _name) const {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == _name)
return true;
return false;
}
//! \details
//! \~english Returns "true" if new property added, else if update existing property return "false"
//! \~russian Возвращает истину если новое свойство добавлено, в случае обновления "ложь"
bool PIPropertyStorage::addProperty(const PIPropertyStorage::Property & p) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == p.name) {
props[i] = p;
return false;
}
props << p;
return true;
}
bool PIPropertyStorage::addProperty(PIPropertyStorage::Property && p) {
for (uint i = 0; i < props.size(); ++i)
if (props[i].name == p.name) {
props[i] = std::move(p);
return false;
}
props << std::move(p);
return true;
}
//! \details
//! \~english Returns "true" if new property added, else if update existing property return "false"
//! \~russian Возвращает истину если новое свойство добавлено, в случае обновления "ложь"
bool PIPropertyStorage::addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment, int _flags) {
return addProperty(Property(_name, _comment, _def_value, _flags));
}
bool PIPropertyStorage::removeProperty(const PIString & _name) {
for (uint i = 0; i < props.size(); ++i) {
if (props[i].name == _name) {
props.remove(i);
return true;
}
}
return false;
}
//! \details
//! \~english "flag" checked as bitfield
//! \~russian "flag" проверяется как битовое поле
int PIPropertyStorage::removePropertiesByFlag(int flag) {
int ret = 0;
for (int i = 0; i < props.size_s(); ++i) {
if ((props[i].flags & flag) == flag) {
props.remove(i);
--i;
ret++;
}
}
return ret;
}
//! \details
//! \~english "flag_ignore" is bitfield to ignore property in merge process
//! \~russian "flag_ignore" - битовое поле для исключения свойств из процесса слияния
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();
}
bool 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 true;
}
}
return false;
}
bool 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 true;
}
}
return false;
}
bool 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 true;
}
}
return false;
}
PIPropertyStorage::Property & PIPropertyStorage::operator[](const PIString & name) {
piForeach (Property & p, props)
if (p.name == name)
return p;
addProperty(name, "");
return props.back();
}
const PIPropertyStorage::Property PIPropertyStorage::operator[](const PIString & name) const {
piForeachC (Property & p, props)
if (p.name == name)
return p;
return Property();
}

View File

@@ -1,296 +0,0 @@
/*! \file pipropertystorage.h
* \ingroup Core
* \~\brief
* \~english Properties array
* \~russian Массив свойств
*/
/*
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"
//! \ingroup Core
//! \~\brief
//! \~english This class provides key-value properties storage.
//! \~russian Этот класс предоставляет ключ-значение хранение свойств.
class PIP_EXPORT PIPropertyStorage {
public:
//! \~english Contructs an empty %PIPropertyStorage
//! \~russian Создает пустой %PIPropertyStorage
PIPropertyStorage() {}
//! \ingroup Core
//! \~\brief
//! \~english PIPropertyStorage element.
//! \~russian Элемент PIPropertyStorage.
struct PIP_EXPORT Property {
//! \~english Contructs %PIPropertyStorage::Property with name "n", comment "c", value "v" and flags "f"
//! \~russian Создает %PIPropertyStorage::Property с именем "n", комментарием "c", значением "v" и флагами "f"
Property(const PIString & n = PIString(), const PIString & c = PIString(), const PIVariant & v = PIVariant(), int f = 0): name(n), comment(c), value(v), flags(f) {}
//! \~english Contructs copy of another %PIPropertyStorage::Property "o"
//! \~russian Создает копию %PIPropertyStorage::Property "o"
Property(const Property & o): name(o.name), comment(o.comment), value(o.value), flags(o.flags) {}
Property(Property && o) {swap(o);}
//! \~english Assign operator
//! \~russian Оператор присваивания
Property & operator =(const Property & v) {
name = v.name;
comment = v.comment;
value = v.value;
flags = v.flags;
return *this;
}
Property & operator =(Property && v) {swap(v); return *this;}
//! \~english Returns value as boolean
//! \~russian Возвращает значение как логическое
bool toBool() const {return value.toBool();}
//! \~english Returns value as integer
//! \~russian Возвращает значение как целое
int toInt() const {return value.toInt();}
//! \~english Returns value as float
//! \~russian Возвращает значение как float
float toFloat() const {return value.toFloat();}
//! \~english Returns value as double
//! \~russian Возвращает значение как double
double toDouble() const {return value.toDouble();}
//! \~english Returns value as string
//! \~russian Возвращает значение как строку
PIString toString() const {return value.toString();}
void swap(Property & o) {
name.swap(o.name);
comment.swap(o.comment);
value.swap(o.value);
piSwap(flags, o.flags);
}
//! \~english Property name (uniqueue for %PIPropertyStorage)
//! \~russian Имя свойства (уникальное для %PIPropertyStorage)
PIString name;
//! \~english Optional description of property
//! \~russian Опциональный комментарий свойства
PIString comment;
//! \~english Property value
//! \~russian Значение свойства
PIVariant value;
//! \~english Abstract flags which may be used for user needs
//! \~russian Абстрактные флаги, могут быть использованы для своих нужд
int flags;
};
//! \~english Contructs %PIPropertyStorage with "pl" properties
//! \~russian Создает %PIPropertyStorage со свойствами "pl"
PIPropertyStorage(const PIVector<Property> & pl) {props = pl;}
//! \~english Contructs %PIPropertyStorage from another "o"
//! \~russian Создает %PIPropertyStorage из другого "o"
PIPropertyStorage(PIVector<Property> && o): props(std::move(o)) {}
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();}
//! \~english Returns properties count
//! \~russian Возвращает количество свойств
int length() const {return props.length();}
//! \~english Returns properties count
//! \~russian Возвращает количество свойств
int size() const {return props.size();}
//! \~english Returns if no properties
//! \~russian Возвращает нет ли свойств
bool isEmpty() const {return props.isEmpty();}
//! \~english Returns if properties
//! \~russian Возвращает есть ли свойства
bool isNotEmpty() const {return props.isNotEmpty();}
//! \~english Returns first property
//! \~russian Возвращает первое свойство
Property & front() {return props.front();}
//! \~english Returns first property as const
//! \~russian Возвращает первое свойство как константу
const Property & front() const {return props.front();}
//! \~english Returns last property
//! \~russian Возвращает последнее свойство
Property & back() {return props.back();}
//! \~english Returns last property as const
//! \~russian Возвращает последнее свойство как константу
const Property & back() const {return props.back();}
//! \~english Remove property at index "i"
//! \~russian Удаляет свойство по индексу "i"
void removeAt(int i) {props.remove(i);}
//! \~english Remove all properties
//! \~russian Удаляет все свойства
void clear() {props.clear();}
//! \~english Returns copy of this %PIPropertyStorage
//! \~russian Возвращает копию этого %PIPropertyStorage
PIPropertyStorage copy() const {return PIPropertyStorage(*this);}
//! \~english Returns properties count
//! \~russian Возвращает количество свойств
int propertiesCount() const {return props.size();}
//! \~english Returns properties as PIVector
//! \~russian Возвращает свойства как PIVector
PIVector<Property> & properties() {return props;}
//! \~english Returns properties as const PIVector
//! \~russian Возвращает свойства как константный PIVector
const PIVector<Property> & properties() const {return props;}
const PIPropertyStorage & propertyStorage() const {return *this;}
//! \~english Returns if properties with name "name" exists
//! \~russian Возвращает присутствует ли свойство с именем "name"
bool isPropertyExists(const PIString & name) const;
//! \~english Remove all properties
//! \~russian Удаляет все свойства
void clearProperties() {props.clear();}
//! \~english Add property if name isn't present in storage, otherwrise update existing property with same name
//! \~russian Добавляет новое свойство, если его имени не было в контейнере, иначе обновляет существующее свойство с этим именем
bool addProperty(const Property & p);
bool addProperty(Property && p);
//! \~english Add property if name isn't present in storage, otherwrise update existing property with same name
//! \~russian Добавляет новое свойство, если его имени не было в контейнере, иначе обновляет существующее свойство с этим именем
bool addProperty(const PIString & _name, const PIVariant & _def_value, const PIString & _comment = PIString(), int _flags = 0);
//! \~english Remove property with name "name", returns if property removed
//! \~russian Удаляет свойство с именем "name", возвращает было ли оно удалено
bool removeProperty(const PIString & name);
//! \~english Remove all properties with flag "flag" set, returns removed properties count
//! \~russian Удаляет все свойства с флагом "flag", возвращает количество удаленных свойств
int removePropertiesByFlag(int flag);
//! \~english Merge other "properties" into this
//! \~russian Объединяет "properties" с текущим контейнером
void updateProperties(const PIVector<Property> & properties, int flag_ignore = 0);
//! \~english Returns property with name "name" or default-constructed %PIPropertyStorage::Property
//! \~russian Возвращает свойство с именем "name" или пустое %PIPropertyStorage::Property
Property propertyByName(const PIString & name) const;
//! \~english Returns property value with name "name" or invalid %PIVariant
//! \~russian Возвращает значение свойства с именем "name" или недействительный %PIVariant
PIVariant propertyValueByName(const PIString & name) const;
//! \~english Set value of property with name "name" to "value", returns if property exists
//! \~russian Устанавливает значение "value" свойству с именем "name", возвращает существует ли такое свойство
bool setPropertyValue(const PIString & name, const PIVariant & value);
//! \~english Set comment of property with name "name" to "comment", returns if property exists
//! \~russian Устанавливает комментарий "comment" свойству с именем "name", возвращает существует ли такое свойство
bool setPropertyComment(const PIString & name, const PIString & comment);
//! \~english Set flags of property with name "name" to "flags", returns if property exists
//! \~russian Устанавливает флаги "flags" свойству с именем "name", возвращает существует ли такое свойство
bool setPropertyFlags(const PIString & name, int flags);
//! \~english Add property "p"
//! \~russian Добавляет свойство "p"
PIPropertyStorage & operator <<(const PIPropertyStorage::Property & p) {props << p; return *this;}
//! \~english Add properties "p"
//! \~russian Добавляет свойства "p"
PIPropertyStorage & operator <<(const PIVector<Property> & p) {props << p; return *this;}
//! \~english Add properties "p"
//! \~russian Добавляет свойства "p"
PIPropertyStorage & operator <<(const PIPropertyStorage & p) {props << p.props; return *this;}
//! \~english Returns property with index "i"
//! \~russian Возвращает свойство по индексу "i"
Property & operator[](int i) {return props[i];}
//! \~english Returns property with index "i" as const
//! \~russian Возвращает свойство по индексу "i" как константу
const Property & operator[](int i) const {return props[i];}
//! \~english Returns property with name "name"
//! \~russian Возвращает свойство с именем "name"
Property & operator[](const PIString & name);
//! \~english Returns property with name "name" as const
//! \~russian Возвращает свойство с именем "name" как константу
const Property operator[](const PIString & name) const;
protected:
PIVector<Property> props;
};
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIPropertyStorage::Property) {s << v.name << v.value << v.comment << v.flags; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIPropertyStorage::Property) {s >> v.name >> v.value >> v.comment >> v.flags; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIPropertyStorage) {s << v.properties(); return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIPropertyStorage) {s >> v.properties(); return s;}
#endif // PIPROPERTYSTORAGE_H

View File

@@ -1,1799 +0,0 @@
/*
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"
#include "pimathbase.h"
#ifdef PIP_ICU
# define U_NOEXCEPT
# include "unicode/ucnv.h"
#endif
#ifdef WINDOWS
# include <stringapiset.h>
#endif
#include <string>
#include <locale>
#include <codecvt>
//! \class PIString pistring.h
//! \~\details
//! \~english \section PIString_sec0 Synopsis
//! \~russian \section PIString_sec0 Краткий обзор
//!
//! \~english
//! String is a sequence of \a PIChar. Real memory size of string is symbols count * 2.
//! String can be constucted from many types of data and can be converted
//! to many types. There are many operators and handly functions to use
//! string as you wish.
//!
//! \~russian
//! Строка состоит из последовательности \a PIChar. Реальный объем памяти,
//! занимаемый строкой, равен количеству символов * 2. Строка может быть
//! создана из множества типов и преобразована в несколько типов.
//! Имеет множество методов для манипуляций.
//!
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 char PIString::fromBaseN[] = {(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char) 0, (char) 1, (char) 2, (char) 3, (char) 4, (char) 5, (char) 6, (char) 7, (char) 8, (char) 9, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, (char)21, (char)22, (char)23, (char)24,
(char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, (char)32, (char)33, (char)34, (char)35, (char)36, (char)37, (char)38, (char)39, (char)-1,
(char)-1, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, (char)21, (char)22, (char)23, (char)24,
(char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, (char)32, (char)33, (char)34, (char)35, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1};
const float PIString::ElideLeft = 0.f;
const float PIString::ElideCenter = .5f;
const float PIString::ElideRight = 1.f;
template <typename T>
T toDecimal(const PIString & s) {
int part = 0, exp = 0;
bool negative = false, negative_exp = false, err = false, has_digit = false;
T ret = 0., frac = 0., frac_delim = 1.;
for (const PIChar pc: s) {
char c = pc.toAscii();
switch (part) {
case 0: // sign
if (pc.isSpace()) continue;
if (c >= '0' && c <= '9') {
has_digit = true;
ret = c - '0';
part = 1;
continue;
}
if (c == '+') {
part = 1;
continue;
}
if (c == '-') {
negative = true;
part = 1;
continue;
}
if (c == '.' || c == ',') {
part = 2;
continue;
}
err = true;
break;
case 1: // integer
if (c >= '0' && c <= '9') {
has_digit = true;
ret = ret * 10 + (c - '0');
continue;
}
if (c == '.' || c == ',') {
part = 2;
continue;
}
if ((c == 'e' || c == 'E') && has_digit) {
part = 3;
continue;
}
err = true;
break;
case 2: // fractional
if (c >= '0' && c <= '9') {
has_digit = true;
frac = frac * 10 + (c - '0');
frac_delim *= 10.;
continue;
}
if ((c == 'e' || c == 'E') && has_digit) {
part = 3;
continue;
}
err = true;
break;
case 3: // exponent with sign
if (c == '+') {
part = 4;
continue;
}
if (c == '-') {
negative_exp = true;
part = 4;
continue;
}
case 4: // exponent
if (c >= '0' && c <= '9') {
exp = (exp * 10) + (c - '0');
continue;
}
err = true;
break;
}
if (err) break;
}
frac /= frac_delim;
ret += frac;
if (negative && has_digit) ret = -ret;
if (exp > 0) {
if (negative_exp) ret /= pow10((T)exp);
else ret *= pow10((T)exp);
}
return ret;
}
#define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); snprintf(ch, 256, f, v); return PIStringAscii(ch);
PIString PIString::itos(const int num) {pisprintf("%d", num);}
PIString PIString::ltos(const long num) {pisprintf("%ld", num);}
PIString PIString::lltos(const llong num) {pisprintf("%lld", num);}
PIString PIString::uitos(const uint num) {pisprintf("%u", num);}
PIString PIString::ultos(const ulong num) {pisprintf("%lu", num);}
PIString PIString::ulltos(const ullong num) {pisprintf("%llu", num);}
PIString PIString::dtos(const double num, char format, int precision) {
char f[8] = "%.";
int wr = snprintf(&(f[2]), 4, "%d", precision);
if (wr > 4) wr = 4;
f[2 + wr] = format;
f[3 + wr] = 0;
pisprintf(f, num);
}
#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) {
static const PIString s_0x = PIStringAscii("0x");
PIString v = value.trimmed();
if (base < 0) {
int ind = v.find(s_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;
char 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) {
// piCout << "appendFromChars";
if (s == 0) return;
int old_sz = size_s();
if (s == -1) s = strlen(c);
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(codepage, &e);
if (cc) {
d.enlarge(s);
e = (UErrorCode)0;
int sz = ucnv_toUChars(cc, (UChar*)(d.data(old_sz)), s, c, s, &e);
d.resize(old_sz+sz);
ucnv_close(cc);
return;
}
#else
# ifdef WINDOWS
int sz = MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, 0, 0);
if (sz <= 0) return;
d.enlarge(sz);
MultiByteToWideChar((uint)(uintptr_t)codepage, MB_ERR_INVALID_CHARS, c, s, (LPWSTR)d.data(old_sz), sz);
# else
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> ucs2conv;
std::u16string ucs2 = ucs2conv.from_bytes(c, c+s);
d.enlarge(ucs2.size());
ucs2.copy((char16_t *)d.data(old_sz), ucs2.size());
# endif
#endif
}
PIString PIString::fromConsole(const PIByteArray & ba) {
PIString ret;
if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __sysoemname__);
return ret;
}
PIString PIString::fromConsole(const char * s) {
PIString ret;
if (!s) return ret;
if (s[0] != '\0') ret.appendFromChars(s, -1, __sysoemname__);
return ret;
}
PIString PIString::fromSystem(const PIByteArray & ba) {
PIString ret;
if (ba.isNotEmpty()) ret.appendFromChars((const char*)ba.data(), ba.size(), __syslocname__);
return ret;
}
PIString PIString::fromSystem(const char * s) {
PIString ret;
if (!s) return ret;
if (s[0] != '\0') ret.appendFromChars(s, -1, __syslocname__);
return ret;
}
PIString PIString::fromUTF8(const char * s) {
PIString ret;
if (!s) return ret;
if (s[0] != '\0') {
if ((uchar)s[0] == 0xEF && (uchar)s[1] == 0xBB && (uchar)s[2] == 0xBF) {
s += 3;
if (s[0] == '\0') return ret;
}
ret.appendFromChars(s, -1, __utf8name__);
}
return ret;
}
PIString PIString::fromUTF8(const PIByteArray & ba) {
PIString ret;
if (ba.isNotEmpty()) {
const char * data = (const char*)ba.data();
int size = ba.size();
if (ba.size() >= 3) {
if (ba[0] == 0xEF && ba[1] == 0xBB && ba[2] == 0xBF) {
data += 3;
size -= 3;
if (size == 0) return ret;
}
}
ret.appendFromChars(data, size, __utf8name__);
}
return ret;
}
PIString PIString::fromAscii(const char * s) {
return fromAscii(s, strlen(s));
}
PIString PIString::fromAscii(const char * s, int len) {
PIString ret;
ret.resize(len);
for (int l = 0; l < len; ++l) {
ret[l] = s[l];
}
return ret;
}
PIString PIString::fromCodepage(const char * s, const char * c) {
PIString ret;
if (s[0] > '\0') ret.appendFromChars(s, -1
#ifdef PIP_ICU
, c
#else
# ifdef WINDOWS
, __utf8name__
# endif
#endif
);
return ret;
}
//! \~\details
//! \~english
//! Example:
//! \~russian
//! Пример:
//! \~\code
//! piCout << PIString::readableSize(512); // 512 B
//! piCout << PIString::readableSize(5120); // 5.0 kB
//! piCout << PIString::readableSize(512000); // 500.0 kB
//! piCout << PIString::readableSize(5120000); // 4.8 MB
//! piCout << PIString::readableSize(512000000); // 488.2 MB
//! piCout << PIString::readableSize(51200000000); // 47.6 GB
//! \endcode
PIString PIString::readableSize(llong bytes) {
PIString s;
s.setReadableSize(bytes);
return s;
}
void PIString::buildData(const char * cp) const {
deleteData();
#ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
UConverter * cc = ucnv_open(cp, &e);
if (cc) {
const size_t len = MB_CUR_MAX*size()+1;
data_ = (char *)malloc(len);
int sz = ucnv_fromUChars(cc, data_, len, (const UChar*)(d.data()), d.size_s(), &e);
ucnv_close(cc);
data_[sz] = '\0';
return;
}
#else
# ifdef WINDOWS
int sz = WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), 0, 0, NULL, NULL);
if (sz <= 0) {
data_ = (char *)malloc(1);
data_[0] = '\0';
return;
}
data_ = (char *)malloc(sz+1);
WideCharToMultiByte((uint)(uintptr_t)cp, 0, (LPCWCH)d.data(), d.size_s(), (LPSTR)data_, sz, NULL, NULL);
data_[sz] = '\0';
return;
# else
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> ucs2conv;
std::string u8str = ucs2conv.to_bytes((char16_t*)d.data(), (char16_t*)d.data() + d.size());
data_ = (char *)malloc(u8str.size()+1);
strcpy(data_, u8str.c_str());
# endif
#endif
}
void PIString::deleteData() const {
if (!data_) return;
free(data_);
data_ = nullptr;
}
void PIString::trimsubstr(int &st, int &fn) const {
for (int i = 0; i < d.size_s(); ++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 = d.size_s() - 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;
}
}
}
uint PIString::hash() const {
return piHashData((const uchar*)d.data(), d.size() * sizeof(PIChar));
}
PIByteArray PIString::toSystem() const {
if (isEmpty()) return PIByteArray();
buildData(__syslocname__);
return PIByteArray(data_, strlen(data_));
}
PIByteArray PIString::toUTF8() const {
if (isEmpty()) return PIByteArray();
buildData(__utf8name__);
return PIByteArray(data_, strlen(data_));
}
PIByteArray PIString::toCharset(const char * c) const {
if (isEmpty()) return PIByteArray();
buildData(
#ifdef PIP_ICU
c
#else
# ifdef WINDOWS
__utf8name__
# endif
#endif
);
return PIByteArray(data_, strlen(data_));
}
PIString PIString::simplified() const {
PIString ret(*this);
for (int i = 0; i < ret.size_s(); ++i)
if (!ret[i].isAscii())
ret[i] = '?';
return ret;
}
PIString & PIString::operator +=(const char * str) {
if (!str) return *this;
appendFromChars(str, -1, __syslocname__);
return *this;
}
PIString & PIString::operator +=(const PIByteArray & ba) {
appendFromChars((const char * )ba.data(), ba.size_s(), __utf8name__);
return *this;
}
PIString::~PIString() {
deleteData();
}
PIString & PIString::operator +=(const wchar_t * str) {
if (!str) return *this;
int i = -1;
while (str[++i]) {
d.push_back(PIChar(str[i]));
}
return *this;
}
PIString & PIString::operator +=(const PIString & str) {
d.append(str.d);
return *this;
}
PIString & PIString::operator +=(const PIConstChars & str) {
if (!str.isEmpty()) {
size_t os = d.size();
d.enlarge(str.size());
for (size_t l = 0; l < d.size(); ++l) {
d[os + l] = str[l];
}
}
return *this;
}
bool PIString::operator ==(const PIString & str) const {
return d == str.d;
}
bool PIString::operator !=(const PIString & str) const {
return d != str.d;
}
bool PIString::operator <(const PIString & str) const {
size_t l = str.size();
if (size() < l) return true;
if (size() > l) return false;
for (size_t i = 0; i < l; ++i) {
if (at(i) == str.at(i)) continue;
if (at(i) < str.at(i)) return true;
else return false;
}
return false;
}
bool PIString::operator >(const PIString & str) const {
size_t l = str.size();
if (size() < l) return false;
if (size() > l) return true;
for (size_t i = 0; i < l; ++i) {
if (at(i) == str.at(i)) continue;
if (at(i) < str.at(i)) return false;
else return true;
}
return false;
}
//! \~\details
//! \~english
//! If "len" < 0 then returns substring from symbol "start" to end.
//! "start" should be >= 0.
//! \~russian
//! Если "len" < 0 тогда возвращается подстрока от символа "start" и до конца.
//! "start" должен быть >= 0.
//! \~\code
//! PIString s("0123456789");
//! piCout << s.mid(0, -1); // s = "0123456789"
//! piCout << s.mid(0, 2); // s = "01"
//! piCout << s.mid(3); // s = "3456789"
//! piCout << s.mid(3, 4); // s = "3456"
//! piCout << s.mid(7, 1); // s = "7"
//! piCout << s.mid(7, 4); // s = "789"
//! piCout << s.mid(-1); // s = ""
//! \endcode
//! \~\sa \a left(), \a right()
PIString PIString::mid(int start, int len) const {
if (len == 0 || start >= length()) return PIString();
if (start < 0) {
return PIString();
}
if (len < 0) {
return PIString(d.data(start), size_s() - start);
} else {
if (len > length() - start) len = length() - start;
return PIString(d.data(start), len);
}
return PIString();
}
//! \~\details
//! \~english
//! If "len" < 0 then remove substring from symbol "start" to end.
//! "start" should be >= 0.
//! \~russian
//! Если "len" < 0 тогда удаляется подстрока от символа "start" и до конца.
//! "start" должен быть >= 0.
//! \~\code
//! PIString s("0123456789");
//! s.cutMid(1, 3);
//! piCout << s; // s = "0456789"
//! s.cutMid(0, 2);
//! piCout << s; // s = "56789"
//! s.cutMid(3, -1);
//! piCout << s; // s = "567"
//! s.cutMid(-1, -1);
//! piCout << s; // s = "567"
//! \endcode
//! \~\sa \a cutLeft(), \a cutRight()
PIString & PIString::cutMid(int start, int len) {
if (len == 0) return *this;
if (start < 0) {
return *this;
}
if (len < 0) {
d.remove(start, size() - start);
} else {
if (len > length() - start) len = length() - start;
d.remove(start, len);
}
return *this;
}
//! \~\details
//! \~english Remove spaces, tabulations, line feeds and null symbols:
//! \~russian Удаляет пробелы, табуляцию, переводы строк и нулевые символы:
//! \~ ' ', '\\n', '\\r', '\\t', '\\0'
//! \~\code
//! PIString s(" \t string \n");
//! s.trim();
//! piCout << s; // s = "string"
//! \endcode
//! \~\sa \a trimmed()
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);
}
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! s.replace(2, 3, "_cut_");
//! piCout << s; // s = "01_cut_56789"
//! s.replace(0, 1, "one_");
//! piCout << s; // s = "one_1_cut_56789"
//! \endcode
//! \~\sa \a replaced(), \a replaceAll()
PIString & PIString::replace(int from, int count, const PIString & with) {
count = piMini(count, length() - from);
if (count == with.size_s()) {
memcpy(d.data(from), with.d.data(), count * sizeof(PIChar));
} else {
d.remove(from, count);
d.insert(from, with.d);
}
return *this;
}
//! \~\details
//! \~english If "ok" is not null, it set to "true" if something was replaced
//! \~russian Если "ok" не null, то устанавливает в "true" если замена произведена
//! \~\code
//! PIString s("pip string");
//! bool ok;
//! s.replace("string", "conf", &ok);
//! piCout << s << ok; // s = "pip conf", true
//! s.replace("PIP", "PlInPr", &ok);
//! piCout << s << ok; // s = "pip conf", false
//! \endcode
//! \~\sa \a replaced(), \a replaceAll()
PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) {
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;
}
//! \~\details
//! \~\code
//! PIString s("substrings");
//! s.replaceAll("s", "_");
//! piCout << s; // s = "_ub_tring_"
//! \endcode
//! \~\sa \a replace(), \a replaced(), \a replacedAll()
PIString & PIString::replaceAll(const PIString & what, const PIString & with) {
if (what.isEmpty() || what == with) return *this;
if (with.isEmpty()) {
removeAll(what);
} else {
int l = what.length(), dl = with.length() - what.length();
for (int i = 0; i < length() - l + 1; ++i) {
bool match = true;
for (int j = 0; j < l; ++j) {
if (at(j + i) != what[j]) {
match = false;
break;
}
}
if (!match) continue;
if (dl > 0) d.insert(i, PIDeque<PIChar>((size_t)dl));
if (dl < 0) d.remove(i, -dl);
memcpy(d.data(i), with.d.data(), with.size() * sizeof(PIChar));
}
}
return *this;
}
//! \~\details
//! \~\code
//! PIString s("substrings");
//! s.replaceAll("s", '_');
//! piCout << s; // s = "_ub_tring_"
//! \endcode
//! \~\sa \a replace(), \a replaced(), \a replacedAll()
PIString & PIString::replaceAll(const PIString & what, const char with) {
if (what.isEmpty()) return *this;
int l = what.length(), dl = what.length() - 1;
for (int i = 0; i < length() - l + 1; ++i) {
bool match = true;
for (int j = 0; j < l; ++j) {
if (at(j + i) != what[j]) {
match = false;
break;
}
}
if (!match) continue;
if (dl > 0) d.remove(i, dl);
d[i] = PIChar(with);
}
return *this;
}
//! \~\details
//! \~\code
//! PIString s("substrings");
//! s.replaceAll('s', '_');
//! piCout << s; // s = "_ub_tring_"
//! \endcode
//! \~\sa \a replace(), \a replaced(), \a replacedAll()
PIString & PIString::replaceAll(const char what, const char with) {
int l = length();
for (int i = 0; i < l; ++i) {
if (at(i) == what) d[i] = with;
}
return *this;
}
PIString & PIString::removeAll(const PIString & str) {
if (str.isEmpty()) return *this;
int l = str.length();
for (int i = 0; i < length() - l + 1; ++i) {
bool match = true;
for (int j = 0; j < l; ++j) {
if (d.at(j + i) != str.at(j)) {
match = false;
break;
}
}
if (!match) continue;
d.remove(i, l);
i -= l;
}
return *this;
}
PIString & PIString::insert(int index, const PIString & str) {
d.insert(index, str.d);
return *this;
}
PIString & PIString::elide(int size, float pos) {
static const PIString s_dotdot = PIStringAscii("..");
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);
d.remove(ls, length() - ns);
d.insert(ls, s_dotdot.d);
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;
}
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.find('-'); // -1
//! piCout << s.find('3'); // 3
//! piCout << s.find('3', 4); // 9
//! piCout << s.find('3', 10); // -1
//! \endcode
//! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::find(const char c, const int start) const {
for (int i = start; i < length(); ++i) {
if (at(i) == c) return i;
}
return -1;
}
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.find("-"); // -1
//! piCout << s.find("34"); // 3
//! piCout << s.find("3", 4); // 9
//! piCout << s.find("3", 10); // -1
//! \endcode
//! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
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;
}
//! \~\details
//! \~\code
//! piCout << PIString("1.str").findAny(".,:"); // 1
//! piCout << PIString("1,str").findAny(".,:"); // 1
//! piCout << PIString("1:str").findAny(".,:"); // 1
//! \endcode
//! \~\sa \a find(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
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;
}
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.findLast('-'); // -1
//! piCout << s.findLast('3'); // 9
//! piCout << s.findLast('3', 4); // 9
//! piCout << s.findLast('3', 10); // -1
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int PIString::findLast(const char c, const int start) const {
for (int i = length() - 1; i >= start; --i) {
if (at(i) == c) return i;
}
return -1;
}
int PIString::findLast(PIChar c, const int start) const
{
for (int i = length() - 1; i >= start; --i) {
if (at(i) == c) return i;
}
return -1;
}
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.findLast("-"); // -1
//! piCout << s.findLast("34"); // 9
//! piCout << s.findLast("3", 4); // 9
//! piCout << s.findLast("3", 10); // -1
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
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;
}
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str,0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str:0").findAnyLast(".,:"); // 4
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findWord(), \a findCWord(), \a findRange()
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;
}
//! \~\details
//! \~\code
//! PIString s("this is <PIP>");
//! piCout << s.findWord("this"); // 0
//! piCout << s.findWord("is"); // 5
//! piCout << s.findWord("PIP", 4); // -1
//! piCout << s.findWord("<PIP>", 4); // 8
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findAnyLast(), \a findCWord(), \a findRange()
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 = at(f - 1);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
ok = false;
continue;
}
}
if (f + wl < tl) {
c = at(f + wl);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
ok = false;
continue;
}
}
if (ok) return f;
}
return -1;
}
//! \~\details
//! \~\code
//! PIString s("this::is <PIP>");
//! piCout << s.findCWord("this"); // 0
//! piCout << s.findCWord("is"); // 6
//! piCout << s.findCWord("PIP", 4); // 10
//! piCout << s.findCWord("<PIP>", 4); // 9
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findRange()
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 = at(f - 1);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {
ok = false;
continue;
}
}
if (f + wl < tl) {
c = at(f + wl);
if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {
ok = false;
continue;
}
}
if (ok) return f;
}
return -1;
}
//! \~\details
//! \~\code
//! PIString s(" {figures{inside}}");
//! int len = -1;
//! piCout << s.findRange('{', '}', '\\', 0, &len) << len << s.mid(2, len); // 2 15 figures{inside}
//! s = "\"text\\\"shielded\" next";
//! piCout << s.findRange('"', '"', '\\', 0, &len) << len << s.mid(1, len); // 1 14 text\"shielded
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord()
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::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());
}
//! \~\details
//! \~\code
//! piCout << PIString("true").toBool(); // true
//! piCout << PIString("Yes").toBool(); // true
//! piCout << PIString(" TRUE ").toBool(); // true
//! piCout << PIString(" 1 ").toBool(); // true
//! piCout << PIString("0").toBool(); // false
//! piCout << PIString("0.1").toBool(); // true
//! piCout << PIString("-1").toBool(); // false
//! piCout << PIString("").toBool(); // false
//! \endcode
bool PIString::toBool() const {
static const PIString s_true = PIStringAscii("true");
static const PIString s_yes = PIStringAscii("yes" );
static const PIString s_on = PIStringAscii("on" );
static const PIString s_ok = PIStringAscii("ok" );
PIString s(*this);
s = s.trimmed().toLowerCase();
if (s == s_true || s == s_yes || s == s_on || s == s_ok) return true;
if (toDouble() > 0.) return true;
return false;
}
//! \~\details
//! \~\code
//! PIString s("\t ! word");
//! piCout << s.takeSymbol(); // "!"
//! piCout << s.takeSymbol(); // "w"
//! piCout << s.takeSymbol(); // "o"
//! piCout << s; // "rd"
//! \endcode
//! \~\sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange()
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;
}
//! \~\details
//! \~\code
//! PIString s("some words\nnew line ");
//! piCout << s.takeWord(); // "some"
//! piCout << s.takeWord(); // "words"
//! piCout << s.takeWord(); // "new"
//! piCout << s; // " line "
//! \endcode
//! \~\sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange()
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;
}
//! \~\details
//! \~\code
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange()
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;
}
//! \~\details
//! \~\code
//! PIString s("some words\nnew line \n\nend");
//! piCout << s.takeLine(); // "some words"
//! piCout << s.takeLine(); // "new line "
//! piCout << s.takeLine(); // ""
//! piCout << s; // "end"
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange()
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;
}
//! \~\details
//! \~\code
//! PIString s(" 0xFF -99 1.2E+5f 1000L");
//! piCout << s.takeNumber(); // "0xFF"
//! piCout << s.takeNumber(); // "-99"
//! piCout << s.takeNumber(); // "1.2E+5f"
//! piCout << s.takeNumber(); // "1000L"
//! piCout << s; // ""
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange()
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') || c == '.') {
le = i;
if (ls < 0) ls = i;
if (c == '.') phase = 3;
else phase = 2;
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;
}
//! \~\details
//! \~english "shield" symbol prevent analysis of the next symbol
//! \~russian Символ "shield" экранирует следующий символ
//! \~\code
//! PIString s(" {figures{inside}}");
//! piCout << s.takeRange('{', '}'); // "figures{inside}"
//! piCout << s; // ""
//! s = "\"text\\\"shielded\" next";
//! piCout << s.takeRange('"', '"'); // "text\"shielded"
//! piCout << s; // " next"
//! \endcode
//! \~\sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber()
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;
}
//! \~\details
//! \~\code
//! PIString s("a(b(c)d)e");
//! piCout << s.inBrackets('(', ')'); // "b(c)d"
//! piCout << s; // s = "a(b(c)d)e"
//! \endcode
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();
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence of chars.
//! Length of this buffer is count of symbols + end byte '\0'.
//! Returned pointer is valid until next execution of this function.
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\code
//! piCout << PIString("0123456789").data(); // 0123456789
//! piCout << PIString("№1").data(); // №1
//! \endcode
//! \~\sa \a dataConsole(), \a dataUTF8()
const char * PIString::data() const {
if (isEmpty()) return "";
buildData(__syslocname__);
return data_;
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence of chars.
//! Length of this buffer is count of symbols + end byte '\0'.
//! Returned pointer is valid until next execution of this function.
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\sa \a data(), \a dataUTF8()
const char * PIString::dataConsole() const {
if (isEmpty()) return "";
buildData(__sysoemname__ );
return data_;
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence of chars.
//! Length of this buffer is count of symbols + end byte '\0'.
//! Returned pointer is valid until next execution of this function.
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\sa \a data(), \a dataConsole()
const char * PIString::dataUTF8() const {
if (isEmpty()) return "";
buildData(__utf8name__);
return data_;
}
//! \~\details
//! \~english
//! This function fill internal buffer by sequence of chars.
//! Length of this buffer is count of symbols + end byte '\0'.
//! Returned pointer is valid until next execution of this function.
//! \~russian
//! Этот метод заполняет внутренный байтовый буфер. Размер
//! этого буфера равен количеству символов строки + завершающий байт '\0'.
//! Возвращаемый указатель действителен до следующего вызова этого метода.
//! \~\sa \a dataConsole(), \a dataUTF8()
const char * PIString::dataAscii() const {
if (isEmpty()) return "";
deleteData();
data_ = (char*)malloc(size()+1);
for (int i = 0; i < size_s(); ++i) {
data_[i] = uchar(at(i).ch);
}
data_[size()] = '\0';
return data_;
}
PIString PIString::toUpperCase() const {
PIString str(*this);
int l = str.size();
for (int i = 0; i < l; ++i) {
str.d[i] = str.d[i].toUpper();
}
return str;
}
PIString PIString::toLowerCase() const {
PIString str(*this);
int l = str.size();
for (int i = 0; i < l; ++i) {
str.d[i] = str.d[i].toLower();
}
return str;
}
char PIString::toChar() const {
char v;
sscanf(dataAscii(), "%c", &v);
return v;
}
float PIString::toFloat() const {
return toDecimal<float>(*this);
}
double PIString::toDouble() const {
return toDecimal<double>(*this);
}
ldouble PIString::toLDouble() const {
return toDecimal<ldouble>(*this);
}
//! \~\details
//! \~english
//! Example:
//! \~russian
//! Пример:
//! \~\code
//! PIString s;
//! s.setReadableSize(512);
//! piCout << s; // 512 B
//! s.setReadableSize(5120);
//! piCout << s; // 5.0 kB
//! s.setReadableSize(512000);
//! piCout << s; // 500.0 kB
//! s.setReadableSize(5120000);
//! piCout << s; // 4.8 MB
//! s.setReadableSize(512000000);
//! piCout << s; // 488.2 MB
//! s.setReadableSize(51200000000);
//! piCout << s; // 47.6 GB
//! \endcode
PIString & PIString::setReadableSize(llong bytes) {
clear();
if (bytes < 1024) {
*this += (PIString::fromNumber(bytes) + PIStringAscii(" B"));
return *this;
}
double fres = bytes / 1024.;
llong res = bytes / 1024;
fres -= res;
if (res < 1024) {
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" kB"));
return *this;
}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" MB"));
return *this;
}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" GB"));
return *this;
}
fres = res / 1024.;
res /= 1024;
fres -= res;
if (res < 1024) {
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" TB"));
return *this;
}
fres = res / 1024.;
res /= 1024;
fres -= res;
*this += (PIString::fromNumber(res) + PIStringAscii(".") + PIString::fromNumber(llong(fres * 10)).left(1) + PIStringAscii(" PB"));
return *this;
}
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, PIStringAscii(".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(PIStringAscii("pre"))) {
s.cutLeft(3);
ret -= 1;
}
if (s.startsWith(PIStringAscii("rc"))) {
s.cutLeft(2);
ret += s.toInt();
}
if (s.startsWith(PIStringAscii("r"))) {
s.cutLeft(1);
ret += 10000 + s.toInt();
}
if (s == PIStringAscii("alpha")) ret -= 4;
if (s == PIStringAscii("beta" )) ret -= 2;
return ret;
}
//! \relatesalso PIString
//! \~\details
//! \~english
//! 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" < "rc[N]" < "" < "r[N]".
//! Example:
//! \~russian
//! Этот метод разбирает версии на числовые части и метку. Затем сравнивает
//! не более чем "components" частей. Если различий нет, то сравниваются
//! метки. Каждой метке соответствует своё значение так, что
//! "prealpha" < "alpha" < "prebeta" < "beta" < "rc[N]" < "" < "r[N]".
//! Пример:
//! \~\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_r2", "1.0.0", 3); // 0, =
//! piCout << versionCompare(".2-alpha", "0.2_alpha"); // 0, =
//! piCout << versionCompare("1_prebeta", "1.0_alpha"); // 1, >
//! \endcode
//! \~\return
//! \~english
//! * 0 - equal
//! * 1 - v0 > v1
//! * -1 - v0 < v1
//! \~russian
//! * 0 - равны
//! * 1 - v0 > v1
//! * -1 - v0 < v1
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;
}
//! \relatesalso PIString
//! \~\details
//! \~english
//! Parse version as described in \a versionCompare() and returns
//! classic view of codes and labels: major.minor.revision[-build][_label].
//! Example:
//! \~russian
//! Разбирает версию по описанию \a versionCompare() и возвращает
//! классическое представление версии и метки: major.minor.revision[-build][_label].
//! Пример:
//! \~\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
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;
}

View File

@@ -1,1570 +0,0 @@
/*! \file pistring.h
* \ingroup Core
* \brief
* \~english String class
* \~russian Класс строки
*/
/*
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"
#include "piconstchars.h"
#define PIStringAscii PIString::fromAscii
class PIStringList;
//! \ingroup Core
//! \~\brief
//! \~english String class.
//! \~russian Класс строки.
class PIP_EXPORT PIString
{
BINARY_STREAM_FRIEND(PIString);
public:
typedef PIDeque<PIChar>::iterator iterator;
typedef PIDeque<PIChar>::const_iterator const_iterator;
typedef PIDeque<PIChar>::reverse_iterator reverse_iterator;
typedef PIDeque<PIChar>::const_reverse_iterator const_reverse_iterator;
typedef PIChar value_type;
typedef PIChar* pointer;
typedef const PIChar* const_pointer;
typedef PIChar& reference;
typedef const PIChar& const_reference;
typedef size_t size_type;
//! \~english Contructs an empty string.
//! \~russian Создает пустую строку.
PIString() {}
//! \~english Value for elide at left.
//! \~russian Значение для пропуска слева.
static const float ElideLeft ;
//! \~english Value for elide at center.
//! \~russian Значение для пропуска в середине.
static const float ElideCenter;
//! \~english Value for elide at right.
//! \~russian Значение для пропуска справа.
static const float ElideRight ;
PIString & operator +=(const PIChar & c) {d.push_back(c); return *this;}
PIString & operator +=(const char c) {d.push_back(PIChar(c)); return *this;}
PIString & operator +=(const char * str);
PIString & operator +=(const wchar_t * str);
PIString & operator +=(const PIByteArray & ba);
PIString & operator +=(const PIString & str);
PIString & operator +=(const PIConstChars & str);
PIString(uchar ) = delete;
PIString( short) = delete;
PIString(ushort) = delete;
PIString( int ) = delete;
PIString(uint ) = delete;
PIString( long ) = delete;
PIString(ulong ) = delete;
PIString( llong) = delete;
PIString(ullong) = delete;
PIString & operator +=(uchar ) = delete;
PIString & operator +=( short) = delete;
PIString & operator +=(ushort) = delete;
PIString & operator +=( int ) = delete;
PIString & operator +=(uint ) = delete;
PIString & operator +=( long ) = delete;
PIString & operator +=(ulong ) = delete;
PIString & operator +=( llong) = delete;
PIString & operator +=(ullong) = delete;
//! \~english Contructs a copy of string.
//! \~russian Создает копию строки.
PIString(const PIString & o) {d = o.d;}
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIString(PIString && o): d(std::move(o.d)) {piSwap(data_, o.data_);}
//! \~english Contructs string with single character "c".
//! \~russian Создает строку из одного символа "c".
PIString(const PIChar c) {d.push_back(c);}
//! \~english Contructs string with single character "c".
//! \~russian Создает строку из одного символа "c".
PIString(const char c) {d.push_back(PIChar(c));}
//! \~english Contructs string from C-string "str" (system codepage).
//! \~russian Создает строку из C-строки "str" (кодировка системы).
//! \~\details
//! \~english
//! "str" should be null-terminated\n
//! \~russian
//! "str" должна заканчиваться нулевым байтом\n
//! \~\code
//! PIString s("string");
//! \endcode
PIString(const char * str) {*this += str;}
//! \~english Contructs string from \c wchar_t C-string "str".
//! \~russian Создает строку из \c wchar_t C-строки "str".
//! \~\details
//! \~english
//! "str" should be null-terminated
//! \~russian
//! "str" должна заканчиваться нулевым \c wchar_t
//! \~\code
//! PIString s(L"string");
//! \endcode
PIString(const wchar_t * str) {*this += str;}
//! \~english Contructs string from byte array "ba" (as UTF-8).
//! \~russian Создает строку из байтового массива "ba" (как UTF-8).
PIString(const PIByteArray & ba) {*this += ba;}
//! \~english Contructs string from "len" characters of buffer "str".
//! \~russian Создает строку из "len" символов массива "str".
PIString(const PIChar * str, const int len): d(str, size_t(len)) {}
//! \~english Contructs string from "len" characters of buffer "str" (system codepage).
//! \~russian Создает строку из "len" символов массива "str" (кодировка системы).
//! \~\details
//! \~\code
//! PIString s("string", 3); // s = "str"
//! \endcode
PIString(const char * str, const int len) {appendFromChars(str, len);}
//! \~english Contructs string as sequence of characters "c" of buffer with length "len".
//! \~russian Создает строку как последовательность длиной "len" символа "c".
//! \~\details
//! \~\code
//! PIString s(5, 'p'); // s = "ppppp"
//! \endcode
PIString(const int len, const char c) {for (int i = 0; i < len; ++i) d.push_back(PIChar(c));}
//! \~english Contructs string as sequence of characters "c" of buffer with length "len".
//! \~russian Создает строку как последовательность длиной "len" символа "c".
//! \~\details
//! \~\code
//! PIString s(5, "№"); // s = "№№№№№"
//! \endcode
PIString(const int len, const PIChar c) {for (int i = 0; i < len; ++i) d.push_back(c);}
PIString(const PIConstChars & c) {*this += c;}
~PIString();
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIString & operator =(const PIString & o) {if (this == &o) return *this; d = o.d; return *this;}
//! \~english Assign move operator.
//! \~russian Оператор перемещающего присваивания.
PIString & operator =(PIString && o) {d.swap(o.d); piSwap(data_, o.data_); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIString & operator =(const PIConstChars & o) {d.clear(); *this += o; return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIString & operator =(const char * o) {d.clear(); *this += o; return *this;}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator ==(const PIString & str) const;
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator ==(const PIChar c) const {if (d.size() != 1) return false; return d.at(0) == c;}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator ==(const char * str) const {return *this == PIString(str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator !=(const PIString & str) const;
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator !=(const PIChar c) const {if (d.size() != 1) return true; return d.at(0) != c;}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator !=(const char * str) const {return *this != PIString(str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator <(const PIString & str) const;
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator <(const PIChar c) const {if (d.size() != 1) return d.size() < 1; return d.at(0) < c;}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator <(const char * str) const {return *this < PIString(str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator >(const PIString & str) const;
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator >(const PIChar c) const {if (d.size() != 1) return d.size() > 1; return d.at(0) > c;}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator >(const char * str) const {return *this > PIString(str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator <=(const PIString & str) const {return !(*this > str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator <=(const PIChar c) const {return !(*this > c);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator <=(const char * str) const {return *this <= PIString(str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator >=(const PIString & str) const {return !(*this < str);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator >=(const PIChar c) const {return !(*this < c);}
//! \~english Compare operator.
//! \~russian Оператор сравнения.
bool operator >=(const char * str) const {return *this >= PIString(str);}
//! \~english Iterator to the first element.
//! \~russian Итератор на первый элемент.
//! \~\details
//! \~\return \ref stl_iterators
//! \~\sa \a end(), \a rbegin(), \a rend()
inline iterator begin() {return d.begin();}
//! \~english Iterator to the element following the last element.
//! \~russian Итератор на элемент, следующий за последним элементом.
//! \~\details
//! \~\return \ref stl_iterators
//! \~\sa \a begin(), \a rbegin(), \a rend()
inline iterator end() {return d.end();}
inline const_iterator begin() const {return d.begin();}
inline const_iterator end() const {return d.end();}
//! \~english Returns a reverse iterator to the first element of the reversed array.
//! \~russian Обратный итератор на первый элемент.
//! \~\details
//! \~english It corresponds to the last element of the non-reversed array.
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на последний элемент.
//! \~\return \ref stl_iterators
//! \~\sa \a rend(), \a begin(), \a end()
inline reverse_iterator rbegin() {return d.rbegin();}
//! \~english Returns a reverse iterator to the element.
//! following the last element of the reversed array.
//! \~russian Обратный итератор на элемент, следующий за последним элементом.
//! \~\details
//! \~english It corresponds to the element preceding the first element of the non-reversed array.
//! \~russian Итератор для прохода массива в обратном порядке.
//! Указывает на элемент, предшествующий первому элементу.
//! \~\return \ref stl_iterators
//! \~\sa \a rbegin(), \a begin(), \a end()
inline reverse_iterator rend() {return d.rend();}
inline const_reverse_iterator rbegin() const {return d.rbegin();}
inline const_reverse_iterator rend() const {return d.rend();}
//! \~english Full access to character by `index`.
//! \~russian Полный доступ к символу по индексу `index`.
//! \~\details
//! \~english Сharacter index starts from `0`.
//! Сharacter index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс элемента считается от `0`.
//! Индекс символа должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline PIChar & operator [](size_t index) {return d[index];}
inline PIChar operator [](size_t index) const {return d[index];}
//! \~english Read only access to character by `index`.
//! \~russian Доступ исключительно на чтение к символу по индексу `index`.
//! \~\details
//! \~english Сharacter index starts from `0`.
//! Сharacter index must be in range from `0` to `size()-1`.
//! Otherwise will be undefined behavior.
//! \~russian Индекс символа считается от `0`.
//! Индекс символа должен лежать в пределах от `0` до `size()-1`.
//! Иначе это приведёт к неопределённому поведению программы и ошибкам памяти.
inline const PIChar at(size_t index) const {return d.at(index);}
//! \~english Returns the last character of the string.
//! \~russian Возвращает последний символ строки.
inline PIChar & back() {return d.back();}
inline PIChar back() const {return d.back();}
inline PIChar & front() {return d.front();}
inline PIChar front() const {return d.front();}
//! \~english Sets size of the string, new characters are copied from `c`.
//! \~russian Устанавливает размер строки, новые символы копируются из `c`.
//! \~\details
//! \~english If `new_size` is greater than the current \a size(),
//! characters are added to the end; the new characters are initialized from `c`.
//! If `new_size` is less than the current \a size(), characters are removed from the end.
//! \~russian Если `new_size` больше чем текущий размер строки \a size(),
//! новые символы добавляются в конец строки и создаются из `с`.
//! Если `new_size` меньше чем текущий размер строки \a size(),
//! лишние символы удаляются с конца строки.
//! \~\sa \a size(), \a clear()
inline PIString & resize(size_t new_size, PIChar c = PIChar()) {d.resize(new_size, c); return *this;}
//! \~english Delete one character at the end of string.
//! \~russian Удаляет один символ с конца строки.
inline PIString & pop_back() {d.pop_back(); return *this;}
//! \~english Delete one character at the benig of string.
//! \~russian Удаляет один символ с начала строки.
inline PIString & pop_front() {d.pop_front(); return *this;}
//! \~english Removes `count` characters from the string, starting at `index` position.
//! \~russian Удаляет символы из строки, начиная с позиции `index` в количестве `count`.
inline PIString & remove(size_t index, size_t count = 1) {d.remove(index, count); return *this;}
//! \~english Assigns character 'c' to all string characters.
//! \~russian Заполняет всю строку символами `c`.
inline PIString & fill(PIChar c = PIChar()) {d.fill(c); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & prepend(const char * str) {insert(0, str); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & prepend(const PIString & str) {d.prepend(str.d); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & prepend(const PIChar c) {d.prepend(c); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & prepend(const char c) {d.prepend(PIChar(c)); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & push_front(const char * str) {insert(0, str); return *this;}
//! \~english Insert string "str" at the begin of string.
//! \~russian Вставляет "str" в начало строки.
PIString & push_front(const PIString & str) {d.push_front(str.d); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & push_front(const PIChar c) {d.push_front(c); return *this;}
//! \~english Insert character `c` at the begin of string.
//! \~russian Вставляет символ `c` в начало строки.
PIString & push_front(const char c) {d.push_front(PIChar(c)); return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & append(const char * str) {*this += str; return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & append(const PIString & str) {d.append(str.d); return *this;}
PIString & append(const PIConstChars & str) {*this += str; return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & append(const PIChar c) {d.append(c); return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & append(const char c) {d.append(PIChar(c)); return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & push_back(const char * str) {*this += str; return *this;}
//! \~english Insert string "str" at the end of string.
//! \~russian Вставляет "str" в конец строки.
PIString & push_back(const PIString & str) {d.push_back(str.d); return *this;}
PIString & push_back(const PIConstChars & str) {*this += str; return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & push_back(const PIChar c) {d.push_back(c); return *this;}
//! \~english Insert character `c` at the end of string.
//! \~russian Вставляет символ `c` в конец строки.
PIString & push_back(const char c) {d.push_back(PIChar(c)); return *this;}
//! \~english Returns part of string from character at index "start" and maximum length "len".
//! \~russian Возвращает подстроку от символа "start" и максимальной длиной "len".
PIString mid(int start, int len = -1) const;
//! \~english Synonym of \a mid().
//! \~russian Аналог \a mid().
PIString subString(int start, int len = -1) const {return mid(start, len);}
//! \~english Returns part of string from start and maximum length "len".
//! \~russian Возвращает подстроку от начала и максимальной длиной "len".
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.left(-1); // s = ""
//! piCout << s.left(1); // s = "0"
//! piCout << s.left(5); // s = "01234"
//! piCout << s.left(15); // s = "0123456789"
//! \endcode
//! \~\sa \a mid(), \a right()
PIString left(int len) const {return len <= 0 ? PIString() : mid(0, len);}
//! \~english Returns part of string at end and maximum length "len".
//! \~russian Возвращает подстроку максимальной длиной "len" и до конца.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.right(-1); // s = ""
//! piCout << s.right(1); // s = "9"
//! piCout << s.right(5); // s = "56789"
//! piCout << s.right(15); // s = "0123456789"
//! \endcode
//! \~\sa \a mid(), \a left()
PIString right(int len) const {return len <= 0 ? PIString() : mid(size() - len, len);}
//! \~english Remove part of string from character as index "start" and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от символа "start" и максимальной длины "len", возвращает эту строку.
PIString & cutMid(int start, int len);
//! \~english Remove part of string from start and maximum length "len" and return this string.
//! \~russian Удаляет часть строки от начала и максимальной длины "len", возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! s.cutLeft(1);
//! piCout << s; // s = "123456789"
//! s.cutLeft(3);
//! piCout << s; // s = "456789"
//! s.cutLeft(30);
//! piCout << s; // s = ""
//! \endcode
//! \~\sa \a cutMid(), \a cutRight()
PIString & cutLeft(int len) {return len <= 0 ? *this : cutMid(0, len);}
//! \~english Remove part of string at end and maximum length "len" and return this string.
//! \~russian Удаляет часть строки максимальной длины "len" от конца, возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! s.cutRight(1);
//! piCout << s; // s = "012345678"
//! s.cutRight(3);
//! piCout << s; // s = "012345"
//! s.cutRight(30);
//! piCout << s; // s = ""
//! \endcode
//! \~\sa \a cutMid(), \a cutLeft()
PIString & cutRight(int len) {return len <= 0 ? *this : cutMid(size() - len, len);}
//! \~english Remove spaces at the start and at the end of string and return this string.
//! \~russian Удаляет пробельные символы с начала и конца строки и возвращает эту строку.
PIString & trim();
//! \~english Returns copy of this string without spaces at the start and at the end.
//! \~russian Возвращает копию этой строки без пробельных символов с начала и конца.
//! \~\details
//! \~\code
//! PIString s(" \t string \n");
//! piCout << s.trimmed(); // s = "string"
//! piCout << s; // s = " string "
//! \endcode
//! \~\sa \a trim()
PIString trimmed() const;
//! \~english Replace part of string from index "from" and maximum length "len" with string "with" and return this string.
//! \~russian Заменяет часть строки от символа "from" и максимальной длины "len" строкой "with", возвращает эту строку.
PIString & replace(const int from, const int count, const PIString & with);
//! \~english Replace part copy of this string from index "from" and maximum length "len" with string "with".
//! \~russian Заменяет часть копии этой строки от символа "from" и максимальной длины "len" строкой "with".
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.replaced(2, 3, "_cut_"); // s = "01_cut_56789"
//! piCout << s.replaced(0, 1, "one_"); // s = "one_123456789"
//! \endcode
//! \~\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;}
//! \~english Replace first founded substring "what" with string "with" and return this string.
//! \~russian Заменяет первую найденную подстроку "what" строкой "with", возвращает эту строку.
PIString & replace(const PIString & what, const PIString & with, bool * ok = 0);
//! \~english Replace in string copy first founded substring "what" with string "with".
//! \~russian Заменяет в копии строки первую найденную подстроку "what" строкой "with".
//! \~\details
//! \~english If "ok" is not null, it set to "true" if something was replaced.
//! \~russian Если "ok" не null, то устанавливает в "true" если замена произведена.
//! \~\code
//! PIString s("pip string");
//! bool ok;
//! piCout << s.replace("string", "conf", &ok); // s = "pip conf", true
//! piCout << s.replace("PIP", "PlInPr", &ok); // s = "pip string", false
//! \endcode
//! \~\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;}
//! \~english Replace all founded substrings "what" with strings "with" and return this string.
//! \~russian Заменяет все найденные подстроки "what" строками "with", возвращает эту строку.
PIString & replaceAll(const PIString & what, const PIString & with);
//! \~english Replace all founded substrings "what" with characters "with" and return this string.
//! \~russian Заменяет все найденные подстроки "what" символами "with", возвращает эту строку.
PIString & replaceAll(const PIString & what, const char with);
//! \~english Replace all founded characters "what" with characters "with" and return this string.
//! \~russian Заменяет все найденные символы "what" символами "with", возвращает эту строку.
PIString & replaceAll(const char what, const char with);
//! \~english Replace all founded substrings "what" with strings "with" in string copy.
//! \~russian Заменяет в копии строки все найденные подстроки "what" строками "with".
//! \~\sa \a replaceAll()
PIString replacedAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Replace all founded substrings "what" with characters "with" in string copy.
//! \~russian Заменяет в копии строки все найденные подстроки "what" символами "with".
//! \~\sa \a replaceAll()
PIString replacedAll(const PIString & what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Replace all founded characters "what" with characters "with" in string copy.
//! \~russian Заменяет в копии строки все найденные символы "what" символами "with".
//! \~\sa \a replaceAll()
PIString replacedAll(const char what, const char with) const {PIString str(*this); str.replaceAll(what, with); return str;}
//! \~english Remove all founded substrings "what" and return this string.
//! \~russian Удаляет все найденные подстроки "what", возвращает эту строку.
PIString & removeAll(const PIString & str);
//! \~english Remove all founded characters "what" and return this string.
//! \~russian Удаляет все найденные символы "what", возвращает эту строку.
PIString & removeAll(char c) {d.removeAll(PIChar(c)); return *this;}
//! \~english Repeat content of string "times" times and return this string.
//! \~russian Повторяет содержимое строки "times" раз и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s(" :-) ");
//! s.repeat(3);
//! piCout << s; // :-) :-) :-)
//! \endcode
//! \~\sa \a repeated()
PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;}
//! \~english Returns repeated "times" times string.
//! \~russian Возвращает повторённую "times" раз строку.
//! \~\details
//! \~\code
//! PIString s(" :-) ");
//! piCout << s.repeated(3); // :-) :-) :-)
//! piCout << s; // :-)
//! \endcode
//! \~\sa \a repeat()
PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);}
//! \~english Insert character "c" after index "index" and return this string.
//! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("pp");
//! s.insert(1, "i");
//! piCout << s; // s = "pip"
//! \endcode
PIString & insert(const int index, const PIChar c) {d.insert(index, c); return *this;}
//! \~english Insert character "c" after index "index" and return this string.
//! \~russian Вставляет символ "c" после позиции "index" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("pp");
//! s.insert(1, 'i');
//! piCout << s; // s = "pip"
//! \endcode
PIString & insert(const int index, const char c) {return insert(index, PIChar(c));}
//! \~english Insert string "str" after index "index" and return this string.
//! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("stg");
//! s.insert(2, "rin");
//! piCout << s; // s = "string"
//! \endcode
PIString & insert(const int index, const PIString & str);
//! \~english Insert string "str" after index "index" and return this string.
//! \~russian Вставляет строку "str" после позиции "index" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("stg");
//! s.insert(2, "rin");
//! piCout << s; // s = "string"
//! \endcode
PIString & insert(const int index, const char * c) {return insert(index, PIString(c));}
//! \~english Enlarge string to length "len" by addition characters "c" at the end, and return this string.
//! \~russian Увеличивает длину строки до "len" добавлением символов "c" в конец и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("str");
//! s.expandRightTo(2, "_");
//! piCout << s; // s = "str"
//! s.expandRightTo(6, "_");
//! piCout << s; // s = "str___"
//! \endcode
//! \~\sa \a expandLeftTo(), \a expandedRightTo(), \a expandedLeftTo()
PIString & expandRightTo(const int len, const PIChar c) {if (len > d.size_s()) d.resize(len, c); return *this;}
//! \~english Enlarge string to length "len" by addition characters "c" at the begin, and return this string.
//! \~russian Увеличивает длину строки до "len" добавлением символов "c" в начало и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("str");
//! s.expandLeftTo(2, "_");
//! piCout << s; // s = "str"
//! s.expandLeftTo(6, "_");
//! piCout << s; // s = "___str"
//! \endcode
//! \~\sa \a expandRightTo(), \a expandedRightTo(), \a expandedLeftTo()
PIString & expandLeftTo(const int len, const PIChar c) {if (len > d.size_s()) insert(0, PIString(len - d.size_s(), c)); return *this;}
//! \~english Enlarge copy of this string to length "len" by addition characters "c" at the end.
//! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в конец.
//! \~\details
//! \~\code
//! PIString s("str");
//! piCouy << s.expandedRightTo(5, "_"); // s = "str__"
//! piCout << s; // s = "str"
//! \endcode
//! \~\sa \a expandRightTo(), \a expandLeftTo(), \a expandedLeftTo()
PIString expandedRightTo(const int len, const PIChar c) const {return PIString(*this).expandRightTo(len, c);}
//! \~english Enlarge copy of this string to length "len" by addition characters "c" at the begin.
//! \~russian Увеличивает длину копии этой строки до "len" добавлением символов "c" в начало.
//! \~\details
//! \~\code
//! PIString s("str");
//! piCouy << s.expandedLeftTo(5, "_"); // s = "__str"
//! piCout << s; // s = "str"
//! \endcode
//! \~\sa \a expandRightTo(), \a expandLeftTo(), \a expandedRightTo()
PIString expandedLeftTo(const int len, const PIChar c) const {return PIString(*this).expandLeftTo(len, c);}
//! \~english Add "c" characters at the beginning and end, and return this string.
//! \~russian Добавляет символ "c" в начало и конец и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("str");
//! s.quote();
//! piCout << s; // s = ""str""
//! \endcode
//! \~\sa \a quoted()
PIString & quote(PIChar c = PIChar('"')) {d.prepend(c); d.append(c); return *this;}
//! \~english Returns quoted copy of this string.
//! \~russian Возвращает копию строки с добавленным в начало и конец символом "c".
//! \~\details
//! \~\code
//! PIString s("str");
//! piCout << s.quoted(); // s = ""str""
//! piCout << s; // s = "str"
//! \endcode
//! \~\sa \a quote()
PIString quoted(PIChar c = PIChar('"')) {return PIString(*this).quote(c);}
//! \~english Reverse string and return this string.
//! \~russian Разворачивает и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! s.reverse();
//! piCout << s; // s = "9876543210"
//! \endcode
//! \~\sa \a reversed()
PIString & reverse() {d.reverse(); return *this;}
//! \~english Reverse copy of this string.
//! \~russian Разворачивает копию этой строки.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.reversed(); // s = "9876543210"
//! piCout << s; // s = "0123456789"
//! \endcode
//! \~\sa \a reverse()
PIString reversed() const {PIString ret(*this); return ret.reverse();}
//! \~english Fit string to maximum size "size" by inserting ".." at position "pos" and return this string.
//! \~russian Уменьшает строку до размера "size", вставляя ".." в положение "pos" и возвращает эту строку.
//! \~\sa \a elided()
PIString & elide(int size, float pos = ElideCenter);
//! \~english Fit copy of this string to maximum size "size" by inserting ".." at position "pos".
//! \~russian Уменьшает копию этой строки до размера "size", вставляя ".." в положение "pos".
//! \~\details
//! \~\code
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideLeft); // ..ABCDEF
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideCenter); // 123..DEF
//! piCout << PIString("123456789ABCDEF").elided(8, PIString::ElideRight); // 123456..
//! piCout << PIString("123456789ABCDEF").elided(8, 0.25); // 12..CDEF
//! \endcode
//! \~\sa \a elide()
PIString elided(int size, float pos = ElideCenter) const {PIString str(*this); str.elide(size, pos); return str;}
//! \~english Take a part of string from character at index "start" and maximum length "len" and return it.
//! \~russian Извлекает часть строки от символа "start" максимальной длины "len" и возвращает её.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.takeMid(1, 3); // "123"
//! piCout << s; // s = "0456789"
//! \endcode
//! \~\sa \a takeLeft, \a takeRight()
PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;}
//! \~english Take a part from the begin of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки от начала максимальной длины "len" и возвращает её.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.takeLeft(3); // "012"
//! piCout << s; // s = "3456789"
//! \endcode
//! \~\sa \a takeMid(), \a takeRight()
PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;}
//! \~english Take a part from the end of string with maximum length "len" and return it.
//! \~russian Извлекает часть строки с конца максимальной длины "len" и возвращает её.
//! \~\details
//! \~\code
//! PIString s("0123456789");
//! piCout << s.takeRight(3); // "789"
//! piCout << s; // s = "0123456"
//! \endcode
//! \~\sa \a takeMid(), \a takeLeft()
PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;}
//! \~english Take a character from the begin of this string and return it.
//! \~russian Извлекает символ с начала строки и возвращает его как строку.
PIString takeSymbol();
//! \~english Take a word from the begin of this string and return it.
//! \~russian Извлекает слово с начала строки и возвращает его.
PIString takeWord();
//! \~english Take a word with letters, numbers and '_' characters from the begin of this string and return it.
//! \~russian Извлекает слово из букв, цифр и симолов '_' с начала строки и возвращает его.
PIString takeCWord();
//! \~english Take a line from the begin of this string and return it.
//! \~russian Извлекает строку текста (до новой строки) с начала строки и возвращает её.
PIString takeLine();
//! \~english Take a number with C-format from the begin of this string and return it.
//! \~russian Извлекает число в C-формате с начала строки и возвращает его как строку.
PIString takeNumber();
//! \~english Take a range between "start" and "end" characters from the begin of this string and return it.
//! \~russian Извлекает диапазон между символами "start" и "end" с начала строки и возвращает его.
PIString takeRange(const PIChar start, const PIChar end, const PIChar shield = '\\');
//! \~english Returns string in brackets "start" and "end" characters from the beginning.
//! \~russian Возвращает строку между символами "start" и "end" с начала строки.
PIString inBrackets(const PIChar start, const PIChar end) const;
//! \~english Returns \c char * representation of this string in system codepage.
//! \~russian Возвращает \c char * представление строки в системной кодировке.
const char * data() const;
//! \~english Returns \c char * representation of this string in terminal codepage.
//! \~russian Возвращает \c char * представление строки в кодировке консоли.
const char * dataConsole() const;
//! \~english Returns \c char * representation of this string in UTF-8.
//! \~russian Возвращает \c char * представление строки в кодировке UTF-8.
const char * dataUTF8() const;
//! \~english Returns \c char * representation of this string in ASCII.
//! \~russian Возвращает \c char * представление строки в кодировке ASCII.
const char * dataAscii() const;
//! \~english Returns hash of string
//! \~russian Возвращает хэш строки
uint hash() const;
//! \~english Same as \a toUTF8().
//! \~russian Тоже самое, что \a toUTF8().
PIByteArray toByteArray() const {return toUTF8();}
//! \~english Returns \a PIByteArray contains \a data() of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий \a data() строки без завершающего нулевого байта.
PIByteArray toSystem() const;
//! \~english Returns \a PIByteArray contains \a dataUTF8() of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий \a dataUTF8() строки без завершающего нулевого байта.
PIByteArray toUTF8() const;
//! \~english Returns \a PIByteArray contains custom charset representation of this string without terminating null-char.
//! \~russian Возвращает \a PIByteArray содержащий строку в указанной кодировке без завершающего нулевого байта.
PIByteArray toCharset(const char * c) const;
//! \~english Returns \a PIString with non-ASCII symbols replaced with '?'.
//! \~russian Возвращает \a PIString с заменёнными '?' не-ASCII символами.
PIString simplified() const;
//! \~english Split string with delimiter "delim" to \a PIStringList.
//! \~russian Разделяет строку в \a PIStringList через разделитель "delim".
//! \~\details
//! \~\code
//! PIString s("1 2 3");
//! piCout << s.split(" "); // {"1", "2", "3"}
//! \endcode
PIStringList split(const PIString & delim) const;
//! \~english Convert each character in copied string to upper case.
//! \~russian Преобразует каждый символ в скопированной строке в верхний регистр.
PIString toUpperCase() const;
//! \~english Convert each character in copied string to lower case.
//! \~russian Преобразует каждый символ в скопированной строке в нижний регистр.
PIString toLowerCase() const;
//! \~english Returns if string contains character "c".
//! \~russian Возвращает содержит ли строка символ "c".
bool contains(const char c) const {return d.contains(PIChar(c));}
//! \~english Returns if string contains substring "str".
//! \~russian Возвращает содержит ли строка подстроку "str".
bool contains(const char * str) const {return contains(PIString(str));}
//! \~english Returns if string contains substring "str".
//! \~russian Возвращает содержит ли строка подстроку "str".
bool contains(const PIString & str) const {return find(str) >= 0;}
//! \~english Search character "c" from character at index "start" and return first occur position.
//! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение.
int find(const char c, const int start = 0) const;
//! \~english Search character "c" from character at index "start" and return first occur position.
//! \~russian Ищет символ "c" от символа "start" и возвращает первое вхождение.
int find(PIChar c, const int start = 0) const {return d.indexOf(c, start);}
//! \~english Search substring "str" from character at index "start" and return first occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение.
int find(const PIString & str, const int start = 0) const;
//! \~english Search substring "str" from character at index "start" and return first occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает первое вхождение.
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.find("-"); // -1
//! piCout << s.find("34"); // 3
//! piCout << s.find("3", 4); // 9
//! piCout << s.find("3", 10); // -1
//! \endcode
//! \~\sa \a findAny(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int find(const char * str, const int start = 0) const {return find(PIString(str), start);}
//! \~english Search any character of "str" from character at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение.
int findAny(const PIString & str, const int start = 0) const;
//! \~english Search any character of "str" from character at index "start" and return first occur position.
//! \~russian Ищет любой символ строки "str" от симола "start" и возвращает первое вхождение.
//! \~\details
//! \~\code
//! piCout << PIString("1.str").findAny(".,:"); // 1
//! piCout << PIString("1,str").findAny(".,:"); // 1
//! piCout << PIString("1:str").findAny(".,:"); // 1
//! \endcode
//! \~\sa \a find(), \a findLast(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);}
//! \~english Search character "c" from character at index "start" and return last occur position.
//! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение.
int findLast(const char c, const int start = 0) const;
//! \~english Search character "c" from character at index "start" and return last occur position.
//! \~russian Ищет символ "c" от символа "start" и возвращает последнее вхождение.
int findLast(PIChar c, const int start = 0) const;
//! \~english Search substring "str" from character at index "start" and return last occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение.
int findLast(const PIString & str, const int start = 0) const;
//! \~english Search substring "str" from character at index "start" and return last occur position.
//! \~russian Ищет подстроку "str" от символа "start" и возвращает последнее вхождение.
//! \~\details
//! \~\code
//! PIString s("012345012345");
//! piCout << s.findLast("-"); // -1
//! piCout << s.findLast("34"); // 9
//! piCout << s.findLast("3", 4); // 9
//! piCout << s.findLast("3", 10); // -1
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findAnyLast(), \a findWord(), \a findCWord(), \a findRange()
int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);}
//! \~english Search any character of "str" from character at index "start" and return last occur position.
//! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение.
int findAnyLast(const PIString & str, const int start = 0) const;
//! \~english Search any character of "str" from character at index "start" and return last occur position.
//! \~russian Ищет любой символ строки "str" от символа "start" и возвращает последнее вхождение.
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str,0").findAnyLast(".,:"); // 4
//! piCout << PIString(".str:0").findAnyLast(".,:"); // 4
//! \endcode
//! \~\sa \a find(), \a findAny(), \a findLast(), \a findWord(), \a findCWord(), \a findRange()
int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);}
//! \~english Search word "word" from character at index "start" and return first occur position.
//! \~russian Ищет слово "word" от симола "start" и возвращает первое вхождение.
int findWord(const PIString & word, const int start = 0) const;
//! \~english Search C-word "word" from character at index "start" and return first occur position.
//! \~russian Ищет C-слово "word" от симола "start" и возвращает первое вхождение.
int findCWord(const PIString & word, const int start = 0) const;
//! \~english Search range start between "start" and "end" characters at index "start_index" and return first occur position.
//! \~russian Ищет начало диапазона между символами "start" и "end" от симола "start" и возвращает первое вхождение.
int findRange(const PIChar start, const PIChar end, const PIChar shield = '\\', const int start_index = 0, int * len = 0) const;
//! \~english Returns number of occurrences of character "c".
//! \~russian Возвращает число вхождений символа "c".
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").entries("."); // 2
//! piCout << PIString(".str.0").entries("0"); // 1
//! \endcode
int entries(const PIChar c) const;
//! \~english Returns number of occurrences of character "c".
//! \~russian Возвращает число вхождений символа "c".
//! \~\details
//! \~\code
//! piCout << PIString(".str.0").entries('.'); // 2
//! piCout << PIString(".str.0").entries('0'); // 1
//! \endcode
int entries(char c) const {return entries(PIChar(c));}
//! \~english Returns if string starts with "str".
//! \~russian Возвращает начинается ли строка со "str".
bool startsWith(const PIString & str) const;
//! \~english Returns if string ends with "str".
//! \~russian Возвращает оканчивается ли строка на "str".
bool endsWith(const PIString & str) const;
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
int length() const {return d.size_s();}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
size_t size() const {return d.size();}
//! \~english Returns characters length of string.
//! \~russian Возвращает длину строки в символах.
ssize_t size_s() const {return d.size_s();}
//! \~english Returns \c true if string is empty, i.e. length = 0.
//! \~russian Возвращает \c true если строка пустая, т.е. длина = 0.
bool isEmpty() const {if (d.isEmpty()) return true; if (d.at(0) == PIChar()) return true; return false;}
//! \~english Returns \c true if string is not empty, i.e. length > 0.
//! \~russian Возвращает \c true если строка непустая, т.е. длина > 0.
bool isNotEmpty() const {return !isEmpty();}
//! \~english Clear string, will be empty string.
//! \~russian Очищает строку, строка становится пустой.
//! \~\details
//! \~\note
//! \~english Reserved memory will not be released.
//! \~russian Зарезервированная память не освободится.
//! \~\sa \a resize()
void clear() {d.clear();}
//! \~english Returns \c true if string equal "true", "yes", "on" or positive not null numeric value.
//! \~russian Возвращает \c true если строка равна "true", "yes", "on" или числу > 0.
bool toBool() const;
//! \~english Returns \c char numeric value of string.
//! \~russian Возвращает \c char числовое значение строки.
char toChar() const;
//! \~english Returns \c short numeric value of string in base "base".
//! \~russian Возвращает \c short числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toShort(); // 123
//! piCout << PIString("123").toShort(16); // 291
//! piCout << PIString("0x123").toShort(); // 291
//! piCout << PIString("1001").toShort(2); // 9
//! \endcode
short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));}
//! \~english Returns \c ushort numeric value of string in base "base".
//! \~russian Возвращает \c ushort числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toUShort(); // 123
//! piCout << PIString("123").toUShort(16); // 291
//! piCout << PIString("0x123").toUShort(); // 291
//! piCout << PIString("1001").toUShort(2); // 9
//! \endcode
ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));}
//! \~english Returns \c int numeric value of string in base "base".
//! \~russian Возвращает \c int числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toInt(); // 123
//! piCout << PIString("123").toInt(16); // 291
//! piCout << PIString("0x123").toInt(); // 291
//! piCout << PIString("1001").toInt(2); // 9
//! \endcode
int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));}
//! \~english Returns \c uint numeric value of string in base "base".
//! \~russian Возвращает \c uint числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toUInt(); // 123
//! piCout << PIString("123").toUInt(16); // 291
//! piCout << PIString("0x123").toUInt(); // 291
//! piCout << PIString("1001").toUInt(2); // 9
//! \endcode
uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));}
//! \~english Returns \c long numeric value of string in base "base".
//! \~russian Возвращает \c long числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toLong(); // 123
//! piCout << PIString("123").toLong(16); // 291
//! piCout << PIString("0x123").toLong(); // 291
//! piCout << PIString("1001").toLong(2); // 9
//! \endcode
long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));}
//! \~english Returns \c ulong numeric value of string in base "base".
//! \~russian Возвращает \c ulong числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toULong(); // 123
//! piCout << PIString("123").toULong(16); // 291
//! piCout << PIString("0x123").toULong(); // 291
//! piCout << PIString("1001").toULong(2); // 9
//! \endcode
ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));}
//! \~english Returns \c llong numeric value of string in base "base".
//! \~russian Возвращает \c llong числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toLLong(); // 123
//! piCout << PIString("123").toLLong(16); // 291
//! piCout << PIString("0x123").toLLong(); // 291
//! piCout << PIString("1001").toLLong(2); // 9
//! \endcode
llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);}
//! \~english Returns \c ullong numeric value of string in base "base".
//! \~russian Возвращает \c ullong числовое значение строки по основанию "base".
//! \~\details
//! \~english If "base" < 0 then base automatically select 16 if string start with "0x", therwise 10.
//! \~russian Если "base" < 0 тогда основание автоматически принимается 16 если строка начинается с "0x", иначе 10.
//! \~\code
//! piCout << PIString("123").toULLong(); // 123
//! piCout << PIString("123").toULLong(16); // 291
//! piCout << PIString("0x123").toULLong(); // 291
//! piCout << PIString("1001").toULLong(2); // 9
//! \endcode
ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));}
//! \~english Returns \c float numeric value of string.
//! \~russian Возвращает \c float числовое значение строки.
//! \~\details
//! \~\code
//! piCout << PIString("123").toFloat(); // 123
//! piCout << PIString("1.2E+2").toFloat(); // 120
//! piCout << PIString("0.01").toFloat(); // 0.01
//! \endcode
float toFloat() const;
//! \~english Returns \c double numeric value of string.
//! \~russian Возвращает \c double числовое значение строки.
//! \~\details
//! \~\code
//! piCout << PIString("123").toDouble(); // 123
//! piCout << PIString("1.2E+2").toDouble(); // 120
//! piCout << PIString("0.01").toDouble(); // 0.01
//! \endcode
double toDouble() const;
//! \~english Returns \c ldouble numeric value of string.
//! \~russian Возвращает \c ldouble числовое значение строки.
//! \~\details
//! \~\code
//! piCout << PIString("123").toLDouble(); // 123
//! piCout << PIString("1.2E+2").toLDouble(); // 120
//! piCout << PIString("0.01").toLDouble(); // 0.01
//! \endcode
ldouble toLDouble() const;
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const short value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const int value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const long value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" in base "base" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" по основанию "base" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(123);
//! piCout << s; // 123
//! s.setNumber(123, 16);
//! piCout << s; // 7B
//! \endcode
PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {*this = PIString::fromNumber(value, base, ok); return *this;}
//! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(12.3);
//! piCout << s; // 12.30000000
//! s.setNumber(12.3, 'f', 3);
//! piCout << s; // 12.300
//! s.setNumber(12.123456, 'f', 3);
//! piCout << s; // 12.123
//! s.setNumber(123456789., 'g', 2);
//! piCout << s; // 1.2e+08
//! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789
//! \endcode
PIString & setNumber(const float value, char format = 'f', int precision = 8) {*this = PIString::fromNumber(value, format, precision); return *this;}
//! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(12.3);
//! piCout << s; // 12.30000000
//! s.setNumber(12.3, 'f', 3);
//! piCout << s; // 12.300
//! s.setNumber(12.123456, 'f', 3);
//! piCout << s; // 12.123
//! s.setNumber(123456789., 'g', 2);
//! piCout << s; // 1.2e+08
//! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789
//! \endcode
PIString & setNumber(const double & value, char format = 'f', int precision = 8) {*this = PIString::fromNumber(value, format, precision); return *this;}
//! \~english Set string content to text representation of "value" with format "format" and precision "precision" and return this string.
//! \~russian Устанавливает содержимое строки в текстовое представление "value" в формате "format" и точностью "precision" и возвращает эту строку.
//! \~\details
//! \~\code
//! PIString s;
//! s.setNumber(12.3);
//! piCout << s; // 12.30000000
//! s.setNumber(12.3, 'f', 3);
//! piCout << s; // 12.300
//! s.setNumber(12.123456, 'f', 3);
//! piCout << s; // 12.123
//! s.setNumber(123456789., 'g', 2);
//! piCout << s; // 1.2e+08
//! s.setNumber(123456789., 'f', 0);
//! piCout << s; // 123456789
//! \endcode
PIString & setNumber(const ldouble & value, char format = 'f', int precision = 8) {*this = PIString::fromNumber(value, format, precision); return *this;}
//! \~english Set string content to human readable size in B/kB/MB/GB/TB/PB.
//! \~russian Устанавливает содержимое в строку с читаемым размером B/kB/MB/GB/TB/PB.
//! \~\sa PIString::readableSize()
PIString & setReadableSize(llong bytes);
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);}
//! \~english Returns string contains numeric representation of "value" in base "base".
//! \~russian Возвращает строковое представление числа "value" по основанию "base".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(123); // 123
//! piCout << PIString::fromNumber(123, 16); // 7B
//! \endcode
static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);}
//! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision".
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000
//! piCout << PIString::fromNumber(12.3, 'f', 3); // 12.300
//! piCout << PIString::fromNumber(12.123456, 'f', 3); // 12.123
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \endcode
static PIString fromNumber(const float value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
//! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision".
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000
//! piCout << PIString::fromNumber(12.3, 'f', 3); // 12.300
//! piCout << PIString::fromNumber(12.123456, 'f', 3); // 12.123
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \endcode
static PIString fromNumber(const double & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
//! \~english Returns string contains numeric representation of "value" with format "format" and precision "precision".
//! \~russian Возвращает строковое представление числа "value" в формате "format" и точностью "precision".
//! \~\details
//! \~\code
//! piCout << PIString::fromNumber(12.3); // 12.30000000
//! piCout << PIString::fromNumber(12.3, 'f', 3); // 12.300
//! piCout << PIString::fromNumber(12.123456, 'f', 3); // 12.123
//! piCout << PIString::fromNumber(123456789., 'g', 2); // 1.2e+08
//! piCout << PIString::fromNumber(123456789., 'f', 0); // 123456789
//! \endcode
static PIString fromNumber(const ldouble & value, char format = 'f', int precision = 8) {return dtos(value, format, precision);}
//! \~english Returns "true" or "false"
//! \~russian Возвращает "true" или "false"
static PIString fromBool(const bool value) {return PIString(value ? PIStringAscii("true") : PIStringAscii("false"));}
//! \~english Returns string constructed from terminal codepage.
//! \~russian Возвращает строку созданную из кодировки консоли.
static PIString fromConsole(const PIByteArray & s);
//! \~english Returns string constructed from terminal codepage.
//! \~russian Возвращает строку созданную из кодировки консоли.
static PIString fromConsole(const char * s);
//! \~english Returns string constructed from system codepage.
//! \~russian Возвращает строку созданную из кодировки системы.
static PIString fromSystem(const PIByteArray & s);
//! \~english Returns string constructed from system codepage.
//! \~russian Возвращает строку созданную из кодировки системы.
static PIString fromSystem(const char * s);
//! \~english Returns string constructed from UTF-8.
//! \~russian Возвращает строку созданную из UTF-8.
static PIString fromUTF8(const char * s);
//! \~english Returns string constructed from UTF-8.
//! \~russian Возвращает строку созданную из UTF-8.
static PIString fromUTF8(const PIByteArray & utf);
//! \~english Returns string constructed from ASCII.
//! \~russian Возвращает строку созданную из ASCII.
static PIString fromAscii(const char * s);
//! \~english Returns string constructed from "len" chars ASCII.
//! \~russian Возвращает строку созданную из "len" символов ASCII.
static PIString fromAscii(const char * s, int len);
//! \~english Returns string constructed from "cp" codepage.
//! \~russian Возвращает строку созданную из кодировки "cp".
static PIString fromCodepage(const char * s, const char * cp);
//! \~english Returns string contains human readable size in B/kB/MB/GB/TB/PB.
//! \~russian Возвращает строку с читаемым размером B/kB/MB/GB/TB/PB.
//! \~\sa PIString::setReadableSize()
static PIString readableSize(llong bytes);
//! \~english Swaps string `str` other with this string.
//! \~russian Меняет строку `str` с этой строкой.
//! \~\details
//! \~english This operation is very fast and never fails.
//! \~russian Эта операция выполняется мгновенно без копирования памяти и никогда не дает сбоев.
void swap(PIString & str) {
d.swap(str.d);
piSwap(data_, str.data_);
}
private:
static const char toBaseN[];
static const char 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 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 deleteData() const;
void trimsubstr(int &st, int &fn) const;
PIDeque<PIChar> d;
mutable char * data_ = nullptr;
};
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIString) {s << v.d; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIString) {s >> v.d; return s;}
//! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк.
inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;}
//! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк.
inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;}
//! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк.
inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;}
//! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк.
inline PIString operator +(const char c, const PIString & f) {return PIString(c) + f;}
//! \~english Returns concatenated string.
//! \~russian Возвращает соединение строк.
inline PIString operator +(const PIString & f, const char c) {PIString s(f); s.push_back(c); return s;}
//! \relatesalso PIString
//! \~english Compare two version strings in free notation and returns 0, -1 or 1.
//! \~russian Сравнивает две строки с версиями в произвольной форме и возвращает 0, -1 или 1.
int PIP_EXPORT versionCompare(const PIString & v0, const PIString & v1, int components = 6);
//! \relatesalso PIString
//! \~english Converts version string in free notation to classic view.
//! \~russian Преобразует строку с версией в произвольной форме к классическому виду.
PIString PIP_EXPORT versionNormalize(const PIString & v);
template<> inline uint piHash(const PIString & s) {return s.hash();}
template<> inline void piSwap(PIString & f, PIString & s) {
f.swap(s);
}
#endif // PISTRING_H

View File

@@ -1,131 +0,0 @@
/*! \file pistring_std.h
* \ingroup Core
* \brief
* \~english STD convertions for PIString
* \~russian Преобразования в/из STD для строки
*/
/*
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;
ushort wc;
uchar tc;
if (v.size() > 0) {
for (int i = 0; i < v.length(); ++i) {
wc = v[i].unicode16Code();
while (tc = wc & 0xFF, tc) {
s.push_back(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[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(PIChar(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

View File

@@ -1,110 +0,0 @@
/*
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"
//! \~\class PIStringList pistringlist.h
//! \~\details
//!
//! \details
//! \~english Example:
//! \~russian Пример:
//! \~\code
//! PIStringList sl("1", "2");
//! sl << "3";
//! piCout << sl.join(" < "); // 1 < 2 < 3
//! \endcode
PIString PIStringList::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;
}
//! \details
//! \~english Example:
//! \~russian Пример:
//! \~\code
//! PIStringList sl("1", "2");
//! sl << "1" << "2" << "3";
//! piCout << sl; // {"1", "2", "1", "2", "3"}
//! piCout << sl.removeStrings("1"); // {"2", "2", "3"}
//! \endcode
PIStringList & PIStringList::removeStrings(const PIString & value) {
for (uint i = 0; i < size(); ++i) {
if (at(i) == value) {
remove(i);
--i;
}
}
return *this;
}
//! \details
//! \~english Example:
//! \~russian Пример:
//! \~\code
//! PIStringList sl("1", "2");
//! sl << "1" << "2" << "3";
//! piCout << sl; // {"1", "2", "1", "2", "3"}
//! piCout << sl.removeDuplicates(); // {"1", "2", "3"}
//! \endcode
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;
}
//! \details
//! \~english Example:
//! \~russian Пример:
//! \~\code
//! PIStringList sl(" 1 ", "\t2", " 3\n");
//! piCout << sl; // {" 1 ", " 2", " 3\n"}
//! piCout << sl.trim(); // {"1", "2", "3"}
//! \endcode
PIStringList & PIStringList::trim() {
for (uint i = 0; i < size(); ++i)
(*this)[i].trim();
return *this;
}

View File

@@ -1,151 +0,0 @@
/*! \file pistringlist.h
* \ingroup Core
* \~\brief
* \~english Based on \a PIDeque<PIString> strings list
* \~russian Основанный на \a PIDeque<PIString> массив строк
*/
/*
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"
//! \ingroup Core
//! \~\brief
//! \~english Based on \a PIDeque<PIString> strings list.
//! \~russian Основанный на \a PIDeque<PIString> массив строк.
class PIP_EXPORT PIStringList: public PIDeque<PIString>
{
public:
//! \~english Contructs an empty strings list
//! \~russian Создает пустой список строк
PIStringList() {;}
//! \~english Contructs strings list with one string "str"
//! \~russian Создает список строк с одной строкой "str"
PIStringList(const PIString & str) {push_back(str);}
PIStringList(PIString && str) {push_back(std::move(str));}
//! \~english Contructs strings list with strings "s0" and "s1"
//! \~russian Создает список строк со строками "s0" и "s1"
PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);}
PIStringList(PIString && s0, PIString && s1) {push_back(std::move(s0)); push_back(std::move(s1));}
//! \~english Contructs strings list with strings "s0", "s1" and "s2"
//! \~russian Создает список строк со строками "s0", "s1" и "s2"
PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);}
PIStringList(PIString && s0, PIString && s1, PIString && s2) {push_back(std::move(s0)); push_back(std::move(s1)); push_back(std::move(s2));}
//! \~english Contructs strings list with strings "s0", "s1", "s2" and "s3"
//! \~russian Создает список строк со строками "s0", "s1", "s2" и "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(PIString && s0, PIString && s1, PIString && s2, PIString && s3) {push_back(std::move(s0)); push_back(std::move(s1)); push_back(std::move(s2)); push_back(std::move(s3));}
//! \~english Contructs strings list with strings "o"
//! \~russian Создает список строк со строками "o"
PIStringList(const PIStringList & o): PIDeque<PIString>(o) {}
PIStringList(PIStringList && o): PIDeque<PIString>(std::move(o)) {}
//! \~english Contructs strings list with strings "o"
//! \~russian Создает список строк со строками "o"
PIStringList(const PIVector<PIString> & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
//! \~english Contructs strings list with strings "o"
//! \~russian Создает список строк со строками "o"
PIStringList(const PIDeque<PIString> & o): PIDeque<PIString>() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];}
//! \~english Contructs strings list with strings "init_list" in std::initializer_list format
//! \~russian Создает список строк со строками "init_list" в формате std::initializer_list
PIStringList(std::initializer_list<PIString> init_list): PIDeque<PIString>(init_list) {}
//! \~english Join all strings in one with delimiter "delim" and returns it
//! \~russian Соединяет все строки в одну через разделитель "delim" и возвращает её
PIString join(const PIString & delim) const;
//! \~english Remove all strings equal "value" and returns reference to this
//! \~russian Удаляет все строки равные "value" и возвращает ссылку на этот список строк
PIStringList & removeStrings(const PIString & value);
PIStringList & remove(uint num) {PIDeque<PIString>::remove(num); return *this;}
PIStringList & remove(uint num, uint count) {PIDeque<PIString>::remove(num, count); return *this;}
//! \~english Remove duplicated strings and returns reference to this
//! \~russian Удаляет все дублированные строки и возвращает ссылку на этот список строк
PIStringList & removeDuplicates();
//! \~english Trim all strings and returns reference to this
//! \~russian Подчищает у всех строк пробельные символы в начале и в конце и возвращает ссылку на этот список строк
PIStringList & trim();
//! \~english Returns sum of lengths of all strings
//! \~russian Возвращает сумму длин всех строк
uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;}
//! \~english Compare operator
//! \~russian Оператор сравнения
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;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const PIStringList & o) const {return !(o == (*this));}
//! \~english Assign operator
//! \~russian Оператор присваивания
PIStringList & operator =(const PIStringList & o) {PIDeque<PIString>::operator=(o); return *this;}
//! \~english Append string "str"
//! \~russian Добавляет строку "str"
PIStringList & operator <<(const PIString & str) {append(str); return *this;}
PIStringList & operator <<(PIString && str) {append(std::move(str)); return *this;}
//! \~english Append strings list "sl"
//! \~russian Добавляет список строк "sl"
PIStringList & operator <<(const PIStringList & sl) {append(sl); return *this;}
};
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIStringList) {
s << static_cast<const PIDeque<PIString> &>(v);
return s;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIStringList) {
s >> static_cast<PIDeque<PIString> &>(v);
return s;
}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.saveAndSetControls(0); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << "\"" << v[i] << "\""; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControls(); return s;}
#endif // PISTRINGLIST_H

View File

@@ -1,219 +0,0 @@
/*
PIP - Platform Independent Primitives
Unix time
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 "pisystemtime.h"
#include "pitime.h"
#include <ctime>
#ifdef QNX
# include <time.h>
#endif
#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;}
#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 MICRO_PIP
# include <sys/time.h>
#endif
//! \class PISystemTime pisystemtime.h
//! \details
//! \~english \section PISystemTime_sec0 Synopsis
//! \~russian \section PISystemTime_sec0 Краткий обзор
//! \~english
//! 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.
//!
//! \~russian
//! Этот класс предоставляет арифметику для системного времени в формате POSIX.
//! Это время представлено в виде целочисленных секунд и наносекунд.
//! Можно взять текущее время с помощью метода \a PISystemTime::current(),
//! сравнивать, суммировать и вычитать времена, преобразовывать в/из
//! секунд, миллисекунд, микросекунд и наносекунд.
//!
//! \~english \section PISystemTime_sec1 Example
//! \~russian \section PISystemTime_sec1 Пример
//! \~\snippet pitimer.cpp system_time
//!
//! \class PITimeMeasurer pisystemtime.h
//! \details
//! \~english \section PITimeMeasurer_sec0 Usage
//! \~russian \section PITimeMeasurer_sec0 Использование
//! \~english
//! 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"
//!
//! \~russian
//! Метод \a reset() устанавливает текущую метку системного времени. Далее методы
//! "double elapsed_*()" возвращают время, прошедшее от установленной метки.
//! Эти методы возвращают нано, микро, милли и секунды с приставками
//! "n", "u", "m" и "s".
//!
//! \details
//! \warning
//! \~english
//! 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
//! \~russian
//! Используйте этот метод для ожидания разниц системных времен или своего времени.
//! Если метод будет вызван для системного времени \a PISystemTime::current(), то
//! ожидание будет почти бесконечным
void PISystemTime::sleep() {
piUSleep(piFloord(toMicroseconds()));
}
void PISystemTime::toTimespec(void * ts) {
#ifndef WINDOWS
((timespec*)ts)->tv_sec = seconds;
((timespec*)ts)->tv_nsec = nanoseconds;
#endif
}
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);
}
#elif defined(MAC_OS)
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
#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;
# endif
#else
timespec t_cur;
clock_gettime(precise_but_not_system ? CLOCK_MONOTONIC : 0, &t_cur);
#endif
#ifndef WINDOWS
return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec);
#endif
}
PITimeMeasurer::PITimeMeasurer() {
reset();
}
double PITimeMeasurer::elapsed_n() const {
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()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+3
#endif
;
}
double PITimeMeasurer::elapsed_m() const {
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()
#ifndef MICRO_PIP
- PISystemTests::time_elapsed_ns / 1.E+9
#endif
;
}
PISystemTime PITimeMeasurer::elapsed() const {
return (PISystemTime::current(true) - t_st);
}

View File

@@ -1,253 +0,0 @@
/*! \file pisystemtime.h
* \ingroup Core
* \~\brief
* \~english System time structs and methods
* \~russian Типы и методы системного времени
*/
/*
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 PISYSTEMTIME_H
#define PISYSTEMTIME_H
#include "pistring.h"
//! \ingroup Core
//! \~\brief
//! \~english System time with nanosecond precision.
//! \~russian Системное время с точностью до наносекунд.
class PIP_EXPORT PISystemTime {
public:
//! \~english Contructs time with seconds and nanoseconds = 0
//! \~russian Создает время с секундами и наносекундами = 0
PISystemTime() {seconds = nanoseconds = 0;}
//! \~english Contructs time with "s" seconds and "ns" nanoseconds
//! \~russian Создает время с секундами "s" и наносекундами "ns"
PISystemTime(int s, int ns) {seconds = s; nanoseconds = ns; checkOverflows();}
//! \~english Returns time value in seconds
//! \~russian Возвращает значение времени в секундах
double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;}
//! \~english Returns time value in milliseconds
//! \~russian Возвращает значение времени в миллисекундах
double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;}
//! \~english Returns time value in microseconds
//! \~russian Возвращает значение времени в микросекундах
double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;}
//! \~english Returns time value in nanoseconds
//! \~russian Возвращает значение времени в наносекундах
double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);}
//! \~english Add to time "v" seconds
//! \~russian Добавляет ко времени "v" секунд
PISystemTime & addSeconds(double v) {*this += fromSeconds(v); return *this;}
//! \~english Add to time "v" milliseconds
//! \~russian Добавляет ко времени "v" миллисекунд
PISystemTime & addMilliseconds(double v) {*this += fromMilliseconds(v); return *this;}
//! \~english Add to time "v" microseconds
//! \~russian Добавляет ко времени "v" микросекунд
PISystemTime & addMicroseconds(double v) {*this += fromMicroseconds(v); return *this;}
//! \~english Add to time "v" nanoseconds
//! \~russian Добавляет ко времени "v" наносекунд
PISystemTime & addNanoseconds(double v) {*this += fromNanoseconds(v); return *this;}
//! \~english Sleep for this time
//! \~russian Ожидать это время
void sleep();
//! \~english On *nix system assign current value to timespec struct
//! \~russian На *nix системах присваивает время к timespec структуре
void toTimespec(void * ts);
//! \~english Returns copy of this time with absolutely values of s and ns
//! \~russian Возвращает копию времени с модулем значения
PISystemTime abs() const;
//! \~english Returns sum of this time with "t"
//! \~russian Возвращает сумму этого времени с "t"
PISystemTime operator +(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;}
//! \~english Returns difference between this time and "t"
//! \~russian Возвращает разницу между этим временем и "t"
PISystemTime operator -(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;}
//! \~english Returns multiplication between this time and "t"
//! \~russian Возвращает это временя умноженное на "t"
PISystemTime operator *(const double & v) const {return fromMilliseconds(toMilliseconds() * v);}
//! \~english Returns division between this time and "t"
//! \~russian Возвращает это временя поделённое на "t"
PISystemTime operator /(const double & v) const {return fromMilliseconds(toMilliseconds() / v);}
//! \~english Add to time "t"
//! \~russian Добавляет ко времени "t"
PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;}
//! \~english Subtract from time "t"
//! \~russian Вычитает из времени "t"
PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;}
//! \~english Multiply time by "v"
//! \~russian Умножает время на "v"
PISystemTime & operator *=(const double & v) {*this = fromMilliseconds(toMilliseconds() * v); return *this;}
//! \~english Divide time by "v"
//! \~russian Делит время на "v"
PISystemTime & operator /=(const double & v) {*this = fromMilliseconds(toMilliseconds() / v); return *this;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator ==(const PISystemTime & t) const {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator !=(const PISystemTime & t) const {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator >=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;}
//! \~english Compare operator
//! \~russian Оператор сравнения
bool operator <=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;}
//! \~english Contructs time from seconds "v"
//! \~russian Создает время из "v" секунд
static PISystemTime fromSeconds(double v) {int s = piFloord(v); return PISystemTime(s, int((v - s) * 1000000000.));}
//! \~english Contructs time from milliseconds "v"
//! \~russian Создает время из "v" миллисекунд
static PISystemTime fromMilliseconds(double v) {int s = piFloord(v / 1000.); return PISystemTime(s, int((v / 1000. - s) * 1000000000.));}
//! \~english Contructs time from microseconds "v"
//! \~russian Создает время из "v" микросекунд
static PISystemTime fromMicroseconds(double v) {int s = piFloord(v / 1000000.); return PISystemTime(s, int((v / 1000000. - s) * 1000000000.));}
//! \~english Contructs time from nanoseconds "v"
//! \~russian Создает время из "v" наносекунд
static PISystemTime fromNanoseconds(double v) {int s = piFloord(v / 1000000000.); return PISystemTime(s, int((v / 1000000000. - s) * 1000000000.));}
//! \~english Returns current system time
//! \~russian Возвращает текущее системное время
static PISystemTime current(bool precise_but_not_system = false);
//! \~english Seconds time part
//! \~russian Секунды времени
int seconds;
//! \~english Nanoseconds time part
//! \~russian Наносекунды времени
int nanoseconds;
private:
void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}}
};
//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout
inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.saveAndSetControls(0); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControls(); return s;}
//! \ingroup Core
//! \~\brief
//! \~english Time measurements.
//! \~russian Измерение времени.
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

View File

@@ -1,341 +0,0 @@
/*! \file pitextstream.h
* \ingroup Core
* \~\brief
* \~english Text serialization functionality over PIBinaryStream
* \~russian Функциональность текстовой сериализации поверх PIBinaryStream
*/
/*
PIP - Platform Independent Primitives
Text serialization functionality over PIBinaryStream
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 PITEXTSTREAM_H
#define PITEXTSTREAM_H
#include "pistring.h"
//! \ingroup Core
//! \~\brief
//! \~english Text serialization functionality over PIBinaryStream.
//! \~russian Функциональность текстовой сериализации поверх PIBinaryStream.
template<typename P>
class PITextStream {
public:
//! \~english Floating-point numbers write format
//! \~russian Формат записи чисел с плавающей точкой
enum FloatFormat {
DecimalFormat /** \~english Decimal format, "*.*" \~russian Десятичный формат, "*.*" */ = 'f',
ExponentFormat /** \~english Exponential format, "*e+-<E>" \~russian Экспонентный формат, "*e+-<E>" */ = 'e'
};
//! \~english String encoding
//! \~russian Кодировка строк
enum Encoding {
System /** \~english System encoding \~russian Системная кодировка */,
UTF8 /** \~english UTF-8 encoding \~russian Кодировка UTF-8 */,
};
//! \~english Construct text stream binded to "stream_"
//! \~russian Возвращает привязанный к "stream_" текстовый поток
PITextStream(PIBinaryStream<P> * stream_) {setStream(stream_);}
//! \~english Returns binded PIBinaryStream
//! \~russian Возвращает привязанный PIBinaryStream
PIBinaryStream<P> * stream() const {return s;}
void setStream(PIBinaryStream<P> * stream_) {
s = stream_;
is_end = false;
}
//! \~english Returns if end of stream reached
//! \~russian Возвращает достигнут ли конец потока
bool isEnd() const {return is_end;}
//! \~english Returns read/write encoding
//! \~russian Возвращает кодировку чтения/записи
Encoding encoding() const {return enc;}
//! \~english Set read/write encoding, default UTF8
//! \~russian Устанавливает кодировку чтения/записи, по умолчанию UTF8
void setEncoding(Encoding e) {enc = e;}
//! \~english Returns float numbers write format
//! \~russian Возвращает формат записи чисел с плавающей точкой
FloatFormat floatFormat() const {return format_;}
//! \~english Set float numbers write format, default DecimalFormat
//! \~russian Устанавливает формат записи чисел с плавающей точкой, по умолчанию DecimalFormat
void setFloatFormat(FloatFormat format) {format_ = format;}
//! \~english Returns float numbers write precision
//! \~russian Возвращает точность записи чисел с плавающей точкой
int floatPrecision() const {return prec_;}
//! \~english Set float numbers write precision to "prec_" digits, default 5
//! \~russian Устанавливает точность записи чисел с плавающей точкой, по умолчанию 5
void setFloatPrecision(int prec) {prec_ = prec;}
//! \~english Append space
//! \~russian Добавляет пробел
PITextStream<P> & space() {s->binaryStreamAppend(' '); return *this;}
//! \~english Append new line
//! \~russian Добавляет новую строку
PITextStream<P> & newLine() {s->binaryStreamAppend('\n'); return *this;}
//! \~english Append "v" string
//! \~russian Добавляет строку "v"
void append(const PIString & v) {
if (v.isEmpty()) return;
PIByteArray d;
switch (enc) {
case System: d = v.toSystem(); break;
case UTF8 : d = v.toUTF8(); break;
}
s->binaryStreamAppend(d.data(), d.size());
}
//! \~english Append "v" as ASCII
//! \~russian Добавляет "v" как ASCII
void append(const PIConstChars & v) {if (!v.isEmpty()) s->binaryStreamAppend(v.data(), v.size());}
//! \~english Append "v" char as character
//! \~russian Добавляет "v" как символ
void append(char v) {s->binaryStreamAppend(v);}
//! \~english Append "v" as ASCII
//! \~russian Добавляет "v" как ASCII
void append(const char * v) {append(PIConstChars(v));}
//! \~english Append boolean, "true" of "false"
//! \~russian Добавляет логическое, "true" of "false"
void append(bool v) {append(v ? "true" : "false");}
//! \~english Append integer
//! \~russian Добавляет целое
void append(int v) {append(PIString::fromNumber(v));}
//! \~english Append integer
//! \~russian Добавляет целое
void append(llong v) {append(PIString::fromNumber(v));}
//! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision()
//! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision()
void append(float v) {append(PIString::fromNumber(v, (char)format_, prec_));}
//! \~english Append floating-point number, using \a floatFormat() and \a floatPrecision()
//! \~russian Добавляет число с плавающей точкой, используя \a floatFormat() и \a floatPrecision()
void append(double v) {append(PIString::fromNumber(v, (char)format_, prec_));}
//! \~english Read character
//! \~russian Читает символ
char readChar(bool * rok) {
char ret;
bool ok = s->binaryStreamTake(&ret, sizeof(ret));
if (!ok) is_end = true;
if (rok) *rok = ok;
return ret;
}
//! \~english Read line
//! \~russian Читает строку
PIString readLine() {
PIByteArray ret;
bool ok = true;
for (;;) {
char b = readChar(&ok);
if (!ok || b == '\n') break;
if (b != '\r')
ret.append((uchar)b);
}
return fromBytes(ret);
}
//! \~english Read word, skip leading whitespaces, until next whitespace
//! \~russian Читает слово, пропуская начальные пробельные символы, до следующего пробельного символа
PIString readWord() {
static PIConstChars spaces(" \t\n\r");
return readUntil(spaces);
}
//! \~english Read C-word, skip leading and until non C-identifier
//! \~russian Читает C-слово, пропуская начальные и до следующих символов, не являющихся C-идентификаторами
PIString readCWord() {
static PIConstChars chars(" \t\n\r:;%$&#@!?~/*-+=.,\\\"'`[](){}<>");
return readUntil(chars);
}
private:
PIString fromBytes(const PIByteArray & ba) {
switch (enc) {
case System: return PIString::fromSystem(ba);
case UTF8 : return PIString::fromUTF8(ba);
}
return PIString();
}
PIString readUntil(const PIConstChars & chars) {
//static PIConstChars spaces(" \t\n\r");
bool ok = true;
char c = skipWhile(chars, &ok);
if (!ok) return PIString();
PIByteArray ret;
ret.append((uchar)c);
for (;;) {
c = readChar(&ok);
if (!ok || chars.contains(c)) break;
ret.append((uchar)c);
}
return fromBytes(ret);
}
// returns first non-"chars" char
char skipWhile(const PIConstChars & chars, bool * rok) {
bool ok = true;
char c = 0;
for (;;) {
c = readChar(&ok);
if (!ok || !chars.contains(c)) break;
}
if (rok) *rok = ok;
return c;
}
PIBinaryStream<P> * s;
Encoding enc = UTF8;
FloatFormat format_ = DecimalFormat;
bool is_end = false;
int prec_ = 5;
};
//! \~english Returns PITextStream for binary stream "stream"
//! \~russian Возвращает PITextStream для бинарного потока "stream"
template<typename P>
inline PITextStream<P> createPITextStream(PIBinaryStream<P> * stream) {return PITextStream<P>(stream);}
//! \~english Append boolean
//! \~russian Добавляет логическое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, bool v) {s.append(v); return s;}
//! \~english Append character
//! \~russian Добавляет символ
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, char v) {s.append(v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, uchar v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, short v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, ushort v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, int v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, uint v) {s.append((int)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, llong v) {s.append((llong)v); return s;}
//! \~english Append integer
//! \~russian Добавляет целое
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, ullong v) {s.append((llong)v); return s;}
//! \~english Append floating-point number
//! \~russian Добавляет число с плавающей точкой
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, float v) {s.append(v); return s;}
//! \~english Append floating-point number
//! \~russian Добавляет число с плавающей точкой
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, double v) {s.append(v); return s;}
//! \~english Append string
//! \~russian Добавляет строку
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const char * v) {s.append(v); return s;}
//! \~english Append string
//! \~russian Добавляет строку
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const PIConstChars & v) {s.append(v); return s;}
//! \~english Append string
//! \~russian Добавляет строку
template<typename P> inline PITextStream<P> & operator <<(PITextStream<P> & s, const PIString & v) {s.append(v); return s;}
//! \~english Read word as bool
//! \~russian Читает слово как логическое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, bool & v) {v = s.readWord().toBool(); return s;}
//! \~english Read character
//! \~russian Читает символ
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, char & v) {v = s.readChar(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, uchar & v) {v = s.readWord().toUInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, short & v) {v = s.readWord().toInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, ushort & v) {v = s.readWord().toUInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, int & v) {v = s.readWord().toInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, uint & v) {v = s.readWord().toUInt(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, llong & v) {v = s.readWord().toLLong(); return s;}
//! \~english Read word as integer
//! \~russian Читает слово как целое
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, ullong & v) {v = s.readWord().toULLong(); return s;}
//! \~english Read word as floating-point number
//! \~russian Читает слово как число с плавающей точкой
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, float & v) {v = s.readWord().toFloat(); return s;}
//! \~english Read word as floating-point number
//! \~russian Читает слово как число с плавающей точкой
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, double & v) {v = s.readWord().toDouble(); return s;}
//! \~english Read word
//! \~russian Читает слово
template<typename P> inline PITextStream<P> & operator >>(PITextStream<P> & s, PIString & v) {v = s.readWord(); return s;}
#endif

View File

@@ -1,61 +0,0 @@
/*
PIP - Platform Independent Primitives
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"
#ifdef QNX
# include <time.h>
#endif
#ifndef MICRO_PIP
# include "pisystemtests.h"
#elif defined(ARDUINO)
# include <Arduino.h>
#endif
#ifdef MICRO_PIP
# include <sys/time.h>
#endif
//! \details
//! \~english
//! This function consider \c "usleep" offset
//! on QNX/Linux/Mac, which is calculated with
//! \a pip_sys_test program. If this is correct
//! offset value in system config, this function
//! wait \b exactly "usecs" microseconds.
//! \~russian
//! Этот метод учитывает смещение \c "usleep"
//! на QNX/Linux/Mac, которое расчитывается с помощью
//! утилиты \a pip_sys_test. Если это значение в системном
//! конфиге действительно, то этот метод будет ожидать
//! \b точно "usecs" микросекунд.
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
}

View File

@@ -1,58 +0,0 @@
/*! \file pitime.h
* \ingroup Core
* \~\brief
* \~english System time, time and date
* \~russian Системное время, время и дата
*/
/*
PIP - Platform Independent Primitives
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 "pidatetime.h"
//! \ingroup Core
//! \~english Precise sleep for "usecs" microseconds
//! \~russian Точно ожидает "usecs" микросекунд
PIP_EXPORT void piUSleep(int usecs); // on !Windows consider constant "usleep" offset
//! \ingroup Core
//! \brief
//! \~english Precise sleep for "msecs" milliseconds
//! \~russian Точно ожидает "msecs" миллисекунд
//! \~\details
//! \~english This function exec \a piUSleep (msecs * 1000)
//! \~russian Этот метод вызывает \a piUSleep (msecs * 1000)
inline void piMSleep(double msecs) {piUSleep(int(msecs * 1000.));} // on !Windows consider constant "usleep" offset
//! \ingroup Core
//! \brief
//! \~english Precise sleep for "secs" seconds
//! \~russian Точно ожидает "secs" секунд
//! \~\details
//! \~english This function exec \a piUSleep (msecs * 1000000)
//! \~russian Этот метод вызывает \a piUSleep (msecs * 1000000)
inline void piSleep(double secs) {piUSleep(int(secs * 1000000.));} // on !Windows consider constant "usleep" offset
//! \ingroup Core
//! \~english Shortest available on current system sleep
//! \~russian Наименее возможное для данной системы по длительности ожидание
inline void piMinSleep() {piMSleep(PIP_MIN_MSLEEP);}
#endif // PITIME_H

View File

@@ -1,88 +0,0 @@
/*! \file pitime_win.h
* \ingroup Core
* \brief
* \~english PITime conversions for Windows
* \~russian Преобразования PITime для 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, &lt);
FileTimeToSystemTime(&lt, &st);
return SYSTEMTIME2PIDateTime(st);
}
inline SYSTEMTIME PIDateTime2SYSTEMTIME(const PIDateTime &dt) {
SYSTEMTIME st;
st.wYear = dt.year;
st.wMonth = dt.month;
st.wDay = dt.day;
st.wHour = dt.hours;
st.wMinute = dt.minutes;
st.wSecond = dt.seconds;
st.wMilliseconds = dt.milliseconds;
return st;
}
inline FILETIME PIDateTime2FILETIME(const PIDateTime &dt) {
FILETIME lt, ret;
SYSTEMTIME st = PIDateTime2SYSTEMTIME(dt);
SystemTimeToFileTime(&st, &lt);
LocalFileTimeToFileTime(&lt, &ret);
return ret;
}
#endif // WINDOWS
#endif // PITIME_WIN_H

View File

@@ -1,939 +0,0 @@
/*
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 pivariant.h
//! \details
//! \~english \section PIVariant_sec0 Synopsis
//! \~russian \section PIVariant_sec0 Краткий обзор
//! \~english
//! 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.
//!
//! \~russian
//! Этот класс предоставляет некий общий тип, который может содержать все стандартные тип,
//! некоторые типы PIP, а также любой свой тип. В случае стандартных типов предоставляется
//! автоматическое преобразование между ними.
//!
//! \~english \section PIVariant_sec1 Usage
//! \~russian \section PIVariant_sec1 Использование
//! \~english
//! %PIVariant useful if you want pass many variables with different types in
//! single array, or type may vary from case to case, e.g.:
//!
//! \~russian
//! %PIVariant полезен когда надо передать несколько разнотипных значений
//! одним массивом, или тип заранее неизвестен, например:
//!
//! \~\code{cpp}
//! PIVector<PIVariant> array;
//! array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
//! piCout << array;
//! for (auto i: array)
//! piCout << i.toInt();
//! \endcode
//!
//! \~english Result:
//! \~russian Результат:
//! \~\code{cpp}
//! {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
//! 10
//! 1
//! 1
//! 255
//! \endcode
//!
#ifdef CUSTOM_PIVARIANT
PIMap<PIString, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = 0;
#endif
PIVariant::PIVariant() {
_type = PIVariant::pivInvalid;
_info = 0;
}
PIVariant::PIVariant(const PIVariant & v) {
_type = v._type;
_content = v._content;
#ifdef CUSTOM_PIVARIANT
_info = v._info;
#endif
}
PIVariant::PIVariant(PIVariant && v) {
swap(v);
}
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;
}
PIVariant & PIVariant::operator =(PIVariant && v) {
swap(v);
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;
if (s == "line") return PIVariant::pivLine;
if (s == "device" || s == "iodevice") return PIVariant::pivIODevice;
return PIVariant::pivInvalid;
}
PIString PIVariant::typeName() const {
#ifdef CUSTOM_PIVARIANT
if ((_type == pivCustom) && _info)
return _info->typeName;
#endif
return typeName(_type);
}
void PIVariant::swap(PIVariant & v) {
piSwap(_type, v._type);
_content.swap(v._content);
#ifdef CUSTOM_PIVARIANT
piSwap(_info, v._info);
#endif
}
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
//! \~english Returns variant content as boolean
//! \~russian Возвращает содержимое как boolean
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для численных типов возвращает \b true если значение != 0. \n
//! Для типа String возвращает \a PIString::toBool(). \n
//! Для типа StringList возвращает \b false если массив пустой, \n
//! иначе возвращает \a PIString::toBool() первой строки. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as int
//! \~russian Возвращает содержимое как int
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для численных типов возвращает целочисленное значение. \n
//! Для типа String возвращает \a PIString::toInt(). \n
//! Для типа StringList возвращает \b 0 если массив пустой, \n
//! иначе возвращает \a PIString::toInt() первой строки. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as long long
//! \~russian Возвращает содержимое как long long
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для численных типов возвращает целочисленное значение. \n
//! Для типа String возвращает \a PIString::toLLong(). \n
//! Для типа StringList возвращает \b 0L если массив пустой, \n
//! иначе возвращает \a PIString::toLLong() первой строки. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as float
//! \~russian Возвращает содержимое как float
//!
//! \~\details
//! \~english
//! 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 .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toFloat(). \n
//! Для типа StringList возвращает \b 0.f если массив пустой, \n
//! иначе возвращает \a PIString::toFloat() первой строки. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as double
//! \~russian Возвращает содержимое как double
//!
//! \~\details
//! \~english
//! 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. .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toDouble(). \n
//! Для типа StringList возвращает \b 0. если массив пустой, \n
//! иначе возвращает \a PIString::toDouble() первой строки. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as long double
//! \~russian Возвращает содержимое как long double
//!
//! \~\details
//! \~english
//! 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. .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toLDouble(). \n
//! Для типа StringList возвращает \b 0. если массив пустой, \n
//! иначе возвращает \a PIString::toLDouble() первой строки. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as time
//! \~russian Возвращает содержимое как время
//!
//! \~\details
//! \~english
//! 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().
//!
//! \~russian
//! Для типа Time возвращает время. \n
//! Для типа DateTime возвращает часть времени. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as date
//! \~russian Возвращает содержимое как дата
//!
//! \~\details
//! \~english
//! 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().
//!
//! \~russian
//! Для типа Date возвращает дату. \n
//! Для типа DateTime возвращает часть даты. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as date and time
//! \~russian Возвращает содержимое как дата и время
//!
//! \~\details
//! \~english
//! 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().
//!
//! \~russian
//! Для типа Time возвращает время без даты. \n
//! Для типа Date возвращает дату без времени. \n
//! Для типа DateTime возвращает время и дату. \n
//! Для остальных типов возвращает \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
//! \~english Returns variant content as system time
//! \~russian Возвращает содержимое как системное время
//!
//! \~\details
//! \~english
//! In case of SystemTime type returns system time. \n
//! In case of other types returns \a PISystemTime::fromSeconds() from \a toDouble().
//!
//! \~russian
//! Для типа SystemTime возвращает системное время. \n
//! Для остальных типов возвращает \a PISystemTime::fromSeconds() от \a toDouble().
//!
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
//! \~english Returns variant content as string
//! \~russian Возвращает содержимое как строка
//!
//! \~\details
//! \~english
//! 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 "".
//!
//! \~russian
//! Для численных типов возвращает \a PIString::fromNumber(). \n
//! Для типа String возвращает строку. \n
//! Для типа StringList возвращает объединенную строку ("(" + PIStringList::join("; ") + ")"). \n
//! Для типов BitArray или ByteArray возвращает количество бит/байт. \n
//! Для типов Time, Date или DateTime возвращает toString(). \n
//! Для типов SystemTime возвращает секунды и наносекунды в формате "(s, ns)".
//! Для остальных типов возвращает \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
//! \~english Returns variant content as strings list
//! \~russian Возвращает содержимое как массив строк
//!
//! \~\details
//! \~english
//! In case of StringList type returns strings list value. \n
//! In case of other types returns \a PIStringList with one string \a toString().
//!
//! \~russian
//! Для типа StringList возвращает массив строк. \n
//! Для остальных типов возвращает \a PIStringList с одной строкой \a toString().
//!
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
//! \~english Returns variant content as bit array
//! \~russian Возвращает содержимое как массив битов
//!
//! \~\details
//! \~english
//! In case of BitArray type returns bit array value. \n
//! In case of other types returns \a PIBitArray from \a toLLong() value.
//!
//! \~russian
//! Для типа BitArray возвращает массив битов. \n
//! Для остальных типов возвращает \a PIBitArray от значения \a toLLong().
//!
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
//! \~english Returns variant content as byte array
//! \~russian Возвращает содержимое как массив байтов
//!
//! \~\details
//! \~english
//! In case of ByteArray type returns byte array value. \n
//! In case of other types returns empty \a PIByteArray.
//!
//! \~russian
//! Для типа ByteArray возвращает массив байтов. \n
//! Для остальных типов возвращает пустой \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
//! \~english Returns variant content as enum
//! \~russian Возвращает содержимое как перечисление
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для типа Enum возвращает перечисление. \n
//! Для типа String возвращает Enum с одним членом. \n
//! Для типа StringList возвращает Enum с членами по строкам. \n
//! Для остальных типов возвращает пустой 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
//! \~english Returns variant content as file
//! \~russian Возвращает содержимое как файл
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для типа File возвращает файл. \n
//! Для типа String возвращает File с путем значения строки. \n
//! Для остальных типов возвращает пустой 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
//! \~english Returns variant content as dir
//! \~russian Возвращает содержимое как директория
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для типа Dir возвращает директорию. \n
//! Для типа String возвращает Dir с путем значения строки. \n
//! Для остальных типов возвращает пустой 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
//! \~english Returns variant content as color
//! \~russian Возвращает содержимое как цвет
//!
//! \~\details
//! \~english
//! 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.
//!
//! \~russian
//! Для типа Color возвращает цвет. \n
//! Для типа Int возвращает цвет с целочисленным значением. \n
//! Для остальных типов возвращает пустой 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
//! \~english Returns variant content as IODevice
//! \~russian Возвращает содержимое как IODevice
//!
//! \~\details
//! \~english
//! In case of IODevice type returns IODevice value. \n
//! In case of other types returns empty IODevice.
//!
//! \~russian
//! Для типа IODevice возвращает IODevice. \n
//! Для остальных типов возвращает пустой IODevice.
//!
PIVariantTypes::IODevice PIVariant::toIODevice() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivIODevice) {PIVariantTypes::IODevice r; ba >> r; return r;}
return PIVariantTypes::IODevice();
}
//! \~\brief
//! \~english Returns variant content as point
//! \~russian Возвращает содержимое как точка
//!
//! \~\details
//! \~english
//! In case of Point type returns point value. \n
//! In case of other types returns empty PIPointd.
//!
//! \~russian
//! Для типа Point возвращает точку. \n
//! Для остальных типов возвращает пустую PIPointd.
//!
PIPointd PIVariant::toPoint() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivPoint) {PIPointd r; ba >> r; return r;}
return PIPointd();
}
//! \~\brief
//! \~english Returns variant content as rect
//! \~russian Возвращает содержимое как прямоугольник
//!
//! \~\details
//! \~english
//! In case of Rect type returns rect value. \n
//! In case of other types returns empty PIRectd.
//!
//! \~russian
//! Для типа Rect возвращает прямоугольник. \n
//! Для остальных типов возвращает пустой PIRectd.
//!
PIRectd PIVariant::toRect() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivRect) {PIRectd r; ba >> r; return r;}
return PIRectd();
}
//! \~\brief
//! \~english Returns variant content as line
//! \~russian Возвращает содержимое как линия
//!
//! \~\details
//! \~english
//! In case of Line type returns line value. \n
//! In case of other types returns empty PILined.
//!
//! \~russian
//! Для типа Line возвращает линию. \n
//! Для остальных типов возвращает пустую PILined.
//!
PILined PIVariant::toLine() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivLine) {PILined r; ba >> r; return r;}
return PILined();
}
//! \~\brief
//! \~english Returns variant content as math vector
//! \~russian Возвращает содержимое как вектор
//!
//! \~\details
//! \~english
//! In case of MathVector type returns rect value. \n
//! In case of other types returns empty PIMathVectord.
//!
//! \~russian
//! Для типа MathVector возвращает вектор. \n
//! Для остальных типов возвращает пустой PIMathVectord.
//!
PIMathVectord PIVariant::toMathVector() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivMathVector) {PIMathVectord r; ba >> r; return r;}
return PIMathVectord();
}
//! \~\brief
//! \~english Returns variant content as math matrix
//! \~russian Возвращает содержимое как матрица
//!
//! \~\details
//! \~english
//! In case of MathMatrix type returns rect value. \n
//! In case of other types returns empty PIMathMatrixd.
//!
//! \~russian
//! Для типа MathMatrix возвращает матрицу. \n
//! Для остальных типов возвращает пустую PIMathMatrixd.
//!
PIMathMatrixd PIVariant::toMathMatrix() const {
PIByteArray ba(_content);
if (_type == PIVariant::pivMathMatrix) {PIMathMatrixd r; ba >> r; return r;}
return PIMathMatrixd();
}

View File

@@ -1,1001 +0,0 @@
/*! \file pivariant.h
* \ingroup Core
* \brief
* \~english Variant type
* \~russian Вариативный тип
*/
/*
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 "piconstchars.h"
#include "pitime.h"
#include "pigeometry.h"
#include "pimathmatrix.h"
#ifdef DOXYGEN
//! \relatesalso PIVariant
//! \~\brief
//! \~english Macro to register type for using in %PIVariant
//! \~russian Макрос для регистрации типа для использования в %PIVariant
# define REGISTER_VARIANT(Typename)
//! \relatesalso PIVariant
//! \~\brief
//! \~english Macro to register type with namespace for using in %PIVariant
//! \~russian Макрос для регистрации типа с пространством имен для использования в %PIVariant
# define REGISTER_NS_VARIANT(Namespace, Typename)
#endif
#ifndef QNX
# define CUSTOM_PIVARIANT
#endif
#ifdef CUSTOM_PIVARIANT
template<typename T>
class __PIVariantFunctions__ {
public:
static PIString typeNameHelper() {return PIStringAscii("");}
static bool isSimpleHelper() {return false;}
template<typename C> static PIByteArray castHelper(PIByteArray ba) {return PIByteArray();}
template<typename C> static C castVariant(const T & v) {return C();}
};
struct PIP_EXPORT __PIVariantInfo__ {
__PIVariantInfo__() {
simple = false;
}
typedef PIByteArray(*castHelperFunc)(PIByteArray);
PIMap<PIString, castHelperFunc> cast;
PIString typeName;
bool simple;
};
template<typename T>
struct __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 __##classname##_PIVariantInitializer__ { \
public: \
__##classname##_PIVariantInitializer__(const PIString & name) { \
if (__PIVariantInfoStorage__::get()->map->contains(name)) \
return; \
__PIVariantInfo__ * vi = new __PIVariantInfo__(); \
vi->typeName = name; \
(*(__PIVariantInfoStorage__::get()->map))[name] = vi; \
} \
};
#define REGISTER_NS_VARIANT_CPP(ns, classname) \
template <typename T> \
class __##ns##classname##_PIVariantInitializer__ { \
public: \
__##ns##classname##_PIVariantInitializer__(const PIString & name) { \
if (__PIVariantInfoStorage__::get()->map->contains(name)) \
return; \
__PIVariantInfo__ * vi = new __PIVariantInfo__(); \
vi->typeName = name; \
(*(__PIVariantInfoStorage__::get()->map))[name] = vi; \
} \
};
#define INIT_VARIANT(classname) \
__##classname##_PIVariantInitializer__< classname > __##classname##_pivariant_initializer__(#classname);
#define INIT_NS_VARIANT(ns, classname) \
__##ns##classname##_PIVariantInitializer__< ns::classname > __##ns##classname##_pivariant_initializer__(#ns"::"#classname);
#define REGISTER_VARIANT(classname) \
REGISTER_VARIANT_H(classname) \
REGISTER_VARIANT_CPP(classname) \
static INIT_VARIANT(classname)
#define REGISTER_NS_VARIANT(ns, classname) \
REGISTER_NS_VARIANT_H(ns, classname) \
REGISTER_NS_VARIANT_CPP(ns, classname) \
static INIT_NS_VARIANT(ns, classname)
#define REGISTER_VARIANT_CAST_H(classname_from, classname_to) \
template<> template<> inline \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v);
#define REGISTER_VARIANT_CAST_CPP(classname_from, classname_to) \
template<> template<> inline \
PIByteArray __PIVariantFunctions__<classname_from>::castHelper<classname_to>(PIByteArray v) { \
classname_from f; v >> f; \
classname_to t = __PIVariantFunctions__<classname_from>::castVariant<classname_to>(f); \
PIByteArray ret; ret << t; \
return ret;} \
template <typename T, typename C> \
class __##classname_from##_##classname_to##_PIVariantCastInitializer__ { \
public: \
__##classname_from##_##classname_to##_PIVariantCastInitializer__(const PIString & name, const PIString & cname) { \
__PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(name, 0)); \
if (!vi) { \
piCout << "Warning! Using REGISTER_VARIANT_CAST("#classname_from", "#classname_to") before REGISTER_VARIANT("#classname_from"), ignore."; \
return; \
} \
vi->cast[cname] = __PIVariantFunctions__<classname_from>::castHelper<classname_to>; \
} \
}; \
static __##classname_from##_##classname_to##_PIVariantCastInitializer__< classname_from, classname_to > __##classname_from##_##classname_to##_pivariant_cast_initializer__(#classname_from, #classname_to); \
template<> template<> \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v)
#define REGISTER_VARIANT_CAST(classname_from, classname_to) \
REGISTER_VARIANT_CAST_H(classname_from, classname_to) \
REGISTER_VARIANT_CAST_CPP(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE(classname_from, classname_to) REGISTER_VARIANT_CAST(classname_from, classname_to) {return classname_to(v);}
#define REGISTER_VARIANT_CAST_SIMPLE_H(classname_from, classname_to) REGISTER_VARIANT_CAST_H(classname_from, classname_to)
#define REGISTER_VARIANT_CAST_SIMPLE_CPP(classname_from, classname_to) REGISTER_VARIANT_CAST_CPP(classname_from, classname_to) {return classname_to(v);}
#else
#define REGISTER_VARIANT_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
//! \ingroup Core
//! \~\brief
//! \~english Variant type.
//! \~russian Вариантный тип.
class PIP_EXPORT PIVariant {
friend PICout operator <<(PICout s, const PIVariant & v);
BINARY_STREAM_FRIEND(PIVariant);
public:
//! \~english Type of %PIVariant content
//! \~russian Тип содержимого %PIVariant
enum Type {
pivInvalid /** \~english Invalid type, default type of empty contructor \~russian Недействительный тип, также конструированный по умолчанию */ = 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<double> */ ,
pivRect /** PIRect<double> */ ,
pivIODevice /** PIVariantTypes::IODevice */ ,
pivMathVector /** PIMathVector<double> */ ,
pivMathMatrix /** PIMathMatrix<double> */ ,
pivLine /** PILine<double> */ ,
pivCustom /** \~english Custom \~russian Свой тип */ = 0xFF
};
//! \~english Construct \a pivInvalid %PIVariant
//! \~russian Создает \a pivInvalid %PIVariant
PIVariant();
//! \~english Contructs a copy of %PIVariant.
//! \~russian Создает копию %PIVariant.
PIVariant(const PIVariant & v);
//! \~english Move constructor.
//! \~russian Перемещающий конструктор.
PIVariant(PIVariant && v);
//! \~english Constructs %PIVariant from string
//! \~russian Создает %PIVariant из строки.
PIVariant(const char * v) {initType(PIString(v));}
//! \~english Constructs %PIVariant from boolean
//! \~russian Создает %PIVariant из логического значения.
PIVariant(const bool v) {initType(v);}
//! \~english Constructs %PIVariant from char
//! \~russian Создает %PIVariant из символа.
PIVariant(const char v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const uchar v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const short v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const ushort v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const int & v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const uint & v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const llong & v) {initType(v);}
//! \~english Constructs %PIVariant from integer
//! \~russian Создает %PIVariant из целого числа.
PIVariant(const ullong & v) {initType(v);}
//! \~english Constructs %PIVariant from float
//! \~russian Создает %PIVariant из вещественного числа.
PIVariant(const float & v) {initType(v);}
//! \~english Constructs %PIVariant from double
//! \~russian Создает %PIVariant из вещественного числа.
PIVariant(const double & v) {initType(v);}
//! \~english Constructs %PIVariant from long double
//! \~russian Создает %PIVariant из вещественного числа.
PIVariant(const ldouble & v) {initType(v);}
//! \~english Constructs %PIVariant from bit array
//! \~russian Создает %PIVariant из массива битов.
PIVariant(const PIBitArray & v) {initType(v);}
//! \~english Constructs %PIVariant from byte array
//! \~russian Создает %PIVariant из массива байтов.
PIVariant(const PIByteArray & v) {initType(v);}
//! \~english Constructs %PIVariant from string
//! \~russian Создает %PIVariant из строки.
PIVariant(const PIString & v) {initType(v);}
//! \~english Constructs %PIVariant from strings list
//! \~russian Создает %PIVariant из массива строк.
PIVariant(const PIStringList & v) {initType(v);}
//! \~english Constructs %PIVariant from time
//! \~russian Создает %PIVariant из времени.
PIVariant(const PITime & v) {initType(v);}
//! \~english Constructs %PIVariant from date
//! \~russian Создает %PIVariant из даты.
PIVariant(const PIDate & v) {initType(v);}
//! \~english Constructs %PIVariant from date and time
//! \~russian Создает %PIVariant из даты и времени.
PIVariant(const PIDateTime & v) {initType(v);}
//! \~english Constructs %PIVariant from system time
//! \~russian Создает %PIVariant из системного времени.
PIVariant(const PISystemTime & v) {initType(v);}
//! \~english Constructs %PIVariant from enum
//! \~russian Создает %PIVariant из перечисления.
PIVariant(const PIVariantTypes::Enum & v) {initType(v);}
//! \~english Constructs %PIVariant from file
//! \~russian Создает %PIVariant из файла.
PIVariant(const PIVariantTypes::File & v) {initType(v);}
//! \~english Constructs %PIVariant from dir
//! \~russian Создает %PIVariant из директории.
PIVariant(const PIVariantTypes::Dir & v) {initType(v);}
//! \~english Constructs %PIVariant from color
//! \~russian Создает %PIVariant из цвета.
PIVariant(const PIVariantTypes::Color & v) {initType(v);}
//! \~english Constructs %PIVariant from IODevice
//! \~russian Создает %PIVariant из IODevice.
PIVariant(const PIVariantTypes::IODevice & v) {initType(v);}
//! \~english Constructs %PIVariant from point
//! \~russian Создает %PIVariant из точки.
PIVariant(const PIPointd & v) {initType(v);}
//! \~english Constructs %PIVariant from rect
//! \~russian Создает %PIVariant из прямоугольника.
PIVariant(const PIRectd & v) {initType(v);}
//! \~english Constructs %PIVariant from line
//! \~russian Создает %PIVariant из линии.
PIVariant(const PILined & v) {initType(v);}
//! \~english Constructs %PIVariant from MathVector
//! \~russian Создает %PIVariant из MathVector.
PIVariant(const PIMathVectord & v) {initType(v);}
//! \~english Constructs %PIVariant from MathMatrix
//! \~russian Создает %PIVariant из MathMatrix.
PIVariant(const PIMathMatrixd & v) {initType(v);}
//! \~english Set variant content and type to string
//! \~russian Устанавливает значение и тип из строки
void setValue(const char * v) {setValue(PIString(v));}
//! \~english Set variant content and type to boolean
//! \~russian Устанавливает значение и тип из
void setValue(const bool v) {initType(v);}
//! \~english Set variant content and type to char
//! \~russian Устанавливает значение и тип из символа
void setValue(const char v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const uchar v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const short v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const ushort v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const int & v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const uint & v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const llong & v) {initType(v);}
//! \~english Set variant content and type to integer
//! \~russian Устанавливает значение и тип из целого числа
void setValue(const ullong & v) {initType(v);}
//! \~english Set variant content and type to float
//! \~russian Устанавливает значение и тип из вещественного числа
void setValue(const float & v) {initType(v);}
//! \~english Set variant content and type to double
//! \~russian Устанавливает значение и тип из вещественного числа
void setValue(const double & v) {initType(v);}
//! \~english Set variant content and type to long double
//! \~russian Устанавливает значение и тип из вещественного числа
void setValue(const ldouble & v) {initType(v);}
//! \~english Set variant content and type to bit array
//! \~russian Устанавливает значение и тип из массива битов
void setValue(const PIBitArray & v) {initType(v);}
//! \~english Set variant content and type to byte array
//! \~russian Устанавливает значение и тип из массива байтов
void setValue(const PIByteArray & v) {initType(v);}
//! \~english Set variant content and type to string
//! \~russian Устанавливает значение и тип из строки
void setValue(const PIString & v) {initType(v);}
//! \~english Set variant content and type to strings list
//! \~russian Устанавливает значение и тип из массива строк
void setValue(const PIStringList & v) {initType(v);}
//! \~english Set variant content and type to time
//! \~russian Устанавливает значение и тип из времени
void setValue(const PITime & v) {initType(v);}
//! \~english Set variant content and type to date
//! \~russian Устанавливает значение и тип из даты
void setValue(const PIDate & v) {initType(v);}
//!
//! \~english Set variant content and type to date and time
//! \~russian Устанавливает значение и тип из даты и времени
void setValue(const PIDateTime & v) {initType(v);}
//! \~english Set variant content and type to system time
//! \~russian Устанавливает значение и тип из системного времени
void setValue(const PISystemTime & v) {initType(v);}
//! \~english Set variant content and type to enum
//! \~russian Устанавливает значение и тип из перечисления
void setValue(const PIVariantTypes::Enum & v) {initType(v);}
//! \~english Set variant content and type to file
//! \~russian Устанавливает значение и тип из файла
void setValue(const PIVariantTypes::File & v) {initType(v);}
//! \~english Set variant content and type to dir
//! \~russian Устанавливает значение и тип из директории
void setValue(const PIVariantTypes::Dir & v) {initType(v);}
//! \~english Set variant content and type to color
//! \~russian Устанавливает значение и тип из цвета
void setValue(const PIVariantTypes::Color & v) {initType(v);}
//! \~english Set variant content and type to IODevice
//! \~russian Устанавливает значение и тип из IODevice
void setValue(const PIVariantTypes::IODevice & v) {initType(v);}
//! \~english Set variant content and type to point
//! \~russian Устанавливает значение и тип из точки
void setValue(const PIPointd & v) {initType(v);}
//! \~english Set variant content and type to rect
//! \~russian Устанавливает значение и тип из прямоугольника
void setValue(const PIRectd & v) {initType(v);}
//! \~english Set variant content and type to line
//! \~russian Устанавливает значение и тип из линии
void setValue(const PILined & v) {initType(v);}
//! \~english Set variant content and type to math vector
//! \~russian Устанавливает значение и тип из вектора
void setValue(const PIMathVectord & v) {initType(v);}
//! \~english Set variant content and type to math matrix
//! \~russian Устанавливает значение и тип из матрицы
void setValue(const PIMathMatrixd & v) {initType(v);}
//! \~english Set current value from string without change type
//! \~russian Устанавливает текущее значение из строки без изменения типа
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;
PILined toLine() const;
PIMathVectord toMathVector() const;
PIMathMatrixd toMathMatrix() const;
//! \~\brief
//! \~english Returns variant content as custom type
//! \~russian Возвращает содержимое в качестве своего типа
//! \~\details
//! \~english
//! In case of known types this function equivalent \a to<Type> function. \n
//! Otherwise returns content as type T only if this type was set earlier.
//! \~russian
//! Для стандартных типов эквиваленстно методу \a to<Type>. \n
//! Для других возвращает тип T только если он был установлен ранее.
template<typename T>
T value() const {return getAsValue<T>(*this);}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariant & v);
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(PIVariant && v);
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const char * v) {setValue(PIString(v)); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const bool v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const char v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const uchar v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const short v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const ushort v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const int & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const uint & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const llong & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const ullong & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const float & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const double & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const ldouble & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIBitArray & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIByteArray & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIString & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIStringList & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PITime & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIDate & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIDateTime & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PISystemTime & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::Enum & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::File & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::Dir & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::Color & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIVariantTypes::IODevice & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIPointd & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PILined & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariant & operator =(const PIMathMatrixd & v) {setValue(v); return *this;}
//! \~english Compare operator. Check type and content.
//! \~russian Оператор сравнения. Сравнивает тип и содержимое.
bool operator ==(const PIVariant & v) const;
//! \~english Compare operator. Check type and content.
//! \~russian Оператор сравнения. Сравнивает тип и содержимое.
bool operator !=(const PIVariant & v) const {return !(*this == v);}
//! \~english Returns type of variant content.
//! \~russian Возвращает тип значения.
PIVariant::Type type() const {return _type;}
//! \~english Returns type name of variant content.
//! \~russian Возвращает имя типа значения.
PIString typeName() const;
//! \~english Returns if type is not \a pivInvalid.
//! \~russian Возвращает не является ли тип \a pivInvalid.
bool isValid() const {return _type != PIVariant::pivInvalid;}
//! \~english Swaps with other %PIVariant.
//! \~russian Меняет с другим %PIVariant.
void swap(PIVariant & v);
//! \~\brief
//! \~english Returns new %PIVariant from custom type value.
//! \~russian Возвращает новый %PIVariant из значения своего типа.
//! \~\details
//! \~english
//! In case of known types this function equivalent \a PIVariant() constructors. \n
//! Otherwise returns variant with content "v" and type \a pivCustom.
//! \~russian
//! Для стандартных типов эквиваленстно конструктору \a PIVariant(). \n
//! Для других устанавливает содержимое из "v" и тип \a pivCustom.
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;
}
//! \~english Returns type from its name.
//! \~russian Возвращает тип из его названия.
static PIVariant::Type typeFromName(const PIString & tname);
//! \~english Returns type name.
//! \~russian Возвращает имя типа.
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 PILined PIVariant::value() const {return toLine();}
template<> inline PIVariant PIVariant::value() const {return *this;}
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 PILined & 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 PIVariant::fromValue(const PIVariant & 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<PILined>() {return PIVariant::pivLine;}
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(PILined)
REGISTER_VARIANT(PIMathVectord)
REGISTER_VARIANT(PIMathMatrixd)
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariant) {
s << v._content << 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;
}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ(PIVariant) {
s >> v._content >> v._type;
if (v._type == PIVariant::pivCustom) {
PIString tn;
s >> tn;
#ifdef CUSTOM_PIVARIANT
PIByteArray vc = v._content;
v = PIVariant::fromValue(vc, tn);
#endif
}
return s;
}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariant & v) {
s.space(); s.saveAndSetControls(0);
s << "PIVariant(" << v.typeName();
if (v.isValid())
s << ", " << v.toString();
s << ")";
s.restoreControls(); return s;
}
#endif // PIVARIANT_H

View File

@@ -1,186 +0,0 @@
/*! \file pivariantsimple.h
* \ingroup Core
* \brief
* \~english Simple variant type
* \~russian Простой вариативный тип
*/
/*
PIP - Platform Independent Primitives
Variant simple type
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 PIVARIANTSIMPLE_H
#define PIVARIANTSIMPLE_H
#include "pistring.h"
#include <typeinfo>
#ifdef MICRO_PIP
#include "pivariant.h"
#endif
class __VariantFunctionsBase__ {
public:
virtual __VariantFunctionsBase__ * instance() {return 0;}
virtual PIString typeName() const {return PIString();}
virtual uint hash() const {return 0;}
virtual void newT(void *& ptr, const void * value) {;}
virtual void newNullT(void *& ptr) {;}
virtual void assignT(void *& ptr, const void * value) {;}
virtual void deleteT(void *& ptr) {;}
};
template<typename T>
class __VariantFunctions__: public __VariantFunctionsBase__ {
public:
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;}
#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;}
#endif
uint hash() const final {static uint ret = typeName().hash(); return ret;}
void newT(void *& ptr, const void * value) final {ptr = (void*)(new T(*(const T*)value));}
void newNullT(void *& ptr) final {ptr = (void*)(new T());}
void assignT(void *& ptr, const void * value) final {*(T*)ptr = *(const T*)value;}
void deleteT(void *& ptr) final {delete (T*)(ptr);}
};
//! \addtogroup Core
//! \{
//! \~\class PIVariantSimple pivariantsimple.h
//! \~\brief
//! \~english Simple variant type.
//! \~russian Простой вариативный тип.
//!
//! \~\details
//! \~english
//!
//! \~russian
//!
//! \}
class PIVariantSimple {
public:
//! \~english Construct null %PIVariantSimple
//! \~russian Создает пустой %PIVariantSimple
PIVariantSimple() {ptr = 0; f = 0;}
//! \~english Contructs a copy of %PIVariantSimple.
//! \~russian Создает копию %PIVariantSimple.
PIVariantSimple(const PIVariantSimple & v) {
ptr = 0;
f = v.f;
if (f && v.ptr)
f->newT(ptr, v.ptr);
}
~PIVariantSimple() {destroy();}
//! \~english Assign operator.
//! \~russian Оператор присваивания.
PIVariantSimple & operator=(const PIVariantSimple & v) {
destroy();
f = v.f;
if (f && v.ptr)
f->newT(ptr, v.ptr);
return *this;
}
//! \~english Set value to "v".
//! \~russian Устанавливает значение в "v".
template <typename T>
void setValue(const T & v) {
if (f) {
if (isMyType<T>()) {
f->assignT(ptr, (const void *)&v);
return;
}
}
destroy();
f = __VariantFunctions__<T>().instance();
f->newT(ptr, (const void *)&v);
}
//! \~\brief
//! \~english Returns value as type "T".
//! \~russian Возвращает значение как тип "T".
//! \~\details
//! \~english
//! In contrast of PIVariant this class has strong check of type.
//! Returns value only if this type was set before.
//!
//! \~russian
//! В отличии от PIVariant этот класс строго проверяет типы.
//! Возвращает значение только если этот же тип был установлен ранее.
//!
template <typename T>
T value() const {
if (!f) return T();
if (!isMyType<T>())
return T();
return *(T*)(ptr);
}
//! \~english Returns %PIVariantSimple with value "v".
//! \~russian Возвращает %PIVariantSimple со значением "v".
template <typename T>
static PIVariantSimple fromValue(const T & v) {
PIVariantSimple ret;
ret.setValue(v);
return ret;
}
private:
template <typename T>
bool isMyType() const {
if (!f) return false;
uint mh = f->hash(), th = __VariantFunctions__<T>().instance()->hash();
if (mh == 0 || th == 0) return false;
return mh == th;
}
void destroy() {
if (ptr && f)
f->deleteT(ptr);
ptr = 0;
f = 0;
}
void * ptr;
__VariantFunctionsBase__ * f;
};
#define REGISTER_PIVARIANTSIMPLE(Type) \
template<> \
class __VariantFunctions__<Type>: public __VariantFunctionsBase__ { \
public: \
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<Type> ret; return &ret;} \
PIString typeName() const final {static PIString ret(#Type); return ret;} \
uint hash() const final {static uint ret = typeName().hash(); return ret;} \
void newT(void *& ptr, const void * value) final {ptr = (void*)(new Type(*(const Type *)value));} \
void newNullT(void *& ptr) final {ptr = (void*)(new Type());} \
void assignT(void *& ptr, const void * value) final {*(Type *)ptr = *(const Type *)value;} \
void deleteT(void *& ptr) final {delete (Type *)(ptr);} \
};
REGISTER_PIVARIANTSIMPLE(std::function<void(void*)>)
#endif // PIVARIANTSIMPLE_H

View File

@@ -1,158 +0,0 @@
/*
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"
#ifndef MICRO_PIP
# include "piiodevice.h"
#endif
int PIVariantTypes::Enum::selectedValue() const {
for (const auto & e: enum_list)
if (e.name == selected)
return e.value;
return 0;
}
bool PIVariantTypes::Enum::selectValue(int v) {
for (const auto & e: enum_list)
if (e.value == v) {
selected = e.name;
return true;
}
return false;
}
bool PIVariantTypes::Enum::selectName(const PIString & n) {
for (const auto & e: enum_list)
if (e.name == n) {
selected = e.name;
return true;
}
return false;
}
int PIVariantTypes::Enum::value(const PIString & n) const {
for (const auto & e: enum_list)
if (e.name == n)
return e.value;
return 0;
}
PIString PIVariantTypes::Enum::name(int v) const {
for (const auto & e: enum_list)
if (e.value == v)
return e.name;
return PIString();
}
PIVector<int> PIVariantTypes::Enum::values() const {
PIVector<int> ret;
for (const auto & e: enum_list)
ret << e.value;
return ret;
}
PIStringList PIVariantTypes::Enum::names() const {
PIStringList ret;
for (const auto & e: enum_list)
ret << e.name;
return ret;
}
PIVariantTypes::IODevice::IODevice() {
#ifndef MICRO_PIP
mode = PIIODevice::ReadWrite;
#else
mode = 0; // TODO: PIIODevice for MICRO PIP
#endif // MICRO_PIP
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=";
#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() + "\"";
}
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) {
for (const auto & s: v)
(*this) << s;
return *this;
}

View File

@@ -1,379 +0,0 @@
/*! \file pivarianttypes.h
* \ingroup Core
* \brief
* \~english Types for PIVariant
* \~russian Типы для 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;
//! \ingroup Core
//! \relatesalso PIVariant
//! \~english Namespace contains several types for PIVariant
//! \~russian Пространство имен содержит некоторые типы для PIVariant
namespace PIVariantTypes {
//! \addtogroup Core
//! \{
//! \~\struct Enumerator pivarianttypes.h
//! \~\brief
//! \~english Name-value pair.
//! \~russian Пара имя-значение.
//! \}
struct PIP_EXPORT Enumerator {
Enumerator(int v = 0, const PIString & n = PIString()): value(v), name(n) {}
//! \~english Value.
//! \~russian Значение.
int value;
//! \~english Name.
//! \~russian Имя.
PIString name;
};
//! \addtogroup Core
//! \{
//! \~\struct Enum pivarianttypes.h
//! \~\brief
//! \~english Collection of PIVariantTypes::Enumerator.
//! \~russian Набор PIVariantTypes::Enumerator.
//! \~\details
//! \~english
//! This class represents classic c-style enum.
//! Contains elements with unique names and not uniqueue values, also
//! name of enum and selected member.
//!
//! \~russian
//! Этот класс представляет классический c-style enum.
//! Содержит элементы с уникальными именами и неуникальными значениями,
//! а также имя перечисления и выбранного элемента.
//!
//! \}
struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()): enum_name(n) {}
//! \~english Returns selected value, or 0 if there is no name in members.
//! \~russian Возвращает выбранное значение, или 0, если выбранного имени нет в элементах.
int selectedValue() const;
//! \~english Returns selected name.
//! \~russian Возвращает выбранное имя.
PIString selectedName() const {return selected;}
//! \~\brief
//! \~english Select value if exists in Enum.
//! \~russian Выбирает значение, если оно существует в Enum.
//!
//! \~\details
//! \~english
//! If Enum contains several PIVariantTypes::Enumerator with same values,
//! first PIVariantTypes::Enumerator will selected.
//! Returns if value exists in Enum.
//!
//! \~russian
//! Если Enum содержит несколько PIVariantTypes::Enumerator с этим значением,
//! то будет выбран первый.
//! Возвращает существовал ли такой Enum.
//!
bool selectValue(int v);
//! \~\brief
//! \~english Select name if exists in Enum.
//! \~russian Выбирает имя, если оно существует в Enum.
//!
//! \~\details
//! \~english
//! Returns if name exists in Enum.
//!
//! \~russian
//! Возвращает существовал ли такой Enum.
//!
bool selectName(const PIString & n);
//! \~english Find PIVariantTypes::Enumerator with name "n" and return it value, otherwise 0.
//! \~russian Ищет PIVariantTypes::Enumerator с именем "n" и возвращает его значение, иначе 0.
int value(const PIString & n) const;
//! \~english Find PIVariantTypes::Enumerator with value "v" and return it name, otherwise empty string.
//! \~russian Ищет PIVariantTypes::Enumerator со значением "v" и возвращает его имя, иначе пустую строку.
PIString name(int v) const;
//! \~english Returns all members values.
//! \~russian Возвращает все значения членов.
PIVector<int> values() const;
//! \~english Returns all members names.
//! \~russian Возвращает все имена членов.
PIStringList names() const;
//! \~english Add PIVariantTypes::Enumerator to Enum.
//! \~russian Добавляет в Enum PIVariantTypes::Enumerator.
Enum & operator <<(const Enumerator & v);
//! \~english Add PIVariantTypes::Enumerator with name "v" and value of last element + 1, otherwise 0.
//! \~russian Добавляет PIVariantTypes::Enumerator с именем "v" и значением последнего элемента + 1, иначе 0.
Enum & operator <<(const PIString & v);
//! \~english Add PIVariantTypes::Enumerator element for each name of vector.
//! \~russian Добавляет PIVariantTypes::Enumerator для каждой строки из массива.
Enum & operator <<(const PIStringList & v);
//! \~english Returns if Enum is empty.
//! \~russian Возвращает пустой ли Enum.
bool isEmpty() const {return enum_list.isEmpty();}
//! \~english Name of Enum.
//! \~russian Имя Enum.
PIString enum_name;
//! \~english Name of selected element.
//! \~russian Имя выбранного элемента.
PIString selected;
//! \~english Members.
//! \~russian Элементы.
PIVector<Enumerator> enum_list;
};
//! \addtogroup Core
//! \{
//! \~\struct File pivarianttypes.h
//! \~\brief
//! \~english File location description.
//! \~russian Описание положения файла.
//! \}
struct PIP_EXPORT File {
File(const PIString & p = PIString(), const PIString & f = PIString(), bool abs = false, bool save_mode = false):
file(p), filter(f), is_abs(abs), is_save(save_mode) {}
//! \~english Returns path.
//! \~russian Возвращает путь.
PIString toString() const {return file;}
//! \~english Path.
//! \~russian Путь.
PIString file;
//! \~english Name filter.
//! \~russian Фильтр имени.
PIString filter;
//! \~english If path is absolute.
//! \~russian Абсолютный ли путь.
bool is_abs;
//! \~english If save is available.
//! \~russian Доступно ли сохранение.
bool is_save;
};
//! \addtogroup Core
//! \{
//! \~\struct Dir pivarianttypes.h
//! \~\brief
//! \~english Directory description.
//! \~russian Описание директории.
//! \}
struct PIP_EXPORT Dir {
Dir(const PIString & d = PIString(), bool abs = false):
dir(d), is_abs(abs) {}
//! \~english Returns path.
//! \~russian Возвращает путь.
PIString toString() const {return dir;}
//! \~english Path.
//! \~russian Путь.
PIString dir;
//! \~english If path is absolute.
//! \~russian Абсолютный ли путь.
bool is_abs;
};
//! \addtogroup Core
//! \{
//! \~\struct Color pivarianttypes.h
//! \~\brief
//! \~english 32-bits color.
//! \~russian 32-битный цвет.
//! \}
struct PIP_EXPORT Color {
Color(uint v = 0) {rgba = v;}
//! \~english Integer color.
//! \~russian Целочисленный цвет.
uint rgba;
};
//! \addtogroup Core
//! \{
//! \~\struct IODevice pivarianttypes.h
//! \~\brief
//! \~english Input/output device description.
//! \~russian Описание устройства ввода/вывода.
//! \}
struct PIP_EXPORT IODevice {
IODevice();
//! \~english Serialize "ps" and set it to "props".
//! \~russian Сериализует "ps" и устанавливает "props".
void set(const PIPropertyStorage & ps);
//! \~english Deserialize "props" and returns it.
//! \~russian Десериализует "props" и возвращает свойства.
PIPropertyStorage get() const;
//! \~english Returns string for PICout.
//! \~russian Возвращает строку для PICout.
PIString toPICout() const;
//! \~english PIIODevice prefix, see \ref PIIODevice_sec7.
//! \~russian Префикс PIIODevice, см. \ref PIIODevice_sec7.
PIString prefix;
//! PIIODevice::DeviceMode.
int mode;
//! PIIODevice::DeviceOptions.
int options;
//! \~english Serialized properties.
//! \~russian Сериализованные свойства.
PIByteArray props;
};
}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Enumerator & v) {s << v.name << "(" << v.value << ")"; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Enum & v) {s << "Enum(" << v.selectedValue() << "=" << v.selectedName() << ")"; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::File & v) {s << "File(\"" << v.file << "\")"; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Dir & v) {s << "Dir(\"" << v.dir << "\")"; return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::Color & v) {s.saveControls(); s << PICoutManipulators::Hex << "Color(#" << v.rgba << ")"; s.restoreControls(); return s;}
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
inline PICout operator <<(PICout s, const PIVariantTypes::IODevice & v) {s << v.toPICout(); return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Enumerator) {s << v.value << v.name; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Enumerator) {s >> v.value >> v.name; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Enum) {s << v.enum_name << v.selected << v.enum_list; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Enum) {s >> v.enum_name >> v.selected >> v.enum_list; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::File) {s << v.file << v.filter << uchar((v.is_abs ? 1 : 0) + (v.is_save ? 2 : 0)); return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::File) {uchar f(0); s >> v.file >> v.filter >> f; v.is_abs = ((f & 1) == 1); v.is_save = ((f & 2) == 2); return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Dir) {s << v.dir << v.is_abs; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Dir) {s >> v.dir >> v.is_abs; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::Color) {s << v.rgba; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::Color) {s >> v.rgba; return s;}
//! \relatesalso PIBinaryStream
//! \~english Store operator.
//! \~russian Оператор сохранения.
BINARY_STREAM_WRITE(PIVariantTypes::IODevice) {s << v.prefix << v.mode << v.options << v.props; return s;}
//! \relatesalso PIBinaryStream
//! \~english Restore operator.
//! \~russian Оператор извлечения.
BINARY_STREAM_READ (PIVariantTypes::IODevice) {s >> v.prefix >> v.mode >> v.options >> v.props; return s;}
#endif // PIVARIANTYPES_H