admin 发布的文章

python有chardet,java有cpdetector,C或者C++搜索了好久,找到了uchardet

其实python的chardet与uchardet都是源自于Firefox中的universalchardet

http://lxr.mozilla.org/seamonkey/source/extensions/universalchardet/

uchardet的地址:

https://github.com/BYVoid/uchardet

 

代码摘自网络:(https://blog.csdn.net/a33445621/article/details/71127745)

 

/*-----------------内码转换-------------------------------------*/
//转换UCS4编码到UTF8编码
int UCS4_To_UTF8( unsigned int dwUCS4, BYTE*pbUTF8 )
{
const BYTE abPrefix[] = {0, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};const unsigned int adwCodeUp[] ={0x80, //U+00000000 ~ U+0000007F 0x800, //U+00000080 ~ U+000007FF 0x10000, //U+00000800 ~ U+0000FFFF 0x200000, //U+00010000 ~ U+001FFFFF 0x4000000, //U+00200000 ~ U+03FFFFFF 0x80000000 //U+04000000 ~ U+7FFFFFFF };inti, iLen;//根据UCS4编码范围确定对应的UTF-8编码字节数 iLen = sizeof(adwCodeUp) / sizeof(DWORD);for( i = 0; i < iLen; i++)
{
if( dwUCS4 <adwCodeUp[i] )
{
break;
}
}
if( i == iLen )return 0; //无效的UCS4编码 iLen= i + 1; //UTF-8编码字节数 if( pbUTF8 !=NULL )
{
//转换为UTF-8编码 for( ; i > 0; i--)
{
pbUTF8[i]
= static_cast<BYTE>((dwUCS4 & 0x3F) | 0x80);
dwUCS4
>>= 6;
}

pbUTF8[
0] = static_cast<BYTE>(dwUCS4 | abPrefix[iLen - 1]);
}
returniLen;
}
//转换UTF8编码到UCS4编码 int UTF8_To_UCS4( const BYTE* pbUTF8, unsigned int&dwUCS4 )
{
INT i, iLen;
BYTE b;
if( pbUTF8 ==NULL )
{
//参数错误 return 0;
}

b
= *pbUTF8++;if( b < 0x80)
{
dwUCS4
=b;return 1;
}
if( b < 0xC0 || b > 0xFD)
{
//非法UTF8 return 0;
}
if( b < 0xE0)
{
dwUCS4
= b & 0x1F;
iLen
= 2;
}
else if( b < 0xF0)
{
dwUCS4
= b & 0x0F;
iLen
= 3;
}
else if( b < 0xF8)
{
dwUCS4
= b & 7;
iLen
= 4;
}
else if( b < 0xFC)
{
dwUCS4
= b & 3;
iLen
= 5;
}
else{
dwUCS4
= b & 1;
iLen
= 6;
}
for( i = 1; i < iLen; i++)
{
b
= *pbUTF8++;if( b < 0x80 || b > 0xBF)
{
//非法UTF8 break;
}

dwUCS4
= (dwUCS4 << 6) + (b & 0x3F);
}
if( i <iLen )
{
//非法UTF8 return 0;
}
returniLen;
}
//转换UCS4编码到UCS2编码 int UCS4_To_UTF16( DWORD dwUCS4, WORD*pwUTF16 )
{
if( dwUCS4 <= 0xFFFF)
{
if( pwUTF16 !=NULL )
{
*pwUTF16 = static_cast<WORD>(dwUCS4);
}
return 1;
}
else if( dwUCS4 <= 0xEFFFF)
{
if( pwUTF16 !=NULL )
{
pwUTF16[
0] = static_cast<WORD>( 0xD800 + (dwUCS4 >> 10) - 0x40 ); //高10位 pwUTF16[1] = static_cast<WORD>( 0xDC00 + (dwUCS4 & 0x03FF) ); //低10位 }return 2;
}
else{return 0;
}
}
//转换UCS2编码到UCS4编码 INT UTF16_To_UCS4( const WORD* pwUTF16, unsigned int&dwUCS4 )
{
WORD w1, w2;
if( pwUTF16 ==NULL )
{
//参数错误 return 0;
}

w1
= pwUTF16[0];if( w1 >= 0xD800 && w1 <= 0xDFFF)
{
//编码在替代区域(Surrogate Area) if( w1 < 0xDC00)
{
w2
= pwUTF16[1];if( w2 >= 0xDC00 && w2 <= 0xDFFF)
{
dwUCS4
= (w2 & 0x03FF) + (((w1 & 0x03FF) + 0x40) << 10);return 2;
}
}
return 0; //非法UTF16编码 }
dwUCS4
=w1;return 1;
}
//转换UTF8字符串到UTF16字符串 INT UTF8Str_To_UTF16Str( const BYTE* pbszUTF8Str, WORD*pwszUTF16Str )
{
INT iNum, iLen;
unsigned
intdwUCS4;if( pbszUTF8Str ==NULL )
{
//参数错误 return 0;
}

iNum
= 0; //统计有效字符个数 while( *pbszUTF8Str )
{
//UTF8编码转换为UCS4编码 iLen =UTF8_To_UCS4( pbszUTF8Str, dwUCS4 );if( iLen == 0)
{
//非法的UTF8编码 return 0;
}

pbszUTF8Str
+=iLen;//UCS4编码转换为UTF16编码 iLen =UCS4_To_UTF16( dwUCS4, pwszUTF16Str );if( iLen == 0)
{
return 0;
}
if( pwszUTF16Str !=NULL )
{
pwszUTF16Str
+=iLen;
}

iNum
+=iLen;
}
if( pwszUTF16Str !=NULL )
{
*pwszUTF16Str = 0; //写入字符串结束标记 }returniNum;
}
//转换UTF16字符串到UTF8字符串 int UTF16Str_To_UTF8Str( const WORD* pwszUTF16Str, BYTE*pbszUTF8Str )
{
INT iNum, iLen;
unsigned
intdwUCS4;if( pwszUTF16Str ==NULL )
{
//参数错误 return 0;
}

iNum
= 0;while( *pwszUTF16Str )
{
//UTF16编码转换为UCS4编码 iLen =UTF16_To_UCS4( pwszUTF16Str, dwUCS4 );if( iLen == 0)
{
//非法的UTF16编码 return 0;
}

pwszUTF16Str
+=iLen;//UCS4编码转换为UTF8编码 iLen =UCS4_To_UTF8( dwUCS4, pbszUTF8Str );if( iLen == 0)
{
return 0;
}
if( pbszUTF8Str !=NULL )
{
pbszUTF8Str
+=iLen;
}

iNum
+=iLen;
}
if( pbszUTF8Str !=NULL )
{
*pbszUTF8Str = 0; //写入字符串结束标记 }returniNum;
}

 

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

 主体类定义:

#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
intint_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:
typedef
void* (*def_func)(void* config_pesist, void*user_param);
typedef
bool (*deep_copy)(void* dest, const void* src, unsigned intsize);

typedef
structtagConfigItem
{
unsigned
intoffset;
unsigned
intsize;
unsigned
inttype_mask_;const char*itemname;
def_func default_func;
deep_copy deep_copy_func;
}ConfigItem;

typedef
structtagConfigItemLink
{
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
intfirst_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{
unsigned
shortx;
unsigned
shorty;
unsigned
shortwidth;
unsigned
shortheight;
}rect_t;

typedef
structmusic_player_config{
unsigned
shortversion;
unsigned
shortaaa;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(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 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(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)
{
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_) {
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;
}

 

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

主体类定义:

#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> structUID{};

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
intint_value;
}type_mask;

template
<class TBase> classXConfigContainer
{
public:
typedef
void* (*def_func)();
typedef
bool (*deep_copy)(void* dest, const void* src, unsigned intsize);

typedef
structtagConfigItem
{
unsigned
intoffset;
unsigned
intsize;
unsigned
inttype_mask_;const char*itemname;
def_func default_func;
deep_copy deep_copy_func;
}ConfigItem;

typedef
structtagConfigItemLink
{
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
intfirst_item_; \public: \
class_name() { \
memset(
&first_item_, 0, sizeof( class_name ) - (unsigned int)(size_t)&(((class_name *)0)->first_item_ )); \
}; \
~class_name() {} \static unsigned intx_config_item_count; \static const ConfigItemLink*GetConfigItem(); \public: \
template
<int N> struct ConfigItemSeq{ staticConfigItemLink 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 }; returnval.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>) {returnget_default_func;}; \static deep_copy get_deep_copy_func(UID<__property_##item_name##_idx>) {returncopy_func;}; \public: \
property_##item_name##_t
& get_##item_name () {returnx_##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) \unsignedint 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; \returnclass_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 intx_config_item_count; \static const ConfigItemLink*GetConfigItem(); \public: \
template
<int N> struct ConfigItemSeq{ staticConfigItemLink 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 }; returnval.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>) {returnget_default_func;}; \static deep_copy get_deep_copy_func(UID<__property_##item_name##_idx>) {returncopy_func;}; \public: \
property_##item_name##_t
& get_##item_name () {returnitem_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) \unsignedint 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; \returnclass_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;returnval1.t1_val2;
}
#define DEFALUT_VALUE_FLOAT_DECL(value) []() -> void* {return union_cast<void*>(value);} #endif

使用办法:

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

typedef structconfig_param_t {
unsigned
shortparam_version;
unsigned
shortaaa;floatbbb;floatccc;
} 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 intsize){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>unsignedint 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>unsignedint 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>unsignedint 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(unsignedchar* dest, unsigned intsize){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>unsignedint 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>unsignedint 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 intsize){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>unsignedint 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>unsignedint 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(unsignedchar* dest, unsigned intsize){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>unsignedint 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>unsignedint 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_ = newCSimpleIniA();if(SI_OK != ini_file_stream_ptr_->LoadFile(szConfigIni)){return;
}

x_config_param.load(ini_file_stream_ptr_, DEFAULT);

 

原文地址:http://blog.csdn.net/zhangting00_2000/archive/2009/04/20/4095272.aspx

我叫张挺,虽然开博,除了转了一篇黄色文章以外,技术文章从来没有写,所以呢,感到很不好意思!于是决定还写一篇在网上也留点痕迹。我这里主要是介 绍TCPMP的移植以及如何把这个鸟鸟整到自己的界面中来.网上关于TCPMP的开发文章不是很多,有一点点呢,犹如JJ太短,不能深入;又或者不实用. 今天呢,我先讲如何编译,然后讲如何操控制.eMail:zt00@tom.com

一、编译。

关于编译,我是引用的别人的文章,我实验过,确实可行。如下所言:

开发环境:windows xp sp2 + EVC4.0(SP4)
目标平台:Windows CE5.0(ARMV4)

1.下载源码,可以去下载TCPMP源代码。我下载的源码版本是0.72RC1。

2.编译环境.我安装的是evc4.2(SP4)+standard sdk+Win32(WCE ARMV4) Release.如果是编译x86或者Emulator版本的.要下载一个nasm汇编工具.这点在readme.txt里面提到.nasm的下载地址否则的话会因为缺少汇编器而报大量的错误。

3.下载下来的源码包中不包含ARM的解码器源码,可以从下面2个网址下载AMR的解码器的源代码: 
 
并且分别拷贝到AMR目录下的26104和26204中。同样,这个信息在readme.txt中提到。             

4.准备ARM的汇编器,根据实践经验,从ARM官网上面下载下来的汇编器编译时会报错,不适合使用,建议使用VS2005的ARM汇编器ARMASM.EXE,将其拷贝到C:\Microsoft eMbedded C++ 4.0\EVC\WCE400\BIN下面。

5.编译的时候切勿rebuild all,否则会报大量的错误,从Project—-Dependencies下来框里选择 player_ce3(主项目),可以看到子项目间的相互依赖关系,所以player_ce3是最后一个编译的项目。随便在下拉框中选择一个子项目,在依 赖项中都会发现common项目,说明该项目应该是首先需要进行编译的,下面我们首先从common项目入手。

6.将player_ce3项目set as active project,编译版本直接选择 Win32 (WCE ARMV4) Release。这个项目将最后一个进行编译,最终生成一个player_ce3.exe的应用程序,那我们的目标 也就达成了。但编译这个程序依赖许多的库。这些库就是其他的project编译后提供的。

7.在EVC左边的文件查看模式里首先选择common files,右键菜单Build(selection only)进行common项目的 编译,会很顺利的过去。接下来由上而下顺序为子项目进行编译,当然,在Project—-Dependencies中没有关联的项目不需要进行编译(总共 6项:player_ce2、sample_ce3、setup_ce2、setup_ce3、template、vorbislq),其它的把 asap、flac、player_ce3三项放下来最后处理,这三项需要对编译器进行额外配置,否则会报大量错误。不出意外的话,都会顺利编译过去。接 下来我们需要处理剩下来的3个项目。

8.编译asap项目。右键点 asap files –>settings–>c/c++–>Category–>Preprocessor在 Additional include directories:中增加项目路径(注意这个是相对路径,以下所有需添加内容都不包括引 号)”.,asap,atari800/src”.不然一堆头文件会找不到.在Preprocessor definitions:中增加一个宏定 义”,ASAP”当然这2步动作也可以在源代码中修改.如此设置完毕后,asap files project就可以正确编译了. 

9.编译flac项目。同8,打开flac的settings到相同界面.在Additional include directories:中增 加路径”flac/include,flac/src/libFLAC/include”,不然一堆头文件找不到。然后,在 Preprocessor definitions添加”,FLAC__NO_DLL”。增加这个定义避免使用_declspec(dllexport) 定义函数造成的一大堆c2491错误.如此设置后,flac project应该可以正确编译.

10.同理修改player_ce3项目,在Additional include directories中增加路径 ”../asap /asap,../asap,../asap/atari800/src,flac/include,flac/src/libFLAC /include”。然后在Preprocessor difinitions:增加”,ASAP”。这是最后一个项目文件,也是主项目文件,成功编译 player_ce3.exe。

11. 拷贝包含player_ce3.exe在内所有的生成文件到目标板上(所有文件必须放在同一个目录中),可以运行!但是菜单没有显示正确。 主要原因是现实语言配置文件没有加载上去,可以将源码lang目录下面的多国语言支持文件拷贝到目标板同一个目录下面。如果只需要简体中文和英文的,只要 拷贝lang_std.txt lang_en.txt,lang_chs.txt,lang_ca.def四个文件(四个语言配置文件一定要和应用程序 放在同一个目录)就可以了,打开后默认显示是英语,你可以更改到简体中文,前提是你的CE平台支持简体中文。

我是在VS2005中用开发平台的模拟器跑的,一切正常,就是播放不流畅,后期需要对这块进行优化。

我也尝试将其编译到ARMV4I平台上,结果也是可行的,不过由于的平台的特殊性,有部分配置需要改动,也有部分插件不被支持,不过不影响使用,大体总结如下:

1.经验总结表明在ARMV4I平台的编译工作中,TCPMP有部分模块不被支持,编译提示缺少相应文件。由于该部分不被支持的模块不影响播放器的 正常使用,可以在Project–Dependenties中下拉框中选择player_ce3,然后将以下几项前面的勾拿掉:ffmpeg、mpc、 speex 这三项可以不必编译。

2.Win32 (WCE ARMV4I) Debug及Release版本需要自己手动创建。在Build–Configurations里为每 个子项目选择ADD(上面提到的3项,和依赖项中不需要编译的6项不必添加),CPU选择Win32 (WCE ARMV4I),在 Copy settings from里选择Win32 (WCE ARMV4) Release,然后选择OK,你就为该子项目添加了相应编译版本。

3.右击需要编译的子项目,选择Settings–Link,在Category中选择General,然后再下面Project Options里将最后一行语句:/MACHINE:ARM 改成 /MACHINE:THUMB (每个项目都必须要改)

4.其它步骤按照按照上文ARMV4的过程来就可以了,相应的修改也是需要的,先从common开始,以player_ce3结束。

经过以上过程,你就可以定制自己专用的TCPMP播放器了,可以在interface项目中更改TCPMP的外观,当然,重头工作还在于对于特定平台的一些优化工作:)

二、关于控制TCPMP(张挺 )

说到控制,世界上很多东西需要控制,就象女人也同样需要控制,控制的好,于是社会才能和谐!

1、让TCPMP播放时能在我们自己指定的窗口.

呵呵,要真正让TCPMP播放器在我们指定的窗口播放,是需要修改COMMON插件的.请同志们把COMMON设置成当前工程,然后把GetDC函 数全部搜索出来,然后通通GetDC(Context()->Wnd)代替,并且ReleaseDC(NULL,DC)也通通用 ReleaseDC(Context()->Wnd,DC)代替;然后编译出来的插件就是我们需要的插件.只有这样,才能使 Context_Wnd(this->GetSafeHwnd())真正有效.

2、建立一个MFC的对话框工程.下面贴出代码:

下载代码请到:

下面贴出主要代码:

头文件:

//TCPMP_MyUIDlg.h : header file//张挺 2009-04-20 eMail:zt00@tom.com

#if !defined(AFX_TCPMP_MYUIDLG_H__B5DD421B_AF1E_4678_AD26_08A3F0DE3087__INCLUDED_)
#define AFX_TCPMP_MYUIDLG_H__B5DD421B_AF1E_4678_AD26_08A3F0DE3087__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif //_MSC_VER >= 1000

//包含TCPMP的头文件
#include "include/common.h"

/////////////////////////////////////////////////////////////////////////////
//CTCPMP_MyUIDlg dialog

class CTCPMP_MyUIDlg : publicCDialog
{
//Construction public:
CTCPMP_MyUIDlg(CWnd
* pParent = NULL); //standard constructor//Dialog Data//{{AFX_DATA(CTCPMP_MyUIDlg) enum { IDD =IDD_TCPMP_MYUI_DIALOG };
CSliderCtrl m_sliderPlay;
CStatic m_TextOutLable;
//}}AFX_DATA//ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CTCPMP_MyUIDlg) public:virtualBOOL DestroyWindow();protected:virtual void DoDataExchange(CDataExchange* pDX); //DDX/DDV support//}}AFX_VIRTUAL public:intm_TrackPos;
CString m_TextOutStr,m_TotalTimeStr;

BOOL m_bPlayOrPaulse;
//"播放/暂停"标志 player* m_Player;//操控TCPMP播放器的指针 BOOL InitTcpmp();//初始化TCPMP CString TickToStringZhang(int Tick);//时间转换 protected:
HICON m_hIcon;
//Generated message map functions//{{AFX_MSG(CTCPMP_MyUIDlg) virtualBOOL OnInitDialog();
afx_msg
voidOnPlay();
afx_msg
voidOnStop();//}}AFX_MSG afx_msg LRESULT PlayerEventMsg(WPARAM wParam, LPARAM lParam);

DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}//Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. #endif //!defined(AFX_TCPMP_MYUIDLG_H__B5DD421B_AF1E_4678_AD26_08A3F0DE3087__INCLUDED_)

 

下面是CPP文件:

//TCPMP_MyUIDlg.cpp : implementation file//
//张挺 2009-04-20 eMail:zt00@tom.com
#include "stdafx.h"#include"TCPMP_MyUI.h"#include"TCPMP_MyUIDlg.h"#ifdef _DEBUG#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] =__FILE__;#endif

#define WM_PLAYER_EVENTMSG WM_USER + 1985//播放器事件消息notify Notify;//通知
CWnd*g_pPlayerWnd =NULL;int PlayerNotify(node* Player,int Param,intParam2)
{

g_pPlayerWnd
->PostMessage(WM_PLAYER_EVENTMSG,Param,(LPARAM)Param2);returnERR_NONE;
}
///////////////////////////////////////////////////////////////////////////// //CTCPMP_MyUIDlg dialog CTCPMP_MyUIDlg::CTCPMP_MyUIDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTCPMP_MyUIDlg::IDD, pParent),m_bPlayOrPaulse(
true)
{
//{{AFX_DATA_INIT(CTCPMP_MyUIDlg)//}}AFX_DATA_INIT//Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

m_Player
=NULL;

m_TrackPos
= 0;

}
void CTCPMP_MyUIDlg::DoDataExchange(CDataExchange*pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTCPMP_MyUIDlg) DDX_Control(pDX, IDC_PERCENT, m_sliderPlay);
DDX_Control(pDX, IDC_TIME, m_TextOutLable);
//}}AFX_DATA_MAP }

BEGIN_MESSAGE_MAP(CTCPMP_MyUIDlg, CDialog)
//{{AFX_MSG_MAP(CTCPMP_MyUIDlg) ON_BN_CLICKED(IDC_PLAY, OnPlay)
ON_BN_CLICKED(IDC_STOP, OnStop)
//}}AFX_MSG_MAP ON_MESSAGE(WM_PLAYER_EVENTMSG, PlayerEventMsg)
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// //CTCPMP_MyUIDlg message handlers BOOL CTCPMP_MyUIDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//Set the icon for this dialog. The framework does this automatically//when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); //Set big icon SetIcon(m_hIcon, FALSE); //Set small icon CenterWindow(GetDesktopWindow());//center to the hpc screen//TODO: Add extra initialization here g_pPlayerWnd = this;

m_sliderPlay.SetRange(
0,30000);

InitTcpmp();
return TRUE; //return TRUE unless you set the focus to a control }


rect DefaultRect
= {0,0,320,240};//播放电影窗口区域 tchar_t URL[] = _T("Card\\TCPMP72NEW\\008.mp4");//播放文件的路径//初始化TCPMP BOOL CTCPMP_MyUIDlg::InitTcpmp()
{
//初始化 if(Context_Init(_T("TCPMP"),_T("0.72RC1"),3,(tchar_t*)AfxGetApp()->m_lpCmdLine,NULL))//{

context
* pContext=Context();//获得上下文 if(pContext)
m_Player
=(player*)(pContext->Player);else return false;


Context_Wnd(
this->GetSafeHwnd());//播放窗口关联//设置通知处理函数 Notify.Func =(notifyfunc)PlayerNotify;
Notify.This
= (void*)m_Player;if(m_Player)
m_Player
->Set(m_Player,PLAYER_NOTIFY,&Notify,sizeof(Notify));int i = 0;
m_Player
->Set(m_Player,PLAYER_LIST_COUNT,&i,sizeof(int));//播放列表清空 m_Player->Set(m_Player,PLAYER_LIST_URL+0,URL,sizeof(URL));

m_Player
->Set(m_Player,PLAYER_SKIN_VIEWPORT,&DefaultRect,sizeof(rect));//设置播放电影窗口区域 int index = 0;
m_Player
->Set(m_Player,PLAYER_LIST_CURRIDX,&index,sizeof(int));//设置播放列表里的某个文件为当前播放文件 m_Player->Set(m_Player,PLAYER_PLAY,&m_bPlayOrPaulse,sizeof(BOOL));//开始播放 }else return false;return true;

}
void CTCPMP_MyUIDlg::OnPlay()//播放/暂停 {if(m_Player)
{

m_bPlayOrPaulse
= !m_bPlayOrPaulse;

m_Player
->Set(m_Player,PLAYER_PLAY,&m_bPlayOrPaulse,sizeof(BOOL));

}



}
void CTCPMP_MyUIDlg::OnStop()//停止 {if(m_Player)
m_Player
->Set(m_Player,PLAYER_STOP,NULL,0);

}

BOOL CTCPMP_MyUIDlg::DestroyWindow()
//程序退出 {if(m_Player)
{

Context_Wnd(NULL);

Context_Done();

::Sleep(
200);
}
returnCDialog::DestroyWindow();
}

CString CTCPMP_MyUIDlg::TickToStringZhang(
intTick)
{
if (Tick<0)
Tick
= -Tick;intHour,Min,Sec;

Hour
= Tick / 3600 / TICKSPERSEC;//获得小时 Tick -= Hour * 3600 *TICKSPERSEC;
Min
= Tick / 60 / TICKSPERSEC;//获得分钟 Tick -= Min * 60 *TICKSPERSEC;
Sec
= Tick / TICKSPERSEC;//获得秒钟 Tick -= Sec *TICKSPERSEC;

CString strTime;

strTime.Format(_T(
"0%d:%d:%d"),Hour,Min,Sec);if(Min<10)
strTime.Insert(
3,'0');if(Sec<10)
strTime.Insert(strTime.GetLength()
-1,'0');returnstrTime;
}

LRESULT CTCPMP_MyUIDlg::PlayerEventMsg(WPARAM wParam, LPARAM lParam)
{
fraction f;
int Msg_Id = (int)wParam;int Msg_Status = (int)lParam;switch(Msg_Id)
{
casePLAYER_PERCENT:if(Msg_Status == 1)
{
m_Player
->Get(m_Player,PLAYER_PERCENT,&f,sizeof(fraction));
m_TrackPos
= Scale(30000,f.Num,f.Den);if(m_TrackPos>=29700)
m_TrackPos
= 30000;

m_sliderPlay.SetPos( m_TrackPos );

tick_t Time
=0;//tchar_t Dur[32]; if (m_Player->Get(m_Player,PLAYER_POSITION,&Time,sizeof(tick_t)) == ERR_NONE)//PLAYER_DURATION {

}
else{

}
m_TextOutStr.Empty();
m_TextOutStr
=TickToStringZhang(Time);
m_TextOutStr
+=_T("/");
m_TextOutStr
+=m_TotalTimeStr;//m_TextOutStr+=_T(" ");//m_TextOutStr+=m_TitleNameStr; m_TextOutLable.SetWindowText(m_TextOutStr);
}
break;casePLAYER_PLAY:break;casePLAYER_TITLE:break;default:break;


}
return true;

}

 

呵呵,请结合代码进行查看,一切变的很简单!