Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/file

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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