inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/file
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_file
00005 #define inlib_file
00006 
00007 #include <string>
00008 #include <vector>
00009 #include <cstdio>
00010 #include <cstdlib>
00011 #include <cstring>
00012 
00013 namespace inlib {
00014 namespace file {
00015 
00016 inline bool exists(const std::string& a_string) {
00017   FILE* file = ::fopen(a_string.c_str(),"rb");
00018   if(!file) return false;
00019   ::fclose(file);
00020   return true;
00021 }
00022 
00023 inline bool size(const std::string& a_file,long& a_size){
00024   FILE* file = ::fopen(a_file.c_str(),"rb");
00025   if(!file) {
00026     a_size = 0L;
00027     return false;
00028   }
00029   //::rewind(file);
00030   ::fseek(file,0L,SEEK_END);
00031   a_size = ::ftell(file);
00032   ::fclose(file);
00033   return true;
00034 }
00035 
00036 inline bool is_empty(const std::string& a_file){
00037   long sz;
00038   if(!size(a_file,sz)) return true; //if not existing, consider it empty.
00039   return (sz==0L)?true:false;  
00040 }
00041 
00042 inline bool write(const std::string& a_file,const std::string& a_string) {
00043   // a_string could contain \n separated lines.
00044   FILE* file = ::fopen(a_file.c_str(),"wb");
00045   if(!file) return false;
00046   if(::fprintf(file,"%s",a_string.c_str())<0) {
00047     ::fclose(file);
00048     return false;
00049   }
00050   ::fclose(file);
00051   return true;
00052 }
00053 
00054 inline bool write(const std::string& a_file,const std::vector<std::string>& a_text){
00055   FILE* file = ::fopen(a_file.c_str(),"wb");
00056   if(!file) return false;
00057   std::vector<std::string>::const_iterator it;
00058   for(it=a_text.begin();it!=a_text.end();++it) {
00059     if(::fprintf(file,"%s\n",(*it).c_str())<0) {
00060       ::fclose(file);
00061       return false;
00062     }
00063   }
00064   ::fclose(file);
00065   return true;
00066 }
00067 
00068 inline bool read_buff(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) {
00069   a_length = ::fread(a_buff,1,a_lbuf,a_file);
00070   return true;
00071 }
00072 
00073 inline bool read_cstring(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) {
00074   if(::fgets(a_buff,a_lbuf,a_file)==NULL) {
00075     a_length = 0;
00076     return false; //EOF
00077   }
00078 
00079   size_t l = ::strlen(a_buff);
00080   //  On Windows, editors when saving binary files,
00081   // put \r\n at place of \n ; we then look for \r\n.
00082   if( (l>=2) && (a_buff[l-2]=='\r') && (a_buff[l-1]=='\n') ) {
00083     a_buff[l-2] = '\0';
00084     l -= 2;
00085   } else if( (l>=1) && (a_buff[l-1]=='\n') ) {
00086     a_buff[l-1] = '\0';
00087     l -= 1;
00088   }
00089 
00090   a_length = l;
00091   return true;
00092 }
00093 
00094 
00095 inline bool read(const std::string& a_file,std::vector<std::string>& a_text){
00096   a_text.clear();
00097   FILE* file = ::fopen(a_file.c_str(),"rb");
00098   if(!file) return false;
00099   unsigned int BUFSIZE = 65536;
00100   char* buffer = new char[BUFSIZE+1];
00101   if(!buffer) {::fclose(file);return false;}
00102   while(true) {
00103     size_t l;
00104     if(!read_cstring(file,buffer,BUFSIZE,l)) break; // EOF.
00105     a_text.push_back(buffer);
00106   }
00107   delete [] buffer;
00108   ::fclose(file);
00109   return true;
00110 }
00111 
00112 inline bool read_num(const std::string& a_file,std::vector<std::string>::size_type a_num,std::vector<std::string>& a_text){
00113   a_text.clear();
00114   FILE* file = ::fopen(a_file.c_str(),"rb");
00115   if(!file) return false;
00116   unsigned int BUFSIZE = 65536;
00117   char* buffer = new char[BUFSIZE+1];
00118   if(!buffer) {::fclose(file);return false;}
00119   while(true) {
00120     size_t l;
00121     if(!read_cstring(file,buffer,BUFSIZE,l)) break; // EOF.
00122     if(a_text.size()<a_num) {
00123       a_text.push_back(buffer);
00124     } else {
00125       break;
00126     }
00127   }
00128   delete [] buffer;
00129   ::fclose(file);
00130   return true;
00131 }
00132 
00133 inline bool read_bytes(const std::string& a_file,char*& a_buffer,long& a_length){
00134   // Returned buffer should be deleted with delete [].
00135   FILE* file = ::fopen(a_file.c_str(),"rb");
00136   if(!file) {
00137     a_buffer = 0;
00138     a_length = 0L;
00139     return false;
00140   }
00141   // Get file size :
00142   ::fseek(file,0L,SEEK_END);
00143   long filesize = ::ftell(file);
00144   if(!filesize) {
00145     ::fclose(file);
00146     a_buffer = new char[1];
00147     a_length = 0L;
00148     return true; //empty file.
00149   }
00150   // Add one byte to be able to add \n if file contain lines.
00151   a_buffer = new char[filesize+1];
00152   if(!a_buffer) {
00153     ::fclose(file);
00154     a_buffer = 0;
00155     a_length = 0L;
00156     return false;
00157   }
00158   ::rewind(file);
00159   size_t nitem = ::fread(a_buffer,(size_t)filesize,(size_t)1,file);
00160   if(nitem!=1){
00161     ::fclose(file);
00162     delete [] a_buffer;
00163     a_buffer = 0;
00164     a_length = 0L;
00165     return false;
00166   }
00167   ::fclose(file);
00168   a_buffer[filesize] = 0;
00169   a_length = filesize;
00170   return true;
00171 }  
00172 
00173 inline bool write_bytes(const std::string& a_file,const char* a_buffer,size_t a_length){
00174   FILE* file = ::fopen(a_file.c_str(),"wb");
00175   if(!file) return false;
00176   if(!a_length) {
00177     ::fclose(file);
00178     return true;
00179   }
00180   size_t nitem = ::fwrite((char*)a_buffer,a_length,(size_t)1,file);
00181   ::fclose(file);
00182   return (nitem!=1?false:true);
00183 }  
00184 
00185 // get the first four "signature" charachters 
00186 inline bool signature(const std::string& a_file,unsigned char a_head[],unsigned int a_num = 4){ //it is assumed a_head[] can contain a_num chars.
00187   FILE* file = ::fopen(a_file.c_str(),"rb");
00188   if(!file) return false;
00189   size_t nitem = ::fread(a_head,1,a_num,file);
00190   ::fclose(file);
00191   if(nitem!=a_num) return false;
00192   return true;
00193 }
00194 
00195 inline bool is_gzip(const std::string& a_file,bool& a_is){
00196   unsigned char head[4];
00197   if(!signature(a_file,head)) {a_is = false;return false;}
00198   if(head[0]!=31) {a_is = false;return true;}
00199   if(head[1]!=139) {a_is = false;return true;}
00200   //if(head[2]!=8) {a_is = false;return true;}
00201   //if(head[3]!=8) {a_is = false;return true;}
00202   a_is = true;  
00203   return true;
00204 }
00205 
00206 inline bool is_jpeg(const std::string& a_file,bool& a_is){
00207   unsigned char head[4];
00208   if(!signature(a_file,head)) {a_is = false;return false;}
00209   if(head[0]!=255) {a_is = false;return true;}
00210   if(head[1]!=216) {a_is = false;return true;}
00211   if(head[2]!=255) {a_is = false;return true;}
00212   //if(head[3]!=224) {a_is = false;return true;} //LRI.jpg is 225 !
00213   a_is = true;  
00214   return true;
00215 }
00216 
00217 inline bool is_png(const std::string& a_file,bool& a_is){
00218   unsigned char head[4];
00219   if(!signature(a_file,head)) {a_is = false;return false;}
00220   if(head[0]!=137) {a_is = false;return true;}
00221   if(head[1]!='P') {a_is = false;return true;}
00222   if(head[2]!='N') {a_is = false;return true;}
00223   if(head[3]!='G') {a_is = false;return true;}
00224   a_is = true;  
00225   return true;
00226 }
00227 
00228 inline bool is_root(const std::string& a_file,bool& a_is){
00229   unsigned char head[4];
00230   if(!signature(a_file,head)) {a_is = false;return false;}
00231   if(head[0]!='r') {a_is = false;return true;}
00232   if(head[1]!='o') {a_is = false;return true;}
00233   if(head[2]!='o') {a_is = false;return true;}
00234   if(head[3]!='t') {a_is = false;return true;}
00235   // Aie, we are in a mess.
00236   a_is = true;  
00237   return true;
00238 }
00239 
00240 inline bool is_iv(const std::string& a_file,bool& a_is){
00241   unsigned char head[9];
00242   if(!signature(a_file,head,9)) {a_is = false;return false;}
00243   if(head[0]!='#') {a_is = false;return true;}
00244   if(head[1]!='I') {a_is = false;return true;}
00245   if(head[2]!='n') {a_is = false;return true;}
00246   if(head[3]!='v') {a_is = false;return true;}
00247   if(head[4]!='e') {a_is = false;return true;}
00248   if(head[5]!='n') {a_is = false;return true;}
00249   if(head[6]!='t') {a_is = false;return true;}
00250   if(head[7]!='o') {a_is = false;return true;}
00251   if(head[8]!='r') {a_is = false;return true;}
00252   a_is = true;  
00253   return true;
00254 }
00255 
00256 inline bool is_aida(const std::string& a_file,bool& a_is){
00257   //NOTE : it assumes that the file is not compressed.
00258   // AIDA XML expected header :
00259   //   <?xml version="1.0" encoding="UTF-8"?>
00260   //   <!DOCTYPE aida SYSTEM "http://aida.freehep.org/schemas/3.0/aida.dtd">
00261   //   <aida version="3.2.1">
00262   std::vector<std::string> lines;
00263   if(!read_num(a_file,2,lines)) {a_is = false;return false;}
00264   if(lines.size()<2) {a_is = false;return false;}
00265   //static const std::string saida = "<!DOCTYPE aida"; //CINT don't want that.
00266   static const char s_aida[] = "<!DOCTYPE aida";
00267   if(lines[1].substr(0,::strlen(s_aida))!=s_aida) {a_is = false;return true;}
00268   a_is = true;  
00269   return true;
00270 }
00271 
00272 inline bool is_exsg(const std::string& a_file,bool& a_is){
00273   unsigned char head[5];
00274   if(!signature(a_file,head,5)) {a_is = false;return false;}
00275   if(head[0]!='<') {a_is = false;return true;}
00276   if(head[1]!='e') {a_is = false;return true;}
00277   if(head[2]!='x') {a_is = false;return true;}
00278   if(head[3]!='s') {a_is = false;return true;}
00279   if(head[4]!='g') {a_is = false;return true;}
00280   a_is = true;  
00281   return true;
00282 }
00283 
00284 /*
00285 inline bool copy(const std::string& a_from,const std::string& a_to){
00286   if(a_to==a_from) return true; //done
00287   std::vector<std::string> text;
00288   if(!inlib::file::read(a_from,text)) return false;
00289   return inlib::file::write(a_to,text);
00290 }
00291 */
00292 
00293 inline bool found(const std::string& a_file,const std::string& a_what,std::vector<std::string>& a_found){
00294   a_found.clear();
00295   std::vector<std::string> text;
00296   if(!inlib::file::read(a_file,text)) return false;
00297   std::vector<std::string>::const_iterator it;
00298   for(it=text.begin();it!=text.end();++it) {
00299     if((*it).find(a_what)!=std::string::npos) {
00300       a_found.push_back(*it);
00301     }
00302   }
00303   return true;
00304 }
00305 
00306 inline bool std_remove(const std::string& a_file) {
00307   return (::remove(a_file.c_str()) ==0 ? true : false);
00308 }
00309 
00310 inline bool std_remove(std::vector<std::string>& a_files) {
00311   bool status = true;
00312   std::vector<std::string>::iterator it;
00313   for(it=a_files.begin();it!=a_files.end();++it) {
00314     if(!std_remove(*it)) status = false;
00315   }
00316   a_files.clear();
00317   return status;
00318 }
00319 
00320 inline bool std_rename(const std::string& a_from,const std::string& a_to) {
00321   //NOTE : a_from must not be a path !
00322   //       Darwin is ok with a path but not Linux !
00323   //       For example : 
00324   //         ::rename("/tmp/tmp01"."x");
00325   //       return -1 on Linux.
00326   //       To do the upper then someone must use move. 
00327   //       But there is no move in the standard lib C !
00328   return (::rename(a_from.c_str(),a_to.c_str()) == 0 ? true : false);
00329 }
00330 
00334 
00335 enum chmod_who { ch_user, ch_group, ch_other, ch_all };
00336 enum chmod_operation { ch_add, ch_sub };
00337 enum chmod_what { ch_read, ch_write, ch_exec };
00338 
00339 inline bool chmod(const std::string& a_file,chmod_who a_who,chmod_operation a_op,chmod_what a_what){
00340 #ifdef WIN32
00341   //FIXME
00342   return false;
00343 #else
00344   std::string cmd = "chmod ";
00345   switch(a_who){
00346   case ch_user: cmd += "u";break;
00347   case ch_group: cmd += "g";break;
00348   case ch_other: cmd += "o";break;
00349   case ch_all: cmd += "a";break;
00350   //default:break;
00351   }
00352   switch(a_op){
00353   case ch_add: cmd += "+";break;
00354   case ch_sub: cmd += "-";break;
00355   //default:break;
00356   }
00357   switch(a_what){
00358   case ch_read: cmd += "r";break;
00359   case ch_write: cmd += "w";break;
00360   case ch_exec: cmd += "x";break;
00361   //default:break;
00362   }
00363   cmd += " ";
00364   cmd += a_file;
00365   int ret = ::system(cmd.c_str());
00366   return (ret==(-1)?false:true);
00367 #endif  
00368 }
00369 
00370 inline std::string quote(const std::string& a_path) {
00371   if(a_path.find(' ')==std::string::npos) return a_path;
00372   // path with spaces :
00373   if(a_path[0]=='"') return a_path; //Already in double quote.
00374   return std::string("\"")+a_path+"\"";
00375 }
00376 
00377 // used in OnX/BaseUI.
00378 inline bool mv(const std::string& a_from,const std::string& a_to){
00379   if(a_to==a_from) return true;
00380 #ifdef WIN32
00381   std::string cmd = "MOVE /Y";
00382 #else
00383   std::string cmd = "/bin/mv";
00384 #endif
00385   cmd += " ";
00386   cmd += quote(a_from);
00387   cmd += " ";
00388   cmd += quote(a_to);
00389   int ret = ::system(cmd.c_str());
00390   return (ret==(-1)?false:true);
00391 }
00392 
00393 inline bool cp(const std::string& a_from,const std::string& a_to) {
00394   if(a_to==a_from) return true;
00395 #ifdef WIN32
00396   std::string cmd = "COPY /Y";
00397 #else
00398   std::string cmd = "/bin/cp";
00399 #endif
00400   cmd += " ";
00401   cmd += quote(a_from);
00402   cmd += " ";
00403   cmd += quote(a_to);
00404   int ret = ::system(cmd.c_str());
00405   return (ret==(-1)?false:true);
00406 }
00407 
00408 inline bool rm(const std::string& a_file){
00409   // WARNING : do not confuse with inlib::file::std_remove which is 
00410   //           an encapsulation of the remove of stdio.h that
00411   //           does not support wildcards.
00412 #ifdef WIN32
00413   std::string cmd = "DEL /Q";
00414 #else
00415   std::string cmd = "/bin/rm -f";
00416 #endif
00417   cmd += " ";
00418   cmd += quote(a_file);
00419   int ret = ::system(cmd.c_str());
00420   return (ret==(-1)?false:true);
00421 }
00422 
00423 }}
00424 
00425 #include "file_reader"
00426 
00427 namespace inlib {
00428 
00429 class FILE_reader : public virtual inlib::file::reader {
00430 public: //file_reader
00431   virtual bool open(const std::string& a_file) {
00432     if(m_FILE) return false;
00433     m_FILE = ::fopen(a_file.c_str(),"rb");
00434     if(!m_FILE) return false;
00435     return true;
00436   }
00437   virtual void close() {
00438     if(!m_FILE) return;
00439     ::fclose(m_FILE);
00440     m_FILE = 0;
00441   }
00442   virtual bool is_open() const {return m_FILE?true:false;}
00443   virtual bool read(char* a_buff,unsigned int a_lbuf,
00444                     size_t& a_length) {
00445     a_length = ::fread(a_buff,1,a_lbuf,m_FILE);
00446     return true;
00447   }
00448 public:
00449   FILE_reader():m_FILE(0){}
00450   virtual ~FILE_reader() {if(m_FILE) ::fclose(m_FILE);}
00451 protected:
00452   FILE_reader(const FILE_reader& a_from)
00453   : inlib::file::reader(a_from)
00454   ,m_FILE(0)
00455   {}
00456   FILE_reader& operator=(const FILE_reader&){return *this;}
00457 private:
00458   FILE* m_FILE;
00459 };
00460 
00461 }
00462 
00463 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines