class PIBinaryStream {
public:
// one should implements next methods:
//
// bool binaryStreamAppend(const void * d, size_t s);
// bool binaryStreamTake(void * d, size_t s);
bool append(const void * d, size_t s) {
if (!static_cast(this)->binaryStreamAppend(d, s)) {
return false;
printf("[PIBinaryStream] append() error\n");
}
return true;
}
bool take(void * d, size_t s) {
if (!static_cast
(this)->binaryStreamTake(d, s)) {
return false;
printf("[PIBinaryStream] take() error\n");
}
return true;
}
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) {
if (!s.take(&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::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);
if (!s.take(v.data(), sz * sizeof(T))) {
printf("error with PIVector<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
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);
if (!s.take(v.data(), sz * sizeof(T))) {
printf("error with PIDeque<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
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);
if (!s.take(v.data(), v.size() * sizeof(T))) {
printf("error with PIVector2D<%s>\n", __PIP_TYPENAME__(T));
assert(false);
}
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