Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 2 // See the file tools.license for terms. 3 3 4 #ifndef tools_wroot_file 4 #ifndef tools_wroot_file 5 #define tools_wroot_file 5 #define tools_wroot_file 6 6 7 #include "ifile" 7 #include "ifile" 8 8 9 #include "directory" 9 #include "directory" 10 10 11 #include "infos" 11 #include "infos" 12 #include "free_seg" 12 #include "free_seg" 13 13 14 #include "../platform" 14 #include "../platform" 15 15 16 #include "../path" 16 #include "../path" 17 17 18 #include <map> 18 #include <map> 19 19 20 #include <fcntl.h> 20 #include <fcntl.h> 21 #include <errno.h> 21 #include <errno.h> 22 #include <sys/stat.h> 22 #include <sys/stat.h> 23 23 24 #if defined(_MSC_VER) || defined(__MINGW32__) 24 #if defined(_MSC_VER) || defined(__MINGW32__) 25 #include <direct.h> 25 #include <direct.h> 26 #include <io.h> 26 #include <io.h> 27 #else 27 #else 28 #include <unistd.h> 28 #include <unistd.h> 29 #endif 29 #endif 30 30 31 namespace tools { 31 namespace tools { 32 namespace wroot { 32 namespace wroot { 33 33 34 class file : public virtual ifile { 34 class file : public virtual ifile { 35 file& get_me() {return *this;} //_MSC_VER : 35 file& get_me() {return *this;} //_MSC_VER : to avoid warning about the usage of "this" in the constructor. 36 static int not_open() {return -1;} 36 static int not_open() {return -1;} 37 static uint32 kBegin() {return 64;} 37 static uint32 kBegin() {return 64;} 38 public: 38 public: 39 static const std::string& s_class() { 39 static const std::string& s_class() { 40 static const std::string s_v("tools::wroot 40 static const std::string s_v("tools::wroot::file"); 41 return s_v; 41 return s_v; 42 } 42 } 43 virtual const std::string& s_cls() const {re 43 virtual const std::string& s_cls() const {return s_class();} 44 public: //ifile 44 public: //ifile 45 virtual bool verbose() const {return m_verbo 45 virtual bool verbose() const {return m_verbose;} 46 virtual std::ostream& out() const {return m_ 46 virtual std::ostream& out() const {return m_out;} 47 47 48 virtual bool byte_swap() const {return is_li 48 virtual bool byte_swap() const {return is_little_endian();} 49 virtual bool set_pos(seek a_offset = 0,from 49 virtual bool set_pos(seek a_offset = 0,from a_from = begin){ 50 int whence = 0; 50 int whence = 0; 51 switch(a_from) { 51 switch(a_from) { 52 case begin: 52 case begin: 53 whence = SEEK_SET; 53 whence = SEEK_SET; 54 break; 54 break; 55 case current: 55 case current: 56 whence = SEEK_CUR; 56 whence = SEEK_CUR; 57 break; 57 break; 58 case end: 58 case end: 59 whence = SEEK_END; 59 whence = SEEK_END; 60 break; 60 break; 61 } 61 } 62 62 63 #if defined(__linux__) && (__GLIBC__ == 2) && 63 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2) 64 if (::lseek64(m_file, a_offset, whence) < 64 if (::lseek64(m_file, a_offset, whence) < 0) { 65 #elif defined(_MSC_VER) || defined(__MINGW32__ 65 #elif defined(_MSC_VER) || defined(__MINGW32__) 66 if (::_lseeki64(m_file, a_offset, whence) 66 if (::_lseeki64(m_file, a_offset, whence) < 0) { 67 #else 67 #else 68 if (::lseek(m_file, a_offset, whence) < 0) 68 if (::lseek(m_file, a_offset, whence) < 0) { 69 #endif 69 #endif 70 m_out << "tools::wroot::file::set_pos :" 70 m_out << "tools::wroot::file::set_pos :" 71 << " cannot set position " << a_of 71 << " cannot set position " << a_offset 72 << " in file " << sout(m_path) << 72 << " in file " << sout(m_path) << "." 73 << std::endl; 73 << std::endl; 74 return false; 74 return false; 75 } 75 } 76 return true; 76 return true; 77 } 77 } 78 78 79 virtual seek END() const {return m_END;} 79 virtual seek END() const {return m_END;} 80 virtual void set_END(seek a_end){ 80 virtual void set_END(seek a_end){ 81 m_END = a_end; 81 m_END = a_end; 82 82 83 if(m_free_segs.empty()) { 83 if(m_free_segs.empty()) { 84 m_out << "tools::wroot::file::set_END :" 84 m_out << "tools::wroot::file::set_END :" 85 << " free_seg list should not be e 85 << " free_seg list should not be empty here." 86 << std::endl; 86 << std::endl; 87 } else { 87 } else { 88 free_seg* end_seg = m_free_segs.back(); 88 free_seg* end_seg = m_free_segs.back(); 89 if(end_seg->last()!=START_BIG_FILE()) { 89 if(end_seg->last()!=START_BIG_FILE()) { 90 m_out << "tools::wroot::file::set_END 90 m_out << "tools::wroot::file::set_END :" 91 << " last free_seg is not the en 91 << " last free_seg is not the ending of file one." 92 << " free_seg list looks corrupt 92 << " free_seg list looks corrupted." 93 << std::endl; 93 << std::endl; 94 } else { 94 } else { 95 m_free_segs.back()->set_first(m_END); 95 m_free_segs.back()->set_first(m_END); 96 } 96 } 97 } 97 } 98 } 98 } 99 99 100 virtual bool write_buffer(const char* a_buff 100 virtual bool write_buffer(const char* a_buffer,uint32 a_length) { 101 // Write a buffer to the file. This is the 101 // Write a buffer to the file. This is the basic low level write operation. 102 #ifdef _MSC_VER 102 #ifdef _MSC_VER 103 typedef int ssize_t; 103 typedef int ssize_t; 104 #endif 104 #endif 105 ssize_t siz; 105 ssize_t siz; 106 while ((siz = ::write(m_file,a_buffer,a_le 106 while ((siz = ::write(m_file,a_buffer,a_length)) < 0 && 107 error_number() == EINTR) reset_err 107 error_number() == EINTR) reset_error_number(); 108 108 109 if(siz < 0) { 109 if(siz < 0) { 110 m_out << "tools::wroot::file::write_buff 110 m_out << "tools::wroot::file::write_buffer :" 111 << " error writing to file " << so 111 << " error writing to file " << sout(m_path) << "." 112 << std::endl; 112 << std::endl; 113 return false; 113 return false; 114 } 114 } 115 if(siz!=(ssize_t)a_length) { 115 if(siz!=(ssize_t)a_length) { 116 m_out << "tools::wroot::file::write_buff 116 m_out << "tools::wroot::file::write_buffer :" 117 << "error writing all requested byt 117 << "error writing all requested bytes to file " << sout(m_path) 118 << ", wrote " << long_out(siz) << " 118 << ", wrote " << long_out(siz) << " of " << a_length 119 << std::endl; 119 << std::endl; 120 return false; 120 return false; 121 } 121 } 122 //m_bytes_write += siz; 122 //m_bytes_write += siz; 123 return true; 123 return true; 124 } 124 } 125 125 126 virtual uint32 version() const { 126 virtual uint32 version() const { 127 // Return version id as an integer, i.e. " 127 // Return version id as an integer, i.e. "2.22/04" -> 22204. 128 static const uint32 ROOT_MAJOR_VERSION = 4 128 static const uint32 ROOT_MAJOR_VERSION = 4; 129 static const uint32 ROOT_MINOR_VERSION = 0 129 static const uint32 ROOT_MINOR_VERSION = 0; 130 static const uint32 ROOT_PATCH_VERSION = 0 130 static const uint32 ROOT_PATCH_VERSION = 0; 131 return 131 return 132 10000 * ROOT_MAJOR_VERSION + 132 10000 * ROOT_MAJOR_VERSION + 133 100 * ROOT_MINOR_VERSION + 133 100 * ROOT_MINOR_VERSION + 134 ROOT_PATCH_VERSION; 134 ROOT_PATCH_VERSION; 135 } 135 } 136 136 137 virtual bool synchronize(){ 137 virtual bool synchronize(){ 138 // Synchornize a file's in-core and on-dis 138 // Synchornize a file's in-core and on-disk states. 139 #ifdef _MSC_VER 139 #ifdef _MSC_VER 140 if(::_commit(m_file)) { 140 if(::_commit(m_file)) { 141 m_out << "tools::wroot::file::synchroniz 141 m_out << "tools::wroot::file::synchronize :" 142 << " in _commit() for file " << so 142 << " in _commit() for file " << sout(m_path) << "." 143 << std::endl; 143 << std::endl; 144 return false; 144 return false; 145 } 145 } 146 #elif defined(__MINGW32__) 146 #elif defined(__MINGW32__) 147 return true; 147 return true; 148 #else 148 #else 149 if (::fsync(m_file) < 0) { 149 if (::fsync(m_file) < 0) { 150 m_out << "tools::wroot::file::synchroniz 150 m_out << "tools::wroot::file::synchronize :" 151 << " error in fsync() for file " < 151 << " error in fsync() for file " << sout(m_path) << "." 152 << std::endl; 152 << std::endl; 153 return false; 153 return false; 154 } 154 } 155 #endif 155 #endif 156 return true; 156 return true; 157 } 157 } 158 158 159 virtual bool ziper(char a_key,compress_func& 159 virtual bool ziper(char a_key,compress_func& a_func) const { 160 std::map<char,compress_func>::const_iterat 160 std::map<char,compress_func>::const_iterator it = m_zipers.find(a_key); 161 if(it==m_zipers.end()) { 161 if(it==m_zipers.end()) { 162 a_func = 0; 162 a_func = 0; 163 return false; 163 return false; 164 } 164 } 165 a_func = (*it).second; 165 a_func = (*it).second; 166 return true; 166 return true; 167 } 167 } 168 virtual uint32 compression() const {return m 168 virtual uint32 compression() const {return m_compress;} 169 virtual void compress_buffer(const buffer& a 169 virtual void compress_buffer(const buffer& a_buffer,char*& a_kbuf,uint32& a_klen,bool& a_kdel) { 170 //NOTE: if(kdelete) delete [] kbuf; << 170 //NOTE : if(kdelete) delete [] kbuf; 171 171 172 a_kbuf = 0; 172 a_kbuf = 0; 173 a_klen = 0; 173 a_klen = 0; 174 a_kdel = false; 174 a_kdel = false; 175 175 176 uint32 nbytes = a_buffer.length(); 176 uint32 nbytes = a_buffer.length(); 177 uint32 cxlevel = m_compress; 177 uint32 cxlevel = m_compress; 178 if(cxlevel && (nbytes>256)) { 178 if(cxlevel && (nbytes>256)) { 179 compress_func func; 179 compress_func func; 180 if(!ziper('Z',func)) { 180 if(!ziper('Z',func)) { 181 //m_out << "tools::wroot::file::compre << 181 //m_out << "tools::wroot::directory::write_object :" 182 // << " zlib ziper not found." 182 // << " zlib ziper not found." 183 // << std::endl; 183 // << std::endl; 184 a_kbuf = (char*)a_buffer.buf(); 184 a_kbuf = (char*)a_buffer.buf(); 185 a_klen = a_buffer.length(); 185 a_klen = a_buffer.length(); 186 a_kdel = false; 186 a_kdel = false; 187 } else { 187 } else { 188 const uint32 kMAXBUF = 0xffffff; 188 const uint32 kMAXBUF = 0xffffff; 189 const uint32 HDRSIZE = 9; 189 const uint32 HDRSIZE = 9; 190 uint32 nbuffers = nbytes/kMAXBUF; 190 uint32 nbuffers = nbytes/kMAXBUF; 191 uint32 buf_out_size = kMAXBUF+HDRSIZE+ << 191 uint32 buflen = nbytes+HDRSIZE*(nbuffers+1); 192 uint32 buflen = (nbuffers+1)*buf_out_s << 193 a_kbuf = new char[buflen]; 192 a_kbuf = new char[buflen]; 194 a_kdel = true; 193 a_kdel = true; 195 char* src = (char*)a_buffer.buf(); 194 char* src = (char*)a_buffer.buf(); 196 char* tgt = a_kbuf; 195 char* tgt = a_kbuf; 197 uint32 nzip = 0; 196 uint32 nzip = 0; 198 for(uint32 i=0;i<=nbuffers;i++) { 197 for(uint32 i=0;i<=nbuffers;i++) { 199 uint32 bufmax = ((i == nbuffers) ? n 198 uint32 bufmax = ((i == nbuffers) ? nbytes - nzip : kMAXBUF); 200 uint32 nout; 199 uint32 nout; 201 if(!zip(m_out,func,cxlevel,bufmax,sr << 200 if(!zip(m_out,func,cxlevel,bufmax,src,bufmax,tgt,nout)) { 202 delete [] a_kbuf; 201 delete [] a_kbuf; 203 a_kbuf = (char*)a_buffer.buf(); 202 a_kbuf = (char*)a_buffer.buf(); 204 a_klen = a_buffer.length(); 203 a_klen = a_buffer.length(); 205 a_kdel = false; 204 a_kdel = false; 206 return; << 205 break; 207 } 206 } 208 tgt += nout; //nout includes HDRSIZE 207 tgt += nout; //nout includes HDRSIZE 209 a_klen += nout; 208 a_klen += nout; 210 src += kMAXBUF; 209 src += kMAXBUF; 211 nzip += kMAXBUF; 210 nzip += kMAXBUF; 212 } 211 } 213 if(a_klen>=a_buffer.length()) { << 212 //::printf("debug : compress : end : %u %u\n",nbytes,klen); 214 //NOTE: It is in the ROOT/IO specifi << 215 // are detected at read time by << 216 // the overall output size (fNb << 217 // By using the zlib-ng compres << 218 // output size (a_klen here at << 219 // induces problem when reading << 220 delete [] a_kbuf; << 221 a_kbuf = (char*)a_buffer.buf(); << 222 a_klen = a_buffer.length(); << 223 a_kdel = false; << 224 } << 225 } 213 } 226 } else { 214 } else { 227 a_kbuf = (char*)a_buffer.buf(); 215 a_kbuf = (char*)a_buffer.buf(); 228 a_klen = a_buffer.length(); 216 a_klen = a_buffer.length(); 229 a_kdel = false; 217 a_kdel = false; 230 } 218 } 231 } 219 } 232 public: 220 public: 233 file(std::ostream& a_out,const std::string& 221 file(std::ostream& a_out,const std::string& a_path,bool a_verbose = false) 234 :m_out(a_out) 222 :m_out(a_out) 235 ,m_path(a_path) 223 ,m_path(a_path) 236 ,m_verbose(a_verbose) 224 ,m_verbose(a_verbose) 237 ,m_file(not_open()) 225 ,m_file(not_open()) 238 //,m_bytes_write(0) 226 //,m_bytes_write(0) 239 ,m_root_directory(get_me(),nosuffix(a_path), 227 ,m_root_directory(get_me(),nosuffix(a_path),m_title) 240 // begin of record : 228 // begin of record : 241 ,m_version(0) 229 ,m_version(0) 242 ,m_BEGIN(0) 230 ,m_BEGIN(0) 243 ,m_END(0) 231 ,m_END(0) 244 ,m_seek_free(0) 232 ,m_seek_free(0) 245 ,m_nbytes_free(0) 233 ,m_nbytes_free(0) 246 ,m_nbytes_name(0) 234 ,m_nbytes_name(0) 247 ,m_units(4) 235 ,m_units(4) 248 ,m_compress(1) 236 ,m_compress(1) 249 ,m_seek_info(0) 237 ,m_seek_info(0) 250 ,m_nbytes_info(0) 238 ,m_nbytes_info(0) 251 { 239 { 252 #ifdef TOOLS_MEM 240 #ifdef TOOLS_MEM 253 mem::increment(s_class().c_str()); 241 mem::increment(s_class().c_str()); 254 #endif 242 #endif 255 243 256 m_version = version(); 244 m_version = version(); 257 245 258 if(access_path(m_path,kFileExists)) unlink 246 if(access_path(m_path,kFileExists)) unlink(m_path); 259 247 260 if(!m_root_directory.is_valid()) { 248 if(!m_root_directory.is_valid()) { 261 m_out << "tools::wroot::file::file :" 249 m_out << "tools::wroot::file::file :" 262 << " " << sout(m_path) << " root d 250 << " " << sout(m_path) << " root directory badly created." 263 << std::endl; 251 << std::endl; 264 return; 252 return; 265 } 253 } 266 254 267 m_file = _open(a_path.c_str(), 255 m_file = _open(a_path.c_str(), 268 #if defined(_MSC_VER) || defined(__MINGW32__) 256 #if defined(_MSC_VER) || defined(__MINGW32__) 269 O_RDWR | O_CREA 257 O_RDWR | O_CREAT | O_BINARY,S_IREAD | S_IWRITE 270 #else 258 #else 271 O_RDWR | O_CREA 259 O_RDWR | O_CREAT,0644 272 #endif 260 #endif 273 ); 261 ); 274 if(m_file==not_open()) { 262 if(m_file==not_open()) { 275 m_out << "tools::wroot::file::file :" 263 m_out << "tools::wroot::file::file :" 276 << " can't open " << sout(a_path) 264 << " can't open " << sout(a_path) << "." 277 << std::endl; 265 << std::endl; 278 return; 266 return; 279 } 267 } 280 268 281 //initialize : 269 //initialize : 282 270 283 m_BEGIN = kBegin(); // First used word in 271 m_BEGIN = kBegin(); // First used word in file following the file header. 284 m_END = m_BEGIN; // Pointer to end of fi 272 m_END = m_BEGIN; // Pointer to end of file. 285 273 286 m_free_segs.push_back(new free_seg(m_out,m 274 m_free_segs.push_back(new free_seg(m_out,m_BEGIN,START_BIG_FILE())); 287 275 288 // Write Directory info : 276 // Write Directory info : 289 uint32 namelen = 277 uint32 namelen = 290 key::std_string_record_size(m_path) + 278 key::std_string_record_size(m_path) + 291 key::std_string_record_size(m_title); 279 key::std_string_record_size(m_title); 292 uint32 nbytes = namelen + m_root_directory 280 uint32 nbytes = namelen + m_root_directory.record_size(); 293 << 294 //TUUID version 1: << 295 nbytes += sizeof(unsigned int); << 296 nbytes += 2*sizeof(unsigned short); << 297 nbytes += 8*sizeof(unsigned char); << 298 << 299 wroot::key key(m_out,*this,0,m_path,m_titl 281 wroot::key key(m_out,*this,0,m_path,m_title,"TFile",nbytes); // It does a (*this).set_END(). 300 282 301 // m_nbytes_name = start point of director 283 // m_nbytes_name = start point of directory info from key head. 302 m_nbytes_name = key.key_length() + namelen 284 m_nbytes_name = key.key_length() + namelen; 303 m_root_directory.set_nbytes_name(m_nbytes_ 285 m_root_directory.set_nbytes_name(m_nbytes_name); 304 m_root_directory.set_seek_directory(key.se 286 m_root_directory.set_seek_directory(key.seek_key()); //at EOF. 305 287 306 //the below write 45 bytes at BOF (Begin O 288 //the below write 45 bytes at BOF (Begin Of File). 307 if(!write_header()) { //need m_nbytes_name 289 if(!write_header()) { //need m_nbytes_name, m_END after key written. 308 m_out << "tools::wroot::file::file :" 290 m_out << "tools::wroot::file::file :" 309 << " can't write file header." 291 << " can't write file header." 310 << std::endl; 292 << std::endl; 311 return; 293 return; 312 } 294 } 313 295 314 {char* pos = key.data_buffer(); 296 {char* pos = key.data_buffer(); 315 wbuf wb(m_out,byte_swap(),key.eob(),pos); 297 wbuf wb(m_out,byte_swap(),key.eob(),pos); 316 if(!wb.write(m_path)) return; 298 if(!wb.write(m_path)) return; 317 if(!wb.write(m_title)) return; 299 if(!wb.write(m_title)) return; 318 if(!m_root_directory.to_buffer(wb)) return << 300 if(!m_root_directory.to_buffer(wb)) return;} 319 //TUUID version 1: << 320 if(!wb.write((unsigned int)0)) return; << 321 if(!wb.write((unsigned short)0)) return; << 322 if(!wb.write((unsigned short)0)) return; << 323 {for(size_t count=0;count<8;count++) if(!wb << 324 301 325 if(m_verbose) { 302 if(m_verbose) { 326 m_out << "tools::wroot::file::file :" 303 m_out << "tools::wroot::file::file :" 327 << " write key (" 304 << " write key (" 328 << namelen 305 << namelen 329 << ", " 306 << ", " 330 << m_root_directory.record_size() 307 << m_root_directory.record_size() 331 << ", " 308 << ", " 332 << nbytes 309 << nbytes 333 << ", " 310 << ", " 334 << m_nbytes_name 311 << m_nbytes_name 335 << ", " 312 << ", " 336 << key.seek_key() 313 << key.seek_key() 337 << ")." 314 << ")." 338 << std::endl; 315 << std::endl; 339 } 316 } 340 317 341 key.set_cycle(1); 318 key.set_cycle(1); 342 if(!key.write_self(*this)) { 319 if(!key.write_self(*this)) { 343 m_out << "tools::wroot::file::file :" 320 m_out << "tools::wroot::file::file :" 344 << " key.write_self() failed." 321 << " key.write_self() failed." 345 << std::endl; 322 << std::endl; 346 return; 323 return; 347 } 324 } 348 325 349 //the below write at kBegin + nbytes. 326 //the below write at kBegin + nbytes. 350 //64+52 327 //64+52 351 uint32 n; 328 uint32 n; 352 if(!key.write_file(*this,n)) { 329 if(!key.write_file(*this,n)) { 353 m_out << "tools::wroot::file::file :" 330 m_out << "tools::wroot::file::file :" 354 << " can't write key in file." 331 << " can't write key in file." 355 << std::endl; 332 << std::endl; 356 return; 333 return; 357 } 334 } 358 //::printf("debug : file::file : write key 335 //::printf("debug : file::file : write key : %d\n",n); 359 336 360 } 337 } 361 virtual ~file() { 338 virtual ~file() { 362 close(); 339 close(); 363 #ifdef TOOLS_MEM 340 #ifdef TOOLS_MEM 364 mem::decrement(s_class().c_str()); 341 mem::decrement(s_class().c_str()); 365 #endif 342 #endif 366 } 343 } 367 protected: 344 protected: 368 file(const file& a_from) 345 file(const file& a_from) 369 :ifile(a_from) 346 :ifile(a_from) 370 ,m_out(a_from.m_out) 347 ,m_out(a_from.m_out) 371 ,m_root_directory(get_me()) 348 ,m_root_directory(get_me()) 372 { 349 { 373 #ifdef TOOLS_MEM 350 #ifdef TOOLS_MEM 374 mem::increment(s_class().c_str()); 351 mem::increment(s_class().c_str()); 375 #endif 352 #endif 376 } 353 } 377 file& operator=(const file&){return *this;} 354 file& operator=(const file&){return *this;} 378 public: 355 public: 379 const std::string& path() const {return m_pa 356 const std::string& path() const {return m_path;} 380 357 381 void set_compression(uint32 a_level) { 358 void set_compression(uint32 a_level) { 382 // level = 0 objects written to this file 359 // level = 0 objects written to this file will not be compressed. 383 // level = 1 minimal compression level but 360 // level = 1 minimal compression level but fast. 384 // .... 361 // .... 385 // level = 9 maximal compression level but 362 // level = 9 maximal compression level but slow. 386 m_compress = a_level; 363 m_compress = a_level; 387 if(m_compress>9) m_compress = 9; 364 if(m_compress>9) m_compress = 9; 388 } 365 } 389 366 390 bool is_open() const {return (m_file==not_op 367 bool is_open() const {return (m_file==not_open()?false:true);} 391 368 392 void close() { 369 void close() { 393 if(m_file==not_open()) return; 370 if(m_file==not_open()) return; 394 m_root_directory.close(); 371 m_root_directory.close(); 395 372 396 if(m_free_segs.size()) { 373 if(m_free_segs.size()) { 397 if(!write_free_segments()) { 374 if(!write_free_segments()) { 398 m_out << "tools::wroot::file::close :" 375 m_out << "tools::wroot::file::close :" 399 << " can't write free segments." 376 << " can't write free segments." 400 << std::endl; 377 << std::endl; 401 } 378 } 402 if(!write_header()) { // Now write file 379 if(!write_header()) { // Now write file header 403 m_out << "tools::wroot::file::close :" 380 m_out << "tools::wroot::file::close :" 404 << " can't write file header." 381 << " can't write file header." 405 << std::endl; 382 << std::endl; 406 } 383 } 407 } 384 } 408 385 409 {std::list<free_seg*>::iterator it; 386 {std::list<free_seg*>::iterator it; 410 for(it=m_free_segs.begin(); 387 for(it=m_free_segs.begin(); 411 it!=m_free_segs.end(); 388 it!=m_free_segs.end(); 412 it = m_free_segs.erase(it)) { 389 it = m_free_segs.erase(it)) { 413 delete (*it); 390 delete (*it); 414 }} 391 }} 415 392 416 ::close(m_file); 393 ::close(m_file); 417 m_file = not_open(); 394 m_file = not_open(); 418 } 395 } 419 396 420 directory& dir() {return m_root_directory;} 397 directory& dir() {return m_root_directory;} 421 const directory& dir() const {return m_root_ 398 const directory& dir() const {return m_root_directory;} 422 399 423 bool write(uint32& a_nbytes){ 400 bool write(uint32& a_nbytes){ 424 // Write memory objects to this file : 401 // Write memory objects to this file : 425 // Loop on all objects in m_root_director 402 // Loop on all objects in m_root_directory (including subdirectories). 426 // A new key is created in the directorie 403 // A new key is created in the directories m_keys linked list 427 // for each object. 404 // for each object. 428 // The list of keys is then saved on the 405 // The list of keys is then saved on the file (via write_keys) 429 // as a single data record. 406 // as a single data record. 430 // The directory header info is rewritten 407 // The directory header info is rewritten on the directory header record. 431 // //The linked list of FREE segments is 408 // //The linked list of FREE segments is written. 432 // The file header is written (bytes 1->m 409 // The file header is written (bytes 1->m_BEGIN). 433 a_nbytes = 0; 410 a_nbytes = 0; 434 411 435 if(m_verbose) { 412 if(m_verbose) { 436 m_out << "tools::wroot::file::write :" 413 m_out << "tools::wroot::file::write :" 437 << " writing Name=" << sout(m_path 414 << " writing Name=" << sout(m_path) 438 << " Title=" << sout(m_title) << " 415 << " Title=" << sout(m_title) << "." 439 << std::endl; 416 << std::endl; 440 } 417 } 441 418 442 uint32 nbytes; 419 uint32 nbytes; 443 if(!m_root_directory.write(nbytes)) return 420 if(!m_root_directory.write(nbytes)) return false; // Write directory tree 444 421 445 if(!write_streamer_infos()) { 422 if(!write_streamer_infos()) { 446 m_out << "tools::wroot::file::write :" 423 m_out << "tools::wroot::file::write :" 447 << " write_streamer_infos failed." 424 << " write_streamer_infos failed." 448 << std::endl; 425 << std::endl; 449 return false; 426 return false; 450 } 427 } 451 428 452 if(!write_free_segments()) { 429 if(!write_free_segments()) { 453 m_out << "tools::wroot::file::write :" 430 m_out << "tools::wroot::file::write :" 454 << " can't write free segments." 431 << " can't write free segments." 455 << std::endl; 432 << std::endl; 456 return false; 433 return false; 457 } 434 } 458 435 459 if(!write_header()) { //write 45 bytes at 436 if(!write_header()) { //write 45 bytes at BOF. 460 m_out << "tools::wroot::file::write :" 437 m_out << "tools::wroot::file::write :" 461 << " can't write file header." 438 << " can't write file header." 462 << std::endl; 439 << std::endl; 463 return false; 440 return false; 464 } 441 } 465 442 466 a_nbytes = nbytes; 443 a_nbytes = nbytes; 467 return true; 444 return true; 468 } 445 } 469 446 470 bool add_ziper(char a_key,compress_func a_fu 447 bool add_ziper(char a_key,compress_func a_func){ 471 std::map<char,compress_func>::const_iterat 448 std::map<char,compress_func>::const_iterator it = m_zipers.find(a_key); 472 if(it!=m_zipers.end()) { 449 if(it!=m_zipers.end()) { 473 //(*it).second = a_func; //override ? 450 //(*it).second = a_func; //override ? 474 return false; 451 return false; 475 } else { 452 } else { 476 m_zipers[a_key] = a_func; 453 m_zipers[a_key] = a_func; 477 return true; 454 return true; 478 } 455 } 479 } 456 } 480 protected: 457 protected: 481 enum EAccessMode { 458 enum EAccessMode { 482 kFileExists = 0, 459 kFileExists = 0, 483 kExecutePermission = 1, 460 kExecutePermission = 1, 484 kWritePermission = 2, 461 kWritePermission = 2, 485 kReadPermission = 4 462 kReadPermission = 4 486 }; 463 }; 487 static bool access_path(const std::string& a 464 static bool access_path(const std::string& a_path,EAccessMode a_mode){ 488 // Returns true if one can access a file u 465 // Returns true if one can access a file using the specified access mode. 489 // Mode is the same as for the WinNT acces 466 // Mode is the same as for the WinNT access(2) function. 490 #ifdef _MSC_VER 467 #ifdef _MSC_VER 491 return (::_access(a_path.c_str(),a_mode) = 468 return (::_access(a_path.c_str(),a_mode) == 0) ? true : false; 492 #else 469 #else 493 return (::access(a_path.c_str(),a_mode) == 470 return (::access(a_path.c_str(),a_mode) == 0) ? true : false; 494 #endif 471 #endif 495 } 472 } 496 static bool unlink(const std::string& a_path 473 static bool unlink(const std::string& a_path){ 497 // Unlink, i.e. remove, a file or director 474 // Unlink, i.e. remove, a file or directory. Returns true when succesfull, 498 // false in case of failure. 475 // false in case of failure. 499 struct stat finfo; 476 struct stat finfo; 500 if (::stat(a_path.c_str(),&finfo) < 0) ret 477 if (::stat(a_path.c_str(),&finfo) < 0) return false; 501 #ifdef _MSC_VER 478 #ifdef _MSC_VER 502 if (finfo.st_mode & S_IFDIR) 479 if (finfo.st_mode & S_IFDIR) 503 return (::_rmdir(a_path.c_str())==-1 ? f 480 return (::_rmdir(a_path.c_str())==-1 ? false : true); 504 else 481 else 505 return (::unlink(a_path.c_str())==-1 ? f 482 return (::unlink(a_path.c_str())==-1 ? false : true); 506 #else 483 #else 507 if (S_ISDIR(finfo.st_mode)) 484 if (S_ISDIR(finfo.st_mode)) 508 return (::rmdir(a_path.c_str())==-1 ? fa 485 return (::rmdir(a_path.c_str())==-1 ? false : true); 509 else 486 else 510 return (::unlink(a_path.c_str())==-1 ? f 487 return (::unlink(a_path.c_str())==-1 ? false : true); 511 #endif 488 #endif 512 } 489 } 513 490 514 static int _open(const char* a_name,int a_fl 491 static int _open(const char* a_name,int a_flags,unsigned int a_mode) { 515 #if defined(__linux__) && (__GLIBC__ == 2) && 492 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2) 516 return ::open64(a_name,a_flags,a_mode); 493 return ::open64(a_name,a_flags,a_mode); 517 #else 494 #else 518 return ::open(a_name,a_flags,a_mode); 495 return ::open(a_name,a_flags,a_mode); 519 #endif 496 #endif 520 } 497 } 521 bool write_header() { 498 bool write_header() { 522 const char root[] = "root"; 499 const char root[] = "root"; 523 //char psave[kBegin()]; 500 //char psave[kBegin()]; 524 char psave[128]; 501 char psave[128]; 525 const char* eob = psave + kBegin(); 502 const char* eob = psave + kBegin(); 526 char* pos = psave; 503 char* pos = psave; 527 ::memcpy(pos,root,4); pos += 4; 504 ::memcpy(pos,root,4); pos += 4; 528 uint32 vers = m_version; 505 uint32 vers = m_version; 529 if((m_END>START_BIG_FILE()) || 506 if((m_END>START_BIG_FILE()) || 530 (m_seek_free>START_BIG_FILE()) || 507 (m_seek_free>START_BIG_FILE()) || 531 (m_seek_info>START_BIG_FILE()) ){ 508 (m_seek_info>START_BIG_FILE()) ){ 532 vers += 1000000; 509 vers += 1000000; 533 m_units = 8; 510 m_units = 8; 534 } 511 } 535 wbuf wb(m_out,byte_swap(),eob,pos); 512 wbuf wb(m_out,byte_swap(),eob,pos); 536 if(!wb.write(vers)) return false; 513 if(!wb.write(vers)) return false; 537 if(!wb.write((seek32)m_BEGIN)) return fals 514 if(!wb.write((seek32)m_BEGIN)) return false; 538 if(vers>1000000) { 515 if(vers>1000000) { 539 if(!wb.write(m_END)) return false; 516 if(!wb.write(m_END)) return false; 540 if(!wb.write(m_seek_free)) return false; 517 if(!wb.write(m_seek_free)) return false; 541 } else { 518 } else { 542 if(!wb.write((seek32)m_END)) return fals 519 if(!wb.write((seek32)m_END)) return false; 543 if(!wb.write((seek32)m_seek_free)) retur 520 if(!wb.write((seek32)m_seek_free)) return false; 544 } 521 } 545 if(!wb.write(m_nbytes_free)) return false; 522 if(!wb.write(m_nbytes_free)) return false; 546 //int nfree = fFreeSegments.size(); 523 //int nfree = fFreeSegments.size(); 547 uint32 nfree = 0; //FIXME 524 uint32 nfree = 0; //FIXME 548 if(!wb.write(nfree)) return false; 525 if(!wb.write(nfree)) return false; 549 if(!wb.write(m_nbytes_name)) return false; 526 if(!wb.write(m_nbytes_name)) return false; 550 if(!wb.write(m_units)) return false; 527 if(!wb.write(m_units)) return false; 551 if(!wb.write(m_compress)) return false; 528 if(!wb.write(m_compress)) return false; 552 if(vers>1000000) { 529 if(vers>1000000) { 553 if(!wb.write(m_seek_info)) return false; 530 if(!wb.write(m_seek_info)) return false; 554 } else { 531 } else { 555 if(!wb.write((seek32)m_seek_info)) retur 532 if(!wb.write((seek32)m_seek_info)) return false; 556 } 533 } 557 if(!wb.write(m_nbytes_info)) return false; 534 if(!wb.write(m_nbytes_info)) return false; 558 if(!set_pos()) return false; //BOF 535 if(!set_pos()) return false; //BOF 559 uint32 nbytes = uint32(pos - psave); 536 uint32 nbytes = uint32(pos - psave); 560 //::printf("debug : write_header : %d\n",n 537 //::printf("debug : write_header : %d\n",nbytes); 561 if(!write_buffer(psave,nbytes)) return fal 538 if(!write_buffer(psave,nbytes)) return false; 562 if(!synchronize()) return false; 539 if(!synchronize()) return false; 563 return true; 540 return true; 564 } 541 } 565 542 566 bool write_streamer_infos() { 543 bool write_streamer_infos() { 567 obj_list<streamer_info> sinfos; 544 obj_list<streamer_info> sinfos; 568 fill_infos(sinfos,m_out); 545 fill_infos(sinfos,m_out); 569 546 570 if(sinfos.empty()) return false; 547 if(sinfos.empty()) return false; 571 548 572 buffer bref(m_out,byte_swap(),256); 549 buffer bref(m_out,byte_swap(),256); 573 550 574 if(!sinfos.stream(bref)) { 551 if(!sinfos.stream(bref)) { 575 m_out << "tools::wroot::file::write_stre 552 m_out << "tools::wroot::file::write_streamer_infos :" 576 << " cannot stream obj_list<stream 553 << " cannot stream obj_list<streamer_info>." 577 << std::endl; 554 << std::endl; 578 return false; 555 return false; 579 } 556 } 580 uint32 nbytes = bref.length(); 557 uint32 nbytes = bref.length(); 581 558 582 wroot::key key(m_out,*this, 559 wroot::key key(m_out,*this, 583 m_root_directory.seek_direc 560 m_root_directory.seek_directory(), 584 "StreamerInfo","", 561 "StreamerInfo","", 585 sinfos.store_cls(), 562 sinfos.store_cls(), 586 nbytes); // It does a (*thi 563 nbytes); // It does a (*this).set_END(). 587 if(!key.seek_key()) return false; 564 if(!key.seek_key()) return false; 588 565 589 if(!bref.displace_mapped(key.key_length()) 566 if(!bref.displace_mapped(key.key_length())) return false; 590 567 591 ::memcpy(key.data_buffer(),bref.buf(),nbyt 568 ::memcpy(key.data_buffer(),bref.buf(),nbytes); 592 569 593 //key.set_cycle(1); 570 //key.set_cycle(1); 594 if(!key.write_self(*this)) { 571 if(!key.write_self(*this)) { 595 m_out << "tools::wroot::file::write_stre 572 m_out << "tools::wroot::file::write_streamer_infos :" 596 << " key.write_self() failed." 573 << " key.write_self() failed." 597 << std::endl; 574 << std::endl; 598 return false; 575 return false; 599 } 576 } 600 577 601 m_seek_info = key.seek_key(); 578 m_seek_info = key.seek_key(); 602 m_nbytes_info = key.number_of_bytes(); 579 m_nbytes_info = key.number_of_bytes(); 603 //FIXME sumBuffer(key.objectSize()); 580 //FIXME sumBuffer(key.objectSize()); 604 581 605 uint32 n; 582 uint32 n; 606 if(!key.write_file(*this,n)) return false; 583 if(!key.write_file(*this,n)) return false; 607 if(!n) return false; 584 if(!n) return false; 608 585 609 return true; 586 return true; 610 } 587 } 611 588 612 bool make_free_seg(seek a_first,seek a_last) 589 bool make_free_seg(seek a_first,seek a_last) { 613 // Mark unused bytes on the file : 590 // Mark unused bytes on the file : 614 // The list of free segments is in the m_ 591 // The list of free segments is in the m_free_segs list 615 // When an object is deleted from the fil 592 // When an object is deleted from the file, the freed space is added 616 // into the FREE linked list (m_free_segs 593 // into the FREE linked list (m_free_segs). The FREE list consists 617 // of a chain of consecutive free segmen 594 // of a chain of consecutive free segments on the file. At the same 618 // time, the first 4 bytes of the freed r 595 // time, the first 4 bytes of the freed record on the file 619 // are overwritten by GAPSIZE where 596 // are overwritten by GAPSIZE where 620 // GAPSIZE = -(Number of bytes occupied 597 // GAPSIZE = -(Number of bytes occupied by the record). 621 598 622 if(m_free_segs.empty()) { 599 if(m_free_segs.empty()) { 623 m_out << "tools::wroot::file::make_free_ 600 m_out << "tools::wroot::file::make_free_seg :" 624 << " free_seg list should not be e 601 << " free_seg list should not be empty here." 625 << std::endl; 602 << std::endl; 626 return false; 603 return false; 627 } 604 } 628 605 629 free_seg* newfree = add_free(m_free_segs,a 606 free_seg* newfree = add_free(m_free_segs,a_first,a_last); 630 if(!newfree) { 607 if(!newfree) { 631 m_out << "tools::wroot::file::make_free_ 608 m_out << "tools::wroot::file::make_free_seg :" 632 << " add_free failed." 609 << " add_free failed." 633 << std::endl; 610 << std::endl; 634 return false; 611 return false; 635 } 612 } 636 613 637 seek nfirst = newfree->first(); 614 seek nfirst = newfree->first(); 638 seek nlast = newfree->last(); 615 seek nlast = newfree->last(); 639 616 640 seek _nbytes = nlast-nfirst+1; 617 seek _nbytes = nlast-nfirst+1; 641 if(_nbytes>START_BIG_FILE()) _nbytes = STA 618 if(_nbytes>START_BIG_FILE()) _nbytes = START_BIG_FILE(); 642 int nbytes = -int(_nbytes); 619 int nbytes = -int(_nbytes); 643 620 644 int nb = sizeof(int); 621 int nb = sizeof(int); 645 622 646 char psave[128]; 623 char psave[128]; 647 const char* eob = psave + nb; 624 const char* eob = psave + nb; 648 char* pos = psave; 625 char* pos = psave; 649 626 650 wbuf wb(m_out,byte_swap(),eob,pos); 627 wbuf wb(m_out,byte_swap(),eob,pos); 651 if(!wb.write(nbytes)) return false; 628 if(!wb.write(nbytes)) return false; 652 629 653 if(nlast == (m_END-1)) m_END = nfirst; 630 if(nlast == (m_END-1)) m_END = nfirst; 654 if(!set_pos(nfirst)) return false; 631 if(!set_pos(nfirst)) return false; 655 if(!write_buffer(psave,nb)) return false; 632 if(!write_buffer(psave,nb)) return false; 656 if(!synchronize()) return false; 633 if(!synchronize()) return false; 657 return true; 634 return true; 658 } 635 } 659 636 660 bool write_free_segments(){ 637 bool write_free_segments(){ 661 // The linked list of FREE segments (fFre 638 // The linked list of FREE segments (fFree) is written as a single data record. 662 639 663 // Delete old record if it exists : 640 // Delete old record if it exists : 664 if(m_seek_free){ 641 if(m_seek_free){ 665 if(!make_free_seg(m_seek_free, m_seek_fr 642 if(!make_free_seg(m_seek_free, m_seek_free + m_nbytes_free -1)) { 666 m_out << "tools::wroot::file::write_fr 643 m_out << "tools::wroot::file::write_free_segments :" 667 << " key.write_self() failed." 644 << " key.write_self() failed." 668 << std::endl; 645 << std::endl; 669 return false; 646 return false; 670 } 647 } 671 } 648 } 672 649 673 //::printf("debug : write_free_segments : 650 //::printf("debug : write_free_segments : seg list :\n"); 674 651 675 uint32 nbytes = 0; 652 uint32 nbytes = 0; 676 {tools_lforcit(free_seg*,m_free_segs,it) { 653 {tools_lforcit(free_seg*,m_free_segs,it) { 677 nbytes += (*it)->record_size(); 654 nbytes += (*it)->record_size(); 678 //::printf("debug : write_free_segments 655 //::printf("debug : write_free_segments : %lu %lu\n", 679 // (*it)->first(),(*it)->last()) 656 // (*it)->first(),(*it)->last()); 680 }} 657 }} 681 if(!nbytes) return true; 658 if(!nbytes) return true; 682 659 683 wroot::key key(m_out,*this, 660 wroot::key key(m_out,*this, 684 m_root_directory.seek_direc 661 m_root_directory.seek_directory(), 685 m_path,m_title,"TFile", 662 m_path,m_title,"TFile", 686 nbytes); // It does a (*thi 663 nbytes); // It does a (*this).set_END(). 687 if(!key.seek_key()) return false; 664 if(!key.seek_key()) return false; 688 665 689 {char* pos = key.data_buffer(); 666 {char* pos = key.data_buffer(); 690 wbuf wb(m_out,byte_swap(),key.eob(),pos); 667 wbuf wb(m_out,byte_swap(),key.eob(),pos); 691 tools_lforcit(free_seg*,m_free_segs,it) { 668 tools_lforcit(free_seg*,m_free_segs,it) { 692 if(!(*it)->fill_buffer(wb)) return false 669 if(!(*it)->fill_buffer(wb)) return false; 693 }} 670 }} 694 671 695 //key.set_cycle(1); 672 //key.set_cycle(1); 696 if(!key.write_self(*this)) { 673 if(!key.write_self(*this)) { 697 m_out << "tools::wroot::file::write_free 674 m_out << "tools::wroot::file::write_free_segments :" 698 << " key.write_self() failed." 675 << " key.write_self() failed." 699 << std::endl; 676 << std::endl; 700 return false; 677 return false; 701 } 678 } 702 679 703 m_seek_free = key.seek_key(); 680 m_seek_free = key.seek_key(); 704 m_nbytes_free = key.number_of_bytes(); 681 m_nbytes_free = key.number_of_bytes(); 705 if(m_verbose) { 682 if(m_verbose) { 706 m_out << "tools::wroot::file::write_free 683 m_out << "tools::wroot::file::write_free_segments :" 707 << " write key." << std::endl; 684 << " write key." << std::endl; 708 } 685 } 709 686 710 uint32 n; 687 uint32 n; 711 if(!key.write_file(*this,n)) return false; 688 if(!key.write_file(*this,n)) return false; 712 if(!n) return false; 689 if(!n) return false; 713 690 714 return true; 691 return true; 715 } 692 } 716 693 717 static bool zip(std::ostream& a_out, 694 static bool zip(std::ostream& a_out, 718 compress_func a_func, 695 compress_func a_func, 719 int a_level, 696 int a_level, 720 uint32 a_srcsize,char* a_src 697 uint32 a_srcsize,char* a_src, 721 uint32 a_tgtsize,char* a_tgt 698 uint32 a_tgtsize,char* a_tgt, 722 uint32& a_irep){ 699 uint32& a_irep){ 723 700 724 // from Rio/Bits/R__zip using zlib. 701 // from Rio/Bits/R__zip using zlib. 725 702 726 const uint32 HDRSIZE = 9; 703 const uint32 HDRSIZE = 9; 727 704 728 if(a_tgtsize<HDRSIZE) { 705 if(a_tgtsize<HDRSIZE) { 729 a_out << "tools::wroot::file::zip :" << 706 a_out << "tools::wroot::directory::zip :" 730 << " target buffer too small." 707 << " target buffer too small." 731 << std::endl; 708 << std::endl; 732 a_irep = 0; 709 a_irep = 0; 733 return false; 710 return false; 734 } 711 } 735 if(a_srcsize>0xffffff) { 712 if(a_srcsize>0xffffff) { 736 a_out << "tools::wroot::file::zip :" << 713 a_out << "tools::wroot::directory::zip :" 737 << " source buffer too big." 714 << " source buffer too big." 738 << std::endl; 715 << std::endl; 739 a_irep = 0; 716 a_irep = 0; 740 return false; 717 return false; 741 } 718 } 742 719 743 uint32 out_size; 720 uint32 out_size; 744 if(!a_func(a_out,a_level, 721 if(!a_func(a_out,a_level, 745 a_srcsize,a_src, 722 a_srcsize,a_src, 746 a_tgtsize,a_tgt+HDRSIZE, 723 a_tgtsize,a_tgt+HDRSIZE, 747 out_size)) { 724 out_size)) { 748 a_out << "tools::wroot::file::zip :" << 725 a_out << "tools::wroot::directory::zip :" 749 << " zipper failed." 726 << " zipper failed." 750 << std::endl; 727 << std::endl; 751 a_irep = 0; 728 a_irep = 0; 752 return false; 729 return false; 753 } 730 } 754 << 755 if((HDRSIZE+out_size)>a_tgtsize) { 731 if((HDRSIZE+out_size)>a_tgtsize) { 756 a_out << "tools::wroot::file::zip :" << 732 a_out << "tools::wroot::directory::zip :" 757 << " target buffer overflow." 733 << " target buffer overflow." 758 << std::endl; 734 << std::endl; 759 a_irep = 0; 735 a_irep = 0; 760 return false; 736 return false; 761 } 737 } 762 738 763 // HEADER : 739 // HEADER : 764 a_tgt[0] = 'Z'; // Signature ZLib 740 a_tgt[0] = 'Z'; // Signature ZLib 765 a_tgt[1] = 'L'; 741 a_tgt[1] = 'L'; 766 a_tgt[2] = 8; //DEFLATE 742 a_tgt[2] = 8; //DEFLATE 767 743 768 a_tgt[3] = (char)(out_size & 0xff); 744 a_tgt[3] = (char)(out_size & 0xff); 769 a_tgt[4] = (char)((out_size >> 8) & 0xff); 745 a_tgt[4] = (char)((out_size >> 8) & 0xff); 770 a_tgt[5] = (char)((out_size >> 16) & 0xff) 746 a_tgt[5] = (char)((out_size >> 16) & 0xff); 771 747 772 a_tgt[6] = (char)(a_srcsize & 0xff); 748 a_tgt[6] = (char)(a_srcsize & 0xff); 773 a_tgt[7] = (char)((a_srcsize >> 8) & 0xff) 749 a_tgt[7] = (char)((a_srcsize >> 8) & 0xff); 774 a_tgt[8] = (char)((a_srcsize >> 16) & 0xff 750 a_tgt[8] = (char)((a_srcsize >> 16) & 0xff); 775 751 776 a_irep = HDRSIZE+out_size; 752 a_irep = HDRSIZE+out_size; 777 753 778 return true; 754 return true; 779 } 755 } 780 756 781 #if defined(__sun) && !defined(__linux__) && ( 757 #if defined(__sun) && !defined(__linux__) && (__SUNPRO_CC > 0x420) 782 int error_number() {return ::errno;} 758 int error_number() {return ::errno;} 783 void reset_error_number() {::errno = 0;} 759 void reset_error_number() {::errno = 0;} 784 #else 760 #else 785 int error_number() {return errno;} 761 int error_number() {return errno;} 786 void reset_error_number() {errno = 0;} 762 void reset_error_number() {errno = 0;} 787 #endif 763 #endif 788 764 789 protected: 765 protected: 790 std::ostream& m_out; 766 std::ostream& m_out; 791 std::string m_path; 767 std::string m_path; 792 bool m_verbose; 768 bool m_verbose; 793 int m_file; 769 int m_file; 794 //uint64 m_bytes_write; //Number of bytes wr 770 //uint64 m_bytes_write; //Number of bytes write in this file 795 std::string m_title; //must be before the be 771 std::string m_title; //must be before the below. 796 directory m_root_directory; 772 directory m_root_directory; 797 std::map<char,compress_func> m_zipers; 773 std::map<char,compress_func> m_zipers; 798 std::list<free_seg*> m_free_segs; //Free seg 774 std::list<free_seg*> m_free_segs; //Free segments linked list table 799 // begin of record : 775 // begin of record : 800 // "root" 776 // "root" 801 uint32 m_version; //File format versio 777 uint32 m_version; //File format version 802 seek m_BEGIN; //First used byte in 778 seek m_BEGIN; //First used byte in file 803 seek m_END; //Last used byte in 779 seek m_END; //Last used byte in file 804 seek m_seek_free; //Location on disk o 780 seek m_seek_free; //Location on disk of free segments structure 805 uint32 m_nbytes_free; //Number of bytes fo 781 uint32 m_nbytes_free; //Number of bytes for free segments structure 806 //int nfree 782 //int nfree 807 uint32 m_nbytes_name; //Number of bytes in 783 uint32 m_nbytes_name; //Number of bytes in TNamed at creation time 808 char m_units; //Number of bytes fo 784 char m_units; //Number of bytes for file pointers 809 uint32 m_compress; //(=1 file is compre 785 uint32 m_compress; //(=1 file is compressed, 0 otherwise) 810 seek m_seek_info; //Location on disk o 786 seek m_seek_info; //Location on disk of StreamerInfo record 811 uint32 m_nbytes_info; //Number of bytes fo 787 uint32 m_nbytes_info; //Number of bytes for StreamerInfo record 812 }; 788 }; 813 789 814 790 815 }} 791 }} 816 792 817 #endif 793 #endif 818 794 819 //doc 795 //doc 820 // 796 // 821 // A ROOT file is a suite of consecutive data 797 // A ROOT file is a suite of consecutive data records with the following 822 // format (see also the TKey class); 798 // format (see also the TKey class); 823 // TKey --------------------- 799 // TKey --------------------- 824 // byte 1->4 Nbytes = Length of compr 800 // byte 1->4 Nbytes = Length of compressed object (in bytes) 825 // 5->6 Version = TKey version id 801 // 5->6 Version = TKey version identifier 826 // 7->10 ObjLen = Length of uncom 802 // 7->10 ObjLen = Length of uncompressed object 827 // 11->14 Datime = Date and time w 803 // 11->14 Datime = Date and time when object was written to file 828 // 15->16 KeyLen = Length of the k 804 // 15->16 KeyLen = Length of the key structure (in bytes) 829 // 17->18 Cycle = Cycle of key 805 // 17->18 Cycle = Cycle of key 830 // 19->22 SeekKey = Pointer to reco 806 // 19->22 SeekKey = Pointer to record itself (consistency check) 831 // 23->26 SeekPdir = Pointer to dire 807 // 23->26 SeekPdir = Pointer to directory header 832 // 27->27 lname = Number of bytes 808 // 27->27 lname = Number of bytes in the class name 833 // 28->.. ClassName = Object Class Na 809 // 28->.. ClassName = Object Class Name 834 // ..->.. lname = Number of bytes 810 // ..->.. lname = Number of bytes in the object name 835 // ..->.. Name = lName bytes wit 811 // ..->.. Name = lName bytes with the name of the object 836 // ..->.. lTitle = Number of bytes 812 // ..->.. lTitle = Number of bytes in the object title 837 // ..->.. Title = Title of the ob 813 // ..->.. Title = Title of the object 838 // -----> DATA = Data bytes asso 814 // -----> DATA = Data bytes associated to the object 839 // 815 // 840 // The first data record starts at byte fBEGI 816 // The first data record starts at byte fBEGIN (currently set to kBegin) 841 // Bytes 1->kBegin contain the file descripti 817 // Bytes 1->kBegin contain the file description: 842 // byte 1->4 "root" = Root file i 818 // byte 1->4 "root" = Root file identifier 843 // 5->8 fVersion = File format 819 // 5->8 fVersion = File format version 844 // 9->12 fBEGIN = Pointer to 820 // 9->12 fBEGIN = Pointer to first data record 845 // 13->16 fEND = Pointer to 821 // 13->16 fEND = Pointer to first free word at the EOF 846 // 17->20 fSeekFree = Pointer to 822 // 17->20 fSeekFree = Pointer to FREE data record 847 // 21->24 fNbytesFree = Number of b 823 // 21->24 fNbytesFree = Number of bytes in FREE data record 848 // 25->28 nfree = Number of f 824 // 25->28 nfree = Number of free data records 849 // 29->32 fNbytesName = Number of b 825 // 29->32 fNbytesName = Number of bytes in TNamed at creation time 850 // 33->33 fUnits = Number of b 826 // 33->33 fUnits = Number of bytes for file pointers 851 // 34->37 fCompress = Zip compres 827 // 34->37 fCompress = Zip compression level 852 // 828 //