配置信息读取代码(VS2012编译通过,使用了C++11特性)

配置文件的读取重复代码极多,且容易漏掉、出错,如下一段配置信息读取代码,可以简化编程。

主体类定义:

#ifndef _CONFIG_CONTAINER_H_
#define _CONFIG_CONTAINER_H_

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <vector>
#include <string>

#include <type_traits>

template<unsigned int> struct UID{};

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<class TBase>
class XConfigContainer
{
public:
    typedef void* (*def_func)();
    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;

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)  \
class class_name : public XConfigContainer<class_name> \
{ \
private:    \
    unsigned int first_item_;   \
public: \
    class_name() { \
        memset(&first_item_, 0, sizeof( class_name ) - (unsigned int)(size_t)&(((class_name *)0)-> first_item_ )); \
    }; \
    ~class_name() {} \
    static unsigned int x_config_item_count; \
    static const ConfigItemLink* GetConfigItem(); \
public: \
    template<int N> struct ConfigItemSeq{  static ConfigItemLink config_item_seq; }; \
private: \
    typedef class_name thisClass; \
    enum {__property_first_idx = __COUNTER__}; \

#define CONFIG_ITEM(type_name, item_name, get_default_func, copy_func) \
public: \
    typedef type_name property_##item_name##_t; \
private: \
    enum {__property_##item_name##_idx = __COUNTER__ - __property_first_idx - 1}; \
    static unsigned int get_offset(UID<__property_##item_name##_idx>) {return (unsigned int)(size_t)&(((thisClass *)0)-> x_##item_name##_ );}; \
    static unsigned int get_size(UID<__property_##item_name##_idx>) {return sizeof(property_##item_name##_t); }; \
    static unsigned int get_type_mask(UID<__property_##item_name##_idx>) {static type_mask val = \
                                                                                    {std::is_integral<property_##item_name##_t>::value, \
                                                                                        std::is_enum<property_##item_name##_t>::value, \
                                                                                        std::is_floating_point<property_##item_name##_t>::value, \
                                                                                        std::is_signed<property_##item_name##_t>::value, \
                                                                                        std::is_class<property_##item_name##_t>::value }; return val.int_value; }; \
    static const char*  get_item_name(UID<__property_##item_name##_idx>) {return #item_name;}; \
    static def_func     get_default_value(UID<__property_##item_name##_idx>) {return get_default_func;}; \
    static deep_copy    get_deep_copy_func(UID<__property_##item_name##_idx>) {return copy_func;}; \
public: \
    property_##item_name##_t& get_##item_name () {return x_##item_name##_;} \
protected: \
    property_##item_name##_t x_##item_name##_;

#define END_CONFIG_CONTAINER()      \
private: \
    enum {__property_last_idx = __COUNTER__ - __property_first_idx - 1}; \
public: \
    static const unsigned int get_config_count() {return __property_last_idx;}; \
};

#define CONFIG_CONTAINER_IMPL(class_name) \
unsigned int class_name :: x_config_item_count = class_name :: __property_last_idx; \
template<int N> class_name::ConfigItemLink class_name ::ConfigItemSeq<N>::config_item_seq = { {get_offset(UID<N>() ), get_size(UID<N>() ), get_type_mask(UID<N>() ), get_item_name(UID<N>()), get_default_value(UID<N>()), get_deep_copy_func(UID<N>())  }, & ConfigItemSeq<N-1>::config_item_seq }; \
template<>      class_name::ConfigItemLink class_name ::ConfigItemSeq<0>::config_item_seq = { {get_offset(UID<0>() ), get_size(UID<0>() ), get_type_mask(UID<0>() ), get_item_name(UID<0>()), get_default_value(UID<0>()), get_deep_copy_func(UID<0>())  }, 0 }; \
const class_name::ConfigItemLink* class_name ::GetConfigItem() \
{ \
    static class_name::ConfigItemLink* class_name##ItemArray = & ConfigItemSeq<__property_last_idx - 1>::config_item_seq; \
    return class_name##ItemArray;\
}

#define BEGIN_CONFIG2_CONTAINER(class_name, struct_name)  \
class class_name : public struct_name, public XConfigContainer< class_name> \
{ \
public: \
    class_name() { \
        memset((struct_name*)this, 0, sizeof( struct_name )); \
    }; \
    ~class_name() {} \
    static unsigned int x_config_item_count; \
    static const ConfigItemLink* GetConfigItem(); \
public: \
    template<int N> struct ConfigItemSeq{  static ConfigItemLink config_item_seq; }; \
private: \
    typedef class_name thisClass; \
    typedef struct_name thisStruct; \
    enum {__property_first_idx = __COUNTER__}; \

#define CONFIG2_ITEM(type_name, item_name, get_default_func, copy_func) \
public: \
    typedef type_name property_##item_name##_t; \
private: \
    enum {__property_##item_name##_idx = __COUNTER__ - __property_first_idx - 1}; \
    static unsigned int get_offset(UID<__property_##item_name##_idx>) {return (unsigned int)(size_t)&(((thisClass *)0)-> item_name );}; \
    static unsigned int get_size(UID<__property_##item_name##_idx>) {return sizeof(property_##item_name##_t); }; \
    static unsigned int get_type_mask(UID<__property_##item_name##_idx>) {static type_mask val = \
                                                                                   {std::is_integral<property_##item_name##_t>::value, \
                                                                                    std::is_enum<property_##item_name##_t>::value, \
                                                                                    std::is_floating_point<property_##item_name##_t>::value, \
                                                                                    std::is_signed<property_##item_name##_t>::value, \
                                                                                    std::is_class<property_##item_name##_t>::value }; return val.int_value; }; \
    static const char*  get_item_name(UID<__property_##item_name##_idx>) {return #item_name;}; \
    static def_func     get_default_value(UID<__property_##item_name##_idx>) {return get_default_func;}; \
    static deep_copy    get_deep_copy_func(UID<__property_##item_name##_idx>) {return copy_func;}; \
public: \
    property_##item_name##_t& get_##item_name () {return item_name;} \

#define END_CONFIG2_CONTAINER()      \
private: \
    enum {__property_last_idx = __COUNTER__ - __property_first_idx - 1}; \
public: \
    static const unsigned int get_config_count() {return __property_last_idx;}; \
};

#define CONFIG2_CONTAINER_IMPL(class_name) \
unsigned int class_name :: x_config_item_count = class_name :: __property_last_idx; \
template<int N> class_name::ConfigItemLink class_name ::ConfigItemSeq<N>::config_item_seq = { {get_offset(UID<N>() ), get_size(UID<N>() ), get_type_mask(UID<N>() ), get_item_name(UID<N>()), get_default_value(UID<N>()), get_deep_copy_func(UID<N>())  }, & ConfigItemSeq<N-1>::config_item_seq }; \
template<>      class_name::ConfigItemLink class_name ::ConfigItemSeq<0>::config_item_seq = { {get_offset(UID<0>() ), get_size(UID<0>() ), get_type_mask(UID<0>() ), get_item_name(UID<0>()), get_default_value(UID<0>()), get_deep_copy_func(UID<0>())  }, 0 }; \
const class_name::ConfigItemLink* class_name ::GetConfigItem() \
{ \
    static class_name::ConfigItemLink* class_name##ItemArray = & ConfigItemSeq<__property_last_idx - 1>::config_item_seq; \
    return class_name##ItemArray;\
}
#define DEFALUT_VALUE_DECL(value)         []() -> void* {return (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;
}

#define DEFALUT_VALUE_FLOAT_DECL(value)   []() -> void* {return  union_cast<void*>(value);}

#endif

使用办法:

1.预先定义好的配置信息结构体

typedef struct config_param_t {
    unsigned short param_version;   
    unsigned short aaa;                     
    float  bbb;
    float  ccc;
} config_param;

2.声明相应的结构信息说明:

#include "ConfigContainer.h"

BEGIN_CONFIG2_CONTAINER(ConfigParam, config_param);
    CONFIG2_ITEM(unsigned short, param_version,          DEFALUT_VALUE_DECL(57920),          NULL);
    CONFIG2_ITEM(unsigned short, aaa,                DEFALUT_VALUE_DECL(0),              NULL);
    CONFIG2_ITEM(float,  bbb,                      DEFALUT_VALUE_FLOAT_DECL(0.5f),       NULL);  // ,默认值为0.5
    CONFIG2_ITEM(float,  ccc,                       DEFALUT_VALUE_FLOAT_DECL(0.5f),       NULL);  // ,默认值为0.6
END_CONFIG2_CONTAINER();

3.实现结构信息说明:

#include "config_param.h"

CONFIG2_CONTAINER_IMPL(ConfigParam);

 

4-1.使用Ini来读取配置文件,相应代码:

#include <SimpleIni.h>
#include "ConfigContainer.h"

template<class T>
void copy_value(unsigned char* dest, T* src, unsigned int size){
    switch (size)
    {
    case sizeof(unsigned char):
        if (std::is_signed<T>::value)
            *(char*)dest = *(char*)src;
        else
            *(unsigned char*)dest = *(unsigned char*)src;
        return;
    case sizeof(unsigned short):
        if (std::is_signed<T>::value)
            *(short*)dest = *(short*)src;
        else
            *(unsigned short*)dest = *(unsigned short*)src;
        return;
    case sizeof(unsigned int):
        if (std::is_floating_point<T>::value){
            *(float*)dest = *(float*)src;
        } else {
            if (std::is_signed<T>::value)
                *(int*)dest = *(int*)src;
            else
                *(unsigned int*)dest = *(unsigned int*)src;
        }
        return;
    }
    // 其他情况,使用memcpy
    memcpy(dest, src, size);
}

template<class TBase>
unsigned int XConfigContainer<TBase>::init(void* user_param)
{
    // 依次读取配置项
    type_mask temp_type_mask;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        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_)());
                copy_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_)());
                copy_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_)());
            copy_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &float_val, lpItem->cfg_item.size);
        } else { // 其他,默认是字符串
            //char* strDef = (char*)((*def_func_)());
            char* strValue = (char*)((*def_func_)());
            // 如果有深度拷贝,则使用深拷贝函数
            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_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)
{
    // 内部对象
    CSimpleIniA * c_ini = (CSimpleIniA *)(config_pesist);
    if (0 == c_ini) {
        return 1;
    }

    // 依次读取配置项
    type_mask temp_type_mask;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        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 = (signed int)c_ini->GetLongValue((const char*)user_param, lpItem->cfg_item.itemname, union_cast<signed int>((*def_func_)()));
                copy_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 = (signed int)c_ini->GetLongValue((const char*)user_param, lpItem->cfg_item.itemname, union_cast<unsigned int>((*def_func_)()));
                copy_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &unsigned_val, lpItem->cfg_item.size);
            }
        } else if (temp_type_mask.is_float_){ // 浮点数
            //float def_float_val = union_cast<float>((*def_func_)());
            float float_val = (float)c_ini->GetDoubleValue((const char*)user_param, lpItem->cfg_item.itemname, union_cast<float>((*def_func_)()));
            copy_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &float_val, lpItem->cfg_item.size);
        } else { // 其他,默认是字符串
            //char* strDef = (char*)((*def_func_)());
            char* strValue = (char*)c_ini->GetValue((const char*)user_param, lpItem->cfg_item.itemname, (char*)((*def_func_)()));
            // 如果有深度拷贝,则使用深拷贝函数
            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_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_detla(void* config_pesist, void* user_param)
{
    // 内部对象
    CSimpleIniA * c_ini = (CSimpleIniA *)(config_pesist);
    if (0 == c_ini) {
        return 1;
    }

    // 依次读取配置项
    type_mask temp_type_mask;
    //cJSON * c_item = NULL;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        temp_type_mask.int_value = lpItem->cfg_item.type_mask_;

        lpItem = lpItem->lpnext;
    }

    return 0;
}

template<class T>
T read_value(unsigned char* dest,  unsigned int size){
    switch (size)
    {
    case sizeof(unsigned char):
        if (std::is_signed<T>::value)
            return (T)*(char*)dest;
        else
            return (T)*(unsigned char*)dest;
    case sizeof(unsigned short):
        if (std::is_signed<T>::value)
            return (T)*(short*)dest;
        else
            return (T)*(unsigned short*)dest;
    case sizeof(unsigned int):
        if (std::is_floating_point<T>::value){
            return (T)*(float*)dest;
        } else {
            if (std::is_signed<T>::value)
                return (T)*(int*)dest;
            else
                return (T)*(unsigned int*)dest;
        }
    case sizeof(double):
        return *(T*)dest;
    default:
        return *(T*)dest;
    }
    return 0;
}

template<class TBase>
unsigned int XConfigContainer<TBase>::save(void* config_pesist, void* user_param) const
{
    // 内部对象
    CSimpleIniA * c_ini = (CSimpleIniA *)(config_pesist);
    if (0 == c_ini) {
        return 1;
    }

    // 依次读取配置项
    type_mask temp_type_mask;
    //cJSON * c_item = NULL;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        lpItem = lpItem->lpnext;
    }

    return 0;
}

template<class TBase>
unsigned int XConfigContainer<TBase>::save_to_struct(void* config_struct, void* user_param) const
{
    void* algo_config = (void*)config_struct;
    if (0 == algo_config) {
        return 1;
    }

    type_mask temp_type_mask;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        temp_type_mask.int_value = lpItem->cfg_item.type_mask_;
        if (temp_type_mask.is_int_) {
            if (temp_type_mask.is_signed_) {
                signed int def_val = *(signed int*)&(((unsigned char*)this)[lpItem->cfg_item.offset]);
                copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
            } else {
                unsigned int def_val = *(unsigned int*)&(((unsigned char*)this)[lpItem->cfg_item.offset]);
                copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
            }
        } else if (temp_type_mask.is_float_){ // 浮点数
            float def_val = *(float*)&(((unsigned char*)this)[lpItem->cfg_item.offset]);
            copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
        } else { // 其他,默认是字符串
            const char* strDef = ((std::string*) &(((unsigned char*)this)[lpItem->cfg_item.offset]))->c_str();
            // 如果有深度拷贝,则使用深拷贝函数
            if (lpItem->cfg_item.deep_copy_func) {
                (*(lpItem->cfg_item.deep_copy_func))(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size);
            } else {
                copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size);
            }
        }

        lpItem = lpItem->lpnext;
    }

    return 0;
}

4-2.如果使用Json,则是如下的转化代码:

#include "ConfigContainer.h"

#include "cJSON.h"

template<class T>
void copy_value(unsigned char* dest, T* src, unsigned int size){
    switch (size)
    {
    case sizeof(unsigned char):
        if (std::is_signed<T>::value)
            *(char*)dest = *(char*)src;
        else
            *(unsigned char*)dest = *(unsigned char*)src;
        return;
    case sizeof(unsigned short):
        if (std::is_signed<T>::value)
            *(short*)dest = *(short*)src;
        else
            *(unsigned short*)dest = *(unsigned short*)src;
        return;
    case sizeof(unsigned int):
        if (std::is_floating_point<T>::value){
            *(float*)dest = *(float*)src;
        } else {
            if (std::is_signed<T>::value)
                *(int*)dest = *(int*)src;
            else
                *(unsigned int*)dest = *(unsigned int*)src;
        }
        return;
    }
    // 其他情况,使用memcpy
    memcpy(dest, src, size);
}

template<class TBase>
unsigned int XConfigContainer<TBase>::load(void* config_pesist, void* user_param)
{
    // 内部对象
    cJSON * c_json = (cJSON *)(config_pesist);
    if (0 == c_json) {
        return 1;
    }

    // 依次读取配置项
    type_mask temp_type_mask;
    cJSON * c_item = NULL;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        // 从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_)());
                    copy_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
                } else {
                    unsigned int def_val = (unsigned int)((*def_func_)());
                    copy_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_)());
                copy_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
            } else { // 其他,默认是字符串
                char* strDef = (char*)((*def_func_)());
                // 如果有深度拷贝,则使用深拷贝函数
                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_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_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
                } else {
                    unsigned int def_val = c_item->valueint;
                    copy_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_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_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size);
                }
            }
        }

        lpItem = lpItem->lpnext;
    }

    return 0;
}

