// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_file #define tools_file #include "gzip" #include "forit" #include "words" //is_hippo #include "path" //suffix #include "S_STRING" #include #include #ifdef TOOLS_MEM #include "mem" #endif namespace tools { namespace file { inline bool exists(const std::string& a_string) { FILE* file = ::fopen(a_string.c_str(),"rb"); if(!file) return false; ::fclose(file); return true; } inline bool write(const std::string& a_file,const std::string& a_string) { // a_string could contain \n separated lines. FILE* file = ::fopen(a_file.c_str(),"wb"); if(!file) return false; if(::fprintf(file,"%s",a_string.c_str())<0) { ::fclose(file); return false; } ::fclose(file); return true; } inline bool write(const std::string& a_file,const std::vector& a_text){ FILE* file = ::fopen(a_file.c_str(),"wb"); if(!file) return false; tools_vforcit(std::string,a_text,it) { if(::fprintf(file,"%s\n",(*it).c_str())<0) { ::fclose(file); return false; } } ::fclose(file); return true; } inline bool read_buff(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) { a_length = ::fread(a_buff,1,a_lbuf,a_file); return true; } inline bool read_cstring(FILE* a_file,char* a_buff,unsigned int a_lbuf,size_t& a_length) { if(::fgets(a_buff,a_lbuf,a_file)==NULL) { a_length = 0; return false; //EOF } size_t l = ::strlen(a_buff); // On Windows, editors when saving binary files, // put \r\n at place of \n ; we then look for \r\n. if( (l>=2) && (a_buff[l-2]=='\r') && (a_buff[l-1]=='\n') ) { a_buff[l-2] = '\0'; l -= 2; } else if( (l>=1) && (a_buff[l-1]=='\n') ) { a_buff[l-1] = '\0'; l -= 1; } a_length = l; return true; } inline bool read(const std::string& a_file,std::vector& a_text){ a_text.clear(); FILE* file = ::fopen(a_file.c_str(),"rb"); if(!file) return false; unsigned int BUFSIZE = 65536; char* buffer = new char[BUFSIZE+1]; if(!buffer) {::fclose(file);return false;} while(true) { size_t l; if(!read_cstring(file,buffer,BUFSIZE,l)) break; // EOF. a_text.push_back(buffer); } delete [] buffer; ::fclose(file); return true; } inline bool read_num(const std::string& a_file,std::vector::size_type a_num,std::vector& a_text,const std::string& a_cmt = ""){ a_text.clear(); FILE* file = ::fopen(a_file.c_str(),"rb"); if(!file) return false; unsigned int BUFSIZE = 65536; char* buffer = new char[BUFSIZE+1]; if(!buffer) {::fclose(file);return false;} while(true) { size_t l; if(!read_cstring(file,buffer,BUFSIZE,l)) break; // EOF. if(a_cmt.size()&&(!strncmp(a_cmt.c_str(),buffer,a_cmt.size()))) continue; if(a_text.size()=mx) break; a_sep = sep; a_number = number; return false; //since a number expected. } //::printf("debug : d %g\n",d); number++; if(*end!=sep) { if(end>=mx) break; a_sep = sep; a_number = number; return false; //since a sep is expected. } pos = end+1; if(pos>mx) break; } a_sep = sep; a_number = number; return true; } // NOTE : take care of the open in exlib/app/tntnet/main_cpp which can't work by using suffix. inline bool is_hippo(const std::string& a_file,bool& a_is){ //if((suffix(a_file)=="hiptxt")||(suffix(a_file)=="tnt")) { // a_is = true; // return true; //} // An hippo file as : // one line for title. // one line with n labels separated by \t // data lines with n numbers separated by a char sep (not necessary \t) (at least one data line expected). std::vector txt; if(!file::read_num(a_file,3,txt)) {a_is=false;return false;} if(txt.size()<3) {a_is=false;return true;} char csep; unsigned int number; if(!num_csv_doubles(txt[2],csep,number)) {a_is=false;return true;} std::vector ws; words(txt[1],"\t",false,ws); if(ws.size()!=number) {a_is=false;return true;} bool all_doubles = true; tools_vforcit(std::string,ws,it) { const char* pos = (*it).c_str(); char* end; double d = ::strtod(pos,&end);(void)d; if(end==pos) {all_doubles=false;break;} } a_is = all_doubles?false:true; //all_double=false then we assume the second line is labels of columns. return true; } // NOTE : the below is_csv() does not take into account a column with strings. inline bool is_csv(const std::vector& a_txt,bool& a_is){ //a_sep = 0; a_is = false; if(a_txt.empty()) return true; //guess sep from first data line : char sep = 0; {const char* buffer = a_txt[0].c_str(); //::printf("debug : |%s|\n",buffer); const char* pos = buffer; char* end; {double d = ::strtod(pos,&end);(void)d;} //::printf("debug : d first %g\n",d); if(end==pos) return true; //not starting with a number. //end==mx is ok, one column only. sep = *end;} //::printf("debug : %d\n",sep); unsigned int first_coln = 0; tools_vforcit(std::string,a_txt,it) { const char* buffer = (*it).c_str(); //::printf("debug : |%s|\n",buffer); const char* pos = buffer; const char* mx = buffer+(*it).size(); unsigned int coln = 0; while(true) { char* end; {double d = ::strtod(pos,&end);(void)d;} if(end==pos) break; //::printf("debug : d %g\n",d); if(*end!=sep) return true; coln++; pos = end+1; if(pos>mx) break; } //::printf("debug : coln %d\n",coln); if(it==a_txt.begin()) { first_coln = coln; } else { if(coln!=first_coln) return true; } } //a_sep = sep; a_is = true; return true; } inline bool is_csv(const std::string& a_file,bool& a_is){ // look at suffix. Some file can't be guessed. if(suffix(a_file)=="csv") {a_is = true;return true;} //try to guess : std::vector txt; if(!file::read_num(a_file,3,txt,"#")) {a_is=false;return false;} return is_csv(txt,a_is); } inline bool is_lua(const std::string& a_file,bool& a_is){ // look at suffix. Some file can't be guessed. if(suffix(a_file)=="lua") {a_is = true;return true;} //try to guess ? a_is = false; return true; } inline bool is_py(const std::string& a_file,bool& a_is){ // look at suffix. Some file can't be guessed. if(suffix(a_file)=="py") {a_is = true;return true;} //try to guess ? a_is = false; return true; } }} #include "fileis" namespace tools { namespace file { inline bool mime_type(const std::string& a_file,std::string& a_mime){ //////////////// // binaries : //////////////// {bool is; if(is_jpeg(a_file,is)&&is) { a_mime = "image/jpeg"; return true; }} {bool is; if(is_png(a_file,is)&&is) { a_mime = "image/png"; return true; }} {bool is; if(is_ico(a_file,is)&&is) { a_mime = "image/vnd.microsoft.icon"; return true; }} {bool is; if(is_fits(a_file,is)&&is) { a_mime = "image/fits"; return true; }} {bool is; if(is_gzip(a_file,is)&&is) { a_mime = "application/gzip"; return true; }} {bool is; if(is_zip(a_file,is)&&is) { a_mime = "application/zip"; return true; }} {bool is; if(is_root(a_file,is)&&is) { a_mime = "application/octet-stream"; return true; }} //////////////// // text : //////////////// {bool is; if(is_aida(a_file,is)&&is) { a_mime = "text/xml"; return true; }} {bool is; if(is_exsg(a_file,is)&&is) { a_mime = "text/xml"; return true; }} {bool is; if(is_scenarios(a_file,is)&&is) { a_mime = "text/xml"; return true; }} {bool is; if(is_slides(a_file,is)&&is) { a_mime = "text/xml"; return true; }} {bool is; if(is_gdml(a_file,is)&&is) { a_mime = "text/xml"; return true; }} {bool is; if(is_ps(a_file,is)&&is) { a_mime = "application/postscript"; return true; }} {bool is; if(is_fog(a_file,is)&&is) { a_mime = "text/plain"; return true; }} {bool is; if(is_csv(a_file,is)&&is) { a_mime = "text/csv"; return true; }} {bool is; if(is_hippo(a_file,is)&&is) { a_mime = "text/plain"; return true; }} {bool is; if(is_dot(a_file,is)&&is) { a_mime = "text/plain"; return true; }} {bool is; if(is_iv(a_file,is)&&is) { a_mime = "application/octet-stream"; return true; }} a_mime = "application/octet-stream"; return false; } /* inline bool copy(const std::string& a_from,const std::string& a_to){ if(a_to==a_from) return true; //done std::vector text; if(!file::read(a_from,text)) return false; return file::write(a_to,text); } */ inline bool found(const std::string& a_file,const std::string& a_what,std::vector& a_found){ a_found.clear(); std::vector text; if(!file::read(a_file,text)) return false; tools_vforcit(std::string,text,it) { if((*it).find(a_what)!=std::string::npos) { a_found.push_back(*it); } } return true; } inline bool std_remove(const std::string& a_file) { if(a_file.empty()) return true; return (::remove(a_file.c_str()) ==0 ? true : false); } inline bool std_remove(std::vector& a_files) { bool status = true; tools_vforit(std::string,a_files,it) { if(!std_remove(*it)) status = false; } a_files.clear(); return status; } inline bool std_rename(const std::string& a_from,const std::string& a_to) { //NOTE : a_from must not be a path ! // Darwin is ok with a path but not Linux ! // For example : // ::rename("/tmp/tmp01"."x"); // return -1 on Linux. // To do the upper then someone must use move. // But there is no move in the standard lib C ! return (::rename(a_from.c_str(),a_to.c_str()) == 0 ? true : false); } inline bool copy_bytes(const std::string& a_from,const std::string& a_to) { if(a_to==a_from) return true; char* buffer; long length; if(!read_bytes(a_from,buffer,length)) return false; bool status = write_bytes(a_to,buffer,(size_t)length); delete [] buffer; #ifdef TOOLS_MEM mem::decrement(s_new().c_str()); #endif return status; } /* class holder { public: TOOLS_SCLASS(tools::file::holder) public: holder(const std::string& a_path):m_path(a_path){ #ifdef TOOLS_MEM mem::increment(s_class().c_str()); #endif } virtual ~holder() { std_remove(m_path); #ifdef TOOLS_MEM mem::decrement(s_class().c_str()); #endif } public: holder(const holder& a_from):m_path(a_from.m_path){ #ifdef TOOLS_MEM mem::increment(s_class().c_str()); #endif } holder& operator=(const holder& a_from){ m_path = a_from.m_path; return *this; } protected: std::string m_path; }; */ }} #include "file_reader" namespace tools { class FILE_reader : public virtual file::reader { public: //file_reader virtual bool open(const std::string& a_file) { if(m_FILE) return false; m_FILE = ::fopen(a_file.c_str(),"rb"); if(!m_FILE) return false; return true; } virtual void close() { if(!m_FILE) return; ::fclose(m_FILE); m_FILE = 0; } virtual bool is_open() const {return m_FILE?true:false;} virtual bool read(char* a_buff,unsigned int a_lbuf,size_t& a_length) { a_length = ::fread(a_buff,1,a_lbuf,m_FILE); return true; } virtual bool get_line(char* a_buff,unsigned int a_lbuf) { return ::fgets(a_buff,a_lbuf,m_FILE)==NULL?false:true; } virtual bool eof() const { #if defined(_MSC_VER) && _MSC_VER <= 1400 return feof(m_FILE)?true:false; #else return ::feof(m_FILE)?true:false; #endif } public: FILE_reader():m_FILE(0){} virtual ~FILE_reader() {if(m_FILE) ::fclose(m_FILE);} protected: FILE_reader(const FILE_reader& a_from) :file::reader(a_from) ,m_FILE(0) {} FILE_reader& operator=(const FILE_reader&){return *this;} protected: FILE* m_FILE; }; } #include "file_format" //backcomp #include "fsize" //backcomp #endif