支持多重结构的配置信息读取代码,基于VS2008
配置文件的读取重复代码极多,且容易漏掉、出错,如下一段配置信息读取代码,可以简化编程。
主体类定义:
#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;
};
unsignedintint_value;
}type_mask;
template<typename T>inline unsignedint_get_type_mask()
{return 0;
}
template<>inline unsignedint _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;returntype_mask_int.int_value;
}
template<>inline unsignedint _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;returntype_mask_int.int_value;
}
template<>inline unsignedint _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;returntype_mask_int.int_value;
}
template<>inline unsignedint _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;returntype_mask_int.int_value;
}
template<>inline unsignedint _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;returntype_mask_int.int_value;
}
template<>inline unsignedint _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;returntype_mask_int.int_value;
}
template<>inline unsignedint _get_type_mask<float>()
{
type_mask type_mask_int;
type_mask_int.int_value= 0;
type_mask_int.is_float_= 1;returntype_mask_int.int_value;
}
template<>inline unsignedint _get_type_mask<double>()
{
type_mask type_mask_int;
type_mask_int.int_value= 0;
type_mask_int.is_float_= 1;returntype_mask_int.int_value;
}
template<class TBase> classXConfigContainer
{public:
typedefvoid* (*def_func)(void* config_pesist, void*user_param);
typedefbool (*deep_copy)(void* dest, const void* src, unsigned intsize);
typedefstructtagConfigItem
{
unsignedintoffset;
unsignedintsize;
unsignedinttype_mask_;const char*itemname;
def_func default_func;
deep_copy deep_copy_func;
}ConfigItem;
typedefstructtagConfigItemLink
{
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() {}
unsignedint init(void*user_param);
unsignedint load(void* config_pesist, void*user_param);
unsignedint load_detla(void* config_pesist, void*user_param);
unsignedint save(void* config_pesist, void* user_param) const;
unsignedint 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: \
unsignedintfirst_item_; \
typedef class_name thisClass; \public: \static unsigned intx_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) \{ { (unsignedint)(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;returnval1.t1_val2;
}#endif
使用办法:
1.预先定义好的配置信息结构体
typedef structrect_t{
unsignedshortx;
unsignedshorty;
unsignedshortwidth;
unsignedshortheight;
}rect_t;
typedefstructmusic_player_config{
unsignedshortversion;
unsignedshortaaa;floatbbb;
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(unsignedshort, x, DEFALUT_VALUE_DECL(unsigned short, 0), NULL)
CONFIG_ITEM(unsignedshort, y, DEFALUT_VALUE_DECL(unsigned short, 0), NULL)
CONFIG_ITEM(unsignedshort, width, DEFALUT_VALUE_DECL(unsigned short, 0), NULL)
CONFIG_ITEM(unsignedshort, height, DEFALUT_VALUE_DECL(unsigned short, 0), NULL)
END_CONFIG_CONTAINER()void* _load_rect_func(void* config_pesist, void*user_param);
template<>inline unsignedint _get_type_mask<struct rect_t>()
{
type_mask type_mask_int;
type_mask_int.int_value= 0;
type_mask_int.is_class_= 1;returntype_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(unsignedshort, version, DEFALUT_VALUE_DECL(unsigned short, 12345), NULL)
CONFIG_ITEM(unsignedshort, 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)
{staticRect_T stRect;
stRect.load(config_pesist, user_param);return &stRect;
}
template<class T> void copy_signed_value(unsigned char* dest, T* src, unsigned intsize){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 intsize){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 intsize){*(float*)dest = *(float*)src;
}
template<class TBase>unsignedint 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>unsignedint 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_) {
signedint 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{
unsignedint 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_) {
signedint def_val = c_item->valueint;
copy_signed_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
}else{
unsignedint 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;
}