引言
大学读的是一个很时髦的专业, 学了四年的游戏竞技. 可惜没学好. 但认真过, 比做什么都认真. 见证了 ......
打的所有游戏人物中 分享一位最喜爱 的
“I've been alone for 10 thousand years. 我孤独了一万年。”
“What I may be,whatever I may become in this world,know that I will always look out of you,Tyrande. 无论我做了什么,无论我变成什么样子,我会永远关心你的,泰兰德。”
前言
上一次 写了两篇 关于 C json 引擎 解析和 构造内容
结合上面加上当前这篇, 一个高效能用的 cjson 引擎就诞生了.
今天 , 分享这篇, 至少可以让大家, 学到简单深拷贝. 一些构造技巧. 还有就是cjson的辅助函数使用!
同样先分享一个函数 封装 开始.
/* * 这个代码是 对 strdup 的再实现, 调用之后需要free * str : 待复制的源码内容 * : 返回 复制后的串内容 */ char* str_dup(const char* str) { int len; char* nstr; DEBUG_CODE({ if (NULL == str) { SL_WARNING("check is NULL == str!!"); return NULL; } }); len = sizeof(char) * (strlen(str) + 1); if (!(nstr = malloc(len))) { SL_FATAL("malloc is error! len = %d.", len); return NULL; } // 返回最后结果 return memcpy(nstr, str, len); }
老代码中 有过 strdup 深拷贝 字符串, 后面各个平台支持的不一样 _strdup __strdup , strdup 各种. 后面为了统一写了一个.
其中 DEBUG_CODE 是对 assert 宏的扩展
/* * 10.1 这里是一个 在 DEBUG 模式下的测试宏 * * 用法 : * DEBUG_CODE({ * puts("debug start..."); * }); */ #ifndef DEBUG_CODE # ifdef _DEBUG # define DEBUG_CODE(code) code # else # define DEBUG_CODE(code) # endif // ! _DEBUG #endif // !DEBUG_CODE
在 _DEBUG模式下开启 测试代码, 没有_DEBUG处于发布状态的时候,这段检测代码编译的时候会被去掉. 为了效率而生.
对于SL_FATAL 是 sclog.h 接口中 一个 内部错误 日志宏. sclog.h 这个日志记录类, 也很不错. 前面博文中
最后那部分 讲解了 sclog.h 代码, 当时讲的的太多了,应该分开细说的. sclog.h 思路还是很不错的, 基本上业界大体也是这个思路.
多用户, 分级等手段. 前言已经介绍完了. 后面就随意了, 都可以不看了.
正文
1. cjson 辅助操作添加的接口
新加的接口如下
// --------------------------------- 下面是 cjson 输出部分的辅助代码 ----------------------------------------- /* * 创建一个bool的对象 b==0表示false,否则都是true, 需要自己释放 cjson_delete * b : bool 值 最好是 _Bool * : 返回 创建好的json 内容 */ extern cjson_t cjson_newnull(); extern cjson_t cjson_newbool(int b); extern cjson_t cjson_newnumber(double vd); extern cjson_t cjson_newstring(const char* vs); extern cjson_t cjson_newarray(void); extern cjson_t cjson_newobject(void); /* * 按照类型,创建 对映类型的数组 cjson对象 *目前支持 _CJSON_NULL _CJSON_BOOL/FALSE or TRUE , _CJSON_NUMBER, _CJSON_STRING * NULL => array 传入NULL, FALSE 使用char[],也可以传入NULL, NUMBER 只接受double, string 只接受char** * type : 类型目前支持 上面几种类型 * array : 数组原始数据 * len : 数组中元素长度 * : 返回创建的数组对象 */ extern cjson_t cjson_newtypearray(int type, const void* array, int len); /* * 将 jstr中 不需要解析的字符串都去掉 * jstr : 待处理的json串 * : 返回压缩后的json串内容 */ extern char* cjson_mini(char* jstr); /* * 将json文件解析成json内容返回. 需要自己调用 cjson_delete * jpath : json串路径 * : 返回处理好的cjson_t 内容,失败返回NULL */ extern cjson_t cjson_dofile(char* jpath); /* * 在array中分离第idx个索引项内容. * array : 待处理的json_t 数组内容 * idx : 索引内容 * : 返回分离的json_t内容 */ extern cjson_t cjson_detacharray(cjson_t array, int idx); /* * 在object json 中分离 key 的项出去 * object : 待分离的对象主体内容 * key : 关联的键 * : 返回分离的 object中 key的项json_t */ extern cjson_t cjson_detachobject(cjson_t object, const char* key);
前面是创建, 后面是分离, 分离的意思就是离开和上一轮没关系了. 线程也有分离的概念. 分离后自己自行回收.
其中 cjson_mini 是为了去掉 cjson 字符串中 无用的字符内容.
2. 摘录其中优秀的接口,分析设计
首先看看下面一个函数
/* * 将 jstr中 不需要解析的字符串都去掉,并且纪念mini 比男的还平 * jstr : 待处理的json串 * : 返回压缩后的json串内容 */ char* cjson_mini(char* jstr) { char* in = jstr; char* to = jstr; char c; while(!!(c=*to)){ if(sh_isspace(c)) ++to; else if(c == '/' && to[1] == '/') while((c=*++to) && c!=' '); else if(c == '/' && to[1] == '*'){ while((c=*++to) && !(c=='*' && to[1] =='/')) ; if(c) to+=2; } else if(c=='"'){ *in++ = c; while((c=*++to) && (c!='"' || to[-1]=='\')) *in++ = c; if(c) { *in++=c; ++to; } } else *in++ = *to++; } *in = '