不可不知的JSON处理库cJSON

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的打包和解析,更多处理玩法,见文章末尾链接。

开始cJSON

cJSON合并到您的项目

因为整个库只有一个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 256
100 #define cJSON_StringIsConst 512
101 
102 103 typedef  cJSON
104 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_Hooks
126 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_LIMIT
137 #define CJSON_NESTING_LIMIT 1000
138 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 so
207  * 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 so
210  * 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 before
226  * 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 will
251  * 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 #endif
View 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 == '\0' 144         {
 145              146         }
 147  148 
 149     return tolower(*string1) - tolower(*string2);
 150  151 
 152 typedef  internal_hooks
 153  154     allocate)(size_t size);
 155     void (CJSON_CDECL *deallocate)(pointer);
 156     void *(CJSON_CDECL *reallocate)(pointer,size_t size);
 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 CJSON_CDECL internal_free(pointer)
 166  167     (pointer);
 168  169 void * CJSON_CDECL internal_realloc( 170  171     realloc(pointer,size);
 172  173  174 #define internal_malloc malloc
 175 #define internal_free free
 176 #define internal_realloc realloc
 177  178 
 179  strlen of character literals resolved at compile time  180 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
 181 
 182 static internal_hooks global_hooks = { internal_malloc,internal_free,internal_realloc };
 183 
 184 static unsigned char* cJSON_strdup(char* const internal_hooks *  hooks)
 185  186     size_t length =  187     unsigned char *copy = 188 
 189     if (string == NULL)
 190  191          192  193 
 194     length = strlen((char*)string) + sizeof("" 195     copy = (unsigned char*)hooks->allocate(length);
 196     if (copy == 197  198          199  200     memcpy(copy,length);
 201 
 202      copy;
 203  204 
 205 CJSON_PUBLIC( 206  207     if (hooks == 208  209          Reset hooks  210         global_hooks.allocate =  211         global_hooks.deallocate =  212         global_hooks.reallocate =  213          214  215 
 216     global_hooks.allocate =  217     if (hooks->malloc_fn != 218  219         global_hooks.allocate = hooks->malloc_fn;
 220  221 
 222     global_hooks.deallocate =  223     if (hooks->free_fn != 224  225         global_hooks.deallocate = hooks->free_fn;
 226  227 
 228      use realloc only if both free and malloc are used  229     global_hooks.reallocate = 230     if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == ))
 231  232         global_hooks.reallocate =  233  234  235 
 236  Internal constructor.  237 static cJSON *cJSON_New_Item( 238  239     cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
 240     if (node)
 241  242         memset(node,1)">',1)"> 243  244 
 245      node;
 246  247 
 248  Delete a cJSON structure.  249 CJSON_PUBLIC(item)
 250  251     cJSON *next = 252     while (item != 253  254         next = item-> 255         if (!(item->type & cJSON_IsReference) && (item->child != 256  257             cJSON_Delete(item-> 258  259         if (!(item->type & cJSON_IsReference) && (item->valuestring != 260  261             global_hooks.deallocate(item-> 262  263         if (!(item->type & cJSON_StringIsConst) && (item->string != 264  265             global_hooks.deallocate(item-> 266  267         global_hooks.deallocate(item);
 268         item = next;
 269  270  271 
 272  get the decimal point character of the current locale  273 char get_decimal_point( 274  275  276     struct lconv *lconv = localeconv();
 277     return (unsigned char) lconv->decimal_point[ 278  279     . 280  281  282 
 283 typedef struct
 284  285     content;
 286     size_t length;
 287     size_t offset;
 288     size_t depth;  How deeply nested (in arrays/objects) is the input at the current offset.  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 can_read(buffer,size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
 294  check if the buffer can be accessed at the given index (starting with 0)  295 #define can_access_at_index(buffer,index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
 296 #define cannot_access_at_index(buffer,index) (!can_access_at_index(buffer,index))
 297  get a pointer to the buffer at the position  298 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
 299 
 300  Parse the input text to generate a number,and populate the result into item.  301 static cJSON_bool parse_number(cJSON *  input_buffer)
 302  303     double number =  304     unsigned char *after_end = 305     unsigned char number_c_string[64 306     unsigned char decimal_point = get_decimal_point();
 307     size_t i =  308 
 309     if ((input_buffer == NULL) || (input_buffer->content == 310  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 '\0' not necessarily being available for marking the end of the input  317     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer,i); i++ 318  319         switch (buffer_at_offset(input_buffer)[i])
 320  321             case 0:
 322             1 323             2 324             3 325             4 326             5 327             6 328             7 329             8 330             9 331             + 332             - 333             e 334             E 335                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
 336                 break 337 
 338              339                 number_c_string[i] = decimal_point;
 340                  341 
 342             default 343                 goto loop_end;
 344  345  346 loop_end:
 347     number_c_string[i] =  348 
 349     number = strtod((char*)number_c_string,(char**)&after_end);
 350     if (number_c_string == after_end)
 351  352         false;  parse_error  353  354 
 355     item->valuedouble = number;
 356 
 357      use saturation in case of overflow  358     if (number >= INT_MAX)
 359  360         item->valueint = INT_MAX;
 361  362     else if (number <= ()INT_MIN)
 363  364         item->valueint = INT_MIN;
 365  366     else
 367  368         item->valueint = ()number;
 369  370 
 371     item->type = cJSON_Number;
 372 
 373     input_buffer->offset += (size_t)(after_end - number_c_string);
 374     true 375  376 
 377  don't ask me,but the original cJSON_SetNumberValue returns an integer or double  378 CJSON_PUBLIC( number)
 379  380      381  382         object->valueint = 383  384      385  386          387  388      389  390         object->valueint = ( 391  392 
 393     object->valuedouble = 394  395 
 396 CJSON_PUBLIC(valuestring)
 397  398      399      if object's type is not cJSON_String or is cJSON_IsReference,it should not set valuestring  400     if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
 401  402          403  404     if (strlen(valuestring) <= strlen(object->valuestring))
 405  406         strcpy(valuestring,valuestring);
 407          408  409     copy = (char*) cJSON_strdup((char*)valuestring,&global_hooks);
 410      411  412          413  414     object->valuestring != 415  416         cJSON_free( 417  418     object->valuestring = 419 
 420      421  422 
 423 typedef  424  425     unsigned buffer;
 426  427  428     size_t depth;  current nesting depth (for formatted printing)  429     cJSON_bool noalloc;
 430     cJSON_bool format;  is this print a formatted print  431  432 } printbuffer;
 433 
 434  realloc printbuffer if necessary to have at least "needed" bytes more  435 char* ensure(printbuffer *  p,size_t needed)
 436  437     unsigned char *newbuffer = 438     size_t newsize =  439 
 440     if ((p == NULL) || (p->buffer == 441  442          443  444 
 445     if ((p->length > 0) && (p->offset >= p->length))
 446  447          make sure that offset is valid  448          449  450 
 451     if (needed > 452  453          sizes bigger than INT_MAX are currently not supported  454          455  456 
 457     needed += p->offset +  458     if (needed <= p->length)
 459  460         return p->buffer + p->offset;
 461  462 
 463     if (p->noalloc) {
 464          465  466 
 467      calculate new buffer size  468     if (needed > (INT_MAX /  469  470          overflow of int,use INT_MAX if possible  471         if (needed <= 472  473             newsize = 474  475          476  477              478  479  480      481  482         newsize = needed *  483  484 
 485     if (p->hooks.reallocate != 486  487          reallocate with realloc if available  488         newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer,newsize);
 489         if (newbuffer == 490  491             p->hooks.deallocate(p->buffer);
 492             p->length =  493             p->buffer = 494 
 495              496  497  498      499  500          otherwise reallocate manually  501         newbuffer = (unsigned char*)p->hooks.allocate(newsize);
 502         newbuffer)
 503  504             p->hooks.deallocate(p-> 505             p->length =  506             p->buffer = 507 
 508              509  510          (newbuffer)
 511  512             memcpy(newbuffer,p->buffer,p->offset +  513  514         p->hooks.deallocate(p-> 515  516     p->length = newsize;
 517     p->buffer = newbuffer;
 518 
 519     return newbuffer + p-> 520  521 
 522  calculate the new length of the string in a printbuffer and update the offset  523 void update_offset(printbuffer *  buffer)
 524  525     char *buffer_pointer = 526     if ((buffer == NULL) || (buffer->buffer == 527  528          529  530     buffer_pointer = buffer->buffer + buffer-> 531 
 532     buffer->offset += strlen((char*)buffer_pointer);
 533  534 
 535  securely comparison of floating-point variables  536 static cJSON_bool compare_double(double a,1)"> b)
 537  538     double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
 539     return (fabs(a - b) <= maxVal * DBL_EPSILON);
 540  541 
 542  Render the number nicely from the given item into a string.  543 static cJSON_bool print_number( output_buffer)
 544  545     unsigned char *output_pointer = 546     double d = item-> 547     int length =  548     size_t i =  549     unsigned char number_buffer[26] = {0};  temporary buffer to print the number into  550     unsigned  551     double test = 0.0 552 
 553     if (output_buffer == 554  555          556  557 
 558      This checks for NaN and Infinity  559     if (isnan(d) || isinf(d))
 560  561         length = sprintf((char*)number_buffer,1)">null 562  563      564  565          Try 15 decimal places of precision to avoid nonsignificant nonzero digits  566         length = sprintf((%1.15g 567 
 568          Check whether the original double can be recovered  569         if ((sscanf((%lg1) || !compare_double(()test,d))
 570  571              If not,print with 17 decimal places of precision  572             length = sprintf((%1.17g 573  574  575 
 576      sprintf failed or buffer overrun occurred  577     if ((length < 0) || (length > (int)(sizeof(number_buffer) - )))
 578  579          580  581 
 582      reserve appropriate space in the output  583     output_pointer = ensure(output_buffer,(size_t)length +  584     if (output_pointer == 585  586          587  588 
 589      copy the printed number to the output and replace locale
 590      * dependent decimal point with '.'  591     0; i < ((size_t)length); i++ 592  593         if (number_buffer[i] == decimal_point)
 594  595             output_pointer[i] =  596             continue 597  598 
 599         output_pointer[i] = number_buffer[i];
 600  601     output_pointer[i] =  602 
 603     output_buffer->offset += (size_t)length;
 604 
 605      606  607 
 608  parse 4 digit hexadecimal number  609 static unsigned parse_hex4( input)
 610  611     unsigned int h =  612     size_t i =  613 
 614     0; i < 4; i++ 615  616          parse digit  617         if ((input[i] >= ') && (input[i] <=  618  619             h += (unsigned int) input[i] -  620  621         AF 622  623             h += (unsigned int) 10 + input[i] -  624  625         af 626  627             h += (unsigned  628  629          invalid  630  631              632  633 
 634         if (i < 3 635  636              shift left to make place for the next nibble  637             h = h << 4 638  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 char utf16_literal_to_utf8(const input_pointer,1)">const input_end,unsigned output_pointer)
 647  648     long unsigned int codepoint =  649     unsigned int first_code =  650     char *first_sequence = input_pointer;
 651     unsigned char utf8_length =  652     unsigned char utf8_position =  653     unsigned char sequence_length =  654     unsigned char first_byte_mark =  655 
 656     if ((input_end - first_sequence) < 6 657  658          input ends unexpectedly  659          fail;
 660  661 
 662      get the first utf16 sequence  663     first_code = parse_hex4(first_sequence +  664 
 665      check that the code is valid  666     if (((first_code >= 0xDC00) && (first_code <= 0xDFFF 667  668          669  670 
 671      UTF16 surrogate pair  672     if ((first_code >= 0xD800) && (first_code <= 0xDBFF 673  674         char *second_sequence = first_sequence +  675         unsigned int second_code =  676         sequence_length = 12;  \uXXXX\uXXXX  677 
 678         if ((input_end - second_sequence) <  679  680              681              682  683 
 684         if ((second_sequence[0] != \\') || (second_sequence[1] != u 685  686              missing second half of the surrogate pair  687              688  689 
 690          get the second utf16 sequence  691         second_code = parse_hex4(second_sequence +  692          693         if ((second_code < 0xDC00) || (second_code >  694  695              invalid second half of the surrogate pair  696              697  698 
 699 
 700          calculate the unicode codepoint from the surrogate pair  701         codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF 702  703      704  705         sequence_length = 6;  \uXXXX  706         codepoint = first_code;
 707  708 
 709      encode as UTF-8
 710      * takes at maximum 4 bytes to encode:
 711      * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  712     if (codepoint < 0x80 713  714          normal ascii,encoding 0xxxxxxx  715         utf8_length =  716  717     0x800 718  719          two bytes,encoding 110xxxxx 10xxxxxx  720         utf8_length =  721         first_byte_mark = 0xC0;  11000000  722  723     0x10000 724  725          three bytes,encoding 1110xxxx 10xxxxxx 10xxxxxx  726         utf8_length =  727         first_byte_mark = 0xE0;  11100000  728  729     if (codepoint <= 0x10FFFF 730  731          four bytes,encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx  732         utf8_length =  733         first_byte_mark = 0xF0;  11110000  734  735      736  737          invalid unicode codepoint  738          739  740 
 741      encode as utf8  742     for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position-- 743  744          10xxxxxx  745         (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF 746         codepoint >>=  747  748      encode first byte  749     if (utf8_length >  750  751         (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF 752  753      754  755         (*output_pointer)[char)(codepoint & 0x7F 756  757 
 758     *output_pointer += utf8_length;
 759 
 760      sequence_length;
 761 
 762 fail:
 763      764  765 
 766  Parse the input text into an unescaped cinput,and populate item.  767 static cJSON_bool parse_string(cJSON *  768  769     char *input_pointer = buffer_at_offset(input_buffer) +  770     char *input_end = buffer_at_offset(input_buffer) +  771     unsigned  772     unsigned char *output = 773 
 774      not a string  775     if (buffer_at_offset(input_buffer)[\" 776  777          778  779 
 780  781          calculate approximate size of the output (overestimate)  782         size_t allocation_length =  783         size_t skipped_bytes =  784         while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end !=  785  786              is escape sequence  787             if (input_end[0] ==  788             {
 789                 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer-> 790                 {
 791                      prevent buffer overflow when last input character is a backslash  792                      793                 }
 794                 skipped_bytes++ 795                 input_end++ 796             }
 797             input_end++ 798  799         if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end !=  800  801             goto fail;  string ended unexpectedly  802  803 
 804          This is at most how much we need for the output  805         allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
 806         output = (unsigned char*)input_buffer->hooks.allocate(allocation_length +  807         if (output == 808  809              allocation failure  810  811  812 
 813     output_pointer = output;
 814      loop through the string literal  815     while (input_pointer < input_end)
 816  817         if (*input_pointer !=  818  819             *output_pointer++ = *input_pointer++ 820  821          escape sequence  822          823  824             unsigned  825             if ((input_end - input_pointer) <  826  827                  828  829 
 830             switch (input_pointer[])
 831  832                 b 833                     *output_pointer++ = \b 834                      835                  836                     *output_pointer++ = \f 837                      838                 n 839                     *output_pointer++ = \n 840                      841                 r 842                     *output_pointer++ = \r 843                      844                 t 845                     *output_pointer++ = \t 846                      847                  848                  849                 / 850                     *output_pointer++ = input_pointer[ 851                      852 
 853                  UTF-16 literal  854                  855                     sequence_length = utf16_literal_to_utf8(input_pointer,input_end,1)">output_pointer);
 856                     if (sequence_length ==  857                     {
 858                          failed to convert UTF16-literal to UTF-8  859                          860                     }
 861                      862 
 863                  864                      865  866             input_pointer += 867  868  869 
 870      zero terminate the output  871     *output_pointer =  872 
 873     item->type = cJSON_String;
 874     item->valuestring = ()output;
 875 
 876     input_buffer->offset = (size_t) (input_end - input_buffer->content);
 877     input_buffer->offset++ 878 
 879      880 
 881  882     if (output != 883  884         input_buffer->hooks.deallocate(output);
 885  886 
 887     if (input_pointer != 888  889         input_buffer->offset = (size_t)(input_pointer - input_buffer-> 890  891 
 892      893  894 
 895  Render the cstring provided to an escaped version that can be printed.  896 static cJSON_bool print_string_ptr(const input,1)"> 897  898     char *input_pointer = 899     unsigned  900     unsigned  901     size_t output_length =  902      numbers of additional characters needed for escaping  903     size_t escape_characters =  904 
 905      906  907          908  909 
 910      empty string  911     if (input == 912  913         output = ensure(output_buffer,1)">\"\" 914          915  916              917  918         strcpy((char*)output,1)"> 919 
 920          921  922 
 923      set "flag" to 1 if something needs to be escaped  924     for (input_pointer = input; *input_pointer; input_pointer++ 925  926         switch (*input_pointer)
 927  928              929              930              931              932              933              934              935                  one character escape sequence  936                 escape_characters++ 937                  938              939                 if (*input_pointer < 32 940  941                      UTF-16 escape sequence uXXXX  942                     escape_characters += 5 943  944                  945  946  947     output_length = (size_t)(input_pointer - input) + escape_characters;
 948 
 949     output = ensure(output_buffer,output_length +  950      951  952          953  954 
 955      no characters have to be escaped  956     if (escape_characters ==  957  958         output[0] =  959         memcpy(output +  960         output[output_length + 1] =  961         output[output_length + 2] =  962 
 963          964  965 
 966     output[ 967     output_pointer = output +  968      copy the string  969     for (input_pointer = input; *input_pointer != '; (void)input_pointer++,output_pointer++ 970  971         if ((*input_pointer > 31) && (*input_pointer != ') && (*input_pointer !=  972  973              normal character,copy  974             *output_pointer = *input_pointer;
 975  976          977  978              character needs to be escaped  979             *output_pointer++ =  980              981  982                  983                     *output_pointer =  984                      985                  986                     *output_pointer =  987                      988                  989                     *output_pointer =  990                      991                  992                     *output_pointer =  993                      994                  995                     *output_pointer =  996                      997                  998                     *output_pointer =  999                     1000                 1001                     *output_pointer = 1002                     1003                 1004                      escape and print as unicode codepoint 1005                     sprintf((char*)output_pointer,1)">u%04xinput_pointer);
1006                     output_pointer += 1007                     1008 1009 1010 1011     output[output_length + 1012     output[output_length + 1013 
1014     1015 1016 
1017  Invoke print_string_ptr (which is useful) on an item. 1018 static cJSON_bool print_string( p)
1019 1020     return print_string_ptr((unsigned char*)item->1021 1022 
1023  Predeclare these prototypes. 1024 static cJSON_bool parse_value(cJSON *  input_buffer);
1025 static cJSON_bool print_value( output_buffer);
1026 static cJSON_bool parse_array(cJSON * 1027 static cJSON_bool print_array(1028 static cJSON_bool parse_object(cJSON * 1029 static cJSON_bool print_object(1030 
1031  Utility to jump whitespace and cr/lf 1032 static parse_buffer *buffer_skip_whitespace(parse_buffer * 1033 1034     if ((buffer == NULL) || (buffer->content ==1035 1036         1037 1038 
1039     if (cannot_access_at_index(buffer,1)">1040 1041          buffer;
1042 1043 
1044     while (can_access_at_index(buffer,1)">0) && (buffer_at_offset(buffer)[0] <= 1045 1046        buffer->offset++1047 1048 
1049     if (buffer->offset == buffer->1050 1051         buffer->offset--1052 1053 
1054     1055 1056 
1057  skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer 1058 static parse_buffer *skip_utf8_bom(parse_buffer * 1059 1060     if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 1061 1062         1063 1064 
1065     if (can_access_at_index(buffer,1)">4) && (strncmp((char*)buffer_at_offset(buffer),1)">\xEF\xBB\xBF3) == 1066 1067         buffer->offset += 1068 1069 
1070     1071 1072 
1073 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(1074 1075     size_t buffer_length;
1076 
1077     if (NULL == value)
1078 1079         1080 1081 
1082      Adding null character size due to require_null_terminated. 1083     buffer_length = strlen(value) + 1084 
1085      cJSON_ParseWithLengthOpts(value,buffer_length,return_parse_end,require_null_terminated);
1086 1087 
1088  Parse an object - create a new root,and populate. 1089 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(1090 1091     parse_buffer buffer = { 0,{  } };
1092     cJSON *item =1093 
1094      reset error position 1095     global_error.json =1096     global_error.position = 1097 
1098     if (value == NULL || 0 == buffer_length)
1099 1100         1101 1102 
1103     buffer.content = ()value;
1104     buffer.length = buffer_length; 
1105     buffer.offset = 1106     buffer.hooks = global_hooks;
1107 
1108     item = cJSON_New_Item(&1109     if (item == NULL)  memory fail 1110 1111         1112 1113 
1114     if (!parse_value(item,buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1115 1116          parse failure. ep is set. 1117         1118 1119 
1120      if we require null-terminated JSON without appended garbage,skip and then check for a null terminator 1121      (require_null_terminated)
1122 1123         buffer_skip_whitespace(&1124         if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[1125 1126             1127 1128 1129      (return_parse_end)
1130 1131         *return_parse_end = (char*)buffer_at_offset(&1132 1133 
1134      item;
1135 
1136 1137     if (item !=1138 1139         cJSON_Delete(item);
1140 1141 
1142     if (value !=1143 1144         error local_error;
1145         local_error.json = (1146         local_error.position = 1147 
1148         if (buffer.offset < buffer.length)
1149 1150             local_error.position = buffer.offset;
1151 1152         if (buffer.length > 1153 1154             local_error.position = buffer.length - 1155 1156 
1157         if (return_parse_end !=1158 1159             *return_parse_end = (char*)local_error.json + local_error.position;
1160 1161 
1162         global_error = local_error;
1163 1164 
1165     1166 1167 
1168  Default options for cJSON_Parse 1169 CJSON_PUBLIC(cJSON *) cJSON_Parse(value)
1170 1171     return cJSON_ParseWithOpts(value,1)">1172 1173 
1174 CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(1175 1176     return cJSON_ParseWithLengthOpts(value,1)">1177 1178 
1179 #define cjson_min(a,b) (((a) < (b)) ? (a) : (b))
1180 
1181 char *print(1182 1183     const size_t default_buffer_size = 2561184     printbuffer buffer[1185     unsigned char *printed =1186 
1187     memset(buffer,1)">(buffer));
1188 
1189      create buffer 1190     buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1191     buffer->length = default_buffer_size;
1192     buffer->format = format;
1193     buffer->hooks = *hooks;
1194     if (buffer->buffer ==1195 1196         1197 1198 
1199      print the value 1200     print_value(item,buffer))
1201 1202         1203 1204     update_offset(buffer);
1205 
1206      check if reallocate is available 1207     if (hooks->reallocate !=1208 1209         printed = (unsigned char*) hooks->reallocate(buffer->buffer,buffer->offset + 1210         if (printed == NULL) {
1211             1212 1213         buffer->buffer =1214 1215      otherwise copy the JSON over to a new buffer 1216 1217         printed = (unsigned char*) hooks->allocate(buffer->offset + 1218         1219 1220             1221 1222         memcpy(printed,buffer->buffer,cjson_min(buffer->length,1)">1223         printed[buffer->offset] = ';  just to be sure 1224 
1225          free the buffer 1226         hooks->deallocate(buffer->1227 1228 
1229      printed;
1230 
1231 1232     if (buffer->buffer !=1233 1234         hooks->deallocate(buffer->1235 1236 
1237     if (printed !=1238 1239         hooks->deallocate(printed);
1240 1241 
1242     1243 1244 
1245  Render a cJSON item/entity/structure to text. 1246 CJSON_PUBLIC(1247 1248     char*)print(item,1)">true,1)">1249 1250 
1251 CJSON_PUBLIC(1252 1253     false,1)">1254 1255 
1256 CJSON_PUBLIC(1257 1258     printbuffer p = { 1259 
1260     if (prebuffer < 1261 1262         1263 1264 
1265     p.buffer = (unsigned )global_hooks.allocate((size_t)prebuffer);
1266     p.buffer)
1267 1268         1269 1270 
1271     p.length = (size_t)prebuffer;
1272     p.offset = 1273     p.noalloc = 1274     p.format = fmt;
1275     p.hooks =1276 
1277     if (!print_value(item,1)">p))
1278 1279         global_hooks.deallocate(p.buffer);
1280         1281 1282 
1283     )p.buffer;
1284 1285 
1286 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item,1)"> cJSON_bool format)
1287 1288     printbuffer p = { 1289 
1290     0) || (buffer ==1291 1292         1293 1294 
1295     p.buffer = (unsigned )buffer;
1296     p.length =1297     p.offset = 1298     p.noalloc = 1299     p.format =1300     p.hooks =1301 
1302     return print_value(item,1)">p);
1303 1304 
1305  Parser core - when encountering text,process appropriately. 1306 1307 1308     1309 1310          no input 1311 1312 
1313      parse the different types of values 1314      null 1315     if (can_read(input_buffer,1)">char*)buffer_at_offset(input_buffer),1)">4) == 1316 1317         item->type = cJSON_NULL;
1318         input_buffer->offset += 1319         1320 1321      false 1322     5) && (strncmp((false5) == 1323 1324         item->type = cJSON_False;
1325         input_buffer->offset += 1326         1327 1328      true 1329     true1330 1331         item->type = cJSON_True;
1332         item->valueint = 1333         input_buffer->offset += 1334         1335 1336      string 1337     if (can_access_at_index(input_buffer,1)">0) && (buffer_at_offset(input_buffer)[1338 1339          parse_string(item,input_buffer);
1340 1341      number 1342     0) && ((buffer_at_offset(input_buffer)[') || ((buffer_at_offset(input_buffer)[0] >= ') && (buffer_at_offset(input_buffer)[))))
1343 1344          parse_number(item,1)">1345 1346      array 1347     [1348 1349          parse_array(item,1)">1350 1351      object 1352     {1353 1354          parse_object(item,1)">1355 1356 
1357     1358 1359 
1360  Render a value to text. 1361 1362 1363     unsigned 1364 
1365     if ((item == NULL) || (output_buffer ==1366 1367         1368 1369 
1370     switch ((item->type) & 1371 1372         case cJSON_NULL:
1373             output = ensure(output_buffer,1)">1374             1375 1376                 1377 1378             strcpy((1379             1380 
1381          cJSON_False:
1382             output = ensure(output_buffer,1)">1383             1384 1385                 1386 1387             strcpy((1388             1389 
1390          cJSON_True:
1391             output = ensure(output_buffer,1)">1392             1393 1394                 1395 1396             strcpy((1397             1398 
1399          cJSON_Number:
1400              print_number(item,output_buffer);
1401 
1402          cJSON_Raw:
1403 1404             size_t raw_length = 1405             if (item->valuestring ==1406 1407                 1408 1409 
1410             raw_length = strlen(item->valuestring) + 1411             output = ensure(output_buffer,raw_length);
1412             1413 1414                 1415 1416             memcpy(output,1)">1417             1418 1419 
1420          cJSON_String:
1421              print_string(item,1)">1422 
1423          cJSON_Array:
1424              print_array(item,1)">1425 
1426          cJSON_Object:
1427              print_object(item,1)">1428 
1429         1430             1431 1432 1433 
1434  Build an array from input text. 1435 1436 1437     cJSON *head = NULL;  head of the linked list 1438     cJSON *current_item =1439 
1440     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1441 1442          to deeply nested 1443 1444     input_buffer->depth++1445 
1446     1447 1448          not an array 1449         1450 1451 
1452     input_buffer->offset++1453     buffer_skip_whitespace(input_buffer);
1454     ]1455 1456          empty array 1457          success;
1458 1459 
1460      check if we skipped to the end of the buffer 1461     if (cannot_access_at_index(input_buffer,1)">1462 1463         input_buffer->offset--1464         1465 1466 
1467      step back to character in front of the first element 1468     input_buffer->offset--1469      loop through the comma separated array elements 1470     do
1471 1472          allocate next item 1473         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1474         if (new_item ==1475 1476             1477 1478 
1479          attach next item to list 1480         if (head ==1481 1482              start the linked list 1483             current_item = head = new_item;
1484 1485         1486 1487              add to the end and advance 1488             current_item->next =1489             new_item->prev = current_item;
1490             current_item =1491 1492 
1493          parse next value 1494         input_buffer->offset++1495         buffer_skip_whitespace(input_buffer);
1496         parse_value(current_item,input_buffer))
1497 1498              failed to parse value 1499 1500 1501 1502     while (can_access_at_index(input_buffer,1503 
1504     0) || buffer_at_offset(input_buffer)[1505 1506          expected end of array 1507 1508 
1509 success:
1510     input_buffer->depth--1511 
1512     item->type = cJSON_Array;
1513     item->child = head;
1514 
1515     input_buffer->offset++1516 
1517     1518 
1519 1520     if (head !=1521 1522         cJSON_Delete(head);
1523 1524 
1525     1526 1527 
1528  Render an array to text 1529 1530 1531     unsigned 1532     size_t length = 1533     cJSON *current_element = item->1534 
1535     1536 1537         1538 1539 
1540      Compose the output array. 1541      opening square bracket 1542     output_pointer = ensure(output_buffer,1)">1543     1544 1545         1546 1547 
1548     *output_pointer = 1549     output_buffer->offset++1550     output_buffer->depth++1551 
1552     while (current_element !=1553 1554         print_value(current_element,output_buffer))
1555 1556             1557 1558         update_offset(output_buffer);
1559         if (current_element->next)
1560 1561             length = (size_t) (output_buffer->format ? 2 : 1562             output_pointer = ensure(output_buffer,length + 1563             1564 1565                 1566 1567             *output_pointer++ = 1568             if(output_buffer->format)
1569 1570                 *output_pointer++ = ' 1571 1572             *output_pointer = 1573             output_buffer->offset += length;
1574 1575         current_element = current_element->1576 1577 
1578     output_pointer = ensure(output_buffer,1)">1579     1580 1581         1582 1583     *output_pointer++ = 1584     *output_pointer = 1585     output_buffer->depth--1586 
1587     1588 1589 
1590  Build an object from the text. 1591 1592 1593     cJSON *head = NULL;  linked list head 1594     cJSON *current_item =1595 
1596     1597 1598         1599 1600     input_buffer->depth++1601 
1602     0) || (buffer_at_offset(input_buffer)[1603 1604          not an object 1605 1606 
1607     input_buffer->offset++1608 1609     }1610 1611         goto success;  empty object 1612 1613 
1614     1615     1616 1617         input_buffer->offset--1618         1619 1620 
1621     1622     input_buffer->offset--1623     1624     1625 1626         1627         cJSON *new_item = cJSON_New_Item(&(input_buffer->1628         1629 1630             1631 1632 
1633         1634         1635 1636             1637             current_item = head =1638 1639         1640 1641             1642             current_item->next =1643             new_item->prev =1644             current_item =1645 1646 
1647          parse the name of the child 1648         input_buffer->offset++1649 1650         parse_string(current_item,1)">1651 1652              failed to parse name 1653 1654 1655 
1656          swap valuestring and string,because we parsed the name 1657         current_item->string = current_item->1658         current_item->valuestring =1659 
1660         :1661 1662              invalid object 1663 1664 
1665          parse the value 1666         input_buffer->offset++1667 1668         1669 1670             1671 1672 1673 1674     1675 
1676     1677 1678          expected end of object 1679 1680 
1681 1682     input_buffer->depth--1683 
1684     item->type = cJSON_Object;
1685     item->child =1686 
1687     input_buffer->offset++1688     1689 
1690 1691     1692 1693 1694 1695 
1696     1697 1698 
1699  Render an object to text. 1700 1701 1702     unsigned 1703     size_t length = 1704     cJSON *current_item = item->1705 
1706     1707 1708         1709 1710 
1711      Compose the output: 1712     length = (size_t) (output_buffer->format ? 1);  fmt: {\n 1713     output_pointer = ensure(output_buffer,1)">1714     1715 1716         1717 1718 
1719     *output_pointer++ = 1720     output_buffer->depth++1721     if (output_buffer->1722 1723         *output_pointer++ = 1724 1725     output_buffer->offset +=1726 
1727     while (current_item)
1728 1729         1730 1731             size_t i;
1732             output_pointer = ensure(output_buffer,output_buffer->depth);
1733             1734 1735                 1736 1737             0; i < output_buffer->depth; i++1738 1739                 *output_pointer++ = 1740 1741             output_buffer->offset += output_buffer->depth;
1742 1743 
1744          print key 1745         if (!print_string_ptr((unsigned char*)current_item->1746 1747             1748 1749 1750 
1751         length = (size_t) (output_buffer->format ? 1752         output_pointer =1753         1754 1755             1756 1757         *output_pointer++ = 1758         1759 1760             *output_pointer++ = 1761 1762         output_buffer->offset +=1763 
1764          print value 1765         print_value(current_item,1)">1766 1767             1768 1769 1770 
1771          print comma if not last 1772         length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1773         output_pointer = ensure(output_buffer,1)">1774         1775 1776             1777 1778         if (current_item->1779 1780             *output_pointer++ = 1781 1782 
1783         1784 1785             *output_pointer++ = 1786 1787         *output_pointer = 1788         output_buffer->offset +=1789 
1790         current_item = current_item->1791 1792 
1793     output_pointer = ensure(output_buffer,output_buffer->format ? (output_buffer->depth + 1) : 1794     1795 1796         1797 1798     1799 1800         size_t i;
1801         0; i < (output_buffer->depth - 1); i++1802 1803             *output_pointer++ = 1804 1805 1806     *output_pointer++ = 1807     *output_pointer = 1808     output_buffer->depth--1809 
1810     1811 1812 
1813  Get Array size/item / object item. 1814 CJSON_PUBLIC(array)
1815 1816     cJSON *child =1817     size_t size = 1818 
1819     if (array ==1820 1821         1822 1823 
1824     child = array->1825 
1826     while(child !=1827 1828         size++1829         child = child->1830 1831 
1832      FIXME: Can overflow here. Cannot be fixed without breaking the API 1833 
1834     )size;
1835 1836 
1837 static cJSON* get_array_item(array,size_t index)
1838 1839     cJSON *current_child =1840 
1841     1842 1843         1844 1845 
1846     current_child = array->1847     while ((current_child != NULL) && (index > 1848 1849         index--1850         current_child = current_child->1851 1852 
1853      current_child;
1854 1855 
1856 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem( index)
1857 1858     if (index < 1859 1860         1861 1862 
1863      get_array_item(array,(size_t)index);
1864 1865 
1866 static cJSON *get_object_item( cJSON_bool case_sensitive)
1867 1868     cJSON *current_element =1869 
1870     if ((object == NULL) || (name ==1871 1872         1873 1874 
1875     current_element = 1876      (case_sensitive)
1877 1878         while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name,current_element->string) != 1879 1880             current_element = current_element->1881 1882 1883     1884 1885         while ((current_element != NULL) && (case_insensitive_strcmp((char*)name,1)">char*)(current_element->string)) != 1886 1887             current_element = current_element->1888 1889 1890 
1891     if ((current_element == NULL) || (current_element-> NULL)) {
1892         1893 1894 
1895      current_element;
1896 1897 
1898 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(1899 1900     return get_object_item(1901 1902 
1903 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(1904 1905     1906 1907 
1908 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(1909 1910     return cJSON_GetObjectItem(string) ? 1911 1912 
1913  Utility for array list handling. 1914 void suffix_object(cJSON *prev,1)">1915 1916     prev->next =1917     item->prev = prev;
1918 1919 
1920  Utility for handling references. 1921 static cJSON *create_reference(1922 1923     cJSON *reference =1924     if (item ==1925 1926         1927 1928 
1929     reference = cJSON_New_Item(hooks);
1930     if (reference ==1931 1932         1933 1934 
1935     memcpy(reference,item,1)">1936     reference->string =1937     reference->type |= cJSON_IsReference;
1938     reference->next = reference->prev =1939      reference;
1940 1941 
1942 static cJSON_bool add_item_to_array(cJSON *array,1)">1943 1944     cJSON *child =1945 
1946     if ((item == NULL) || (array == NULL) || (array == item))
1947 1948         1949 1950 
1951     child = array->1952     1953      * To find the last item in array quickly,we use prev in array
1954      1955     if (child ==1956 1957          list is empty,start new one 1958         array->child =1959         item->prev =1960         item->next =1961 1962     1963 1964          append to the end 1965         if (child->prev)
1966 1967             suffix_object(child->prev,item);
1968             array->child->prev =1969 1970         1971 1972             while (child->1973 1974                 child = child->1975 1976             suffix_object(child,1)">1977             array->child->prev =1978 1979 1980 
1981     1982 1983 
1984  Add item to array/object. 1985 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array,1)">1986 1987      add_item_to_array(array,1)">1988 1989 
1990 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1991     #pragma GCC diagnostic push
1992 1993 1994 #pragma GCC diagnostic ignored "-Wcast-qual"
1995 1996  helper function to cast away const 1997 void* cast_away_const(void* 1998 1999     void*)2000 2001 2002     #pragma GCC diagnostic pop
2003 2004 
2005 
2006 static cJSON_bool add_item_to_object(cJSON * const hooks,1)"> cJSON_bool constant_key)
2007 2008     char *new_key =2009     int new_type = cJSON_Invalid;
2010 
2011     object == NULL) || (string == NULL) || (item == NULL) || (object ==2012 2013         2014 2015 
2016      (constant_key)
2017 2018         new_key = (char*)cast_away_const(2019         new_type = item->type | cJSON_StringIsConst;
2020 2021     2022 2023         new_key = (char*)cJSON_strdup((2024         if (new_key ==2025 2026             2027 2028 
2029         new_type = item->type & ~cJSON_StringIsConst;
2030 2031 
2032     2033 2034         hooks->deallocate(item->2035 2036 
2037     item-> new_key;
2038     item->type = new_type;
2039 
2040     return add_item_to_array(2041 2042 
2043 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *2044 2045     return add_item_to_object(2046 2047 
2048  Add an item to an object with constant string as key 2049 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *2050 2051     2052 2053 
2054 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array,1)">2055 2056     2057 2058         2059 2060 
2061     return add_item_to_array(array,create_reference(item,1)">global_hooks));
2062 2063 
2064 CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *2065 2066     2067 2068         2069 2070 
2071     2072 2073 
2074 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON *  name)
2075 2076     cJSON *null = cJSON_CreateNull();
2077     if (add_item_to_object(null,1)">2078 2079         null2080 2081 
2082     cJSON_Delete(2083     2084 2085 
2086 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * 2087 2088     cJSON *true_item = cJSON_CreateTrue();
2089     2090 2091          true_item;
2092 2093 
2094     cJSON_Delete(true_item);
2095     2096 2097 
2098 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * 2099 2100     cJSON *false_item = cJSON_CreateFalse();
2101     2102 2103          false_item;
2104 2105 
2106     cJSON_Delete(false_item);
2107     2108 2109 
2110 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON *  cJSON_bool boolean)
2111 2112     cJSON *bool_item = cJSON_CreateBool(boolean);
2113     2114 2115          bool_item;
2116 2117 
2118     cJSON_Delete(bool_item);
2119     2120 2121 
2122 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * 2123 2124     cJSON *number_item = cJSON_CreateNumber(number);
2125     2126 2127          number_item;
2128 2129 
2130     cJSON_Delete(number_item);
2131     2132 2133 
2134 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * 2135 2136     cJSON *string_item = cJSON_CreateString(2137     2138 2139          string_item;
2140 2141 
2142     cJSON_Delete(string_item);
2143     2144 2145 
2146 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON *  raw)
2147 2148     cJSON *raw_item = cJSON_CreateRaw(raw);
2149     2150 2151          raw_item;
2152 2153 
2154     cJSON_Delete(raw_item);
2155     2156 2157 
2158 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * 2159 2160     cJSON *object_item = cJSON_CreateObject();
2161     2162 2163          object_item;
2164 2165 
2166     cJSON_Delete(object_item);
2167     2168 2169 
2170 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * 2171 2172     cJSON *array = cJSON_CreateArray();
2173     2174 2175          array;
2176 2177 
2178     cJSON_Delete(array);
2179     2180 2181 
2182 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent,1)"> item)
2183 2184     if ((parent == NULL) || (item ==2185 2186         2187 2188 
2189     if (item != parent->child)
2190 2191          not the first element 2192         item->prev->next = item->2193 2194     if (item->next !=2195 2196          not the last element 2197         item->next->prev = item->2198 2199 
2200     if (item == parent->2201 2202          first element 2203         parent->child = item->2204 2205      make sure the detached item doesn't point anywhere anymore 2206     item->prev =2207     item->next =2208 
2209     2210 2211 
2212 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array,1)"> which)
2213 2214     if (which < 2215 2216         2217 2218 
2219      cJSON_DetachItemViaPointer(array,get_array_item(array,(size_t)which));
2220 2221 
2222 CJSON_PUBLIC(2223 2224     cJSON_Delete(cJSON_DetachItemFromArray(array,which));
2225 2226 
2227 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *2228 2229     cJSON *to_detach = cJSON_GetObjectItem(2230 
2231     return cJSON_DetachItemViaPointer(2232 2233 
2234 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *2235 2236     cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(2237 
2238     2239 2240 
2241 CJSON_PUBLIC(2242 2243     cJSON_Delete(cJSON_DetachItemFromObject(2244 2245 
2246 CJSON_PUBLIC(2247 2248     cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(2249 2250 
2251  Replace array/object items with new ones. 2252 CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array,1)">newitem)
2253 2254     cJSON *after_inserted =2255 
2256     2257 2258         2259 2260 
2261     after_inserted =2262     if (after_inserted ==2263 2264         2265 2266 
2267     newitem->next = after_inserted;
2268     newitem->prev = after_inserted->2269     after_inserted->prev = newitem;
2270     if (after_inserted == array->2271 2272         array->child =2273 2274     2275 2276         newitem->prev->next =2277 2278     2279 2280 
2281 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *  replacement)
2282 2283     if ((parent == NULL) || (replacement == NULL) || (item ==2284 2285         2286 2287 
2288     if (replacement ==2289 2290         2291 2292 
2293     replacement->next = item->2294     replacement->prev = item->2295 
2296     if (replacement->next !=2297 2298         replacement->next->prev = replacement;
2299 2300     if (parent->child ==2301 2302         parent->child =2303 2304     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 child
2308          2309         if (replacement->prev !=2310 2311             replacement->prev->next =2312 2313 2314 
2315     item->next =2316     item->prev =2317     cJSON_Delete(item);
2318 
2319     2320 2321 
2322 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array,1)">2323 2324     2325 2326         2327 2328 
2329      cJSON_ReplaceItemViaPointer(array,(size_t)which),1)">2330 2331 
2332 static cJSON_bool replace_item_in_object(cJSON *replacement,cJSON_bool case_sensitive)
2333 2334     if ((replacement == NULL) || (2335 2336         2337 2338 
2339      replace the name in the replacement 2340     if (!(replacement->type & cJSON_StringIsConst) && (replacement->2341 2342         cJSON_free(replacement->2343 2344     replacement->string = (2345     replacement->type &= ~2346 
2347     return cJSON_ReplaceItemViaPointer(2348 2349 
2350 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *2351 2352     return replace_item_in_object(2353 2354 
2355 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *2356 2357     2358 2359 
2360  Create basic types: 2361 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(2362 2363     cJSON *item = cJSON_New_Item(&2364     (item)
2365 2366         item->type =2367 2368 
2369     2370 2371 
2372 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(2373 2374     cJSON *item = cJSON_New_Item(&2375     2376 2377         item->type =2378 2379 
2380     2381 2382 
2383 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(2384 2385     cJSON *item = cJSON_New_Item(&2386     2387 2388         item->type =2389 2390 
2391     2392 2393 
2394 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2395 2396     cJSON *item = cJSON_New_Item(&2397     2398 2399         item->type = boolean ? cJSON_True : cJSON_False;
2400 2401 
2402     2403 2404 
2405 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber( num)
2406 2407     cJSON *item = cJSON_New_Item(&2408     2409 2410         item->type =2411         item->valuedouble = num;
2412 
2413         2414         if (num >=2415 2416             item->valueint =2417 2418         if (num <= (2419 2420             item->valueint =2421 2422         2423 2424             item->valueint = ()num;
2425 2426 2427 
2428     2429 2430 
2431 CJSON_PUBLIC(cJSON *) cJSON_CreateString(2432 2433     cJSON *item = cJSON_New_Item(&2434     2435 2436         item->type =2437         item->valuestring = (2438         if(!item->2439 2440             cJSON_Delete(item);
2441             2442 2443 2444 
2445     2446 2447 
2448 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(2449 2450     cJSON *item = cJSON_New_Item(&2451     2452 2453         item->type = cJSON_String |2454         item->valuestring = (2455 2456 
2457     2458 2459 
2460 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(2461 2462     cJSON *item = cJSON_New_Item(&2463     2464         item->type = cJSON_Object |2465         item->child = (cJSON*)cast_away_const(child);
2466 2467 
2468     2469 2470 
2471 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(child) {
2472     cJSON *item = cJSON_New_Item(&2473     2474         item->type = cJSON_Array |2475         item->child = (cJSON*2476 2477 
2478     2479 2480 
2481 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(raw)
2482 2483     cJSON *item = cJSON_New_Item(&2484     2485 2486         item->type = cJSON_Raw;
2487         item->valuestring = (char*)raw,1)">2488         2489 2490 2491             2492 2493 2494 
2495     2496 2497 
2498 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(2499 2500     cJSON *item = cJSON_New_Item(&2501     2502 2503         item->type=cJSON_Array;
2504 2505 
2506     2507 2508 
2509 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(2510 2511     cJSON *item = cJSON_New_Item(&2512      (item)
2513 2514         item->type =2515 2516 
2517     2518 2519 
2520  Create Arrays: 2521 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray( count)
2522 2523     size_t i = 2524     cJSON *n =2525     cJSON *p =2526     cJSON *a =2527 
2528     if ((count < 0) || (numbers ==2529 2530         2531 2532 
2533     a =2534     for(i = 0; a && (i < (size_t)count); i++2535 2536         n = cJSON_CreateNumber(numbers[i]);
2537         n)
2538 2539             cJSON_Delete(a);
2540             2541 2542         if(!i)
2543 2544             a->child = n;
2545 2546         2547 2548             suffix_object(p,n);
2549 2550         p =2551 2552 
2553      a;
2554 2555 
2556 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(2557 2558     size_t i = 2559     cJSON *n =2560     cJSON *p =2561     cJSON *a =2562 
2563     2564 2565         2566 2567 
2568     a =2569 
2570     2571 2572         n = cJSON_CreateNumber(()numbers[i]);
2573         2574 2575 2576             2577 2578         2579 2580             a->child =2581 2582         2583 2584 2585 2586         p =2587 2588 
2589     2590 2591 
2592 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(2593 2594     size_t i = 2595     cJSON *n =2596     cJSON *p =2597     cJSON *a =2598 
2599     2600 2601         2602 2603 
2604     a =2605 
2606     0;a && (i < (size_t)count); i++2607 2608         n =2609         2610 2611 2612             2613 2614         2615 2616             a->child =2617 2618         2619 2620 2621 2622         p =2623 2624 
2625     2626 2627 
2628 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(2629 2630     size_t i = 2631     cJSON *n =2632     cJSON *p =2633     cJSON *a =2634 
2635     0) || (strings ==2636 2637         2638 2639 
2640     a =2641 
2642     2643 2644         n = cJSON_CreateString(strings[i]);
2645         2646 2647 2648             2649 2650         2651 2652             a->child =2653 2654         2655 2656 2657 2658         p =2659 2660 
2661     2662 2663 
2664  Duplication 2665 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(2666 2667     cJSON *newitem =2668     cJSON *child =2669     cJSON *next =2670     cJSON *newchild =2671 
2672      Bail on bad ptr 2673     2674 2675         2676 2677      Create new item 2678     newitem = cJSON_New_Item(&2679     2680 2681         2682 2683      Copy over all vars 2684     newitem->type = item->type & (~cJSON_IsReference);
2685     newitem->valueint = item->valueint;
2686     newitem->valuedouble = item->2687     if (item->2688 2689         newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring,1)">2690         if (!newitem->2691 2692             2693 2694 2695     2696 2697         newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (2698         2699 2700             2701 2702 2703      If non-recursive,then we're done! 2704     recurse)
2705 2706         2707 2708      Walk the ->next chain for the child. 2709     child = item->2710     while (child !=2711 2712         newchild = cJSON_Duplicate(child,1)">true);  Duplicate (with recurse) each item in the ->next chain 2713         newchild)
2714 2715             2716 2717         if (next !=2718 2719              If newitem->child already set,then crosswire ->prev and ->next and move on 2720             next->next = newchild;
2721             newchild->prev =2722             next =2723 2724         2725 2726              Set newitem->child and move to it 2727             newitem->child =2728             next =2729 2730         child = child->2731 2732 
2733     2734 
2735 2736     if (newitem !=2737 2738         cJSON_Delete(newitem);
2739 2740 
2741     2742 2743 
2744 void skip_oneline_comment(input)
2745 2746     *input += static_strlen(//2747 
2748     for (; (*input)['; ++(*input))
2749 2750         if ((*input)[) {
2751             *input += static_strlen(2752             2753 2754 2755 2756 
2757 void skip_multiline_comment(2758 2759     *input += static_strlen(/*2760 
2761     2762 2763         if (((*input)[*') && ((*input)[1] == 2764 2765             *input += static_strlen(*/2766             2767 2768 2769 2770 
2771 void minify_string(char **input,1)">output) {
2772     (*output)[0] = (*input)[2773     *input += static_strlen(2774     *output += static_strlen(2775 
2776 
2777     void)++(*input),++(*output)) {
2778         (*output)[2779 
2780         2781             (*output)[2782             *input += static_strlen(2783             *output += static_strlen(2784             2785         } )) {
2786             (*output)[1] = (*input)[2787             *input += static_strlen(2788             *output += static_strlen(2789 2790 2791 2792 
2793 CJSON_PUBLIC(json)
2794 2795     char *into = json;
2796 
2797     if (json ==2798 2799         2800 2801 
2802     while (json[2803 2804         switch (json[2805 2806             2807             2808             2809             2810                 json++2811                 2812 
2813             2814                 if (json[2815 2816                     skip_oneline_comment(&2817 2818                 2819 2820                     skip_multiline_comment(&2821                 } else2822                     json++2823 2824                 2825 
2826             2827                 minify_string(&json,1)">into);
2828                 2829 
2830             2831                 into[0] = json[2832                 json++2833                 into++2834 2835 2836 
2837      and null-terminate. 2838     *into = 2839 2840 
2841 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(2842 2843     2844 2845         2846 2847 
2848     return (item->type & 0xFF) ==2849 2850 
2851 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(2852 2853     2854 2855         2856 2857 
2858     2859 2860 
2861 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(2862 2863     2864 2865         2866 2867 
2868     0xff) ==2869 2870 
2871 
2872 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(2873 2874     2875 2876         2877 2878 
2879     return (item->type & (cJSON_True | cJSON_False)) != 2880 2881 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(2882 2883     2884 2885         2886 2887 
2888     2889 2890 
2891 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(2892 2893     2894 2895         2896 2897 
2898     2899 2900 
2901 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(2902 2903     2904 2905         2906 2907 
2908     2909 2910 
2911 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(2912 2913     2914 2915         2916 2917 
2918     2919 2920 
2921 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(2922 2923     2924 2925         2926 2927 
2928     2929 2930 
2931 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(2932 2933     2934 2935         2936 2937 
2938     2939 2940 
2941 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(2942 2943     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2944 2945         2946 2947 
2948      check if type is valid 2949     switch (a->type & 2950 2951         2952         2953         2954         2955         2956         2957         2958         2959             2960 
2961         2962             2963 2964 
2965      identical objects are equal 2966     if (a ==2967 2968         2969 2970 
2971     2972 2973          in these cases and equal type is enough 2974         2975         2976         2977             2978 
2979         2980             if (compare_double(a->valuedouble,b->valuedouble))
2981 2982                 2983 2984             2985 
2986         2987         2988             if ((a->valuestring == NULL) || (b->valuestring ==2989 2990                 2991 2992             if (strcmp(a->valuestring,b->valuestring) == 2993 2994                 2995 2996 
2997             2998 
2999         3000 3001             cJSON *a_element = a->3002             cJSON *b_element = b->3003 
3004             for (; (a_element != NULL) && (b_element != NULL);)
3005 3006                 cJSON_Compare(a_element,b_element,case_sensitive))
3007 3008                     3009 3010 
3011                 a_element = a_element->3012                 b_element = b_element->3013 3014 
3015              one of the arrays is longer than the other 3016             if (a_element != b_element) {
3017                 3018 3019 
3020             3021 3022 
3023         3024 3025             cJSON *a_element =3026             cJSON *b_element =3027             cJSON_ArrayForEach(a_element,a)
3028 3029                  TODO This has O(n^2) runtime,which is horrible! 3030                 b_element = get_object_item(b,a_element->3031                 if (b_element ==3032 3033                     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 3046                 a_element = get_object_item(a,b_element->3047                 if (a_element ==3048 3049                     3050 3051 
3052                 cJSON_Compare(b_element,a_element,1)">3053 3054                     3055 3056 3057 
3058             3059 3060 
3061         3062             3063 3064 3065 
3066 CJSON_PUBLIC() cJSON_malloc(size_t size)
3067 3068      global_hooks.allocate(size);
3069 3070 
3071 CJSON_PUBLIC(3072 3073     global_hooks.deallocate(3074 }
View Code

 

 参考:

https://blog.csdn.net/shizhe0123/article/details/94742514

https://blog.csdn.net/fengxinlinux/article/details/53121287

https://www.cnblogs.com/skullboyer/p/8152157.html

相关文章

一.C语言中的static关键字 在C语言中,static可以用来修饰局...
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
浅谈C/C++中的指针和数组(一)指针是C/C++...
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...