aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/oo/ObjSelector.h
diff options
context:
space:
mode:
Diffstat (limited to 'meowpp/oo/ObjSelector.h')
-rw-r--r--meowpp/oo/ObjSelector.h245
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__