Warning, /include/Geant4/tools/file is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_file
0005 #define tools_file
0006
0007 #include "gzip"
0008 #include "forit"
0009 #include "words" //is_hippo
0010 #include "path" //suffix
0011 #include "S_STRING"
0012
0013 #include <cstdlib>
0014 #include <cstring>
0015
0016 #ifdef TOOLS_MEM
0017 #include "mem"
0018 #endif
0019
0020 namespace tools {
0021 namespace file {
0022
0023 inline bool exists(const std::string& a_string) {
0024 FILE* file = ::fopen(a_string.c_str(),"rb");
0025 if(!file) return false;
0026 ::fclose(file);
0027 return true;
0028 }
0029
0030 inline bool write(const std::string& a_file,const std::string& a_string) {
0031 // a_string could contain \n separated lines.
0032 FILE* file = ::fopen(a_file.c_str(),"wb");
0033 if(!file) return false;
0034 if(::fprintf(file,"%s",a_string.c_str())<0) {
0035 ::fclose(file);
0036 return false;
0037 }
0038 ::fclose(file);
0039 return true;
0040 }
0041
0042 inline bool write(const std::string& a_file,const std::vector<std::string>& a_text){
0043 FILE* file = ::fopen(a_file.c_str(),"wb");
0044 if(!file) return false;
0045 tools_vforcit(std::string,a_text,it) {
0046 if(::fprintf(file,"%s\n",(*it).c_str())<0) {
0047 ::fclose(file);
0048 return false;
0049 }
0050 }
0051 ::fclose(file);
0052 return true;
0053 }
0054
0055 inline bool make_empty(const std::string& a_file) {
0056 FILE* file = ::fopen(a_file.c_str(),"wb");
0057 if(!file) return false;
0058 ::fclose(file);
0059 return true;
0060 }
0061
0062 inline bool read_buff(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) {
0063 a_length = ::fread(a_buff,1,a_lbuf,a_file);
0064 return true;
0065 }
0066
0067 inline bool read_cstring(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) {
0068 if(::fgets(a_buff,a_lbuf,a_file)==NULL) {
0069 a_length = 0;
0070 return false; //EOF
0071 }
0072
0073 size_t l = ::strlen(a_buff);
0074 // On Windows, editors when saving binary files,
0075 // put \r\n at place of \n ; we then look for \r\n.
0076 if( (l>=2) && (a_buff[l-2]=='\r') && (a_buff[l-1]=='\n') ) {
0077 a_buff[l-2] = '\0';
0078 l -= 2;
0079 } else if( (l>=1) && (a_buff[l-1]=='\n') ) {
0080 a_buff[l-1] = '\0';
0081 l -= 1;
0082 }
0083
0084 a_length = l;
0085 return true;
0086 }
0087
0088
0089 inline bool read(FILE* a_FILE,std::vector<std::string>& a_text){
0090 a_text.clear();
0091 unsigned int BUFSIZE = 65536;
0092 char* buffer = new char[BUFSIZE+1];
0093 if(!buffer) return false;
0094 while(true) {
0095 size_t l;
0096 if(!read_cstring(a_FILE,buffer,BUFSIZE,l)) break; // EOF.
0097 a_text.push_back(buffer);
0098 }
0099 delete [] buffer;
0100 return true;
0101 }
0102
0103 inline bool read(const std::string& a_file,std::vector<std::string>& a_text){
0104 FILE* file = ::fopen(a_file.c_str(),"rb");
0105 if(!file) {a_text.clear();return false;}
0106 bool status = read(file,a_text);
0107 ::fclose(file);
0108 return status;
0109 }
0110
0111 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 = ""){
0112 a_text.clear();
0113 FILE* file = ::fopen(a_file.c_str(),"rb");
0114 if(!file) return false;
0115 unsigned int BUFSIZE = 65536;
0116 char* buffer = new char[BUFSIZE+1];
0117 if(!buffer) {::fclose(file);return false;}
0118 while(true) {
0119 size_t l;
0120 if(!read_cstring(file,buffer,BUFSIZE,l)) break; // EOF.
0121 if(a_cmt.size()&&(!strncmp(a_cmt.c_str(),buffer,a_cmt.size()))) continue;
0122 if(a_text.size()<a_num) {
0123 a_text.push_back(buffer);
0124 } else {
0125 break;
0126 }
0127 }
0128 delete [] buffer;
0129 ::fclose(file);
0130 return true;
0131 }
0132
0133 inline bool read_bytes(const std::string& a_file,char*& a_buffer,long& a_length){
0134 // Returned buffer should be deleted with delete [].
0135 FILE* file = ::fopen(a_file.c_str(),"rb");
0136 if(!file) {
0137 a_buffer = 0;
0138 a_length = 0L;
0139 return false;
0140 }
0141 // Get file size :
0142 ::fseek(file,0L,SEEK_END);
0143 long filesize = ::ftell(file);
0144 if(!filesize) {
0145 ::fclose(file);
0146 a_buffer = new char[1];
0147 #ifdef TOOLS_MEM
0148 mem::increment(s_new().c_str());
0149 #endif
0150 a_length = 0L;
0151 return true; //empty file.
0152 }
0153 // Add one byte to be able to add \n if file contain lines.
0154 a_buffer = new char[filesize+1];
0155 if(!a_buffer) {
0156 ::fclose(file);
0157 a_buffer = 0;
0158 a_length = 0L;
0159 return false;
0160 }
0161 #ifdef TOOLS_MEM
0162 mem::increment(s_new().c_str());
0163 #endif
0164 ::rewind(file);
0165 size_t nitem = ::fread(a_buffer,(size_t)filesize,(size_t)1,file);
0166 if(nitem!=1){
0167 ::fclose(file);
0168 delete [] a_buffer;
0169 #ifdef TOOLS_MEM
0170 mem::decrement(s_new().c_str());
0171 #endif
0172 a_buffer = 0;
0173 a_length = 0L;
0174 return false;
0175 }
0176 ::fclose(file);
0177 a_buffer[filesize] = 0;
0178 a_length = filesize;
0179 return true;
0180 }
0181
0182 inline bool write_bytes(const std::string& a_file,const char* a_buffer,size_t a_length){
0183 FILE* file = ::fopen(a_file.c_str(),"wb");
0184 if(!file) return false;
0185 if(!a_length) {
0186 ::fclose(file);
0187 return true;
0188 }
0189 size_t nitem = ::fwrite((char*)a_buffer,a_length,(size_t)1,file);
0190 ::fclose(file);
0191 return (nitem!=1?false:true);
0192 }
0193
0194 inline bool num_csv_doubles(const std::string& a_string,char& a_sep,unsigned int& a_number){
0195 if(a_string.empty()) {a_sep=0;a_number=0;return true;} //it is ok.
0196
0197 //guess sep :
0198 char sep = 0;
0199 {const char* buffer = a_string.c_str();
0200 //::printf("debug : |%s|\n",buffer);
0201 const char* pos = buffer;
0202 const char* mx = buffer+a_string.size();
0203 char* end;
0204 {double d = ::strtod(pos,&end);(void)d;}
0205 //::printf("debug : d first %g\n",d);
0206 if(end==pos) {a_sep=0;a_number=0;return false;} //not starting with a number.
0207 if(end==mx) {a_sep=0;a_number=1;return true;} //is ok, one number only.
0208 sep = *end;}
0209
0210 //::printf("debug : %d\n",sep);
0211
0212 unsigned int number = 0;
0213
0214 const char* buffer = a_string.c_str();
0215 //::printf("debug : |%s|\n",buffer);
0216 const char* pos = buffer;
0217 const char* mx = buffer+a_string.size();
0218 while(true) {
0219 char* end;
0220 {double d = ::strtod(pos,&end);(void)d;}
0221 if(end==pos) {
0222 if(end>=mx) break;
0223 a_sep = sep;
0224 a_number = number;
0225 return false; //since a number expected.
0226 }
0227 //::printf("debug : d %g\n",d);
0228 number++;
0229 if(*end!=sep) {
0230 if(end>=mx) break;
0231 a_sep = sep;
0232 a_number = number;
0233 return false; //since a sep is expected.
0234 }
0235 pos = end+1;
0236 if(pos>mx) break;
0237 }
0238
0239 a_sep = sep;
0240 a_number = number;
0241 return true;
0242 }
0243
0244 // NOTE : take care of the open in exlib/app/tntnet/main_cpp which can't work by using suffix.
0245
0246 inline bool is_hippo(const std::string& a_file,bool& a_is){
0247 //if((suffix(a_file)=="hiptxt")||(suffix(a_file)=="tnt")) {
0248 // a_is = true;
0249 // return true;
0250 //}
0251 // An hippo file as :
0252 // one line for title.
0253 // one line with n labels separated by \t
0254 // data lines with n numbers separated by a char sep (not necessary \t) (at least one data line expected).
0255 std::vector<std::string> txt;
0256 if(!file::read_num(a_file,3,txt)) {a_is=false;return false;}
0257 if(txt.size()<3) {a_is=false;return true;}
0258 char csep;
0259 unsigned int number;
0260 if(!num_csv_doubles(txt[2],csep,number)) {a_is=false;return true;}
0261 std::vector<std::string> ws;
0262 words(txt[1],"\t",false,ws);
0263 if(ws.size()!=number) {a_is=false;return true;}
0264 bool all_doubles = true;
0265 tools_vforcit(std::string,ws,it) {
0266 const char* pos = (*it).c_str();
0267 char* end;
0268 double d = ::strtod(pos,&end);(void)d;
0269 if(end==pos) {all_doubles=false;break;}
0270 }
0271 a_is = all_doubles?false:true; //all_double=false then we assume the second line is labels of columns.
0272 return true;
0273 }
0274
0275 // NOTE : the below is_csv() does not take into account a column with strings.
0276
0277 inline bool is_csv(const std::vector<std::string>& a_txt,bool& a_is){
0278 //a_sep = 0;
0279 a_is = false;
0280 if(a_txt.empty()) return true;
0281
0282 //guess sep from first data line :
0283 char sep = 0;
0284 {const char* buffer = a_txt[0].c_str();
0285 //::printf("debug : |%s|\n",buffer);
0286 const char* pos = buffer;
0287 char* end;
0288 {double d = ::strtod(pos,&end);(void)d;}
0289 //::printf("debug : d first %g\n",d);
0290 if(end==pos) return true; //not starting with a number.
0291 //end==mx is ok, one column only.
0292 sep = *end;}
0293
0294 //::printf("debug : %d\n",sep);
0295
0296 unsigned int first_coln = 0;
0297
0298 tools_vforcit(std::string,a_txt,it) {
0299 const char* buffer = (*it).c_str();
0300 //::printf("debug : |%s|\n",buffer);
0301 const char* pos = buffer;
0302 const char* mx = buffer+(*it).size();
0303 unsigned int coln = 0;
0304 while(true) {
0305 char* end;
0306 {double d = ::strtod(pos,&end);(void)d;}
0307 if(end==pos) break;
0308 //::printf("debug : d %g\n",d);
0309 if(*end!=sep) return true;
0310 coln++;
0311 pos = end+1;
0312 if(pos>mx) break;
0313 }
0314 //::printf("debug : coln %d\n",coln);
0315 if(it==a_txt.begin()) {
0316 first_coln = coln;
0317 } else {
0318 if(coln!=first_coln) return true;
0319 }
0320 }
0321
0322 //a_sep = sep;
0323 a_is = true;
0324 return true;
0325 }
0326
0327 inline bool is_csv(const std::string& a_file,bool& a_is){
0328 // look at suffix. Some file can't be guessed.
0329 if(suffix(a_file)=="csv") {a_is = true;return true;}
0330 //try to guess :
0331 std::vector<std::string> txt;
0332 if(!file::read_num(a_file,3,txt,"#")) {a_is=false;return false;}
0333 return is_csv(txt,a_is);
0334 }
0335
0336 inline bool is_lua(const std::string& a_file,bool& a_is){
0337 // look at suffix. Some file can't be guessed.
0338 if(suffix(a_file)=="lua") {a_is = true;return true;}
0339 //try to guess ?
0340 a_is = false;
0341 return true;
0342 }
0343
0344 inline bool is_py(const std::string& a_file,bool& a_is){
0345 // look at suffix. Some file can't be guessed.
0346 if(suffix(a_file)=="py") {a_is = true;return true;}
0347 //try to guess ?
0348 a_is = false;
0349 return true;
0350 }
0351
0352 inline bool is_kumac(const std::string& a_file,bool& a_is){
0353 // look at suffix. Some file can't be guessed.
0354 if(suffix(a_file)=="kumac") {a_is = true;return true;}
0355 //try to guess ?
0356 a_is = false;
0357 return true;
0358 }
0359
0360 inline bool is_insh(const std::string& a_file,bool& a_is){
0361 if(suffix(a_file)=="insh") {a_is = true;return true;}
0362 unsigned char head[6];
0363 {unsigned int num = 6;
0364 if(!signature(a_file,head,num)) {a_is = false;return false;}
0365 if(num!=6) {a_is = false;return true;}}
0366 if(head[0]!='#') {a_is = false;return true;}
0367 if(head[1]!='!') {a_is = false;return true;}
0368 if(head[2]!='i') {a_is = false;return true;}
0369 if(head[3]!='n') {a_is = false;return true;}
0370 if(head[4]!='s') {a_is = false;return true;}
0371 if(head[5]!='h') {a_is = false;return true;}
0372 a_is = true;
0373 return true;
0374 }
0375
0376 }}
0377
0378 #include "fileis"
0379
0380 namespace tools {
0381 namespace file {
0382
0383 inline bool mime_type(const std::string& a_file,std::string& a_mime){
0384 ////////////////
0385 // binaries :
0386 ////////////////
0387 {bool is;
0388 if(is_jpeg(a_file,is)&&is) {
0389 a_mime = "image/jpeg";
0390 return true;
0391 }}
0392
0393 {bool is;
0394 if(is_png(a_file,is)&&is) {
0395 a_mime = "image/png";
0396 return true;
0397 }}
0398
0399 {bool is;
0400 if(is_ico(a_file,is)&&is) {
0401 a_mime = "image/vnd.microsoft.icon";
0402 return true;
0403 }}
0404
0405 {bool is;
0406 if(is_fits(a_file,is)&&is) {
0407 a_mime = "image/fits";
0408 return true;
0409 }}
0410
0411 {bool is;
0412 if(is_gzip(a_file,is)&&is) {
0413 a_mime = "application/gzip";
0414 return true;
0415 }}
0416
0417 {bool is;
0418 if(is_zip(a_file,is)&&is) {
0419 a_mime = "application/zip";
0420 return true;
0421 }}
0422
0423 {bool is;
0424 if(is_root(a_file,is)&&is) {
0425 a_mime = "application/octet-stream";
0426 return true;
0427 }}
0428
0429 ////////////////
0430 // text :
0431 ////////////////
0432 {bool is;
0433 if(is_aida(a_file,is)&&is) {
0434 a_mime = "text/xml";
0435 return true;
0436 }}
0437 {bool is;
0438 if(is_exsg(a_file,is)&&is) {
0439 a_mime = "text/xml";
0440 return true;
0441 }}
0442 {bool is;
0443 if(is_scenarios(a_file,is)&&is) {
0444 a_mime = "text/xml";
0445 return true;
0446 }}
0447 {bool is;
0448 if(is_slides(a_file,is)&&is) {
0449 a_mime = "text/xml";
0450 return true;
0451 }}
0452 {bool is;
0453 if(is_gdml(a_file,is)&&is) {
0454 a_mime = "text/xml";
0455 return true;
0456 }}
0457
0458 {bool is;
0459 if(is_ps(a_file,is)&&is) {
0460 a_mime = "application/postscript";
0461 return true;
0462 }}
0463
0464 {bool is;
0465 if(is_fog(a_file,is)&&is) {
0466 a_mime = "text/plain";
0467 return true;
0468 }}
0469
0470 {bool is;
0471 if(is_csv(a_file,is)&&is) {
0472 a_mime = "text/csv";
0473 return true;
0474 }}
0475
0476 {bool is;
0477 if(is_hippo(a_file,is)&&is) {
0478 a_mime = "text/plain";
0479 return true;
0480 }}
0481
0482 {bool is;
0483 if(is_dot(a_file,is)&&is) {
0484 a_mime = "text/plain";
0485 return true;
0486 }}
0487
0488 {bool is;
0489 if(is_iv(a_file,is)&&is) {
0490 a_mime = "application/octet-stream";
0491 return true;
0492 }}
0493
0494 a_mime = "application/octet-stream";
0495 return false;
0496 }
0497
0498 /*
0499 inline bool copy(const std::string& a_from,const std::string& a_to){
0500 if(a_to==a_from) return true; //done
0501 std::vector<std::string> text;
0502 if(!file::read(a_from,text)) return false;
0503 return file::write(a_to,text);
0504 }
0505 */
0506
0507 inline bool found(const std::string& a_file,const std::string& a_what,std::vector<std::string>& a_found){
0508 a_found.clear();
0509 std::vector<std::string> text;
0510 if(!file::read(a_file,text)) return false;
0511 tools_vforcit(std::string,text,it) {
0512 if((*it).find(a_what)!=std::string::npos) {
0513 a_found.push_back(*it);
0514 }
0515 }
0516 return true;
0517 }
0518
0519 inline bool std_remove(const std::string& a_file) {
0520 if(a_file.empty()) return true;
0521 return (::remove(a_file.c_str()) ==0 ? true : false);
0522 }
0523
0524 inline bool std_remove(std::vector<std::string>& a_files) {
0525 bool status = true;
0526 tools_vforit(std::string,a_files,it) {
0527 if(!std_remove(*it)) status = false;
0528 }
0529 a_files.clear();
0530 return status;
0531 }
0532
0533 inline bool std_rename(const std::string& a_from,const std::string& a_to) {
0534 //NOTE : a_from must not be a path !
0535 // Darwin is ok with a path but not Linux !
0536 // For example :
0537 // ::rename("/tmp/tmp01","x");
0538 // return -1 on Linux.
0539 // To do the upper then someone must use move.
0540 // But there is no move in the standard lib C !
0541 return (::rename(a_from.c_str(),a_to.c_str()) == 0 ? true : false);
0542 }
0543
0544 inline bool copy_bytes(const std::string& a_from,const std::string& a_to) {
0545 if(a_to==a_from) return true;
0546 char* buffer;
0547 long length;
0548 if(!read_bytes(a_from,buffer,length)) return false;
0549 bool status = write_bytes(a_to,buffer,(size_t)length);
0550 delete [] buffer;
0551 #ifdef TOOLS_MEM
0552 mem::decrement(s_new().c_str());
0553 #endif
0554 return status;
0555 }
0556
0557 /*
0558 class holder {
0559 public:
0560 TOOLS_SCLASS(tools::file::holder)
0561 public:
0562 holder(const std::string& a_path):m_path(a_path){
0563 #ifdef TOOLS_MEM
0564 mem::increment(s_class().c_str());
0565 #endif
0566 }
0567 virtual ~holder() {
0568 std_remove(m_path);
0569 #ifdef TOOLS_MEM
0570 mem::decrement(s_class().c_str());
0571 #endif
0572 }
0573 public:
0574 holder(const holder& a_from):m_path(a_from.m_path){
0575 #ifdef TOOLS_MEM
0576 mem::increment(s_class().c_str());
0577 #endif
0578 }
0579 holder& operator=(const holder& a_from){
0580 m_path = a_from.m_path;
0581 return *this;
0582 }
0583 protected:
0584 std::string m_path;
0585 };
0586 */
0587
0588 }}
0589
0590 #include "file_reader"
0591
0592 namespace tools {
0593
0594 class FILE_reader : public virtual file::reader {
0595 public: //file_reader
0596 virtual bool open(const std::string& a_file) {
0597 if(m_FILE) return false;
0598 m_FILE = ::fopen(a_file.c_str(),"rb");
0599 if(!m_FILE) return false;
0600 return true;
0601 }
0602 virtual void close() {
0603 if(!m_FILE) return;
0604 ::fclose(m_FILE);
0605 m_FILE = 0;
0606 }
0607 virtual bool is_open() const {return m_FILE?true:false;}
0608 virtual bool read(char* a_buff,unsigned int a_lbuf,size_t& a_length) {
0609 a_length = ::fread(a_buff,1,a_lbuf,m_FILE);
0610 return true;
0611 }
0612 virtual bool get_line(char* a_buff,unsigned int a_lbuf) {
0613 return ::fgets(a_buff,a_lbuf,m_FILE)==NULL?false:true;
0614 }
0615 virtual bool eof() const {
0616 #if defined(_MSC_VER) && _MSC_VER <= 1400
0617 return feof(m_FILE)?true:false;
0618 #else
0619 return ::feof(m_FILE)?true:false;
0620 #endif
0621 }
0622 public:
0623 FILE_reader():m_FILE(0){}
0624 virtual ~FILE_reader() {if(m_FILE) ::fclose(m_FILE);}
0625 protected:
0626 FILE_reader(const FILE_reader& a_from)
0627 :file::reader(a_from)
0628 ,m_FILE(0)
0629 {}
0630 FILE_reader& operator=(const FILE_reader&){return *this;}
0631 protected:
0632 FILE* m_FILE;
0633 };
0634
0635 }
0636
0637 #include "file_format" //backcomp
0638 #include "fsize" //backcomp
0639
0640 #endif