C json实战引擎 3 , 最终完结部分帮衬函数澳门美高梅手机网站

先是名 ZoneAlarm Pro (Zone Labs集团出品的网络防火墙)
ZoneAlarm Pro
是壹款不错的网络防火墙软件,使用很简短,界面易于浏览,具有很强的反探测和预防网络侵略的工具。只要在安装时填入你的资料,安装完后再度开机,ZoneAlarm
就会活动运转,帮你执行职分。其重要功用模块包蕴:
◆获奖的防火墙,能够定义信任和不相信的互连网和区域,定制高级防火墙规则。
◆应用程控,控制应用程序是不是足以访问网络,提供劳务和出殡和埋葬邮件。
◆反间谍,爱护你的处理器免于间谍软件的重伤。(lrj六.x 版新增)
◆反病毒软件监察和控制,监控你的微处理器是不是安装了反病毒软件及是还是不是为新型的病毒定义。
◆邮件尊敬,珍贵总结机免受邮件恶意代码和病毒的勒迫。
◆隐秘爱慕,能够操纵 Cookies,过滤广告,幸免恶意的运动代码的威吓。
◆ID锁,爱护敏感数据和隐衷数据不被窃取和出殡和埋葬。
◆警报和日志,记录系统安全活动日志并提醒安全情形。
下载网站:
ZoneAlarm Pro v6.5.722.000
http://www.crsky.com/soft/1602.html
Code: hh11s-pv5cu-batbk-1mvdqe-md0gc0
ZoneAlarm Pro v6.1.737 汉化版
http://www./***.com/Software/Catalog183/994.html
Code:hh11s-pv5cu-batbk-1mvdqe-md0gc0
ZoneAlarm Pro v6.5.731.000 正式版
http://www.51ct.cn/downinfo/374.html
设置系列号:FA7壹F8九8
LGYTR-G5UKR-XH8LH-ROCXC
设置连串号:01742288
LMLTK-XT5RC-XHVML-ROE4W.
ZoneAlarm Pro 6.0.6陆7 汉化注册标准版 免费版
http://www.okget.com/Soft/Soft_981.htm
Code:hh11s-pv5cu-batbk-1mvdqe-md0gc0

引言

第二名 Outpost Firewall Pro 防火墙
Agnitum 公司是一家高质素的有限帮衬软体开发商,其 Outpost Firewall PRO 及
Outpost Office Firewall 能够为个体电脑及办公室网路提供必须的 Internet
网路爱护 , Agnitum Outpost Firewall 是一款短小精悍的互联网防火墙软体,
它的功力是同类 PC 软体中最强的。 Outpost Firewall
是3个整合各种防火墙功能的出品, 效用包涵广告和图纸过滤、 内容过滤、
电子邮件附件过滤等, 能够预防来自 Internet 的网络攻击、 浏览器攻击、
後门程式、 窃密软体、 广告软体和任何的互联网勒迫。
该软体不需配备就可应用, 那对於许多新手来说, 更简便易用。
对於壹般用户而言, Outpost Firewall 所进入的情节感应指示,
在输入资料时更能获得理想的维护效能,
因为不少时防火墙失效是因为用户设定不当, 当您设定 Outpost Firewall 时,
Smart Advisor 效用会对新程式及数据沟通发出提问,
及教你什么设定防火墙规则, 正确的答应难题可给您最佳的保安。
抱有反间谍软体功效 ,合营其机动开发的反木马程式 Tauscan
软体模组,令黑客无从动手。 面对地位盗窃的胁迫, Outpost Firewall 加入 ID
封锁功用,利用拦截及不一致清单协作字串过滤,有关心重视要的地位数据及敏感资料,例如信用卡数字、登入资料及密码、hpwsj人名及地址等资料,将不会由此即时通讯软体、电子邮件等败露给黑客
,有关设定也很便宜。其它别的假冒的通信请求及未经授权的有线网路连接请求也会被拒绝
,盗用宽频网路的题材可得以解决。
在扫描速度方面, Outpost Firewall 较 Norton 或 ZoneAlarm
等防火墙更佳。
下载网站:
Outpost Firewall Pro v三.5一.74捌.641玖 (46二) 官方简体中文版
http://www.51ct.cn/downinfo/619.html

  大学读的是一个极流行的科班, 学了4年的嬉戏竞赛. 可惜没学好. 但认真过, 比做什么都认真. 见证了 
……

Single-User License:
0l9O/uXM+WioBd3Wq+zlAISRa3uTOxL0MRHJZ
tTh7CDCXAOCz0S+CJcJjjYhhciK8UZuWpFZRL
Ac2+ZZIOQL17+Bp9CW/fdolTecZU1XMYGosXg
b8r2SBRX9iixwpinjHZL89QXR8/6aK2900alx
8fuhdWg++CIDEQ3ltlnSJNl316seBWx4X

打客车全体游戏人物中 分享一人最热衷 的

Family License:
04JfUgKnwExHNiSuE5PDlCN81ANawtSLbCOVcA
y8XBp1/DbV4iQLkeStXaB4L7FJx9c46nO+V+j8
oFMgh3U5DaNA/0HNfScpFnXwTU/rDCEyn/N9u3
umYB20TkWSc2CQjGXMWgKMa5Ovh0e5q7Fkx0Oq
FRsj37gO55dJOqOLyM3PH5TmQLo+Otw=

  澳门美高梅手机网站 1

Agnitum Outpost Firewall Pro 三.5一.74捌.641玖 (46二) 多国语言注册免费版
http://www.okget.com/Soft/Soft_191.htm
Agnitum Outpost Firewall Pro(专业级防火墙) v三.0 更软件
http://www./***.com/Software/Catalog183/2591.html
Outpost Firewall 防火牆3.5
http://www.version-2.com/products/?product_id=6&id=45

    
    “I’ve been alone for 十 thousand years. 作者孤单了一万年。”

第三名 Norton Personal Firewall
华语简称Norton个人民防空火墙
,人所共知的symantec集团出品,是一款智能型防火墙,可确定保障电脑的安全,提供多层防御机制,可活动<拦截侵略行为,能够控制全体传入和扩散的联网通信,防止黑客和隐秘威逼,保养私有情报安全。不仅是效果齐备的防火墙,更提供凌犯防护与隐衷权控管的效用。Norton个人民防空火墙结合了那么些成效,使用简单,安装后立即拥有强劲的警务装备能力。
Norton Personal Firewall 200陆 是Norton Internet Security 200陆组件。安装前请仔细阅读表达。
下载网站:
Norton Personal Firewall 2006 v玖.0
(最新智能型防火墙)能分享到86玖天乐趣。
http://www.51ct.cn/downinfo/992.html
KEY:JCRCD-VVM6R-73WMV-M33J3-4VV7P

    

