// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_rroot_rbuf #define tools_rroot_rbuf #include "../stype" #include "../long_out" #include "../charp_out" #include #include #include //memcpy namespace tools { namespace rroot { class rbuf { ///////////////////////////////////////////////////////// /// swap //////////////////////////////////////////////// ///////////////////////////////////////////////////////// // NOTE : on most common platforms (including Android, iPad) // CERN-ROOT byte swaps ! (Bad luck). We have arranged to // optimize this operation. The below "_swap_" functions // do not have local variables and manipulates pointers // directly. static void read_swap_2(char* a_pos,char* a_x) { *a_x++ = *(a_pos+1); *a_x++ = *a_pos; } static void read_swap_4(char* a_pos,char* a_x) { a_pos += 3; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos; } static void read_swap_8(char* a_pos,char* a_x) { a_pos += 7; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos--; *a_x++ = *a_pos; } ///////////////////////////////////////////////////////// /// nswp //////////////////////////////////////////////// ///////////////////////////////////////////////////////// static void read_nswp_2(char* a_pos,char* a_x) { ::memcpy(a_x,a_pos,2); } static void read_nswp_4(char* a_pos,char* a_x) { ::memcpy(a_x,a_pos,4); } static void read_nswp_8(char* a_pos,char* a_x) { ::memcpy(a_x,a_pos,8); } ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// static const std::string& s_class() { static const std::string s_v("tools::rroot::rbuf"); return s_v; } typedef void (*r_2_func)(char*,char*); typedef void (*r_4_func)(char*,char*); typedef void (*r_8_func)(char*,char*); public: rbuf(std::ostream& a_out,bool a_byte_swap,const char* a_eob,char*& a_pos) :m_out(a_out) ,m_byte_swap(a_byte_swap) ,m_eob(a_eob) ,m_pos(a_pos) ,m_r_2_func(0) ,m_r_4_func(0) ,m_r_8_func(0) { set_byte_swap(a_byte_swap); } virtual ~rbuf(){ } public: rbuf(const rbuf& a_from) :m_out(a_from.m_out) ,m_byte_swap(a_from.m_byte_swap) ,m_eob(a_from.m_eob) ,m_pos(a_from.m_pos) ,m_r_2_func(a_from.m_r_2_func) ,m_r_4_func(a_from.m_r_4_func) ,m_r_8_func(a_from.m_r_8_func) { set_byte_swap(a_from.m_byte_swap); } rbuf& operator=(const rbuf& a_from){ set_byte_swap(a_from.m_byte_swap); m_eob = a_from.m_eob; //m_pos is a ref. m_r_2_func = a_from.m_r_2_func; m_r_4_func = a_from.m_r_4_func; m_r_8_func = a_from.m_r_8_func; return *this; } public: std::ostream& out() const {return m_out;} void skip(unsigned int a_num) {m_pos += a_num;} void set_eob(const char* a_eob){m_eob = a_eob;} char*& pos() {return m_pos;} const char* eob() const {return m_eob;} void set_byte_swap(bool a_value) { m_byte_swap = a_value; if(m_byte_swap) { m_r_2_func = read_swap_2; m_r_4_func = read_swap_4; m_r_8_func = read_swap_8; } else { m_r_2_func = read_nswp_2; m_r_4_func = read_nswp_4; m_r_8_func = read_nswp_8; } } public: bool read(unsigned char& a_x) { if(!_check_eob(a_x)) return false; a_x = *m_pos;m_pos++; return true; } bool read(unsigned short& a_x) { if(!_check_eob(a_x)) return false; m_r_2_func(m_pos,(char*)&a_x); m_pos += sizeof(unsigned short); return true; } bool read(unsigned int& a_x) { if(!_check_eob(a_x)) return false; m_r_4_func(m_pos,(char*)&a_x); m_pos += sizeof(unsigned int); return true; } bool read(uint64& a_x){ if(!_check_eob(a_x)) return false; m_r_8_func(m_pos,(char*)&a_x); m_pos += 8; return true; } bool read(float& a_x) { if(!_check_eob(a_x)) return false; m_r_4_func(m_pos,(char*)&a_x); m_pos += sizeof(float); return true; } bool read(double& a_x) { if(!_check_eob(a_x)) return false; m_r_8_func(m_pos,(char*)&a_x); m_pos += sizeof(double); return true; } bool read(char& a_x) { if(!_check_eob(a_x)) return false; a_x = *m_pos;m_pos++; return true; } bool read(short& a_x) { if(!_check_eob(a_x)) return false; m_r_2_func(m_pos,(char*)&a_x); m_pos += sizeof(short); return true; } bool read(int& a_x) { if(!_check_eob(a_x)) return false; m_r_4_func(m_pos,(char*)&a_x); m_pos += sizeof(int); return true; } bool read(int64& a_x){ if(!_check_eob(a_x)) return false; m_r_8_func(m_pos,(char*)&a_x); m_pos += 8; return true; } bool read(std::string& a_x) { unsigned char nwh; if(!read(nwh)) {a_x.clear();return false;} int nchars; if(nwh == 255) { if(!read(nchars)) {a_x.clear();return false;} } else { nchars = nwh; } if(nchars<0) { m_out << s_class() << "::read(string) :" << " negative char number " << nchars << "." << std::endl; a_x.clear(); return false; } if((m_pos+nchars)>m_eob) { m_out << s_class() << "::read(string) :" << " try to access out of buffer " << long_out(nchars) << " bytes " << " (pos=" << charp_out(m_pos) << ", eob=" << charp_out(m_eob) << ")." << std::endl; a_x.clear(); return false; } a_x.resize(nchars); ::memcpy((char*)a_x.c_str(),m_pos,nchars); m_pos += nchars; return true; } bool read(bool& x){ unsigned char uc = 0; bool status = read(uc); x = uc?true:false; return status; } bool read(std::vector& a_a) { int n; if(!read(n)) {a_a.clear();return false;} for(int index=0;index bool read_fast_array(T* a_a,uint32 a_n){ if(!a_n) return true; uint32 l = a_n * sizeof(T); if(!check_eob(l)) { m_out << s_class() << "::read_fast_array :" << " try to access out of buffer " << long_out(l) << " bytes " << " (pos=" << charp_out(m_pos) << ", eob=" << charp_out(m_eob) << ")." << std::endl; return false; } if(m_byte_swap) { for(uint32 i=0;i bool read_array(uint32 a_sz,T*& a_a,uint32& a_n) { a_n = 0; {int n; if(!read(n)) {a_n = 0;return false;} a_n = n;} if(!a_n) return true; uint32 l = a_n * sizeof(T); if(!check_eob(l)) return false; bool owner = false; if(!a_a) { //ignore a_sz a_a = new T[a_n]; if(!a_a) {a_n=0;return false;} owner = true; } else { if(a_n>a_sz) return false; } if(m_byte_swap) { for(uint32 i=0;i bool read_array(std::vector& a_v) { T* buffer = 0; uint32 n; if(!read_array(0,buffer,n)) {a_v.clear();return false;} if(!buffer) {a_v.clear();return true;} a_v.resize(n); for(uint32 index=0;index bool read_array2(std::vector< std::vector >& a_v) { int n; if(!read(n)) {a_v.clear();return false;} a_v.resize(n); for(int index=0;indexm_eob) { m_out << "tools::rroot::rbuf::check_eob :" << " try to access out of buffer " << n << " bytes." << std::endl; return false; } return true; } protected: template bool _check_eob(T& a_x){ if((m_pos+sizeof(T))>m_eob) { a_x = T(); m_out << s_class() << " : " << stype(T()) << " : " << " try to access out of buffer " << long_out(sizeof(T)) << " bytes" << " (pos=" << charp_out(m_pos) << ", eob=" << charp_out(m_eob) << ")." << std::endl; return false; } return true; } protected: std::ostream& m_out; bool m_byte_swap; const char* m_eob; char*& m_pos; r_2_func m_r_2_func; r_4_func m_r_4_func; r_8_func m_r_8_func; }; }} #endif