template<class TBase>
unsigned int XConfigContainer<TBase>::load_detla(void* config_pesist, void* user_param)
{
    // 内部对象
    cJSON * c_json = (cJSON *)(config_pesist);
    if (0 == c_json) {
        return 1;
    }

    // 依次读取配置项
    type_mask temp_type_mask;
    cJSON * c_item = NULL;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        // 从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){
            if (temp_type_mask.is_int_) {
                if (temp_type_mask.is_signed_) {
                    signed int def_val = c_item->valueint;
                    copy_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
                } else {
                    unsigned int def_val = c_item->valueint;
                    copy_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_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_value(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size);
                }
            }
        }

        lpItem = lpItem->lpnext;
    }

    return 0;
}

template<class T>
T read_value(unsigned char* dest,  unsigned int size){
    switch (size)
    {
    case sizeof(unsigned char):
        if (std::is_signed<T>::value)
            return (T)*(char*)dest;
        else
            return (T)*(unsigned char*)dest;
    case sizeof(unsigned short):
        if (std::is_signed<T>::value)
            return (T)*(short*)dest;
        else
            return (T)*(unsigned short*)dest;
    case sizeof(unsigned int):
        if (std::is_floating_point<T>::value){
            return (T)*(float*)dest;
        } else {
            if (std::is_signed<T>::value)
                return (T)*(int*)dest;
            else
                return (T)*(unsigned int*)dest;
        }
    case sizeof(double):
        return *(T*)dest;
    default:
        return *(T*)dest;
    }
    return 0;
}