Norton Personal Firewall 2005
http://www.crsky.com/soft/4134.html

    “What I may be,whatever I may become in this world,know that I
will always look out of you,Tyrande.
无论自个儿做了什么样,无论自己成为啥样体统,笔者会永远关心你的,泰兰德。”

第四名 Norman Personal Firewall
1款能够的私人住房防火墙,有针对性电邮系统及信息组的防毒作用,检查电邮附件时若觉察电邮软件有异动,就会即时禁止,对商厦网络环境中最易被侵犯的电邮伺服器提供更加大的保证。更新快人一步
,特别游客快车扫描引擎 .SSB扫描成效,管理设定不难,通过决定网络连接、Active-Xs、Java-VB-Scripts、Java
Applets、cookies、共享等来决定安全,能够IP过滤,防止特罗伊木马入侵
下载网站:
Norman Personal Firewall v1.4二 英文免费版
http://www.crsky.com/soft/5459.html
Norman Personal Firewall v1.42 特别版
http://www.doocoo.net/Software/Catalog411/10381.html
Norman Personal Firewall v1.4二私有(官方简中版附破解)
http://www.cmput.com/myspace.aspx?username=toysec

 

第五名 SurfSecret Personal Firewall
一款功效超强的互联网安全工具,提供多个级别尊崇
* 火急防护上锁效率。
* 自订上锁条件 – 荧屏保护程序运行时,可能定时上锁。
* 过滤器设定Smart – 能够钦命允许哪些 IP 透过哪个 Port
联机到您的处理器。
* 援助 IP 地址范围、IP 地址屏蔽。
* 能够在封包被堵住后产生提示,并且自动计次。
* 纪录最终12个体协会同到本机的 IP.lrj
下载网站:
SurfSecret Personal Firewall v3.0
http://www.crsky.com/soft/6723.html
SurfSecret Personal Firewall v3.0 注册机
http://soft.winzheng.com/SoftView/SoftView_26165.htm

前言

第六名 McAfee Personal Firewall Plus (卖咖啡)
McAfee公司的三个绝妙的村办防火墙软件,是依照ConSeal Private Desktop,
Signal 9 Solutions
的收获的国际认证个人民防空火墙软件包。它能够维护你免受来自Internet的黑客和木马程序等攻击。它的性状是:保护个人音讯、即时报警、详细事件记录、阻塞特定的互连网系统、多层安全、2四小时自动更新,还有正是整合了hackerwatch.com的能源,使得你能查看详细的抨击音讯。
该软件在第1遍安装到位后将自行弹出挂号界面,您能够立即报了名或在之后手动更新时登记。您只需利用有效邮箱和密码(无需邮箱真实密码)来创立升级账号,该软件系统将依照你的注册账号进行机动或手动升级,并且不定期的运用该账号对您的软件重新校验。
您能够随时通过点击托盘处的“更新”来手动更新软件,在产出的页面输入框中输入您的账号,系统将机关运行进步!
下载网站:
McAfee Personal Firewall Plus 二零零五 七.一.11三 简体普通话版 免费版
http://www.okget.com/Soft/Soft_2902.htm
McAfee Personal Firewall Plus 2006 简体普通话尤其版
http://www.51ct.cn/downinfo/450.html
McAfee2006 官方Infiniti制简体普通话版
http://www.51ct.cn/downinfo/1795.html
McAfee Personal firewall v7.1 最新汉化!
http://www.crsky.com/soft/559.html
McAfee Personal Firewall Plus 200陆 简体汉语 自由软件
http://soft.winzheng.com/SoftView/SoftView_29404.htm

  上一回 写了两篇 关于 C json 引擎 解析和 构造内容

第七名 BullGuard
反病毒和木马的工具!他得以周到拥戴你的微处理器免受病毒的侵凌!不论病毒是经过Email,浏览器,或然是像KaZaA那样的P二P软件和聊天工具,他都足以圆满拦截!

  C json实战引擎 壹 ,
完结解析部分

BullGuard 6.1
http://www.onlinedown.net/soft/22343.htm
http://www.ddowng.com/softdown/23548.html
http://download.it168.com/08/0804/2270/2270_4.shtml
BullGuard V6.0 绿色版!
http://www.cnbbs.us/read-htm-tid-16871-page-e-fpage-39.html

  C json实战引擎 贰 ,
达成结构部分

第八名 Sygate Personal Firewall Pro
即便以前的Sybergen Secure
Desktop,程序功效强大,能够随心所欲调节安全级别,从全无到最高,适合于那么些互联网中的单机用户来严防凌犯者非法进入系统。作为三个依照主机的消除方案,该软件提供了多层保障的防火墙安全环境,能够使得地预防入侵者和黑客的侵犯。与真的的防火墙差别的是,Sygate
Personal Firewall
能够从系统内部开始展览维护,并且能够在后台不间断地运作。其它,该软件还提供有安全访问和访问监视成效,并可向你提供具有用户的运动报告,当检查测试到侵犯和不当的行使后,能够立即发出警报。
Sygate Personal Firewall Pro V5.6.2828
http://www.duigou.cn/soft/245/2006/2006040222786.html
Sygate Personal Firewall Pro 伍.5.2710 汉化注册版 免费版
http://www.okget.com/Soft/Soft_2059.htm

    结合地点加上圈套前那篇, 一个高功用用的 cjson 引擎就诞生了.

第九名 Injoy Firewall
是一款国内很少人清楚的强力防火墙,界面帅气专业,拥有壹些生活费防火墙程序软件研讨所未有的增加期服用务器的功力,如远程监察和控制桌面条和凌犯珍重。防火墙尊敬质量优秀,国内网址少有下载。
InJoy Firewall 三.0 专职能試用版
http://www.cwt.idv.tw/modules.ph … iewtopic&t=6777
InJoy Firewall 3
http://cn.shareware-download.org/injoy-firewall-i29118.php

  

第十名 BlackICE PC Protection
ISS安全集团出品的壹款名牌的侵犯检查测试系统,拥有强大的检验,分析以及防范效率,系统财富占用率极少,而且很不难选拔,可以侦查出何人在扫你的端口,在它们进攻我们的微处理器此前拦截,爱惜咱们的处理器不受欺害,能够收集入欺者的IP地址、计算机名-互连网体系地址、硬件地址-MAC地址,有日记供大家查阅!作为个体互连网防火墙来说,相对是您的首要选拔!
BlackICE PC
Protection是1款强大的警务装备违规打扰及防火墙工具。该软件通过分析进出电脑的功率信号,并用该功率信号建立自由的防火墙以体贴总括机。它可避防患超过5/10项目标不法打扰,并得以服从须要自定义相关安装等。lrj
,BlackICE PC Protection
的三.陆版包含新的组成协议分析模块九(PAM),支持程序级协议分析和7层协议侦测技术,还进步了APM的可用性和修复错误,该版本软件更易于使用.
下载网址:
BlackICE 三.六 cpa 汉化注册版 免费版
http://www.okget.com/Soft/Soft_708.htm
http://www.superdown.com/soft/17117.htm
BlackICE PC Protection v3.6 特别版
http://www.hao3515.com/soft/11/69/2006/04/29/200604292755.html
name:http://www.hao3515.com/
sn:2837490-RS-A46B7
布莱克ICE 三.陆 cpa 汉化注册版 免费版
注册码: 1677790-rs-a4532
http://www.okget.com/Soft/Soft_708.htm
ISS BlackICE PC Protection v3.6 cno 注册机
http://www.down550.com/soft/4870.html

  后天, 分享那篇, 至少可以让大家, 学到简单深拷贝. 壹些布局技巧. 还有正是cjson的相助函数使用!

