#pragma once #include #include #include #include namespace fc { /** * The purpose of this datastream is to provide a fast, effecient, means * of calculating the amount of data "about to be written" and then * writing it. This means having two modes of operation, "test run" where * you call the entire pack sequence calculating the size, and then * actually packing it after doing a single allocation. */ template struct datastream { datastream( T start, size_t s ) :m_start(start),m_pos(start),m_end(start+s){}; inline void skip( size_t s ){ m_pos += s; } inline bool read( char* d, size_t s ) { if( size_t(m_end - m_pos) >= (size_t)s ) { memcpy( d, m_pos, s ); m_pos += s; return true; } FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - s))).set("buffer_size", int64_t(m_end-m_start)) ); return false; } inline bool write( const char* d, size_t s ) { if( m_end - m_pos >= (int32_t)s ) { memcpy( m_pos, d, s ); m_pos += s; return true; } FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - s))).set("buffer_size", int64_t(m_end-m_start)) ); return false; } inline bool put(char c) { if( m_pos < m_end ) { *m_pos = c; ++m_pos; return true; } FC_THROW_REPORT( "Attempt to write ${bytes_past} bytes beyond end of buffer with size ${buffer_size} ", fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - 1))).set("buffer_size", int64_t(m_end-m_start)) ); return false; } inline bool get( unsigned char& c ) { return get( *(char*)&c ); } inline bool get( char& c ) { if( m_pos < m_end ) { c = *m_pos; ++m_pos; return true; } FC_THROW_REPORT( "Attempt to read ${bytes_past} bytes beyond end of buffer of size ${buffer_size} ", fc::value().set("bytes_past",int64_t(-((m_end-m_pos) - 1))).set("buffer_size", int64_t(m_end-m_start)) ); ++m_pos; return false; } T pos()const { return m_pos; } inline bool valid()const { return m_pos <= m_end && m_pos >= m_start; } inline bool seekp(size_t p) { m_pos = m_start + p; return m_pos <= m_end; } inline size_t tellp()const { return m_pos - m_start; } inline size_t remaining()const { return m_end - m_pos; } private: T m_start; T m_pos; T m_end; }; template<> struct datastream { datastream( size_t init_size = 0):m_size(init_size){}; inline bool skip( size_t s ) { m_size += s; return true; } inline bool write( const char* d,size_t s ) { m_size += s; return true; } inline bool put(char c) { ++m_size; return true; } inline bool valid()const { return true; } inline bool seekp(size_t p) { m_size = p; return true; } inline size_t tellp()const { return m_size; } inline size_t remaining()const { return 0; } private: size_t m_size; }; /* template inline datastream& operator<<(datastream& ds, const size_t& d) { ds.write( (const char*)&d, sizeof(d) ); return *this; } template inline datastream& operator>>(datastream& ds, size_t& d) { ds.read((char*)&d, sizeof(d) ); return *this; } */ template inline datastream& operator<<(datastream& ds, const int32_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, int32_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const uint32_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, uint32_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const int64_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, int64_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const uint64_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, uint64_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const int16_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, int16_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const uint16_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, uint16_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const int8_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, int8_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } template inline datastream& operator<<(datastream& ds, const uint8_t& d) { ds.write( (const char*)&d, sizeof(d) ); return ds; } template inline datastream& operator>>(datastream& ds, uint8_t& d) { ds.read((char*)&d, sizeof(d) ); return ds; } } // namespace fc