template<class TBase>
unsigned int XConfigContainer<TBase>::save(void* config_pesist, void* user_param) const
{
    // 内部对象
    cJSON * c_json = (cJSON *)(config_pesist);
    if (0 == c_json) {
        return 1;
    }

    // 依次读取配置项
    type_mask temp_type_mask;
    cJSON * c_item = NULL;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        temp_type_mask.int_value = lpItem->cfg_item.type_mask_;
        if (temp_type_mask.is_int_) {
            // 暂时还不支持64位大整数
            if (temp_type_mask.is_signed_) {
                cJSON_AddNumberToObject(c_json, lpItem->cfg_item.itemname, read_value<signed int>(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), lpItem->cfg_item.size));
            } else {
                cJSON_AddNumberToObject(c_json, lpItem->cfg_item.itemname, read_value<unsigned int>(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), lpItem->cfg_item.size));
            }
        } else if (temp_type_mask.is_float_){ // 浮点数
            if (lpItem->cfg_item.size == sizeof(float)) {
                cJSON_AddNumberToObject(c_json, lpItem->cfg_item.itemname, read_value<float>(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), lpItem->cfg_item.size));
            } else {
                cJSON_AddNumberToObject(c_json, lpItem->cfg_item.itemname, read_value<double>(&(((unsigned char*)(TBase*)this)[lpItem->cfg_item.offset]), lpItem->cfg_item.size));
            }            
        } else { // 其他,默认是字符串
            cJSON_AddStringToObject(c_json, lpItem->cfg_item.itemname, ((std::string*)&((char*)(TBase*)this)[lpItem->cfg_item.offset]) -> c_str());
        }

        lpItem = lpItem->lpnext;
    }

    return 0;
}