第10一名名 Kaspersky Anti-Hacker
Kaspersky Anti-哈克er 是Kaspersky
公司出品的壹款特别非凡的网络安全防火墙!和名扬四海的杀毒软件
AVP是同一个供销合作社的创作!珍贵你的微处理器不被黑客攻击和侵犯,全方位爱戴你的数额安全!全体网络资料存取的动作都会经过它对你发出提醒,存取动作是或不是放行,都由你来支配,可以抵挡来自于个中网络或网际网络的黑客攻击!
内附注册文件,能够从安装之日起运用1切一年。使用密钥文件有三种办法,壹是在设置英文版添加密钥,2是将密钥文件复制到
X:\Program Files\Common Files\Kaspersky Lab 目录下,此处 X
为设置操作系统的分区。
下载网站:
卡Bath基防火墙『Kaspersky Anti-哈克er』 v一.90.40 正式授权版
http://www.51ct.cn/downinfo/101.html
Kaspersky Anti-哈克er 卡Bath基防火墙 V一.九叁.七 Final 淡紫白版
http://www./***.com/Software/Catalog183/4880.html
卡Bath基反击黑社会客防火墙v一.八.180 免安装铁黑优化版
http://soft.yiiu.com/Software/Catalog91/1118.html

壹如既往先分享三个函数 封装 开首.  

/*
* 这个代码是 对 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 各类. 前面为了统1写了2个.

其中 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 接口中 1个 内部错误 日志宏. sclog.h 那一个日志记录类, 也很不错. 前边博文中

  C 基础框架开发

最后那有个别 讲解了 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!='\n');
        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 = '\0';
    return jstr;
}

思路是 先去掉空格字符, 后边去掉 // 和 /* */ 注释内容. 再对此
“” 包裹的字符串特殊处理. 其它字符维持原状 . 当中 sh_isspace 宏设计

如下

/*
 * c 如果是空白字符返回 true, 否则返回false
 * c : 必须是 int 值,最好是 char 范围
 */
#define sh_isspace(c) \
    ((c==' ')||(c>='\t'&&c<='\r'))

思路也很巧妙. 都以办事总计. 不用谢.

还有一个 营造数组对象代码

/*
 * 按照类型,创建 对映类型的数组 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        : 数组中元素长度
 *            : 返回创建的数组对象
 */
cjson_t 
cjson_newtypearray(int type, const void* array, int len)
{
    int i;
    cjson_t n = NULL, p = NULL, a;
    // _DEBUG 模式下简单检测一下
    DEBUG_CODE({
        if(type < _CJSON_FALSE || type > _CJSON_STRING || len <=0){
            SL_FATAL("check param is error! type = %d, len = %d.", type, len);
            return NULL;
        }
    });

    // 这里是实际执行代码
    a = cjson_newarray();
    for(i=0; i<len; ++i){
        switch(type){
        case _CJSON_NULL: n = cjson_newnull(); break;
        case _CJSON_FALSE: n = cjson_newbool(array? ((char*)array)[i] : 0); break;
        case _CJSON_TRUE: n = cjson_newbool(array? ((char*)array)[i] : 1); break;
        case _CJSON_NUMBER: n = cjson_newnumber(((double*)array)[i]); break;
        case _CJSON_STRING: n = cjson_newstring(((char**)array)[i]);break;
        }
        if(i){ //有你更好
            p->next = n;
            n->prev = p;
        }
        else
            a->child = n;
        p = n;
    }
    return a;
}

其中

    cjson_t n = NULL, p = NULL, a;

是为了免除编写翻译器警告, 未有定义就使用未开首化值. 对于里边创制代码都以 普通的 分类型搞. 非常大白话.

对于 对象 分离代码如下

/*
 * 在object json 中分离 key 的项出去
 * object    : 待分离的对象主体内容
 * key        : 关联的键
 *            : 返回分离的 object中 key的项json_t
 */
cjson_t 
cjson_detachobject(cjson_t object, const char* key)
{
    cjson_t c;
    DEBUG_CODE({
        if(!object || !object->child || !key || !*key){
            SL_WARNING("check param is object:%p, key:%s.", object, key);
            return NULL;
        }
    });

    for(c=object->child; c && str_icmp(c->key, key); c=c->next)
        ;
    if(!c) {
        SL_WARNING("check param key:%s => vlaue is empty.", key);
        return NULL;
    }
    if(c->prev)
        c->prev->next = c->next;
    if(c->next)
        c->next->prev = c->prev;
    if(c == object->child)
        object->child = c->next;
    c->prev = c->next = NULL;
    return c;
}

首假若寻觅, 查找到了 从优异链表中上传这么些指标,重新构建链接关系. 当中 str_icmp 在眼下分析过
, 很抢眼

/*
 * 这是个不区分大小写的比较函数
 * ls        : 左边比较字符串
 * rs        : 右边比较字符串
 *            : 返回 ls>rs => >0 ; ls = rs => 0 ; ls<rs => <0
 */
int 
str_icmp(const char* ls, const char* rs)
{
    int l, r;
    if(!ls || !rs)
        return (int)ls - (int)rs;

    do {
        if((l=*ls++)>='a' && l<='z')
            l -= 'a' - 'A';
        if((r=*rs++)>='a' && r<='z')
            r -= 'a' - 'A';
    } while(l && l==r);

    return l-r;
}

末尾分享 1个 常用函数
, 从json文件中得到cjson_t 对象. 再扯一点, 多写代码,后边纯熟后你会发觉, 代码正是最好的注释.

/*
 *    将json文件解析成json内容返回, 需要自己调用 cjson_delete
 * jpath    : json串路径
 *            : 返回处理好的cjson_t 内容,失败返回NULL
 */
cjson_t 
cjson_dofile(char* jpath)
{
    cjson_t root;
    tstring tstr = file_malloc_readend(jpath);
    if(!tstr){
        SL_WARNING("readend jpath:%s is error!", jpath);
        return NULL;
    }
    root = cjson_parse(tstr->str);
    tstring_destroy(&tstr);
    return root;
}

