inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/rroot/rbuf
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_rroot_rbuf
00005 #define inlib_rroot_rbuf
00006 
00007 #include "../pointer"
00008 #include "../stype"
00009 
00010 #include <ostream>
00011 #include <vector>
00012 
00013 #ifdef INLIB_MEM
00014 #include "../mem"
00015 #endif
00016 
00017 namespace inlib {
00018 namespace rroot {
00019 
00020 class rbuf {
00021 
00025   // NOTE : on most common platforms (including Android, iPad)
00026   //        CERN-ROOT byte swaps ! (Bad luck). We have arranged to
00027   //        optimize this operation. The below "_swap_" functions
00028   //        do not have local variables and manipulates pointers
00029   //        directly.
00030 
00031   static void read_swap_2(char* a_pos,char* a_x) {
00032     *a_x++ = *(a_pos+1);
00033     *a_x++ = *a_pos;
00034   }
00035   static void read_swap_4(char* a_pos,char* a_x) {
00036     a_pos += 3;
00037     *a_x++ = *a_pos--;
00038     *a_x++ = *a_pos--;
00039     *a_x++ = *a_pos--;
00040     *a_x++ = *a_pos;
00041   }
00042   static void read_swap_8(char* a_pos,char* a_x) {
00043     a_pos += 7;
00044     *a_x++ = *a_pos--;
00045     *a_x++ = *a_pos--;
00046     *a_x++ = *a_pos--;
00047     *a_x++ = *a_pos--;
00048     *a_x++ = *a_pos--;
00049     *a_x++ = *a_pos--;
00050     *a_x++ = *a_pos--;
00051     *a_x++ = *a_pos;
00052   }
00056   static void read_nswp_2(char* a_pos,char* a_x) {
00057     ::memcpy(a_x,a_pos,2);
00058   }
00059   static void read_nswp_4(char* a_pos,char* a_x) {
00060     ::memcpy(a_x,a_pos,4);
00061   }
00062   static void read_nswp_8(char* a_pos,char* a_x) {
00063     ::memcpy(a_x,a_pos,8);
00064   }
00068   
00069   
00070   static const std::string& s_class() {
00071     static const std::string s_v("inlib::rroot::rbuf");
00072     return s_v;
00073   }
00074   typedef void (*r_2_func)(char*,char*);
00075   typedef void (*r_4_func)(char*,char*);
00076   typedef void (*r_8_func)(char*,char*);
00077 public:
00078   rbuf(std::ostream& a_out,bool a_byte_swap,
00079               const char* a_eob,char*& a_pos)
00080   :m_out(a_out)
00081   ,m_byte_swap(a_byte_swap)
00082   ,m_eob(a_eob)
00083   ,m_pos(a_pos)
00084 
00085   ,m_r_2_func(0)
00086   ,m_r_4_func(0)
00087   ,m_r_8_func(0)
00088   {
00089 #ifdef INLIB_MEM
00090     mem::increment(s_class().c_str());
00091 #endif
00092     if(m_byte_swap) {
00093       m_r_2_func = read_swap_2;
00094       m_r_4_func = read_swap_4;
00095       m_r_8_func = read_swap_8;
00096     } else {
00097       m_r_2_func = read_nswp_2;
00098       m_r_4_func = read_nswp_4;
00099       m_r_8_func = read_nswp_8;
00100     }
00101   }
00102   virtual ~rbuf(){
00103 #ifdef INLIB_MEM
00104     mem::decrement(s_class().c_str());
00105 #endif
00106   }
00107 protected:
00108   rbuf(const rbuf& a_from)
00109   :m_out(a_from.m_out),m_eob(a_from.m_eob),m_pos(a_from.m_pos){
00110 #ifdef INLIB_MEM
00111     mem::increment(s_class().c_str());
00112 #endif
00113   }
00114   rbuf& operator=(const rbuf&){return *this;}
00115 public:
00116   std::ostream& out() const {return m_out;}
00117 
00118   void skip(unsigned int a_num) {m_pos += a_num;}
00119 
00120   void set_eob(const char* a_eob){m_eob = a_eob;}
00121   char*& pos() {return m_pos;}
00122   const char* eob() const {return m_eob;}
00123 
00124 public:
00125   bool read(unsigned char& a_x) {
00126     if(!_check_eob<unsigned char>(a_x)) return false;
00127     a_x = *m_pos++;
00128     return true;
00129   }
00130   bool read(unsigned short& a_x) {
00131     if(!_check_eob<unsigned short>(a_x)) return false;
00132     m_r_2_func(m_pos,(char*)&a_x);
00133     m_pos += sizeof(unsigned short);
00134     return true;
00135   }
00136 
00137   bool read(unsigned int& a_x) {
00138     if(!_check_eob<unsigned int>(a_x)) return false;
00139     m_r_4_func(m_pos,(char*)&a_x);
00140     m_pos += sizeof(unsigned int);
00141     return true;
00142   }
00143 
00144   bool read(uint64& a_x){
00145     if(!_check_eob<uint64>(a_x)) return false;
00146     m_r_8_func(m_pos,(char*)&a_x);
00147     m_pos += 8;
00148     return true;
00149   }
00150 
00151   bool read(float& a_x) {
00152     if(!_check_eob<float>(a_x)) return false;
00153     m_r_4_func(m_pos,(char*)&a_x);
00154     m_pos += sizeof(float);
00155     return true;
00156   }
00157 
00158   bool read(double& a_x) {
00159     if(!_check_eob<double>(a_x)) return false;
00160     m_r_8_func(m_pos,(char*)&a_x);
00161     m_pos += sizeof(double);
00162     return true;
00163   }
00164 
00165   bool read(char& a_x) {
00166     if(!_check_eob<char>(a_x)) return false;
00167     a_x = *m_pos++;
00168     return true;
00169   }
00170   bool read(short& a_x) {
00171     if(!_check_eob<short>(a_x)) return false;
00172     m_r_2_func(m_pos,(char*)&a_x);
00173     m_pos += sizeof(short);
00174     return true;
00175   }
00176 
00177   bool read(int& a_x) {
00178     if(!_check_eob<int>(a_x)) return false;
00179     m_r_4_func(m_pos,(char*)&a_x);
00180     m_pos += sizeof(int);
00181     return true;
00182   }
00183 
00184   bool read(int64& a_x){
00185     if(!_check_eob<int64>(a_x)) return false;
00186     m_r_8_func(m_pos,(char*)&a_x);
00187     m_pos += 8;
00188     return true;
00189   }
00190 
00191   bool read(std::string& a_x) {
00192     unsigned char nwh;
00193     if(!read(nwh)) {a_x.clear();return false;}
00194     int nchars;
00195     if(nwh == 255) {
00196       if(!read(nchars)) {a_x.clear();return false;}
00197     } else {
00198       nchars = nwh;
00199     }
00200     if(nchars<0) {
00201       m_out << s_class() << "::read(string) :"
00202             << " negative char number " << nchars << "." << std::endl;
00203       a_x.clear();
00204       return false;
00205     }
00206     if((m_pos+nchars)>m_eob) {
00207       m_out << s_class() << "::read(string) :"
00208             << " try to access out of buffer " << long2s(nchars) << " bytes "
00209             << " (pos=" << char_p2s(m_pos)
00210             << ", eob=" << char_p2s(m_eob) << ")." << std::endl;
00211       a_x.clear();
00212       return false;
00213     }
00214     a_x.resize(nchars);  
00215     ::memcpy((char*)a_x.c_str(),m_pos,nchars);
00216     m_pos += nchars;
00217     return true;
00218   }
00219 
00220   bool read(bool& x){ 
00221     unsigned char uc = 0;
00222     bool status = read(uc); 
00223     x = uc?true:false;
00224     return status;
00225   }
00226   bool read(std::vector<std::string>& a_a) {
00227     int n;
00228     if(!read(n)) {a_a.clear();return false;}
00229     for(int index=0;index<n;index++) {
00230       std::string s;
00231       if(!read(s)) {a_a.clear();return false;}
00232       a_a.push_back(s);
00233     }
00234     return true;
00235   }
00236 
00240   bool read_fast_array(bool* b,uint32 n){
00241     // Read array of n characters from the I/O buffer.
00242     if(!n) return true;
00243     uint32 l = n * sizeof(unsigned char);
00244     if(!check_eob(l)) return false;
00245     for(uint32 i = 0; i < n; i++) {
00246       unsigned char uc;
00247       if(!read(uc)) return false;
00248       b[i] = uc?true:false;
00249     }
00250     return true;
00251   }
00252   bool read_fast_array(char* c,uint32 n){
00253     // Read array of n characters from the I/O buffer.
00254     if(!n) return true;
00255     uint32 l = n * sizeof(char);
00256     if(!check_eob(l)) return false;
00257     ::memcpy(c,m_pos,l);
00258     m_pos += l;
00259     return true;
00260   }
00261   bool read_fast_array(unsigned char* c,uint32 n){
00262     // Read array of n characters from the I/O buffer.
00263     if(!n) return true;
00264     uint32 l = n * sizeof(unsigned char);
00265     if(!check_eob(l)) return false;
00266     ::memcpy(c, m_pos, l);
00267     m_pos += l;
00268     return true;
00269   }
00270 
00271   template <class T>
00272   bool read_fast_array(T* a_a,uint32 a_n){
00273     // Read array of n ints from the I/O buffer.
00274     if(!a_n) return true;
00275 
00276     uint32 l = a_n * sizeof(T);
00277     if(!check_eob(l)) {
00278       m_out << s_class() << "::read_fast_array :"
00279             << " try to access out of buffer " << long2s(l) << " bytes "
00280             << " (pos=" << char_p2s(m_pos)
00281             << ", eob=" << char_p2s(m_eob) << ")." << std::endl;
00282       return false;
00283     }
00284 
00285     if(m_byte_swap) {
00286       for(uint32 i=0;i<a_n;i++) {
00287         if(!read(*(a_a+i))) return false;
00288       }
00289     } else {
00290       ::memcpy(a_a,m_pos,l);
00291       m_pos += l;
00292     }
00293     return true;
00294   }
00295   
00296   template <class T>
00297   bool read_array(uint32 a_sz,T*& a_a,uint32& a_n) {
00298     a_n = 0;
00299    {int n;
00300     if(!read(n)) {a_n = 0;return false;}
00301     a_n = n;}
00302 
00303     if(!a_n) return true;
00304   
00305     uint32 l = a_n * sizeof(T);
00306     if(!check_eob(l)) return false;
00307 
00308     bool owner = false;
00309     if(!a_a) {
00310       //ignore a_sz
00311       a_a = new T[a_n];
00312       if(!a_a) {a_n=0;return false;}
00313       owner = true;
00314     } else {
00315       if(a_n>a_sz) return false;
00316     }
00317 
00318     if(m_byte_swap) {
00319       for(uint32 i=0;i<a_n;i++) {     
00320         if(!read(*(a_a+i))) {
00321           if(owner) {delete [] a_a;a_a = 0;}
00322           a_n = 0;
00323           return false;
00324         }
00325       }
00326     } else {
00327       ::memcpy(a_a,m_pos,l);
00328       m_pos += l;
00329     }
00330     return true;
00331   }
00332 
00333   bool check_eob(uint32 n){
00334     if((m_pos+n)>m_eob) {
00335       m_out << "inlib::rroot::rbuf::check_eob :"
00336             << " try to access out of buffer " << n << " bytes."
00337             << std::endl;
00338       return false;
00339     }
00340     return true;
00341   }
00342 
00343 protected:
00344   template <class T>
00345   bool _check_eob(T& a_x){
00346     if((m_pos+sizeof(T))>m_eob) {
00347       a_x = T();
00348       m_out << s_class() << " : " << stype(T()) << " : "
00349            << " try to access out of buffer " << long2s(sizeof(T)) << " bytes"
00350            << " (pos=" << char_p2s(m_pos)
00351            << ", eob=" << char_p2s(m_eob) << ")." << std::endl;
00352       return false;
00353     }
00354     return true;
00355   }
00356 protected:
00357   std::ostream& m_out;
00358   bool m_byte_swap;
00359   const char* m_eob;
00360   char*& m_pos;
00361 
00362   r_2_func m_r_2_func;
00363   r_4_func m_r_4_func;
00364   r_8_func m_r_8_func;
00365 };
00366 
00367 }}
00368 
00369 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines