Warning, /include/Geant4/tools/wroot/directory is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_wroot_directory
0005 #define tools_wroot_directory
0006
0007 #include "idir"
0008
0009 #include "date"
0010 #include "key"
0011 #include "ifile"
0012 #include "date"
0013 #include "buffer"
0014 #include "iobject"
0015
0016 #include "../strip"
0017 #include "../vmanip"
0018 #include "../forit"
0019
0020 #include <vector>
0021 #include <list>
0022
0023 namespace tools {
0024 namespace wroot {
0025
0026 class directory : public virtual idir {
0027 static uint32 class_version() {return 1;}
0028 public:
0029 static const std::string& s_class() {
0030 static const std::string s_v("tools::wroot::directory");
0031 return s_v;
0032 }
0033 public: //idir
0034 virtual ifile& file() {return m_file;}
0035 virtual seek seek_directory() const {return m_seek_directory;}
0036 virtual void append_object(iobject* a_object) {m_objs.push_back(a_object);} //take ownership of a_object
0037 public:
0038 directory(ifile& a_file)
0039 :m_file(a_file)
0040 ,m_parent(0)
0041 ,m_is_valid(false)
0042 ,m_date_C(0)
0043 ,m_date_M(0)
0044 ,m_nbytes_keys(0)
0045 ,m_nbytes_name(0)
0046 ,m_seek_directory(0)
0047 ,m_seek_parent(0)
0048 ,m_seek_keys(0)
0049 {
0050 }
0051 directory(ifile& a_file,const std::string& a_name,const std::string& a_title)
0052 :m_file(a_file)
0053 ,m_parent(0)
0054 ,m_is_valid(false)
0055 ,m_name(a_name)
0056 ,m_title(a_title)
0057 ,m_nbytes_keys(0)
0058 ,m_nbytes_name(0)
0059 ,m_seek_directory(0)
0060 ,m_seek_parent(0)
0061 ,m_seek_keys(0)
0062 {
0063 m_date_C = get_date();
0064 m_date_M = get_date();
0065
0066 if(m_name.empty()) {
0067 m_file.out() << "tools::wroot::directory::directory :"
0068 << " directory name cannot be \"\"."
0069 << std::endl;
0070 return; //FIXME : throw
0071 }
0072 if(m_name.find('/')!=std::string::npos) {
0073 m_file.out() << "tools::wroot::directory::directory :"
0074 << " directory name " << sout(m_name)
0075 << " cannot contain a slash."
0076 << std::endl;
0077 return; //FIXME : throw
0078 }
0079 if(m_title.empty()) m_title = m_name;
0080 m_is_valid = true;
0081 }
0082 directory(ifile& a_file,
0083 directory* a_parent, //assume a_parent not nul.
0084 const std::string& a_name,
0085 const std::string& a_title)
0086 :m_file(a_file)
0087 ,m_parent(a_parent)
0088 ,m_is_valid(false)
0089 ,m_name(a_name)
0090 ,m_title(a_title)
0091 ,m_nbytes_keys(0)
0092 ,m_nbytes_name(0)
0093 ,m_seek_directory(0)
0094 ,m_seek_parent(0)
0095 ,m_seek_keys(0)
0096 {
0097 m_date_C = get_date();
0098 m_date_M = get_date();
0099
0100 if(m_name.empty()) {
0101 m_file.out() << "tools::wroot::directory::directory :"
0102 << " directory name cannot be \"\"."
0103 << std::endl;
0104 return; //FIXME : throw
0105 }
0106 if(m_name.find('/')!=std::string::npos) {
0107 m_file.out() << "tools::wroot::directory::directory :"
0108 << " directory name " << sout(m_name)
0109 << " cannot contain a slash."
0110 << std::endl;
0111 return; //FIXME : throw
0112 }
0113
0114 if(m_title.empty()) m_title = m_name;
0115
0116 if(m_parent->find_key(m_name)) {
0117 m_file.out() << "tools::wroot::directory::directory :"
0118 << " directory " << sout(m_name) << " exists already."
0119 << std::endl;
0120 return; //FIXME : throw
0121 }
0122
0123 m_seek_parent = m_parent->seek_directory();
0124 uint32 nbytes = record_size();
0125
0126 wroot::key* key = new wroot::key(m_file.out(),m_file,m_parent->seek_directory(),
0127 m_name,m_title,"TDirectory",nbytes); // It does a m_file.set_END().
0128 m_nbytes_name = key->key_length();
0129 m_seek_directory = key->seek_key(); //at EOF
0130 if(!m_seek_directory) {
0131 m_file.out() << "tools::wroot::directory::directory :"
0132 << " bad key."
0133 << std::endl;
0134 delete key;
0135 return; //FIXME : throw
0136 }
0137 {char* buffer = key->data_buffer();
0138 wbuf wb(m_file.out(),m_file.byte_swap(),key->eob(),buffer);
0139 if(!to_buffer(wb)) {
0140 m_file.out() << "tools::wroot::directory::directory :"
0141 << " directory name " << sout(m_name)
0142 << " cannot fill buffer."
0143 << std::endl;
0144 delete key;
0145 return; //FIXME : throw
0146 }}
0147 uint16 cycle = m_parent->append_key(key);
0148 key->set_cycle(cycle);
0149 if(!key->write_self(m_file)) {
0150 m_file.out() << "tools::wroot::directory::directory :"
0151 << " key.write_self() failed."
0152 << std::endl;
0153 return; //FIXME : throw
0154 }
0155 uint32 n;
0156 if(!key->write_file(m_file,n)) {
0157 m_file.out() << "tools::wroot::directory::directory :"
0158 << " directory name " << sout(m_name)
0159 << " cannot write key to file."
0160 << std::endl;
0161 return; //FIXME : throw
0162 }
0163
0164 m_is_valid = true;
0165 }
0166 virtual ~directory(){
0167 clear_dirs();
0168 clear_objs();
0169 clear_keys();
0170 }
0171 protected:
0172 directory(const directory& a_from)
0173 :idir(a_from)
0174 ,m_file(a_from.m_file)
0175 ,m_parent(0)
0176 ,m_is_valid(false){
0177 }
0178 directory& operator=(const directory &){
0179 m_is_valid = false;
0180 return *this;
0181 }
0182 public:
0183 bool is_valid() const {return m_is_valid;}
0184 void set_seek_directory(seek a_seek) {m_seek_directory = a_seek;}
0185
0186 directory* mkdir(const std::string& a_name,const std::string& a_title = ""){
0187 // Create a sub-directory and return a pointer to the created directory.
0188 // Note that the directory name cannot contain slashes.
0189 if(a_name.empty()) {
0190 m_file.out() << "tools::wroot::directory::mkdir :"
0191 << " directory name cannot be \"\"."
0192 << std::endl;
0193 return 0;
0194 }
0195 if(a_name.find('/')!=std::string::npos) {
0196 m_file.out() << "tools::wroot::directory::mkdir :"
0197 << " " << sout(a_name)
0198 << " cannot contain a slash."
0199 << std::endl;
0200 return 0;
0201 }
0202 directory* dir = new directory(m_file,this,a_name,a_title.empty()?a_name:a_title);
0203 if(!dir->is_valid()) {
0204 m_file.out() << "tools::wroot::directory::mkdir :"
0205 << " directory badly created."
0206 << std::endl;
0207 delete dir;
0208 return 0;
0209 }
0210 m_dirs.push_back(dir);
0211 return dir;
0212 }
0213
0214 //uint32 nbytes_name() const {return m_nbytes_name;}
0215 void set_nbytes_name(uint32 a_n) {m_nbytes_name = a_n;}
0216
0217 uint32 record_size() const {
0218 uint32 nbytes = sizeof(short);
0219 nbytes += sizeof(date); //m_date_C.record_size();
0220 nbytes += sizeof(date); //m_date_M.record_size();
0221 nbytes += sizeof(m_nbytes_keys);
0222 nbytes += sizeof(m_nbytes_name);
0223 //ROOT version >= 40000:
0224 nbytes += sizeof(seek);
0225 nbytes += sizeof(seek);
0226 nbytes += sizeof(seek);
0227 return nbytes;
0228 }
0229
0230 bool close() {
0231 if(!save()) return false;
0232 clear_dirs();
0233 clear_objs();
0234 clear_keys();
0235 return true;
0236 }
0237
0238 bool to_buffer(wbuf& a_wb){
0239 // Decode input buffer.
0240 // (Name, title) are stored in the (name, title) of the associated key.
0241 short version = class_version();
0242 version += big_file_version_tag(); //GB : enforce writing on seek (and not seek32).
0243 if(!a_wb.write(version)) return false;
0244 if(!a_wb.write(m_date_C)) return false;
0245 if(!a_wb.write(m_date_M)) return false;
0246 if(!a_wb.write(m_nbytes_keys)) return false;
0247 if(!a_wb.write(m_nbytes_name)) return false;
0248
0249 if(!a_wb.write(m_seek_directory)) return false;
0250 if(!a_wb.write(m_seek_parent)) return false;
0251 if(!a_wb.write(m_seek_keys)) return false;
0252
0253 if(m_file.verbose()) {
0254 m_file.out() << "tools::wroot::key::to_buffer :"
0255 << " nbytes keys : " << m_nbytes_keys
0256 << ", pos keys : " << m_seek_keys
0257 << std::endl;
0258 }
0259 return true;
0260 }
0261
0262 bool write(uint32& a_nbytes){
0263 // Write all objects in memory to disk.
0264 // Loop on all objects in memory (including subdirectories).
0265 // A new key is created in the m_keys linked list for each object.
0266 // For allowed options see TObject::Write().
0267 // The directory header info is rewritten on the directory header record
0268 a_nbytes = 0;
0269 if(m_file.verbose()) {
0270 m_file.out() << "tools::wroot::directory::write :"
0271 << " " << sout(m_name)
0272 << " : " << m_dirs.size()
0273 << " : " << m_objs.size()
0274 << " objects."
0275 << std::endl;
0276 }
0277
0278 uint32 nbytes = 0;
0279
0280 {tools_vforcit(directory*,m_dirs,it) {
0281 uint32 n;
0282 if(!(*it)->write(n)) return false;
0283 nbytes += n;
0284 }}
0285
0286 {tools_vforit(iobject*,m_objs,it) {
0287 uint32 n;
0288 if(!write_object(*(*it),n)) {
0289 m_file.out() << "tools::wroot::directory::write :"
0290 << " for directory " << sout(m_name)
0291 << ", write_object " << sout((*it)->name())
0292 << " failed."
0293 << std::endl;
0294 return false;
0295 }
0296 nbytes += n;
0297 }}
0298
0299 if(!save_self()) {
0300 m_file.out() << "tools::wroot::directory::write :"
0301 << " for directory " << sout(m_name)
0302 << ", save_self failed."
0303 << std::endl;
0304 return false; //it will write keys of objects.
0305 }
0306
0307 a_nbytes = nbytes;
0308 return true;
0309 }
0310
0311 void clear_dirs() {safe_clear<directory>(m_dirs);}
0312 void clear_objs() {safe_clear<iobject>(m_objs);}
0313
0314 const std::list<key*>& keys() const {return m_keys;}
0315
0316 protected:
0317 void clear_keys() {
0318 std::list<key*>::iterator it;
0319 for(it=m_keys.begin();it!=m_keys.end();) {
0320 key* k = *it;
0321 it = m_keys.erase(it);
0322 delete k;
0323 }
0324 m_keys.clear();
0325 }
0326
0327 bool save(){
0328 if(!save_self()) return false;
0329 tools_vforit(directory*,m_dirs,it) {
0330 if(!(*it)->save()) return false;
0331 }
0332 return true;
0333 }
0334
0335 bool save_self() {
0336 // Save Directory keys and header :
0337 // If the directory has been modified (fModified set), write the keys
0338 // and the directory header.
0339 //if (fModified || aForce) {
0340 // if(!fFile.freeSegments().empty()) {
0341 // if(!writeKeys()) return false; // Write keys record.
0342 // if(!writeHeader()) return false; // Update directory record.
0343 // }
0344 //}
0345 if(!write_keys()) return false;
0346 if(!write_header()) return false;
0347 return true;
0348 }
0349
0350 key* find_key(const std::string& a_name) {
0351 if(m_file.verbose()) {
0352 m_file.out() << "tools::wroot::directory::find_key :"
0353 << " " << sout(a_name) << " ..."
0354 << std::endl;
0355 }
0356 tools_lforcit(key*,m_keys,it) {
0357 if((*it)->object_name()==a_name) return *it;
0358 }
0359
0360 return 0;
0361 }
0362 seek seek_keys() const {return m_seek_keys;}
0363
0364 uint16 append_key(key* a_key){ //take ownership of a_key
0365 tools_lforit(key*,m_keys,it) {
0366 if((*it)->object_name()==a_key->object_name()) {
0367 m_keys.insert(it,a_key); //a_key will be before *it.
0368 return ((*it)->cycle() + 1);
0369 }
0370 }
0371 // Not found :
0372 m_keys.push_back(a_key);
0373 return 1;
0374 }
0375
0376 bool write_keys(){
0377 // The list of keys (m_keys) is written as a single data record
0378 // Delete the old keys structure if it exists
0379
0380 // Write new keys record :
0381 uint32 nkeys = uint32(m_keys.size());
0382
0383 // Compute size of all keys
0384 uint32 nbytes = sizeof(nkeys);
0385
0386 {tools_lforit(key*,m_keys,it) {
0387 nbytes += (*it)->key_length();
0388 }}
0389
0390 key headerkey(m_file.out(),m_file,m_seek_directory,m_name,m_title,"TDirectory",nbytes); // m_file.set_END().
0391 if(!headerkey.seek_key()) return false;
0392
0393 {char* buffer = headerkey.data_buffer();
0394 wbuf wb(m_file.out(),m_file.byte_swap(),headerkey.eob(),buffer);
0395 if(!wb.write(nkeys)) return false;
0396 {tools_lforit(key*,m_keys,it) {
0397 if(!((*it)->to_buffer(wb,m_file.verbose()))) return false;
0398 }}}
0399
0400 m_seek_keys = headerkey.seek_key();
0401 m_nbytes_keys = headerkey.number_of_bytes();
0402
0403 if(m_file.verbose()) {
0404 m_file.out() << "tools::wroot::directory::write_keys :"
0405 << " write header key"
0406 << " " << sout(m_name)
0407 << " " << sout(m_title)
0408 << " (" << nkeys
0409 << ", " << nbytes
0410 << ", " << m_seek_keys
0411 << ", " << m_nbytes_keys
0412 << "):"
0413 << std::endl;
0414 }
0415
0416 headerkey.set_cycle(1);
0417 if(!headerkey.write_self(m_file)) {
0418 m_file.out() << "tools::wroot::directory::write_keys :"
0419 << " key.write_self() failed."
0420 << std::endl;
0421 return false;
0422 }
0423
0424 uint32 n;
0425 return headerkey.write_file(m_file,n);
0426 }
0427
0428 bool write_header(){
0429 // Overwrite the Directory header record.
0430 uint32 nbytes = record_size();
0431 char* header = new char[nbytes];
0432 char* buffer = header;
0433 m_date_M = get_date();
0434 wbuf wb(m_file.out(),m_file.byte_swap(),header+nbytes,buffer);
0435 if(!to_buffer(wb)) {
0436 delete [] header;
0437 return false;
0438 }
0439 // do not overwrite the name/title part
0440 seek pointer = m_seek_directory + m_nbytes_name;
0441 if(!m_file.set_pos(pointer)) {
0442 delete [] header;
0443 return false;
0444 }
0445 if(!m_file.write_buffer(header,nbytes)) {
0446 delete [] header;
0447 return false;
0448 }
0449 if(!m_file.synchronize()) {
0450 delete [] header;
0451 return false;
0452 }
0453 delete [] header;
0454 return true;
0455 }
0456
0457 bool write_object(iobject& a_obj,uint32& a_nbytes){
0458 buffer bref(m_file.out(),m_file.byte_swap(),256*128); //32768
0459 if(!a_obj.stream(bref)) {
0460 m_file.out() << "tools::wroot::directory::write_object :"
0461 << " cannot stream object of store class name "
0462 << " " << sout(a_obj.store_class_name()) << "."
0463 << std::endl;
0464 a_nbytes = 0;
0465 return false;
0466 }
0467
0468 std::string name = a_obj.name();
0469 strip(name);
0470
0471 //first create the key to get key_length();
0472
0473 wroot::key* key = new wroot::key(m_file.out(),m_file,m_seek_directory,
0474 name,
0475 a_obj.title(),a_obj.store_class_name(),
0476 bref.length()); // It does a m_file.set_END().
0477
0478 if(!key->seek_key()) {
0479 delete key;
0480 return false;
0481 }
0482
0483 if(!bref.displace_mapped(key->key_length())) { //done before compression.
0484 delete key;
0485 return false;
0486 }
0487
0488 char* kbuf = 0;
0489 uint32 klen = 0;
0490 bool kdelete = false;
0491 m_file.compress_buffer(bref,kbuf,klen,kdelete);
0492
0493 ::memcpy(key->data_buffer(),kbuf,klen);
0494 if(kdelete) delete [] kbuf;
0495
0496 {uint32 nkey = key->key_length()+klen;
0497 m_file.set_END(key->seek_key()+nkey);
0498 key->set_number_of_bytes(nkey);}
0499
0500 uint16 cycle = append_key(key);
0501 key->set_cycle(cycle);
0502
0503 if(!key->write_self(m_file)) {
0504 m_file.out() << "tools::wroot::directory::write_object :"
0505 << " key.write_self() failed."
0506 << std::endl;
0507 return false;
0508 }
0509
0510 //FIXME m_file.sumBuffer(key->object_size()); //uncompressed data size.
0511
0512 if(m_file.verbose()) {
0513 m_file.out() << "tools::wroot::directory::_write_buffer :"
0514 << " " << sout(a_obj.name()) << "."
0515 << std::endl;
0516 }
0517
0518 return key->write_file(m_file,a_nbytes);
0519 }
0520
0521 protected:
0522 ifile& m_file;
0523 directory* m_parent;
0524 bool m_is_valid;
0525 std::string m_name;
0526 std::string m_title;
0527 std::vector<directory*> m_dirs;
0528 std::vector<iobject*> m_objs;
0529 std::list<key*> m_keys;
0530 // Record (stored in file):
0531 date m_date_C; //Date and time when directory is created
0532 date m_date_M; //Date and time of last modification
0533 uint32 m_nbytes_keys; //Number of bytes for the keys
0534 uint32 m_nbytes_name; //Number of bytes in TNamed at creation time
0535 seek m_seek_directory; //Location of directory on file
0536 seek m_seek_parent; //Location of parent directory on file
0537 seek m_seek_keys; //Location of Keys record on file
0538 };
0539
0540 }}
0541
0542 #endif