引言 - 以前那些系列
长活短说, 写的最终 scjson 纯c跨平台引擎, 希望在合适场景中替代老的csjon引擎, 速度更快, 更轻巧.
下面也是算一个系列吧. 从cjson 中得到灵感, 外加上很久以前自己写的json引擎. 具体的可以看看下面链接.
代码也许有点乱, 但是相信你看 cjson那个源码, 那就更乱了. 有些代码不讲道理, 好吃的东西都得让你难受一下. 才有转折.
本文是为了scjson 手写引擎添加注释解析功能. 再在跨平台上再做一些修改, 最终给出完整的测试demo.
c json实战引擎四 , 最后❤跳跃 (这就是程序语言设计中自举例子)
本文最终的资源 test_scjson.zip
前言 - 那就从json文件看起
先看我们需要处理的 goods.json 文件
[ /* * 物品定义处: * 物品名,品质,作用值,加血,加魔,加攻击,加防御,加速度,加幸运,价格, * 占用包裹,加暴击,拥有量,最大拥有,可买(1可买,0不可买),可卖(1可卖, 0不可买) */ ["小灵芝", "低级★", 1, 50, 0, 0, 0, 0, 0, 20, 1, 0, 3, 99, 1, 1], ["中灵芝", "中级★★", 1, 100, 0, 0, 0, 0, 0, 40, 2, 0, 1, 99, 1, 1], ["大灵芝", "高级★★★", 1, 200, 0, 0, 0, 0, 0, 80, 3, 0, 1, 99, 1, 1], ["卤肉 ", "初级★", 1, 80, 0, 0, 0, 0, 0, 30, 1, 0, 0, 99, 1, 0], ["小鸭脖", "初级★", 1, 100, 0, 0, 0, 0, 0, 35, 1, 0, 5, 99, 1, 1], ["小蓝瓶", "初级★", 1, 0, 50, 0, 0, 0, 0, 20, 1, 0, 0, 99, 1, 1], ["中蓝瓶", "中级★★", 1, 0, 100, 0, 0, 0, 0, 40, 2, 0, 0, 99, 1, 1], ["大蓝瓶", "高级★★★", 1, 0, 200, 0, 0, 0, 0, 80, 3, 0, 1, 99, 1, 1], ["金鳌 ", "高级★★★", 3, 0, 0, 5, 0, 0, 0, 200, 2, 0, 2, 99, 1, 1], ["野山椒", "中级★★", 3, 0, 0, 2, 0, 0, 0, 80, 2, 0, 1, 99, 1, 1], ["巨蜥肉", "高级★★★", 3, 0, 0, 0, 10, 0, 0, 100, 3, 0, 1, 99, 1, 1], ["龙血 ", "神级★★★★★", 3, 300, 100, 2, 2, 2, 0, 600, 5, 0, 1, 99, 0, 0], ["龙肉 ", "神级★★★★★", 3, 0, 0, 10, 20, 10, 0, 800, 5, 0, 1, 99, 0, 0], ["木剑 ", "初级★", 2, 0, 0, 10, 0, 0, 0, 50, 1, 0, 1, 1, 0, 0], ["木衣 ", "初级★", 2, 0, 0, 0, 10, 0, 0, 50, 1, 0, 1, 1, 0, 0], ["木鞋 ", "初级★", 2, 0, 0, 0, 0, 10, 0, 50, 1, 0, 1, 1, 0, 0], ["屠龙剑", "神级★★★★★", 2, 0, 0, 100, 0, 0, 0, 10000, 0, 0, 0, 1, 1, 1], ["龙皮铠甲", "神级★★★★★", 2, 0, 0, 0, 200, 0, 0, 10000, 0, 0, 0, 1, 1, 1], ["涅槃丹", "神级★★★★", 3, 100, 100, 100, 100, 20, 10, 5000, 1, 1, 0, 1, 1, 1] ]
扯一点我是用notepad++ 编辑的, 请安装 JsTool 插件处理json很好用
切入正题我们处理思路是, 在文件读取的时候, 去掉无效字符和注释字符. 主要code思路如下
// 从json文件中解析出最简json数据 static tstr_t _cjson_newfile(const char * path) { char c, n; tstr_t tstr; FILE * txt = fopen(path, "r"); if (NULL == txt) { CERR("fopen r %s is error!", path); return NULL; } //这里创建文本串对象 tstr = tstr_new(NULL); while ((c = fgetc(txt)) != EOF) { // step 1 : 处理字符串 if (c == '"') { tstr_append(tstr, c); for (n = c; ((c = fgetc(txt)) != EOF) && (c != '"' || n == '\'); n = c) tstr_append(tstr, c); if (EOF != c) tstr_append(tstr, c); continue; } // step 2 : 处理不可见特殊字符 if (c < '!') continue; if (c == '/') { // step 3 : 处理 // 解析到行末尾 n = fgetc(txt); if (n == '/') { while ((c = fgetc(txt)) != EOF && c != ' ') ; continue; } // step 4 : 处理 /* if (n == '*') { while ((c = fgetc(txt)) != EOF) { if (c == '*') { n = fgetc(txt); if (n == '/') break; ungetc(n, txt); } } continue; } ungetc(n, txt); } // step 5 : 合法数据直接保存 tstr_append(tstr, c); } fclose(txt);//很重要创建了就要释放,否则会出现隐藏的句柄bug return tstr; }
(请原谅, 这种一言不合就上源码的套路.) 主要分5类
1. "" 字符串, 不处理直接放入
2. 1-32 空字符直接舍弃, ['!' == 33, 可以查看ascii表]
3. // 注释直接 舍弃到 , 行尾
4. /* 舍弃到 */ 为止
5. 合法字符直接放入
附注ascii码表如下
挺不错的, 可以自行查查.
同样对于json内存串也是采用相同的处理思路
/* * 将 jstr中 不需要解析的字符串都去掉,并且纪念mini 比男的还平 * jstr : 待处理的json串 * : 返回压缩后的json串长度 */ static int _cjson_mini(char * jstr) { char c, *in = jstr, *to = jstr; while ((c = *to)) { // step 1 : 处理字符串 if (c == '"') { *in++ = c; while ((c = *++to) && (c != '"' || to[-1] == '\')) *in++ = c; if (c) { *in++ = c; ++to; } continue; } // step 2 : 处理不可见特殊字符 if (c < '!') { ++to; continue; } if (c == '/') { // step 3 : 处理 // 解析到行末尾 if (to[1] == '/') { while ((c = *++to) && c != ' ') ; continue; } // step 4 : 处理 /* if (to[1] == '*') { while ((c = *++to) && (c != '*' || to[1] != '/')) ; if (c) to += 2; continue; } } // step 5 : 合法数据直接保存 *in++ = *to++; } *in = '