Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_file 5 #define tools_file 6 7 #include "gzip" 8 #include "forit" 9 #include "words" //is_hippo 10 #include "path" //suffix 11 #include "S_STRING" 12 13 #include <cstdlib> 14 #include <cstring> 15 16 #ifdef TOOLS_MEM 17 #include "mem" 18 #endif 19 20 namespace tools { 21 namespace file { 22 23 inline bool exists(const std::string& a_string) { 24 FILE* file = ::fopen(a_string.c_str(),"rb"); 25 if(!file) return false; 26 ::fclose(file); 27 return true; 28 } 29 30 inline bool write(const std::string& a_file,const std::string& a_string) { 31 // a_string could contain \n separated lines. 32 FILE* file = ::fopen(a_file.c_str(),"wb"); 33 if(!file) return false; 34 if(::fprintf(file,"%s",a_string.c_str())<0) { 35 ::fclose(file); 36 return false; 37 } 38 ::fclose(file); 39 return true; 40 } 41 42 inline bool write(const std::string& a_file,const std::vector<std::string>& a_text){ 43 FILE* file = ::fopen(a_file.c_str(),"wb"); 44 if(!file) return false; 45 tools_vforcit(std::string,a_text,it) { 46 if(::fprintf(file,"%s\n",(*it).c_str())<0) { 47 ::fclose(file); 48 return false; 49 } 50 } 51 ::fclose(file); 52 return true; 53 } 54 55 inline bool make_empty(const std::string& a_file) { 56 FILE* file = ::fopen(a_file.c_str(),"wb"); 57 if(!file) return false; 58 ::fclose(file); 59 return true; 60 } 61 62 inline bool read_buff(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) { 63 a_length = ::fread(a_buff,1,a_lbuf,a_file); 64 return true; 65 } 66 67 inline bool read_cstring(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) { 68 if(::fgets(a_buff,a_lbuf,a_file)==NULL) { 69 a_length = 0; 70 return false; //EOF 71 } 72 73 size_t l = ::strlen(a_buff); 74 // On Windows, editors when saving binary files, 75 // put \r\n at place of \n ; we then look for \r\n. 76 if( (l>=2) && (a_buff[l-2]=='\r') && (a_buff[l-1]=='\n') ) { 77 a_buff[l-2] = '\0'; 78 l -= 2; 79 } else if( (l>=1) && (a_buff[l-1]=='\n') ) { 80 a_buff[l-1] = '\0'; 81 l -= 1; 82 } 83 84 a_length = l; 85 return true; 86 } 87 88 89 inline bool read(FILE* a_FILE,std::vector<std::string>& a_text){ 90 a_text.clear(); 91 unsigned int BUFSIZE = 65536; 92 char* buffer = new char[BUFSIZE+1]; 93 if(!buffer) return false; 94 while(true) { 95 size_t l; 96 if(!read_cstring(a_FILE,buffer,BUFSIZE,l)) break; // EOF. 97 a_text.push_back(buffer); 98 } 99 delete [] buffer; 100 return true; 101 } 102 103 inline bool read(const std::string& a_file,std::vector<std::string>& a_text){ 104 FILE* file = ::fopen(a_file.c_str(),"rb"); 105 if(!file) {a_text.clear();return false;} 106 bool status = read(file,a_text); 107 ::fclose(file); 108 return status; 109 } 110 111 inline bool read_num(const std::string& a_file,std::vector<std::string>::size_type a_num,std::vector<std::string>& a_text,const std::string& a_cmt = ""){ 112 a_text.clear(); 113 FILE* file = ::fopen(a_file.c_str(),"rb"); 114 if(!file) return false; 115 unsigned int BUFSIZE = 65536; 116 char* buffer = new char[BUFSIZE+1]; 117 if(!buffer) {::fclose(file);return false;} 118 while(true) { 119 size_t l; 120 if(!read_cstring(file,buffer,BUFSIZE,l)) break; // EOF. 121 if(a_cmt.size()&&(!strncmp(a_cmt.c_str(),buffer,a_cmt.size()))) continue; 122 if(a_text.size()<a_num) { 123 a_text.push_back(buffer); 124 } else { 125 break; 126 } 127 } 128 delete [] buffer; 129 ::fclose(file); 130 return true; 131 } 132 133 inline bool read_bytes(const std::string& a_file,char*& a_buffer,long& a_length){ 134 // Returned buffer should be deleted with delete []. 135 FILE* file = ::fopen(a_file.c_str(),"rb"); 136 if(!file) { 137 a_buffer = 0; 138 a_length = 0L; 139 return false; 140 } 141 // Get file size : 142 ::fseek(file,0L,SEEK_END); 143 long filesize = ::ftell(file); 144 if(!filesize) { 145 ::fclose(file); 146 a_buffer = new char[1]; 147 #ifdef TOOLS_MEM 148 mem::increment(s_new().c_str()); 149 #endif 150 a_length = 0L; 151 return true; //empty file. 152 } 153 // Add one byte to be able to add \n if file contain lines. 154 a_buffer = new char[filesize+1]; 155 if(!a_buffer) { 156 ::fclose(file); 157 a_buffer = 0; 158 a_length = 0L; 159 return false; 160 } 161 #ifdef TOOLS_MEM 162 mem::increment(s_new().c_str()); 163 #endif 164 ::rewind(file); 165 size_t nitem = ::fread(a_buffer,(size_t)filesize,(size_t)1,file); 166 if(nitem!=1){ 167 ::fclose(file); 168 delete [] a_buffer; 169 #ifdef TOOLS_MEM 170 mem::decrement(s_new().c_str()); 171 #endif 172 a_buffer = 0; 173 a_length = 0L; 174 return false; 175 } 176 ::fclose(file); 177 a_buffer[filesize] = 0; 178 a_length = filesize; 179 return true; 180 } 181 182 inline bool write_bytes(const std::string& a_file,const char* a_buffer,size_t a_length){ 183 FILE* file = ::fopen(a_file.c_str(),"wb"); 184 if(!file) return false; 185 if(!a_length) { 186 ::fclose(file); 187 return true; 188 } 189 size_t nitem = ::fwrite((char*)a_buffer,a_length,(size_t)1,file); 190 ::fclose(file); 191 return (nitem!=1?false:true); 192 } 193 194 inline bool num_csv_doubles(const std::string& a_string,char& a_sep,unsigned int& a_number){ 195 if(a_string.empty()) {a_sep=0;a_number=0;return true;} //it is ok. 196 197 //guess sep : 198 char sep = 0; 199 {const char* buffer = a_string.c_str(); 200 //::printf("debug : |%s|\n",buffer); 201 const char* pos = buffer; 202 const char* mx = buffer+a_string.size(); 203 char* end; 204 {double d = ::strtod(pos,&end);(void)d;} 205 //::printf("debug : d first %g\n",d); 206 if(end==pos) {a_sep=0;a_number=0;return false;} //not starting with a number. 207 if(end==mx) {a_sep=0;a_number=1;return true;} //is ok, one number only. 208 sep = *end;} 209 210 //::printf("debug : %d\n",sep); 211 212 unsigned int number = 0; 213 214 const char* buffer = a_string.c_str(); 215 //::printf("debug : |%s|\n",buffer); 216 const char* pos = buffer; 217 const char* mx = buffer+a_string.size(); 218 while(true) { 219 char* end; 220 {double d = ::strtod(pos,&end);(void)d;} 221 if(end==pos) { 222 if(end>=mx) break; 223 a_sep = sep; 224 a_number = number; 225 return false; //since a number expected. 226 } 227 //::printf("debug : d %g\n",d); 228 number++; 229 if(*end!=sep) { 230 if(end>=mx) break; 231 a_sep = sep; 232 a_number = number; 233 return false; //since a sep is expected. 234 } 235 pos = end+1; 236 if(pos>mx) break; 237 } 238 239 a_sep = sep; 240 a_number = number; 241 return true; 242 } 243 244 // NOTE : take care of the open in exlib/app/tntnet/main_cpp which can't work by using suffix. 245 246 inline bool is_hippo(const std::string& a_file,bool& a_is){ 247 //if((suffix(a_file)=="hiptxt")||(suffix(a_file)=="tnt")) { 248 // a_is = true; 249 // return true; 250 //} 251 // An hippo file as : 252 // one line for title. 253 // one line with n labels separated by \t 254 // data lines with n numbers separated by a char sep (not necessary \t) (at least one data line expected). 255 std::vector<std::string> txt; 256 if(!file::read_num(a_file,3,txt)) {a_is=false;return false;} 257 if(txt.size()<3) {a_is=false;return true;} 258 char csep; 259 unsigned int number; 260 if(!num_csv_doubles(txt[2],csep,number)) {a_is=false;return true;} 261 std::vector<std::string> ws; 262 words(txt[1],"\t",false,ws); 263 if(ws.size()!=number) {a_is=false;return true;} 264 bool all_doubles = true; 265 tools_vforcit(std::string,ws,it) { 266 const char* pos = (*it).c_str(); 267 char* end; 268 double d = ::strtod(pos,&end);(void)d; 269 if(end==pos) {all_doubles=false;break;} 270 } 271 a_is = all_doubles?false:true; //all_double=false then we assume the second line is labels of columns. 272 return true; 273 } 274 275 // NOTE : the below is_csv() does not take into account a column with strings. 276 277 inline bool is_csv(const std::vector<std::string>& a_txt,bool& a_is){ 278 //a_sep = 0; 279 a_is = false; 280 if(a_txt.empty()) return true; 281 282 //guess sep from first data line : 283 char sep = 0; 284 {const char* buffer = a_txt[0].c_str(); 285 //::printf("debug : |%s|\n",buffer); 286 const char* pos = buffer; 287 char* end; 288 {double d = ::strtod(pos,&end);(void)d;} 289 //::printf("debug : d first %g\n",d); 290 if(end==pos) return true; //not starting with a number. 291 //end==mx is ok, one column only. 292 sep = *end;} 293 294 //::printf("debug : %d\n",sep); 295 296 unsigned int first_coln = 0; 297 298 tools_vforcit(std::string,a_txt,it) { 299 const char* buffer = (*it).c_str(); 300 //::printf("debug : |%s|\n",buffer); 301 const char* pos = buffer; 302 const char* mx = buffer+(*it).size(); 303 unsigned int coln = 0; 304 while(true) { 305 char* end; 306 {double d = ::strtod(pos,&end);(void)d;} 307 if(end==pos) break; 308 //::printf("debug : d %g\n",d); 309 if(*end!=sep) return true; 310 coln++; 311 pos = end+1; 312 if(pos>mx) break; 313 } 314 //::printf("debug : coln %d\n",coln); 315 if(it==a_txt.begin()) { 316 first_coln = coln; 317 } else { 318 if(coln!=first_coln) return true; 319 } 320 } 321 322 //a_sep = sep; 323 a_is = true; 324 return true; 325 } 326 327 inline bool is_csv(const std::string& a_file,bool& a_is){ 328 // look at suffix. Some file can't be guessed. 329 if(suffix(a_file)=="csv") {a_is = true;return true;} 330 //try to guess : 331 std::vector<std::string> txt; 332 if(!file::read_num(a_file,3,txt,"#")) {a_is=false;return false;} 333 return is_csv(txt,a_is); 334 } 335 336 inline bool is_lua(const std::string& a_file,bool& a_is){ 337 // look at suffix. Some file can't be guessed. 338 if(suffix(a_file)=="lua") {a_is = true;return true;} 339 //try to guess ? 340 a_is = false; 341 return true; 342 } 343 344 inline bool is_py(const std::string& a_file,bool& a_is){ 345 // look at suffix. Some file can't be guessed. 346 if(suffix(a_file)=="py") {a_is = true;return true;} 347 //try to guess ? 348 a_is = false; 349 return true; 350 } 351 352 inline bool is_kumac(const std::string& a_file,bool& a_is){ 353 // look at suffix. Some file can't be guessed. 354 if(suffix(a_file)=="kumac") {a_is = true;return true;} 355 //try to guess ? 356 a_is = false; 357 return true; 358 } 359 360 inline bool is_insh(const std::string& a_file,bool& a_is){ 361 if(suffix(a_file)=="insh") {a_is = true;return true;} 362 unsigned char head[6]; 363 {unsigned int num = 6; 364 if(!signature(a_file,head,num)) {a_is = false;return false;} 365 if(num!=6) {a_is = false;return true;}} 366 if(head[0]!='#') {a_is = false;return true;} 367 if(head[1]!='!') {a_is = false;return true;} 368 if(head[2]!='i') {a_is = false;return true;} 369 if(head[3]!='n') {a_is = false;return true;} 370 if(head[4]!='s') {a_is = false;return true;} 371 if(head[5]!='h') {a_is = false;return true;} 372 a_is = true; 373 return true; 374 } 375 376 }} 377 378 #include "fileis" 379 380 namespace tools { 381 namespace file { 382 383 inline bool mime_type(const std::string& a_file,std::string& a_mime){ 384 //////////////// 385 // binaries : 386 //////////////// 387 {bool is; 388 if(is_jpeg(a_file,is)&&is) { 389 a_mime = "image/jpeg"; 390 return true; 391 }} 392 393 {bool is; 394 if(is_png(a_file,is)&&is) { 395 a_mime = "image/png"; 396 return true; 397 }} 398 399 {bool is; 400 if(is_ico(a_file,is)&&is) { 401 a_mime = "image/vnd.microsoft.icon"; 402 return true; 403 }} 404 405 {bool is; 406 if(is_fits(a_file,is)&&is) { 407 a_mime = "image/fits"; 408 return true; 409 }} 410 411 {bool is; 412 if(is_gzip(a_file,is)&&is) { 413 a_mime = "application/gzip"; 414 return true; 415 }} 416 417 {bool is; 418 if(is_zip(a_file,is)&&is) { 419 a_mime = "application/zip"; 420 return true; 421 }} 422 423 {bool is; 424 if(is_root(a_file,is)&&is) { 425 a_mime = "application/octet-stream"; 426 return true; 427 }} 428 429 //////////////// 430 // text : 431 //////////////// 432 {bool is; 433 if(is_aida(a_file,is)&&is) { 434 a_mime = "text/xml"; 435 return true; 436 }} 437 {bool is; 438 if(is_exsg(a_file,is)&&is) { 439 a_mime = "text/xml"; 440 return true; 441 }} 442 {bool is; 443 if(is_scenarios(a_file,is)&&is) { 444 a_mime = "text/xml"; 445 return true; 446 }} 447 {bool is; 448 if(is_slides(a_file,is)&&is) { 449 a_mime = "text/xml"; 450 return true; 451 }} 452 {bool is; 453 if(is_gdml(a_file,is)&&is) { 454 a_mime = "text/xml"; 455 return true; 456 }} 457 458 {bool is; 459 if(is_ps(a_file,is)&&is) { 460 a_mime = "application/postscript"; 461 return true; 462 }} 463 464 {bool is; 465 if(is_fog(a_file,is)&&is) { 466 a_mime = "text/plain"; 467 return true; 468 }} 469 470 {bool is; 471 if(is_csv(a_file,is)&&is) { 472 a_mime = "text/csv"; 473 return true; 474 }} 475 476 {bool is; 477 if(is_hippo(a_file,is)&&is) { 478 a_mime = "text/plain"; 479 return true; 480 }} 481 482 {bool is; 483 if(is_dot(a_file,is)&&is) { 484 a_mime = "text/plain"; 485 return true; 486 }} 487 488 {bool is; 489 if(is_iv(a_file,is)&&is) { 490 a_mime = "application/octet-stream"; 491 return true; 492 }} 493 494 a_mime = "application/octet-stream"; 495 return false; 496 } 497 498 /* 499 inline bool copy(const std::string& a_from,const std::string& a_to){ 500 if(a_to==a_from) return true; //done 501 std::vector<std::string> text; 502 if(!file::read(a_from,text)) return false; 503 return file::write(a_to,text); 504 } 505 */ 506 507 inline bool found(const std::string& a_file,const std::string& a_what,std::vector<std::string>& a_found){ 508 a_found.clear(); 509 std::vector<std::string> text; 510 if(!file::read(a_file,text)) return false; 511 tools_vforcit(std::string,text,it) { 512 if((*it).find(a_what)!=std::string::npos) { 513 a_found.push_back(*it); 514 } 515 } 516 return true; 517 } 518 519 inline bool std_remove(const std::string& a_file) { 520 if(a_file.empty()) return true; 521 return (::remove(a_file.c_str()) ==0 ? true : false); 522 } 523 524 inline bool std_remove(std::vector<std::string>& a_files) { 525 bool status = true; 526 tools_vforit(std::string,a_files,it) { 527 if(!std_remove(*it)) status = false; 528 } 529 a_files.clear(); 530 return status; 531 } 532 533 inline bool std_rename(const std::string& a_from,const std::string& a_to) { 534 //NOTE : a_from must not be a path ! 535 // Darwin is ok with a path but not Linux ! 536 // For example : 537 // ::rename("/tmp/tmp01","x"); 538 // return -1 on Linux. 539 // To do the upper then someone must use move. 540 // But there is no move in the standard lib C ! 541 return (::rename(a_from.c_str(),a_to.c_str()) == 0 ? true : false); 542 } 543 544 inline bool copy_bytes(const std::string& a_from,const std::string& a_to) { 545 if(a_to==a_from) return true; 546 char* buffer; 547 long length; 548 if(!read_bytes(a_from,buffer,length)) return false; 549 bool status = write_bytes(a_to,buffer,(size_t)length); 550 delete [] buffer; 551 #ifdef TOOLS_MEM 552 mem::decrement(s_new().c_str()); 553 #endif 554 return status; 555 } 556 557 /* 558 class holder { 559 public: 560 TOOLS_SCLASS(tools::file::holder) 561 public: 562 holder(const std::string& a_path):m_path(a_path){ 563 #ifdef TOOLS_MEM 564 mem::increment(s_class().c_str()); 565 #endif 566 } 567 virtual ~holder() { 568 std_remove(m_path); 569 #ifdef TOOLS_MEM 570 mem::decrement(s_class().c_str()); 571 #endif 572 } 573 public: 574 holder(const holder& a_from):m_path(a_from.m_path){ 575 #ifdef TOOLS_MEM 576 mem::increment(s_class().c_str()); 577 #endif 578 } 579 holder& operator=(const holder& a_from){ 580 m_path = a_from.m_path; 581 return *this; 582 } 583 protected: 584 std::string m_path; 585 }; 586 */ 587 588 }} 589 590 #include "file_reader" 591 592 namespace tools { 593 594 class FILE_reader : public virtual file::reader { 595 public: //file_reader 596 virtual bool open(const std::string& a_file) { 597 if(m_FILE) return false; 598 m_FILE = ::fopen(a_file.c_str(),"rb"); 599 if(!m_FILE) return false; 600 return true; 601 } 602 virtual void close() { 603 if(!m_FILE) return; 604 ::fclose(m_FILE); 605 m_FILE = 0; 606 } 607 virtual bool is_open() const {return m_FILE?true:false;} 608 virtual bool read(char* a_buff,unsigned int a_lbuf,size_t& a_length) { 609 a_length = ::fread(a_buff,1,a_lbuf,m_FILE); 610 return true; 611 } 612 virtual bool get_line(char* a_buff,unsigned int a_lbuf) { 613 return ::fgets(a_buff,a_lbuf,m_FILE)==NULL?false:true; 614 } 615 virtual bool eof() const { 616 #if defined(_MSC_VER) && _MSC_VER <= 1400 617 return feof(m_FILE)?true:false; 618 #else 619 return ::feof(m_FILE)?true:false; 620 #endif 621 } 622 public: 623 FILE_reader():m_FILE(0){} 624 virtual ~FILE_reader() {if(m_FILE) ::fclose(m_FILE);} 625 protected: 626 FILE_reader(const FILE_reader& a_from) 627 :file::reader(a_from) 628 ,m_FILE(0) 629 {} 630 FILE_reader& operator=(const FILE_reader&){return *this;} 631 protected: 632 FILE* m_FILE; 633 }; 634 635 } 636 637 #include "file_format" //backcomp 638 #include "fsize" //backcomp 639 640 #endif