// name/value map // !note: the map save the point of value, so the value's life circle must more than the valuemap #ifndef BASE_UTIL_VALUEMAP_H_ #define BASE_UTIL_VALUEMAP_H_ #include "base/base_export.h" #include "base/macros.h" #include #include namespace nbase { class BASE_EXPORT ValueMap { public: // 参数的访问限制 enum { access_read = 0x01, access_write = 0x02 }; private: struct VToString { virtual ~VToString(){} virtual std::string to_string(void *v) const = 0; virtual bool to_value(const char *s, void *v) = 0; }; template struct NumberToString : public VToString { const char *format_; NumberToString(const char *format) : format_(format){} virtual std::string to_string(void *v) const { assert(v); char buf[128]; sprintf(buf, format_, *((const T *)v)); return std::string((const char *)buf); } virtual bool to_value(const char *s, void *v) { return sscanf(s, format_, v) == 1; } }; struct StringToString : public VToString { virtual std::string to_string(void *v) const { assert(v); return *((const std::string *)v); } virtual bool to_value(const char *s, void *v) { *((std::string *)v) = s; return true; } }; public: enum Type { t_char = 0 , t_float, t_double, t_string, t_pointer, t_i8, t_u8, t_i16, t_u16, t_i32, t_u32, t_i64, t_u64, t_o8, t_o16, t_o32, t_o64, t_h8, t_h16, t_h32, t_h64, types_num }; private: struct Item { uint8_t access_; // access_read | access_write Type type_; void *ptr_; Item() : access_(access_read), type_(t_pointer), ptr_(0){} Item(Type t, void *v, uint8_t a) : access_(a), type_(t), ptr_(v) { assert(ptr_); } Item(const Item & src) { access_ = src.access_; type_ = src.type_; ptr_ = src.ptr_; } Item& operator = (const Item &src) { access_ = src.access_; type_ = src.type_; ptr_ = src.ptr_; return *this; } }; typedef std::map Map; VToString *formats_[types_num]; Map items_; public: ValueMap() { // initialize format map formats_[t_char] = new NumberToString(CHAR_FORMAT); formats_[t_float] = new NumberToString(FLOAT_FORMAT); formats_[t_double] = new NumberToString(DOUBLE_FORMAT); formats_[t_string] = new StringToString; formats_[t_pointer] = new NumberToString(POINTER_FORMAT); formats_[t_i8] = new NumberToString(INT8_FORMAT); formats_[t_u8] = new NumberToString(UINT8_FORMAT); formats_[t_i16] = new NumberToString(INT16_FORMAT); formats_[t_u16] = new NumberToString(UINT16_FORMAT); formats_[t_i32] = new NumberToString(INT32_FORMAT); formats_[t_u32] = new NumberToString(UINT32_FORMAT); formats_[t_i64] = new NumberToString(INT64_FORMAT); formats_[t_u64] = new NumberToString(UINT64_FORMAT); formats_[t_o8] = new NumberToString(OCT8_FORMAT); formats_[t_o16] = new NumberToString(OCT16_FORMAT); formats_[t_o32] = new NumberToString(OCT32_FORMAT); formats_[t_o64] = new NumberToString(OCT64_FORMAT); formats_[t_h8] = new NumberToString(HEX8_FORMAT); formats_[t_h16] = new NumberToString(HEX16_FORMAT); formats_[t_h32] = new NumberToString(HEX32_FORMAT); formats_[t_h64] = new NumberToString(HEX64_FORMAT); } ~ValueMap() { items_.clear(); for(size_t i = 0; i < types_num; ++i) delete formats_[i]; } void clear() { items_.clear(); } void bind(const std::string &name, void *ptr, Type type, uint8_t access = access_read) { assert(ptr); assert(type >= t_char && type < types_num); items_[name] = Item(type, ptr, access); } void bind(const char *name, void *ptr, Type type, uint8_t access = access_read) { bind(std::string(name), ptr, type, access); } void unbind(const std::string &name) { Map::iterator it=items_.find(name); if (it != items_.end()) items_.erase(it); } void unbind(const char *name) { unbind(std::string(name)); } std::string get(const std::string &name) const { Map::const_iterator it=items_.find(name); if (it==items_.end()) return std::string(""); const Item &i = it->second; if (i.access_ && access_read) return formats_[i.type_]->to_string(i.ptr_); else return std::string(""); } std::string get(const char *name) const { return get(std::string(name)); } bool set(const std::string &name, const char *value) { assert(value); Map::iterator it = items_.find(name); if (it==items_.end()) return false; Item &i = it->second; // forbid set pointer or string if (i.type_ == t_string || i.type_ == t_pointer) return false; if (!(i.access_ & access_write)) return false; return formats_[i.type_]->to_value(value,i.ptr_); } bool set(const char *name, const char *value) { return set(std::string(name), value) ; } void enumerate(std::vector &names) const { Map::const_iterator it=items_.begin(); for (; it != items_.end(); ++it) names.push_back(it->first) ; } }; } // namespace nbase #endif // BASE_UTIL_VALUEMAP_H_