• 支持多重结构的配置信息读取代码,基于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;
    }
  • 相关阅读:
    不使用SpringBoot如何将原生Feign集成到Spring中来简化http调用
    干货!从Tomcat执行流程了解jsp是如何被解析的,错误提示是哪里生成的。
    对TCP三次握手四次分手还不清楚的速度进,超简单解析,明白了就很好记!
    SpringCache与redis集成,优雅的缓存解决方案
    高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)
    Hibernate级联之一对多和inverse解析
    Spring的面向切面
    归并排序:步骤讲解与代码实现
    关于操作系统中多个fork()会创建几个进程的理解
    win-sudo插件解决Git bash 执行脚本报错问题 bash: sudo: command not found
  • 原文地址:https://www.cnblogs.com/eaglexmw/p/14784817.html
Copyright © 2020-2023  润新知