地点关于 tstring 设计 具体看上面博文.

  C 封装一个通用链表 和
二个简短字符串开发库

到此地 关于cjson库 补充的 支持函数首要设计就结束了.

 

三. cjson 定稿代码 总显得

cjson.h

澳门美高梅手机网站 2澳门美高梅手机网站 3

#ifndef _H_CJSON
#define _H_CJSON

// json 中几种数据类型定义 , 对于C而言 最难的是看不见源码,而不是api复杂, 更不是业务复杂
#define _CJSON_FALSE    (0)
#define _CJSON_TRUE        (1)
#define _CJSON_NULL        (2)
#define _CJSON_NUMBER    (3)
#define _CJSON_STRING    (4)
#define _CJSON_ARRAY    (5)
#define _CJSON_OBJECT    (6)

#define _CJSON_ISREF    (256)        //set 时候用如果是引用就不释放了
#define _CJSON_ISCONST    (512)        //set时候用, 如果是const char* 就不释放了

struct cjson {
    struct cjson *next, *prev;
    struct cjson *child; // type == _CJSON_ARRAY or type == _CJSON_OBJECT 那么 child 就不为空

    int type;
    char *key;    // json内容那块的 key名称     
    char *vs;    // type == _CJSON_STRING, 是一个字符串     
    double vd;  // type == _CJSON_NUMBER, 是一个num值, ((int)c->vd) 转成int 或 bool
};

//定义cjson_t json类型
typedef struct cjson* cjson_t;

/*
 * 这个宏,协助我们得到 int 值 或 bool 值 
 * 
 * item : 待处理的目标cjson_t结点
 */
#define cjson_getint(item) \
    ((int)((item)->vd))

/*
 *  删除json串内容  
 * c        : 待释放json_t串内容
 */
extern void cjson_delete(cjson_t* pc);

/*
 * 对json字符串解析返回解析后的结果
 * jstr        : 待解析的字符串
 */
extern cjson_t cjson_parse(const char* jstr);

/*
 * 根据 item当前结点的 next 一直寻找到 NULL, 返回个数
 *推荐是数组使用
 * array    : 待处理的cjson_t数组对象
 *            : 返回这个数组中长度
 */
extern int cjson_getlen(cjson_t array);

/*
 * 根据索引得到这个数组中对象
 * array    : 数组对象
 * idx        : 查找的索引 必须 [0,cjson_getlen(array)) 范围内
 *            : 返回查找到的当前对象
 */
extern cjson_t cjson_getarray(cjson_t array, int idx);

/*
 * 根据key得到这个对象 相应位置的值
 * object    : 待处理对象中值
 * key        : 寻找的key
 *            : 返回 查找 cjson_t 对象
 */
extern cjson_t cjson_getobject(cjson_t object, const char* key);


// --------------------------------- 下面是 cjson 输出部分的处理代码 -----------------------------------------

/*
 *  这里是将 cjson_t item 转换成字符串内容,需要自己free 
 * item        : cjson的具体结点
 *            : 返回生成的item的json串内容
 */
extern char* cjson_print(cjson_t item);

// --------------------------------- 下面是 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);

#endif // !_H_CJSON

View Code

 

cjson.c

澳门美高梅手机网站 4澳门美高梅手机网站 5

#include <cjson.h>
#include <schead.h>
#include <sclog.h>
#include <tstring.h>
#include <float.h>
#include <math.h>

// 删除cjson
static void __cjson_delete(cjson_t c)
{
    cjson_t next;
    while (c) {
        next = c->next;
        //递归删除儿子
        if (!(c->type & _CJSON_ISREF)) {
            if (c->child) //如果不是尾递归,那就先递归
                __cjson_delete(c->child);
            if (c->vs)
                free(c->vs);
        }
        else if (!(c->type & _CJSON_ISCONST) && c->key)
            free(c->key);
        free(c);
        c = next;
    }
}

/*
*  删除json串内容,最近老是受清华的老学生打击, 会起来的......
* c        : 待释放json_t串内容
*/
void 
cjson_delete(cjson_t* pc)
{
    if (!pc || !*pc)
        return;
    __cjson_delete(*pc);
    *pc = NULL;
}

//构造一个空 cjson 对象
static inline cjson_t __cjson_new(void)
{
    cjson_t c = calloc(1, sizeof(struct cjson));
    if (!c) {
        SL_FATAL("calloc sizeof struct cjson error!");
        exit(_RT_EM);
    }
    return c;
}

// 简化的代码段,用宏来简化代码书写 , 16进制处理
#define __parse_hex4_code(c, h) \
    if (c >= '0' && c <= '9') \
        h += c - '0'; \
    else if (c >= 'A' && c <= 'F') \
        h += 10 + c - 'A'; \
    else if (c >= 'a' && c <= 'z') \
        h += 10 + c - 'F'; \
    else \
        return 0

// 等到unicode char代码
static unsigned __parse_hex4(const char* str)
{
    unsigned h = 0;
    char c = *str;
    //第一轮
    __parse_hex4_code(c, h);
    h <<= 4;
    c = *++str;
    //第二轮
    __parse_hex4_code(c, h);
    h <<= 4;
    c = *++str;
    //第三轮
    __parse_hex4_code(c, h);
    h <<= 4;
    c = *++str;
    //第四轮
    __parse_hex4_code(c, h);

    return h;
}

