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 281 294 //TUUID version 1: 282 //TUUID version 1: 295 nbytes += sizeof(unsigned int); 283 nbytes += sizeof(unsigned int); 296 nbytes += 2*sizeof(unsigned short); 284 nbytes += 2*sizeof(unsigned short); 297 nbytes += 8*sizeof(unsigned char); 285 nbytes += 8*sizeof(unsigned char); 298 286 299 wroot::key key(m_out,*this,0,m_path,m_titl 287 wroot::key key(m_out,*this,0,m_path,m_title,"TFile",nbytes); // It does a (*this).set_END(). 300 288 301 // m_nbytes_name = start point of director 289 // m_nbytes_name = start point of directory info from key head. 302 m_nbytes_name = key.key_length() + namelen 290 m_nbytes_name = key.key_length() + namelen; 303 m_root_directory.set_nbytes_name(m_nbytes_ 291 m_root_directory.set_nbytes_name(m_nbytes_name); 304 m_root_directory.set_seek_directory(key.se 292 m_root_directory.set_seek_directory(key.seek_key()); //at EOF. 305 293 306 //the below write 45 bytes at BOF (Begin O 294 //the below write 45 bytes at BOF (Begin Of File). 307 if(!write_header()) { //need m_nbytes_name 295 if(!write_header()) { //need m_nbytes_name, m_END after key written. 308 m_out << "tools::wroot::file::file :" 296 m_out << "tools::wroot::file::file :" 309 << " can't write file header." 297 << " can't write file header." 310 << std::endl; 298 << std::endl; 311 return; 299 return; 312 } 300 } 313 301 314 {char* pos = key.data_buffer(); 302 {char* pos = key.data_buffer(); 315 wbuf wb(m_out,byte_swap(),key.eob(),pos); 303 wbuf wb(m_out,byte_swap(),key.eob(),pos); 316 if(!wb.write(m_path)) return; 304 if(!wb.write(m_path)) return; 317 if(!wb.write(m_title)) return; 305 if(!wb.write(m_title)) return; 318 if(!m_root_directory.to_buffer(wb)) return 306 if(!m_root_directory.to_buffer(wb)) return; 319 //TUUID version 1: 307 //TUUID version 1: 320 if(!wb.write((unsigned int)0)) return; 308 if(!wb.write((unsigned int)0)) return; 321 if(!wb.write((unsigned short)0)) return; 309 if(!wb.write((unsigned short)0)) return; 322 if(!wb.write((unsigned short)0)) return; 310 if(!wb.write((unsigned short)0)) return; 323 {for(size_t count=0;count<8;count++) if(!wb 311 {for(size_t count=0;count<8;count++) if(!wb.write((unsigned char)0)) return;}} 324 312 325 if(m_verbose) { 313 if(m_verbose) { 326 m_out << "tools::wroot::file::file :" 314 m_out << "tools::wroot::file::file :" 327 << " write key (" 315 << " write key (" 328 << namelen 316 << namelen 329 << ", " 317 << ", " 330 << m_root_directory.record_size() 318 << m_root_directory.record_size() 331 << ", " 319 << ", " 332 << nbytes 320 << nbytes 333 << ", " 321 << ", " 334 << m_nbytes_name 322 << m_nbytes_name 335 << ", " 323 << ", " 336 << key.seek_key() 324 << key.seek_key() 337 << ")." 325 << ")." 338 << std::endl; 326 << std::endl; 339 } 327 } 340 328 341 key.set_cycle(1); 329 key.set_cycle(1); 342 if(!key.write_self(*this)) { 330 if(!key.write_self(*this)) { 343 m_out << "tools::wroot::file::file :" 331 m_out << "tools::wroot::file::file :" 344 << " key.write_self() failed." 332 << " key.write_self() failed." 345 << std::endl; 333 << std::endl; 346 return; 334 return; 347 } 335 } 348 336 349 //the below write at kBegin + nbytes. 337 //the below write at kBegin + nbytes. 350 //64+52 338 //64+52 351 uint32 n; 339 uint32 n; 352 if(!key.write_file(*this,n)) { 340 if(!key.write_file(*this,n)) { 353 m_out << "tools::wroot::file::file :" 341 m_out << "tools::wroot::file::file :" 354 << " can't write key in file." 342 << " can't write key in file." 355 << std::endl; 343 << std::endl; 356 return; 344 return; 357 } 345 } 358 //::printf("debug : file::file : write key 346 //::printf("debug : file::file : write key : %d\n",n); 359 347 360 } 348 } 361 virtual ~file() { 349 virtual ~file() { 362 close(); 350 close(); 363 #ifdef TOOLS_MEM 351 #ifdef TOOLS_MEM 364 mem::decrement(s_class().c_str()); 352 mem::decrement(s_class().c_str()); 365 #endif 353 #endif 366 } 354 } 367 protected: 355 protected: 368 file(const file& a_from) 356 file(const file& a_from) 369 :ifile(a_from) 357 :ifile(a_from) 370 ,m_out(a_from.m_out) 358 ,m_out(a_from.m_out) 371 ,m_root_directory(get_me()) 359 ,m_root_directory(get_me()) 372 { 360 { 373 #ifdef TOOLS_MEM 361 #ifdef TOOLS_MEM 374 mem::increment(s_class().c_str()); 362 mem::increment(s_class().c_str()); 375 #endif 363 #endif 376 } 364 } 377 file& operator=(const file&){return *this;} 365 file& operator=(const file&){return *this;} 378 public: 366 public: 379 const std::string& path() const {return m_pa 367 const std::string& path() const {return m_path;} 380 368 381 void set_compression(uint32 a_level) { 369 void set_compression(uint32 a_level) { 382 // level = 0 objects written to this file 370 // level = 0 objects written to this file will not be compressed. 383 // level = 1 minimal compression level but 371 // level = 1 minimal compression level but fast. 384 // .... 372 // .... 385 // level = 9 maximal compression level but 373 // level = 9 maximal compression level but slow. 386 m_compress = a_level; 374 m_compress = a_level; 387 if(m_compress>9) m_compress = 9; 375 if(m_compress>9) m_compress = 9; 388 } 376 } 389 377 390 bool is_open() const {return (m_file==not_op 378 bool is_open() const {return (m_file==not_open()?false:true);} 391 379 392 void close() { 380 void close() { 393 if(m_file==not_open()) return; 381 if(m_file==not_open()) return; 394 m_root_directory.close(); 382 m_root_directory.close(); 395 383 396 if(m_free_segs.size()) { 384 if(m_free_segs.size()) { 397 if(!write_free_segments()) { 385 if(!write_free_segments()) { 398 m_out << "tools::wroot::file::close :" 386 m_out << "tools::wroot::file::close :" 399 << " can't write free segments." 387 << " can't write free segments." 400 << std::endl; 388 << std::endl; 401 } 389 } 402 if(!write_header()) { // Now write file 390 if(!write_header()) { // Now write file header 403 m_out << "tools::wroot::file::close :" 391 m_out << "tools::wroot::file::close :" 404 << " can't write file header." 392 << " can't write file header." 405 << std::endl; 393 << std::endl; 406 } 394 } 407 } 395 } 408 396 409 {std::list<free_seg*>::iterator it; 397 {std::list<free_seg*>::iterator it; 410 for(it=m_free_segs.begin(); 398 for(it=m_free_segs.begin(); 411 it!=m_free_segs.end(); 399 it!=m_free_segs.end(); 412 it = m_free_segs.erase(it)) { 400 it = m_free_segs.erase(it)) { 413 delete (*it); 401 delete (*it); 414 }} 402 }} 415 403 416 ::close(m_file); 404 ::close(m_file); 417 m_file = not_open(); 405 m_file = not_open(); 418 } 406 } 419 407 420 directory& dir() {return m_root_directory;} 408 directory& dir() {return m_root_directory;} 421 const directory& dir() const {return m_root_ 409 const directory& dir() const {return m_root_directory;} 422 410 423 bool write(uint32& a_nbytes){ 411 bool write(uint32& a_nbytes){ 424 // Write memory objects to this file : 412 // Write memory objects to this file : 425 // Loop on all objects in m_root_director 413 // Loop on all objects in m_root_directory (including subdirectories). 426 // A new key is created in the directorie 414 // A new key is created in the directories m_keys linked list 427 // for each object. 415 // for each object. 428 // The list of keys is then saved on the 416 // The list of keys is then saved on the file (via write_keys) 429 // as a single data record. 417 // as a single data record. 430 // The directory header info is rewritten 418 // The directory header info is rewritten on the directory header record. 431 // //The linked list of FREE segments is 419 // //The linked list of FREE segments is written. 432 // The file header is written (bytes 1->m 420 // The file header is written (bytes 1->m_BEGIN). 433 a_nbytes = 0; 421 a_nbytes = 0; 434 422 435 if(m_verbose) { 423 if(m_verbose) { 436 m_out << "tools::wroot::file::write :" 424 m_out << "tools::wroot::file::write :" 437 << " writing Name=" << sout(m_path 425 << " writing Name=" << sout(m_path) 438 << " Title=" << sout(m_title) << " 426 << " Title=" << sout(m_title) << "." 439 << std::endl; 427 << std::endl; 440 } 428 } 441 429 442 uint32 nbytes; 430 uint32 nbytes; 443 if(!m_root_directory.write(nbytes)) return 431 if(!m_root_directory.write(nbytes)) return false; // Write directory tree 444 432 445 if(!write_streamer_infos()) { 433 if(!write_streamer_infos()) { 446 m_out << "tools::wroot::file::write :" 434 m_out << "tools::wroot::file::write :" 447 << " write_streamer_infos failed." 435 << " write_streamer_infos failed." 448 << std::endl; 436 << std::endl; 449 return false; 437 return false; 450 } 438 } 451 439 452 if(!write_free_segments()) { 440 if(!write_free_segments()) { 453 m_out << "tools::wroot::file::write :" 441 m_out << "tools::wroot::file::write :" 454 << " can't write free segments." 442 << " can't write free segments." 455 << std::endl; 443 << std::endl; 456 return false; 444 return false; 457 } 445 } 458 446 459 if(!write_header()) { //write 45 bytes at 447 if(!write_header()) { //write 45 bytes at BOF. 460 m_out << "tools::wroot::file::write :" 448 m_out << "tools::wroot::file::write :" 461 << " can't write file header." 449 << " can't write file header." 462 << std::endl; 450 << std::endl; 463 return false; 451 return false; 464 } 452 } 465 453 466 a_nbytes = nbytes; 454 a_nbytes = nbytes; 467 return true; 455 return true; 468 } 456 } 469 457 470 bool add_ziper(char a_key,compress_func a_fu 458 bool add_ziper(char a_key,compress_func a_func){ 471 std::map<char,compress_func>::const_iterat 459 std::map<char,compress_func>::const_iterator it = m_zipers.find(a_key); 472 if(it!=m_zipers.end()) { 460 if(it!=m_zipers.end()) { 473 //(*it).second = a_func; //override ? 461 //(*it).second = a_func; //override ? 474 return false; 462 return false; 475 } else { 463 } else { 476 m_zipers[a_key] = a_func; 464 m_zipers[a_key] = a_func; 477 return true; 465 return true; 478 } 466 } 479 } 467 } 480 protected: 468 protected: 481 enum EAccessMode { 469 enum EAccessMode { 482 kFileExists = 0, 470 kFileExists = 0, 483 kExecutePermission = 1, 471 kExecutePermission = 1, 484 kWritePermission = 2, 472 kWritePermission = 2, 485 kReadPermission = 4 473 kReadPermission = 4 486 }; 474 }; 487 static bool access_path(const std::string& a 475 static bool access_path(const std::string& a_path,EAccessMode a_mode){ 488 // Returns true if one can access a file u 476 // Returns true if one can access a file using the specified access mode. 489 // Mode is the same as for the WinNT acces 477 // Mode is the same as for the WinNT access(2) function. 490 #ifdef _MSC_VER 478 #ifdef _MSC_VER 491 return (::_access(a_path.c_str(),a_mode) = 479 return (::_access(a_path.c_str(),a_mode) == 0) ? true : false; 492 #else 480 #else 493 return (::access(a_path.c_str(),a_mode) == 481 return (::access(a_path.c_str(),a_mode) == 0) ? true : false; 494 #endif 482 #endif 495 } 483 } 496 static bool unlink(const std::string& a_path 484 static bool unlink(const std::string& a_path){ 497 // Unlink, i.e. remove, a file or director 485 // Unlink, i.e. remove, a file or directory. Returns true when succesfull, 498 // false in case of failure. 486 // false in case of failure. 499 struct stat finfo; 487 struct stat finfo; 500 if (::stat(a_path.c_str(),&finfo) < 0) ret 488 if (::stat(a_path.c_str(),&finfo) < 0) return false; 501 #ifdef _MSC_VER 489 #ifdef _MSC_VER 502 if (finfo.st_mode & S_IFDIR) 490 if (finfo.st_mode & S_IFDIR) 503 return (::_rmdir(a_path.c_str())==-1 ? f 491 return (::_rmdir(a_path.c_str())==-1 ? false : true); 504 else 492 else 505 return (::unlink(a_path.c_str())==-1 ? f 493 return (::unlink(a_path.c_str())==-1 ? false : true); 506 #else 494 #else 507 if (S_ISDIR(finfo.st_mode)) 495 if (S_ISDIR(finfo.st_mode)) 508 return (::rmdir(a_path.c_str())==-1 ? fa 496 return (::rmdir(a_path.c_str())==-1 ? false : true); 509 else 497 else 510 return (::unlink(a_path.c_str())==-1 ? f 498 return (::unlink(a_path.c_str())==-1 ? false : true); 511 #endif 499 #endif 512 } 500 } 513 501 514 static int _open(const char* a_name,int a_fl 502 static int _open(const char* a_name,int a_flags,unsigned int a_mode) { 515 #if defined(__linux__) && (__GLIBC__ == 2) && 503 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2) 516 return ::open64(a_name,a_flags,a_mode); 504 return ::open64(a_name,a_flags,a_mode); 517 #else 505 #else 518 return ::open(a_name,a_flags,a_mode); 506 return ::open(a_name,a_flags,a_mode); 519 #endif 507 #endif 520 } 508 } 521 bool write_header() { 509 bool write_header() { 522 const char root[] = "root"; 510 const char root[] = "root"; 523 //char psave[kBegin()]; 511 //char psave[kBegin()]; 524 char psave[128]; 512 char psave[128]; 525 const char* eob = psave + kBegin(); 513 const char* eob = psave + kBegin(); 526 char* pos = psave; 514 char* pos = psave; 527 ::memcpy(pos,root,4); pos += 4; 515 ::memcpy(pos,root,4); pos += 4; 528 uint32 vers = m_version; 516 uint32 vers = m_version; 529 if((m_END>START_BIG_FILE()) || 517 if((m_END>START_BIG_FILE()) || 530 (m_seek_free>START_BIG_FILE()) || 518 (m_seek_free>START_BIG_FILE()) || 531 (m_seek_info>START_BIG_FILE()) ){ 519 (m_seek_info>START_BIG_FILE()) ){ 532 vers += 1000000; 520 vers += 1000000; 533 m_units = 8; 521 m_units = 8; 534 } 522 } 535 wbuf wb(m_out,byte_swap(),eob,pos); 523 wbuf wb(m_out,byte_swap(),eob,pos); 536 if(!wb.write(vers)) return false; 524 if(!wb.write(vers)) return false; 537 if(!wb.write((seek32)m_BEGIN)) return fals 525 if(!wb.write((seek32)m_BEGIN)) return false; 538 if(vers>1000000) { 526 if(vers>1000000) { 539 if(!wb.write(m_END)) return false; 527 if(!wb.write(m_END)) return false; 540 if(!wb.write(m_seek_free)) return false; 528 if(!wb.write(m_seek_free)) return false; 541 } else { 529 } else { 542 if(!wb.write((seek32)m_END)) return fals 530 if(!wb.write((seek32)m_END)) return false; 543 if(!wb.write((seek32)m_seek_free)) retur 531 if(!wb.write((seek32)m_seek_free)) return false; 544 } 532 } 545 if(!wb.write(m_nbytes_free)) return false; 533 if(!wb.write(m_nbytes_free)) return false; 546 //int nfree = fFreeSegments.size(); 534 //int nfree = fFreeSegments.size(); 547 uint32 nfree = 0; //FIXME 535 uint32 nfree = 0; //FIXME 548 if(!wb.write(nfree)) return false; 536 if(!wb.write(nfree)) return false; 549 if(!wb.write(m_nbytes_name)) return false; 537 if(!wb.write(m_nbytes_name)) return false; 550 if(!wb.write(m_units)) return false; 538 if(!wb.write(m_units)) return false; 551 if(!wb.write(m_compress)) return false; 539 if(!wb.write(m_compress)) return false; 552 if(vers>1000000) { 540 if(vers>1000000) { 553 if(!wb.write(m_seek_info)) return false; 541 if(!wb.write(m_seek_info)) return false; 554 } else { 542 } else { 555 if(!wb.write((seek32)m_seek_info)) retur 543 if(!wb.write((seek32)m_seek_info)) return false; 556 } 544 } 557 if(!wb.write(m_nbytes_info)) return false; 545 if(!wb.write(m_nbytes_info)) return false; 558 if(!set_pos()) return false; //BOF 546 if(!set_pos()) return false; //BOF 559 uint32 nbytes = uint32(pos - psave); 547 uint32 nbytes = uint32(pos - psave); 560 //::printf("debug : write_header : %d\n",n 548 //::printf("debug : write_header : %d\n",nbytes); 561 if(!write_buffer(psave,nbytes)) return fal 549 if(!write_buffer(psave,nbytes)) return false; 562 if(!synchronize()) return false; 550 if(!synchronize()) return false; 563 return true; 551 return true; 564 } 552 } 565 553 566 bool write_streamer_infos() { 554 bool write_streamer_infos() { 567 obj_list<streamer_info> sinfos; 555 obj_list<streamer_info> sinfos; 568 fill_infos(sinfos,m_out); 556 fill_infos(sinfos,m_out); 569 557 570 if(sinfos.empty()) return false; 558 if(sinfos.empty()) return false; 571 559 572 buffer bref(m_out,byte_swap(),256); 560 buffer bref(m_out,byte_swap(),256); 573 561 574 if(!sinfos.stream(bref)) { 562 if(!sinfos.stream(bref)) { 575 m_out << "tools::wroot::file::write_stre 563 m_out << "tools::wroot::file::write_streamer_infos :" 576 << " cannot stream obj_list<stream 564 << " cannot stream obj_list<streamer_info>." 577 << std::endl; 565 << std::endl; 578 return false; 566 return false; 579 } 567 } 580 uint32 nbytes = bref.length(); 568 uint32 nbytes = bref.length(); 581 569 582 wroot::key key(m_out,*this, 570 wroot::key key(m_out,*this, 583 m_root_directory.seek_direc 571 m_root_directory.seek_directory(), 584 "StreamerInfo","", 572 "StreamerInfo","", 585 sinfos.store_cls(), 573 sinfos.store_cls(), 586 nbytes); // It does a (*thi 574 nbytes); // It does a (*this).set_END(). 587 if(!key.seek_key()) return false; 575 if(!key.seek_key()) return false; 588 576 589 if(!bref.displace_mapped(key.key_length()) 577 if(!bref.displace_mapped(key.key_length())) return false; 590 578 591 ::memcpy(key.data_buffer(),bref.buf(),nbyt 579 ::memcpy(key.data_buffer(),bref.buf(),nbytes); 592 580 593 //key.set_cycle(1); 581 //key.set_cycle(1); 594 if(!key.write_self(*this)) { 582 if(!key.write_self(*this)) { 595 m_out << "tools::wroot::file::write_stre 583 m_out << "tools::wroot::file::write_streamer_infos :" 596 << " key.write_self() failed." 584 << " key.write_self() failed." 597 << std::endl; 585 << std::endl; 598 return false; 586 return false; 599 } 587 } 600 588 601 m_seek_info = key.seek_key(); 589 m_seek_info = key.seek_key(); 602 m_nbytes_info = key.number_of_bytes(); 590 m_nbytes_info = key.number_of_bytes(); 603 //FIXME sumBuffer(key.objectSize()); 591 //FIXME sumBuffer(key.objectSize()); 604 592 605 uint32 n; 593 uint32 n; 606 if(!key.write_file(*this,n)) return false; 594 if(!key.write_file(*this,n)) return false; 607 if(!n) return false; 595 if(!n) return false; 608 596 609 return true; 597 return true; 610 } 598 } 611 599 612 bool make_free_seg(seek a_first,seek a_last) 600 bool make_free_seg(seek a_first,seek a_last) { 613 // Mark unused bytes on the file : 601 // Mark unused bytes on the file : 614 // The list of free segments is in the m_ 602 // The list of free segments is in the m_free_segs list 615 // When an object is deleted from the fil 603 // When an object is deleted from the file, the freed space is added 616 // into the FREE linked list (m_free_segs 604 // into the FREE linked list (m_free_segs). The FREE list consists 617 // of a chain of consecutive free segmen 605 // of a chain of consecutive free segments on the file. At the same 618 // time, the first 4 bytes of the freed r 606 // time, the first 4 bytes of the freed record on the file 619 // are overwritten by GAPSIZE where 607 // are overwritten by GAPSIZE where 620 // GAPSIZE = -(Number of bytes occupied 608 // GAPSIZE = -(Number of bytes occupied by the record). 621 609 622 if(m_free_segs.empty()) { 610 if(m_free_segs.empty()) { 623 m_out << "tools::wroot::file::make_free_ 611 m_out << "tools::wroot::file::make_free_seg :" 624 << " free_seg list should not be e 612 << " free_seg list should not be empty here." 625 << std::endl; 613 << std::endl; 626 return false; 614 return false; 627 } 615 } 628 616 629 free_seg* newfree = add_free(m_free_segs,a 617 free_seg* newfree = add_free(m_free_segs,a_first,a_last); 630 if(!newfree) { 618 if(!newfree) { 631 m_out << "tools::wroot::file::make_free_ 619 m_out << "tools::wroot::file::make_free_seg :" 632 << " add_free failed." 620 << " add_free failed." 633 << std::endl; 621 << std::endl; 634 return false; 622 return false; 635 } 623 } 636 624 637 seek nfirst = newfree->first(); 625 seek nfirst = newfree->first(); 638 seek nlast = newfree->last(); 626 seek nlast = newfree->last(); 639 627 640 seek _nbytes = nlast-nfirst+1; 628 seek _nbytes = nlast-nfirst+1; 641 if(_nbytes>START_BIG_FILE()) _nbytes = STA 629 if(_nbytes>START_BIG_FILE()) _nbytes = START_BIG_FILE(); 642 int nbytes = -int(_nbytes); 630 int nbytes = -int(_nbytes); 643 631 644 int nb = sizeof(int); 632 int nb = sizeof(int); 645 633 646 char psave[128]; 634 char psave[128]; 647 const char* eob = psave + nb; 635 const char* eob = psave + nb; 648 char* pos = psave; 636 char* pos = psave; 649 637 650 wbuf wb(m_out,byte_swap(),eob,pos); 638 wbuf wb(m_out,byte_swap(),eob,pos); 651 if(!wb.write(nbytes)) return false; 639 if(!wb.write(nbytes)) return false; 652 640 653 if(nlast == (m_END-1)) m_END = nfirst; 641 if(nlast == (m_END-1)) m_END = nfirst; 654 if(!set_pos(nfirst)) return false; 642 if(!set_pos(nfirst)) return false; 655 if(!write_buffer(psave,nb)) return false; 643 if(!write_buffer(psave,nb)) return false; 656 if(!synchronize()) return false; 644 if(!synchronize()) return false; 657 return true; 645 return true; 658 } 646 } 659 647 660 bool write_free_segments(){ 648 bool write_free_segments(){ 661 // The linked list of FREE segments (fFre 649 // The linked list of FREE segments (fFree) is written as a single data record. 662 650 663 // Delete old record if it exists : 651 // Delete old record if it exists : 664 if(m_seek_free){ 652 if(m_seek_free){ 665 if(!make_free_seg(m_seek_free, m_seek_fr 653 if(!make_free_seg(m_seek_free, m_seek_free + m_nbytes_free -1)) { 666 m_out << "tools::wroot::file::write_fr 654 m_out << "tools::wroot::file::write_free_segments :" 667 << " key.write_self() failed." 655 << " key.write_self() failed." 668 << std::endl; 656 << std::endl; 669 return false; 657 return false; 670 } 658 } 671 } 659 } 672 660 673 //::printf("debug : write_free_segments : 661 //::printf("debug : write_free_segments : seg list :\n"); 674 662 675 uint32 nbytes = 0; 663 uint32 nbytes = 0; 676 {tools_lforcit(free_seg*,m_free_segs,it) { 664 {tools_lforcit(free_seg*,m_free_segs,it) { 677 nbytes += (*it)->record_size(); 665 nbytes += (*it)->record_size(); 678 //::printf("debug : write_free_segments 666 //::printf("debug : write_free_segments : %lu %lu\n", 679 // (*it)->first(),(*it)->last()) 667 // (*it)->first(),(*it)->last()); 680 }} 668 }} 681 if(!nbytes) return true; 669 if(!nbytes) return true; 682 670 683 wroot::key key(m_out,*this, 671 wroot::key key(m_out,*this, 684 m_root_directory.seek_direc 672 m_root_directory.seek_directory(), 685 m_path,m_title,"TFile", 673 m_path,m_title,"TFile", 686 nbytes); // It does a (*thi 674 nbytes); // It does a (*this).set_END(). 687 if(!key.seek_key()) return false; 675 if(!key.seek_key()) return false; 688 676 689 {char* pos = key.data_buffer(); 677 {char* pos = key.data_buffer(); 690 wbuf wb(m_out,byte_swap(),key.eob(),pos); 678 wbuf wb(m_out,byte_swap(),key.eob(),pos); 691 tools_lforcit(free_seg*,m_free_segs,it) { 679 tools_lforcit(free_seg*,m_free_segs,it) { 692 if(!(*it)->fill_buffer(wb)) return false 680 if(!(*it)->fill_buffer(wb)) return false; 693 }} 681 }} 694 682 695 //key.set_cycle(1); 683 //key.set_cycle(1); 696 if(!key.write_self(*this)) { 684 if(!key.write_self(*this)) { 697 m_out << "tools::wroot::file::write_free 685 m_out << "tools::wroot::file::write_free_segments :" 698 << " key.write_self() failed." 686 << " key.write_self() failed." 699 << std::endl; 687 << std::endl; 700 return false; 688 return false; 701 } 689 } 702 690 703 m_seek_free = key.seek_key(); 691 m_seek_free = key.seek_key(); 704 m_nbytes_free = key.number_of_bytes(); 692 m_nbytes_free = key.number_of_bytes(); 705 if(m_verbose) { 693 if(m_verbose) { 706 m_out << "tools::wroot::file::write_free 694 m_out << "tools::wroot::file::write_free_segments :" 707 << " write key." << std::endl; 695 << " write key." << std::endl; 708 } 696 } 709 697 710 uint32 n; 698 uint32 n; 711 if(!key.write_file(*this,n)) return false; 699 if(!key.write_file(*this,n)) return false; 712 if(!n) return false; 700 if(!n) return false; 713 701 714 return true; 702 return true; 715 } 703 } 716 704 717 static bool zip(std::ostream& a_out, 705 static bool zip(std::ostream& a_out, 718 compress_func a_func, 706 compress_func a_func, 719 int a_level, 707 int a_level, 720 uint32 a_srcsize,char* a_src 708 uint32 a_srcsize,char* a_src, 721 uint32 a_tgtsize,char* a_tgt 709 uint32 a_tgtsize,char* a_tgt, 722 uint32& a_irep){ 710 uint32& a_irep){ 723 711 724 // from Rio/Bits/R__zip using zlib. 712 // from Rio/Bits/R__zip using zlib. 725 713 726 const uint32 HDRSIZE = 9; 714 const uint32 HDRSIZE = 9; 727 715 728 if(a_tgtsize<HDRSIZE) { 716 if(a_tgtsize<HDRSIZE) { 729 a_out << "tools::wroot::file::zip :" << 717 a_out << "tools::wroot::directory::zip :" 730 << " target buffer too small." 718 << " target buffer too small." 731 << std::endl; 719 << std::endl; 732 a_irep = 0; 720 a_irep = 0; 733 return false; 721 return false; 734 } 722 } 735 if(a_srcsize>0xffffff) { 723 if(a_srcsize>0xffffff) { 736 a_out << "tools::wroot::file::zip :" << 724 a_out << "tools::wroot::directory::zip :" 737 << " source buffer too big." 725 << " source buffer too big." 738 << std::endl; 726 << std::endl; 739 a_irep = 0; 727 a_irep = 0; 740 return false; 728 return false; 741 } 729 } 742 730 743 uint32 out_size; 731 uint32 out_size; 744 if(!a_func(a_out,a_level, 732 if(!a_func(a_out,a_level, 745 a_srcsize,a_src, 733 a_srcsize,a_src, 746 a_tgtsize,a_tgt+HDRSIZE, 734 a_tgtsize,a_tgt+HDRSIZE, 747 out_size)) { 735 out_size)) { 748 a_out << "tools::wroot::file::zip :" << 736 a_out << "tools::wroot::directory::zip :" 749 << " zipper failed." 737 << " zipper failed." 750 << std::endl; 738 << std::endl; 751 a_irep = 0; 739 a_irep = 0; 752 return false; 740 return false; 753 } 741 } 754 << 755 if((HDRSIZE+out_size)>a_tgtsize) { 742 if((HDRSIZE+out_size)>a_tgtsize) { 756 a_out << "tools::wroot::file::zip :" << 743 a_out << "tools::wroot::directory::zip :" 757 << " target buffer overflow." 744 << " target buffer overflow." 758 << std::endl; 745 << std::endl; 759 a_irep = 0; 746 a_irep = 0; 760 return false; 747 return false; 761 } 748 } 762 749 763 // HEADER : 750 // HEADER : 764 a_tgt[0] = 'Z'; // Signature ZLib 751 a_tgt[0] = 'Z'; // Signature ZLib 765 a_tgt[1] = 'L'; 752 a_tgt[1] = 'L'; 766 a_tgt[2] = 8; //DEFLATE 753 a_tgt[2] = 8; //DEFLATE 767 754 768 a_tgt[3] = (char)(out_size & 0xff); 755 a_tgt[3] = (char)(out_size & 0xff); 769 a_tgt[4] = (char)((out_size >> 8) & 0xff); 756 a_tgt[4] = (char)((out_size >> 8) & 0xff); 770 a_tgt[5] = (char)((out_size >> 16) & 0xff) 757 a_tgt[5] = (char)((out_size >> 16) & 0xff); 771 758 772 a_tgt[6] = (char)(a_srcsize & 0xff); 759 a_tgt[6] = (char)(a_srcsize & 0xff); 773 a_tgt[7] = (char)((a_srcsize >> 8) & 0xff) 760 a_tgt[7] = (char)((a_srcsize >> 8) & 0xff); 774 a_tgt[8] = (char)((a_srcsize >> 16) & 0xff 761 a_tgt[8] = (char)((a_srcsize >> 16) & 0xff); 775 762 776 a_irep = HDRSIZE+out_size; 763 a_irep = HDRSIZE+out_size; 777 764 778 return true; 765 return true; 779 } 766 } 780 767 781 #if defined(__sun) && !defined(__linux__) && ( 768 #if defined(__sun) && !defined(__linux__) && (__SUNPRO_CC > 0x420) 782 int error_number() {return ::errno;} 769 int error_number() {return ::errno;} 783 void reset_error_number() {::errno = 0;} 770 void reset_error_number() {::errno = 0;} 784 #else 771 #else 785 int error_number() {return errno;} 772 int error_number() {return errno;} 786 void reset_error_number() {errno = 0;} 773 void reset_error_number() {errno = 0;} 787 #endif 774 #endif 788 775 789 protected: 776 protected: 790 std::ostream& m_out; 777 std::ostream& m_out; 791 std::string m_path; 778 std::string m_path; 792 bool m_verbose; 779 bool m_verbose; 793 int m_file; 780 int m_file; 794 //uint64 m_bytes_write; //Number of bytes wr 781 //uint64 m_bytes_write; //Number of bytes write in this file 795 std::string m_title; //must be before the be 782 std::string m_title; //must be before the below. 796 directory m_root_directory; 783 directory m_root_directory; 797 std::map<char,compress_func> m_zipers; 784 std::map<char,compress_func> m_zipers; 798 std::list<free_seg*> m_free_segs; //Free seg 785 std::list<free_seg*> m_free_segs; //Free segments linked list table 799 // begin of record : 786 // begin of record : 800 // "root" 787 // "root" 801 uint32 m_version; //File format versio 788 uint32 m_version; //File format version 802 seek m_BEGIN; //First used byte in 789 seek m_BEGIN; //First used byte in file 803 seek m_END; //Last used byte in 790 seek m_END; //Last used byte in file 804 seek m_seek_free; //Location on disk o 791 seek m_seek_free; //Location on disk of free segments structure 805 uint32 m_nbytes_free; //Number of bytes fo 792 uint32 m_nbytes_free; //Number of bytes for free segments structure 806 //int nfree 793 //int nfree 807 uint32 m_nbytes_name; //Number of bytes in 794 uint32 m_nbytes_name; //Number of bytes in TNamed at creation time 808 char m_units; //Number of bytes fo 795 char m_units; //Number of bytes for file pointers 809 uint32 m_compress; //(=1 file is compre 796 uint32 m_compress; //(=1 file is compressed, 0 otherwise) 810 seek m_seek_info; //Location on disk o 797 seek m_seek_info; //Location on disk of StreamerInfo record 811 uint32 m_nbytes_info; //Number of bytes fo 798 uint32 m_nbytes_info; //Number of bytes for StreamerInfo record 812 }; 799 }; 813 800 814 801 815 }} 802 }} 816 803 817 #endif 804 #endif 818 805 819 //doc 806 //doc 820 // 807 // 821 // A ROOT file is a suite of consecutive data 808 // A ROOT file is a suite of consecutive data records with the following 822 // format (see also the TKey class); 809 // format (see also the TKey class); 823 // TKey --------------------- 810 // TKey --------------------- 824 // byte 1->4 Nbytes = Length of compr 811 // byte 1->4 Nbytes = Length of compressed object (in bytes) 825 // 5->6 Version = TKey version id 812 // 5->6 Version = TKey version identifier 826 // 7->10 ObjLen = Length of uncom 813 // 7->10 ObjLen = Length of uncompressed object 827 // 11->14 Datime = Date and time w 814 // 11->14 Datime = Date and time when object was written to file 828 // 15->16 KeyLen = Length of the k 815 // 15->16 KeyLen = Length of the key structure (in bytes) 829 // 17->18 Cycle = Cycle of key 816 // 17->18 Cycle = Cycle of key 830 // 19->22 SeekKey = Pointer to reco 817 // 19->22 SeekKey = Pointer to record itself (consistency check) 831 // 23->26 SeekPdir = Pointer to dire 818 // 23->26 SeekPdir = Pointer to directory header 832 // 27->27 lname = Number of bytes 819 // 27->27 lname = Number of bytes in the class name 833 // 28->.. ClassName = Object Class Na 820 // 28->.. ClassName = Object Class Name 834 // ..->.. lname = Number of bytes 821 // ..->.. lname = Number of bytes in the object name 835 // ..->.. Name = lName bytes wit 822 // ..->.. Name = lName bytes with the name of the object 836 // ..->.. lTitle = Number of bytes 823 // ..->.. lTitle = Number of bytes in the object title 837 // ..->.. Title = Title of the ob 824 // ..->.. Title = Title of the object 838 // -----> DATA = Data bytes asso 825 // -----> DATA = Data bytes associated to the object 839 // 826 // 840 // The first data record starts at byte fBEGI 827 // The first data record starts at byte fBEGIN (currently set to kBegin) 841 // Bytes 1->kBegin contain the file descripti 828 // Bytes 1->kBegin contain the file description: 842 // byte 1->4 "root" = Root file i 829 // byte 1->4 "root" = Root file identifier 843 // 5->8 fVersion = File format 830 // 5->8 fVersion = File format version 844 // 9->12 fBEGIN = Pointer to 831 // 9->12 fBEGIN = Pointer to first data record 845 // 13->16 fEND = Pointer to 832 // 13->16 fEND = Pointer to first free word at the EOF 846 // 17->20 fSeekFree = Pointer to 833 // 17->20 fSeekFree = Pointer to FREE data record 847 // 21->24 fNbytesFree = Number of b 834 // 21->24 fNbytesFree = Number of bytes in FREE data record 848 // 25->28 nfree = Number of f 835 // 25->28 nfree = Number of free data records 849 // 29->32 fNbytesName = Number of b 836 // 29->32 fNbytesName = Number of bytes in TNamed at creation time 850 // 33->33 fUnits = Number of b 837 // 33->33 fUnits = Number of bytes for file pointers 851 // 34->37 fCompress = Zip compres 838 // 34->37 fCompress = Zip compression level 852 // 839 //