#ifndef __MARSSTREAMS_H__ #define __MARSSTREAMS_H__ #include #include #include #include #include #include #include #include "mars_linalg.h" #include "mars_util.h" namespace mars { class ObjectStream { public: #define WRITENUM_IMPL(x) { writeNum(x); return *this; } #define READNUM_IMPL(x) { readNum(x); return *this; } ObjectStream (std::iostream * pIO); ObjectStream (std::istream * pIn); ObjectStream (std::ostream * pOut); ObjectStream & operator << ( const float & f ) WRITENUM_IMPL(f) ObjectStream & operator << ( const double & d ) WRITENUM_IMPL(d) ObjectStream & operator << ( const unsigned long & l) WRITENUM_IMPL(l) ObjectStream & operator << ( const signed long & l) WRITENUM_IMPL(l) ObjectStream & operator << ( const unsigned int & i) WRITENUM_IMPL(i) ObjectStream & operator << ( const signed int & i) WRITENUM_IMPL(i) ObjectStream & operator << ( const unsigned short & s) WRITENUM_IMPL(s) ObjectStream & operator << ( const signed short & s) WRITENUM_IMPL(s) ObjectStream & operator << ( const unsigned char & c) WRITENUM_IMPL(c) ObjectStream & operator << ( const signed char & c) WRITENUM_IMPL(c) //ObjectStream & operator << ( const std::streamoff & so) WRITENUM_IMPL(so) //ObjectStream & operator << ( const std::streampos & sp) WRITENUM_IMPL(sp) ObjectStream & operator << ( const bool & b) WRITENUM_IMPL(static_cast< char > (b ? 1 : 0)) ObjectStream & operator << ( const std::string & str ) { assert(_pOut != NULL); size_t nLen = str.size(); preprocess(nLen); _pOut->write(reinterpret_cast< char * > (&nLen), sizeof(size_t)); _pOut->write(str.c_str(), nLen); return *this; } template< typename T > ObjectStream & operator << ( const std::vector< T > & vec) { writeContainer(vec); return *this; } template< typename T > ObjectStream & operator << ( const std::list< T > & lst) { writeContainer(lst); return *this; } template< typename T > ObjectStream & operator << ( const std::set< T > & st) { writeContainer(st); return *this; } template< typename T > ObjectStream & operator << ( const vector2D< T > & v ) { operator << (v.x); operator << (v.y); return *this; } template< typename T > ObjectStream & operator << ( const vector3D< T > & v ) { operator << (v.x); operator << (v.y); operator << (v.z); return *this; } template< typename T > ObjectStream & operator << ( const BBox< T > & bbox ) { operator << (bbox.left); operator << (bbox.top); operator << (bbox.right); operator << (bbox.bottom); return *this; } template< typename T > ObjectStream & operator << ( const Range< T > & range ) { operator << (range.minimum); operator << (range.maximum); return *this; } template< typename T > ObjectStream & operator << ( const RangeX< T > & range ) { operator << (static_cast< const Range< T > & > (range)); operator << (range.step); return *this; } template< typename A, typename B > ObjectStream & operator << (const std::pair< A, B > & pair) { return *this << pair.first << pair.second; } ObjectStream & operator >> ( float & f ) READNUM_IMPL(f) ObjectStream & operator >> ( double & d ) READNUM_IMPL(d) ObjectStream & operator >> ( unsigned long & l) READNUM_IMPL(l) ObjectStream & operator >> ( signed long & l) READNUM_IMPL(l) ObjectStream & operator >> ( unsigned int & i) READNUM_IMPL(i) ObjectStream & operator >> ( signed int & i) READNUM_IMPL(i) ObjectStream & operator >> ( unsigned short & s) READNUM_IMPL(s) ObjectStream & operator >> ( signed short & s) READNUM_IMPL(s) ObjectStream & operator >> ( unsigned char & c) READNUM_IMPL(c) ObjectStream & operator >> ( signed char & c) READNUM_IMPL(c) //ObjectStream & operator >> ( std::streamoff & so) READNUM_IMPL(so) //ObjectStream & operator >> ( std::streampos & sp) READNUM_IMPL(sp) ObjectStream & operator >> ( bool & b) { char c; readNum (c); b = (c && ~0); return *this; } ObjectStream & operator >> ( std::string & str ) { assert(_pIn != NULL); size_t nLen; _pIn->read(reinterpret_cast< char * > (&nLen), sizeof(size_t)); preprocess(nLen); char * pStr = new char[nLen]; _pIn->read(pStr, nLen); str = std::string(pStr, nLen); delete [] pStr; return *this; } template< typename T > ObjectStream & operator >> ( std::vector< T > & vec) { readContainer(vec); return *this; } template< typename T > ObjectStream & operator >> ( std::list< T > & lst) { readContainer(lst); return *this; } template< typename T > ObjectStream & operator >> ( std::set< T > & st) { readContainer(st); return *this; } template< typename T > ObjectStream & operator >> ( vector2D< T > & v ) { operator >> (v.x); operator >> (v.y); return *this; } template< typename T > ObjectStream & operator >> ( vector3D< T > & v ) { operator >> (v.x); operator >> (v.y); operator >> (v.z); return *this; } template< typename T > ObjectStream & operator >> ( BBox< T > & bbox ) { operator >> (bbox.left); operator >> (bbox.top); operator >> (bbox.right); operator >> (bbox.bottom); return *this; } template< typename T > ObjectStream & operator >> ( Range< T > & range ) { operator >> (range.minimum); operator >> (range.maximum); return *this; } template< typename T > ObjectStream & operator >> ( RangeX< T > & range ) { operator >> (static_cast< Range< T > & > (range)); operator >> (range.step); return *this; } template< typename A, typename B > ObjectStream & operator >> (std::pair< A, B > & pair) { return *this >> pair.first >> pair.second; } private: std::istream * _pIn; std::ostream * _pOut; struct Traits { enum Endian { Big, Little } endian; } _traits; static Traits determineTraits (); template< typename T > void writeNum (const T & n, const T = 42) { assert(_pOut != NULL); T val = n; preprocess(val); _pOut->write(reinterpret_cast< const char * > (&val), sizeof(T)); } template< typename T > void writeNums (const T * pN, const size_t nCount, const T = 42) { assert(_pOut != NULL); T * pVals = new T[nCount]; memcpy (pVals, pN, nCount * sizeof(T)); if (_traits.endian == Traits::Big) { for (unsigned int c = 0; c < nCount; ++c) endianFlip (pVals[c]); } size_t nLen = nCount; preprocess(nLen); _pOut->write(reinterpret_cast< const char * > (&nLen), sizeof(size_t)); _pOut->write(reinterpret_cast< const char * > (pVals), sizeof(T) * nCount); } template< typename C > void writeContainer (const C & ctr) { writeNum(static_cast< size_t > (ctr.size())); for (typename C::const_iterator i = ctr.begin(); i != ctr.end(); ++i) *this << *i; } template< typename T > void readNum (T & n, const T = 42) { assert(_pIn != NULL); _pIn->read(reinterpret_cast< char * > (&n), sizeof(T)); preprocess(n); } template< typename T > void readNums (T *& pN, size_t & nCount, const T = 42) { assert(_pIn != NULL); _pIn->read(reinterpret_cast< char * > (&nCount), sizeof(size_t)); preprocess(nCount); pN = new T[nCount]; _pIn->read(reinterpret_cast< char * > (pN), sizeof(T) * nCount); if (_traits.endian == Traits::Big) { for (unsigned int c = 0; c < nCount; ++c) endianFlip (pN[c]); } } template< typename C > void readContainer (C & ctr) { typename C::value_type t; size_t nLen; readNum(nLen); ctr.clear(); reserve< C, typename C::value_type >(ctr, nLen); for (size_t c = 0; c < nLen; ++c) { *this >> t; ctr.push_back(t); } } template< typename T > void endianFlip (T & val, T = 42) const { char * pData = reinterpret_cast< char * > (&val), cTmp; for (unsigned int i = 0; i < sizeof(T); ++i) { cTmp = pData[i]; pData[i] = pData[sizeof(T) - i - 1]; pData[sizeof(T) - i - 1] = cTmp; } } template< typename T > void preprocess (T & val, T = 42) const { if (_traits.endian == Traits::Big) endianFlip(val); } template< typename C, typename T > static void reserve (C & ctr, const size_t nCount) {} template< typename T > static void reserve (std::vector< T > & ctr, const size_t nCount) { ctr.reserve(nCount); } }; } #endif