// 分析字符串的子函数,
static const char* __parse_string(cjson_t item, const char* str)
{
    static unsigned char __marks[] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
    const char *ptr;
    char *nptr, *out;
    int len;
    char c;
    unsigned uc, nuc;

    if (*str != '\"') { // 检查是否是字符串内容
        SL_WARNING("need \\\" str => %s error!", str);
        return NULL;
    }

    for (ptr = str + 1, len = 0; (c = *ptr++) != '\"' && c; ++len)
        if (c == '\\') //跳过转义字符
            ++ptr;
    if (!(out = malloc(len + 1))) {
        SL_FATAL("malloc %d size error!", len + 1);
        return NULL;
    }
    // 这里复制拷贝内容
    for (ptr = str + 1, nptr = out; (c = *ptr) != '\"' && c; ++ptr) {
        if (c != '\\') {
            *nptr++ = c;
            continue;
        }
        // 处理转义字符
        switch ((c = *++ptr)) {
        case 'b': *nptr++ = '\b'; break;
        case 'f': *nptr++ = '\f'; break;
        case 'n': *nptr++ = '\n'; break;
        case 'r': *nptr++ = '\r'; break;
        case 't': *nptr++ = '\t'; break;
        case 'u': // 将utf16 => utf8, 专门的utf处理代码
            uc = __parse_hex4(ptr + 1);
            ptr += 4;//跳过后面四个字符, unicode
            if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0)    break;    /* check for invalid.    */

            if (uc >= 0xD800 && uc <= 0xDBFF)    /* UTF16 surrogate pairs.    */
            {
                if (ptr[1] != '\\' || ptr[2] != 'u')    
                    break;    /* missing second-half of surrogate.    */
                nuc = __parse_hex4(ptr + 3);
                ptr += 6;
                if (nuc < 0xDC00 || nuc>0xDFFF)        
                    break;    /* invalid second-half of surrogate.    */
                uc = 0x10000 + (((uc & 0x3FF) << 10) | (nuc & 0x3FF));
            }

            len = 4;
            if (uc < 0x80) 
                len = 1;
            else if (uc < 0x800) 
                len = 2;
            else if (uc < 0x10000) 
                len = 3; 
            nptr += len;

            switch (len) {
            case 4: *--nptr = ((uc | 0x80) & 0xBF); uc >>= 6;
            case 3: *--nptr = ((uc | 0x80) & 0xBF); uc >>= 6;
            case 2: *--nptr = ((uc | 0x80) & 0xBF); uc >>= 6;
            case 1: *--nptr = (uc | __marks[len]);
            }
            nptr += len;
            break;
        default: *nptr++ = c;
        }
    }

    *nptr = '\0';
    if (c == '\"')
        ++ptr;
    item->vs = out;
    item->type = _CJSON_STRING;
    return ptr;
}

// 分析数值的子函数,写的可以
static const char* __parse_number(cjson_t item, const char* str)
{
    double n = 0.0, ns = 1.0, nd = 0.0; //n把偶才能值, ns表示开始正负, 负为-1, nd 表示小数后面位数
    int e = 0, es = 1; //e表示后面指数, es表示 指数的正负,负为-1
    char c;

    if ((c = *str) == '-' || c == '+') {
        ns = c == '-' ? -1.0 : 1.0; //正负号检测, 1表示负数
        ++str;
    }
    //处理整数部分
    for (c = *str; c >= '0' && c <= '9'; c = *++str)
        n = n * 10 + c - '0';
    if (c == '.')
        for (; (c = *++str) >= '0' && c <= '9'; --nd)
            n = n * 10 + c - '0';

    // 处理科学计数法
    if (c == 'e' || c == 'E') {
        if ((c = *++str) == '+') //处理指数部分
            ++str;
        else if (c == '-')
            es = -1, ++str;
        for (; (c = *str) >= '0' && c <= '9'; ++str)
            e = e * 10 + c - '0';
    }

    //返回最终结果 number = +/- number.fraction * 10^+/- exponent
    n = ns * n * pow(10.0, nd + es * e);
    item->vd = n;
    item->type = _CJSON_NUMBER;
    return str;
}

// 跳过不需要处理的字符
static const char* __skip(const char* in)
{
    if (in && *in && *in <= 32) {
        unsigned char c;
        while ((c = *++in) && c <= 32)
            ;
    }
    return in;
}

// 递归下降分析 需要声明这些函数
static const char* __parse_array(cjson_t item, const char* str);
static const char* __parse_object(cjson_t item, const char* str);
static const char* __parse_value(cjson_t item, const char* value);

// 分析数组的子函数, 采用递归下降分析
static const char* __parse_array(cjson_t item, const char* str)
{
    cjson_t child;
    if (*str != '[') {
        SL_WARNING("array str error start: %s.", str);
        return NULL;
    }

    item->type = _CJSON_ARRAY;
    str = __skip(str + 1);
    if (*str == ']') // 低估提前结束
        return str + 1;

    item->child = child = __cjson_new();
    str = __skip(__parse_value(child, str));
    if (!str) {//解析失败 直接返回
        SL_WARNING("array str error e n d one: %s.", str);
        return NULL;
    }
    while (*str == ',') {
        cjson_t nitem = __cjson_new();
        child->next = nitem;
        nitem->prev = child;
        child = nitem;
        str = __skip(__parse_value(child, __skip(str + 1)));
        if (!str) {// 写代码是一件很爽的事
            SL_WARNING("array str error e n d two: %s.", str);
            return NULL;
        }
    }

    if (*str != ']') {
        SL_WARNING("array str error e n d: %s.", str);
        return NULL;
    }
    return str + 1; // 跳过']'
}

// 分析对象的子函数
static const char* __parse_object(cjson_t item, const char* str)
{
    cjson_t child;
    if (*str != '{') {
        SL_WARNING("object str error start: %s.", str);
        return NULL;
    }

    item->type = _CJSON_OBJECT;
    str = __skip(str + 1);
    if (*str == '}')
        return str + 1;

    //处理结点, 开始读取一个 key
    item->child = child = __cjson_new();
    str = __skip(__parse_string(child, str));
    if (!str || *str != ':') {
        SL_WARNING("__skip __parse_string is error : %s!", str);
        return NULL;
    }
    child->key = child->vs;
    child->vs = NULL;

    str = __skip(__parse_value(child, __skip(str + 1)));
    if (!str) {
        SL_WARNING("__skip __parse_string is error 2!");
        return NULL;
    }

    // 递归解析
    while (*str == ',') {
        cjson_t nitem = __cjson_new();
        child->next = nitem;
        nitem->prev = child;
        child = nitem;
        str = __skip(__parse_string(child, __skip(str + 1)));
        if (!str || *str != ':'){
            SL_WARNING("__parse_string need name or no equal ':' %s.", str);
            return NULL;
        }
        child->key = child->vs;
        child->vs = NULL;

        str = __skip(__parse_value(child, __skip(str+1)));
        if (!str) {
            SL_WARNING("__parse_string need item two ':' %s.", str);
            return NULL;
        }
    }

    if (*str != '}') {
        SL_WARNING("object str error e n d: %s.", str);
        return NULL;
    }
    return str + 1;
}

// 将value 转换塞入 item json值中一部分
static const char* __parse_value(cjson_t item, const char* value)
{
    char c; 
    if ((value) && (c = *value)) {
        switch (c) {
            // n = null, f = false, t = true
        case 'n' : return item->type = _CJSON_NULL, value + 4;
        case 'f' : return item->type = _CJSON_FALSE, value + 5;
        case 't' : return item->type = _CJSON_TRUE, item->vd = 1.0, value + 4;
        case '\"': return __parse_string(item, value);
        case '0' : case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
        case '+' : case '-': return __parse_number(item, value);
        case '[' : return __parse_array(item, value);
        case '{' : return __parse_object(item, value);
        }
    }
    // 循环到这里是意外 数据
    SL_WARNING("params value = %s!", value);
    return NULL;
}

