peerplays-fc/include/fc/datastream.hpp

197 lines
6.4 KiB
C++
Raw Normal View History

#pragma once
2012-09-09 03:46:19 +00:00
#include <fc/utility.hpp>
#include <fc/error_report.hpp>
#include <string.h>
2012-09-09 03:46:19 +00:00
#include <stdint.h>
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<typename T>
struct datastream {
2012-12-18 19:37:14 +00:00
datastream( T start, size_t s )
:m_start(start),m_pos(start),m_end(start+s){};
2012-12-18 19:37:14 +00:00
inline void skip( size_t s ){ m_pos += s; }
inline bool read( char* d, size_t s ) {
2012-12-29 17:00:19 +00:00
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;
}
2012-12-18 19:37:14 +00:00
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; }
2012-12-18 19:37:14 +00:00
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;
2012-09-09 03:46:19 +00:00
};
template<>
struct datastream<size_t> {
datastream( size_t init_size = 0):m_size(init_size){};
2012-12-18 19:37:14 +00:00
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; }
2012-09-09 03:46:19 +00:00
inline bool put(char c) { ++m_size; return true; }
inline bool valid()const { return true; }
2012-12-18 19:37:14 +00:00
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; }
2012-09-09 03:46:19 +00:00
private:
2012-12-18 19:37:14 +00:00
size_t m_size;
2012-09-09 03:46:19 +00:00
};
2012-12-18 19:37:14 +00:00
/*
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const size_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return *this;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, size_t& d) {
ds.read((char*)&d, sizeof(d) );
return *this;
}
*/
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint32_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint32_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint64_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint64_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint16_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint16_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const int8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, int8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
template<typename ST>
inline datastream<ST>& operator<<(datastream<ST>& ds, const uint8_t& d) {
ds.write( (const char*)&d, sizeof(d) );
return ds;
}
template<typename ST, typename DATA>
inline datastream<ST>& operator>>(datastream<ST>& ds, uint8_t& d) {
ds.read((char*)&d, sizeof(d) );
return ds;
}
2012-09-09 03:46:19 +00:00
} // namespace fc