00001 #ifndef PERSISTENT_D_H 00002 #define PERSISTENT_D_H 00003 00004 // written by Thorsten Reinecke (reinecke@thorstenreinecke.de) 00005 // last change: 2004-10-06 00006 00013 extern "C" 00014 { 00015 #include <unistd.h> 00016 } 00017 00018 #include <map> 00019 #include <string> 00020 #include <iostream> 00021 #include <fstream> 00022 00024 class CPersistentDataInterface 00025 { 00026 public: 00027 virtual void Load(std::istream &is) = 0; 00028 virtual void Save(std::ostream &os) const = 0; 00029 virtual ~CPersistentDataInterface() = 0; 00030 }; 00031 CPersistentDataInterface::~CPersistentDataInterface() { } 00032 00033 // gcc-4.0 (experimental) issued warnings about missing virtual destructors. 00034 // Although we don't need destructors for our implementation, we *do* define 00035 // a virtual destructor in the interface. That's because if the interface 00036 // doesn't declare a virtual destructor (and also defines a default 00037 // destructor), then no destructor will be called for the dynamically 00038 // constructed items inside CPersistentDataCollection! 00039 00040 00042 template <typename T> 00043 class CPersistentData : protected CPersistentDataInterface 00044 { 00045 protected: 00046 T &data; // reference of the variable to load/save 00047 CPersistentData(T &mydata) : data(mydata) { } 00048 virtual ~CPersistentData() { } 00049 virtual void Load(std::istream &is) 00050 { 00051 is >> data; 00052 #ifdef VERBOSE 00053 cout << data << endl; 00054 #endif 00055 } 00056 virtual void Save(std::ostream &os) const { os << data << std::endl; } 00057 friend class CPersistentDataCollection; 00058 }; 00059 00060 00078 class CPersistentDataCollection : private ForbidAssignment 00079 { 00080 protected: 00081 typedef std::map<std::string,CPersistentDataInterface*> TCollection; 00082 const std::string filename; 00083 TCollection collection; 00084 00085 public: 00086 00088 void ClearStream() 00089 { 00090 // remove stream 00091 unlink(filename.c_str()); 00092 } 00093 00095 void ClearCollection() 00096 { 00097 while (!collection.empty()) 00098 { 00099 delete collection.begin()->second; 00100 collection.erase(collection.begin()); 00101 } 00102 } 00103 00105 explicit CPersistentDataCollection(const std::string myFilename) 00106 : filename(myFilename) { } 00107 00108 ~CPersistentDataCollection() { ClearCollection(); } 00109 00111 template<typename T> inline void RegisterVar(const std::string ID, T &data) 00112 { 00113 if (collection.find(ID)!=collection.end()) // check for presence 00114 { 00115 // was already present! 00116 exit(1); // for debugging (we could throw an exception instead) 00117 } 00118 else collection[ID] = new CPersistentData<T>(data); 00119 } 00120 00122 template<typename T> inline void UnregisterVar(const std::string ID) 00123 { 00124 if (collection.find(ID)==collection.end()) // check for presence 00125 { 00126 // wasn't present! 00127 exit(1); // for debugging (we could throw an exception instead) 00128 } 00129 else 00130 { 00131 delete collection[ID]; 00132 collection.erase(ID); 00133 } 00134 } 00135 00137 void Load() 00138 { 00139 std::ifstream istr(filename.c_str()); 00140 while (istr) 00141 { 00142 while (isspace(istr.peek())) istr.get(); 00143 00144 // it seems that gcc-3.2.3 has some problems detecting eof, 00145 // I hope this helps... 00146 istr.get(); 00147 if (istr.eof()) break; 00148 istr.unget(); 00149 00150 std::string ID; 00151 istr >> ID; 00152 if (collection.find(ID)==collection.end()) // check for presence 00153 { 00154 MARK; 00155 cout << "ID " << ID << " not found!" << endl; 00156 exit(1); // isn't present! 00157 } 00158 else 00159 { 00160 #ifdef VERBOSE 00161 cout << "Loading ID " << ID << "= "; 00162 #endif 00163 collection[ID]->Load(istr); 00164 } 00165 } 00166 istr.close(); 00167 } 00168 00170 void Save() 00171 { 00172 std::ofstream ostr(filename.c_str(),std::ios::out|std::ios::trunc); 00173 for (TCollection::const_iterator p=collection.begin(); p!=collection.end(); ++p) 00174 { 00175 ostr << p->first << " "; 00176 p->second->Save(ostr); 00177 } 00178 ostr.close(); 00179 } 00180 00181 }; 00182 00183 #endif /* PERSISTENT_D_H */