/*
* 对json字符串解析返回解析后的结果
* jstr        : 待解析的字符串
*            : 返回解析好的字符串内容
*/
cjson_t 
cjson_parse(const char* jstr)
{
    cjson_t c = __cjson_new();
    const char* end;

    if (!(end = __parse_value(c, __skip(jstr)))) {
        SL_WARNING("__parse_value params end = %s!", end);
        cjson_delete(&c);
        return NULL;
    }

    //这里是否检测 返回测试数据
    return c;
}

/*
* 根据 item当前结点的 next 一直寻找到 NULL, 返回个数
*推荐是数组使用
* array    : 待处理的cjson_t数组对象
*            : 返回这个数组中长度
*/
int 
cjson_getlen(cjson_t array)
{
    int len = 0;
    if (array)
        for (array = array->child; array; array = array->next)
            ++len;

    return len;
}

/*
* 根据索引得到这个数组中对象
* array    : 数组对象
* idx        : 查找的索引 必须 [0,cjson_getlen(array)) 范围内
*            : 返回查找到的当前对象
*/
cjson_t 
cjson_getarray(cjson_t array, int idx)
{
    cjson_t c;
    DEBUG_CODE({
        if (!array || idx < 0) {
            SL_FATAL("array:%p, idx=%d params is error!", array, idx);
            return NULL;
        }
    });

    for (c = array->child; c&&idx > 0; c = c->next)
        --idx;

    return c;
}

/*
* 根据key得到这个对象 相应位置的值
* object    : 待处理对象中值
* key        : 寻找的key
*            : 返回 查找 cjson_t 对象
*/
cjson_t 
cjson_getobject(cjson_t object, const char* key)
{
    cjson_t c;
    DEBUG_CODE({
        if (!object || !key || !*key) {
            SL_FATAL("object:%p, key=%s params is error!", object, key);
            return NULL;
        }
    });

    for (c = object->child; c && str_icmp(key, c->key); c = c->next)
        ;

    return c;
}

// --------------------------------- 下面是 cjson 输出部分的处理代码 -----------------------------------------

// 2^n>=x , n是最小的整数
static int __pow2gt(int x)
{
    --x;
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return x + 1;
}

/*
 *     这里使用 tstring 结构 size 这里表示 字符串总大小,没有变化
 * len 表示当前字符串的字符串起始偏移量 即 tstring->str + tstring->len 起始的
 */
static char* __ensure(tstring p, int need)
{
    char* nbuf;
    int nsize;
    if (!p || !p->str) {
        SL_FATAL("p:%p need:%p is error!", p, need);
        return NULL;
    }
    need += p->len;
    if (need <= p->size) //内存够用直接返回结果
        return p->str + p->len;
    nsize = __pow2gt(need);
    if ((nbuf = malloc(nsize*sizeof(char))) == NULL) {
        free(p->str);
        p->size = p->len = 0;
        p->str = NULL;
        SL_FATAL("malloc nsize = %d error!", nsize);
        return NULL;
    }
    //这里复制内容
    memcpy(nbuf, p->str, p->size);
    free(p->str);
    p->size = nsize;
    p->str = nbuf;
    return nbuf + p->len;
}

// 这里更新一下 当前字符串, 返回当前字符串的长度
inline static int __update(tstring p) 
{
    return (!p || !p->str) ? 0 : p->len + strlen(p->str+p->len);
}

// 将item 中值转换成字符串 保存到p中
static char* __print_number(cjson_t item, tstring p)
{
    char* str = NULL;
    double d = item->vd;
    int i = (int)d;

    if (d == 0) {  //普通0
        str = __ensure(p, 2);
        if (str)
            str[0] = '0', str[1] = '\0';
    }
    else if ((fabs(d - i)) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
        str = __ensure(p, 21); //int 值 
        if (str)
            sprintf(str, "%d", i);
    }
    else {
        str = __ensure(p, 64); //double值 
        if (str) {
            double nd = fabs(d); //得到正值开始比较
            if(fabs(floor(d) - d) <= DBL_EPSILON && nd < 1.0e60)
                sprintf(str, "%.0f", d);
            else if(nd < 1.0e-6 || nd > 1.0e9) //科学计数法
                sprintf(str, "%e", d);
            else
                sprintf(str, "%f", d);

        }
    }

    return str;
}

// 输出字符串内容
static char* __print_string(char* str, tstring p)
{
    const char* ptr;
    char *nptr, *out;
    int len = 0, flag = 0;
    unsigned char c;

    if (!str || !*str) { //最特殊情况,什么都没有 返回NULL
        out = __ensure(p, 3);
        if (!out)
            return NULL;
        out[0] = '\"', out[1] = '\"', out[2] = '\0';
        return out;
    }


    for (ptr = str; (c=*ptr); ++ptr)
        flag |= ((c > 0 && c < 32) || c == '\"' || c == '\\');

    if (!flag) {  //没有特殊字符直接处理结果
        len = ptr - str;
        out = __ensure(p,len + 3);
        if (!out)
            return NULL;
        nptr = out;
        *nptr++ = '\"';
        strcpy(nptr, str);
        nptr[len] = '\"';
        nptr[len + 1] = '\0';
        return out;
    }

    //处理 存在 "和转义字符内容
    for (ptr = str; (c = *ptr) && ++len; ++ptr) {
        if (strchr("\"\\\b\f\n\r\t", c))
            ++len;
        else if (c < 32) //隐藏字符的处理, 这里可以改
            len += 5;
    }

    if ((out = __ensure(p, len + 3)) == NULL)
        return NULL;
    //先添加 \"
    nptr = out;
    *nptr++ = '\"';
    for (ptr = str; (c = *ptr); ++ptr) {
        if (c > 31 && c != '\"' && c != '\\') {
            *nptr++ = c;
            continue;
        }
        *nptr++ = '\\';
        switch (c){
        case '\\':    *nptr++ = '\\';    break;
        case '\"':    *nptr++ = '\"';    break;
        case '\b':    *nptr++ = 'b';    break;
        case '\f':    *nptr++ = 'f';    break;
        case '\n':    *nptr++ = 'n';    break;
        case '\r':    *nptr++ = 'r';    break;
        case '\t':    *nptr++ = 't';    break;
        default: sprintf(nptr, "u%04x", c);nptr += 5;    /* 不可见字符 采用 4字节字符编码 */
        }
    }
    *nptr++ = '\"';
    *nptr = '\0';
    return out;
}

//这里是 递归下降 的函数声明处, 分别是处理值, 数组, object
static char* __print_value(cjson_t item, tstring p);
static char* __print_array(cjson_t item, tstring p);
static char* __print_object(cjson_t item, tstring p);

