diff --git a/libs/main/core/pibinarystream.h b/libs/main/core/pibinarystream.h new file mode 100644 index 00000000..02c3635c --- /dev/null +++ b/libs/main/core/pibinarystream.h @@ -0,0 +1,415 @@ +/*! \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 . +*/ + +#ifndef PIBINARYSTREAM_H +#define PIBINARYSTREAM_H + +#include "pibitarray.h" +#include "pimap.h" +#include "pivector2d.h" + + +//! \ingroup Core +//! \~\brief +//! \~english Binary serialization interface. +//! \~russian Интерфейс бинарной сериализации. +template +class PIBinaryStream { +public: + // one should implements next methods: + // + // void appendImp(const void * d, size_t s); + // void takeImp(void * d, size_t s); + + void append(const void * d, size_t s) {static_cast(this)->appendImp(d, s);} + void take(void * d, size_t s) {static_cast(this)->takeImp(d, s);} + template + void append(T v) {append(&v, sizeof(v));} + uchar takeByte() {uchar r = 0; take(&r, sizeof(r)); return r;} + int takeInt() {int r = 0; take(&r, sizeof(r)); return r;} +}; + + +// helper class to detect default operators +template +class PIBinaryStreamRef { +public: + PIBinaryStreamRef(PIBinaryStream

& s): p(s) {} + PIBinaryStream

& p; +}; + + +template inline PIBinaryStream

& operator <<(PIBinaryStreamRef

s, const T & v) {s.p << v; return s.p;} +template inline PIBinaryStream

& operator >>(PIBinaryStreamRef

s, T & v) {s.p >> v; return s.p;} + + +// small types +template inline PIBinaryStreamRef

operator <<(PIBinaryStream

& s, const bool v) {s.append((uchar)v); return s;} +template inline PIBinaryStreamRef

operator <<(PIBinaryStream

& s, const char v) {s.append((uchar)v); return s;} +template inline PIBinaryStreamRef

operator <<(PIBinaryStream

& s, const uchar v) {s.append((uchar)v); return s;} +template inline PIBinaryStreamRef

operator >>(PIBinaryStream

& s, bool & v) {v = s.takeByte(); return s;} +template inline PIBinaryStreamRef

operator >>(PIBinaryStream

& s, char & v) {v = s.takeByte(); return s;} +template inline PIBinaryStreamRef

operator >>(PIBinaryStream

& s, uchar & v) {v = s.takeByte(); return s;} + + + + +// store simple types + + +template::value, int>::type = 0> +inline PIBinaryStreamRef

operator <<(PIBinaryStream

& s, const T & v) { + s.append(&v, sizeof(v)); + return s; +} + + +//! \~english Store operator for PIVector of any trivial copyable type +//! \~russian Оператор сохранения для PIVector тривиальных типов +template::value, int>::type = 0, +typename std::enable_if< std::is_same&>() << std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIVector & v) { + piCout << "<< vector trivial default"; + s.append((int)v.size()); + s.append(v.data(), v.size() * sizeof(T)); + return s; +} +template::value, int>::type = 0, +typename std::enable_if&>() << std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIVector & v) { + piCout << "<< vector trivial custom"; + s.append((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::value, int>::type = 0, +typename std::enable_if< std::is_same&>() << std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIDeque & v) { + piCout << "<< deque trivial default"; + s.append((int)v.size()); + s.append(v.data(), v.size() * sizeof(T)); + return s; +} +template::value, int>::type = 0, +typename std::enable_if&>() << std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIDeque & v) { + piCout << "<< deque trivial custom"; + s.append((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::value, int>::type = 0, +typename std::enable_if< std::is_same&>() << std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIVector2D & v) { + piCout << "<< vector2d trivial default"; + s.append((int)v.rows()); + s.append((int)v.cols()); + s.append(v.data(), v.size() * sizeof(T)); + return s; +} +template::value, int>::type = 0, +typename std::enable_if&>() << std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIVector2D & v) { + piCout << "<< vector2d trivial custom"; + s.append((int)v.rows()); + s.append((int)v.cols()); + s << v.toPlainVector(); + return s; +} + + +//! \~english Store operator +//! \~russian Оператор сохранения +template +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIBitArray & v) {s << v.size_ << v.data_; return s;} + + +//! \~english Store operator +//! \~russian Оператор сохранения +template +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIPair & v) {s << v.first << v.second; return s;} + + + + +// restore simple types + + +template::value, int>::type = 0> +inline PIBinaryStreamRef

