Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party CJSON
提交
a1c022fe
T
Third Party CJSON
项目概览
OpenHarmony
/
Third Party CJSON
大约 1 年 前同步成功
通知
6
Star
22
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party CJSON
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a1c022fe
编写于
10月 29, 2016
作者:
M
Max Bruckner
提交者:
GitHub
10月 29, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #37 from DaveGamble/reformatting
Reformat cJSON_Utils.c and test.c
上级
0c23e8dd
ddeca827
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
1052 addition
and
476 deletion
+1052
-476
cJSON.c
cJSON.c
+1
-1
cJSON.h
cJSON.h
+5
-5
cJSON_Utils.c
cJSON_Utils.c
+753
-335
cJSON_Utils.h
cJSON_Utils.h
+29
-15
test.c
test.c
+264
-120
未找到文件。
cJSON.c
浏览文件 @
a1c022fe
cJSON.h
浏览文件 @
a1c022fe
cJSON_Utils.c
浏览文件 @
a1c022fe
...
...
@@ -4,392 +4,810 @@
#include <stdio.h>
#include "cJSON_Utils.h"
static
int
cJSONUtils_strcasecmp
(
const
char
*
s1
,
const
char
*
s2
)
static
int
cJSONUtils_strcasecmp
(
const
char
*
s1
,
const
char
*
s2
)
{
if
(
!
s1
)
return
(
s1
==
s2
)
?
0
:
1
;
if
(
!
s2
)
return
1
;
for
(;
tolower
(
*
s1
)
==
tolower
(
*
s2
);
++
s1
,
++
s2
)
if
(
*
s1
==
0
)
return
0
;
if
(
!
s1
)
{
return
(
s1
==
s2
)
?
0
:
1
;
/* both NULL? */
}
if
(
!
s2
)
{
return
1
;
}
for
(;
tolower
(
*
s1
)
==
tolower
(
*
s2
);
++
s1
,
++
s2
)
{
if
(
*
s1
==
0
)
{
return
0
;
}
}
return
tolower
(
*
(
const
unsigned
char
*
)
s1
)
-
tolower
(
*
(
const
unsigned
char
*
)
s2
);
}
/* JSON Pointer implementation: */
static
int
cJSONUtils_Pstrcasecmp
(
const
char
*
a
,
const
char
*
e
)
static
int
cJSONUtils_Pstrcasecmp
(
const
char
*
a
,
const
char
*
e
)
{
if
(
!
a
||
!
e
)
return
(
a
==
e
)
?
0
:
1
;
for
(;
*
a
&&
*
e
&&
*
e
!=
'/'
;
a
++
,
e
++
)
{
if
(
*
e
==
'~'
)
{
if
(
!
(
e
[
1
]
==
'0'
&&
*
a
==
'~'
)
&&
!
(
e
[
1
]
==
'1'
&&
*
a
==
'/'
))
return
1
;
else
e
++
;}
else
if
(
tolower
(
*
a
)
!=
tolower
(
*
e
))
return
1
;
if
(
!
a
||
!
e
)
{
return
(
a
==
e
)
?
0
:
1
;
/* both NULL? */
}
for
(;
*
a
&&
*
e
&&
(
*
e
!=
'/'
);
a
++
,
e
++
)
/* compare until next '/' */
{
if
(
*
e
==
'~'
)
{
/* check for escaped '~' (~0) and '/' (~1) */
if
(
!
((
e
[
1
]
==
'0'
)
&&
(
*
a
==
'~'
))
&&
!
((
e
[
1
]
==
'1'
)
&&
(
*
a
==
'/'
)))
{
/* invalid escape sequence or wrong character in *a */
return
1
;
}
else
{
e
++
;
}
}
else
if
(
tolower
(
*
a
)
!=
tolower
(
*
e
))
{
return
1
;
}
if
((
*
e
!=
0
&&
*
e
!=
'/'
)
!=
(
*
a
!=
0
))
return
1
;
}
if
(((
*
e
!=
0
)
&&
(
*
e
!=
'/'
))
!=
(
*
a
!=
0
))
{
/* one string has ended, the other not */
return
1
;
}
return
0
;
}
static
int
cJSONUtils_PointerEncodedstrlen
(
const
char
*
s
)
{
int
l
=
0
;
for
(;
*
s
;
s
++
,
l
++
)
if
(
*
s
==
'~'
||
*
s
==
'/'
)
l
++
;
return
l
;}
static
int
cJSONUtils_PointerEncodedstrlen
(
const
char
*
s
)
{
int
l
=
0
;
for
(;
*
s
;
s
++
,
l
++
)
{
if
((
*
s
==
'~'
)
||
(
*
s
==
'/'
))
{
l
++
;
}
}
return
l
;
}
static
void
cJSONUtils_PointerEncodedstrcpy
(
char
*
d
,
const
char
*
s
)
static
void
cJSONUtils_PointerEncodedstrcpy
(
char
*
d
,
const
char
*
s
)
{
for
(;
*
s
;
s
++
)
for
(;
*
s
;
s
++
)
{
if
(
*
s
==
'/'
)
{
*
d
++
=
'~'
;
*
d
++
=
'1'
;
}
else
if
(
*
s
==
'~'
)
{
if
(
*
s
==
'/'
)
{
*
d
++=
'~'
;
*
d
++=
'1'
;}
else
if
(
*
s
==
'~'
)
{
*
d
++=
'~'
;
*
d
++=
'0'
;}
else
*
d
++=*
s
;
*
d
++
=
'~'
;
*
d
++
=
'0'
;
}
*
d
=
0
;
else
{
*
d
++
=
*
s
;
}
}
*
d
=
'\0'
;
}
char
*
cJSONUtils_FindPointerFromObjectTo
(
cJSON
*
object
,
cJSON
*
target
)
char
*
cJSONUtils_FindPointerFromObjectTo
(
cJSON
*
object
,
cJSON
*
target
)
{
int
type
=
object
->
type
,
c
=
0
;
cJSON
*
obj
=
0
;
int
type
=
object
->
type
;
int
c
=
0
;
cJSON
*
obj
=
0
;
if
(
object
==
target
)
return
strdup
(
""
);
if
(
object
==
target
)
{
/* found */
return
strdup
(
""
);
}
for
(
obj
=
object
->
child
;
obj
;
obj
=
obj
->
next
,
c
++
)
/* recursively search all children of the object */
for
(
obj
=
object
->
child
;
obj
;
obj
=
obj
->
next
,
c
++
)
{
char
*
found
=
cJSONUtils_FindPointerFromObjectTo
(
obj
,
target
);
char
*
found
=
cJSONUtils_FindPointerFromObjectTo
(
obj
,
target
);
if
(
found
)
{
if
(
type
==
cJSON_Array
)
if
(
type
==
cJSON_Array
)
{
char
*
ret
=
(
char
*
)
malloc
(
strlen
(
found
)
+
23
);
sprintf
(
ret
,
"/%d%s"
,
c
,
found
);
/* reserve enough memory for a 64 bit integer + '/' and '\0' */
char
*
ret
=
(
char
*
)
malloc
(
strlen
(
found
)
+
23
);
sprintf
(
ret
,
"/%d%s"
,
c
,
found
);
/* /<array_index><path> */
free
(
found
);
return
ret
;
}
else
if
(
type
==
cJSON_Object
)
else
if
(
type
==
cJSON_Object
)
{
char
*
ret
=
(
char
*
)
malloc
(
strlen
(
found
)
+
cJSONUtils_PointerEncodedstrlen
(
obj
->
string
)
+
2
);
*
ret
=
'/'
;
cJSONUtils_PointerEncodedstrcpy
(
ret
+
1
,
obj
->
string
);
strcat
(
ret
,
found
);
char
*
ret
=
(
char
*
)
malloc
(
strlen
(
found
)
+
cJSONUtils_PointerEncodedstrlen
(
obj
->
string
)
+
2
);
*
ret
=
'/'
;
cJSONUtils_PointerEncodedstrcpy
(
ret
+
1
,
obj
->
string
);
strcat
(
ret
,
found
);
free
(
found
);
return
ret
;
}
/* reached leaf of the tree, found nothing */
free
(
found
);
return
0
;
}
}
/* not found */
return
0
;
}
cJSON
*
cJSONUtils_GetPointer
(
cJSON
*
object
,
const
char
*
pointer
)
cJSON
*
cJSONUtils_GetPointer
(
cJSON
*
object
,
const
char
*
pointer
)
{
while
(
*
pointer
++==
'/'
&&
object
)
/* follow path of the pointer */
while
((
*
pointer
++
==
'/'
)
&&
object
)
{
if
(
object
->
type
==
cJSON_Array
)
{
int
which
=
0
;
/* parse array index */
while
((
*
pointer
>=
'0'
)
&&
(
*
pointer
<=
'9'
))
{
which
=
(
10
*
which
)
+
(
*
pointer
++
-
'0'
);
}
if
(
*
pointer
&&
(
*
pointer
!=
'/'
))
{
if
(
object
->
type
==
cJSON_Array
)
/* not end of string or new path token */
return
0
;
}
object
=
cJSON_GetArrayItem
(
object
,
which
);
}
else
if
(
object
->
type
==
cJSON_Object
)
{
int
which
=
0
;
while
(
*
pointer
>=
'0'
&&
*
pointer
<=
'9'
)
which
=
(
10
*
which
)
+
*
pointer
++
-
'0'
;
if
(
*
pointer
&&
*
pointer
!=
'/'
)
return
0
;
object
=
cJSON_GetArrayItem
(
object
,
which
);
object
=
object
->
child
;
/* GetObjectItem. */
while
(
object
&&
cJSONUtils_Pstrcasecmp
(
object
->
string
,
pointer
))
{
object
=
object
->
next
;
}
else
if
(
object
->
type
==
cJSON_Object
)
/* skip to the next path token or end of string */
while
(
*
pointer
&&
(
*
pointer
!=
'/'
))
{
object
=
object
->
child
;
while
(
object
&&
cJSONUtils_Pstrcasecmp
(
object
->
string
,
pointer
))
object
=
object
->
next
;
/* GetObjectItem. */
while
(
*
pointer
&&
*
pointer
!=
'/'
)
pointer
++
;
pointer
++
;
}
else
return
0
;
}
else
{
return
0
;
}
}
return
object
;
}
/* JSON Patch implementation. */
static
void
cJSONUtils_InplaceDecodePointerString
(
char
*
string
)
{
char
*
s2
=
string
;
for
(;
*
string
;
s2
++
,
string
++
)
*
s2
=
(
*
string
!=
'~'
)
?
(
*
string
)
:
((
*
(
++
string
)
==
'0'
)
?
'~'
:
'/'
);
*
s2
=
0
;
char
*
s2
=
string
;
for
(;
*
string
;
s2
++
,
string
++
)
{
*
s2
=
(
*
string
!=
'~'
)
?
(
*
string
)
:
((
*
(
++
string
)
==
'0'
)
?
'~'
:
'/'
);
}
*
s2
=
'\0'
;
}
static
cJSON
*
cJSONUtils_PatchDetach
(
cJSON
*
object
,
const
char
*
path
)
static
cJSON
*
cJSONUtils_PatchDetach
(
cJSON
*
object
,
const
char
*
path
)
{
char
*
parentptr
=
0
,
*
childptr
=
0
;
cJSON
*
parent
=
0
,
*
ret
=
0
;
char
*
parentptr
=
0
;
char
*
childptr
=
0
;
cJSON
*
parent
=
0
;
cJSON
*
ret
=
0
;
parentptr
=
strdup
(
path
);
childptr
=
strrchr
(
parentptr
,
'/'
);
if
(
childptr
)
*
childptr
++=
0
;
parent
=
cJSONUtils_GetPointer
(
object
,
parentptr
);
/* copy path and split it in parent and child */
parentptr
=
strdup
(
path
);
childptr
=
strrchr
(
parentptr
,
'/'
);
/* last '/' */
if
(
childptr
)
{
/* split strings */
*
childptr
++
=
'\0'
;
}
parent
=
cJSONUtils_GetPointer
(
object
,
parentptr
);
cJSONUtils_InplaceDecodePointerString
(
childptr
);
if
(
!
parent
)
ret
=
0
;
/* Couldn't find object to remove child from. */
else
if
(
parent
->
type
==
cJSON_Array
)
ret
=
cJSON_DetachItemFromArray
(
parent
,
atoi
(
childptr
));
else
if
(
parent
->
type
==
cJSON_Object
)
ret
=
cJSON_DetachItemFromObject
(
parent
,
childptr
);
if
(
!
parent
)
{
/* Couldn't find object to remove child from. */
ret
=
0
;
}
else
if
(
parent
->
type
==
cJSON_Array
)
{
ret
=
cJSON_DetachItemFromArray
(
parent
,
atoi
(
childptr
));
}
else
if
(
parent
->
type
==
cJSON_Object
)
{
ret
=
cJSON_DetachItemFromObject
(
parent
,
childptr
);
}
free
(
parentptr
);
/* return the detachted item */
return
ret
;
}
static
int
cJSONUtils_Compare
(
cJSON
*
a
,
cJSON
*
b
)
static
int
cJSONUtils_Compare
(
cJSON
*
a
,
cJSON
*
b
)
{
if
(
a
->
type
!=
b
->
type
)
return
-
1
;
/* mismatched type. */
if
(
a
->
type
!=
b
->
type
)
{
/* mismatched type. */
return
-
1
;
}
switch
(
a
->
type
)
{
case
cJSON_Number
:
return
(
a
->
valueint
!=
b
->
valueint
||
a
->
valuedouble
!=
b
->
valuedouble
)
?-
2
:
0
;
/* numeric mismatch. */
case
cJSON_String
:
return
(
strcmp
(
a
->
valuestring
,
b
->
valuestring
)
!=
0
)
?-
3
:
0
;
/* string mismatch. */
case
cJSON_Array
:
for
(
a
=
a
->
child
,
b
=
b
->
child
;
a
&&
b
;
a
=
a
->
next
,
b
=
b
->
next
)
{
int
err
=
cJSONUtils_Compare
(
a
,
b
);
if
(
err
)
return
err
;}
return
(
a
||
b
)
?-
4
:
0
;
/* array size mismatch. */
case
cJSON_Number
:
/* numeric mismatch. */
return
((
a
->
valueint
!=
b
->
valueint
)
||
(
a
->
valuedouble
!=
b
->
valuedouble
))
?
-
2
:
0
;
case
cJSON_String
:
/* string mismatch. */
return
(
strcmp
(
a
->
valuestring
,
b
->
valuestring
)
!=
0
)
?
-
3
:
0
;
case
cJSON_Array
:
for
(
a
=
a
->
child
,
b
=
b
->
child
;
a
&&
b
;
a
=
a
->
next
,
b
=
b
->
next
)
{
int
err
=
cJSONUtils_Compare
(
a
,
b
);
if
(
err
)
{
return
err
;
}
}
/* array size mismatch? (one of both children is not NULL) */
return
(
a
||
b
)
?
-
4
:
0
;
case
cJSON_Object
:
cJSONUtils_SortObject
(
a
);
cJSONUtils_SortObject
(
b
);
a
=
a
->
child
,
b
=
b
->
child
;
a
=
a
->
child
;
b
=
b
->
child
;
while
(
a
&&
b
)
{
int
err
;
if
(
cJSONUtils_strcasecmp
(
a
->
string
,
b
->
string
))
return
-
6
;
/* missing member */
err
=
cJSONUtils_Compare
(
a
,
b
);
if
(
err
)
return
err
;
a
=
a
->
next
,
b
=
b
->
next
;
/* compare object keys */
if
(
cJSONUtils_strcasecmp
(
a
->
string
,
b
->
string
))
{
/* missing member */
return
-
6
;
}
err
=
cJSONUtils_Compare
(
a
,
b
);
if
(
err
)
{
return
err
;
}
return
(
a
||
b
)
?-
5
:
0
;
/* object length mismatch */
a
=
a
->
next
;
b
=
b
->
next
;
}
/* object length mismatch (one of both children is not null) */
return
(
a
||
b
)
?
-
5
:
0
;
default:
break
;
default:
break
;
}
/* null, true or false */
return
0
;
}
static
int
cJSONUtils_ApplyPatch
(
cJSON
*
object
,
cJSON
*
patch
)
static
int
cJSONUtils_ApplyPatch
(
cJSON
*
object
,
cJSON
*
patch
)
{
cJSON
*
op
=
0
,
*
path
=
0
,
*
value
=
0
,
*
parent
=
0
;
int
opcode
=
0
;
char
*
parentptr
=
0
,
*
childptr
=
0
;
cJSON
*
op
=
0
;
cJSON
*
path
=
0
;
cJSON
*
value
=
0
;
cJSON
*
parent
=
0
;
int
opcode
=
0
;
char
*
parentptr
=
0
;
char
*
childptr
=
0
;
op
=
cJSON_GetObjectItem
(
patch
,
"op"
);
path
=
cJSON_GetObjectItem
(
patch
,
"path"
);
if
(
!
op
||
!
path
)
return
2
;
/* malformed patch. */
op
=
cJSON_GetObjectItem
(
patch
,
"op"
);
path
=
cJSON_GetObjectItem
(
patch
,
"path"
);
if
(
!
op
||
!
path
)
{
/* malformed patch. */
return
2
;
}
if
(
!
strcmp
(
op
->
valuestring
,
"add"
))
opcode
=
0
;
else
if
(
!
strcmp
(
op
->
valuestring
,
"remove"
))
opcode
=
1
;
else
if
(
!
strcmp
(
op
->
valuestring
,
"replace"
))
opcode
=
2
;
else
if
(
!
strcmp
(
op
->
valuestring
,
"move"
))
opcode
=
3
;
else
if
(
!
strcmp
(
op
->
valuestring
,
"copy"
))
opcode
=
4
;
else
if
(
!
strcmp
(
op
->
valuestring
,
"test"
))
return
cJSONUtils_Compare
(
cJSONUtils_GetPointer
(
object
,
path
->
valuestring
),
cJSON_GetObjectItem
(
patch
,
"value"
));
else
return
3
;
/* unknown opcode. */
/* decode operation */
if
(
!
strcmp
(
op
->
valuestring
,
"add"
))
{
opcode
=
0
;
}
else
if
(
!
strcmp
(
op
->
valuestring
,
"remove"
))
{
opcode
=
1
;
}
else
if
(
!
strcmp
(
op
->
valuestring
,
"replace"
))
{
opcode
=
2
;
}
else
if
(
!
strcmp
(
op
->
valuestring
,
"move"
))
{
opcode
=
3
;
}
else
if
(
!
strcmp
(
op
->
valuestring
,
"copy"
))
{
opcode
=
4
;
}
else
if
(
!
strcmp
(
op
->
valuestring
,
"test"
))
{
/* compare value: {...} with the given path */
return
cJSONUtils_Compare
(
cJSONUtils_GetPointer
(
object
,
path
->
valuestring
),
cJSON_GetObjectItem
(
patch
,
"value"
));
}
else
{
/* unknown opcode. */
return
3
;
}
if
(
opcode
==
1
||
opcode
==
2
)
/* Remove/Replace */
/* Remove/Replace */
if
((
opcode
==
1
)
||
(
opcode
==
2
))
{
cJSON_Delete
(
cJSONUtils_PatchDetach
(
object
,
path
->
valuestring
));
/* Get rid of old. */
if
(
opcode
==
1
)
return
0
;
/* For Remove, this is job done. */
/* Get rid of old. */
cJSON_Delete
(
cJSONUtils_PatchDetach
(
object
,
path
->
valuestring
));
if
(
opcode
==
1
)
{
/* For Remove, this is job done. */
return
0
;
}
}
if
(
opcode
==
3
||
opcode
==
4
)
/* Copy/Move uses "from". */
/* Copy/Move uses "from". */
if
((
opcode
==
3
)
||
(
opcode
==
4
))
{
cJSON
*
from
=
cJSON_GetObjectItem
(
patch
,
"from"
);
if
(
!
from
)
return
4
;
/* missing "from" for copy/move. */
cJSON
*
from
=
cJSON_GetObjectItem
(
patch
,
"from"
);
if
(
!
from
)
{
/* missing "from" for copy/move. */
return
4
;
}
if
(
opcode
==
3
)
value
=
cJSONUtils_PatchDetach
(
object
,
from
->
valuestring
);
if
(
opcode
==
4
)
value
=
cJSONUtils_GetPointer
(
object
,
from
->
valuestring
);
if
(
!
value
)
return
5
;
/* missing "from" for copy/move. */
if
(
opcode
==
4
)
value
=
cJSON_Duplicate
(
value
,
1
);
if
(
!
value
)
return
6
;
/* out of memory for copy/move. */
if
(
opcode
==
3
)
{
/* move */
value
=
cJSONUtils_PatchDetach
(
object
,
from
->
valuestring
);
}
if
(
opcode
==
4
)
{
/* copy */
value
=
cJSONUtils_GetPointer
(
object
,
from
->
valuestring
);
}
if
(
!
value
)
{
/* missing "from" for copy/move. */
return
5
;
}
if
(
opcode
==
4
)
{
value
=
cJSON_Duplicate
(
value
,
1
);
}
if
(
!
value
)
{
/* out of memory for copy/move. */
return
6
;
}
}
else
/* Add/Replace uses "value". */
{
value
=
cJSON_GetObjectItem
(
patch
,
"value"
);
if
(
!
value
)
return
7
;
/* missing "value" for add/replace. */
value
=
cJSON_Duplicate
(
value
,
1
);
if
(
!
value
)
return
8
;
/* out of memory for add/replace. */
value
=
cJSON_GetObjectItem
(
patch
,
"value"
);
if
(
!
value
)
{
/* missing "value" for add/replace. */
return
7
;
}
value
=
cJSON_Duplicate
(
value
,
1
);
if
(
!
value
)
{
/* out of memory for add/replace. */
return
8
;
}
}
/* Now, just add "value" to "path". */
parentptr
=
strdup
(
path
->
valuestring
);
childptr
=
strrchr
(
parentptr
,
'/'
);
if
(
childptr
)
*
childptr
++=
0
;
parent
=
cJSONUtils_GetPointer
(
object
,
parentptr
);
/* split pointer in parent and child */
parentptr
=
strdup
(
path
->
valuestring
);
childptr
=
strrchr
(
parentptr
,
'/'
);
if
(
childptr
)
{
*
childptr
++
=
'\0'
;
}
parent
=
cJSONUtils_GetPointer
(
object
,
parentptr
);
cJSONUtils_InplaceDecodePointerString
(
childptr
);
/* add, remove, replace, move, copy, test. */
if
(
!
parent
)
{
free
(
parentptr
);
cJSON_Delete
(
value
);
return
9
;}
/* Couldn't find object to add to. */
else
if
(
parent
->
type
==
cJSON_Array
)
if
(
!
parent
)
{
/* Couldn't find object to add to. */
free
(
parentptr
);
cJSON_Delete
(
value
);
return
9
;
}
else
if
(
parent
->
type
==
cJSON_Array
)
{
if
(
!
strcmp
(
childptr
,
"-"
))
cJSON_AddItemToArray
(
parent
,
value
);
else
cJSON_InsertItemInArray
(
parent
,
atoi
(
childptr
),
value
);
if
(
!
strcmp
(
childptr
,
"-"
))
{
cJSON_AddItemToArray
(
parent
,
value
);
}
else
{
cJSON_InsertItemInArray
(
parent
,
atoi
(
childptr
),
value
);
}
}
else
if
(
parent
->
type
==
cJSON_Object
)
else
if
(
parent
->
type
==
cJSON_Object
)
{
cJSON_DeleteItemFromObject
(
parent
,
childptr
);
cJSON_AddItemToObject
(
parent
,
childptr
,
value
);
cJSON_DeleteItemFromObject
(
parent
,
childptr
);
cJSON_AddItemToObject
(
parent
,
childptr
,
value
);
}
else
{
cJSON_Delete
(
value
);
}
free
(
parentptr
);
return
0
;
}
int
cJSONUtils_ApplyPatches
(
cJSON
*
object
,
cJSON
*
patches
)
int
cJSONUtils_ApplyPatches
(
cJSON
*
object
,
cJSON
*
patches
)
{
int
err
;
if
(
patches
->
type
!=
cJSON_Array
)
return
1
;
/* malformed patches. */
if
(
patches
)
patches
=
patches
->
child
;
if
(
patches
->
type
!=
cJSON_Array
)
{
/* malformed patches. */
return
1
;
}
if
(
patches
)
{
patches
=
patches
->
child
;
}
while
(
patches
)
{
if
((
err
=
cJSONUtils_ApplyPatch
(
object
,
patches
)))
return
err
;
patches
=
patches
->
next
;
if
((
err
=
cJSONUtils_ApplyPatch
(
object
,
patches
)))
{
return
err
;
}
patches
=
patches
->
next
;
}
return
0
;
}
static
void
cJSONUtils_GeneratePatch
(
cJSON
*
patches
,
const
char
*
op
,
const
char
*
path
,
const
char
*
suffix
,
cJSON
*
val
)
static
void
cJSONUtils_GeneratePatch
(
cJSON
*
patches
,
const
char
*
op
,
const
char
*
path
,
const
char
*
suffix
,
cJSON
*
val
)
{
cJSON
*
patch
=
cJSON_CreateObject
();
cJSON_AddItemToObject
(
patch
,
"op"
,
cJSON_CreateString
(
op
));
cJSON
*
patch
=
cJSON_CreateObject
();
cJSON_AddItemToObject
(
patch
,
"op"
,
cJSON_CreateString
(
op
));
if
(
suffix
)
{
char
*
newpath
=
(
char
*
)
malloc
(
strlen
(
path
)
+
cJSONUtils_PointerEncodedstrlen
(
suffix
)
+
2
);
cJSONUtils_PointerEncodedstrcpy
(
newpath
+
sprintf
(
newpath
,
"%s/"
,
path
),
suffix
);
cJSON_AddItemToObject
(
patch
,
"path"
,
cJSON_CreateString
(
newpath
));
char
*
newpath
=
(
char
*
)
malloc
(
strlen
(
path
)
+
cJSONUtils_PointerEncodedstrlen
(
suffix
)
+
2
);
cJSONUtils_PointerEncodedstrcpy
(
newpath
+
sprintf
(
newpath
,
"%s/"
,
path
),
suffix
);
cJSON_AddItemToObject
(
patch
,
"path"
,
cJSON_CreateString
(
newpath
));
free
(
newpath
);
}
else
cJSON_AddItemToObject
(
patch
,
"path"
,
cJSON_CreateString
(
path
));
if
(
val
)
cJSON_AddItemToObject
(
patch
,
"value"
,
cJSON_Duplicate
(
val
,
1
));
cJSON_AddItemToArray
(
patches
,
patch
);
else
{
cJSON_AddItemToObject
(
patch
,
"path"
,
cJSON_CreateString
(
path
));
}
if
(
val
)
{
cJSON_AddItemToObject
(
patch
,
"value"
,
cJSON_Duplicate
(
val
,
1
));
}
cJSON_AddItemToArray
(
patches
,
patch
);
}
void
cJSONUtils_AddPatchToArray
(
cJSON
*
array
,
const
char
*
op
,
const
char
*
path
,
cJSON
*
val
)
{
cJSONUtils_GeneratePatch
(
array
,
op
,
path
,
0
,
val
);}
void
cJSONUtils_AddPatchToArray
(
cJSON
*
array
,
const
char
*
op
,
const
char
*
path
,
cJSON
*
val
)
{
cJSONUtils_GeneratePatch
(
array
,
op
,
path
,
0
,
val
);
}
static
void
cJSONUtils_CompareToPatch
(
cJSON
*
patches
,
const
char
*
path
,
cJSON
*
from
,
cJSON
*
to
)
static
void
cJSONUtils_CompareToPatch
(
cJSON
*
patches
,
const
char
*
path
,
cJSON
*
from
,
cJSON
*
to
)
{
if
(
from
->
type
!=
to
->
type
)
{
cJSONUtils_GeneratePatch
(
patches
,
"replace"
,
path
,
0
,
to
);
return
;
}
if
(
from
->
type
!=
to
->
type
)
{
cJSONUtils_GeneratePatch
(
patches
,
"replace"
,
path
,
0
,
to
);
return
;
}
switch
(
from
->
type
)
{
case
cJSON_Number
:
if
(
from
->
valueint
!=
to
->
valueint
||
from
->
valuedouble
!=
to
->
valuedouble
)
cJSONUtils_GeneratePatch
(
patches
,
"replace"
,
path
,
0
,
to
);
if
((
from
->
valueint
!=
to
->
valueint
)
||
(
from
->
valuedouble
!=
to
->
valuedouble
))
{
cJSONUtils_GeneratePatch
(
patches
,
"replace"
,
path
,
0
,
to
);
}
return
;
case
cJSON_String
:
if
(
strcmp
(
from
->
valuestring
,
to
->
valuestring
)
!=
0
)
cJSONUtils_GeneratePatch
(
patches
,
"replace"
,
path
,
0
,
to
);
if
(
strcmp
(
from
->
valuestring
,
to
->
valuestring
)
!=
0
)
{
cJSONUtils_GeneratePatch
(
patches
,
"replace"
,
path
,
0
,
to
);
}
return
;
case
cJSON_Array
:
{
int
c
;
char
*
newpath
=
(
char
*
)
malloc
(
strlen
(
path
)
+
23
);
/* Allow space for 64bit int. */
for
(
c
=
0
,
from
=
from
->
child
,
to
=
to
->
child
;
from
&&
to
;
from
=
from
->
next
,
to
=
to
->
next
,
c
++
){
sprintf
(
newpath
,
"%s/%d"
,
path
,
c
);
cJSONUtils_CompareToPatch
(
patches
,
newpath
,
from
,
to
);
int
c
;
char
*
newpath
=
(
char
*
)
malloc
(
strlen
(
path
)
+
23
);
/* Allow space for 64bit int. */
/* generate patches for all array elements that exist in "from" and "to" */
for
(
c
=
0
,
from
=
from
->
child
,
to
=
to
->
child
;
from
&&
to
;
from
=
from
->
next
,
to
=
to
->
next
,
c
++
)
{
sprintf
(
newpath
,
"%s/%d"
,
path
,
c
);
/* path of the current array element */
cJSONUtils_CompareToPatch
(
patches
,
newpath
,
from
,
to
);
}
/* remove leftover elements from 'from' that are not in 'to' */
for
(;
from
;
from
=
from
->
next
,
c
++
)
{
sprintf
(
newpath
,
"%d"
,
c
);
cJSONUtils_GeneratePatch
(
patches
,
"remove"
,
path
,
newpath
,
0
);
}
/* add new elements in 'to' that were not in 'from' */
for
(;
to
;
to
=
to
->
next
,
c
++
)
{
cJSONUtils_GeneratePatch
(
patches
,
"add"
,
path
,
"-"
,
to
);
}
for
(;
from
;
from
=
from
->
next
,
c
++
)
{
sprintf
(
newpath
,
"%d"
,
c
);
cJSONUtils_GeneratePatch
(
patches
,
"remove"
,
path
,
newpath
,
0
);
}
for
(;
to
;
to
=
to
->
next
,
c
++
)
cJSONUtils_GeneratePatch
(
patches
,
"add"
,
path
,
"-"
,
to
);
free
(
newpath
);
return
;
}
case
cJSON_Object
:
{
cJSON
*
a
,
*
b
;
cJSON
*
a
;
cJSON
*
b
;
cJSONUtils_SortObject
(
from
);
cJSONUtils_SortObject
(
to
);
a
=
from
->
child
,
b
=
to
->
child
;
a
=
from
->
child
;
b
=
to
->
child
;
/* for all object values in the object with more of them */
while
(
a
||
b
)
{
int
diff
=
(
!
a
)
?
1
:
(
!
b
)
?-
1
:
cJSONUtils_strcasecmp
(
a
->
string
,
b
->
string
);
int
diff
=
(
!
a
)
?
1
:
((
!
b
)
?
-
1
:
cJSONUtils_strcasecmp
(
a
->
string
,
b
->
string
)
);
if
(
!
diff
)
{
char
*
newpath
=
(
char
*
)
malloc
(
strlen
(
path
)
+
cJSONUtils_PointerEncodedstrlen
(
a
->
string
)
+
2
);
cJSONUtils_PointerEncodedstrcpy
(
newpath
+
sprintf
(
newpath
,
"%s/"
,
path
),
a
->
string
);
cJSONUtils_CompareToPatch
(
patches
,
newpath
,
a
,
b
);
/* both object keys are the same */
char
*
newpath
=
(
char
*
)
malloc
(
strlen
(
path
)
+
cJSONUtils_PointerEncodedstrlen
(
a
->
string
)
+
2
);
cJSONUtils_PointerEncodedstrcpy
(
newpath
+
sprintf
(
newpath
,
"%s/"
,
path
),
a
->
string
);
/* create a patch for the element */
cJSONUtils_CompareToPatch
(
patches
,
newpath
,
a
,
b
);
free
(
newpath
);
a
=
a
->
next
;
b
=
b
->
next
;
a
=
a
->
next
;
b
=
b
->
next
;
}
else
if
(
diff
<
0
)
{
/* object element doesn't exist in 'to' --> remove it */
cJSONUtils_GeneratePatch
(
patches
,
"remove"
,
path
,
a
->
string
,
0
);
a
=
a
->
next
;
}
else
{
/* object element doesn't exist in 'from' --> add it */
cJSONUtils_GeneratePatch
(
patches
,
"add"
,
path
,
b
->
string
,
b
);
b
=
b
->
next
;
}
else
if
(
diff
<
0
)
{
cJSONUtils_GeneratePatch
(
patches
,
"remove"
,
path
,
a
->
string
,
0
);
a
=
a
->
next
;}
else
{
cJSONUtils_GeneratePatch
(
patches
,
"add"
,
path
,
b
->
string
,
b
);
b
=
b
->
next
;}
}
return
;
}
default:
break
;
default:
break
;
}
}
cJSON
*
cJSONUtils_GeneratePatches
(
cJSON
*
from
,
cJSON
*
to
)
cJSON
*
cJSONUtils_GeneratePatches
(
cJSON
*
from
,
cJSON
*
to
)
{
cJSON
*
patches
=
cJSON_CreateArray
();
cJSONUtils_CompareToPatch
(
patches
,
""
,
from
,
to
);
cJSON
*
patches
=
cJSON_CreateArray
();
cJSONUtils_CompareToPatch
(
patches
,
""
,
from
,
to
);
return
patches
;
}
/* sort lists using mergesort */
static
cJSON
*
cJSONUtils_SortList
(
cJSON
*
list
)
{
cJSON
*
first
=
list
,
*
second
=
list
,
*
ptr
=
list
;
cJSON
*
first
=
list
;
cJSON
*
second
=
list
;
cJSON
*
ptr
=
list
;
if
(
!
list
||
!
list
->
next
)
return
list
;
/* One entry is sorted already. */
if
(
!
list
||
!
list
->
next
)
{
/* One entry is sorted already. */
return
list
;
}
while
(
ptr
&&
ptr
->
next
&&
cJSONUtils_strcasecmp
(
ptr
->
string
,
ptr
->
next
->
string
)
<
0
)
ptr
=
ptr
->
next
;
/* Test for list sorted. */
if
(
!
ptr
||
!
ptr
->
next
)
return
list
;
/* Leave sorted lists unmodified. */
ptr
=
list
;
while
(
ptr
&&
ptr
->
next
&&
(
cJSONUtils_strcasecmp
(
ptr
->
string
,
ptr
->
next
->
string
)
<
0
))
{
/* Test for list sorted. */
ptr
=
ptr
->
next
;
}
if
(
!
ptr
||
!
ptr
->
next
)
{
/* Leave sorted lists unmodified. */
return
list
;
}
while
(
ptr
)
{
second
=
second
->
next
;
ptr
=
ptr
->
next
;
if
(
ptr
)
ptr
=
ptr
->
next
;}
/* Walk two pointers to find the middle. */
if
(
second
&&
second
->
prev
)
second
->
prev
->
next
=
0
;
/* Split the lists */
/* reset ptr to the beginning */
ptr
=
list
;
while
(
ptr
)
{
/* Walk two pointers to find the middle. */
second
=
second
->
next
;
ptr
=
ptr
->
next
;
/* advances ptr two steps at a time */
if
(
ptr
)
{
ptr
=
ptr
->
next
;
}
}
if
(
second
&&
second
->
prev
)
{
/* Split the lists */
second
->
prev
->
next
=
0
;
}
first
=
cJSONUtils_SortList
(
first
);
/* Recursively sort the sub-lists. */
second
=
cJSONUtils_SortList
(
second
);
list
=
ptr
=
0
;
/* Recursively sort the sub-lists. */
first
=
cJSONUtils_SortList
(
first
);
second
=
cJSONUtils_SortList
(
second
);
list
=
ptr
=
0
;
while
(
first
&&
second
)
/* Merge the sub-lists */
{
if
(
cJSONUtils_strcasecmp
(
first
->
string
,
second
->
string
)
<
0
)
if
(
cJSONUtils_strcasecmp
(
first
->
string
,
second
->
string
)
<
0
)
{
if
(
!
list
)
{
/* start merged list with the first element of the first list */
list
=
ptr
=
first
;
}
else
{
/* add first element of first list to merged list */
ptr
->
next
=
first
;
first
->
prev
=
ptr
;
ptr
=
first
;
}
first
=
first
->
next
;
}
else
{
if
(
!
list
)
{
if
(
!
list
)
list
=
ptr
=
first
;
else
{
ptr
->
next
=
first
;
first
->
prev
=
ptr
;
ptr
=
first
;}
first
=
first
->
next
;
/* start merged list with the first element of the second list */
list
=
ptr
=
second
;
}
else
{
if
(
!
list
)
list
=
ptr
=
second
;
else
{
ptr
->
next
=
second
;
second
->
prev
=
ptr
;
ptr
=
second
;}
second
=
second
->
next
;
/* add first element of second list to merged list */
ptr
->
next
=
second
;
second
->
prev
=
ptr
;
ptr
=
second
;
}
second
=
second
->
next
;
}
}
if
(
first
)
{
/* Append rest of first list. */
if
(
!
list
)
{
return
first
;
}
ptr
->
next
=
first
;
first
->
prev
=
ptr
;
}
if
(
second
)
{
/* Append rest of second list */
if
(
!
list
)
{
return
second
;
}
ptr
->
next
=
second
;
second
->
prev
=
ptr
;
}
if
(
first
)
{
if
(
!
list
)
return
first
;
ptr
->
next
=
first
;
first
->
prev
=
ptr
;
}
/* Append any tails. */
if
(
second
)
{
if
(
!
list
)
return
second
;
ptr
->
next
=
second
;
second
->
prev
=
ptr
;
}
return
list
;
}
void
cJSONUtils_SortObject
(
cJSON
*
object
)
{
object
->
child
=
cJSONUtils_SortList
(
object
->
child
);}
void
cJSONUtils_SortObject
(
cJSON
*
object
)
{
object
->
child
=
cJSONUtils_SortList
(
object
->
child
);
}
cJSON
*
cJSONUtils_MergePatch
(
cJSON
*
target
,
cJSON
*
patch
)
{
if
(
!
patch
||
patch
->
type
!=
cJSON_Object
)
{
cJSON_Delete
(
target
);
return
cJSON_Duplicate
(
patch
,
1
);}
if
(
!
target
||
target
->
type
!=
cJSON_Object
)
{
cJSON_Delete
(
target
);
target
=
cJSON_CreateObject
();}
if
(
!
patch
||
(
patch
->
type
!=
cJSON_Object
))
{
/* scalar value, array or NULL, just duplicate */
cJSON_Delete
(
target
);
return
cJSON_Duplicate
(
patch
,
1
);
}
patch
=
patch
->
child
;
if
(
!
target
||
(
target
->
type
!=
cJSON_Object
))
{
cJSON_Delete
(
target
);
target
=
cJSON_CreateObject
();
}
patch
=
patch
->
child
;
while
(
patch
)
{
if
(
patch
->
type
==
cJSON_NULL
)
cJSON_DeleteItemFromObject
(
target
,
patch
->
string
);
if
(
patch
->
type
==
cJSON_NULL
)
{
/* NULL is the indicator to remove a value, see RFC7396 */
cJSON_DeleteItemFromObject
(
target
,
patch
->
string
);
}
else
{
cJSON
*
replaceme
=
cJSON_DetachItemFromObject
(
target
,
patch
->
string
);
cJSON_AddItemToObject
(
target
,
patch
->
string
,
cJSONUtils_MergePatch
(
replaceme
,
patch
));
cJSON
*
replaceme
=
cJSON_DetachItemFromObject
(
target
,
patch
->
string
);
cJSON_AddItemToObject
(
target
,
patch
->
string
,
cJSONUtils_MergePatch
(
replaceme
,
patch
));
}
patch
=
patch
->
next
;
patch
=
patch
->
next
;
}
return
target
;
}
cJSON
*
cJSONUtils_GenerateMergePatch
(
cJSON
*
from
,
cJSON
*
to
)
cJSON
*
cJSONUtils_GenerateMergePatch
(
cJSON
*
from
,
cJSON
*
to
)
{
cJSON
*
patch
=
0
;
if
(
!
to
)
return
cJSON_CreateNull
();
if
(
to
->
type
!=
cJSON_Object
||
!
from
||
from
->
type
!=
cJSON_Object
)
return
cJSON_Duplicate
(
to
,
1
);
cJSON
*
patch
=
0
;
if
(
!
to
)
{
/* patch to delete everything */
return
cJSON_CreateNull
();
}
if
((
to
->
type
!=
cJSON_Object
)
||
!
from
||
(
from
->
type
!=
cJSON_Object
))
{
return
cJSON_Duplicate
(
to
,
1
);
}
cJSONUtils_SortObject
(
from
);
cJSONUtils_SortObject
(
to
);
from
=
from
->
child
;
to
=
to
->
child
;
patch
=
cJSON_CreateObject
();
from
=
from
->
child
;
to
=
to
->
child
;
patch
=
cJSON_CreateObject
();
while
(
from
||
to
)
{
int
compare
=
from
?
(
to
?
strcmp
(
from
->
string
,
to
->
string
)
:-
1
)
:
1
;
if
(
compare
<
0
)
int
compare
=
from
?
(
to
?
strcmp
(
from
->
string
,
to
->
string
)
:
-
1
)
:
1
;
if
(
compare
<
0
)
{
cJSON_AddItemToObject
(
patch
,
from
->
string
,
cJSON_CreateNull
());
from
=
from
->
next
;
/* from has a value that to doesn't have -> remove */
cJSON_AddItemToObject
(
patch
,
from
->
string
,
cJSON_CreateNull
());
from
=
from
->
next
;
}
else
if
(
compare
>
0
)
else
if
(
compare
>
0
)
{
cJSON_AddItemToObject
(
patch
,
to
->
string
,
cJSON_Duplicate
(
to
,
1
));
to
=
to
->
next
;
/* to has a value that from doesn't have -> add to patch */
cJSON_AddItemToObject
(
patch
,
to
->
string
,
cJSON_Duplicate
(
to
,
1
));
to
=
to
->
next
;
}
else
{
if
(
cJSONUtils_Compare
(
from
,
to
))
cJSON_AddItemToObject
(
patch
,
to
->
string
,
cJSONUtils_GenerateMergePatch
(
from
,
to
));
from
=
from
->
next
;
to
=
to
->
next
;
/* object key exists in both objects */
if
(
cJSONUtils_Compare
(
from
,
to
))
{
/* not identical --> generate a patch */
cJSON_AddItemToObject
(
patch
,
to
->
string
,
cJSONUtils_GenerateMergePatch
(
from
,
to
));
}
/* next key in the object */
from
=
from
->
next
;
to
=
to
->
next
;
}
}
if
(
!
patch
->
child
)
{
cJSON_Delete
(
patch
);
return
0
;
}
if
(
!
patch
->
child
)
{
cJSON_Delete
(
patch
);
return
0
;}
return
patch
;
}
cJSON_Utils.h
浏览文件 @
a1c022fe
#include "cJSON.h"
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
cJSON
*
cJSONUtils_GetPointer
(
cJSON
*
object
,
const
char
*
pointer
);
cJSON
*
cJSONUtils_GetPointer
(
cJSON
*
object
,
const
char
*
pointer
);
/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
cJSON
*
cJSONUtils_GeneratePatches
(
cJSON
*
from
,
cJSON
*
to
);
void
cJSONUtils_AddPatchToArray
(
cJSON
*
array
,
const
char
*
op
,
const
char
*
path
,
cJSON
*
val
);
/* Utility for generating patch array entries. */
int
cJSONUtils_ApplyPatches
(
cJSON
*
object
,
cJSON
*
patches
);
/* Returns 0 for success. */
cJSON
*
cJSONUtils_GeneratePatches
(
cJSON
*
from
,
cJSON
*
to
);
/* Utility for generating patch array entries. */
void
cJSONUtils_AddPatchToArray
(
cJSON
*
array
,
const
char
*
op
,
const
char
*
path
,
cJSON
*
val
);
/* Returns 0 for success. */
int
cJSONUtils_ApplyPatches
(
cJSON
*
object
,
cJSON
*
patches
);
/*
// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches)
//{
// cJSON *modme=cJSON_Duplicate(*object,1);
// int error=cJSONUtils_ApplyPatches(modme,patches);
// if (!error) {cJSON_Delete(*object);*object=modme;}
// else cJSON_Delete(modme);
// cJSON *modme = cJSON_Duplicate(*object, 1);
// int error = cJSONUtils_ApplyPatches(modme, patches);
// if (!error)
// {
// cJSON_Delete(*object);
// *object = modme;
// }
// else
// {
// cJSON_Delete(modme);
// }
//
// return error;
//}
// Code not added to library since this strategy is a LOT slower.
*/
/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
cJSON
*
cJSONUtils_MergePatch
(
cJSON
*
target
,
cJSON
*
patch
);
/* target will be modified by patch. return value is new ptr for target. */
cJSON
*
cJSONUtils_GenerateMergePatch
(
cJSON
*
from
,
cJSON
*
to
);
/* generates a patch to move from -> to */
/* target will be modified by patch. return value is new ptr for target. */
cJSON
*
cJSONUtils_MergePatch
(
cJSON
*
target
,
cJSON
*
patch
);
/* generates a patch to move from -> to */
cJSON
*
cJSONUtils_GenerateMergePatch
(
cJSON
*
from
,
cJSON
*
to
);
char
*
cJSONUtils_FindPointerFromObjectTo
(
cJSON
*
object
,
cJSON
*
target
);
/* Given a root object and a target object, construct a pointer from one to the other. */
/* Given a root object and a target object, construct a pointer from one to the other. */
char
*
cJSONUtils_FindPointerFromObjectTo
(
cJSON
*
object
,
cJSON
*
target
);
void
cJSONUtils_SortObject
(
cJSON
*
object
);
/* Sorts the members of the object into alphabetical order. */
/* Sorts the members of the object into alphabetical order. */
void
cJSONUtils_SortObject
(
cJSON
*
object
);
test.c
浏览文件 @
a1c022fe
...
...
@@ -27,15 +27,19 @@
/* Parse text to JSON, then render back to text, and print! */
void
doit
(
char
*
text
)
{
char
*
out
;
cJSON
*
json
;
char
*
out
;
cJSON
*
json
;
json
=
cJSON_Parse
(
text
);
if
(
!
json
)
{
printf
(
"Error before: [%s]
\n
"
,
cJSON_GetErrorPtr
());}
json
=
cJSON_Parse
(
text
);
if
(
!
json
)
{
printf
(
"Error before: [%s]
\n
"
,
cJSON_GetErrorPtr
());
}
else
{
out
=
cJSON_Print
(
json
);
out
=
cJSON_Print
(
json
);
cJSON_Delete
(
json
);
printf
(
"%s
\n
"
,
out
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
}
}
...
...
@@ -43,81 +47,165 @@ void doit(char *text)
/* Read a file, parse, render back, etc. */
void
dofile
(
char
*
filename
)
{
FILE
*
f
;
long
len
;
char
*
data
;
FILE
*
f
;
long
len
;
char
*
data
;
/* open in read binary mode */
f
=
fopen
(
filename
,
"rb"
);
/* get the length */
fseek
(
f
,
0
,
SEEK_END
);
len
=
ftell
(
f
);
fseek
(
f
,
0
,
SEEK_SET
);
data
=
(
char
*
)
malloc
(
len
+
1
);
fread
(
data
,
1
,
len
,
f
);
data
[
len
]
=
'\0'
;
fclose
(
f
);
f
=
fopen
(
filename
,
"rb"
);
fseek
(
f
,
0
,
SEEK_END
);
len
=
ftell
(
f
);
fseek
(
f
,
0
,
SEEK_SET
);
data
=
(
char
*
)
malloc
(
len
+
1
);
fread
(
data
,
1
,
len
,
f
);
data
[
len
]
=
'\0'
;
fclose
(
f
);
doit
(
data
);
free
(
data
);
}
/* Used by some code below as an example datatype. */
struct
record
{
const
char
*
precision
;
double
lat
,
lon
;
const
char
*
address
,
*
city
,
*
state
,
*
zip
,
*
country
;
};
struct
record
{
const
char
*
precision
;
double
lat
;
double
lon
;
const
char
*
address
;
const
char
*
city
;
const
char
*
state
;
const
char
*
zip
;
const
char
*
country
;
};
/* Create a bunch of objects as demonstration. */
void
create_objects
()
{
cJSON
*
root
,
*
fmt
,
*
img
,
*
thm
,
*
fld
;
char
*
out
;
int
i
;
/* declare a few. */
/* declare a few. */
cJSON
*
root
;
cJSON
*
fmt
;
cJSON
*
img
;
cJSON
*
thm
;
cJSON
*
fld
;
char
*
out
;
int
i
;
/* Our "days of the week" array: */
const
char
*
strings
[
7
]
=
{
"Sunday"
,
"Monday"
,
"Tuesday"
,
"Wednesday"
,
"Thursday"
,
"Friday"
,
"Saturday"
};
const
char
*
strings
[
7
]
=
{
"Sunday"
,
"Monday"
,
"Tuesday"
,
"Wednesday"
,
"Thursday"
,
"Friday"
,
"Saturday"
};
/* Our matrix: */
int
numbers
[
3
][
3
]
=
{{
0
,
-
1
,
0
},{
1
,
0
,
0
},{
0
,
0
,
1
}};
int
numbers
[
3
][
3
]
=
{
{
0
,
-
1
,
0
},
{
1
,
0
,
0
},
{
0
,
0
,
1
}
};
/* Our "gallery" item: */
int
ids
[
4
]
=
{
116
,
943
,
234
,
38793
};
int
ids
[
4
]
=
{
116
,
943
,
234
,
38793
};
/* Our array of "records": */
struct
record
fields
[
2
]
=
{
{
"zip"
,
37
.
7668
,
-
1.223959e+2
,
""
,
"SAN FRANCISCO"
,
"CA"
,
"94107"
,
"US"
},
{
"zip"
,
37
.
371991
,
-
1.22026e+2
,
""
,
"SUNNYVALE"
,
"CA"
,
"94085"
,
"US"
}};
struct
record
fields
[
2
]
=
{
{
"zip"
,
37
.
7668
,
-
1.223959e+2
,
""
,
"SAN FRANCISCO"
,
"CA"
,
"94107"
,
"US"
},
{
"zip"
,
37
.
371991
,
-
1.22026e+2
,
""
,
"SUNNYVALE"
,
"CA"
,
"94085"
,
"US"
}
};
volatile
double
zero
=
0
.
0
;
/* Here we construct some JSON standards, from the JSON site. */
/* Our "Video" datatype: */
root
=
cJSON_CreateObject
();
root
=
cJSON_CreateObject
();
cJSON_AddItemToObject
(
root
,
"name"
,
cJSON_CreateString
(
"Jack (
\"
Bee
\"
) Nimble"
));
cJSON_AddItemToObject
(
root
,
"format"
,
fmt
=
cJSON_CreateObject
());
cJSON_AddStringToObject
(
fmt
,
"type"
,
"rect"
);
cJSON_AddNumberToObject
(
fmt
,
"width"
,
1920
);
cJSON_AddNumberToObject
(
fmt
,
"height"
,
1080
);
cJSON_AddFalseToObject
(
fmt
,
"interlace"
);
cJSON_AddNumberToObject
(
fmt
,
"frame rate"
,
24
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
/* Print to text, Delete the cJSON, print it, release the string. */
cJSON_AddItemToObject
(
root
,
"format"
,
fmt
=
cJSON_CreateObject
());
cJSON_AddStringToObject
(
fmt
,
"type"
,
"rect"
);
cJSON_AddNumberToObject
(
fmt
,
"width"
,
1920
);
cJSON_AddNumberToObject
(
fmt
,
"height"
,
1080
);
cJSON_AddFalseToObject
(
fmt
,
"interlace"
);
cJSON_AddNumberToObject
(
fmt
,
"frame rate"
,
24
);
/* Print to text */
out
=
cJSON_Print
(
root
);
/* Delete the cJSON */
cJSON_Delete
(
root
);
/* print it */
printf
(
"%s
\n
"
,
out
);
/* release the string */
free
(
out
);
/* Our "days of the week" array: */
root
=
cJSON_CreateStringArray
(
strings
,
7
);
root
=
cJSON_CreateStringArray
(
strings
,
7
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
/* Our matrix: */
root
=
cJSON_CreateArray
();
for
(
i
=
0
;
i
<
3
;
i
++
)
cJSON_AddItemToArray
(
root
,
cJSON_CreateIntArray
(
numbers
[
i
],
3
));
root
=
cJSON_CreateArray
();
for
(
i
=
0
;
i
<
3
;
i
++
)
{
cJSON_AddItemToArray
(
root
,
cJSON_CreateIntArray
(
numbers
[
i
],
3
));
}
/* cJSON_ReplaceItemInArray(root,1,
cJSON_CreateString("Replacement")); */
/* cJSON_ReplaceItemInArray(root, 1,
cJSON_CreateString("Replacement")); */
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
/* Our "gallery" item: */
root
=
cJSON_CreateObject
();
cJSON_AddItemToObject
(
root
,
"Image"
,
img
=
cJSON_CreateObject
());
cJSON_AddNumberToObject
(
img
,
"Width"
,
800
);
cJSON_AddNumberToObject
(
img
,
"Height"
,
600
);
cJSON_AddStringToObject
(
img
,
"Title"
,
"View from 15th Floor"
);
cJSON_AddItemToObject
(
img
,
"Thumbnail"
,
thm
=
cJSON_CreateObject
());
root
=
cJSON_CreateObject
();
cJSON_AddItemToObject
(
root
,
"Image"
,
img
=
cJSON_CreateObject
());
cJSON_AddNumberToObject
(
img
,
"Width"
,
800
);
cJSON_AddNumberToObject
(
img
,
"Height"
,
600
);
cJSON_AddStringToObject
(
img
,
"Title"
,
"View from 15th Floor"
);
cJSON_AddItemToObject
(
img
,
"Thumbnail"
,
thm
=
cJSON_CreateObject
());
cJSON_AddStringToObject
(
thm
,
"Url"
,
"http:/*www.example.com/image/481989943"
);
cJSON_AddNumberToObject
(
thm
,
"Height"
,
125
);
cJSON_AddStringToObject
(
thm
,
"Width"
,
"100"
);
cJSON_AddItemToObject
(
img
,
"IDs"
,
cJSON_CreateIntArray
(
ids
,
4
));
cJSON_AddNumberToObject
(
thm
,
"Height"
,
125
);
cJSON_AddStringToObject
(
thm
,
"Width"
,
"100"
);
cJSON_AddItemToObject
(
img
,
"IDs"
,
cJSON_CreateIntArray
(
ids
,
4
));
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
/* Our array of "records": */
root
=
cJSON_CreateArray
();
for
(
i
=
0
;
i
<
2
;
i
++
)
root
=
cJSON_CreateArray
();
for
(
i
=
0
;
i
<
2
;
i
++
)
{
cJSON_AddItemToArray
(
root
,
fld
=
cJSON_CreateObject
());
cJSON_AddItemToArray
(
root
,
fld
=
cJSON_CreateObject
());
cJSON_AddStringToObject
(
fld
,
"precision"
,
fields
[
i
].
precision
);
cJSON_AddNumberToObject
(
fld
,
"Latitude"
,
fields
[
i
].
lat
);
cJSON_AddNumberToObject
(
fld
,
"Longitude"
,
fields
[
i
].
lon
);
...
...
@@ -128,24 +216,80 @@ void create_objects()
cJSON_AddStringToObject
(
fld
,
"Country"
,
fields
[
i
].
country
);
}
/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root,1),"City",cJSON_CreateIntArray(ids,
4)); */
/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids,
4)); */
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
root
=
cJSON_CreateObject
();
cJSON_AddNumberToObject
(
root
,
"number"
,
1
.
0
/
zero
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
root
=
cJSON_CreateObject
();
cJSON_AddNumberToObject
(
root
,
"number"
,
1
.
0
/
zero
);
out
=
cJSON_Print
(
root
);
cJSON_Delete
(
root
);
printf
(
"%s
\n
"
,
out
);
free
(
out
);
}
int
main
(
int
argc
,
const
char
*
argv
[])
{
int
main
(
int
argc
,
const
char
*
argv
[])
{
/* a bunch of json: */
char
text1
[]
=
"{
\n\"
name
\"
:
\"
Jack (
\\\"
Bee
\\\"
) Nimble
\"
,
\n\"
format
\"
: {
\"
type
\"
:
\"
rect
\"
,
\n\"
width
\"
: 1920,
\n\"
height
\"
: 1080,
\n\"
interlace
\"
: false,
\"
frame rate
\"
: 24
\n
}
\n
}"
;
char
text2
[]
=
"[
\"
Sunday
\"
,
\"
Monday
\"
,
\"
Tuesday
\"
,
\"
Wednesday
\"
,
\"
Thursday
\"
,
\"
Friday
\"
,
\"
Saturday
\"
]"
;
char
text3
[]
=
"[
\n
[0, -1, 0],
\n
[1, 0, 0],
\n
[0, 0, 1]
\n
]
\n
"
;
char
text4
[]
=
"{
\n
\"
Image
\"
: {
\n
\"
Width
\"
: 800,
\n
\"
Height
\"
: 600,
\n
\"
Title
\"
:
\"
View from 15th Floor
\"
,
\n
\"
Thumbnail
\"
: {
\n
\"
Url
\"
:
\"
http:/*www.example.com/image/481989943
\"
,
\n
\"
Height
\"
: 125,
\n
\"
Width
\"
:
\"
100
\"\n
},
\n
\"
IDs
\"
: [116, 943, 234, 38793]
\n
}
\n
}"
;
char
text5
[]
=
"[
\n
{
\n
\"
precision
\"
:
\"
zip
\"
,
\n
\"
Latitude
\"
: 37.7668,
\n
\"
Longitude
\"
: -122.3959,
\n
\"
Address
\"
:
\"\"
,
\n
\"
City
\"
:
\"
SAN FRANCISCO
\"
,
\n
\"
State
\"
:
\"
CA
\"
,
\n
\"
Zip
\"
:
\"
94107
\"
,
\n
\"
Country
\"
:
\"
US
\"\n
},
\n
{
\n
\"
precision
\"
:
\"
zip
\"
,
\n
\"
Latitude
\"
: 37.371991,
\n
\"
Longitude
\"
: -122.026020,
\n
\"
Address
\"
:
\"\"
,
\n
\"
City
\"
:
\"
SUNNYVALE
\"
,
\n
\"
State
\"
:
\"
CA
\"
,
\n
\"
Zip
\"
:
\"
94085
\"
,
\n
\"
Country
\"
:
\"
US
\"\n
}
\n
]"
;
char
text6
[]
=
"<!DOCTYPE html>"
char
text1
[]
=
"{
\n
"
"
\"
name
\"
:
\"
Jack (
\\\"
Bee
\\\"
) Nimble
\"
,
\n
"
"
\"
format
\"
: {
\"
type
\"
:
\"
rect
\"
,
\n
"
"
\"
width
\"
: 1920,
\n
"
"
\"
height
\"
: 1080,
\n
"
"
\"
interlace
\"
: false,
\"
frame rate
\"
: 24
\n
"
"}
\n
"
"}"
;
char
text2
[]
=
"[
\"
Sunday
\"
,
\"
Monday
\"
,
\"
Tuesday
\"
,
\"
Wednesday
\"
,
\"
Thursday
\"
,
\"
Friday
\"
,
\"
Saturday
\"
]"
;
char
text3
[]
=
"[
\n
"
" [0, -1, 0],
\n
"
" [1, 0, 0],
\n
"
" [0, 0, 1]
\n
"
"
\t
]
\n
"
;
char
text4
[]
=
"{
\n
"
"
\t\t\"
Image
\"
: {
\n
"
"
\t\t\t\"
Width
\"
: 800,
\n
"
"
\t\t\t\"
Height
\"
: 600,
\n
"
"
\t\t\t\"
Title
\"
:
\"
View from 15th Floor
\"
,
\n
"
"
\t\t\t\"
Thumbnail
\"
: {
\n
"
"
\t\t\t\t\"
Url
\"
:
\"
http:/*www.example.com/image/481989943
\"
,
\n
"
"
\t\t\t\t\"
Height
\"
: 125,
\n
"
"
\t\t\t\t\"
Width
\"
:
\"
100
\"\n
"
"
\t\t\t
},
\n
"
"
\t\t\t\"
IDs
\"
: [116, 943, 234, 38793]
\n
"
"
\t\t
}
\n
"
"
\t
}"
;
char
text5
[]
=
"[
\n
"
"
\t
{
\n
"
"
\t
\"
precision
\"
:
\"
zip
\"
,
\n
"
"
\t
\"
Latitude
\"
: 37.7668,
\n
"
"
\t
\"
Longitude
\"
: -122.3959,
\n
"
"
\t
\"
Address
\"
:
\"\"
,
\n
"
"
\t
\"
City
\"
:
\"
SAN FRANCISCO
\"
,
\n
"
"
\t
\"
State
\"
:
\"
CA
\"
,
\n
"
"
\t
\"
Zip
\"
:
\"
94107
\"
,
\n
"
"
\t
\"
Country
\"
:
\"
US
\"\n
"
"
\t
},
\n
"
"
\t
{
\n
"
"
\t
\"
precision
\"
:
\"
zip
\"
,
\n
"
"
\t
\"
Latitude
\"
: 37.371991,
\n
"
"
\t
\"
Longitude
\"
: -122.026020,
\n
"
"
\t
\"
Address
\"
:
\"\"
,
\n
"
"
\t
\"
City
\"
:
\"
SUNNYVALE
\"
,
\n
"
"
\t
\"
State
\"
:
\"
CA
\"
,
\n
"
"
\t
\"
Zip
\"
:
\"
94085
\"
,
\n
"
"
\t
\"
Country
\"
:
\"
US
\"\n
"
"
\t
}
\n
"
"
\t
]"
;
char
text6
[]
=
"<!DOCTYPE html>"
"<html>
\n
"
"<head>
\n
"
" <meta name=
\"
viewport
\"
content=
\"
width=device-width, initial-scale=1
\"
>
\n
"
...
...
@@ -171,12 +315,12 @@ int main (int argc, const char * argv[]) {
doit
(
text6
);
/* Parse standard testfiles: */
/*
dofile("../../tests/test1"); */
/*
dofile("../../tests/test2"); */
/*
dofile("../../tests/test3"); */
/*
dofile("../../tests/test4"); */
/*
dofile("../../tests/test5"); */
/*
dofile("../../tests/test6"); */
/*
dofile("../../tests/test1"); */
/*
dofile("../../tests/test2"); */
/*
dofile("../../tests/test3"); */
/*
dofile("../../tests/test4"); */
/*
dofile("../../tests/test5"); */
/*
dofile("../../tests/test6"); */
/* Now some samplecode for building objects concisely: */
create_objects
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录