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_basket 5 #define tools_rroot_basket 6 7 #include "iro" 8 #include "key" 9 10 #include "../scast" 11 #include "buffer" 12 #include "cids" 13 14 namespace tools { 15 namespace rroot { 16 17 class basket : public virtual iro, public key { 18 typedef key parent; 19 static uint32 kDisplacementMask() {return 0xFF000000;} 20 public: 21 static const std::string& s_class() { 22 static const std::string s_v("tools::rroot::basket"); 23 return s_v; 24 } 25 public: //iro 26 virtual void* cast(const std::string& a_class) const { 27 if(void* p = cmp_cast<basket>(this,a_class)) return p; 28 return 0; 29 } 30 virtual const std::string& s_cls() const {return s_class();} 31 public: 32 static cid id_class() {return basket_cid();} 33 virtual void* cast(cid a_class) const { 34 if(void* p = cmp_cast<basket>(this,a_class)) {return p;} 35 else return 0; 36 } 37 public: 38 virtual iro* copy() const {return new basket(*this);} 39 virtual bool stream(buffer& a_buffer) { 40 _clear(); 41 42 uint32 startpos = a_buffer.length(); 43 44 if(!parent::from_buffer(a_buffer.byte_swap(),a_buffer.eob(),a_buffer.pos(),a_buffer.verbose())) return false; 45 46 uint32 fBufferSize; 47 48 short v; 49 if(!a_buffer.read_version(v)) return false; 50 if(!a_buffer.read(fBufferSize)) return false; 51 if(!a_buffer.read(m_nev_buf_size)) return false; 52 if(!a_buffer.read(m_nev)) return false; 53 if(!a_buffer.read(m_last)) return false; 54 char flag; 55 if(!a_buffer.read(flag)) return false; 56 if(m_last>fBufferSize) fBufferSize = m_last; 57 58 uint16 basket_key_length = a_buffer.length()-startpos; 59 if(basket_key_length!=m_key_length) { 60 //m_out << "tools::rroot::basket::stream :" 61 // << " key length not consistent." 62 // << " read " << m_key_length 63 // << ", expected " << basket_key_length 64 // << ". Continue with " << basket_key_length 65 // << std::endl; 66 m_key_length = basket_key_length; 67 } 68 if(!m_object_size) { 69 //m_out << "tools::rroot::basket::stream :" 70 // << " m_object_size is found to be zero." 71 // << " Continue with (m_nbytes-m_key_length) " 72 // << (m_nbytes-m_key_length) 73 // << std::endl; 74 m_object_size = m_nbytes-m_key_length; 75 } 76 77 if(!flag) return true; //fHeaderOnly 78 79 //G.Barrand : add the below test. 80 if( (flag!=1) &&(flag!=2) && 81 (flag!=11)&&(flag!=12) && 82 (flag!=41)&&(flag!=42) && 83 (flag!=51)&&(flag!=52) ) { 84 m_out << "tools::rroot::basket::stream :" 85 << " bad flag " << (int)flag 86 << std::endl; 87 return false; 88 } 89 90 if((flag%10)!=2) { 91 //due to the upper "G.Barrand if", flag is here in {1,11,41,51} 92 93 if(!m_nev_buf_size) { 94 m_out << "tools::rroot::basket::stream :" 95 << " m_nev_buf_size is zero." << std::endl; 96 return false; 97 } 98 if(m_nev>m_nev_buf_size) { 99 m_out << "tools::rroot::basket::stream :" 100 << " m_nev>m_nev_buf_size !" 101 << " m_nev " << m_nev 102 << " m_nev_buf_size " << m_nev_buf_size 103 << std::endl; 104 return false; 105 } 106 m_entry_offset = new int[m_nev_buf_size]; 107 if(m_nev) { 108 uint32 n; 109 if(!a_buffer.read_array<int>(m_nev_buf_size,m_entry_offset,n)) { 110 _clear(); 111 return false; 112 } 113 if((n!=m_nev)&&(n!=(m_nev+1))) { 114 m_out << "tools::rroot::basket::stream :" 115 << " m_entry_offset read len mismatch." 116 << " n " << n 117 << " m_nev " << m_nev 118 << std::endl; 119 _clear(); 120 return false; 121 } 122 } 123 /* Due to the upper "G.Barrand if", flag can't be in ]20,40[, then to quiet Coverity we comment the below test. 124 if((20<flag)&&(flag<40)) { 125 for(uint32 i=0;i<m_nev;i++){ 126 m_entry_offset[i] &= ~kDisplacementMask(); 127 } 128 } 129 */ 130 if(flag>40) { 131 m_displacement = new int[m_nev_buf_size]; 132 uint32 n; 133 if(!a_buffer.read_array<int>(m_nev_buf_size,m_displacement,n)) { 134 _clear(); 135 return false; 136 } 137 if((n!=m_nev)&&(n!=(m_nev+1))) { 138 m_out << "tools::rroot::basket::stream :" 139 << " m_displacement read len mismatch." 140 << " n " << n 141 << " m_nev " << m_nev 142 << std::endl; 143 _clear(); 144 return false; 145 } 146 } 147 } else { 148 //m_nev_buf_size is the size in bytes of one entry. 149 } 150 if((flag==1)||(flag>10)) { 151 delete [] m_buffer; 152 m_buffer = 0; 153 m_buf_size = 0; 154 if(fBufferSize) { 155 char* _buf = new char[fBufferSize]; 156 if(!_buf) { 157 m_out << "tools::rroot::basket::stream :" 158 << " can't alloc " << fBufferSize << std::endl; 159 _clear(); 160 return false; 161 } 162 if(v>1) { 163 if(!a_buffer.read_fast_array(_buf,m_last)) { 164 _clear(); 165 delete [] _buf; 166 return false; 167 } 168 } else { 169 uint32 n; 170 if(!a_buffer.read_array<char>(fBufferSize,_buf,n)) { 171 _clear(); 172 delete [] _buf; 173 return false; 174 } 175 } 176 m_buffer = _buf; 177 m_buf_size = fBufferSize; 178 //fBufferRef->inline_setBufferOffset(m_last); 179 //fBranch.tree().incrementTotalBuffers(fBufferSize); 180 } 181 } 182 183 return true; 184 } 185 public: 186 basket(std::ostream& a_out) 187 :parent(a_out) 188 ,m_nev_buf_size(0) 189 ,m_nev(0) 190 ,m_last(0) 191 ,m_entry_offset(0) 192 ,m_displacement(0) 193 { 194 #ifdef TOOLS_MEM 195 mem::increment(s_class().c_str()); 196 #endif 197 } 198 basket(std::ostream& a_out,seek a_pos,uint32 a_nbytes) 199 :parent(a_out,a_pos,a_nbytes) 200 ,m_nev_buf_size(0) 201 ,m_nev(0) 202 ,m_last(0) 203 ,m_entry_offset(0) 204 ,m_displacement(0) 205 { 206 #ifdef TOOLS_MEM 207 mem::increment(s_class().c_str()); 208 #endif 209 } 210 virtual ~basket(){ 211 _clear(); 212 #ifdef TOOLS_MEM 213 mem::decrement(s_class().c_str()); 214 #endif 215 } 216 public: 217 basket(const basket& a_from) 218 :iro(a_from) 219 ,parent(a_from) 220 ,m_nev_buf_size(a_from.m_nev_buf_size) 221 ,m_nev(a_from.m_nev) 222 ,m_last(a_from.m_last) 223 ,m_entry_offset(0) 224 ,m_displacement(0) 225 { 226 #ifdef TOOLS_MEM 227 mem::increment(s_class().c_str()); 228 #endif 229 if(a_from.m_nev && a_from.m_entry_offset) { 230 m_entry_offset = new int[a_from.m_nev]; 231 if(!m_entry_offset) { 232 m_out << "tools::rroot::basket::basket(cpcstor) :" 233 << " can't alloc " << a_from.m_nev << "." 234 << std::endl; 235 } else { 236 uint32 len = a_from.m_nev*sizeof(int); 237 ::memcpy(m_entry_offset,a_from.m_entry_offset,len); 238 } 239 } 240 if(a_from.m_nev && a_from.m_displacement) { 241 m_displacement = new int[a_from.m_nev]; 242 if(!m_displacement) { 243 m_out << "tools::rroot::basket::basket(cpcstor) :" 244 << " can't alloc " << a_from.m_nev << "." 245 << std::endl; 246 } else { 247 uint32 len = a_from.m_nev*sizeof(int); 248 ::memcpy(m_displacement,a_from.m_displacement,len); 249 } 250 } 251 } 252 basket& operator=(const basket& a_from){ 253 parent::operator=(a_from); 254 255 if(&a_from==this) return *this; 256 257 m_nev_buf_size = a_from.m_nev_buf_size; 258 m_nev = a_from.m_nev; 259 m_last = a_from.m_last; 260 261 delete [] m_entry_offset; 262 m_entry_offset = 0; 263 delete [] m_displacement; 264 m_displacement = 0; 265 266 if(a_from.m_nev && a_from.m_entry_offset) { 267 m_entry_offset = new int[a_from.m_nev]; 268 if(!m_entry_offset) { 269 m_out << "tools::rroot::basket::operator=() :" 270 << " can't alloc " << a_from.m_nev << "." 271 << std::endl; 272 } else { 273 uint32 len = a_from.m_nev*sizeof(int); 274 ::memcpy(m_entry_offset,a_from.m_entry_offset,len); 275 } 276 } 277 if(a_from.m_nev && a_from.m_displacement) { 278 m_displacement = new int[a_from.m_nev]; 279 if(!m_displacement) { 280 m_out << "tools::rroot::basket::operator=() :" 281 << " can't alloc " << a_from.m_nev << "." 282 << std::endl; 283 } else { 284 uint32 len = a_from.m_nev*sizeof(int); 285 ::memcpy(m_displacement,a_from.m_displacement,len); 286 } 287 } 288 289 return *this; 290 } 291 public: 292 int* entry_offset() {return m_entry_offset;} 293 int* displacement() {return m_displacement;} 294 uint32 nev_buf_size() const {return m_nev_buf_size;} 295 uint32 nev() const {return m_nev;} 296 uint32 last() const {return m_last;} 297 298 bool read_offset_tables(bool a_byte_swap) { 299 if(!m_buffer) return false; 300 if(!m_last) return false; 301 302 delete [] m_entry_offset; 303 m_entry_offset = 0; 304 305 buffer _buffer(m_out,a_byte_swap,m_buf_size,m_buffer,0,false); 306 _buffer.set_offset(m_last); 307 308 {uint32 n; 309 if(!_buffer.read_array<int>(0,m_entry_offset,n)) { 310 m_out << "tools::rroot::basket::read_offset_tables :" 311 << " read_array failed." 312 << std::endl; 313 return false; 314 } 315 if((n!=m_nev)&&(n!=(m_nev+1))) { 316 m_out << "tools::rroot::basket::read_offset_tables :" 317 << " m_entry_offset read len mismatch." 318 << " n " << n 319 << " m_nev " << m_nev 320 << std::endl; 321 return false; 322 }} 323 324 delete [] m_displacement; 325 m_displacement = 0; 326 if(_buffer.length()!=_buffer.size()) { 327 // There is more data in the buffer! It is the diplacement 328 // array. 329 uint32 n; 330 if(!_buffer.read_array<int>(0,m_displacement,n)) { 331 m_out << "tools::rroot::basket::read_offset_tables :" 332 << " readArray(2) failed." 333 << std::endl; 334 return false; 335 } 336 if((n!=m_nev)&&(n!=(m_nev+1))) { 337 m_out << "tools::rroot::basket::read_offset_tables :" 338 << " m_displacement read len mismatch." 339 << " n " << n 340 << " m_nev " << m_nev 341 << std::endl; 342 return false; 343 } 344 } 345 346 return true; 347 } 348 349 protected: 350 void _clear(){ 351 delete [] m_entry_offset; 352 delete [] m_displacement; 353 m_entry_offset = 0; 354 m_displacement = 0; 355 } 356 protected: //Named 357 uint32 m_nev_buf_size; //Length in Int_t of m_entry_offset 358 uint32 m_nev; //Number of entries in basket 359 uint32 m_last; //Pointer to last used byte in basket 360 int* m_entry_offset; //[m_nev] Offset of entries in fBuffer(TKey) 361 int* m_displacement; //![m_nev] Displacement of entries in fBuffer(TKey) 362 }; 363 364 }} 365 366 #endif