支持多重结构的配置信息读取代码,基于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;
    };
    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;
}
原文地址:https://www.cnblogs.com/eaglexmw/p/14784817.html