配置文件的读取重复代码极多,且容易漏掉、出错,如下一段配置信息读取代码,可以简化编程。
主体类定义:
#ifndef _CONFIG_CONTAINER_H_ #define _CONFIG_CONTAINER_H_ #include <stdio.h> #include <stdlib.h> #include <memory.h> typedef union type_mask_t { struct { bool is_int_ : 1; bool is_enum_ : 1; bool is_float_ : 1; bool is_signed_ : 1; bool is_class_ : 1; }; unsigned int int_value; }type_mask; template<typename T> inline unsigned int _get_type_mask() { return 0; } template<> inline unsigned int _get_type_mask<unsigned char>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_int_ = 1; type_mask_int.is_signed_ = 0; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<unsigned short>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_int_ = 1; type_mask_int.is_signed_ = 0; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<unsigned int>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_int_ = 1; type_mask_int.is_signed_ = 0; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<char>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_int_ = 1; type_mask_int.is_signed_ = 1; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<short>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_int_ = 1; type_mask_int.is_signed_ = 1; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<int>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_int_ = 1; type_mask_int.is_signed_ = 1; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<float>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_float_ = 1; return type_mask_int.int_value; } template<> inline unsigned int _get_type_mask<double>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_float_ = 1; return type_mask_int.int_value; } template<class TBase> class XConfigContainer { public: typedef void* (*def_func)(void* config_pesist, void* user_param); typedef bool (*deep_copy)(void* dest, const void* src, unsigned int size); typedef struct tagConfigItem { unsigned int offset; unsigned int size; unsigned int type_mask_; const char* itemname; def_func default_func; deep_copy deep_copy_func; }ConfigItem; typedef struct tagConfigItemLink { ConfigItem cfg_item; struct tagConfigItemLink* lpnext; }ConfigItemLink; protected: static inline void _make_array_config_item_link(unsigned int count, ConfigItemLink* lpItem) { for(unsigned int idx = 0; idx < count - 1; idx++) { lpItem[idx].lpnext = &lpItem[idx+1]; } } public: XConfigContainer() {} ~XConfigContainer() {} unsigned int init(void* user_param); unsigned int load(void* config_pesist, void* user_param); unsigned int load_detla(void* config_pesist, void* user_param); unsigned int save(void* config_pesist, void* user_param) const; unsigned int save_to_struct(void* config_struct, void* user_param) const; }; #define BEGIN_CONFIG_CONTAINER(class_name, struct_name) class class_name : public struct_name, public XConfigContainer<class_name> { public: class_name () { memset(&first_item_, 0, sizeof( class_name ) - (unsigned int)(size_t)&((( class_name *)0)-> first_item_ )); }; ~##class_name() {} private: unsigned int first_item_; typedef class_name thisClass; public: static unsigned int x_config_item_count; static unsigned int GetConfigItem(const ConfigItemLink** lppItemLink) { static bool is_initiated = false; static ConfigItemLink x_config_item_link[] = { #define CONFIG_ITEM(type_name, item_name, get_default_func, copy_func) { { (unsigned int)(size_t)&(((thisClass *)0)-> item_name ), sizeof(type_name), _get_type_mask< type_name >(), #item_name , get_default_func, copy_func }, 0}, #define END_CONFIG_CONTAINER() { {0, 0, 0, 0, 0, 0}, 0} }; if (!is_initiated) {is_initiated = true; _make_array_config_item_link(sizeof(x_config_item_link)/ sizeof (ConfigItemLink) - 1, x_config_item_link);}; if (0 != lppItemLink) *lppItemLink = x_config_item_link; return sizeof(x_config_item_link)/ sizeof (ConfigItemLink) - 1; }; }; #define CONFIG_CONTAINER_IMPL(class_name) unsigned int class_name :: x_config_item_count = class_name :: GetConfigItem(0); template<typename T, int value> void* get_default_func(void* config_pesist = NULL, void* user_param =NULL) { union inn_stru{ void* void_value; T real_value; }; inn_stru inn_val; inn_val.real_value = (T)value; return (void*)inn_val.void_value; } #define DEFALUT_VALUE_DECL(type_name, value) &get_default_func<type_name, value> #define DECLAIR_FLOAT_DEF_VALUE_FUNC(type_name, func_name, value) static void* func_name(void*, void*) { union inn_stru{ void* void_value; type_name real_value; }; inn_stru inn_val; inn_val.real_value = (type_name)value; return (void*)inn_val.void_value; } template<class T1, class T2> T1 union_cast(T2 val){ union value_type{ T2 t2_val1; T1 t1_val2; } val1; val1.t2_val1 = val; return val1.t1_val2; } #endif
使用办法:
1.预先定义好的配置信息结构体
typedef struct rect_t{ unsigned short x; unsigned short y; unsigned short width; unsigned short height; }rect_t; typedef struct music_player_config{ unsigned short version; unsigned short aaa; float bbb; rect_t btnOkRect; }music_player_config;
2.声明相应的结构信息说明:
#ifndef ALGOCONFIG_H #define ALGOCONFIG_H #include "ConfigContainer.h" BEGIN_CONFIG_CONTAINER(Rect_T, rect_t) CONFIG_ITEM(unsigned short, x, DEFALUT_VALUE_DECL(unsigned short, 0), NULL) CONFIG_ITEM(unsigned short, y, DEFALUT_VALUE_DECL(unsigned short, 0), NULL) CONFIG_ITEM(unsigned short, width, DEFALUT_VALUE_DECL(unsigned short, 0), NULL) CONFIG_ITEM(unsigned short, height, DEFALUT_VALUE_DECL(unsigned short, 0), NULL) END_CONFIG_CONTAINER() void* _load_rect_func(void* config_pesist, void* user_param); template<> inline unsigned int _get_type_mask<struct rect_t>() { type_mask type_mask_int; type_mask_int.int_value = 0; type_mask_int.is_class_ = 1; return type_mask_int.int_value; } DECLAIR_FLOAT_DEF_VALUE_FUNC(float, _get_bbb_def_value, 0.5f); BEGIN_CONFIG_CONTAINER(PlayerConfig, music_player_config) CONFIG_ITEM(unsigned short, version, DEFALUT_VALUE_DECL(unsigned short, 12345), NULL) CONFIG_ITEM(unsigned short, aaa, DEFALUT_VALUE_DECL(unsigned short, 0), NULL) CONFIG_ITEM(float, bbb, &_get_bbb_def_value, NULL) CONFIG_ITEM(rect_t, btnOkRect, &_load_rect_func, NULL) END_CONFIG_CONTAINER() #endif // ALGOCONFIG_H
3.实现结构信息说明:
#include "PlayerConfig.h" CONFIG_CONTAINER_IMPL(Rect_T); CONFIG_CONTAINER_IMPL(PlayerConfig);
4.使用Json,如下的读取代码:
#include "cJSON.h"
#include "PlayerConfig.h"
void* _load_rect_func(void* config_pesist, void* user_param) { static Rect_T stRect; stRect.load(config_pesist, user_param); return &stRect; } template<class T> void copy_signed_value(unsigned char* dest, T* src, unsigned int size){ switch (size) { case sizeof(unsigned char): *(char*)dest = *(char*)src; return; case sizeof(unsigned short): *(short*)dest = *(short*)src; return; case sizeof(unsigned int): *(int*)dest = *(int*)src; return; } // 其他情况,使用memcpy memcpy(dest, src, size); } template<class T> void copy_unsigned_value(unsigned char* dest, T* src, unsigned int size){ switch (size) { case sizeof(unsigned char): *(unsigned char*)dest = *(unsigned char*)src; return; case sizeof(unsigned short): *(unsigned short*)dest = *(unsigned short*)src; return; case sizeof(unsigned int): *(unsigned int*)dest = *(unsigned int*)src; return; } // 其他情况,使用memcpy memcpy(dest, src, size); } template<class T> void copy_float_value(unsigned char* dest, T* src, unsigned int size){ *(float*)dest = *(float*)src; } template<class TBase> unsigned int XConfigContainer<TBase>::init(void* user_param) { // 依次读取配置项 type_mask temp_type_mask; const ConfigItemLink* lpItem = NULL; TBase::GetConfigItem(&lpItem); while(lpItem != NULL) { temp_type_mask.int_value = lpItem->cfg_item.type_mask_; // 保存在内部变量中:如果是整数 def_func def_func_ = lpItem->cfg_item.default_func; if (temp_type_mask.is_int_) { if (temp_type_mask.is_signed_) { //signed int def_val = (signed int)((*def_func_)()); signed int signed_val = union_cast<signed int>((*def_func_)(NULL, user_param)); copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &signed_val, lpItem->cfg_item.size); } else { //unsigned int def_unsigned_val = (unsigned int)((*def_func_)()); unsigned int unsigned_val = union_cast<unsigned int>((*def_func_)(NULL, user_param)); copy_unsigned_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &unsigned_val, lpItem->cfg_item.size); } } else if (temp_type_mask.is_float_){ // 浮点数 float float_val = union_cast<float>((*def_func_)(NULL, user_param)); copy_float_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &float_val, lpItem->cfg_item.size); } else if (temp_type_mask.is_class_){ // 如果是类,则需要递归进去 void* def_val = (*def_func_)(NULL, user_param); copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), def_val, lpItem->cfg_item.size); } else { // 其他,默认是字符串 char* strValue = (char*)((*def_func_)(NULL, user_param)); // 如果有深度拷贝,则使用深拷贝函数 if (lpItem->cfg_item.deep_copy_func) { (*(lpItem->cfg_item.deep_copy_func))(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strValue, lpItem->cfg_item.size); } else { copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strValue, lpItem->cfg_item.size); } } lpItem = lpItem->lpnext; } return 0; } template<class TBase> unsigned int XConfigContainer<TBase>::load(void* config_pesist, void* user_param) { // 内部对象 cJSON * c_json = (cJSON *)(config_pesist); if (0 == c_json) { // 为空,则调用init接口 init(user_param); return 1; } // 依次读取配置项 type_mask temp_type_mask; cJSON * c_item = NULL; const ConfigItemLink* lpItem = NULL; TBase::GetConfigItem(&lpItem); while(lpItem != NULL) { // 从json数据中读取到内容 c_item = cJSON_GetObjectItem(c_json, lpItem->cfg_item.itemname); temp_type_mask.int_value = lpItem->cfg_item.type_mask_; if (NULL == c_item){ // 保存在内部变量中:如果是整数 def_func def_func_ = lpItem->cfg_item.default_func; if (temp_type_mask.is_int_) { if (temp_type_mask.is_signed_) { signed int def_val = (signed int)((*def_func_)(config_pesist, user_param)); copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size); } else { unsigned int def_val = (unsigned int)((*def_func_)(config_pesist, user_param)); copy_unsigned_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size); } } else if (temp_type_mask.is_float_){ // 浮点数 float def_val = union_cast<float>((*def_func_)(config_pesist, user_param)); copy_float_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size); } else if (temp_type_mask.is_class_){ // 如果是类,则需要递归进去 void* def_val = (*def_func_)(c_item, user_param); copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), def_val, lpItem->cfg_item.size); } else { // 其他,默认是字符串 char* strDef = (char*)((*def_func_)(config_pesist, user_param)); // 如果有深度拷贝,则使用深拷贝函数 if (lpItem->cfg_item.deep_copy_func) { (*(lpItem->cfg_item.deep_copy_func))(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size); } else { copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size); } } } else { if (temp_type_mask.is_int_) { if (temp_type_mask.is_signed_) { signed int def_val = c_item->valueint; copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size); } else { unsigned int def_val = c_item->valueint; copy_unsigned_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size); } } else if (temp_type_mask.is_float_){ // 浮点数 float def_val = (float)(c_item->valuedouble); copy_float_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size); } else if (temp_type_mask.is_class_){ // 如果是类,则需要递归进去 void* def_val = (*(lpItem->cfg_item.default_func))(c_item, user_param); copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), def_val, lpItem->cfg_item.size); } else { // 其他,默认是字符串 char* strDef = c_item->valuestring; // 如果有深度拷贝,则使用深拷贝函数 if (lpItem->cfg_item.deep_copy_func) { (*(lpItem->cfg_item.deep_copy_func))(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size); } else { copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size); } } } lpItem = lpItem->lpnext; } return 0; }
5.使用示例:
#include "stdafx.h" #include "ConfigContainer_json.h" char json_buf[] = "{"version": 123, "aaa": 23, "bbb": 0.6, "btnOkRect" : {"x": 1, "y": 2, "width": 3, "height": 4} }"; int _tmain(int argc, _TCHAR* argv[]) { PlayerConfig stConfig; cJSON * root = NULL; // 构建json对象 root = cJSON_Parse(json_buf); stConfig.load((void*)root, 0); cJSON_Delete(root); return 0; }