// 定义实现部分, 内部私有函数 认为 item 和 p都是存在的
static char* __print_value(cjson_t item, tstring p) 
{
    char* out = NULL;
    switch ((item->type) & UCHAR_MAX) { // 0xff
    case _CJSON_FALSE: if ((out = __ensure(p, 6))) strcpy(out, "false"); break;
    case _CJSON_TRUE: if ((out = __ensure(p, 5))) strcpy(out, "true"); break;
    case _CJSON_NULL: if ((out = __ensure(p, 5))) strcpy(out, "null"); break;
    case _CJSON_NUMBER:    out = __print_number(item, p); break;
    case _CJSON_STRING:    out = __print_string(item->vs, p); break;
    case _CJSON_ARRAY:    out = __print_array(item, p); break;
    case _CJSON_OBJECT:    out = __print_object(item, p); break;
    }

    return out;
}

// 同样 假定 item 和 p都是存在且不为NULL
static char* __print_array(cjson_t item, tstring p)
{
    char* ptr;
    cjson_t child = item->child;
    int ncut, i;
    // 得到孩子结点的深度
    for (ncut = 0; (child); child = child->child)
        ++ncut;
    if (!ncut) { //没有孩子结点 直接空数组返回结果
        char* out = NULL;
        if (!(out = __ensure(p, 3))) 
            strcpy(out, "[]");
        return out;
    }

    i = p->len;
    if (!(ptr = __ensure(p, 1)))
        return NULL;
    *ptr = '[';
    ++p->len;
    for (child = item->child; (child); child = child->next) {
        __print_value(child, p);
        p->len = __update(p);
        if (child->next) {
            if (!(ptr = __ensure(p, 2)))
                return NULL;
            *ptr++ = ',';
            *ptr = '\0';
            p->len += 1;
        }
    }
    if (!(ptr = __ensure(p, 2)))
        return NULL;
    *ptr++ = ']';
    *ptr = '\0';
    return p->str + i;

}

// 同样 假定 item 和 p都是存在且不为NULL, 相信这些代码是安全的
static char* __print_object(cjson_t item, tstring p)
{
    char* ptr;
    int i, ncut, len;
    cjson_t child = item->child;

    // 得到孩子结点的深度
    for (ncut = 0; child; child = child->child)
        ++ncut;
    if (!ncut) {
        char* out = NULL;
        if (!(out = __ensure(p, 3)))
            strcpy(out, "{}");
        return out;
    }

    i = p->len;
    if (!(ptr = __ensure(p, 2)))
        return NULL;
    *ptr++ = '{';
    *ptr -= '\0';
    p->len += 1;
    // 根据子结点 处理
    for (child = item->child; (child); child = child->next) {
        __print_string(child->key, p);
        p->len = __update(p);

        //加入一个冒号
        if (!(ptr = __ensure(p, 1)))
            return NULL;
        *ptr++ = ':';
        p->len += 1;

        //继续打印一个值
        __print_value(child, p);
        p->len = __update(p);

        //结算最后内容
        len = child->next ? 1 : 0;
        if ((ptr = __ensure(p, len + 1)) == NULL)
            return NULL;
        if (child->next)
            *ptr++ = ',';
        *ptr = '\0';
        p->len += len;
    }
    if (!(ptr = __ensure(p, 2)))
        return NULL;
    *ptr++ = '}';
    *ptr = '\0';
    return p->str + i;
}

#define _INT_CJONSTR    (256)
/*
*  这里是将 cjson_t item 转换成字符串内容,需要自己free
* item        : cjson的具体结点
*            : 返回生成的item的json串内容
*/
char* 
cjson_print(cjson_t item)
{
    struct tstring p;
    char* out;
    if ((!item) || !(p.str = malloc(sizeof(char)*_INT_CJONSTR))) {
        SL_FATAL("item:%p, p.str = malloc is error!", item);
        return NULL;
    }
    p.size = _INT_CJONSTR;
    p.len = 0;

    out = __print_value(item, &p); //从值处理开始, 返回最终结果
    if (out == NULL) {
        free(p.str);
        SL_FATAL("__print_value item:%p, p:%p is error!", item, &p);
        return NULL;
    }
    return realloc(out,strlen(out) + 1); // 体积变小 realloc返回一定成功
}

// --------------------------------- 下面是 cjson 输出部分的辅助代码 -----------------------------------------

/*
 * 创建一个bool的对象 b==0表示false,否则都是true, 需要自己释放 cjson_delete
 * b        : bool 值 最好是 _Bool
 *            : 返回 创建好的json 内容
 */
cjson_t 
cjson_newnull()
{
    cjson_t item = __cjson_new();
    item->type = _CJSON_NULL; 
    return item;
}

cjson_t 
cjson_newbool(int b)
{
    cjson_t item = __cjson_new();
    item->vd = item->type = b ? _CJSON_TRUE : _CJSON_FALSE; 
    return item;
}

cjson_t 
cjson_newnumber(double vd)
{
    cjson_t item = __cjson_new();
    item->type = _CJSON_NUMBER;
    item->vd = vd;
    return item;
}

cjson_t 
cjson_newstring(const char* vs)
{
    cjson_t item = __cjson_new();
    item->type = _CJSON_STRING;
    item->vs = str_dup(vs);
    return item;
}

cjson_t 
cjson_newarray(void)
{
    cjson_t item = __cjson_new();
    item->type = _CJSON_ARRAY;
    return item;
}

cjson_t 
cjson_newobject(void)
{
    cjson_t item = __cjson_new();
    item->type = _CJSON_OBJECT;
    return item;
}

/*
 * 按照类型,创建 对映类型的数组 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        : 数组中元素长度
 *            : 返回创建的数组对象
 */
cjson_t 
cjson_newtypearray(int type, const void* array, int len)
{
    int i;
    cjson_t n = NULL, p = NULL, a;
    // _DEBUG 模式下简单检测一下
    DEBUG_CODE({
        if(type < _CJSON_FALSE || type > _CJSON_STRING || len <=0){
            SL_FATAL("check param is error! type = %d, len = %d.", type, len);
            return NULL;
        }
    });

    // 这里是实际执行代码
    a = cjson_newarray();
    for(i=0; i<len; ++i){
        switch(type){
        case _CJSON_NULL: n = cjson_newnull(); break;
        case _CJSON_FALSE: n = cjson_newbool(array? ((char*)array)[i] : 0); break;
        case _CJSON_TRUE: n = cjson_newbool(array? ((char*)array)[i] : 1); break;
        case _CJSON_NUMBER: n = cjson_newnumber(((double*)array)[i]); break;
        case _CJSON_STRING: n = cjson_newstring(((char**)array)[i]);break;
        }
        if(i){ //有你更好
            p->next = n;
            n->prev = p;
        }
        else
            a->child = n;
        p = n;
    }
    return a;
}

/*
 * 将 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!='\n');
        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 = '\0';
    return jstr;
}

/*
 *    将json文件解析成json内容返回, 需要自己调用 cjson_delete
 * jpath    : json串路径
 *            : 返回处理好的cjson_t 内容,失败返回NULL
 */
