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_fcache 00005 #define inlib_fcache 00006 00007 #include <ostream> 00008 #include <map> 00009 #include <string> 00010 #include <cstdio> //::remove 00011 00012 #include "sys/file" 00013 00014 namespace inlib { 00015 namespace file { 00016 00017 class cache { 00018 public: 00019 virtual ~cache(){} 00020 public: 00021 virtual bool fetch(const std::string& a_what,std::string& a_file) = 0; 00022 }; 00023 00024 class base_cache : public virtual cache { 00025 public: 00026 virtual bool fetch(const std::string& a_what,std::string& a_file){ 00027 std::map<std::string,std::string>::iterator it = m_cache.find(a_what); 00028 if(it!=m_cache.end()) { //a_what in the cache. 00029 if(exists((*it).second)) { 00030 a_file = (*it).second; 00031 //std::cout << "inlib::file::base_cache::fetch :" 00032 // << " for what " << sout(a_what) 00033 // << " file in the cache : " << sout(a_file) 00034 // << std::endl; 00035 return true; 00036 } 00037 m_out << "inlib::file::base_cache::fetch :" 00038 << " WARNING : for " << sout(a_what) 00039 << ", file in the map no more here. We fetch again the file." 00040 << std::endl; 00041 m_cache.erase(it); 00042 } 00043 00044 std::string file; 00045 if(!inlib::tmpname(m_tmp_dir,"inlib_base_cache_",m_tmp_suffix,file)) { 00046 m_out << "inlib::file::base_cache::fetch :" 00047 << " can't get a tmpname." 00048 << std::endl; 00049 a_file.clear(); 00050 return false; 00051 } 00052 00053 //std::cout << "inlib::file::base_cache::fetch :" 00054 // << " for what " << sout(a_what) 00055 // << " fetch ..." 00056 // << std::endl; 00057 00058 if(!fetch_file(a_what,file)) { 00059 m_out << "inlib::file::base_cache::fetch :" 00060 << " failed to fetch " << sout(a_what) 00061 << std::endl; 00062 ::remove(file.c_str()); 00063 a_file.clear(); 00064 return false; 00065 } 00066 m_cache[a_what] = file; 00067 a_file = file; 00068 00069 //std::cout << "inlib::file::base_cache::fetch :" 00070 // << " for what " << sout(a_what) 00071 // << " fetch done." 00072 // << std::endl; 00073 00074 return true; 00075 } 00076 protected: 00077 virtual bool fetch_file(const std::string& a_what,const std::string& a_file) = 0; 00078 public: 00079 base_cache(std::ostream& a_out,bool a_verbose) 00080 :m_out(a_out) 00081 ,m_verbose(a_verbose) 00082 {} 00083 virtual ~base_cache(){clear();} 00084 protected: 00085 base_cache(const base_cache& a_from) 00086 : cache(a_from) 00087 ,m_out(a_from.m_out) 00088 ,m_verbose(a_from.m_verbose) 00089 {} 00090 base_cache& operator=(const base_cache&){return *this;} 00091 public: 00092 void set_tmp_dir(const std::string& a_dir) {m_tmp_dir = a_dir;} 00093 void set_tmp_suffix(const std::string& a_suffix) { 00094 m_tmp_suffix = a_suffix; 00095 } 00096 void clear() { 00097 std::map<std::string,std::string>::iterator it; 00098 for(it = m_cache.begin();it!=m_cache.end();++it) { 00099 ::remove((*it).second.c_str()); 00100 } 00101 m_cache.clear(); 00102 } 00103 private: 00104 //to avoid a #include "file". 00105 static std::string sout(const std::string& a_string) { 00106 return std::string("\"")+a_string+"\""; 00107 } 00108 static bool exists(const std::string& a_string) { 00109 FILE* file = ::fopen(a_string.c_str(),"rb"); 00110 if(!file) return false; 00111 ::fclose(file); 00112 return true; 00113 } 00114 protected: 00115 std::ostream& m_out; 00116 bool m_verbose; 00117 private: 00118 std::map<std::string,std::string> m_cache; 00119 std::string m_tmp_dir; 00120 std::string m_tmp_suffix; 00121 }; 00122 00123 }} 00124 00125 #endif