ANSI C中的超轻量级JsON解析器
JsON(JavaScript对象表示法)是一种轻量级的数据交换格式。人类易于阅读和书写。机器很容易解析和生成。它基于JavaScript编程语言标准ECMA-262第三版(1999年12月)的子集 。JsON是一种完全独立于语言的文本格式,但是使用C语言家族(包括C,C ++,C#,Java,JavaScript,Perl,Python等)的程序员熟悉的约定。这些属性使JsON成为理想的数据交换语言。
cJsON旨在成为您可以完成工作的最简单的解析器。它是资源只有一个C的头文件和C文件,所以方便移植。它可以为你各种需要的Json字符串处理,包括打包、解析、修改、删除、添加等。在这里将一探究竟。
在这里将着重叙述Json的打包和解析,更多处理玩法,见文章末尾链接。
开始cJsONcJsON合并到您的项目
因为整个库只有一个C文件和一个头文件,所以您只需复制cJsON.h并复制cJsON.c到项目源并开始使用它。
cJsON用ANSI C(C89)编写,以便支持尽可能多的平台和编译器。
下载:
https://github.com/DaveGamble/cJSON/releases
CJson结构体
/* The cJsON structure: */typedef struct cJsON{ struct cJsON *next; prev; child; int type; char *valuestring; valueint; double valuedouble; string;} cJsON;
结构体项解析:
next 和prev :CJson结构体作为一个双向连表的环,可以通过 next 和prev 指针进行连表遍历
child:可以是cJsON_Array、cJsON_Object类型数据
type:当前项的类型
valuestring:内容存储,当类型是cJsON_String和cJsON_Raw
valueint:内容存储,整型,可以是cJsON_False、cJsON_True数据
valuedouble:内容存储,浮点型,当类型是cJsON_Number
string:键名
数据类型
l cJsON_InvalID表示一个不包含任何值的无效项目。如果将项目设置为全零字节,则将自动具有此类型。
l cJsON_False表示一个false布尔值。您也可以使用来检查布尔值cJsON_IsBool
l cJsON_True表示一个true布尔值。您也可以使用来检查布尔值cJsON_IsBool
l cJsON_NulL表示一个null值
l cJsON_Number 表示一个数字值。该值存储为double in valuedouble和in valueint。如果数字超出整数范围,INT_MAX或INT_MIN用于valueint
l cJsON_String表示一个字符串值。它以零终止字符串的形式存储在中valuestring
l cJsON_Array表示一个数组值。这是通过指向表示数组中值child的cJsON项目的链接列表来实现的。使用next和将元素链接在一起prev,其中第一个元素具有prev.next == NulL和最后一个元素next == NulL
l cJsON_Object 表示一个对象值。对象的存储方式与数组相同,唯一的区别是对象中的项将其键存储在中string
l cJsON_Raw表示以JsON字符存储的零终止形式的任何JsON valuestring。例如,可以使用它来避免一遍又一遍地打印相同的静态JsON以节省性能。解析时,cJsON永远不会创建此类型。另请注意,cJsON不会检查其是否为有效JsON。
类型
#define cJsON_InvalID (0)#define cJsON_False (1 << 0)#define cJsON_True (1 << 1)#define cJsON_NulL (1 << 2)#define cJsON_Number (1 << 3)#define cJsON_String (1 << 4)#define cJsON_Array (1 << 5)#define cJsON_Object (1 << 6)#define cJsON_Raw (1 << 7) /* raw Json */
类型判断
cJsON_IsInvalID(const cJsON * const item);cJsON_IsFalse( item);cJsON_IsTrue( item);cJsON_IsBool( item);cJsON_IsNull( item);cJsON_IsNumber( item);cJsON_Isstring( item);cJsON_IsArray( item);cJsON_IsObject( item);cJsON_IsRaw(const item);
注意
创建cJson对象后,处理完需要进行内存释放:
如果是cJson里的对象,请使用cJsON_Delete()
如果不是对象:cJsON_free()或free()
零字符
cJsON不支持包含零字符'\0'或的字符串\u0000。对于当前的API,这是不可能的,因为字符串以零结尾。
字符编码
cJsON仅支持UTF-8编码的输入。但是在大多数情况下,它不会拒绝无效的UTF-8作为输入,而只是将其原样传播。只要输入不包含无效的UTF-8,输出将始终是有效的UTF-8。
C标准
cJsON用ANSI C(或C89,C90)编写。如果您的编译器或C库未遵循此标准,则不能保证正确的行为。
注意:ANSI C不是C ++,因此不应使用C ++编译器进行编译。您可以使用C编译器对其进行编译,然后将其与C ++代码链接。尽管可以使用C ++编译器进行编译,但是不能保证正确的行为。
浮点数字
double除IEEE754双精度浮点数外,cJsON不正式支持任何实现。它可能仍然可以与其他实现一起使用,但是这些实现的错误将被视为无效。
目前,cJsON支持的浮点文字的最大长度为63个字符。
数组和对象的深层嵌套
cJsON不支持嵌套太深的数组和对象,因为这会导致堆栈溢出。为了防止这种CJsON_nesTING_liMIT情况,默认情况下,cJsON将深度限制为1000,但是可以在编译时进行更改。
格式化输出按标准的格式输出Json字符串,输出完后一定要记得释放内存
代码
1 #include <stdio.h> 2 #include "cJsON.h" 3 #include cJsON.c 4 voID main(){ 5 //待解析字符串 6 char *Json_str={\"key1\":\"dongxiaodong\",\"key2\":1998,\"key3\":55778}"; 7 8 输出原字符串 9 printf(原字符串:%s\r\n,Json_str); 10 11 解析成Json对象 12 cJsON * Json_obj = cJsON_Parse(Json_str); 13 14 格式输出15 char *Json_print_str=NulL;16 Json_print_str=cJsON_Print(Json_obj);17 printf(\r\n输出内容:\r\n\r\n%s\r\n18 19 释放资源 20 free(Json_print_str);21 22 23 cJsON_Delete(Json_obj);24 }Json打包
cJsON_CreateObject函数可创建一个根数据项,在此之后就可以添加各种数据类型的子节点了,使用完成后需要通过cJsON_Delete()释放内存。
创建一层级的Json
代码:
5 cJsON *root_obj = NulL;根,Json对象 char *out_str = NulL; 输出结果 7 root_obj =cJsON_CreateObject();创建 8 添加一个字符串,参数(根对象,键,值) 9 cJsON_AddStringToObject(root_obj,key1",1)">dongxiaodong);10 添加一个整型,参数(根对象,键,值) 11 cJsON_AddNumberToObject(root_obj,1)">key2199812 添加一个浮点型,参数(根对象,键,值) 13 cJsON_AddNumberToObject(root_obj,1)">key322.33添加一个bool类型,参数(根对象,键,值) bool值可以是0/1或false/true 16 cJsON_AddBoolToObject(root_obj,1)">key4017 将Json对象打包成字符串 18 out_str = cJsON_PrintUnformatted(root_obj);销毁Json对象,释放内存 20 cJsON_Delete(root_obj); 21 输出值:{"key1":"dongxiaodong","key2":1998,"key3":22.33,"key4":false} 22 printf(%s23 }
类型创建函数还有:
cJsON_AddNullToObject(cJsON * const object,const char * const name);
cJsON_AddTruetoObject(cJsON * const object,const char * const name);
cJsON_AddFalsetoObject(cJsON * const object,const char * const name);
cJsON_AddBoolToObject(cJsON * const object,const char * const name,const cJsON_bool boolean);
cJsON_AddNumberToObject(cJsON * const object,const double number);
cJsON_AddStringToObject(cJsON * const object,const char * const string);
cJsON_AddRawToObject(cJsON * const object,const char * const raw);
cJsON_AddobjectToObject(cJsON * const object,const char * const name);
cJsON_AddArrayToObject(cJsON * const object,const char * const name);
创建多层级的Json
代码:
6 cJsON *item_obj = NulL;二级Json对象 7 8 9 root_obj =cJsON_CreateObject();10 11 cJsON_AddStringToObject(root_obj,1)">14 创建一个子Json对象16 item_obj= cJsON_AddobjectToObject(root_obj,1)">myson); 向孩子对象中添加内容18 cJsON_AddStringToObject(item_obj,1)">sonkey1东小东19 cJsON_AddNumberToObject(item_obj,1)">sonkey2202020 22 out_str =23 24 25 26 printf(27 }
创建多层Json(数组形式)
代码
数组对象 创建一个子数组对象 16 item_obj= cJsON_AddArrayToObject(root_obj,1)">向数组对象中添加内容18 cJsON_AddItemToArray(item_obj,cJsON_CreateTrue()); 19 cJsON_AddItemToArray(item_obj,cJsON_CreateNumber(22));27 }
创建的对象还可以是下面这些
cJsON_CreateNull(voID);
cJsON_CreateTrue(voID);
cJsON_CreateFalse(voID);
cJsON_CreateBool(cJsON_bool boolean);
cJsON_CreateNumber(double num);
cJsON_CreateString(const char *string);
cJsON_Createraw(const char *raw);
cJsON_CreateArray(voID);
cJsON_CreateObject(voID);
创建混合Json
代码
6 cJsON *son_obj=NulL; 7 cJsON *item_obj = NulL;输出结果 9 根对象 11 root_obj =cJsON_CreateObject();13 cJsON_AddStringToObject(root_obj,1)">15 cJsON_AddNumberToObject(root_obj,1)">16 18 item_obj= cJsON_AddArrayToObject(root_obj,1)">21 cJsON_AddItemToArray(item_obj,1)">22 子对象 24 son_obj =cJsON_CreateObject();26 cJsON_AddStringToObject(son_obj,1)">son127 28 cJsON_AddNumberToObject(son_obj,1)">son229 30 31 32 out_str =33 34 35 36 printf(37 }Json解析
解析一层级的Json
代码:
8 cJsON * Json_obj =项存储 11 cJsON *item=12 13 14 printf(15 16 获取string类型 17 item=cJsON_GetobjectItem(Json_obj,1)">); 18 printf(\r\nkey1:%s\r\nvaluestring);19 cJsON_Delete(item);释放资源 20 获取数字 22 item=cJsON_GetobjectItem(Json_obj,1)">23 printf(\r\nkey2:%d\r\nvalueint);24 cJsON_Delete(item);25 26 27 item=cJsON_GetobjectItem(Json_obj,1)">28 printf(\r\nkey3:%f\r\nvaluedouble);29 cJsON_Delete(item);获取bool 32 item=cJsON_GetobjectItem(Json_obj,1)">33 printf(\r\nkey4:%d\r\n34 cJsON_Delete(item);35 36 是否资源 37 38 }
解析多层级的Json
代码
内部项存储13 cJsON * item_item=16 printf(17 18 19 item=cJsON_GetobjectItem(Json_obj,1)">20 printf(21 cJsON_Delete(item);22 24 item=cJsON_GetobjectItem(Json_obj,1)">25 printf(26 cJsON_Delete(item);27 28 子串29 item=cJsON_GetobjectItem(Json_obj,1)">30 item_item=cJsON_GetobjectItem(item,1)">31 printf(\r\nmyson(sonkey1):%s\r\n32 cJsON_Delete(item_item);33 34 item_item=cJsON_GetobjectItem(item,1)">35 printf(\r\nmyson(sonkey2):%d\r\n36 cJsON_Delete(item_item);37 38 cJsON_Delete(item);39 40 41 42 }
解析多层Json(数组形式)
代码
获取子串 输出数组大小 32 printf(\r\n数组大小:%d\r\n34 输出项1内容 35 item_item=cJsON_GetArrayItem(item,1)">\r\nmyson(0):%d\r\n37 cJsON_Delete(item_item);38 39 输出项2内容 40 item_item=cJsON_GetArrayItem(item,1)">141 printf(\r\nmyson(1):%d\r\n42 cJsON_Delete(item_item);43 44 cJsON_Delete(item);45 46 47 48 }
解析混合Json
代码
44 项3内容45 item_item=cJsON_GetArrayItem(item,1)">246 cJsON *item_item_son=47 48 item_item_son =cJsON_GetobjectItem(item_item,1)">49 printf(\r\nmyson(2)(son1):%s\r\n50 cJsON_Delete(item_item_son);51 52 item_item_son =cJsON_GetobjectItem(item_item,1)">53 printf(\r\nmyson(2)(son2):%d\r\n54 cJsON_Delete(item_item_son);释放资源55 cJsON_Delete(item_item);释放资源 56 57 cJsON_Delete(item);58 59 60 61 }
附件:
cJsON.h
1 /* 2 copyright (c) 2009-2017 Dave Gamble and cJsON contributors 3 4 Permission is hereby granted,free of charge,to any person obtaining a copy 5 of this software and associated documentation files (the "Software"),to deal 6 in the Software without restriction,including without limitation the rights 7 to use,copy,modify,merge,publish,distribute,sublicense,and/or sell 8 copIEs of the Software,and to permit persons to whom the Software is 9 furnished to do so,subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in 12 all copIEs or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR 15 IMPLIED,INCLUDING BUT NOT liMITED TO THE WARRANTIES OF MERCHANTABIliTY, 16 fitness FOR A PARTIculaR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR copYRIGHT HolDERS BE liABLE FOR ANY CLaim,damAGES OR OTHER 18 liABIliTY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,1)"> 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAliNGS IN 20 THE SOFTWARE. 21 */ 22 23 #ifndef cJsON__h 24 #define cJsON__h 25 26 #ifdef __cplusplus 27 extern C 28 { 29 #endif 30 31 #if !defined(__windows__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) 32 #define __windows__ 33 34 35 #ifdef __windows__ 36 37 When compiling for windows,we specify a specific calling convention to avoID issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: 38 39 CJsON_HIDE_SYMBolS - define this in the case where you don't want to ever dllexport symbols 40 CJsON_EXPORT_SYMBolS - define this on library build when you want to dllexport symbols (default) 41 CJsON_import_SYMBolS - define this if you want to dllimport symbol 42 43 For *nix builds that support visibility attribute,you can define similar behavior by 44 45 setting default visibility to hIDden by adding 46 -fvisibility=hIDden (for gcc) 47 or 48 -xldscope=hIDden (for sun cc) 49 to CFLAGS 50 51 then using the CJsON_API_VISIBIliTY flag to "export" the same symbols the way CJsON_EXPORT_SYMBolS does 52 53 54 55 #define CJsON_CDECL __cdecl 56 #define CJsON_STDCALL __stdcall 57 58 export symbols by default,this is necessary for copy pasting the C and header file 59 #if !defined(CJsON_HIDE_SYMBolS) && !defined(CJsON_import_SYMBolS) && !defined(CJsON_EXPORT_SYMBolS) 60 #define CJsON_EXPORT_SYMBolS 61 62 63 #if defined(CJsON_HIDE_SYMBolS) 64 #define CJsON_PUBliC(type) type CJsON_STDCALL 65 #elif defined(CJsON_EXPORT_SYMBolS) 66 #define CJsON_PUBliC(type) __declspec(dllexport) type CJsON_STDCALL 67 #elif defined(CJsON_import_SYMBolS) 68 #define CJsON_PUBliC(type) __declspec(dllimport) type CJsON_STDCALL 69 70 #else /* !__windows__ */ 71 #define CJsON_CDECL 72 #define CJsON_STDCALL 73 74 #if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJsON_API_VISIBIliTY) 75 #define CJsON_PUBliC(type) __attribute__((visibility("default"))) type 76 #else 77 #define CJsON_PUBliC(type) type 78 79 80 81 project version 82 #define CJsON_VERSION_MAJOR 1 83 #define CJsON_VERSION_MInor 7 84 #define CJsON_VERSION_PATCH 13 85 86 #include <stddef.h> 87 88 cJsON Types: 89 90 91 92 93 94 95 96 97 #define cJsON_Raw (1 << 7) /* raw Json */ 98 99 #define cJsON_IsReference 256100 #define cJsON_StringIsConst 512101 102 103 typedef cJsON104 105 next/prev allow you to walk array/object chains. Alternatively,use GetArraySize/GetArrayItem/GetobjectItem 106 next;107 prev;108 An array or object item will have a child pointer pointing to a chain of the items in the array/object. 109 child;110 111 The type of the item,as above. 112 type;113 114 The item's string,if type==cJsON_String and type == cJsON_Raw 115 valuestring;116 writing to valueint is DEPRECATED,use cJsON_SetNumberValue instead 117 valueint;118 The item's number,if type==cJsON_Number 119 valuedouble;120 121 The item's name string,if this item is the child of,or is in the List of subitems of an object. 122 123 } cJsON;124 125 typedef cJsON_Hooks126 127 malloc/free are CDECL on windows regardless of the default calling convention of the compiler,so ensure the hooks allow passing those functions directly. 128 voID *(CJsON_CDECL *malloc_fn)(size_t sz);129 voID (CJsON_CDECL *free_fn)(voID *ptr);130 } cJsON_Hooks;131 132 typedef cJsON_bool;133 134 limits how deeply nested arrays/objects can be before cJsON rejects to parse them.135 * This is to prevent stack overflows. 136 #ifndef CJsON_nesTING_liMIT137 #define CJsON_nesTING_liMIT 1000138 139 140 returns the version of cJsON as a string 141 CJsON_PUBliC(const char*) cJsON_Version(142 143 Supply malloc,realloc and free functions to cJsON 144 CJsON_PUBliC(voID) cJsON_InitHooks(cJsON_Hooks* hooks);145 146 Memory Management: the caller is always responsible to free the results from all variants of cJsON_Parse (with cJsON_Delete) and cJsON_Print (with stdlib free,cJsON_Hooks.free_fn,or cJsON_free as appropriate). The exception is cJsON_PrintPreallocated,where the caller has full responsibility of the buffer. 147 Supply a block of JsON,and this returns a cJsON object you can interrogate. 148 CJsON_PUBliC(cJsON *) cJsON_Parse(value);149 CJsON_PUBliC(cJsON *) cJsON_ParseWithLength(value,size_t buffer_length);150 ParseWithOpts allows you to require (and check) that the JsON is null terminated,and to retrIEve the pointer to the final byte parsed. 151 If you supply a ptr in return_parse_end and parsing fails,then return_parse_end will contain a pointer to the error so will match cJsON_GetErrorPtr(). 152 CJsON_PUBliC(cJsON *) cJsON_ParseWithOpts(char *value,char **return_parse_end,cJsON_bool require_null_terminated);153 CJsON_PUBliC(cJsON *) cJsON_ParseWithLengthOpts(154 155 Render a cJsON entity to text for transfer/storage. 156 CJsON_PUBliC(char *) cJsON_Print(const cJsON *item);157 Render a cJsON entity to text for transfer/storage without any formatting. 158 CJsON_PUBliC(char *) cJsON_PrintUnformatted(159 Render a cJsON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted,=1 gives formatted 160 CJsON_PUBliC(char *) cJsON_PrintBuffered(const cJsON *item,1)"> prebuffer,cJsON_bool fmt);161 Render a cJsON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. 162 NOTE: cJsON is not always 100% accurate in estimating how much memory it will use,so to be safe allocate 5 bytes more than you actually need 163 CJsON_PUBliC(cJsON_bool) cJsON_PrintPreallocated(cJsON *item,1)">char *buffer,1)">int length,1)"> cJsON_bool format);164 Delete a cJsON entity and all subentitIEs. 165 CJsON_PUBliC(voID) cJsON_Delete(cJsON *166 167 Returns the number of items in an array (or object). 168 CJsON_PUBliC(int) cJsON_GetArraySize(array);169 RetrIEve item number "index" from array "array". Returns NulL if unsuccessful. 170 CJsON_PUBliC(cJsON *) cJsON_GetArrayItem(const cJsON *array,1)"> index);171 Get item "string" from object. Case insensitive. 172 CJsON_PUBliC(cJsON *) cJsON_GetobjectItem(object,1)">char * 173 CJsON_PUBliC(cJsON *) cJsON_GetobjectItemCaseSensitive(174 CJsON_PUBliC(cJsON_bool) cJsON_HasObjectItem(175 For analysing Failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. defined when cJsON_Parse() returns 0. 0 when cJsON_Parse() succeeds. 176 CJsON_PUBliC(char *) cJsON_GetErrorPtr(177 178 Check item type and return its value 179 CJsON_PUBliC(char *) cJsON_GetStringValue(cJsON *180 CJsON_PUBliC(double) cJsON_GetNumberValue(cJsON *181 182 These functions check the type of an item 183 CJsON_PUBliC(cJsON_bool) cJsON_IsInvalID( item);184 CJsON_PUBliC(cJsON_bool) cJsON_IsFalse(185 CJsON_PUBliC(cJsON_bool) cJsON_IsTrue(186 CJsON_PUBliC(cJsON_bool) cJsON_IsBool(187 CJsON_PUBliC(cJsON_bool) cJsON_IsNull(188 CJsON_PUBliC(cJsON_bool) cJsON_IsNumber(189 CJsON_PUBliC(cJsON_bool) cJsON_Isstring(190 CJsON_PUBliC(cJsON_bool) cJsON_IsArray(191 CJsON_PUBliC(cJsON_bool) cJsON_IsObject(192 CJsON_PUBliC(cJsON_bool) cJsON_IsRaw(193 194 These calls create a cJsON item of the appropriate type. 195 CJsON_PUBliC(cJsON *) cJsON_CreateNull(196 CJsON_PUBliC(cJsON *) cJsON_CreateTrue(197 CJsON_PUBliC(cJsON *) cJsON_CreateFalse(198 CJsON_PUBliC(cJsON *) cJsON_CreateBool(cJsON_bool boolean);199 CJsON_PUBliC(cJsON *) cJsON_CreateNumber( num);200 CJsON_PUBliC(cJsON *) cJsON_CreateString(201 raw Json 202 CJsON_PUBliC(cJsON *) cJsON_Createraw(raw);203 CJsON_PUBliC(cJsON *) cJsON_CreateArray(204 CJsON_PUBliC(cJsON *) cJsON_CreateObject(205 206 Create a string where valuestring references a string so207 * it will not be freed by cJsON_Delete 208 CJsON_PUBliC(cJsON *) cJsON_CreateStringReference(209 Create an object/array that only references it's elements so210 * they will not be freed by cJsON_Delete 211 CJsON_PUBliC(cJsON *) cJsON_CreateObjectReference(child);212 CJsON_PUBliC(cJsON *) cJsON_CreateArrayReference(213 214 These utilitIEs create an Array of count items.215 * The parameter count cannot be greater than the number of elements in the number array,otherwise array access will be out of bounds.216 CJsON_PUBliC(cJsON *) cJsON_CreateIntArray(int *numbers,1)"> count);217 CJsON_PUBliC(cJsON *) cJsON_CreatefloatArray(float *numbers,1)">218 CJsON_PUBliC(cJsON *) cJsON_CreateDoubleArray(double *numbers,1)">219 CJsON_PUBliC(cJsON *) cJsON_CreateStringArray(const *strings,1)">220 221 Append item to the specifIEd array/object. 222 CJsON_PUBliC(cJsON_bool) cJsON_AddItemToArray(cJsON *array,cJsON *223 CJsON_PUBliC(cJsON_bool) cJsON_AddItemToObject(cJsON *string,1)">224 Use this when string is definitely const (i.e. a literal,or as good as),and will definitely survive the cJsON object.225 * WARNING: When this function was used,make sure to always check that (item->type & cJsON_StringIsConst) is zero before226 * writing to `item->string` 227 CJsON_PUBliC(cJsON_bool) cJsON_AddItemToObjectCS(cJsON *228 Append reference to item to the specifIEd array/object. Use this when you want to add an existing cJsON to a new cJsON,but don't want to corrupt your existing cJsON. 229 CJsON_PUBliC(cJsON_bool) cJsON_AddItemReferencetoArray(cJsON *array,1)">230 CJsON_PUBliC(cJsON_bool) cJsON_AddItemReferencetoObject(cJsON *231 232 Remove/Detach items from Arrays/Objects. 233 CJsON_PUBliC(cJsON *) cJsON_DetachItemViaPointer(cJsON *parent,cJsON * 234 CJsON_PUBliC(cJsON *) cJsON_DetachItemFromArray(cJsON *array,1)"> which);235 CJsON_PUBliC(voID) cJsON_DeleteItemFromArray(cJsON *array,1)">236 CJsON_PUBliC(cJsON *) cJsON_DetachItemFromObject(cJsON *237 CJsON_PUBliC(cJsON *) cJsON_DetachItemFromObjectCaseSensitive(cJsON *238 CJsON_PUBliC(voID) cJsON_DeleteItemFromObject(cJsON *239 CJsON_PUBliC(voID) cJsON_DeleteItemFromObjectCaseSensitive(cJsON *240 241 Update array items. 242 CJsON_PUBliC(cJsON_bool) cJsON_InsertItemInArray(cJsON *array,1)">int which,cJsON *newitem); Shifts pre-existing items to the right. 243 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemViaPointer(cJsON * const parent,1)">const item,1)"> replacement);244 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemInArray(cJsON *array,1)">newitem);245 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemInObject(cJsON *246 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemInObjectCaseSensitive(cJsON *247 248 Duplicate a cJsON item 249 CJsON_PUBliC(cJsON *) cJsON_Duplicate(item,cJsON_bool recurse);250 Duplicate will create a new,IDentical cJsON item to the one you pass,in new memory that will251 * need to be released. With recurse!=0,it will duplicate any children connected to the item.252 * The item->next and ->prev pointers are always zero on return from Duplicate. 253 Recursively compare two cJsON items for equality. If either a or b is NulL or invalID,they will be consIDered unequal.254 * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) 255 CJsON_PUBliC(cJsON_bool) cJsON_Compare(const a,1)">const b,1)"> cJsON_bool case_sensitive);256 257 Minify a strings,remove blank characters(such as ' ','\t','\r','\n') from strings.258 * The input pointer Json cannot point to a read-only address area,such as a string constant,1)">259 * but should point to a readable and writable adress area. 260 CJsON_PUBliC(voID) cJsON_Minify(Json);261 262 Helper functions for creating and adding items to an object at the same time.263 * They return the added item or NulL on failure. 264 CJsON_PUBliC(cJsON*) cJsON_AddNullToObject(cJsON * name);265 CJsON_PUBliC(cJsON*) cJsON_AddTruetoObject(cJsON * 266 CJsON_PUBliC(cJsON*) cJsON_AddFalsetoObject(cJsON * 267 CJsON_PUBliC(cJsON*) cJsON_AddBoolToObject(cJsON * const name,1)"> cJsON_bool boolean);268 CJsON_PUBliC(cJsON*) cJsON_AddNumberToObject(cJsON * number);269 CJsON_PUBliC(cJsON*) cJsON_AddStringToObject(cJsON * 270 CJsON_PUBliC(cJsON*) cJsON_AddRawToObject(cJsON * raw);271 CJsON_PUBliC(cJsON*) cJsON_AddobjectToObject(cJsON * 272 CJsON_PUBliC(cJsON*) cJsON_AddArrayToObject(cJsON * 273 274 When assigning an integer value,it needs to be propagated to valuedouble too. 275 #define cJsON_SetIntValue(object,number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))276 helper for the cJsON_SetNumberValue macro 277 CJsON_PUBliC(double) cJsON_SetNumberHelper(cJsON *278 #define cJsON_SetNumberValue(object,number) ((object != NulL) ? cJsON_SetNumberHelper(object,(double)number) : (number))279 Change the valuestring of a cJsON_String object,only takes effect when type of object is cJsON_String 280 CJsON_PUBliC(char*) cJsON_SetValuestring(cJsON *281 282 Macro for iterating over an array or object 283 #define cJsON_ArrayForEach(element,array) for(element = (array != NulL) ? (array)->child : NulL; element != NulL; element = element->next)284 285 malloc/free objects using the malloc/free functions that have been set with cJsON_InitHooks 286 CJsON_PUBliC() cJsON_malloc(size_t size);287 CJsON_PUBliC(voID) cJsON_free(object288 289 290 }291 292 293 #endifVIEw Code
cJsON.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cJsON 24 JsON parser in C. 25 26 disable warnings about old C89 functions in MSVC 27 #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) 28 #define _CRT_SECURE_NO_DEPRECATE 29 30 31 #ifdef __GNUC__ 32 #pragma GCC visibility push(default) 33 34 #if defined(_MSC_VER) 35 #pragma warning (push) 36 disable warning about single line comments in system headers 37 #pragma warning (disable : 4001) 38 39 40 #include <string.h> 41 #include <stdio.h> 42 #include <math.h> 43 #include <stdlib.h> 44 #include <limits.h> 45 #include <ctype.h> 46 #include <float.h> 47 48 #ifdef ENABLE_LOCALES 49 #include <locale.h> 50 51 52 53 #pragma warning (pop) 54 55 56 #pragma GCC visibility pop 57 58 59 #include 60 61 define our own boolean type 62 #ifdef true 63 #undef true 64 65 #define true ((cJsON_bool)1) 66 67 #ifdef false 68 #undef false 69 70 #define false ((cJsON_bool)0) 71 72 define isnan and isinf for ANSI C,if in C99 or above,isnan and isinf has been defined in math.h 73 #ifndef isinf 74 #define isinf(d) (isnan((d - d)) && !isnan(d)) 75 76 #ifndef isnan 77 #define isnan(d) (d != d) 78 79 80 #ifndef NAN 81 #define NAN 0.0/0.0 82 83 84 typedef { 85 const unsigned Json; 86 size_t position; 87 } error; 88 static error global_error = { NulL,1)"> }; 89 90 CJsON_PUBliC() 91 92 return (char*) (global_error.Json + global_error.position); 93 94 95 CJsON_PUBliC(item) 96 97 if (!cJsON_Isstring(item)) 98 { 99 return NulL; 100 } 101 102 return item-> 103 104 105 CJsON_PUBliC( 106 107 cJsON_IsNumber(item)) 108 109 NAN; 110 111 112 valuedouble; 113 114 115 This is a safeguard to prevent copy-pasters from using incompatible C and header files 116 #if (CJsON_VERSION_MAJOR != 1) || (CJsON_VERSION_MInor != 7) || (CJsON_VERSION_PATCH != 13) 117 #error cJsON.h and cJsON.c have different versions. Make sure that both have the same. 118 119 120 CJsON_PUBliC( 121 122 static char version[15]; 123 sprintf(version,1)">%i.%i.%i 124 125 version; 126 127 128 Case insensitive string comparison,doesn't consIDer two NulL pointers equal though 129 int case_insensitive_strcmp(char *string1,1)">string2) 130 131 if ((string1 == NulL) || (string2 == NulL)) 132 133 return 134 135 136 if (string1 == string2) 137 138 139 140 141 for(; tolower(*string1) == tolower(*string2); (voID)string1++,string2++ 142 143 if (*string1 == '' 144 { 145 146 } 147 148 149 return string2); tolower(*string1) - tolower(* 150 151 152 internal_hooks typedef 153 154 allocate)(size_t size); 155voID pointer); (CJsON_CDECL *deallocate)( 156voID pointer,size_t size); *(CJsON_CDECL *reallocate)( 157} internal_hooks; 158 159 160 work around MSVC error C2322: '...' address of dllimport '...' is not static 161 CJsON_CDECL internal_malloc(size_t size) 162 163 return malloc (size); 164 165 voID pointer) CJsON_CDECL internal_free( 166 167 (pointer); 168 169 voID 170 * CJsON_CDECL internal_realloc( 171 realloc (pointer,size); 172 173 174 #define 175 internal_malloc malloc#define 176 internal_free free#define 177 internal_realloc realloc 178 179 strlen of character literals resolved at compile time 180#define 181 static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) 182 static { internal_malloc,internal_free,internal_realloc }; internal_hooks global_hooks = 183 184 static char unsigned char* cJsON_strdup(const* hooks) internal_hooks * 185 186 187 size_t length = char unsigned 188 *copy = 189 if string ( NulL) == 190 191 192 193 194 char length = strlen((string*)sizeof) + ""( 195char copy = (unsigned allocate(length);*)hooks-> 196if 197 (copy == 198 199 200 201 memcpy(copy,length); 202 copy; 203 204 205 206 CJsON_PUBliC( 207 if 208 (hooks == 209 reset hooks 210 211 global_hooks.allocate = 212 global_hooks.deallocate = 213 global_hooks.reallocate = 214 215 216 217 global_hooks.allocate = if 218 (hooks->malloc_fn != 219 malloc_fn; global_hooks.allocate = hooks-> 220 221 222 223 global_hooks.deallocate = if 224 (hooks->free_fn != 225 free_fn; global_hooks.deallocate = hooks-> 226 227 228 use realloc only if both free and malloc are used 229 230 global_hooks.reallocate =if malloc ((global_hooks.allocate == ))) && (global_hooks.deallocate == 231 232 233 global_hooks.reallocate = 234 235 236 Internal constructor. 237static 238 cJsON *cJsON_New_Item( 239 sizeof cJsON* node = (cJsON*)hooks->allocate((cJsON)); 240if (node) 241 242 244 memset(node,1)">',1)"> 243 245 node; 246 247 248 Delete a cJsON structure. 249item) CJsON_PUBliC( 250 251 252 cJsON *next =while 253 (item != 254 255 next = item->if 256 (!(item->type & cJsON_IsReference) && (item->child != 257 258 cJsON_Delete(item-> 259 if 260 (!(item->type & cJsON_IsReference) && (item->valuestring != 261 262 global_hooks.deallocate(item-> 263 if string (!(item->type & cJsON_StringIsConst) && (item-> 264 != 265 266 global_hooks.deallocate(item-> 267 global_hooks.deallocate(item); 268 next; item = 269 270 271 272 get the decimal point character of the current locale 273char 274 get_decimal_point( 275 276 struct localeconv(); lconv *lconv = 277return char (unsigned 278) lconv->decimal_point[ 279 . 280 281 282 283 struct typedef 284 285 content; 286 size_t length; 287 size_t offset; 288 How deeply nested (in arrays/objects) is the input at the current offset. size_t depth; 289 internal_hooks hooks; 290} parse_buffer; 291 292 check if the given size is left to read in a given parse buffer (starting with 1) 293#define 294 can_read(buffer,size) ((buffer != NulL) && (((buffer)->offset + size) <= (buffer)->length)) check if the buffer can be accessed at the given index (starting with 0) 295#define 296 can_access_at_index(buffer,index) ((buffer != NulL) && (((buffer)->offset + index) < (buffer)->length))#define 297 cannot_access_at_index(buffer,index) (!can_access_at_index(buffer,index)) get a pointer to the buffer at the position 298#define 299 buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) 300 Parse the input text to generate a number,and populate the result into item. 301static input_buffer) cJsON_bool parse_number(cJsON * 302 303 double 304 number = char unsigned 305 *after_end =char unsigned 64 number_c_string[ 306char unsigned get_decimal_point(); decimal_point = 307 308 size_t i = 309 if 310 ((input_buffer == NulL) || (input_buffer->content == 311 false 312 313 314 copy the number into a temporary buffer and replace '.' with the decimal point 315 * of the current locale (for strtod) 316 * This also takes care of ' 317' not necessarily being available for marking the end of the input for0 sizeof (i = 1; (i < ( 318(number_c_string) - 319)) && can_access_at_index(input_buffer,i); i++switch (buffer_at_offset(input_buffer)[i]) 320 321case 0 : 3221 323 2 324 3 325 4 326 5 327 6 328 7 329 8 330 9 331 + 332 - 333 e 334 E 335 buffer_at_offset(input_buffer)[i]; 336 number_c_string[i] =break 337 338 339 decimal_point; 340 number_c_string[i] = 341 342 default 343 goto loop_end; 344 345 346 loop_end: 347 348 349 number_c_string[i] = char char number = strtod((after_end);*)number_c_string,( 350**)&if after_end) 351 (number_c_string == 352false parse_error 353; 354 355 number; 356 item->valuedouble = 357 use saturation in case of overflow 358 if INT_MAX) 359 (number >= 360 INT_MAX; 361 item->valueint = 362else if )INT_MIN) 363 (number <= ( 364 INT_MIN; 365 item->valueint = 366else 367 368)number; 369 item->valueint = ( 370 371 cJsON_Number; 372 item->type = 373 number_c_string); 374 input_buffer->offset += (size_t)(after_end -true 375 376 377 don't ask me,but the original cJsON_SetNumberValue returns an integer or double 378 number) 379 CJsON_PUBliC( 380 381 382 object 383 384->valueint = 385 386 387 388 389 390 object 391 392->valueint = ( 393 object 394 395->valuedouble = 396 valuestring) 397 CJsON_PUBliC( 398 399 if object's type is not cJsON_String or is cJsON_IsReference,it should not set valuestring 400 ifobject object (!( cJsON_IsReference))->type & cJsON_String) || ( 401->type & 402 403 404 if object valuestring)) (strlen(valuestring) <= strlen( 405-> 406valuestring,valuestring); 407 strcpy( 408 409 char char copy = (global_hooks);*) cJsON_strdup(( 410*)valuestring,& 411 412 413 414 object 415 416->valuestring != 417 418 cJsON_free(object 419 420->valuestring = 421 422 423 424 425 typedef buffer; 426 unsigned 427 428 current nesting depth (for formatted printing) 429 size_t depth; cJsON_bool noalloc; 430 is this print a formatted print 431 cJsON_bool format; 432} printbuffer; 433 434 realloc printbuffer if necessary to have at least "needed" bytes more 435 char p,size_t needed) 436* ensure(printbuffer * 437char 438 unsigned 439 *newbuffer = 440 size_t newsize = if 441 442 ((p == NulL) || (p->buffer == 443 444 445 if 0 length)) ((p->length > 446) && (p->offset >= p-> 447 make sure that offset is valID 448 449 450 451 if 452 453 (needed > sizes bigger than INT_MAX are currently not supported 454 455 456 457 458 if needed += p->offset + length) 459 (needed <= p-> 460return offset; 461 p->buffer + p-> 462 463 if noalloc) { 464 (p-> 465 466 467 calculate new buffer size 468 if 469 470 (needed > (INT_MAX / overflow of int,use INT_MAX if possible 471 if 472 473 (needed <= 474 475 newsize = 476 477 478 479 480 481 482 483 484 newsize = needed * 485 if 486 487 (p->hooks.reallocate != reallocate with realloc if available 488 charbuffer,newsize); newbuffer = (unsigned 489*)p->hooks.reallocate(p->if 490 491 (newbuffer ==buffer); 492 p->hooks.deallocate(p-> 493 494 p->length = 495 p->buffer = 496 497 498 499 500 otherwise reallocate manually 501 charhooks.allocate(newsize); newbuffer = (unsigned 502*)p->newbuffer) 503 504 505 506 p->hooks.deallocate(p-> 507 p->length = 508 p->buffer = 509 510 (newbuffer) 511 512 513 514 memcpy(newbuffer,p->buffer,p->offset + 515 516 p->hooks.deallocate(p-> newsize; 517 p->length = newbuffer; 518 p->buffer = 519return 520 521 newbuffer + p-> 522 calculate the new length of the string in a printbuffer and update the offset 523 voID buffer) 524 update_offset(printbuffer * 525char 526 if *buffer_pointer = 527 528 ((buffer == NulL) || (buffer->buffer == 529 530 531 532 buffer_pointer = buffer->buffer + buffer->char )buffer_pointer); buffer->offset += strlen(( 533* 534 535 securely comparison of floating-point variables 536 staticdouble 537 cJsON_bool compare_double( 538 a,1)"> b)double fabs(a) : fabs(b); 539 maxVal = fabs(a) > fabs(b) ?return DBL_EPSILON); 540 (fabs(a - b) <= maxVal * 541 542 Render the number nicely from the given item into a string. 543 static output_buffer) 544 cJsON_bool print_number( 545char 546 unsigned double *output_pointer = 547 int d = item-> 548 549 length = char size_t i = 26 unsigned 0 number_buffer[ temporary buffer to print the number into ] = { 550}; 551double unsigned 0.0 552 test = 553if 554 555 (output_buffer == 556 557 558 This checks for NaN and Infinity 559 if isinf(d)) 560 (isnan(d) || 561char 562 length = sprintf(( 563*)number_buffer,1)">null 564 565 Try 15 decimal places of precision to avoID nonsignificant nonzero digits 566 %1.15g 567 length = sprintf(( 568 Check whether the original double can be recovered 569 if%lg 1 ((sscanf(()test,d)) 570) || !compare_double(( 571 If not,print with 17 decimal places of precision 572 %1.17g 573 length = sprintf(( 574 575 576 sprintf Failed or buffer overrun occurred 577 if0 int ((length < sizeof) || (length > ())))( 578(number_buffer) - 579 580 581 582 reserve appropriate space in the output 583 584if output_pointer = ensure(output_buffer,(size_t)length + 585 586 (output_pointer == 587 588 589 copy the printed number to the output and replace locale 590 * dependent decimal point with '.' 591 0 592 593; i < ((size_t)length); i++if decimal_point) 594 (number_buffer[i] == 595 596 continue output_pointer[i] = 597 598 599 number_buffer[i]; 600 output_pointer[i] = 601 602 603 output_pointer[i] = (size_t)length; 604 output_buffer->offset += 605 606 607 608 parse 4 digit hexadecimal number 609 static input) 610 unsigned parse_hex4( 611int 612 unsigned 613 h = 614 size_t i = 0 4 615; i < 616; i++ parse digit 617 if' 618 ((input[i] >= 619) && (input[i] <= int 620 h += (unsigned 621) input[i] - A F 622 623int 10 h += (unsigned 624) 625 + input[i] - a f 626 627 628 629 h += (unsigned invalID 630 631 632 633 634 if 3 635 (i < 636 shift left to make place for the next nibble 637 4 638 h = h << 639 640 641 h; 642 643 644 converts a UTF-16 literal to UTF-8 645 * A literal can be one or two sequences of the form \uXXXX 646 charconst output_pointer) utf16_literal_to_utf8( 647 input_pointer,1)">const input_end,unsigned 648long int 649 unsigned int codepoint = 650 unsigned char first_code = input_pointer; 651 *first_sequence =char 652 unsigned char utf8_length = 653 unsigned char utf8_position = 654 unsigned char sequence_length = 655 unsigned 656 first_byte_mark = if 6 657 ((input_end - first_sequence) < 658 input ends unexpectedly 659 fail; 660 661 662 get the first utf16 sequence 663 664 665 first_code = parse_hex4(first_sequence + check that the code is valID 666 if0xDC00 0xDFFF (((first_code >= 667) && (first_code <= 668 669 670 671 UTF16 surrogate pair 672 if0xD800 0xDBFF ((first_code >= 673) && (first_code <= 674char 675 int *second_sequence = first_sequence + 676 unsigned 12 second_code = \uXXXX\uXXXX sequence_length = 677; 678if 679 680 ((input_end - second_sequence) < 681 682 683 684 if 0 \ ((second_sequence['] != 1u) || (second_sequence[ 685] != 686 missing second half of the surrogate pair 687 688 689 690 get the second utf16 sequence 691 692 693 second_code = parse_hex4(second_sequence + if 0xDC00 694 ((second_code < 695) || (second_code > invalID second half of the surrogate pair 696 697 698 699 700 calculate the unicode codepoint from the surrogate pair 701 0x100000x3FF codepoint = 10 + (((first_code & 0x3FF) << 702) | (second_code & 703 704 705 6 \uXXXX sequence_length = 706; first_code; 707 codepoint = 708 709 encode as UTF-8 710 * takes at maximum 4 bytes to encode: 711 * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 712 if0x80 713 (codepoint < 714 normal ascii,enCoding 0xxxxxxx 715 716 717 utf8_length = 0x800 718 719 two bytes,enCoding 110xxxxx 10xxxxxx 720 7210xC0 utf8_length = 11000000 first_byte_mark = 722; 7230x10000 724 725 three bytes,enCoding 1110xxxx 10xxxxxx 10xxxxxx 726 7270xE0 utf8_length = 11100000 first_byte_mark = 728; 729if 0x10FFFF 730 (codepoint <= 731 four bytes,enCoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx 732 7330xF0 utf8_length = 11110000 first_byte_mark = 734; 735 736 737 invalID unicode codepoint 738 739 740 741 encode as utf8 742 forchar 1 (utf8_position = (unsigned 0)(utf8_length - 743); utf8_position > 744; utf8_position-- 10xxxxxx 745 char0x80 (*output_pointer)[utf8_position] = (unsigned 0xBF)((codepoint | 746) & 747 748 codepoint >>= encode first byte 749 if 750 751 (utf8_length > 0 char (*output_pointer)[0xFF] = (unsigned 752)((codepoint | first_byte_mark) & 753 754 755 char 0x7F (*output_pointer)[ 756)(codepoint & 757 758 utf8_length; 759 *output_pointer += 760 sequence_length; 761 762fail: 763 764 765 766 Parse the input text into an unescaped cinput,and populate item. 767 static 768 769 cJsON_bool parse_string(cJsON * char 770 char *input_pointer = buffer_at_offset(input_buffer) + 771 772 *input_end = buffer_at_offset(input_buffer) + char unsigned 773 unsigned 774 *output = not a string 775 if\" 776 (buffer_at_offset(input_buffer)[ 777 778 779 780 781 calculate approximate size of the output (overestimate) 782 783 784 size_t allocation_length = while size_t skipped_bytes = 785 786 (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != is escape sequence 787 if0 788 (input_end[ {] == 789 if1 790 ((size_t)(input_end + { - input_buffer->content) >= input_buffer-> 791 prevent buffer overflow when last input character is a backslash 792 793 } 794 795 796 skipped_bytes++ } input_end++ 797 798 799 input_end++if 800 801 (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != goto string ended unexpectedly 802 fail; 803 804 This is at most how much we need for the output 805 skipped_bytes; 806 allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) -char 807 output = (unsigned if*)input_buffer->hooks.allocate(allocation_length + 808 809 (output == allocation failure 810 811 812 813 output; 814 output_pointer = loop through the string literal 815 while input_end) 816 (input_pointer < 817if 818 819 (*input_pointer != 820 821 *output_pointer++ = *input_pointer++ escape sequence 822 823 824 825 if unsigned 826 827 ((input_end - input_pointer) < 828 829 830 switch ]) 831 (input_pointer[ 832b 833 \b 834 *output_pointer++ = 835 836 \f 837 *output_pointer++ = 838n 839 \n 840 *output_pointer++ = 841r 842 \r 843 *output_pointer++ = 844t 845 \t 846 *output_pointer++ = 847 848 849 / 850 851 852 *output_pointer++ = input_pointer[ 853 UTF-16 literal 854 855 856 if sequence_length = utf16_literal_to_utf8(input_pointer,input_end,1)">output_pointer); 857 { (sequence_length == 858 Failed to convert UTF16-literal to UTF-8 859 860 } 861 862 863 864 865 866 867 868 input_pointer += 869 870 zero terminate the output 871 872 873 *output_pointer = cJsON_String; 874 item->type =)output; 875 item->valuestring = ( 876content); 877 input_buffer->offset = (size_t) (input_end - input_buffer-> 878 879 input_buffer->offset++ 880 881 882 if 883 884 (output !=hooks.deallocate(output); 885 input_buffer-> 886 887 if 888 889 (input_pointer != 890 891 input_buffer->offset = (size_t)(input_pointer - input_buffer-> 892 893 894 895 Render the cstring provIDed to an escaped version that can be printed. 896 staticconst 898 cJsON_bool print_string_ptr(char input,1)"> 897 899 900 *input_pointer = 901 unsigned 902 unsigned numbers of additional characters needed for escaPing size_t output_length = 903 904 905 size_t escape_characters = 906 907 908 909 910 empty string 911 if 912 913 (input == 914 915 output = ensure(output_buffer,1)">\"\" 916 917 918 char 920 strcpy(( 921*)output,1)"> 919 922 923 set "flag" to 1 if something needs to be escaped 924 for 925 926 (input_pointer = input; *input_pointer; input_pointer++switch input_pointer) 927 (* 928 929 930 931 932 933 934 935 one character escape sequence 936 937 938 escape_characters++ 939 if 32 940 (*input_pointer < 941 UTF-16 escape sequence uXXXX 942 5 943 escape_characters += 944 945 946 947 escape_characters; 948 output_length = (size_t)(input_pointer - input) + 949 950 951 output = ensure(output_buffer,output_length + 952 953 954 955 no characters have to be escaped 956 if 957 958 (escape_characters == 0 959 output[ 960] = 1 memcpy(output + 961 output[output_length + 2] = 962 output[output_length + 963] = 964 965 966 967 968 output[ copy the string output_pointer = output + 969 for' voID (input_pointer = input; *input_pointer != 970; ( 971)input_pointer++,output_pointer++if 31 ' ((*input_pointer > 972) && (*input_pointer != 973) && (*input_pointer != normal character,copy 974 input_pointer; 975 *output_pointer = * 976 977 978 character needs to be escaped 979 980 981 *output_pointer++ = 982 983 984 985 *output_pointer = 986 987 988 *output_pointer = 989 990 991 *output_pointer = 992 993 994 *output_pointer = 995 996 997 *output_pointer = 998 999 1000 *output_pointer = 1001 1002 1003 *output_pointer = 1004 escape and print as unicode codepoint 1005 charinput_pointer); sprintf((1006*)output_pointer,1)">u%04x10071008 output_pointer += 1009 1010 1011 1012 1013 output[output_length + 1014 output[output_length + 1015 1016 1017 Invoke print_string_ptr (which is useful) on an item. 1018 static p) 1019 cJsON_bool print_string(1020return char 1021 print_string_ptr((unsigned 1022*)item->1023 Predeclare these prototypes. 1024 static input_buffer); 1025 cJsON_bool parse_value(cJsON * static output_buffer); 1026 cJsON_bool print_value(static1027 static cJsON_bool parse_array(cJsON * 1028 static cJsON_bool print_array(1029 static cJsON_bool parse_object(cJsON * 1030 1031 cJsON_bool print_object( Utility to jump whitespace and cr/lf 1032 static1033 1034 parse_buffer *buffer_skip_whitespace(parse_buffer * if 1035 1036 ((buffer == NulL) || (buffer->content ==1037 1038 1039 if 1041 buffer; (cannot_access_at_index(buffer,1)">1040 1042 10431044 while 0 1045 (can_access_at_index(buffer,1)">0) && (buffer_at_offset(buffer)[1046] <= 1047 1048 buffer->offset++1049 if 1050 1051 (buffer->offset == buffer->1052 1053 buffer->offset--1054 1055 1056 1057 skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer 1058 static1059 1060 parse_buffer *skip_utf8_bom(parse_buffer * if 1061 1062 ((buffer == NulL) || (buffer->content == NulL) || (buffer->offset != 1063 1064 1065 if char 3 (can_access_at_index(buffer,1)">4) && (strncmp((1066*)buffer_at_offset(buffer),1)">\xEF\xBB\xBF1067) == 1068 1069 buffer->offset += 1070 1071 1072 1073 1074 1075 CJsON_PUBliC(cJsON *) cJsON_ParseWithOpts( size_t buffer_length; 1076 1077if value) 1078 (NulL ==10791080 1081 1082 Adding null character size due to require_null_terminated. 1083 10841085 buffer_length = strlen(value) + cJsON_ParseWithLengthOpts(value,buffer_length,return_parse_end,require_null_terminated); 1086 10871088 Parse an object - create a new root,and populate. 1089 10901091 CJsON_PUBliC(cJsON *) cJsON_ParseWithLengthOpts(0 } }; parse_buffer buffer = { 1092,{ 10931094 cJsON *item = reset error position 1095 10961097 global_error.Json =1098 global_error.position = if 0 buffer_length) (value == NulL || 1099 ==11001101 1102 1103 )value; 1104 buffer.content = ( buffer_length; 1105 buffer.length =1106 global_hooks; buffer.offset = 1107 buffer.hooks =11081109 if item = cJsON_New_Item(& memory fail 1110 (item == NulL) 11111112 1113 1114 if buffer)))) 1115 (!parse_value(item,buffer_skip_whitespace(skip_utf8_bom(&1116 parse failure. ep is set. 1117 11181119 1120 if we require null-terminated JsON without appended garbage,skip and then check for a null terminator 1121 (require_null_terminated)1122 11231124 if buffer_skip_whitespace(&1125 1126 ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[1127 1128 1129 (return_parse_end) 1130 1131char 1132 *return_parse_end = (1133*)buffer_at_offset(&1134 item; 1135 11361137 if 1138 1139 (item != cJsON_Delete(item); 1140 11411142 if 1143 1144 (value != error local_error; 1145 11461147 local_error.Json = (1148 local_error.position = if buffer.length) 1149 (buffer.offset <1150 buffer.offset; 1151 local_error.position =1152if 1153 1154 (buffer.length > 1155 1156 local_error.position = buffer.length - 1157 if 1158 1159 (return_parse_end !=char local_error.position; *return_parse_end = (1160*)local_error.Json +11611162 local_error; 1163 global_error =11641165 1166 1167 1168 Default options for cJsON_Parse 1169 value)1170 CJsON_PUBliC(cJsON *) cJsON_Parse(1171return 1173 1174 cJsON_ParseWithOpts(value,1)">1172 1175 1176 CJsON_PUBliC(cJsON *) cJsON_ParseWithLength(return 1178 1179 cJsON_ParseWithLengthOpts(value,1)">1177 #define 1180 1181 cJson_min(a,b) (((a) < (b)) ? (a) : (b))char 1182 1183 *print(const 256 1184 size_t default_buffer_size = 1185char printbuffer buffer[1186 unsigned 1187 *printed =1188 1189 memset(buffer,1)">(buffer)); create buffer 1190 charallocate(default_buffer_size); buffer->buffer = (unsigned 1191*) hooks-> default_buffer_size;1192 buffer->length = format;1193 buffer->format =hooks;1194 buffer->hooks = *if1195 1196 (buffer->buffer ==1197 1198 1199 print the value 1200 print_value(item,buffer))1201 12021203 1204 update_offset(buffer); 1205 1206 check if reallocate is available 1207 if1208 1209 (hooks->reallocate !=char 1210 printed = (unsigned if*) hooks->reallocate(buffer->buffer,buffer->offset + NulL) { 1211 (printed ==12121213 1214 1215 buffer->buffer = otherwise copy the JsON over to a new buffer 1216 1217char 1218 printed = (unsigned 1219*) hooks->allocate(buffer->offset + 1220 1221 1222 ' just to be sure memcpy(printed,buffer->buffer,cJson_min(buffer->length,1)">1223 printed[buffer->offset] = 1224; 1225 free the buffer 1226 12271228 hooks->deallocate(buffer->1229 printed; 1230 12311232 if 1233 1234 (buffer->buffer !=1235 1236 hooks->deallocate(buffer->1237 if 1238 1239 (printed !=deallocate(printed); 1240 hooks->12411242 1243 1244 1245 Render a cJsON item/entity/structure to text. 1246 12471248 CJsON_PUBliC(char 1250 1251*)print(item,1)">true,1)">1249 1252 1253 CJsON_PUBliC(false 1255 1256,1)">1254 1257 1258 CJsON_PUBliC(1259 1260 printbuffer p = { if 1261 1262 (prebuffer < 1263 1264 1265 )global_hooks.allocate((size_t)prebuffer); 1266 p.buffer = (unsigned p.buffer)1267 12681269 1270 1271 (size_t)prebuffer; 1272 p.length =12731274 p.offset = fmt; p.noalloc = 1275 p.format =12761277 p.hooks =if 1278 1279 (!print_value(item,1)">p)) global_hooks.deallocate(p.buffer); 1280 12811282 1283 )p.buffer; 1284 12851286 1287 1288 CJsON_PUBliC(cJsON_bool) cJsON_PrintPreallocated(cJsON *item,1)"> cJsON_bool format)1289 1290 printbuffer p = { 0 1291 1292) || (buffer ==1293 1294 1295 )buffer; 1296 p.buffer = (unsigned 12971298 p.length =1299 p.offset = 1300 p.noalloc = 1301 p.format =1302 p.hooks =return 1303 1304 print_value(item,1)">p);1305 Parser core - when encountering text,process appropriately. 1306 13071308 1309 1310 no input 1311 13121313 parse the different types of values 1314 null 1315 if1316 1317 (can_read(input_buffer,1)">char*)buffer_at_offset(input_buffer),1)">4) == cJsON_NulL; 1318 item->type =13191320 input_buffer->offset += 1321 false 1322 5false 5) && (strncmp((13231324) == cJsON_False; 1325 item->type =13261327 input_buffer->offset += 1328 true 1329 true1330 1331 cJsON_True; 1332 item->type =13331334 item->valueint = 1335 input_buffer->offset += 1336 string 1337 if1338 1339 (can_access_at_index(input_buffer,1)">0) && (buffer_at_offset(input_buffer)[ parse_string(item,input_buffer); 1340 1341 number 1342 0' 0) && ((buffer_at_offset(input_buffer)[') || ((buffer_at_offset(input_buffer)[))))] >= 1343) && (buffer_at_offset(input_buffer)[13441346 array parse_number(item,1)">1345 1347 [1348 13491351 object parse_array(item,1)">1350 1352 {1353 13541356 1357 parse_object(item,1)">1355 1358 1359 1360 Render a value to text. 1361 13621363 1364 1365 unsigned if 1366 1367 ((item == NulL) || (output_buffer ==1368 1369 1370 switch 1371 1372 ((item->type) & case cJsON_NulL: 137313751376 output = ensure(output_buffer,1)">1374 1377 1378 1379 1380 strcpy((1381 cJsON_False: 1382 13841385 output = ensure(output_buffer,1)">1383 1386 1387 1388 1389 strcpy((1390 cJsON_True: 1391 13931394 output = ensure(output_buffer,1)">1392 1395 1396 1397 1398 strcpy((1399 cJsON_Number: 1400 print_number(item,output_buffer);1401 1402 cJsON_Raw: 1403 14041405 if size_t raw_length = 1406 1407 (item->valuestring ==1408 1409 1410 1411 ensure(output_buffer,raw_length); raw_length = strlen(item->valuestring) + 1412 output =14131414 1415 1416 1418 1419 memcpy(output,1)">1417 1420 cJsON_String: 1421 1423 cJsON_Array: print_string(item,1)">1422 1424 1426 cJsON_Object: print_array(item,1)">1425 1427 14291430 print_object(item,1)">1428 1431 1432 1433 1434 Build an array from input text. 1435 14361437 head of the linked List 1438 cJsON *head = NulL; 14391440 cJsON *current_item =if CJsON_nesTING_liMIT) 1441 (input_buffer->depth >=1442 to deeply nested 1443 14441445 1446 input_buffer->depth++1447 1448 not an array 1449 14501451 1452 1453 buffer_skip_whitespace(input_buffer); input_buffer->offset++1454 ]1455 1456 empty array 1457 success;1458 14591460 check if we skipped to the end of the buffer 1461 if1463 1464 (cannot_access_at_index(input_buffer,1)">1462 1465 input_buffer->offset--1466 1467 step back to character in front of the first element 1468 1469 loop through the comma separated array elements input_buffer->offset--1470 do1471 1472 allocate next item 1473 hooks));1474 cJsON *new_item = cJsON_New_Item(&(input_buffer->if1475 1476 (new_item ==1477 1478 1479 attach next item to List 1480 if1481 1482 (head == start the linked List 1483 new_item;1484 current_item = head =14851486 1487 add to the end and advance 1488 1489 current_item; current_item->next =1490 new_item->prev =14911492 current_item =1493 parse next value 1494 1495 buffer_skip_whitespace(input_buffer); input_buffer->offset++1496 parse_value(current_item,input_buffer))1497 1498 Failed to parse value 1499 15001501 1502 while 1503 1504 (can_access_at_index(input_buffer,0 1505 1506) || buffer_at_offset(input_buffer)[ expected end of array 1507 15081509 success: 1510 15111512 input_buffer->depth-- cJsON_Array; 1513 item->type = head;1514 item->child =15151516 1517 input_buffer->offset++1518 1519 1520 if 1521 1522 (head != cJsON_Delete(head); 1523 15241525 1526 1527 1528 Render an array to text 1529 15301531 1532 1533 unsigned 1534 size_t length = 1535 cJsON *current_element = item->1536 1537 1538 1539 1540 Compose the output array. 1541 opening square bracket 1542 15441545 output_pointer = ensure(output_buffer,1)">1543 1546 1547 1548 1549 1550 *output_pointer = 1551 output_buffer->offset++1552 output_buffer->depth++while 1553 1554 (current_element !=print_value(current_element,output_buffer)) 1555 15561557 1558 update_offset(output_buffer); 1559 ifnext) 1560 (current_element->15612 1562 length = (size_t) (output_buffer->format ? 1563 : 1564 output_pointer = ensure(output_buffer,length + 1565 1566 1567 1568 if *output_pointer++ = format) 1569(output_buffer->1570' 1571 *output_pointer++ = 1572 1573 length; *output_pointer = 1574 output_buffer->offset +=15751576 1577 current_element = current_element->1578 1580 1581 output_pointer = ensure(output_buffer,1)">1579 1582 1583 1584 1585 *output_pointer++ = 1586 *output_pointer = 1587 output_buffer->depth--1588 1589 1590 Build an object from the text. 1591 15921593 linked List head 1594 cJsON *head = NulL; 15951596 cJsON *current_item =1597 1598 1599 1600 1601 1602 input_buffer->depth++0 1603 1604) || (buffer_at_offset(input_buffer)[ not an object 1605 16061607 1608 1609 input_buffer->offset++} 1610 1611goto empty object 1612 success; 16131614 1615 1616 1617 1618 1619 input_buffer->offset--1620 1621 1622 1623 1624 input_buffer->offset--1625 1626 1627 1628 1629 cJsON *new_item = cJsON_New_Item(&(input_buffer->1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 current_item = head =1640 1641 1642 1643 1644 current_item->next =1645 new_item->prev =1646 current_item =1647 parse the name of the child 1648 16491650 input_buffer->offset++1652 Failed to parse name parse_string(current_item,1)">1651 1653 16541655 1656 swap valuestring and string,because we parsed the name 1657 string1658 current_item->1659 = current_item->1660 current_item->valuestring =: 1661 1662 invalID object 1663 16641665 parse the value 1666 16671668 input_buffer->offset++1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 expected end of object 1679 16801681 1682 1683 1684 input_buffer->depth-- cJsON_Object; 1685 item->type =16861687 item->child =1688 1689 input_buffer->offset++1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 Render an object to text. 1700 17011702 1703 1704 unsigned 1705 size_t length = 1706 cJsON *current_item = item->1707 1708 1709 1710 1711 Compose the output: 1712 1 fmt: {\n length = (size_t) (output_buffer->format ? 1713); 17151716 output_pointer = ensure(output_buffer,1)">1714 1717 1718 1719 1720 1721 *output_pointer++ = if output_buffer->depth++1722 1723 (output_buffer->1724 1725 *output_pointer++ = 1726 1727 output_buffer->offset +=while (current_item) 172817291730 1731 size_t i; 1732 depth);1733 output_pointer = ensure(output_buffer,output_buffer->17341735 1736 1737 0 1738 1739; i < output_buffer->depth; i++1740 1741 *output_pointer++ = depth; 1742 output_buffer->offset += output_buffer->17431744 print key 1745 ifchar 1746 (!print_string_ptr((unsigned 1747*)current_item->1748 1749 1750 1751 1752 1753 length = (size_t) (output_buffer->format ? 1754 output_pointer =1755 1756 1757 1758 1759 *output_pointer++ = 1760 1761 1762 *output_pointer++ = 1763 1764 output_buffer->offset += print value 1765 17671768 print_value(current_item,1)">1766 1769 1770 1771 print comma if not last 1772 10 length = ((size_t)(output_buffer->format ? 1773 : 1775) + (size_t)(current_item->next ? 1776 output_pointer = ensure(output_buffer,1)">1774 1777 1778 if 1779 1780 (current_item->1781 1782 *output_pointer++ = 1783 1784 1785 1786 1787 *output_pointer++ = 1788 1789 *output_pointer = 1790 output_buffer->offset +=1791 1792 current_item = current_item->1793 1 1794 output_pointer = ensure(output_buffer,output_buffer->format ? (output_buffer->depth + 1795) : 1796 1797 1798 1799 1800 size_t i; 1801 01 1802; i < (output_buffer->depth - 1803); i++1804 1805 *output_pointer++ = 1806 1807 1808 *output_pointer++ = 1809 *output_pointer = 1810 output_buffer->depth--1811 1812 1813 Get Array size/item / object item. 1814 array)1815 CJsON_PUBliC(18161817 1818 cJsON *child =1819 size_t size = if 1820 1821 (array ==1822 1823 1824 1825 1826 child = array->while 1827 1828(child !=1829 1830 size++1831 child = child->1832 FIXME: Can overflow here. Cannot be fixed without breaking the API 1833 1834)size; 1835 18361837 static array,size_t index) 1838 cJsON* get_array_item(18391840 1841 cJsON *current_child =1842 1843 1844 1845 1846 1847 while current_child = array->1848 1849 ((current_child != NulL) && (index > 1850 1851 index--1852 current_child = current_child->1853 current_child; 1854 18551856 index) 1857 CJsON_PUBliC(cJsON *) cJsON_GetArrayItem(1858if 1859 1860 (index < 1861 1862 1863 get_array_item(array,(size_t)index); 1864 18651866 static cJsON_bool case_sensitive) 1867 cJsON *get_object_item(18681869 1870 cJsON *current_element =if object 1871 ((1872 == NulL) || (name ==1873 1874 1875 1876 (case_sensitive) current_element = 1877 1878while string string ((current_element != NulL) && (current_element->1879 != NulL) && (strcmp(name,current_element->1880) != 1881 1882 current_element = current_element->1883 1884 1885 while char string ((current_element != NulL) && (case_insensitive_strcmp((1886*)name,1)">char*)(current_element->1887)) != 1888 1889 current_element = current_element->1890 1891 if NulL)) { 1892 ((current_element == NulL) || (current_element->18931894 1895 current_element; 1896 18971898 1899 1900 CJsON_PUBliC(cJsON *) cJsON_GetobjectItem(return 1901 1902 get_object_item(1903 1904 1905 CJsON_PUBliC(cJsON *) cJsON_GetobjectItemCaseSensitive(1906 1907 1908 1909 1910 CJsON_PUBliC(cJsON_bool) cJsON_HasObjectItem(return string 1911 cJsON_GetobjectItem(1912) ? 1913 Utility for array List handling. 1914 voID1916 1917 suffix_object(cJsON *prev,1)">1915 prev; prev->next =1918 item->prev =19191920 Utility for handling references. 1921 static1922 1923 cJsON *create_reference(1924 if cJsON *reference =1925 1926 (item ==1927 1928 1929 cJsON_New_Item(hooks); 1930 reference =if1931 1932 (reference ==1933 1934 1935 string 1937 memcpy(reference,item,1)">1936 reference-> cJsON_IsReference; =1938 reference->type |=1939 reference; reference->next = reference->prev =1940 19411942 static 1944 1945 cJsON_bool add_item_to_array(cJsON *array,1)">1943 1946 cJsON *child =if item)) 1947 ((item == NulL) || (array == NulL) || (array ==19481949 1950 1951 1952 1953 child = array-> * To find the last item in array quickly,we use prev in array 1954 1955if 1956 1957 (child == List is empty,start new one 1958 19591960 array->child =1961 item->prev =1962 item->next =1963 1964 append to the end 1965 ifprev) 1966 (child->1967prev,item); 1968 suffix_object(child->19691970 array->child->prev =1971 1972 while 1973 1974 (child->1975 1976 child = child->1978 1979 suffix_object(child,1)">1977 array->child->prev =1980 1981 1982 1983 1984 Add item to array/object. 1985 19871989 CJsON_PUBliC(cJsON_bool) cJsON_AddItemToArray(cJsON *array,1)">1986 1990 add_item_to_array(array,1)">1988 #if 1991 #pragma defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MInor__ > 5))))1992 1993 GCC diagnostic push1994 #pragma 1995 1996 GCC diagnostic ignored "-Wcast-qual" helper function to cast away const 1997 voIDvoID 1998* cast_away_const(1999* voID 2000 2001*)2002 #pragma 2003 2004 GCC diagnostic pop2005 2006 static const 2007 cJsON_bool add_item_to_object(cJsON * 2008 hooks,1)"> cJsON_bool constant_key)char 2009 int *new_key = cJsON_InvalID; 2010 new_type =2011object string object == NulL) || (2012 == NulL) || (item == NulL) || (2013 ==2014 2015 2016 (constant_key) 2017 2018char 2019 new_key = ( cJsON_StringIsConst;*)cast_away_const(2020 new_type = item->type |20212022 2023 char 2024 new_key = (if*)cJsON_strdup((2025 2026 (new_key ==2027 2028 2029 cJsON_StringIsConst; 2030 new_type = item->type & ~20312032 2033 2034 2035 2036 hooks->deallocate(item->2037 new_key; 2038 item-> new_type;2039 item->type =2040return 2041 2042 add_item_to_array(2043 2044 2045 CJsON_PUBliC(cJsON_bool) cJsON_AddItemToObject(cJsON *return 2046 2047 add_item_to_object(2048 Add an item to an object with constant string as key 2049 20502051 CJsON_PUBliC(cJsON_bool) cJsON_AddItemToObjectCS(cJsON *2052 2053 2054 2056 2057 CJsON_PUBliC(cJsON_bool) cJsON_AddItemReferencetoArray(cJsON *array,1)">2055 2058 2059 2060 2061 return 2062 2063 add_item_to_array(array,create_reference(item,1)">global_hooks));2064 2065 2066 CJsON_PUBliC(cJsON_bool) cJsON_AddItemReferencetoObject(cJsON *2067 2068 2069 2070 2071 2072 2073 2074 name) 2075 CJsON_PUBliC(cJsON*) cJsON_AddNullToObject(cJsON * 2076null cJsON_CreateNull(); cJsON *2077 =ifnull 2079 (add_item_to_object(null,1)">2078 2080 20812082 2083 2084 cJsON_Delete(2085 2086 2087 2088 CJsON_PUBliC(cJsON*) cJsON_AddTruetoObject(cJsON * cJsON_CreateTrue(); 2089 cJsON *true_item =20902091 true_item; 2092 20932094 cJsON_Delete(true_item); 2095 20962097 2098 2099 2100 CJsON_PUBliC(cJsON*) cJsON_AddFalsetoObject(cJsON * cJsON_CreateFalse(); 2101 cJsON *false_item =21022103 false_item; 2104 21052106 cJsON_Delete(false_item); 2107 21082109 2110 cJsON_bool boolean) 2111 CJsON_PUBliC(cJsON*) cJsON_AddBoolToObject(cJsON * 2112 cJsON_CreateBool(boolean); 2113 cJsON *bool_item =21142115 bool_item; 2116 21172118 cJsON_Delete(bool_item); 2119 21202121 2122 2123 2124 CJsON_PUBliC(cJsON*) cJsON_AddNumberToObject(cJsON * cJsON_CreateNumber(number); 2125 cJsON *number_item =21262127 number_item; 2128 21292130 cJsON_Delete(number_item); 2131 21322133 2134 2135 2136 CJsON_PUBliC(cJsON*) cJsON_AddStringToObject(cJsON * 2137 2138 cJsON *string_item = cJsON_CreateString(2139 string_item; 2140 21412142 cJsON_Delete(string_item); 2143 21442145 2146 raw) 2147 CJsON_PUBliC(cJsON*) cJsON_AddRawToObject(cJsON * 2148 cJsON_Createraw(raw); 2149 cJsON *raw_item =21502151 raw_item; 2152 21532154 cJsON_Delete(raw_item); 2155 21562157 2158 2159 2160 CJsON_PUBliC(cJsON*) cJsON_AddobjectToObject(cJsON * cJsON_CreateObject(); 2161 cJsON *object_item =21622163 object_item; 2164 21652166 cJsON_Delete(object_item); 2167 21682169 2170 2171 2172 CJsON_PUBliC(cJsON*) cJsON_AddArrayToObject(cJsON * cJsON_CreateArray(); 2173 cJsON *array =21742175 array; 2176 21772178 cJsON_Delete(array); 2179 21802181 2182 2183 2184 CJsON_PUBliC(cJsON *) cJsON_DetachItemViaPointer(cJsON *parent,1)"> item)if 2185 2186 ((parent == NulL) || (item ==2187 2188 2189 if child) 2190 (item != parent->2191 not the first element 2192 21932194 item->prev->next = item->if 2195 2196 (item->next != not the last element 2197 21982199 item->next->prev = item->2200 if 2201 2202 (item == parent-> first element 2203 22042205 parent->child = item-> make sure the detached item doesn't point anywhere anymore 2206 22072208 item->prev =2209 item->next =2210 2211 2212 2213 2214 CJsON_PUBliC(cJsON *) cJsON_DetachItemFromArray(cJsON *array,1)"> which)if 2215 2216 (which < 2217 2218 2219 cJsON_DetachItemViaPointer(array,get_array_item(array,(size_t)which)); 2220 22212222 2223 2224 CJsON_PUBliC( cJsON_Delete(cJsON_DetachItemFromArray(array,which)); 2225 22262227 2228 2229 CJsON_PUBliC(cJsON *) cJsON_DetachItemFromObject(cJsON *2230 2231 cJsON *to_detach = cJsON_GetobjectItem(return 2232 2233 cJsON_DetachItemViaPointer(2234 2235 2236 CJsON_PUBliC(cJsON *) cJsON_DetachItemFromObjectCaseSensitive(cJsON *2237 2238 cJsON *to_detach = cJsON_GetobjectItemCaseSensitive(2239 2240 2241 2242 2243 CJsON_PUBliC(2244 2245 cJsON_Delete(cJsON_DetachItemFromObject(2246 2247 2248 CJsON_PUBliC(2249 2250 cJsON_Delete(cJsON_DetachItemFromObjectCaseSensitive(2251 Replace array/object items with new ones. 2252 22532254 CJsON_PUBliC(cJsON_bool) cJsON_InsertItemInArray(cJsON *array,1)">newitem)2255 2256 cJsON *after_inserted =2257 2258 2259 2260 2261 2262 if after_inserted =2263 2264 (after_inserted ==2265 2266 2267 after_inserted; 2268 newitem->next =2269 newitem; newitem->prev = after_inserted->2270 after_inserted->prev =if2271 2272 (after_inserted == array->2273 2274 array->child =2275 2276 2277 2278 newitem->prev->next =2279 2280 2281 replacement) 2282 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemViaPointer(cJsON * 2283if 2284 2285 ((parent == NulL) || (replacement == NulL) || (item ==2286 2287 2288 if 2289 2290 (replacement ==2291 2292 2293 2294 2295 replacement->next = item->2296 replacement->prev = item->if 2297 2298 (replacement->next != replacement; 2299 replacement->next->prev =2300if 2301 2302 (parent->child ==2303 2304 parent->child =2305 2306 * To find the last item in array quickly,we use prev in array. { 2307 * We can't modify the last item's next pointer where this item was the parent's child2308 2309if 2310 2311 (replacement->prev !=2312 2313 replacement->prev->next =2314 2315 2316 2317 item->next = cJsON_Delete(item); item->prev =2318 23192320 2321 2322 2324 2325 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemInArray(cJsON *array,1)">2323 2326 2327 2328 2329 2331 2332 cJsON_ReplaceItemViaPointer(array,(size_t)which),1)">2330 static replacement,cJsON_bool case_sensitive) 2333 cJsON_bool replace_item_in_object(cJsON *2334if 2335 2336 ((replacement == NulL) || (2337 2338 2339 replace the name in the replacement 2340 if2341 2342 (!(replacement->type & cJsON_StringIsConst) && (replacement->2343 2344 cJsON_free(replacement->string 2345 replacement->2346 = (2347 replacement->type &= ~return 2348 2349 cJsON_ReplaceItemViaPointer(2350 2351 2352 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemInObject(cJsON *return 2353 2354 replace_item_in_object(2355 2356 2357 CJsON_PUBliC(cJsON_bool) cJsON_ReplaceItemInObjectCaseSensitive(cJsON *2358 2359 2360 Create basic types: 2361 23622363 CJsON_PUBliC(cJsON *) cJsON_CreateNull(2364 (item) cJsON *item = cJsON_New_Item(&2365 23662367 2368 item->type =2369 2370 2371 2372 2373 2374 CJsON_PUBliC(cJsON *) cJsON_CreateTrue(2375 2376 cJsON *item = cJsON_New_Item(&2377 2378 2379 item->type =2380 2381 2382 2383 2384 2385 CJsON_PUBliC(cJsON *) cJsON_CreateFalse(2386 2387 cJsON *item = cJsON_New_Item(&2388 2389 2390 item->type =2391 2392 2393 2394 ) cJsON_CreateBool(cJsON_bool boolean) 2395 CJsON_PUBliC(cJsON *23962397 2398 cJsON *item = cJsON_New_Item(&2399 cJsON_True : cJsON_False; 2400 item->type = boolean ?24012402 2403 2404 2405 num) 2406 CJsON_PUBliC(cJsON *) cJsON_CreateNumber(24072408 2409 cJsON *item = cJsON_New_Item(&2410 2411 num; item->type =2412 item->valuedouble =24132414 if 2415 2416 (num >=2417 2418 item->valueint =if 2419 2420 (num <= (2421 2422 item->valueint =2423 2424 )num; 2425 item->valueint = (24262427 2428 2429 2430 2431 2432 2433 CJsON_PUBliC(cJsON *) cJsON_CreateString(2434 2435 cJsON *item = cJsON_New_Item(&2436 2437 2438 item->type =if item->valuestring = (2439 2440(!item-> cJsON_Delete(item); 2441 24422443 2444 2445 2446 2447 2448 2449 2450 CJsON_PUBliC(cJsON *) cJsON_CreateStringReference(2451 2452 cJsON *item = cJsON_New_Item(&2453 2454 2455 item->type = cJsON_String |2456 item->valuestring = (2457 2458 2459 2460 2461 2462 CJsON_PUBliC(cJsON *) cJsON_CreateObjectReference(2463 2464 cJsON *item = cJsON_New_Item(&2465 )cast_away_const(child); item->type = cJsON_Object |2466 item->child = (cJsON*24672468 2469 2470 2471 child) { 2472 CJsON_PUBliC(cJsON *) cJsON_CreateArrayReference(24732474 cJsON *item = cJsON_New_Item(&2475 2476 item->type = cJsON_Array |2477 item->child = (cJsON*2478 2479 2480 2481 raw) 2482 CJsON_PUBliC(cJsON *) cJsON_Createraw(24832484 2485 cJsON *item = cJsON_New_Item(&2486 cJsON_Raw; 2487 item->type =char2489 item->valuestring = (2490*)raw,1)">2488 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 CJsON_PUBliC(cJsON *) cJsON_CreateArray(2501 2502 cJsON *item = cJsON_New_Item(&2503 cJsON_Array; 2504 item->type=25052506 2507 2508 2509 2510 2511 CJsON_PUBliC(cJsON *) cJsON_CreateObject(2512 (item) cJsON *item = cJsON_New_Item(&2513 25142515 2516 item->type =2517 2518 2519 2520 Create Arrays: 2521 count)2522 CJsON_PUBliC(cJsON *) cJsON_CreateIntArray(25232524 2525 size_t i = 2526 cJsON *n =2527 cJsON *p =2528 cJsON *a =if 0 2529 ((count < 2530) || (numbers ==2531 2532 2533 2534 for a =0 2535(i = 2536; a && (i < (size_t)count); i++ cJsON_CreateNumber(numbers[i]); 2537 n =n)2538 2539 cJsON_Delete(a); 2540 25412542 if i) 2543(!2544 n; 2545 a->child =25462547 2548 suffix_object(p,n); 2549 25502551 2552 p =2553 a; 2554 25552556 2557 2558 CJsON_PUBliC(cJsON *) cJsON_CreatefloatArray(2559 2560 size_t i = 2561 cJsON *n =2562 cJsON *p =2563 cJsON *a =2564 2565 2566 2567 2568 2569 2570 a =2571 2572 )numbers[i]); 2573 n = cJsON_CreateNumber((25742575 2576 2577 2578 2579 2580 2581 2582 a->child =2583 2584 2585 2586 2587 2588 p =2589 2590 2591 2592 2593 2594 CJsON_PUBliC(cJsON *) cJsON_CreateDoubleArray(2595 2596 size_t i = 2597 cJsON *n =2598 cJsON *p =2599 cJsON *a =2600 2601 2602 2603 2604 2605 2606 a =0 2607 2608;a && (i < (size_t)count); i++2609 2610 n =2611 2612 2613 2614 2615 2616 2617 2618 a->child =2619 2620 2621 2622 2623 2624 p =2625 2626 2627 2628 2629 2630 CJsON_PUBliC(cJsON *) cJsON_CreateStringArray(2631 2632 size_t i = 2633 cJsON *n =2634 cJsON *p =2635 cJsON *a =0 2636 2637) || (strings ==2638 2639 2640 2641 2642 a =2643 2644 cJsON_CreateString(strings[i]); 2645 n =26462647 2648 2649 2650 2651 2652 2653 2654 a->child =2655 2656 2657 2658 2659 2660 p =2661 2662 2663 2664 Duplication 2665 26662667 CJsON_PUBliC(cJsON *) cJsON_Duplicate(2668 2669 cJsON *newitem =2670 cJsON *child =2671 cJsON *next =2672 cJsON *newchild = Bail on bad ptr 2673 26742675 2676 2677 Create new item 2678 26792680 newitem = cJsON_New_Item(&2681 2682 2683 copy over all vars 2684 cJsON_IsReference);2685 newitem->type = item->type & (~valueint;2686 newitem->valueint = item->2687if newitem->valuedouble = item->2688 2689 (item->char char newitem->valuestring = (if*)cJsON_strdup((unsigned 2691*)item->valuestring,1)">2690 2692 (!newitem->2693 2694 2695 2696 2697 string string newitem->2698 = (item->type&cJsON_StringIsConst) ? item->2699 : (2700 2701 2702 2703 If non-recursive,then we're done! 2704 recurse)2705 27062707 2708 Walk the ->next chain for the child. 2709 2710while child = item->2711 2712 (child != Duplicate (with recurse) each item in the ->next chain 2713 newchild = cJsON_Duplicate(child,1)">true); newchild)2714 27152716 2717 if 2718 2719 (next != If newitem->child already set,then crosswire ->prev and ->next and move on 2720 newchild;2721 next->next =27222723 newchild->prev =2724 next =2725 2726 Set newitem->child and move to it 2727 27282729 newitem->child =2730 next =2731 2732 child = child->2733 2734 2735 2736 if 2737 2738 (newitem != cJsON_Delete(newitem); 2739 27402741 2742 2743 2744 voID input) 2745 skip_oneline_comment(2746// 2747 *input += static_strlen(2748for ' input)) (; (*input)[2749; ++(*2750if ) { 2751 ((*input)[27522753 *input += static_strlen(2754 2755 2756 2757 voID 2758 2759 skip_multiline_comment(/* 2760 *input += static_strlen(27612762 2763 if * ' (((*input)[12764) && ((*input)[2765] == */ 2766 *input += static_strlen(27672768 2769 2770 2771 voID char 2772 Minify_string(0 **input,1)">output) {2773 (*output)[2774] = (*input)[2775 *input += static_strlen(2776 *output += static_strlen(2777 voID output)) { 2778)++(*input),++(*27792780 (*output)[2781 2782 2783 (*output)[2784 *input += static_strlen(2785 *output += static_strlen()) { 2786 } 12787 (*output)[2788] = (*input)[2789 *input += static_strlen(2790 *output += static_strlen(2791 2792 2793 Json) 2794 CJsON_PUBliC(2795char Json; 2796 *into =2797if 2798 2799 (Json ==2800 2801 2802 while 2803 2804 (Json[switch 2805 2806 (Json[2807 2808 2809 2810 2811 2812 Json++2813 2814 if 2815 2816 (Json[2817 2818 skip_oneline_comment(&2819 2820 2821 else skip_multiline_comment(&2822 } 28232824 Json++2825 2826 2827 2828 2829 Minify_string(&Json,1)">into);2830 2831 0 2832 into[2833] = Json[2834 Json++2835 into++2836 2837 and null-terminate. 2838 28392840 *into = 2841 2842 2843 CJsON_PUBliC(cJsON_bool) cJsON_IsInvalID(2844 2845 2846 2847 2848 return 0xFF 2849 (item->type & 2850) ==2851 2852 2853 CJsON_PUBliC(cJsON_bool) cJsON_IsFalse(2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 CJsON_PUBliC(cJsON_bool) cJsON_IsTrue(2864 2865 2866 2867 2868 0xff 2869 2870) ==2871 2872 2873 2874 CJsON_PUBliC(cJsON_bool) cJsON_IsBool(2875 2876 2877 2878 2879 return 2880 2881 (item->type & (cJsON_True | cJsON_False)) != 2882 2883 CJsON_PUBliC(cJsON_bool) cJsON_IsNull(2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 CJsON_PUBliC(cJsON_bool) cJsON_IsNumber(2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 CJsON_PUBliC(cJsON_bool) cJsON_Isstring(2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 CJsON_PUBliC(cJsON_bool) cJsON_IsArray(2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 CJsON_PUBliC(cJsON_bool) cJsON_IsObject(2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 CJsON_PUBliC(cJsON_bool) cJsON_IsRaw(2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 CJsON_PUBliC(cJsON_bool) cJsON_Compare(if 0xFF 0xFF ((a == NulL) || (b == NulL) || ((a->type & cJsON_IsInvalID(a))) != (b->type & 2944)) ||29452946 2947 2948 check if type is valID 2949 switch2950 2951 (a->type & 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 IDentical objects are equal 2966 if2967 2968 (a ==2969 2970 2971 2972 2973 in these cases and equal type is enough 2974 29752976 2977 2978 2979 2980 if valuedouble)) 2981 (compare_double(a->valuedouble,b->29822983 2984 2985 2986 2987 2988 if 2989 2990 ((a->valuestring == NulL) || (b->valuestring ==2991 2992 if 2993 2994 (strcmp(a->valuestring,b->valuestring) == 2995 2996 2997 2998 2999 3000 3001 3002 3003 cJsON *a_element = a->3004 cJsON *b_element = b->for NulL);) 3005 (; (a_element != NulL) && (b_element !=3006cJsON_Compare(a_element,b_element,case_sensitive)) 3007 30083009 3010 3011 3012 3013 a_element = a_element->3014 b_element = b_element->3015 one of the arrays is longer than the other 3016 if b_element) { 3017 (a_element !=30183019 3020 3021 3022 3023 3024 3025 3026 3027 cJsON *a_element = cJsON_ArrayForEach(a_element,a) cJsON *b_element =3028 3029 Todo This has O(n^2) runtime,which is horrible! 3030 3031if b_element = get_object_item(b,a_element->3032 3033 (b_element ==3034 3035 3036 3037 3038 3039 3040 3041 3042 doing this twice,once on a and b to prevent true comparison if a subset of b 3043 * Todo: Do this the proper way,this is just a fix for Now 3044 cJsON_ArrayForEach(b_element,b)3045 30463047 if a_element = get_object_item(a,b_element->3048 3049 (a_element ==3050 3051 3052 3054 3055 cJsON_Compare(b_element,a_element,1)">3053 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 ) cJsON_malloc(size_t size) 3067 CJsON_PUBliC(3068 global_hooks.allocate(size); 3069 30703071 3072 3073 CJsON_PUBliC(3074 VIEw Code global_hooks.deallocate( }
参考:
https://blog.csdn.net/shizhe0123/article/details/94742514
https://blog.csdn.net/fengxinlinux/article/details/53121287
https://www.cnblogs.com/skullboyer/p/8152157.html
总结以上是内存溢出为你收集整理的不可不知的JSON处理库(cJSON)全部内容,希望文章能够帮你解决不可不知的JSON处理库(cJSON)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)