diff options
Diffstat (limited to 'meowpp/oo/ObjSelector.h')
-rw-r--r-- | meowpp/oo/ObjSelector.h | 245 |
1 files changed, 198 insertions, 47 deletions
diff --git a/meowpp/oo/ObjSelector.h b/meowpp/oo/ObjSelector.h index 58debcb..7664a11 100644 --- a/meowpp/oo/ObjSelector.h +++ b/meowpp/oo/ObjSelector.h @@ -3,60 +3,211 @@ #include "ObjBase.h" +#include <utility> +#include <vector> +#include <string> +#include <map> + #include <cstdlib> +#include <cstdio> namespace meow{ - template<size_t id> - class ObjSelector{ - private: - typedef std::map <std::string, ObjBase*> Funcs; - typedef std::vector<std::string > Types; - // - static Funcs& funcs(){ - static Funcs f; - return f; - } - // - std::string name; - ObjBase* ptr; - public: - ObjSelector( ObjBase* o){ add(name = o->type(), ptr = o); } - ObjSelector(std::string n, ObjBase* o){ add(name = n , ptr = o); } - ~ObjSelector(){ del(name); } - // - static void add(std::string n, ObjBase* b){ - del(n); - funcs()[n] = b; - } - static void del(std::string s){ - if(funcs().find(s) != funcs().end()){ - delete funcs()[s]; - funcs().erase(s); - } - } - static ObjBase const* access(std::string s){ - if(funcs().find(s) == funcs().end()) return NULL; - return funcs()[s]; + +/*! + * @brief 利用register的概念, 達到runtime用string選擇要new的class + * + * @author cathook + */ +template<size_t id> //!< 讓程式可以有不只一個 \c ObjSelector +class ObjSelector { +private: + struct Info { + ObjSelector* parent_; + ObjBase const* pointer_; + bool autoDelete_; + // + Info(ObjSelector* parent, + ObjBase const* ptr, + bool autoDelete) { + parent_ = parent; + pointer_ = ptr; + autoDelete_ = autoDelete; + } + ~Info() { + if (autoDelete_) { + delete pointer_; } - static ObjBase* get(std::string s){ - if(funcs().find(s) == funcs().end() || funcs()[s] == NULL) - return NULL; - return funcs()[s]->create(); + if (parent_ != NULL) { + parent_->me_.second = NULL; } - static std::string find(ObjBase* o){ - for(Funcs::iterator it = funcs().begin(); it != funcs().end(); it++) - if(it->second != NULL && it->second->type() == o->type()){ - return it->first; - } - return std::string(); + } + }; + friend struct Info; + + typedef typename std::map<std::string, Info*> Funcs; + typedef typename std::map<std::string, Info*>::iterator FuncsIterator; + + static Funcs& funcs() { + static Funcs f; + return f; + } + static Info* add(std::string name, + ObjSelector* parent, + ObjBase* ptr, + bool autoDelete) { + Info* info = new Info(parent, ptr, autoDelete); + del(name); + funcs()[name] = info; + return info; + } + + std::pair<std::string, Info*> me_; +public: + /*! + * @brief 新增(註冊) 一個Class (必須要繼承自 \c ObjBase) 並且給定其Name + */ + static void add(std::string name, ObjBase* obj, bool autoDelete) { + add(name, NULL, obj, autoDelete); + } + + /*! + * @brief 新增(註冊) 一個Class (必須要繼承自 \c ObjBase) 並且默認type為name + */ + static void add(ObjBase* obj, bool autoDelete) { + add(obj->type(), NULL, obj, autoDelete); + } + + /*! + * @brief 依照name刪除之前註冊過得Class + */ + static void del(std::string name) { + if (funcs().find(name) != funcs().end()) { + delete funcs()[name]; + funcs().erase(name); + } + } + + /*! + * @brief 取得之前註冊過得Class + */ + static ObjBase const* get(std::string name) { + if (funcs().find(name) == funcs().end()) return NULL; + return funcs()[name]->pointer_; + } + + /*! + * @brief 回傳一個之前註冊過得Class new出來的實體 + */ + static ObjBase* create(std::string name) { + ObjBase const* ptr = get(name); + if(ptr == NULL) return NULL; + return ptr->create(); + } + + /*! + * @brief 利用type檢查是否有註冊過同種類的Class + */ + static bool exist(ObjBase* obj) { + for (FuncsIterator it = funcs().begin(); it != funcs().end(); it++) { + if (it->second->pointer_ == obj || + (it->second->pointer_ != NULL && + it->second->pointer_->type() == obj->type())) { + return true; } - static Types lst(){ - Types ret; - for(Funcs::iterator it = funcs().begin(); it != funcs().end(); it++) - ret.push_back(it->first); - return ret; + } + return false; + } + + /*! + * @brief 利用type尋找name + */ + static std::string name(ObjBase* obj) { + for (FuncsIterator it = funcs().begin(); it != funcs().end(); it++) { + if (it->second->pointer_ == obj || + (it->second->pointer_ != NULL && + it->second->pointer_->type() == obj->type())) { + return it->first; } - }; + } + return std::string(); + } + + /*! + * @brief 回傳所有註冊過的name + */ + static std::vector<std::string> names() { + std::vector<std::string> ret; + for (FuncsIterator it = funcs().begin(); it != funcs().end(); it++) + ret.push_back(it->first); + return ret; + } + + /*! + * @brief 宣告一個ObjSelector實體, 並且註冊一個 ObjBase + */ + ObjSelector(std::string name, ObjBase* obj, bool autoDelete) { + me_.first = name; + me_.second = add(me_.first, this, obj, autoDelete); + } + + /*! + * @brief 宣告一個ObjSelector實體, 並且註冊一個 ObjBase + */ + ObjSelector(ObjBase* obj, bool autoDelete) { + me_.first = obj->type(); + me_.second = add(me_.first, this, obj, autoDelete); + } + + //! 解構子 + ~ObjSelector() { + if (me_.second != NULL) { + del(me_.first); + } + } + + /*! + * @brief 將一個物件寫到檔案裡(該物件必須要有註冊過) + */ + static bool write(FILE* f, bool binary, ObjBase* obj, unsigned int fg) { + if (!exist(obj)) return false; + char const* nme = name(obj).c_str(); + size_t len = strlen(nme); + if (binary) { + if (fwrite(&len, sizeof(size_t ), 1, f) < 1) return false; + if (fwrite(nme , sizeof(char ), len, f) < len) return false; + if (fwrite(&fg , sizeof(unsigned int), 1, f) < 1) return false; + } else { + if (fprintf(f, "%s %u\n", nme, fg) < 2) return false; + } + return obj->write(f, binary, fg); + } + + /*! + * @brief 從檔案中讀取一個物件(該物件必須要有註冊過) + */ + static ObjBase* read(FILE* f, bool binary) { + char name[2048]; + size_t len; + unsigned int fg; + if (binary) { + if (fread(&len, sizeof(size_t ), 1, f) < 1) return NULL; + if (fread(name, sizeof(char ), len, f) < len) return NULL; + if (fread(&fg , sizeof(unsigned int), 1, f) < 1) return NULL; + name[len] = '\0'; + } else { + if (fscanf(f, "%s %u", name, &fg) < 2) return NULL; + } + ObjBase* ret = create(std::string(name)); + if (ret != NULL && ret->read(f, binary, fg) == false) { + delete ret; + ret = NULL; + } + return ret; + } +}; + +static const size_t kGlobalSeletorID = 0; + } #endif // oo_ObjSelector_H__ |