operator >>(PIBinaryStream

& s, T & v) { + s.take(&v, sizeof(v)); + return s; +} + + +//! \~english Restore operator for PIVector of any trivial copyable type +//! \~russian Оператор извлечения для PIVector тривиальных типов +template::value, int>::type = 0, +typename std::enable_if< std::is_same&>() >> std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIVector & v) { + piCout << ">> vector trivial default"; + int sz = s.takeInt(); + v._resizeRaw(sz); + s.take(v.data(), sz*sizeof(T)); + return s; +} +template::value, int>::type = 0, +typename std::enable_if&>() >> std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIVector & v) { + piCout << ">> vector trivial custom"; + int sz = s.takeInt(); + 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::value, int>::type = 0, +typename std::enable_if< std::is_same&>() >> std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIDeque & v) { + piCout << ">> deque trivial default"; + int sz = s.takeInt(); + v._resizeRaw(sz); + s.take(v.data(), sz*sizeof(T)); + return s; +} +template::value, int>::type = 0, +typename std::enable_if&>() >> std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIDeque & v) { + piCout << ">> deque trivial custom"; + int sz = s.takeInt(); + 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::value, int>::type = 0, +typename std::enable_if< std::is_same&>() >> std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIVector2D & v) { + piCout << ">> vector2d trivial default"; + int r, c; + r = s.takeInt(); + c = s.takeInt(); + v._resizeRaw(r, c); + s.take(v.data(), v.size() * sizeof(T)); + return s; +} +template::value, int>::type = 0, +typename std::enable_if&>() >> std::declval()), PIBinaryStreamRef

>::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIVector2D & v) { + piCout << ">> vector2d trivial custom"; + int r, c; + PIVector tmp; + r = s.takeInt(); + c = s.takeInt(); + s >> tmp; + v = PIVector2D(r, c, tmp); + return s; +} +; + + + + +// store complex types + + +//! \~english Store operator for PIVector of any compound type +//! \~russian Оператор сохранения для PIVector сложных типов +template::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIVector & v) { + piCout << "<< vector complex"; + s.append(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::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIDeque & v) { + piCout << "<< deque complex"; + s.append(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::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIVector2D & v) { + piCout << "<< vector2d complex"; + s.append(int(v.rows())); + s.append(int(v.cols())); + s << v.toPlainVector(); + return s; +} + + + + +// restore complex types + + +//! \~english Restore operator for PIVector of any compound type +//! \~russian Оператор извлечения для PIVector сложных типов +template::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIVector & 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.takeInt()); + 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::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIDeque & 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.takeInt()); + 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::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIVector2D & 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 tmp; + r = s.takeInt(); + c = s.takeInt(); + s >> tmp; + v = PIVector2D(r, c, tmp); + return s; +} + + + + +// other types + + +//! \~english Store operator +//! \~russian Оператор сохранения +template +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const PIMap & v) { + s.append((int)v.pim_index.size_s()); + for (uint i = 0; i < v.size(); ++i) { + s.append((int)v.pim_index[i].index); + s << v.pim_index[i].key; + } + s << v.pim_content; + return s; +} + + +//! \~english Restore operator +//! \~russian Оператор извлечения +template +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, PIMap & 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.takeInt(); v.pim_index.resize(sz); + int ind = 0; + for (int i = 0; i < sz; ++i) { + ind = s.takeInt(); + 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::value, int>::type = 0> +inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const T & ) { + static_assert(std::is_trivially_copyable::value, "[PIBinaryStream] Error: using undeclared operator << for complex type!"); + return s; +} + +template::value, int>::type = 0> +inline PIBinaryStream

& operator >>(PIBinaryStream

& s, T & ) { + static_assert(std::is_trivially_copyable::value, "[PIBinaryStream] Error: using undeclared operator >> for complex type!"); + return s; +} + + + + +#endif diff --git a/main.cpp b/main.cpp index 83784703..52ca5804 100644 --- a/main.cpp +++ b/main.cpp @@ -1,161 +1,64 @@ #include "pip.h" +#include "pibinarystream.h" +//#include "stream.h" +//#include "ccm.h" +//#include "pisystemmonitor_.h" using namespace PICoutManipulators; - -template -class BinaryStream { +class ByteArray: public PIBinaryStream { public: - BinaryStream(P & parent): p(parent) {} - void append(const void * d, size_t s) {p.appendImp(d, s);} - void append(int i) {append(&i, sizeof(i));} - void append(uchar byte) {p.appendImp(byte);} - void take(void * d, size_t s) {p.takeImp(d, s);} - uchar takeByte() {return p.takeByteImp();} - int takeInt() {int r = 0; take(&r, sizeof(r)); return r;} -private: - P & p; -}; - -template -class BinaryStreamRef { -public: - BinaryStreamRef(BinaryStream

& s): p(s) {} - BinaryStream

& ref() {return p;} - BinaryStream

& p; -}; - - -template inline BinaryStream

& operator <<(BinaryStreamRef

s, const T & v) {s.ref() << v; return s.p;} -template inline BinaryStream

& operator >>(BinaryStreamRef

s, T & v) {s.ref() >> v; return s.p;} - -template inline BinaryStream

& operator <<(BinaryStream

& s, const bool v) {s.append((uchar)v); return s;} -template inline BinaryStream

& operator <<(BinaryStream

& s, const char v) {s.append((uchar)v); return s;} -template inline BinaryStream

& operator <<(BinaryStream

& s, const uchar v) {s.append((uchar)v); return s;} -template::value, int>::type = 0> -inline BinaryStreamRef

