Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_rroot_rbuf 5 #define tools_rroot_rbuf 6 7 #include "../stype" 8 #include "../long_out" 9 #include "../charp_out" 10 11 #ifdef TOOLS_MEM 12 #include "../mem" 13 #endif 14 15 #include <ostream> 16 #include <vector> 17 #include <cstring> //memcpy 18 19 namespace tools { 20 namespace rroot { 21 22 class rbuf { 23 24 ///////////////////////////////////////////////////////// 25 /// swap //////////////////////////////////////////////// 26 ///////////////////////////////////////////////////////// 27 // NOTE : on most common platforms (including Android, iPad) 28 // CERN-ROOT byte swaps ! (Bad luck). We have arranged to 29 // optimize this operation. The below "_swap_" functions 30 // do not have local variables and manipulates pointers 31 // directly. 32 33 static void read_swap_2(char* a_pos,char* a_x) { 34 *a_x++ = *(a_pos+1); 35 *a_x++ = *a_pos; 36 } 37 static void read_swap_4(char* a_pos,char* a_x) { 38 a_pos += 3; 39 *a_x++ = *a_pos--; 40 *a_x++ = *a_pos--; 41 *a_x++ = *a_pos--; 42 *a_x++ = *a_pos; 43 } 44 static void read_swap_8(char* a_pos,char* a_x) { 45 a_pos += 7; 46 *a_x++ = *a_pos--; 47 *a_x++ = *a_pos--; 48 *a_x++ = *a_pos--; 49 *a_x++ = *a_pos--; 50 *a_x++ = *a_pos--; 51 *a_x++ = *a_pos--; 52 *a_x++ = *a_pos--; 53 *a_x++ = *a_pos; 54 } 55 ///////////////////////////////////////////////////////// 56 /// nswp //////////////////////////////////////////////// 57 ///////////////////////////////////////////////////////// 58 static void read_nswp_2(char* a_pos,char* a_x) { 59 ::memcpy(a_x,a_pos,2); 60 } 61 static void read_nswp_4(char* a_pos,char* a_x) { 62 ::memcpy(a_x,a_pos,4); 63 } 64 static void read_nswp_8(char* a_pos,char* a_x) { 65 ::memcpy(a_x,a_pos,8); 66 } 67 ///////////////////////////////////////////////////////// 68 ///////////////////////////////////////////////////////// 69 ///////////////////////////////////////////////////////// 70 71 72 static const std::string& s_class() { 73 static const std::string s_v("tools::rroot::rbuf"); 74 return s_v; 75 } 76 typedef void (*r_2_func)(char*,char*); 77 typedef void (*r_4_func)(char*,char*); 78 typedef void (*r_8_func)(char*,char*); 79 public: 80 rbuf(std::ostream& a_out,bool a_byte_swap,const char* a_eob,char*& a_pos) 81 :m_out(a_out) 82 ,m_byte_swap(a_byte_swap) 83 ,m_eob(a_eob) 84 ,m_pos(a_pos) 85 86 ,m_r_2_func(0) 87 ,m_r_4_func(0) 88 ,m_r_8_func(0) 89 { 90 #ifdef TOOLS_MEM 91 mem::increment(s_class().c_str()); 92 #endif 93 set_byte_swap(a_byte_swap); 94 } 95 virtual ~rbuf(){ 96 #ifdef TOOLS_MEM 97 mem::decrement(s_class().c_str()); 98 #endif 99 } 100 public: 101 rbuf(const rbuf& a_from) 102 :m_out(a_from.m_out) 103 ,m_byte_swap(a_from.m_byte_swap) 104 ,m_eob(a_from.m_eob) 105 ,m_pos(a_from.m_pos) 106 ,m_r_2_func(a_from.m_r_2_func) 107 ,m_r_4_func(a_from.m_r_4_func) 108 ,m_r_8_func(a_from.m_r_8_func) 109 { 110 #ifdef TOOLS_MEM 111 mem::increment(s_class().c_str()); 112 #endif 113 set_byte_swap(a_from.m_byte_swap); 114 } 115 rbuf& operator=(const rbuf& a_from){ 116 set_byte_swap(a_from.m_byte_swap); 117 m_eob = a_from.m_eob; 118 //m_pos is a ref. 119 m_r_2_func = a_from.m_r_2_func; 120 m_r_4_func = a_from.m_r_4_func; 121 m_r_8_func = a_from.m_r_8_func; 122 return *this; 123 } 124 public: 125 std::ostream& out() const {return m_out;} 126 127 void skip(unsigned int a_num) {m_pos += a_num;} 128 129 void set_eob(const char* a_eob){m_eob = a_eob;} 130 char*& pos() {return m_pos;} 131 const char* eob() const {return m_eob;} 132 133 void set_byte_swap(bool a_value) { 134 m_byte_swap = a_value; 135 if(m_byte_swap) { 136 m_r_2_func = read_swap_2; 137 m_r_4_func = read_swap_4; 138 m_r_8_func = read_swap_8; 139 } else { 140 m_r_2_func = read_nswp_2; 141 m_r_4_func = read_nswp_4; 142 m_r_8_func = read_nswp_8; 143 } 144 } 145 public: 146 bool read(unsigned char& a_x) { 147 if(!_check_eob<unsigned char>(a_x)) return false; 148 a_x = *m_pos;m_pos++; 149 return true; 150 } 151 bool read(unsigned short& a_x) { 152 if(!_check_eob<unsigned short>(a_x)) return false; 153 m_r_2_func(m_pos,(char*)&a_x); 154 m_pos += sizeof(unsigned short); 155 return true; 156 } 157 158 bool read(unsigned int& a_x) { 159 if(!_check_eob<unsigned int>(a_x)) return false; 160 m_r_4_func(m_pos,(char*)&a_x); 161 m_pos += sizeof(unsigned int); 162 return true; 163 } 164 165 bool read(uint64& a_x){ 166 if(!_check_eob<uint64>(a_x)) return false; 167 m_r_8_func(m_pos,(char*)&a_x); 168 m_pos += 8; 169 return true; 170 } 171 172 bool read(float& a_x) { 173 if(!_check_eob<float>(a_x)) return false; 174 m_r_4_func(m_pos,(char*)&a_x); 175 m_pos += sizeof(float); 176 return true; 177 } 178 179 bool read(double& a_x) { 180 if(!_check_eob<double>(a_x)) return false; 181 m_r_8_func(m_pos,(char*)&a_x); 182 m_pos += sizeof(double); 183 return true; 184 } 185 186 bool read(char& a_x) { 187 if(!_check_eob<char>(a_x)) return false; 188 a_x = *m_pos;m_pos++; 189 return true; 190 } 191 bool read(short& a_x) { 192 if(!_check_eob<short>(a_x)) return false; 193 m_r_2_func(m_pos,(char*)&a_x); 194 m_pos += sizeof(short); 195 return true; 196 } 197 198 bool read(int& a_x) { 199 if(!_check_eob<int>(a_x)) return false; 200 m_r_4_func(m_pos,(char*)&a_x); 201 m_pos += sizeof(int); 202 return true; 203 } 204 205 bool read(int64& a_x){ 206 if(!_check_eob<int64>(a_x)) return false; 207 m_r_8_func(m_pos,(char*)&a_x); 208 m_pos += 8; 209 return true; 210 } 211 212 bool read(std::string& a_x) { 213 unsigned char nwh; 214 if(!read(nwh)) {a_x.clear();return false;} 215 int nchars; 216 if(nwh == 255) { 217 if(!read(nchars)) {a_x.clear();return false;} 218 } else { 219 nchars = nwh; 220 } 221 if(nchars<0) { 222 m_out << s_class() << "::read(string) :" 223 << " negative char number " << nchars << "." << std::endl; 224 a_x.clear(); 225 return false; 226 } 227 if((m_pos+nchars)>m_eob) { 228 m_out << s_class() << "::read(string) :" 229 << " try to access out of buffer " << long_out(nchars) << " bytes " 230 << " (pos=" << charp_out(m_pos) 231 << ", eob=" << charp_out(m_eob) << ")." << std::endl; 232 a_x.clear(); 233 return false; 234 } 235 a_x.resize(nchars); 236 ::memcpy((char*)a_x.c_str(),m_pos,nchars); 237 m_pos += nchars; 238 return true; 239 } 240 241 bool read(bool& x){ 242 unsigned char uc = 0; 243 bool status = read(uc); 244 x = uc?true:false; 245 return status; 246 } 247 bool read(std::vector<std::string>& a_a) { 248 int n; 249 if(!read(n)) {a_a.clear();return false;} 250 for(int index=0;index<n;index++) { 251 std::string _s; 252 if(!read(_s)) {a_a.clear();return false;} 253 a_a.push_back(_s); 254 } 255 return true; 256 } 257 258 ////////////////////////////////////////////////////////////// 259 ////////////////////////////////////////////////////////////// 260 ////////////////////////////////////////////////////////////// 261 bool read_fast_array(bool* b,uint32 n){ 262 if(!n) return true; 263 uint32 l = n * sizeof(unsigned char); 264 if(!check_eob(l)) return false; 265 for(uint32 i = 0; i < n; i++) { 266 unsigned char uc; 267 if(!read(uc)) return false; 268 b[i] = uc?true:false; 269 } 270 return true; 271 } 272 bool read_fast_array(char* c,uint32 n){ 273 if(!n) return true; 274 uint32 l = n * sizeof(char); 275 if(!check_eob(l)) return false; 276 ::memcpy(c,m_pos,l); 277 m_pos += l; 278 return true; 279 } 280 bool read_fast_array(unsigned char* c,uint32 n){ 281 if(!n) return true; 282 uint32 l = n * sizeof(unsigned char); 283 if(!check_eob(l)) return false; 284 ::memcpy(c, m_pos, l); 285 m_pos += l; 286 return true; 287 } 288 289 template <class T> 290 bool read_fast_array(T* a_a,uint32 a_n){ 291 if(!a_n) return true; 292 293 uint32 l = a_n * sizeof(T); 294 if(!check_eob(l)) { 295 m_out << s_class() << "::read_fast_array :" 296 << " try to access out of buffer " << long_out(l) << " bytes " 297 << " (pos=" << charp_out(m_pos) 298 << ", eob=" << charp_out(m_eob) << ")." << std::endl; 299 return false; 300 } 301 302 if(m_byte_swap) { 303 for(uint32 i=0;i<a_n;i++) { 304 if(!read(*(a_a+i))) return false; 305 } 306 } else { 307 ::memcpy(a_a,m_pos,l); 308 m_pos += l; 309 } 310 return true; 311 } 312 313 template <class T> 314 bool read_array(uint32 a_sz,T*& a_a,uint32& a_n) { 315 a_n = 0; 316 {int n; 317 if(!read(n)) {a_n = 0;return false;} 318 a_n = n;} 319 320 if(!a_n) return true; 321 322 uint32 l = a_n * sizeof(T); 323 if(!check_eob(l)) return false; 324 325 bool owner = false; 326 if(!a_a) { 327 //ignore a_sz 328 a_a = new T[a_n]; 329 if(!a_a) {a_n=0;return false;} 330 owner = true; 331 } else { 332 if(a_n>a_sz) return false; 333 } 334 335 if(m_byte_swap) { 336 for(uint32 i=0;i<a_n;i++) { 337 if(!read(*(a_a+i))) { 338 if(owner) {delete [] a_a;a_a = 0;} 339 a_n = 0; 340 return false; 341 } 342 } 343 } else { 344 ::memcpy(a_a,m_pos,l); 345 m_pos += l; 346 } 347 return true; 348 } 349 350 template <class T> 351 bool read_array(std::vector<T>& a_v) { 352 T* buffer = 0; 353 uint32 n; 354 if(!read_array(0,buffer,n)) {a_v.clear();return false;} 355 if(!buffer) {a_v.clear();return true;} 356 a_v.resize(n); 357 for(uint32 index=0;index<n;index++) { 358 a_v[index] = buffer[index]; 359 } 360 delete [] buffer; 361 return true; 362 } 363 364 template <class T> 365 bool read_array2(std::vector< std::vector<T> >& a_v) { 366 int n; 367 if(!read(n)) {a_v.clear();return false;} 368 a_v.resize(n); 369 for(int index=0;index<n;index++) { 370 if(!read_array(a_v[index])) return false; 371 } 372 return true; 373 } 374 375 bool check_eob(uint32 n){ 376 if((m_pos+n)>m_eob) { 377 m_out << "tools::rroot::rbuf::check_eob :" 378 << " try to access out of buffer " << n << " bytes." 379 << std::endl; 380 return false; 381 } 382 return true; 383 } 384 385 protected: 386 template <class T> 387 bool _check_eob(T& a_x){ 388 if((m_pos+sizeof(T))>m_eob) { 389 a_x = T(); 390 m_out << s_class() << " : " << stype(T()) << " : " 391 << " try to access out of buffer " << long_out(sizeof(T)) << " bytes" 392 << " (pos=" << charp_out(m_pos) 393 << ", eob=" << charp_out(m_eob) << ")." << std::endl; 394 return false; 395 } 396 return true; 397 } 398 399 protected: 400 std::ostream& m_out; 401 bool m_byte_swap; 402 const char* m_eob; 403 char*& m_pos; 404 405 r_2_func m_r_2_func; 406 r_4_func m_r_4_func; 407 r_8_func m_r_8_func; 408 }; 409 410 }} 411 412 #endif