inlib
1.2.0
|
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