operator <<(BinaryStream

& s, const T & v) { - s.append(&v, sizeof(v)); - return s; -} - -template inline BinaryStream

& operator >>(BinaryStream

& s, bool & v) {v = s.takeByte(); return s;} -template inline BinaryStream

& operator >>(BinaryStream

& s, char & v) {v = s.takeByte(); return s;} -template inline BinaryStream

& operator >>(BinaryStream

& s, uchar & v) {v = s.takeByte(); return s;} -template::value, int>::type = 0> -inline BinaryStreamRef

operator >>(BinaryStream

& s, T & v) { - s.take(&v, sizeof(v)); - return s; -} - - -//! \~english Store operator for PIVector of any trivial copyable type -//! \~russian Оператор сохранения для PIVector тривиальных типов -template::value, int>::type = 0, - typename std::enable_if< std::is_same&>() << std::declval()), BinaryStreamRef

>::value, int>::type = 0> -inline BinaryStream

& operator <<(BinaryStream

& s, const PIVector & v) { - piCout << "<< vector trivial default"; - s.append((int)v.size()); - s.append(v.data(), v.size() * sizeof(T)); - return s; -} -template::value, int>::type = 0, - typename std::enable_if&>() << std::declval()), BinaryStreamRef

>::value, int>::type = 0> -inline BinaryStream

& operator <<(BinaryStream

& s, const PIVector & v) { - piCout << "<< vector trivial custom"; - s.append((int)v.size()); - for (const auto & i: v) s << i; - return s; -} - - -//! \~english Restore operator for PIVector of any trivial copyable type -//! \~russian Оператор извлечения для PIVector тривиальных типов -template::value, int>::type = 0, - typename std::enable_if< std::is_same&>() >> std::declval()), BinaryStreamRef

>::value, int>::type = 0> -inline BinaryStream

& operator >>(BinaryStream

& s, PIVector & v) { - piCout << ">> vector trivial default"; - int sz = s.takeInt(); - v._resizeRaw(sz); - if (sz > 0) - s.take(v.data(), sz*sizeof(T)); - return s; -} -template::value, int>::type = 0, - typename std::enable_if&>() >> std::declval()), BinaryStreamRef

>::value, int>::type = 0> -inline BinaryStream

& operator >>(BinaryStream

& s, PIVector & v) { - piCout << ">> vector trivial custom"; - int sz = s.takeInt(); - v._resizeRaw(sz); - for (int i = 0; i < sz; ++i) s >> v[i]; - return s; -} - - -class ByteArray: public BinaryStream { -public: - ByteArray(): BinaryStream(*this) {} PIByteArray data; void appendImp(const void * d, size_t s) { data.append(d, s); } - void appendImp(uchar byte) { - data.append(byte); - } void takeImp(void * d, size_t s) { memcpy(d, data.data(), s); data.remove(0, s); } - uchar takeByteImp() { - return data.take_front(); - } }; -class File: public BinaryStream { +class File: public PIBinaryStream { public: - File(): BinaryStream(*this) {} PIFile file; void appendImp(const void * d, size_t s) { file.write(d, s); } - void appendImp(uchar byte) { - file.writeBinary(byte); - } void takeImp(void * d, size_t s) { file.read(d, s); } - uchar takeByteImp() { - return (uchar)file.readChar(); - } }; struct TS { - TS(int v0 = -1, float v1 = -1){i = v0; f = v1;} + TS(int v0 = -1, float v1 = -1, PIString v2 = "") {i = v0; f = v1; s = v2;} int i; float f; + PIString s; }; PICout operator << (PICout c, const TS & v) {c << '{' << v.i << ", " << v.f << '}'; return c;} -template inline BinaryStream

& operator <<(BinaryStream

& s, const TS & v) {s << v.i; return s;} -template inline BinaryStream

& operator >>(BinaryStream

& s, TS & v) {s >> v.i; return s;} +template inline PIBinaryStream

& operator <<(PIBinaryStream

& s, const TS & v) {s << v.i; return s;} +template inline PIBinaryStream

& operator >>(PIBinaryStream

& s, TS & v) {s >> v.i; return s;} int main(int argc, char * argv[]) { - //ByteArray ba; - File f; - f.file.open("_", PIIODevice::ReadWrite); - f.file.clear(); - PIVector vi({TS(1,20), TS(3,40)}); - f << vi; - //piCout << "s" << ba.data; - vi.fill(TS()); + ByteArray ba; + /*ProcessStatsFixed_ ps; + ba << ps; + piCout << "s" << ba.data;*/ + //File f; + //f.file.open("_", PIIODevice::ReadWrite); + //f.file.clear(); + //PIVector vi({TS(1,20), TS(3,40)}); + PIVector vi({'a', 'b', 'c'}); + ba << vi; + piCout << "src" << vi; + piCout << "s" << ba.data; + vi.fill(' '); vi.clear(); - f.file.seekToBegin(); - f >> vi; - piCout << "data" << vi; - //piCout << "r" << ba.data; + //f.file.seekToBegin(); + ba >> vi; + piCout << "res" << vi; + piCout << "r" << ba.data; return 0; }