cjson_t 
cjson_dofile(char* jpath)
{
    cjson_t root;
    tstring tstr = file_malloc_readend(jpath);
    if(!tstr){
        SL_WARNING("readend jpath:%s is error!", jpath);
        return NULL;
    }
    root = cjson_parse(tstr->str);
    tstring_destroy(&tstr);
    return root;
}

/*
 * 在array中分离第idx个索引项内容.
 * array    : 待处理的json_t 数组内容
 * idx        : 索引内容
 *            : 返回分离的json_t内容
 */
cjson_t 
cjson_detacharray(cjson_t array, int idx)
{
    cjson_t c;
    DEBUG_CODE({
        if(!array || idx<0){
            SL_WARNING("check param is array:%p, idx:%d.", array, idx);
            return NULL;
        }
    });

    for(c=array->child; idx>0 && c; c = c->next)
        --idx;
    if(c>0){
        SL_WARNING("check param is too dig idx:sub %d.", idx);
        return NULL;
    }
    //这里开始拼接了
    if(c->prev)
        c->prev->next = c->next;
    if(c->next)
        c->next->prev = c->prev;
    if(c == array->child)
        array->child = c->next;
    c->prev = c->next = NULL;
    return c;
}

/*
 * 在object json 中分离 key 的项出去
 * object    : 待分离的对象主体内容
 * key        : 关联的键
 *            : 返回分离的 object中 key的项json_t
 */
cjson_t 
cjson_detachobject(cjson_t object, const char* key)
{
    cjson_t c;
    DEBUG_CODE({
        if(!object || !object->child || !key || !*key){
            SL_WARNING("check param is object:%p, key:%s.", object, key);
            return NULL;
        }
    });

    for(c=object->child; c && str_icmp(c->key, key); c=c->next)
        ;
    if(!c) {
        SL_WARNING("check param key:%s => vlaue is empty.", key);
        return NULL;
    }
    if(c->prev)
        c->prev->next = c->next;
    if(c->next)
        c->next->prev = c->prev;
    if(c == object->child)
        object->child = c->next;
    c->prev = c->next = NULL;
    return c;
}

View Code

 

总的而言 下边代码 加上注释三个文件壹共
1100行左右,去掉注释应该在800行左右. 对于cjson库应该算非常小的了. 很合乎

读书,扩张或再优化.

 

四. 测试代码展示

  对于地点代码又写了三个测试 , 首先 测试的 json文件内容

firefighting_rule.json 内容如下

{     
"firefighting_rule":     
 {    
  "key1":   
   {  
    "id":1,
    "dungeon_id":40008,
    "level_contain":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],
    "active_time":[[1,"110000"],[4,"110000"],[5,"210000"]],
    "boss_ui_head":"UI_icon/IMG_ShiJieBoss_TouXiang.png",
    "activity_tag_icon":"IMG_GaiBan_HuoDong_ShiJieBoss_TuBiao.png",
    "activity_tag_word":"IMG_GaiBan_ZhuCheng_ShiJieBoss_TuBiao_MingZi.png",
    "activity_pic_json":"UI_HuoDong_ShiJieBoss.json",
    "jinbi_buff_icon":"UI_icon/IMG_WorldBoss_JinbiBuff_Atk.png",
    "jinbi_buff_damage":[[8,1000],[9,1000],[11,1000],[12,1000]],
    "jinbi_buff_price":10,
    "jinbi_buff_limit":999,
    "free_change":1,
    "refresh_price":20,
    "change_price":20,
    "show_hero_num":20 
   }  
 }    
}

 处理的辨析文件代码如下

#include <schead.h>
#include <sclog.h>
#include <cjson.h>

#define _STR_FILE "firefighting_rule.json"


/**
 * 这里 是解析 上面的json文件内容
 */
int main(int argc, char* argv[])
{
    INIT_PAUSE();
    // 开启日志记录功能
    sl_start();

    cjson_t rule = cjson_dofile(_STR_FILE);
    if (NULL == rule)
        CERR_EXIT("cjson_dofile " _STR_FILE " is error!");

    // 数据合法 这里开始得到一部分
    cjson_t firefighting_rule = cjson_detachobject(rule, "firefighting_rule");
    // 得到真正的内容
    cjson_t key1 = cjson_detachobject(firefighting_rule, "key1");

    //这里得到 key1 输出内容
    char* nkey = cjson_print(key1);
    if (NULL == nkey)
        CERR_EXIT("cjson_print key1 is error!");

    // 这里打印数据测试 
    puts(nkey);
    free(nkey);

    // 再简单测试一下 
    cjson_t id = cjson_getobject(key1, "id");
    printf("\nid = %d\n", cjson_getint(id));

    //得到数组对象 测试
    cjson_t level_contain = cjson_getobject(key1, "level_contain");
    printf("\ncount(level_contain) = %d\n", cjson_getlen(level_contain));

    cjson_delete(&key1);
    cjson_delete(&firefighting_rule);
    // rule 释放
    cjson_delete(&rule);

    return 0;
}

其普通话件结构是 测试文件在 根目录下 也许和 exe或 out同拔尖目录下. 最终测试结果如下

澳门美高梅手机网站 6

一切常常, 欢迎将以此cjson 库用在融洽 纯C的小项目中. 本身想怎么改就怎么改. 楼主不介意, 还是能帮你订制改. 

 

五. 下四个人作品展望

  C基础框架 付出的基本上了,下次再享受多个 csv文件分析内容库. 再结合一下框架 基本上用C开发小型 单机项目就没怎么难题了.

以往差 互连网库积累 和 图形库积累,图形库 很久贰个版本 内置了 glut 和 glew 后边舍弃了. 太庞大不好, 用起来不爽. 最近稳住正是

后端开发框架. 最终总括 对于自个儿那种农民工 开发库的经历便是,

  有怎么着想法你就去做, 有何错就应声改. 有比自个儿越来越好,立即学习 立异.

再扯一点, 学编制程序真的未有高级中学的做的难,更未曾高校学的剧情深, 真的一个很傻的事情, 薪金能够, 操作机械化. 值得深搞. 

 

后记

  错误是难免, 有人建议来或本人意识了,一定修改!  有始有终 …

澳门美高梅手机网站 7

“ Monster? Is that what you think of me? I was… always care for
you! Tyrand! I thought only to prove this word in this… my power! ”

  (“怪物?你便是这样看本人的?泰兰德?作者从来在乎你!小编只想透过友好的能力来能印证那一点。“)

 

Intro: The Dawn
http://music.163.com/\#/song?id=4017240

另二个王 对 三元丹说

“ Leave this world, and never return… If you do, I’ll be waiting… ”

 (离开那么些世界,永远不要再重回。假设您敢于这么做,小编会等着您……)

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注