UGDK
|
00001 #ifndef UGDK_BASE_GENERICCONTAINER_H_ 00002 #define UGDK_BASE_GENERICCONTAINER_H_ 00003 00004 #include <string> 00005 #include <map> 00006 #include <ugdk/base/resourcecontainer.h> 00007 00008 #ifdef DEBUG 00009 #include <cstdio> 00010 #include <typeinfo> 00011 #define TOSTRING(X) typeid(X).name() 00012 #endif 00013 00014 namespace ugdk { 00015 namespace base { 00016 00017 template <class T, class Loader_T = T (*) (const std::string&)> 00018 class GenericContainer : public virtual ResourceContainer<T> { 00019 private: 00020 typedef std::map<std::string, T> DataMap; 00021 typedef typename DataMap::iterator DataIterator; 00022 DataMap database_; 00023 Loader_T loader_; 00024 00025 public: 00026 GenericContainer() : loader_(T::LoadFromFile) {} 00027 GenericContainer(Loader_T loader) : loader_(loader) {} 00028 virtual ~GenericContainer() {} 00029 00030 void Insert(const std::string& tag, T val) { 00031 DataIterator it = database_.find(tag); 00032 if(it == database_.end()) { 00033 database_[tag] = val; 00034 } else { 00035 #ifdef DEBUG 00036 fprintf(stderr, "UGDK::GenericContainer<%s> Error - Tag '%s' already exists.\n", TOSTRING(T), tag.c_str()); 00037 #endif 00038 } 00039 } 00040 00041 void Replace(const std::string& tag, T val) { 00042 database_[tag] = val; 00043 } 00044 00045 bool Exists(const std::string& tag) const { 00046 return database_.count(tag) > 0; 00047 } 00048 00049 T& Find(const std::string& tag) { 00050 return database_[tag]; 00051 } 00052 00054 virtual T& Load(const std::string& filepath, const std::string& tag) { 00055 if(!Exists(tag)) Insert(tag, loader_(filepath)); 00056 return Find(tag); 00057 } 00058 }; 00059 00060 template <class T> 00061 class GenericContainer<T*, T* (*) (const std::string&)> : public virtual ResourceContainer<T*> { 00062 private: 00063 typedef std::map<std::string, T*> DataMap; 00064 typedef typename DataMap::iterator DataIterator; 00065 typedef T* (*Loader_T) (const std::string&); 00066 00067 DataMap database_; 00068 Loader_T loader_; 00069 00070 public: 00071 GenericContainer() : loader_(T::LoadFromFile) {} 00072 GenericContainer(Loader_T loader) : loader_(loader) {} 00073 virtual ~GenericContainer() { 00074 DataIterator it; 00075 for(it = database_.begin(); it != database_.end(); ++it) { 00076 delete it->second; 00077 } 00078 } 00079 00080 void Insert(const std::string& tag, T* val) { 00081 DataIterator it = database_.find(tag); 00082 if(it == database_.end() || it->second == NULL) { 00083 database_[tag] = val; 00084 } else { 00085 #ifdef DEBUG 00086 fprintf(stderr, "UGDK::GenericContainer<%s> Error - Tag '%s' already exists.\n", TOSTRING(T), tag.c_str()); 00087 #endif 00088 } 00089 } 00090 00091 void Replace(const std::string& tag, T* val) { 00092 DataIterator it = database_.find(tag); 00093 if(it == database_.end() || it->second == NULL) { 00094 database_[tag] = val; 00095 } else { 00096 delete it->second; 00097 it->second = val; 00098 } 00099 } 00100 00101 bool Exists(const std::string& tag) const { 00102 typename DataMap::const_iterator it = database_.find(tag); 00103 return (it != database_.end() && it->second); 00104 } 00105 00106 T* Find(const std::string& tag) { 00107 return database_[tag]; 00108 } 00109 00111 virtual T* Load(const std::string& filepath, const std::string& tag) { 00112 if(Exists(tag)) return Find(tag); 00113 T* obj = loader_(filepath); 00114 Insert(tag, obj); 00115 return obj; 00116 } 00117 }; 00118 00119 } // namespace base 00120 } // namespace ugdk 00121 00122 #endif // UGDK_BASE_GENERICCONTAINER_H_ 00123