inlib
1.2.0
|
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