template<class TBase>
unsigned int XConfigContainer<TBase>::save_to_struct(void* config_struct, void* user_param) const
{
    void* algo_config = (void*)config_struct;
    if (0 == algo_config) {
        return 1;
    }

    type_mask temp_type_mask;
    const ConfigItemLink* lpItem = TBase::GetConfigItem();
    while(lpItem != nullptr) {
        temp_type_mask.int_value = lpItem->cfg_item.type_mask_;
        if (temp_type_mask.is_int_) {
            if (temp_type_mask.is_signed_) {
                signed int def_val = *(signed int*)&(((unsigned char*)this)[lpItem->cfg_item.offset]);
                copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
            } else {
                unsigned int def_val = *(unsigned int*)&(((unsigned char*)this)[lpItem->cfg_item.offset]);
                copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
            }
        } else if (temp_type_mask.is_float_){ // 浮点数
            float def_val = *(float*)&(((unsigned char*)this)[lpItem->cfg_item.offset]);
            copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), &def_val, lpItem->cfg_item.size);
        } else { // 其他,默认是字符串
            const char* strDef = ((std::string*) &(((unsigned char*)this)[lpItem->cfg_item.offset]))->c_str();
            // 如果有深度拷贝,则使用深拷贝函数
            if (lpItem->cfg_item.deep_copy_func) {
                (*(lpItem->cfg_item.deep_copy_func))(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size);
            } else {
                copy_value(&(((unsigned char*)algo_config)[lpItem->cfg_item.offset]), strDef, lpItem->cfg_item.size);
            }
        }

        lpItem = lpItem->lpnext;
    }

    return 0;
}

5.使用时

#include "ConfigContainer_ini.h"

    ConfigParam                 x_config_param;
    CSimpleIniA* ini_file_stream_ptr_ = new CSimpleIniA();
    if(SI_OK != ini_file_stream_ptr_->LoadFile(szConfigIni)){
        return ;
    }

    x_config_param.load(ini_file_stream_ptr_, DEFAULT);

 

posted @ 2021-05-19 13:53  日月王  阅读(212)  评论(0编辑  收藏  举报