cJSON.c (92169B)
1const char *json_string = "{\"abap\":[\"abap\"],\"ags script\":[\"asc\",\"ash\"],\"ampl\":[\"ampl\"],\"antlr\":[\"g4\"],\"apl\":[\"apl\",\"dyalog\"],\"asp\":[\"asp\",\"asax\",\"ascx\",\"ashx\",\"asmx\",\"aspx\",\"axd\"],\"ats\":[\"dats\",\"hats\",\"sats\"],\"actionscript\":[\"as\"],\"ada\":[\"adb\",\"ada\",\"ads\"],\"agda\":[\"agda\"],\"alloy\":[\"als\"],\"apacheconf\":[\"apacheconf\"],\"apex\":[\"cls\"],\"applescript\":[\"applescript\",\"scpt\"],\"arc\":[\"arc\"],\"arduino\":[\"ino\"],\"asciidoc\":[\"asciidoc\",\"adoc\",\"asc\"],\"aspectj\":[\"aj\"],\"assembly\":[\"asm\",\"a51\",\"nasm\"],\"augeas\":[\"aug\"],\"autohotkey\":[\"ahk\",\"ahkl\"],\"autoit\":[\"au3\"],\"awk\":[\"awk\",\"auk\",\"gawk\",\"mawk\",\"nawk\"],\"batchfile\":[\"bat\",\"cmd\"],\"befunge\":[\"befunge\"],\"bison\":[\"y\"],\"bitbake\":[\"bb\"],\"blitzbasic\":[\"bb\",\"decls\"],\"blitzmax\":[\"bmx\"],\"bluespec\":[\"bsv\"],\"boo\":[\"boo\"],\"brainfuck\":[\"b\",\"bf\"],\"brightscript\":[\"brs\"],\"bro\":[\"bro\"],\"c\":[\"c\",\"cats\",\"h\",\"idc\",\"w\"],\"c#\":[\"cs\",\"cshtml\",\"csx\"],\"c++\":[\"cpp\",\"c++\",\"cc\",\"cp\",\"cxx\",\"h\",\"h++\",\"hh\",\"hpp\",\"hxx\",\"inl\",\"ipp\",\"tcc\",\"tpp\"],\"c-objdump\":[\"c-objdump\"],\"c2hs haskell\":[\"chs\"],\"clips\":[\"clp\"],\"cmake\":[\"cmake\",\"cmake.in\"],\"cobol\":[\"cob\",\"cbl\",\"ccp\",\"cobol\",\"cpy\"],\"css\":[\"css\"],\"cap'n proto\":[\"capnp\"],\"cartocss\":[\"mss\"],\"ceylon\":[\"ceylon\"],\"chapel\":[\"chpl\"],\"chuck\":[\"ck\"],\"cirru\":[\"cirru\"],\"clarion\":[\"clw\"],\"clean\":[\"icl\",\"dcl\"],\"clojure\":[\"clj\",\"boot\",\"cl2\",\"cljc\",\"cljs\",\"cljs.hl\",\"cljscm\",\"cljx\",\"hic\"],\"coffeescript\":[\"coffee\",\"_coffee\",\"cjsx\",\"cson\",\"iced\"],\"coldfusion\":[\"cfm\",\"cfml\"],\"coldfusion cfc\":[\"cfc\"],\"common lisp\":[\"lisp\",\"asd\",\"cl\",\"lsp\",\"ny\",\"podsl\"],\"component pascal\":[\"cp\",\"cps\"],\"cool\":[\"cl\"],\"coq\":[\"coq\",\"v\"],\"cpp-objdump\":[\"cppobjdump\",\"c++-objdump\",\"c++objdump\",\"cpp-objdump\",\"cxx-objdump\"],\"creole\":[\"creole\"],\"crystal\":[\"cr\"],\"cucumber\":[\"feature\"],\"cuda\":[\"cu\",\"cuh\"],\"cycript\":[\"cy\"],\"cython\":[\"pyx\",\"pxd\",\"pxi\"],\"d\":[\"d\",\"di\"],\"d-objdump\":[\"d-objdump\"],\"digital command language\":[\"com\"],\"dm\":[\"dm\"],\"dtrace\":[\"d\"],\"darcs patch\":[\"darcspatch\",\"dpatch\"],\"dart\":[\"dart\"],\"diff\":[\"diff\",\"patch\"],\"dockerfile\":[\"dockerfile\"],\"dogescript\":[\"djs\"],\"dylan\":[\"dylan\",\"dyl\",\"intr\",\"lid\"],\"e\":[\"E\"],\"ecl\":[\"ecl\",\"eclxml\"],\"eagle\":[\"sch\",\"brd\"],\"ecere projects\":[\"epj\"],\"eiffel\":[\"e\"],\"elixir\":[\"ex\",\"exs\"],\"elm\":[\"elm\"],\"emacs lisp\":[\"el\",\"emacs\",\"emacs.desktop\"],\"emberscript\":[\"em\",\"emberscript\"],\"erlang\":[\"erl\",\"es\",\"escript\",\"hrl\"],\"f#\":[\"fs\",\"fsi\",\"fsx\"],\"flux\":[\"fx\",\"flux\"],\"fortran\":[\"f90\",\"f\",\"f03\",\"f08\",\"f77\",\"f95\",\"for\",\"fpp\"],\"factor\":[\"factor\"],\"fancy\":[\"fy\",\"fancypack\"],\"fantom\":[\"fan\"],\"filterscript\":[\"fs\"],\"formatted\":[\"for\"],\"forth\":[\"fth\",\"4th\",\"f\",\"for\",\"forth\",\"fr\",\"frt\",\"fs\"],\"frege\":[\"fr\"],\"g-code\":[\"g\",\"gco\",\"gcode\"],\"gams\":[\"gms\"],\"gap\":[\"g\",\"gap\",\"gd\",\"gi\",\"tst\"],\"gas\":[\"s\"],\"gdscript\":[\"gd\"],\"glsl\":[\"glsl\",\"fp\",\"frag\",\"frg\",\"fs\",\"fshader\",\"geo\",\"geom\",\"glslv\",\"gshader\",\"shader\",\"vert\",\"vrx\",\"vshader\"],\"game maker language\":[\"gml\"],\"genshi\":[\"kid\"],\"gentoo ebuild\":[\"ebuild\"],\"gentoo eclass\":[\"eclass\"],\"gettext catalog\":[\"po\",\"pot\"],\"glyph\":[\"glf\"],\"gnuplot\":[\"gp\",\"gnu\",\"gnuplot\",\"plot\",\"plt\"],\"go\":[\"go\"],\"golo\":[\"golo\"],\"gosu\":[\"gs\",\"gst\",\"gsx\",\"vark\"],\"grace\":[\"grace\"],\"gradle\":[\"gradle\"],\"grammatical framework\":[\"gf\"],\"graph modeling language\":[\"gml\"],\"graphviz (dot)\":[\"dot\",\"gv\"],\"groff\":[\"man\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\"],\"groovy\":[\"groovy\",\"grt\",\"gtpl\",\"gvy\"],\"groovy server pages\":[\"gsp\"],\"html\":[\"html\",\"htm\",\"html.hl\",\"st\",\"xht\",\"xhtml\"],\"html+django\":[\"mustache\",\"jinja\"],\"html+erb\":[\"erb\",\"erb.deface\"],\"html+php\":[\"phtml\"],\"http\":[\"http\"],\"hack\":[\"hh\",\"php\"],\"haml\":[\"haml\",\"haml.deface\"],\"handlebars\":[\"handlebars\",\"hbs\"],\"harbour\":[\"hb\"],\"haskell\":[\"hs\",\"hsc\"],\"haxe\":[\"hx\",\"hxsl\"],\"hy\":[\"hy\"],\"idl\":[\"pro\",\"dlm\"],\"igor pro\":[\"ipf\"],\"ini\":[\"ini\",\"cfg\",\"prefs\",\"pro\",\"properties\"],\"irc log\":[\"irclog\",\"weechatlog\"],\"idris\":[\"idr\",\"lidr\"],\"inform 7\":[\"ni\",\"i7x\"],\"inno setup\":[\"iss\"],\"io\":[\"io\"],\"ioke\":[\"ik\"],\"isabelle\":[\"thy\"],\"j\":[\"ijs\"],\"jflex\":[\"flex\",\"jflex\"],\"json\":[\"json\",\"lock\"],\"json5\":[\"json5\"],\"jsonld\":[\"jsonld\"],\"jsoniq\":[\"jq\"],\"jade\":[\"jade\"],\"jasmin\":[\"j\"],\"java\":[\"java\"],\"java server pages\":[\"jsp\"],\"javascript\":[\"js\",\"_js\",\"bones\",\"es6\",\"frag\",\"gs\",\"jake\",\"jsb\",\"jsfl\",\"jsm\",\"jss\",\"jsx\",\"njs\",\"pac\",\"sjs\",\"ssjs\",\"sublime-build\",\"sublime-commands\",\"sublime-completions\",\"sublime-keymap\",\"sublime-macro\",\"sublime-menu\",\"sublime-mousemap\",\"sublime-project\",\"sublime-settings\",\"sublime-theme\",\"sublime-workspace\",\"sublime_metrics\",\"sublime_session\",\"xsjs\",\"xsjslib\"],\"julia\":[\"jl\"],\"krl\":[\"krl\"],\"kicad\":[\"sch\"],\"kit\":[\"kit\"],\"kotlin\":[\"kt\",\"ktm\",\"kts\"],\"lfe\":[\"lfe\"],\"llvm\":[\"ll\"],\"lolcode\":[\"lol\"],\"lsl\":[\"lsl\"],\"labview\":[\"lvproj\"],\"lasso\":[\"lasso\",\"las\",\"lasso8\",\"lasso9\",\"ldml\"],\"latte\":[\"latte\"],\"lean\":[\"lean\",\"hlean\"],\"less\":[\"less\"],\"lilypond\":[\"ly\",\"ily\"],\"limbo\":[\"b\",\"m\"],\"linker script\":[\"ld\",\"lds\"],\"liquid\":[\"liquid\"],\"literate agda\":[\"lagda\"],\"literate coffeescript\":[\"litcoffee\"],\"literate haskell\":[\"lhs\"],\"livescript\":[\"ls\",\"_ls\"],\"logos\":[\"xm\",\"x\",\"xi\"],\"logtalk\":[\"lgt\",\"logtalk\"],\"lookml\":[\"lookml\"],\"loomscript\":[\"ls\"],\"lua\":[\"lua\",\"fcgi\",\"nse\",\"pd_lua\",\"rbxs\",\"wlua\"],\"m\":[\"mumps\",\"m\"],\"mtml\":[\"mtml\"],\"muf\":[\"muf\",\"m\"],\"makefile\":[\"mak\",\"d\",\"mk\"],\"mako\":[\"mako\",\"mao\"],\"markdown\":[\"md\",\"markdown\",\"mkd\",\"mkdn\",\"mkdown\",\"ron\"],\"mask\":[\"mask\"],\"mathematica\":[\"mathematica\",\"cdf\",\"m\",\"ma\",\"nb\",\"nbp\",\"wl\",\"wlt\"],\"matlab\":[\"matlab\",\"m\"],\"max\":[\"maxpat\",\"maxhelp\",\"maxproj\",\"mxt\",\"pat\"],\"mediawiki\":[\"mediawiki\"],\"mercury\":[\"m\",\"moo\"],\"minid\":[\"minid\"],\"mirah\":[\"druby\",\"duby\",\"mir\",\"mirah\"],\"modelica\":[\"mo\"],\"module management system\":[\"mms\",\"mmk\"],\"monkey\":[\"monkey\"],\"moocode\":[\"moo\"],\"moonscript\":[\"moon\"],\"myghty\":[\"myt\"],\"nl\":[\"nl\"],\"nsis\":[\"nsi\",\"nsh\"],\"nemerle\":[\"n\"],\"netlinx\":[\"axs\",\"axi\"],\"netlinx+erb\":[\"axs.erb\",\"axi.erb\"],\"netlogo\":[\"nlogo\"],\"newlisp\":[\"nl\",\"lisp\",\"lsp\"],\"nginx\":[\"nginxconf\"],\"nimrod\":[\"nim\",\"nimrod\"],\"ninja\":[\"ninja\"],\"nit\":[\"nit\"],\"nix\":[\"nix\"],\"nu\":[\"nu\"],\"numpy\":[\"numpy\",\"numpyw\",\"numsc\"],\"ocaml\":[\"ml\",\"eliom\",\"eliomi\",\"ml4\",\"mli\",\"mll\",\"mly\"],\"objdump\":[\"objdump\"],\"objective-c\":[\"m\",\"h\"],\"objective-c++\":[\"mm\"],\"objective-j\":[\"j\",\"sj\"],\"omgrofl\":[\"omgrofl\"],\"opa\":[\"opa\"],\"opal\":[\"opal\"],\"opencl\":[\"cl\",\"opencl\"],\"openedge abl\":[\"p\",\"cls\"],\"openscad\":[\"scad\"],\"org\":[\"org\"],\"ox\":[\"ox\",\"oxh\",\"oxo\"],\"oxygene\":[\"oxygene\"],\"oz\":[\"oz\"],\"pawn\":[\"pwn\"],\"php\":[\"php\",\"aw\",\"ctp\",\"fcgi\",\"php3\",\"php4\",\"php5\",\"phpt\"],\"plsql\":[\"pls\",\"pkb\",\"pks\",\"plb\",\"plsql\",\"sql\"],\"plpgsql\":[\"sql\"],\"pan\":[\"pan\"],\"papyrus\":[\"psc\"],\"parrot\":[\"parrot\"],\"parrot assembly\":[\"pasm\"],\"parrot internal representation\":[\"pir\"],\"pascal\":[\"pas\",\"dfm\",\"dpr\",\"lpr\",\"pp\"],\"perl\":[\"pl\",\"cgi\",\"fcgi\",\"perl\",\"ph\",\"plx\",\"pm\",\"pod\",\"psgi\",\"t\"],\"perl6\":[\"6pl\",\"6pm\",\"nqp\",\"p6\",\"p6l\",\"p6m\",\"pl\",\"pl6\",\"pm\",\"pm6\",\"t\"],\"piglatin\":[\"pig\"],\"pike\":[\"pike\",\"pmod\"],\"pod\":[\"pod\"],\"pogoscript\":[\"pogo\"],\"postscript\":[\"ps\",\"eps\"],\"powershell\":[\"ps1\",\"psd1\",\"psm1\"],\"processing\":[\"pde\"],\"prolog\":[\"pl\",\"ecl\",\"pro\",\"prolog\"],\"propeller spin\":[\"spin\"],\"protocol buffer\":[\"proto\"],\"public key\":[\"asc\",\"pub\"],\"puppet\":[\"pp\"],\"pure data\":[\"pd\"],\"purebasic\":[\"pb\",\"pbi\"],\"purescript\":[\"purs\"],\"python\":[\"py\",\"cgi\",\"fcgi\",\"gyp\",\"lmi\",\"pyde\",\"pyp\",\"pyt\",\"pyw\",\"tac\",\"wsgi\",\"xpy\"],\"python traceback\":[\"pytb\"],\"qml\":[\"qml\"],\"qmake\":[\"pro\",\"pri\"],\"r\":[\"r\",\"rd\",\"rsx\"],\"raml\":[\"raml\"],\"rdoc\":[\"rdoc\"],\"realbasic\":[\"rbbas\",\"rbfrm\",\"rbmnu\",\"rbres\",\"rbtbar\",\"rbuistate\"],\"rhtml\":[\"rhtml\"],\"rmarkdown\":[\"rmd\"],\"racket\":[\"rkt\",\"rktd\",\"rktl\",\"scrbl\"],\"ragel in ruby host\":[\"rl\"],\"raw token data\":[\"raw\"],\"rebol\":[\"reb\",\"r\",\"r2\",\"r3\",\"rebol\"],\"red\":[\"red\",\"reds\"],\"redcode\":[\"cw\"],\"robotframework\":[\"robot\"],\"rouge\":[\"rg\"],\"ruby\":[\"rb\",\"builder\",\"fcgi\",\"gemspec\",\"god\",\"irbrc\",\"jbuilder\",\"mspec\",\"pluginspec\",\"podspec\",\"rabl\",\"rake\",\"rbuild\",\"rbw\",\"rbx\",\"ru\",\"ruby\",\"thor\",\"watchr\"],\"rust\":[\"rs\"],\"sas\":[\"sas\"],\"scss\":[\"scss\"],\"sparql\":[\"sparql\",\"rq\"],\"sqf\":[\"sqf\",\"hqf\"],\"sql\":[\"sql\",\"cql\",\"ddl\",\"prc\",\"tab\",\"udf\",\"viw\"],\"sqlpl\":[\"sql\",\"db2\"],\"ston\":[\"ston\"],\"svg\":[\"svg\"],\"sage\":[\"sage\",\"sagews\"],\"saltstack\":[\"sls\"],\"sass\":[\"sass\"],\"scala\":[\"scala\",\"sbt\",\"sc\"],\"scaml\":[\"scaml\"],\"scheme\":[\"scm\",\"sld\",\"sls\",\"sps\",\"ss\"],\"scilab\":[\"sci\",\"sce\",\"tst\"],\"self\":[\"self\"],\"shell\":[\"sh\",\"bash\",\"bats\",\"cgi\",\"command\",\"fcgi\",\"ksh\",\"tmux\",\"tool\",\"zsh\"],\"shellsession\":[\"sh-session\"],\"shen\":[\"shen\"],\"slash\":[\"sl\"],\"slim\":[\"slim\"],\"smalltalk\":[\"st\",\"cs\"],\"smarty\":[\"tpl\"],\"sourcepawn\":[\"sp\",\"sma\"],\"squirrel\":[\"nut\"],\"standard ml\":[\"ML\",\"fun\",\"sig\",\"sml\"],\"stata\":[\"do\",\"ado\",\"doh\",\"ihlp\",\"mata\",\"matah\",\"sthlp\"],\"stylus\":[\"styl\"],\"supercollider\":[\"scd\",\"sc\"],\"swift\":[\"swift\"],\"systemverilog\":[\"sv\",\"svh\",\"vh\"],\"toml\":[\"toml\"],\"txl\":[\"txl\"],\"tcl\":[\"tcl\",\"adp\",\"tm\"],\"tcsh\":[\"tcsh\",\"csh\"],\"tex\":[\"tex\",\"aux\",\"bbx\",\"bib\",\"cbx\",\"cls\",\"dtx\",\"ins\",\"lbx\",\"ltx\",\"mkii\",\"mkiv\",\"mkvi\",\"sty\",\"toc\"],\"tea\":[\"tea\"],\"text\":[\"txt\",\"fr\"],\"textile\":[\"textile\"],\"thrift\":[\"thrift\"],\"turing\":[\"t\",\"tu\"],\"turtle\":[\"ttl\"],\"twig\":[\"twig\"],\"typescript\":[\"ts\"],\"unified parallel c\":[\"upc\"],\"unrealscript\":[\"uc\"],\"vcl\":[\"vcl\"],\"vhdl\":[\"vhdl\",\"vhd\",\"vhf\",\"vhi\",\"vho\",\"vhs\",\"vht\",\"vhw\"],\"vala\":[\"vala\",\"vapi\"],\"verilog\":[\"v\",\"veo\"],\"viml\":[\"vim\"],\"visual basic\":[\"vb\",\"bas\",\"cls\",\"frm\",\"frx\",\"vba\",\"vbhtml\",\"vbs\"],\"volt\":[\"volt\"],\"web ontology language\":[\"owl\"],\"webidl\":[\"webidl\"],\"xc\":[\"xc\"],\"xml\":[\"xml\",\"ant\",\"axml\",\"ccxml\",\"clixml\",\"cproject\",\"csproj\",\"ct\",\"dita\",\"ditamap\",\"ditaval\",\"dll.config\",\"filters\",\"fsproj\",\"fxml\",\"glade\",\"grxml\",\"ivy\",\"jelly\",\"kml\",\"launch\",\"mm\",\"mxml\",\"nproj\",\"nuspec\",\"odd\",\"osm\",\"plist\",\"pluginspec\",\"ps1xml\",\"psc1\",\"pt\",\"rdf\",\"rss\",\"scxml\",\"srdf\",\"storyboard\",\"stTheme\",\"sublime-snippet\",\"targets\",\"tmCommand\",\"tml\",\"tmLanguage\",\"tmPreferences\",\"tmSnippet\",\"tmTheme\",\"ts\",\"ui\",\"urdf\",\"vbproj\",\"vcxproj\",\"vxml\",\"wsdl\",\"wsf\",\"wxi\",\"wxl\",\"wxs\",\"x3d\",\"xacro\",\"xaml\",\"xib\",\"xlf\",\"xliff\",\"xmi\",\"xml.dist\",\"xsd\",\"xul\",\"zcml\"],\"xproc\":[\"xpl\",\"xproc\"],\"xquery\":[\"xquery\",\"xq\",\"xql\",\"xqm\",\"xqy\"],\"xs\":[\"xs\"],\"xslt\":[\"xslt\",\"xsl\"],\"xojo\":[\"xojo_code\",\"xojo_menu\",\"xojo_report\",\"xojo_script\",\"xojo_toolbar\",\"xojo_window\"],\"xtend\":[\"xtend\"],\"yaml\":[\"yml\",\"reek\",\"rviz\",\"yaml\"],\"zephir\":[\"zep\"],\"zimpl\":[\"zimpl\",\"zmpl\",\"zpl\"],\"desktop\":[\"desktop\",\"desktop.in\"],\"ec\":[\"ec\",\"eh\"],\"edn\":[\"edn\"],\"fish\":[\"fish\"],\"mupad\":[\"mu\"],\"nesc\":[\"nc\"],\"ooc\":[\"ooc\"],\"restructuredtext\":[\"rst\",\"rest\"],\"wisp\":[\"wisp\"],\"xbase\":[\"prg\"]}";
23
/*
4Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
56
Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
1213
The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
1516
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22THE SOFTWARE.
23*/
2425
/* cJSON */
26/* JSON parser in C. */
2728
/* disable warnings about old C89 functions in MSVC */
29#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
30#define _CRT_SECURE_NO_DEPRECATE
31#endif
3233
#ifdef __GNUC__
34#pragma GCC visibility push(default)
35#endif
36#if defined(_MSC_VER)
37#pragma warning (push)
38/* disable warning about single line comments in system headers */
39#pragma warning (disable : 4001)
40#endif
4142
#include <string.h>
43#include <stdio.h>
44#include <math.h>
45#include <stdlib.h>
46#include <limits.h>
47#include <ctype.h>
48#include <float.h>
4950
#ifdef ENABLE_LOCALES
51#include <locale.h>
52#endif
5354
#if defined(_MSC_VER)
55#pragma warning (pop)
56#endif
57#ifdef __GNUC__
58#pragma GCC visibility pop
59#endif
6061
#include "cJSON.h"
6263
/* define our own boolean type */
64#ifdef true
65#undef true
66#endif
67#define true ((cJSON_bool)1)
6869
#ifdef false
70#undef false
71#endif
72#define false ((cJSON_bool)0)
7374
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
75#ifndef isinf
76#define isinf(d) (isnan((d - d)) && !isnan(d))
77#endif
78#ifndef isnan
79#define isnan(d) (d != d)
80#endif
8182
#ifndef NAN
83#ifdef _WIN32
84#define NAN sqrt(-1.0)
85#else
86#define NAN 0.0/0.0
87#endif
88#endif
8990
typedef struct {
91const unsigned char *json;
92size_t position;
93} error;
94static error global_error = { NULL, 0 };
9596
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
97{
98return (const char*) (global_error.json + global_error.position);
99}
100101
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
102{
103if (!cJSON_IsString(item))
104{
105return NULL;
106}
107108
return item->valuestring;
109}
110111
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
112{
113if (!cJSON_IsNumber(item))
114{
115return (double) NAN;
116}
117118
return item->valuedouble;
119}
120121
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
122#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
123#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
124#endif
125126
CJSON_PUBLIC(const char*) cJSON_Version(void)
127{
128static char version[15];
129sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
130131
return version;
132}
133134
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
135static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
136{
137if ((string1 == NULL) || (string2 == NULL))
138{
139return 1;
140}
141142
if (string1 == string2)
143{
144return 0;
145}
146147
for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
148{
149if (*string1 == '\0')
150{
151return 0;
152}
153}
154155
return tolower(*string1) - tolower(*string2);
156}
157158
typedef struct internal_hooks
159{
160void *(CJSON_CDECL *allocate)(size_t size);
161void (CJSON_CDECL *deallocate)(void *pointer);
162void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
163} internal_hooks;
164165
#if defined(_MSC_VER)
166/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
167static void * CJSON_CDECL internal_malloc(size_t size)
168{
169return malloc(size);
170}
171static void CJSON_CDECL internal_free(void *pointer)
172{
173free(pointer);
174}
175static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
176{
177return realloc(pointer, size);
178}
179#else
180#define internal_malloc malloc
181#define internal_free free
182#define internal_realloc realloc
183#endif
184185
/* strlen of character literals resolved at compile time */
186#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
187188
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
189190
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
191{
192size_t length = 0;
193unsigned char *copy = NULL;
194195
if (string == NULL)
196{
197return NULL;
198}
199200
length = strlen((const char*)string) + sizeof("");
201copy = (unsigned char*)hooks->allocate(length);
202if (copy == NULL)
203{
204return NULL;
205}
206memcpy(copy, string, length);
207208
return copy;
209}
210211
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
212{
213if (hooks == NULL)
214{
215/* Reset hooks */
216global_hooks.allocate = malloc;
217global_hooks.deallocate = free;
218global_hooks.reallocate = realloc;
219return;
220}
221222
global_hooks.allocate = malloc;
223if (hooks->malloc_fn != NULL)
224{
225global_hooks.allocate = hooks->malloc_fn;
226}
227228
global_hooks.deallocate = free;
229if (hooks->free_fn != NULL)
230{
231global_hooks.deallocate = hooks->free_fn;
232}
233234
/* use realloc only if both free and malloc are used */
235global_hooks.reallocate = NULL;
236if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
237{
238global_hooks.reallocate = realloc;
239}
240}
241242
/* Internal constructor. */
243static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
244{
245cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
246if (node)
247{
248memset(node, '\0', sizeof(cJSON));
249}
250251
return node;
252}
253254
/* Delete a cJSON structure. */
255CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
256{
257cJSON *next = NULL;
258while (item != NULL)
259{
260next = item->next;
261if (!(item->type & cJSON_IsReference) && (item->child != NULL))
262{
263cJSON_Delete(item->child);
264}
265if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
266{
267global_hooks.deallocate(item->valuestring);
268item->valuestring = NULL;
269}
270if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
271{
272global_hooks.deallocate(item->string);
273item->string = NULL;
274}
275global_hooks.deallocate(item);
276item = next;
277}
278}
279280
/* get the decimal point character of the current locale */
281static unsigned char get_decimal_point(void)
282{
283#ifdef ENABLE_LOCALES
284struct lconv *lconv = localeconv();
285return (unsigned char) lconv->decimal_point[0];
286#else
287return '.';
288#endif
289}
290291
typedef struct
292{
293const unsigned char *content;
294size_t length;
295size_t offset;
296size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
297internal_hooks hooks;
298} parse_buffer;
299300
/* check if the given size is left to read in a given parse buffer (starting with 1) */
301#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
302/* check if the buffer can be accessed at the given index (starting with 0) */
303#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
304#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
305/* get a pointer to the buffer at the position */
306#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
307308
/* Parse the input text to generate a number, and populate the result into item. */
309static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
310{
311double number = 0;
312unsigned char *after_end = NULL;
313unsigned char number_c_string[64];
314unsigned char decimal_point = get_decimal_point();
315size_t i = 0;
316317
if ((input_buffer == NULL) || (input_buffer->content == NULL))
318{
319return false;
320}
321322
/* copy the number into a temporary buffer and replace '.' with the decimal point
323* of the current locale (for strtod)
324* This also takes care of '\0' not necessarily being available for marking the end of the input */
325for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
326{
327switch (buffer_at_offset(input_buffer)[i])
328{
329case '0':
330case '1':
331case '2':
332case '3':
333case '4':
334case '5':
335case '6':
336case '7':
337case '8':
338case '9':
339case '+':
340case '-':
341case 'e':
342case 'E':
343number_c_string[i] = buffer_at_offset(input_buffer)[i];
344break;
345346
case '.':
347number_c_string[i] = decimal_point;
348break;
349350
default:
351goto loop_end;
352}
353}
354loop_end:
355number_c_string[i] = '\0';
356357
number = strtod((const char*)number_c_string, (char**)&after_end);
358if (number_c_string == after_end)
359{
360return false; /* parse_error */
361}
362363
item->valuedouble = number;
364365
/* use saturation in case of overflow */
366if (number >= INT_MAX)
367{
368item->valueint = INT_MAX;
369}
370else if (number <= (double)INT_MIN)
371{
372item->valueint = INT_MIN;
373}
374else
375{
376item->valueint = (int)number;
377}
378379
item->type = cJSON_Number;
380381
input_buffer->offset += (size_t)(after_end - number_c_string);
382return true;
383}
384385
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
386CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
387{
388if (number >= INT_MAX)
389{
390object->valueint = INT_MAX;
391}
392else if (number <= (double)INT_MIN)
393{
394object->valueint = INT_MIN;
395}
396else
397{
398object->valueint = (int)number;
399}
400401
return object->valuedouble = number;
402}
403404
/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
405CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
406{
407char *copy = NULL;
408size_t v1_len;
409size_t v2_len;
410/* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
411if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
412{
413return NULL;
414}
415/* return NULL if the object is corrupted or valuestring is NULL */
416if (object->valuestring == NULL || valuestring == NULL)
417{
418return NULL;
419}
420421
v1_len = strlen(valuestring);
422v2_len = strlen(object->valuestring);
423424
if (v1_len <= v2_len)
425{
426/* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
427if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
428{
429return NULL;
430}
431strcpy(object->valuestring, valuestring);
432return object->valuestring;
433}
434copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
435if (copy == NULL)
436{
437return NULL;
438}
439if (object->valuestring != NULL)
440{
441cJSON_free(object->valuestring);
442}
443object->valuestring = copy;
444445
return copy;
446}
447448
typedef struct
449{
450unsigned char *buffer;
451size_t length;
452size_t offset;
453size_t depth; /* current nesting depth (for formatted printing) */
454cJSON_bool noalloc;
455cJSON_bool format; /* is this print a formatted print */
456internal_hooks hooks;
457} printbuffer;
458459
/* realloc printbuffer if necessary to have at least "needed" bytes more */
460static unsigned char* ensure(printbuffer * const p, size_t needed)
461{
462unsigned char *newbuffer = NULL;
463size_t newsize = 0;
464465
if ((p == NULL) || (p->buffer == NULL))
466{
467return NULL;
468}
469470
if ((p->length > 0) && (p->offset >= p->length))
471{
472/* make sure that offset is valid */
473return NULL;
474}
475476
if (needed > INT_MAX)
477{
478/* sizes bigger than INT_MAX are currently not supported */
479return NULL;
480}
481482
needed += p->offset + 1;
483if (needed <= p->length)
484{
485return p->buffer + p->offset;
486}
487488
if (p->noalloc) {
489return NULL;
490}
491492
/* calculate new buffer size */
493if (needed > (INT_MAX / 2))
494{
495/* overflow of int, use INT_MAX if possible */
496if (needed <= INT_MAX)
497{
498newsize = INT_MAX;
499}
500else
501{
502return NULL;
503}
504}
505else
506{
507newsize = needed * 2;
508}
509510
if (p->hooks.reallocate != NULL)
511{
512/* reallocate with realloc if available */
513newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
514if (newbuffer == NULL)
515{
516p->hooks.deallocate(p->buffer);
517p->length = 0;
518p->buffer = NULL;
519520
return NULL;
521}
522}
523else
524{
525/* otherwise reallocate manually */
526newbuffer = (unsigned char*)p->hooks.allocate(newsize);
527if (!newbuffer)
528{
529p->hooks.deallocate(p->buffer);
530p->length = 0;
531p->buffer = NULL;
532533
return NULL;
534}
535536
memcpy(newbuffer, p->buffer, p->offset + 1);
537p->hooks.deallocate(p->buffer);
538}
539p->length = newsize;
540p->buffer = newbuffer;
541542
return newbuffer + p->offset;
543}
544545
/* calculate the new length of the string in a printbuffer and update the offset */
546static void update_offset(printbuffer * const buffer)
547{
548const unsigned char *buffer_pointer = NULL;
549if ((buffer == NULL) || (buffer->buffer == NULL))
550{
551return;
552}
553buffer_pointer = buffer->buffer + buffer->offset;
554555
buffer->offset += strlen((const char*)buffer_pointer);
556}
557558
/* securely comparison of floating-point variables */
559static cJSON_bool compare_double(double a, double b)
560{
561double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
562return (fabs(a - b) <= maxVal * DBL_EPSILON);
563}
564565
/* Render the number nicely from the given item into a string. */
566static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
567{
568unsigned char *output_pointer = NULL;
569double d = item->valuedouble;
570int length = 0;
571size_t i = 0;
572unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
573unsigned char decimal_point = get_decimal_point();
574double test = 0.0;
575576
if (output_buffer == NULL)
577{
578return false;
579}
580581
/* This checks for NaN and Infinity */
582if (isnan(d) || isinf(d))
583{
584length = sprintf((char*)number_buffer, "null");
585}
586else if(d == (double)item->valueint)
587{
588length = sprintf((char*)number_buffer, "%d", item->valueint);
589}
590else
591{
592/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
593length = sprintf((char*)number_buffer, "%1.15g", d);
594595
/* Check whether the original double can be recovered */
596if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
597{
598/* If not, print with 17 decimal places of precision */
599length = sprintf((char*)number_buffer, "%1.17g", d);
600}
601}
602603
/* sprintf failed or buffer overrun occurred */
604if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
605{
606return false;
607}
608609
/* reserve appropriate space in the output */
610output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
611if (output_pointer == NULL)
612{
613return false;
614}
615616
/* copy the printed number to the output and replace locale
617* dependent decimal point with '.' */
618for (i = 0; i < ((size_t)length); i++)
619{
620if (number_buffer[i] == decimal_point)
621{
622output_pointer[i] = '.';
623continue;
624}
625626
output_pointer[i] = number_buffer[i];
627}
628output_pointer[i] = '\0';
629630
output_buffer->offset += (size_t)length;
631632
return true;
633}
634635
/* parse 4 digit hexadecimal number */
636static unsigned parse_hex4(const unsigned char * const input)
637{
638unsigned int h = 0;
639size_t i = 0;
640641
for (i = 0; i < 4; i++)
642{
643/* parse digit */
644if ((input[i] >= '0') && (input[i] <= '9'))
645{
646h += (unsigned int) input[i] - '0';
647}
648else if ((input[i] >= 'A') && (input[i] <= 'F'))
649{
650h += (unsigned int) 10 + input[i] - 'A';
651}
652else if ((input[i] >= 'a') && (input[i] <= 'f'))
653{
654h += (unsigned int) 10 + input[i] - 'a';
655}
656else /* invalid */
657{
658return 0;
659}
660661
if (i < 3)
662{
663/* shift left to make place for the next nibble */
664h = h << 4;
665}
666}
667668
return h;
669}
670671
/* converts a UTF-16 literal to UTF-8
672* A literal can be one or two sequences of the form \uXXXX */
673static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
674{
675long unsigned int codepoint = 0;
676unsigned int first_code = 0;
677const unsigned char *first_sequence = input_pointer;
678unsigned char utf8_length = 0;
679unsigned char utf8_position = 0;
680unsigned char sequence_length = 0;
681unsigned char first_byte_mark = 0;
682683
if ((input_end - first_sequence) < 6)
684{
685/* input ends unexpectedly */
686goto fail;
687}
688689
/* get the first utf16 sequence */
690first_code = parse_hex4(first_sequence + 2);
691692
/* check that the code is valid */
693if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
694{
695goto fail;
696}
697698
/* UTF16 surrogate pair */
699if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
700{
701const unsigned char *second_sequence = first_sequence + 6;
702unsigned int second_code = 0;
703sequence_length = 12; /* \uXXXX\uXXXX */
704705
if ((input_end - second_sequence) < 6)
706{
707/* input ends unexpectedly */
708goto fail;
709}
710711
if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
712{
713/* missing second half of the surrogate pair */
714goto fail;
715}
716717
/* get the second utf16 sequence */
718second_code = parse_hex4(second_sequence + 2);
719/* check that the code is valid */
720if ((second_code < 0xDC00) || (second_code > 0xDFFF))
721{
722/* invalid second half of the surrogate pair */
723goto fail;
724}
725726
727
/* calculate the unicode codepoint from the surrogate pair */
728codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
729}
730else
731{
732sequence_length = 6; /* \uXXXX */
733codepoint = first_code;
734}
735736
/* encode as UTF-8
737* takes at maximum 4 bytes to encode:
738* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
739if (codepoint < 0x80)
740{
741/* normal ascii, encoding 0xxxxxxx */
742utf8_length = 1;
743}
744else if (codepoint < 0x800)
745{
746/* two bytes, encoding 110xxxxx 10xxxxxx */
747utf8_length = 2;
748first_byte_mark = 0xC0; /* 11000000 */
749}
750else if (codepoint < 0x10000)
751{
752/* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
753utf8_length = 3;
754first_byte_mark = 0xE0; /* 11100000 */
755}
756else if (codepoint <= 0x10FFFF)
757{
758/* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
759utf8_length = 4;
760first_byte_mark = 0xF0; /* 11110000 */
761}
762else
763{
764/* invalid unicode codepoint */
765goto fail;
766}
767768
/* encode as utf8 */
769for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
770{
771/* 10xxxxxx */
772(*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
773codepoint >>= 6;
774}
775/* encode first byte */
776if (utf8_length > 1)
777{
778(*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
779}
780else
781{
782(*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
783}
784785
*output_pointer += utf8_length;
786787
return sequence_length;
788789
fail:
790return 0;
791}
792793
/* Parse the input text into an unescaped cinput, and populate item. */
794static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
795{
796const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
797const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
798unsigned char *output_pointer = NULL;
799unsigned char *output = NULL;
800801
/* not a string */
802if (buffer_at_offset(input_buffer)[0] != '\"')
803{
804goto fail;
805}
806807
{
808/* calculate approximate size of the output (overestimate) */
809size_t allocation_length = 0;
810size_t skipped_bytes = 0;
811while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
812{
813/* is escape sequence */
814if (input_end[0] == '\\')
815{
816if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
817{
818/* prevent buffer overflow when last input character is a backslash */
819goto fail;
820}
821skipped_bytes++;
822input_end++;
823}
824input_end++;
825}
826if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
827{
828goto fail; /* string ended unexpectedly */
829}
830831
/* This is at most how much we need for the output */
832allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
833output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
834if (output == NULL)
835{
836goto fail; /* allocation failure */
837}
838}
839840
output_pointer = output;
841/* loop through the string literal */
842while (input_pointer < input_end)
843{
844if (*input_pointer != '\\')
845{
846*output_pointer++ = *input_pointer++;
847}
848/* escape sequence */
849else
850{
851unsigned char sequence_length = 2;
852if ((input_end - input_pointer) < 1)
853{
854goto fail;
855}
856857
switch (input_pointer[1])
858{
859case 'b':
860*output_pointer++ = '\b';
861break;
862case 'f':
863*output_pointer++ = '\f';
864break;
865case 'n':
866*output_pointer++ = '\n';
867break;
868case 'r':
869*output_pointer++ = '\r';
870break;
871case 't':
872*output_pointer++ = '\t';
873break;
874case '\"':
875case '\\':
876case '/':
877*output_pointer++ = input_pointer[1];
878break;
879880
/* UTF-16 literal */
881case 'u':
882sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
883if (sequence_length == 0)
884{
885/* failed to convert UTF16-literal to UTF-8 */
886goto fail;
887}
888break;
889890
default:
891goto fail;
892}
893input_pointer += sequence_length;
894}
895}
896897
/* zero terminate the output */
898*output_pointer = '\0';
899900
item->type = cJSON_String;
901item->valuestring = (char*)output;
902903
input_buffer->offset = (size_t) (input_end - input_buffer->content);
904input_buffer->offset++;
905906
return true;
907908
fail:
909if (output != NULL)
910{
911input_buffer->hooks.deallocate(output);
912output = NULL;
913}
914915
if (input_pointer != NULL)
916{
917input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
918}
919920
return false;
921}
922923
/* Render the cstring provided to an escaped version that can be printed. */
924static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
925{
926const unsigned char *input_pointer = NULL;
927unsigned char *output = NULL;
928unsigned char *output_pointer = NULL;
929size_t output_length = 0;
930/* numbers of additional characters needed for escaping */
931size_t escape_characters = 0;
932933
if (output_buffer == NULL)
934{
935return false;
936}
937938
/* empty string */
939if (input == NULL)
940{
941output = ensure(output_buffer, sizeof("\"\""));
942if (output == NULL)
943{
944return false;
945}
946strcpy((char*)output, "\"\"");
947948
return true;
949}
950951
/* set "flag" to 1 if something needs to be escaped */
952for (input_pointer = input; *input_pointer; input_pointer++)
953{
954switch (*input_pointer)
955{
956case '\"':
957case '\\':
958case '\b':
959case '\f':
960case '\n':
961case '\r':
962case '\t':
963/* one character escape sequence */
964escape_characters++;
965break;
966default:
967if (*input_pointer < 32)
968{
969/* UTF-16 escape sequence uXXXX */
970escape_characters += 5;
971}
972break;
973}
974}
975output_length = (size_t)(input_pointer - input) + escape_characters;
976977
output = ensure(output_buffer, output_length + sizeof("\"\""));
978if (output == NULL)
979{
980return false;
981}
982983
/* no characters have to be escaped */
984if (escape_characters == 0)
985{
986output[0] = '\"';
987memcpy(output + 1, input, output_length);
988output[output_length + 1] = '\"';
989output[output_length + 2] = '\0';
990991
return true;
992}
993994
output[0] = '\"';
995output_pointer = output + 1;
996/* copy the string */
997for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
998{
999if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1000{
1001/* normal character, copy */
1002*output_pointer = *input_pointer;
1003}
1004else
1005{
1006/* character needs to be escaped */
1007*output_pointer++ = '\\';
1008switch (*input_pointer)
1009{
1010case '\\':
1011*output_pointer = '\\';
1012break;
1013case '\"':
1014*output_pointer = '\"';
1015break;
1016case '\b':
1017*output_pointer = 'b';
1018break;
1019case '\f':
1020*output_pointer = 'f';
1021break;
1022case '\n':
1023*output_pointer = 'n';
1024break;
1025case '\r':
1026*output_pointer = 'r';
1027break;
1028case '\t':
1029*output_pointer = 't';
1030break;
1031default:
1032/* escape and print as unicode codepoint */
1033sprintf((char*)output_pointer, "u%04x", *input_pointer);
1034output_pointer += 4;
1035break;
1036}
1037}
1038}
1039output[output_length + 1] = '\"';
1040output[output_length + 2] = '\0';
10411042
return true;
1043}
10441045
/* Invoke print_string_ptr (which is useful) on an item. */
1046static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1047{
1048return print_string_ptr((unsigned char*)item->valuestring, p);
1049}
10501051
/* Predeclare these prototypes. */
1052static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1053static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1054static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1055static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1056static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1057static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
10581059
/* Utility to jump whitespace and cr/lf */
1060static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1061{
1062if ((buffer == NULL) || (buffer->content == NULL))
1063{
1064return NULL;
1065}
10661067
if (cannot_access_at_index(buffer, 0))
1068{
1069return buffer;
1070}
10711072
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1073{
1074buffer->offset++;
1075}
10761077
if (buffer->offset == buffer->length)
1078{
1079buffer->offset--;
1080}
10811082
return buffer;
1083}
10841085
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1086static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1087{
1088if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1089{
1090return NULL;
1091}
10921093
if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1094{
1095buffer->offset += 3;
1096}
10971098
return buffer;
1099}
11001101
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1102{
1103size_t buffer_length;
11041105
if (NULL == value)
1106{
1107return NULL;
1108}
11091110
/* Adding null character size due to require_null_terminated. */
1111buffer_length = strlen(value) + sizeof("");
11121113
return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1114}
11151116
/* Parse an object - create a new root, and populate. */
1117CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1118{
1119parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1120cJSON *item = NULL;
11211122
/* reset error position */
1123global_error.json = NULL;
1124global_error.position = 0;
11251126
if (value == NULL || 0 == buffer_length)
1127{
1128goto fail;
1129}
11301131
buffer.content = (const unsigned char*)value;
1132buffer.length = buffer_length;
1133buffer.offset = 0;
1134buffer.hooks = global_hooks;
11351136
item = cJSON_New_Item(&global_hooks);
1137if (item == NULL) /* memory fail */
1138{
1139goto fail;
1140}
11411142
if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1143{
1144/* parse failure. ep is set. */
1145goto fail;
1146}
11471148
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1149if (require_null_terminated)
1150{
1151buffer_skip_whitespace(&buffer);
1152if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1153{
1154goto fail;
1155}
1156}
1157if (return_parse_end)
1158{
1159*return_parse_end = (const char*)buffer_at_offset(&buffer);
1160}
11611162
return item;
11631164
fail:
1165if (item != NULL)
1166{
1167cJSON_Delete(item);
1168}
11691170
if (value != NULL)
1171{
1172error local_error;
1173local_error.json = (const unsigned char*)value;
1174local_error.position = 0;
11751176
if (buffer.offset < buffer.length)
1177{
1178local_error.position = buffer.offset;
1179}
1180else if (buffer.length > 0)
1181{
1182local_error.position = buffer.length - 1;
1183}
11841185
if (return_parse_end != NULL)
1186{
1187*return_parse_end = (const char*)local_error.json + local_error.position;
1188}
11891190
global_error = local_error;
1191}
11921193
return NULL;
1194}
11951196
/* Default options for cJSON_Parse */
1197CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1198{
1199return cJSON_ParseWithOpts(value, 0, 0);
1200}
12011202
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1203{
1204return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1205}
12061207
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
12081209
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1210{
1211static const size_t default_buffer_size = 256;
1212printbuffer buffer[1];
1213unsigned char *printed = NULL;
12141215
memset(buffer, 0, sizeof(buffer));
12161217
/* create buffer */
1218buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1219buffer->length = default_buffer_size;
1220buffer->format = format;
1221buffer->hooks = *hooks;
1222if (buffer->buffer == NULL)
1223{
1224goto fail;
1225}
12261227
/* print the value */
1228if (!print_value(item, buffer))
1229{
1230goto fail;
1231}
1232update_offset(buffer);
12331234
/* check if reallocate is available */
1235if (hooks->reallocate != NULL)
1236{
1237printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1238if (printed == NULL) {
1239goto fail;
1240}
1241buffer->buffer = NULL;
1242}
1243else /* otherwise copy the JSON over to a new buffer */
1244{
1245printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1246if (printed == NULL)
1247{
1248goto fail;
1249}
1250memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1251printed[buffer->offset] = '\0'; /* just to be sure */
12521253
/* free the buffer */
1254hooks->deallocate(buffer->buffer);
1255buffer->buffer = NULL;
1256}
12571258
return printed;
12591260
fail:
1261if (buffer->buffer != NULL)
1262{
1263hooks->deallocate(buffer->buffer);
1264buffer->buffer = NULL;
1265}
12661267
if (printed != NULL)
1268{
1269hooks->deallocate(printed);
1270printed = NULL;
1271}
12721273
return NULL;
1274}
12751276
/* Render a cJSON item/entity/structure to text. */
1277CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1278{
1279return (char*)print(item, true, &global_hooks);
1280}
12811282
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1283{
1284return (char*)print(item, false, &global_hooks);
1285}
12861287
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1288{
1289printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
12901291
if (prebuffer < 0)
1292{
1293return NULL;
1294}
12951296
p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1297if (!p.buffer)
1298{
1299return NULL;
1300}
13011302
p.length = (size_t)prebuffer;
1303p.offset = 0;
1304p.noalloc = false;
1305p.format = fmt;
1306p.hooks = global_hooks;
13071308
if (!print_value(item, &p))
1309{
1310global_hooks.deallocate(p.buffer);
1311p.buffer = NULL;
1312return NULL;
1313}
13141315
return (char*)p.buffer;
1316}
13171318
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1319{
1320printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
13211322
if ((length < 0) || (buffer == NULL))
1323{
1324return false;
1325}
13261327
p.buffer = (unsigned char*)buffer;
1328p.length = (size_t)length;
1329p.offset = 0;
1330p.noalloc = true;
1331p.format = format;
1332p.hooks = global_hooks;
13331334
return print_value(item, &p);
1335}
13361337
/* Parser core - when encountering text, process appropriately. */
1338static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1339{
1340if ((input_buffer == NULL) || (input_buffer->content == NULL))
1341{
1342return false; /* no input */
1343}
13441345
/* parse the different types of values */
1346/* null */
1347if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1348{
1349item->type = cJSON_NULL;
1350input_buffer->offset += 4;
1351return true;
1352}
1353/* false */
1354if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1355{
1356item->type = cJSON_False;
1357input_buffer->offset += 5;
1358return true;
1359}
1360/* true */
1361if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1362{
1363item->type = cJSON_True;
1364item->valueint = 1;
1365input_buffer->offset += 4;
1366return true;
1367}
1368/* string */
1369if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1370{
1371return parse_string(item, input_buffer);
1372}
1373/* number */
1374if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
1375{
1376return parse_number(item, input_buffer);
1377}
1378/* array */
1379if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1380{
1381return parse_array(item, input_buffer);
1382}
1383/* object */
1384if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1385{
1386return parse_object(item, input_buffer);
1387}
13881389
return false;
1390}
13911392
/* Render a value to text. */
1393static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1394{
1395unsigned char *output = NULL;
13961397
if ((item == NULL) || (output_buffer == NULL))
1398{
1399return false;
1400}
14011402
switch ((item->type) & 0xFF)
1403{
1404case cJSON_NULL:
1405output = ensure(output_buffer, 5);
1406if (output == NULL)
1407{
1408return false;
1409}
1410strcpy((char*)output, "null");
1411return true;
14121413
case cJSON_False:
1414output = ensure(output_buffer, 6);
1415if (output == NULL)
1416{
1417return false;
1418}
1419strcpy((char*)output, "false");
1420return true;
14211422
case cJSON_True:
1423output = ensure(output_buffer, 5);
1424if (output == NULL)
1425{
1426return false;
1427}
1428strcpy((char*)output, "true");
1429return true;
14301431
case cJSON_Number:
1432return print_number(item, output_buffer);
14331434
case cJSON_Raw:
1435{
1436size_t raw_length = 0;
1437if (item->valuestring == NULL)
1438{
1439return false;
1440}
14411442
raw_length = strlen(item->valuestring) + sizeof("");
1443output = ensure(output_buffer, raw_length);
1444if (output == NULL)
1445{
1446return false;
1447}
1448memcpy(output, item->valuestring, raw_length);
1449return true;
1450}
14511452
case cJSON_String:
1453return print_string(item, output_buffer);
14541455
case cJSON_Array:
1456return print_array(item, output_buffer);
14571458
case cJSON_Object:
1459return print_object(item, output_buffer);
14601461
default:
1462return false;
1463}
1464}
14651466
/* Build an array from input text. */
1467static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1468{
1469cJSON *head = NULL; /* head of the linked list */
1470cJSON *current_item = NULL;
14711472
if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1473{
1474return false; /* to deeply nested */
1475}
1476input_buffer->depth++;
14771478
if (buffer_at_offset(input_buffer)[0] != '[')
1479{
1480/* not an array */
1481goto fail;
1482}
14831484
input_buffer->offset++;
1485buffer_skip_whitespace(input_buffer);
1486if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1487{
1488/* empty array */
1489goto success;
1490}
14911492
/* check if we skipped to the end of the buffer */
1493if (cannot_access_at_index(input_buffer, 0))
1494{
1495input_buffer->offset--;
1496goto fail;
1497}
14981499
/* step back to character in front of the first element */
1500input_buffer->offset--;
1501/* loop through the comma separated array elements */
1502do
1503{
1504/* allocate next item */
1505cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1506if (new_item == NULL)
1507{
1508goto fail; /* allocation failure */
1509}
15101511
/* attach next item to list */
1512if (head == NULL)
1513{
1514/* start the linked list */
1515current_item = head = new_item;
1516}
1517else
1518{
1519/* add to the end and advance */
1520current_item->next = new_item;
1521new_item->prev = current_item;
1522current_item = new_item;
1523}
15241525
/* parse next value */
1526input_buffer->offset++;
1527buffer_skip_whitespace(input_buffer);
1528if (!parse_value(current_item, input_buffer))
1529{
1530goto fail; /* failed to parse value */
1531}
1532buffer_skip_whitespace(input_buffer);
1533}
1534while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
15351536
if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1537{
1538goto fail; /* expected end of array */
1539}
15401541
success:
1542input_buffer->depth--;
15431544
if (head != NULL) {
1545head->prev = current_item;
1546}
15471548
item->type = cJSON_Array;
1549item->child = head;
15501551
input_buffer->offset++;
15521553
return true;
15541555
fail:
1556if (head != NULL)
1557{
1558cJSON_Delete(head);
1559}
15601561
return false;
1562}
15631564
/* Render an array to text */
1565static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1566{
1567unsigned char *output_pointer = NULL;
1568size_t length = 0;
1569cJSON *current_element = item->child;
15701571
if (output_buffer == NULL)
1572{
1573return false;
1574}
15751576
/* Compose the output array. */
1577/* opening square bracket */
1578output_pointer = ensure(output_buffer, 1);
1579if (output_pointer == NULL)
1580{
1581return false;
1582}
15831584
*output_pointer = '[';
1585output_buffer->offset++;
1586output_buffer->depth++;
15871588
while (current_element != NULL)
1589{
1590if (!print_value(current_element, output_buffer))
1591{
1592return false;
1593}
1594update_offset(output_buffer);
1595if (current_element->next)
1596{
1597length = (size_t) (output_buffer->format ? 2 : 1);
1598output_pointer = ensure(output_buffer, length + 1);
1599if (output_pointer == NULL)
1600{
1601return false;
1602}
1603*output_pointer++ = ',';
1604if(output_buffer->format)
1605{
1606*output_pointer++ = ' ';
1607}
1608*output_pointer = '\0';
1609output_buffer->offset += length;
1610}
1611current_element = current_element->next;
1612}
16131614
output_pointer = ensure(output_buffer, 2);
1615if (output_pointer == NULL)
1616{
1617return false;
1618}
1619*output_pointer++ = ']';
1620*output_pointer = '\0';
1621output_buffer->depth--;
16221623
return true;
1624}
16251626
/* Build an object from the text. */
1627static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1628{
1629cJSON *head = NULL; /* linked list head */
1630cJSON *current_item = NULL;
16311632
if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1633{
1634return false; /* to deeply nested */
1635}
1636input_buffer->depth++;
16371638
if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1639{
1640goto fail; /* not an object */
1641}
16421643
input_buffer->offset++;
1644buffer_skip_whitespace(input_buffer);
1645if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1646{
1647goto success; /* empty object */
1648}
16491650
/* check if we skipped to the end of the buffer */
1651if (cannot_access_at_index(input_buffer, 0))
1652{
1653input_buffer->offset--;
1654goto fail;
1655}
16561657
/* step back to character in front of the first element */
1658input_buffer->offset--;
1659/* loop through the comma separated array elements */
1660do
1661{
1662/* allocate next item */
1663cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1664if (new_item == NULL)
1665{
1666goto fail; /* allocation failure */
1667}
16681669
/* attach next item to list */
1670if (head == NULL)
1671{
1672/* start the linked list */
1673current_item = head = new_item;
1674}
1675else
1676{
1677/* add to the end and advance */
1678current_item->next = new_item;
1679new_item->prev = current_item;
1680current_item = new_item;
1681}
16821683
if (cannot_access_at_index(input_buffer, 1))
1684{
1685goto fail; /* nothing comes after the comma */
1686}
16871688
/* parse the name of the child */
1689input_buffer->offset++;
1690buffer_skip_whitespace(input_buffer);
1691if (!parse_string(current_item, input_buffer))
1692{
1693goto fail; /* failed to parse name */
1694}
1695buffer_skip_whitespace(input_buffer);
16961697
/* swap valuestring and string, because we parsed the name */
1698current_item->string = current_item->valuestring;
1699current_item->valuestring = NULL;
17001701
if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1702{
1703goto fail; /* invalid object */
1704}
17051706
/* parse the value */
1707input_buffer->offset++;
1708buffer_skip_whitespace(input_buffer);
1709if (!parse_value(current_item, input_buffer))
1710{
1711goto fail; /* failed to parse value */
1712}
1713buffer_skip_whitespace(input_buffer);
1714}
1715while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
17161717
if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1718{
1719goto fail; /* expected end of object */
1720}
17211722
success:
1723input_buffer->depth--;
17241725
if (head != NULL) {
1726head->prev = current_item;
1727}
17281729
item->type = cJSON_Object;
1730item->child = head;
17311732
input_buffer->offset++;
1733return true;
17341735
fail:
1736if (head != NULL)
1737{
1738cJSON_Delete(head);
1739}
17401741
return false;
1742}
17431744
/* Render an object to text. */
1745static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1746{
1747unsigned char *output_pointer = NULL;
1748size_t length = 0;
1749cJSON *current_item = item->child;
17501751
if (output_buffer == NULL)
1752{
1753return false;
1754}
17551756
/* Compose the output: */
1757length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1758output_pointer = ensure(output_buffer, length + 1);
1759if (output_pointer == NULL)
1760{
1761return false;
1762}
17631764
*output_pointer++ = '{';
1765output_buffer->depth++;
1766if (output_buffer->format)
1767{
1768*output_pointer++ = '\n';
1769}
1770output_buffer->offset += length;
17711772
while (current_item)
1773{
1774if (output_buffer->format)
1775{
1776size_t i;
1777output_pointer = ensure(output_buffer, output_buffer->depth);
1778if (output_pointer == NULL)
1779{
1780return false;
1781}
1782for (i = 0; i < output_buffer->depth; i++)
1783{
1784*output_pointer++ = '\t';
1785}
1786output_buffer->offset += output_buffer->depth;
1787}
17881789
/* print key */
1790if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1791{
1792return false;
1793}
1794update_offset(output_buffer);
17951796
length = (size_t) (output_buffer->format ? 2 : 1);
1797output_pointer = ensure(output_buffer, length);
1798if (output_pointer == NULL)
1799{
1800return false;
1801}
1802*output_pointer++ = ':';
1803if (output_buffer->format)
1804{
1805*output_pointer++ = '\t';
1806}
1807output_buffer->offset += length;
18081809
/* print value */
1810if (!print_value(current_item, output_buffer))
1811{
1812return false;
1813}
1814update_offset(output_buffer);
18151816
/* print comma if not last */
1817length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1818output_pointer = ensure(output_buffer, length + 1);
1819if (output_pointer == NULL)
1820{
1821return false;
1822}
1823if (current_item->next)
1824{
1825*output_pointer++ = ',';
1826}
18271828
if (output_buffer->format)
1829{
1830*output_pointer++ = '\n';
1831}
1832*output_pointer = '\0';
1833output_buffer->offset += length;
18341835
current_item = current_item->next;
1836}
18371838
output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1839if (output_pointer == NULL)
1840{
1841return false;
1842}
1843if (output_buffer->format)
1844{
1845size_t i;
1846for (i = 0; i < (output_buffer->depth - 1); i++)
1847{
1848*output_pointer++ = '\t';
1849}
1850}
1851*output_pointer++ = '}';
1852*output_pointer = '\0';
1853output_buffer->depth--;
18541855
return true;
1856}
18571858
/* Get Array size/item / object item. */
1859CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1860{
1861cJSON *child = NULL;
1862size_t size = 0;
18631864
if (array == NULL)
1865{
1866return 0;
1867}
18681869
child = array->child;
18701871
while(child != NULL)
1872{
1873size++;
1874child = child->next;
1875}
18761877
/* FIXME: Can overflow here. Cannot be fixed without breaking the API */
18781879
return (int)size;
1880}
18811882
static cJSON* get_array_item(const cJSON *array, size_t index)
1883{
1884cJSON *current_child = NULL;
18851886
if (array == NULL)
1887{
1888return NULL;
1889}
18901891
current_child = array->child;
1892while ((current_child != NULL) && (index > 0))
1893{
1894index--;
1895current_child = current_child->next;
1896}
18971898
return current_child;
1899}
19001901
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1902{
1903if (index < 0)
1904{
1905return NULL;
1906}
19071908
return get_array_item(array, (size_t)index);
1909}
19101911
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1912{
1913cJSON *current_element = NULL;
19141915
if ((object == NULL) || (name == NULL))
1916{
1917return NULL;
1918}
19191920
current_element = object->child;
1921if (case_sensitive)
1922{
1923while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1924{
1925current_element = current_element->next;
1926}
1927}
1928else
1929{
1930while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1931{
1932current_element = current_element->next;
1933}
1934}
19351936
if ((current_element == NULL) || (current_element->string == NULL)) {
1937return NULL;
1938}
19391940
return current_element;
1941}
19421943
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1944{
1945return get_object_item(object, string, false);
1946}
19471948
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1949{
1950return get_object_item(object, string, true);
1951}
19521953
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1954{
1955return cJSON_GetObjectItem(object, string) ? 1 : 0;
1956}
19571958
/* Utility for array list handling. */
1959static void suffix_object(cJSON *prev, cJSON *item)
1960{
1961prev->next = item;
1962item->prev = prev;
1963}
19641965
/* Utility for handling references. */
1966static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1967{
1968cJSON *reference = NULL;
1969if (item == NULL)
1970{
1971return NULL;
1972}
19731974
reference = cJSON_New_Item(hooks);
1975if (reference == NULL)
1976{
1977return NULL;
1978}
19791980
memcpy(reference, item, sizeof(cJSON));
1981reference->string = NULL;
1982reference->type |= cJSON_IsReference;
1983reference->next = reference->prev = NULL;
1984return reference;
1985}
19861987
static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1988{
1989cJSON *child = NULL;
19901991
if ((item == NULL) || (array == NULL) || (array == item))
1992{
1993return false;
1994}
19951996
child = array->child;
1997/*
1998* To find the last item in array quickly, we use prev in array
1999*/
2000if (child == NULL)
2001{
2002/* list is empty, start new one */
2003array->child = item;
2004item->prev = item;
2005item->next = NULL;
2006}
2007else
2008{
2009/* append to the end */
2010if (child->prev)
2011{
2012suffix_object(child->prev, item);
2013array->child->prev = item;
2014}
2015}
20162017
return true;
2018}
20192020
/* Add item to array/object. */
2021CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2022{
2023return add_item_to_array(array, item);
2024}
20252026
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2027#pragma GCC diagnostic push
2028#endif
2029#ifdef __GNUC__
2030#pragma GCC diagnostic ignored "-Wcast-qual"
2031#endif
2032/* helper function to cast away const */
2033static void* cast_away_const(const void* string)
2034{
2035return (void*)string;
2036}
2037#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2038#pragma GCC diagnostic pop
2039#endif
20402041
2042
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
2043{
2044char *new_key = NULL;
2045int new_type = cJSON_Invalid;
20462047
if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2048{
2049return false;
2050}
20512052
if (constant_key)
2053{
2054new_key = (char*)cast_away_const(string);
2055new_type = item->type | cJSON_StringIsConst;
2056}
2057else
2058{
2059new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2060if (new_key == NULL)
2061{
2062return false;
2063}
20642065
new_type = item->type & ~cJSON_StringIsConst;
2066}
20672068
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2069{
2070hooks->deallocate(item->string);
2071}
20722073
item->string = new_key;
2074item->type = new_type;
20752076
return add_item_to_array(object, item);
2077}
20782079
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2080{
2081return add_item_to_object(object, string, item, &global_hooks, false);
2082}
20832084
/* Add an item to an object with constant string as key */
2085CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2086{
2087return add_item_to_object(object, string, item, &global_hooks, true);
2088}
20892090
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2091{
2092if (array == NULL)
2093{
2094return false;
2095}
20962097
return add_item_to_array(array, create_reference(item, &global_hooks));
2098}
20992100
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2101{
2102if ((object == NULL) || (string == NULL))
2103{
2104return false;
2105}
21062107
return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2108}
21092110
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2111{
2112cJSON *null = cJSON_CreateNull();
2113if (add_item_to_object(object, name, null, &global_hooks, false))
2114{
2115return null;
2116}
21172118
cJSON_Delete(null);
2119return NULL;
2120}
21212122
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2123{
2124cJSON *true_item = cJSON_CreateTrue();
2125if (add_item_to_object(object, name, true_item, &global_hooks, false))
2126{
2127return true_item;
2128}
21292130
cJSON_Delete(true_item);
2131return NULL;
2132}
21332134
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2135{
2136cJSON *false_item = cJSON_CreateFalse();
2137if (add_item_to_object(object, name, false_item, &global_hooks, false))
2138{
2139return false_item;
2140}
21412142
cJSON_Delete(false_item);
2143return NULL;
2144}
21452146
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2147{
2148cJSON *bool_item = cJSON_CreateBool(boolean);
2149if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2150{
2151return bool_item;
2152}
21532154
cJSON_Delete(bool_item);
2155return NULL;
2156}
21572158
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2159{
2160cJSON *number_item = cJSON_CreateNumber(number);
2161if (add_item_to_object(object, name, number_item, &global_hooks, false))
2162{
2163return number_item;
2164}
21652166
cJSON_Delete(number_item);
2167return NULL;
2168}
21692170
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2171{
2172cJSON *string_item = cJSON_CreateString(string);
2173if (add_item_to_object(object, name, string_item, &global_hooks, false))
2174{
2175return string_item;
2176}
21772178
cJSON_Delete(string_item);
2179return NULL;
2180}
21812182
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2183{
2184cJSON *raw_item = cJSON_CreateRaw(raw);
2185if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2186{
2187return raw_item;
2188}
21892190
cJSON_Delete(raw_item);
2191return NULL;
2192}
21932194
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2195{
2196cJSON *object_item = cJSON_CreateObject();
2197if (add_item_to_object(object, name, object_item, &global_hooks, false))
2198{
2199return object_item;
2200}
22012202
cJSON_Delete(object_item);
2203return NULL;
2204}
22052206
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2207{
2208cJSON *array = cJSON_CreateArray();
2209if (add_item_to_object(object, name, array, &global_hooks, false))
2210{
2211return array;
2212}
22132214
cJSON_Delete(array);
2215return NULL;
2216}
22172218
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2219{
2220if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
2221{
2222return NULL;
2223}
22242225
if (item != parent->child)
2226{
2227/* not the first element */
2228item->prev->next = item->next;
2229}
2230if (item->next != NULL)
2231{
2232/* not the last element */
2233item->next->prev = item->prev;
2234}
22352236
if (item == parent->child)
2237{
2238/* first element */
2239parent->child = item->next;
2240}
2241else if (item->next == NULL)
2242{
2243/* last element */
2244parent->child->prev = item->prev;
2245}
22462247
/* make sure the detached item doesn't point anywhere anymore */
2248item->prev = NULL;
2249item->next = NULL;
22502251
return item;
2252}
22532254
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2255{
2256if (which < 0)
2257{
2258return NULL;
2259}
22602261
return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2262}
22632264
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2265{
2266cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2267}
22682269
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2270{
2271cJSON *to_detach = cJSON_GetObjectItem(object, string);
22722273
return cJSON_DetachItemViaPointer(object, to_detach);
2274}
22752276
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2277{
2278cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
22792280
return cJSON_DetachItemViaPointer(object, to_detach);
2281}
22822283
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2284{
2285cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2286}
22872288
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2289{
2290cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2291}
22922293
/* Replace array/object items with new ones. */
2294CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2295{
2296cJSON *after_inserted = NULL;
22972298
if (which < 0 || newitem == NULL)
2299{
2300return false;
2301}
23022303
after_inserted = get_array_item(array, (size_t)which);
2304if (after_inserted == NULL)
2305{
2306return add_item_to_array(array, newitem);
2307}
23082309
if (after_inserted != array->child && after_inserted->prev == NULL) {
2310/* return false if after_inserted is a corrupted array item */
2311return false;
2312}
23132314
newitem->next = after_inserted;
2315newitem->prev = after_inserted->prev;
2316after_inserted->prev = newitem;
2317if (after_inserted == array->child)
2318{
2319array->child = newitem;
2320}
2321else
2322{
2323newitem->prev->next = newitem;
2324}
2325return true;
2326}
23272328
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2329{
2330if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
2331{
2332return false;
2333}
23342335
if (replacement == item)
2336{
2337return true;
2338}
23392340
replacement->next = item->next;
2341replacement->prev = item->prev;
23422343
if (replacement->next != NULL)
2344{
2345replacement->next->prev = replacement;
2346}
2347if (parent->child == item)
2348{
2349if (parent->child->prev == parent->child)
2350{
2351replacement->prev = replacement;
2352}
2353parent->child = replacement;
2354}
2355else
2356{ /*
2357* To find the last item in array quickly, we use prev in array.
2358* We can't modify the last item's next pointer where this item was the parent's child
2359*/
2360if (replacement->prev != NULL)
2361{
2362replacement->prev->next = replacement;
2363}
2364if (replacement->next == NULL)
2365{
2366parent->child->prev = replacement;
2367}
2368}
23692370
item->next = NULL;
2371item->prev = NULL;
2372cJSON_Delete(item);
23732374
return true;
2375}
23762377
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2378{
2379if (which < 0)
2380{
2381return false;
2382}
23832384
return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2385}
23862387
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2388{
2389if ((replacement == NULL) || (string == NULL))
2390{
2391return false;
2392}
23932394
/* replace the name in the replacement */
2395if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2396{
2397cJSON_free(replacement->string);
2398}
2399replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2400if (replacement->string == NULL)
2401{
2402return false;
2403}
24042405
replacement->type &= ~cJSON_StringIsConst;
24062407
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2408}
24092410
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2411{
2412return replace_item_in_object(object, string, newitem, false);
2413}
24142415
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2416{
2417return replace_item_in_object(object, string, newitem, true);
2418}
24192420
/* Create basic types: */
2421CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2422{
2423cJSON *item = cJSON_New_Item(&global_hooks);
2424if(item)
2425{
2426item->type = cJSON_NULL;
2427}
24282429
return item;
2430}
24312432
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2433{
2434cJSON *item = cJSON_New_Item(&global_hooks);
2435if(item)
2436{
2437item->type = cJSON_True;
2438}
24392440
return item;
2441}
24422443
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2444{
2445cJSON *item = cJSON_New_Item(&global_hooks);
2446if(item)
2447{
2448item->type = cJSON_False;
2449}
24502451
return item;
2452}
24532454
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2455{
2456cJSON *item = cJSON_New_Item(&global_hooks);
2457if(item)
2458{
2459item->type = boolean ? cJSON_True : cJSON_False;
2460}
24612462
return item;
2463}
24642465
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2466{
2467cJSON *item = cJSON_New_Item(&global_hooks);
2468if(item)
2469{
2470item->type = cJSON_Number;
2471item->valuedouble = num;
24722473
/* use saturation in case of overflow */
2474if (num >= INT_MAX)
2475{
2476item->valueint = INT_MAX;
2477}
2478else if (num <= (double)INT_MIN)
2479{
2480item->valueint = INT_MIN;
2481}
2482else
2483{
2484item->valueint = (int)num;
2485}
2486}
24872488
return item;
2489}
24902491
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2492{
2493cJSON *item = cJSON_New_Item(&global_hooks);
2494if(item)
2495{
2496item->type = cJSON_String;
2497item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2498if(!item->valuestring)
2499{
2500cJSON_Delete(item);
2501return NULL;
2502}
2503}
25042505
return item;
2506}
25072508
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2509{
2510cJSON *item = cJSON_New_Item(&global_hooks);
2511if (item != NULL)
2512{
2513item->type = cJSON_String | cJSON_IsReference;
2514item->valuestring = (char*)cast_away_const(string);
2515}
25162517
return item;
2518}
25192520
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2521{
2522cJSON *item = cJSON_New_Item(&global_hooks);
2523if (item != NULL) {
2524item->type = cJSON_Object | cJSON_IsReference;
2525item->child = (cJSON*)cast_away_const(child);
2526}
25272528
return item;
2529}
25302531
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2532cJSON *item = cJSON_New_Item(&global_hooks);
2533if (item != NULL) {
2534item->type = cJSON_Array | cJSON_IsReference;
2535item->child = (cJSON*)cast_away_const(child);
2536}
25372538
return item;
2539}
25402541
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2542{
2543cJSON *item = cJSON_New_Item(&global_hooks);
2544if(item)
2545{
2546item->type = cJSON_Raw;
2547item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2548if(!item->valuestring)
2549{
2550cJSON_Delete(item);
2551return NULL;
2552}
2553}
25542555
return item;
2556}
25572558
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2559{
2560cJSON *item = cJSON_New_Item(&global_hooks);
2561if(item)
2562{
2563item->type=cJSON_Array;
2564}
25652566
return item;
2567}
25682569
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2570{
2571cJSON *item = cJSON_New_Item(&global_hooks);
2572if (item)
2573{
2574item->type = cJSON_Object;
2575}
25762577
return item;
2578}
25792580
/* Create Arrays: */
2581CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2582{
2583size_t i = 0;
2584cJSON *n = NULL;
2585cJSON *p = NULL;
2586cJSON *a = NULL;
25872588
if ((count < 0) || (numbers == NULL))
2589{
2590return NULL;
2591}
25922593
a = cJSON_CreateArray();
25942595
for(i = 0; a && (i < (size_t)count); i++)
2596{
2597n = cJSON_CreateNumber(numbers[i]);
2598if (!n)
2599{
2600cJSON_Delete(a);
2601return NULL;
2602}
2603if(!i)
2604{
2605a->child = n;
2606}
2607else
2608{
2609suffix_object(p, n);
2610}
2611p = n;
2612}
26132614
if (a && a->child) {
2615a->child->prev = n;
2616}
26172618
return a;
2619}
26202621
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2622{
2623size_t i = 0;
2624cJSON *n = NULL;
2625cJSON *p = NULL;
2626cJSON *a = NULL;
26272628
if ((count < 0) || (numbers == NULL))
2629{
2630return NULL;
2631}
26322633
a = cJSON_CreateArray();
26342635
for(i = 0; a && (i < (size_t)count); i++)
2636{
2637n = cJSON_CreateNumber((double)numbers[i]);
2638if(!n)
2639{
2640cJSON_Delete(a);
2641return NULL;
2642}
2643if(!i)
2644{
2645a->child = n;
2646}
2647else
2648{
2649suffix_object(p, n);
2650}
2651p = n;
2652}
26532654
if (a && a->child) {
2655a->child->prev = n;
2656}
26572658
return a;
2659}
26602661
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2662{
2663size_t i = 0;
2664cJSON *n = NULL;
2665cJSON *p = NULL;
2666cJSON *a = NULL;
26672668
if ((count < 0) || (numbers == NULL))
2669{
2670return NULL;
2671}
26722673
a = cJSON_CreateArray();
26742675
for(i = 0; a && (i < (size_t)count); i++)
2676{
2677n = cJSON_CreateNumber(numbers[i]);
2678if(!n)
2679{
2680cJSON_Delete(a);
2681return NULL;
2682}
2683if(!i)
2684{
2685a->child = n;
2686}
2687else
2688{
2689suffix_object(p, n);
2690}
2691p = n;
2692}
26932694
if (a && a->child) {
2695a->child->prev = n;
2696}
26972698
return a;
2699}
27002701
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2702{
2703size_t i = 0;
2704cJSON *n = NULL;
2705cJSON *p = NULL;
2706cJSON *a = NULL;
27072708
if ((count < 0) || (strings == NULL))
2709{
2710return NULL;
2711}
27122713
a = cJSON_CreateArray();
27142715
for (i = 0; a && (i < (size_t)count); i++)
2716{
2717n = cJSON_CreateString(strings[i]);
2718if(!n)
2719{
2720cJSON_Delete(a);
2721return NULL;
2722}
2723if(!i)
2724{
2725a->child = n;
2726}
2727else
2728{
2729suffix_object(p,n);
2730}
2731p = n;
2732}
27332734
if (a && a->child) {
2735a->child->prev = n;
2736}
27372738
return a;
2739}
27402741
/* Duplication */
2742cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);
27432744
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2745{
2746return cJSON_Duplicate_rec(item, 0, recurse );
2747}
27482749
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
2750{
2751cJSON *newitem = NULL;
2752cJSON *child = NULL;
2753cJSON *next = NULL;
2754cJSON *newchild = NULL;
27552756
/* Bail on bad ptr */
2757if (!item)
2758{
2759goto fail;
2760}
2761/* Create new item */
2762newitem = cJSON_New_Item(&global_hooks);
2763if (!newitem)
2764{
2765goto fail;
2766}
2767/* Copy over all vars */
2768newitem->type = item->type & (~cJSON_IsReference);
2769newitem->valueint = item->valueint;
2770newitem->valuedouble = item->valuedouble;
2771if (item->valuestring)
2772{
2773newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2774if (!newitem->valuestring)
2775{
2776goto fail;
2777}
2778}
2779if (item->string)
2780{
2781newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2782if (!newitem->string)
2783{
2784goto fail;
2785}
2786}
2787/* If non-recursive, then we're done! */
2788if (!recurse)
2789{
2790return newitem;
2791}
2792/* Walk the ->next chain for the child. */
2793child = item->child;
2794while (child != NULL)
2795{
2796if(depth >= CJSON_CIRCULAR_LIMIT) {
2797goto fail;
2798}
2799newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
2800if (!newchild)
2801{
2802goto fail;
2803}
2804if (next != NULL)
2805{
2806/* If newitem->child already set, then crosswire ->prev and ->next and move on */
2807next->next = newchild;
2808newchild->prev = next;
2809next = newchild;
2810}
2811else
2812{
2813/* Set newitem->child and move to it */
2814newitem->child = newchild;
2815next = newchild;
2816}
2817child = child->next;
2818}
2819if (newitem && newitem->child)
2820{
2821newitem->child->prev = newchild;
2822}
28232824
return newitem;
28252826
fail:
2827if (newitem != NULL)
2828{
2829cJSON_Delete(newitem);
2830}
28312832
return NULL;
2833}
28342835
static void skip_oneline_comment(char **input)
2836{
2837*input += static_strlen("//");
28382839
for (; (*input)[0] != '\0'; ++(*input))
2840{
2841if ((*input)[0] == '\n') {
2842*input += static_strlen("\n");
2843return;
2844}
2845}
2846}
28472848
static void skip_multiline_comment(char **input)
2849{
2850*input += static_strlen("/*");
28512852
for (; (*input)[0] != '\0'; ++(*input))
2853{
2854if (((*input)[0] == '*') && ((*input)[1] == '/'))
2855{
2856*input += static_strlen("*/");
2857return;
2858}
2859}
2860}
28612862
static void minify_string(char **input, char **output) {
2863(*output)[0] = (*input)[0];
2864*input += static_strlen("\"");
2865*output += static_strlen("\"");
28662867
2868
for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2869(*output)[0] = (*input)[0];
28702871
if ((*input)[0] == '\"') {
2872(*output)[0] = '\"';
2873*input += static_strlen("\"");
2874*output += static_strlen("\"");
2875return;
2876} else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2877(*output)[1] = (*input)[1];
2878*input += static_strlen("\"");
2879*output += static_strlen("\"");
2880}
2881}
2882}
28832884
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2885{
2886char *into = json;
28872888
if (json == NULL)
2889{
2890return;
2891}
28922893
while (json[0] != '\0')
2894{
2895switch (json[0])
2896{
2897case ' ':
2898case '\t':
2899case '\r':
2900case '\n':
2901json++;
2902break;
29032904
case '/':
2905if (json[1] == '/')
2906{
2907skip_oneline_comment(&json);
2908}
2909else if (json[1] == '*')
2910{
2911skip_multiline_comment(&json);
2912} else {
2913json++;
2914}
2915break;
29162917
case '\"':
2918minify_string(&json, (char**)&into);
2919break;
29202921
default:
2922into[0] = json[0];
2923json++;
2924into++;
2925}
2926}
29272928
/* and null-terminate. */
2929*into = '\0';
2930}
29312932
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2933{
2934if (item == NULL)
2935{
2936return false;
2937}
29382939
return (item->type & 0xFF) == cJSON_Invalid;
2940}
29412942
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2943{
2944if (item == NULL)
2945{
2946return false;
2947}
29482949
return (item->type & 0xFF) == cJSON_False;
2950}
29512952
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2953{
2954if (item == NULL)
2955{
2956return false;
2957}
29582959
return (item->type & 0xff) == cJSON_True;
2960}
29612962
2963
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2964{
2965if (item == NULL)
2966{
2967return false;
2968}
29692970
return (item->type & (cJSON_True | cJSON_False)) != 0;
2971}
2972CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2973{
2974if (item == NULL)
2975{
2976return false;
2977}
29782979
return (item->type & 0xFF) == cJSON_NULL;
2980}
29812982
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2983{
2984if (item == NULL)
2985{
2986return false;
2987}
29882989
return (item->type & 0xFF) == cJSON_Number;
2990}
29912992
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2993{
2994if (item == NULL)
2995{
2996return false;
2997}
29982999
return (item->type & 0xFF) == cJSON_String;
3000}
30013002
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
3003{
3004if (item == NULL)
3005{
3006return false;
3007}
30083009
return (item->type & 0xFF) == cJSON_Array;
3010}
30113012
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
3013{
3014if (item == NULL)
3015{
3016return false;
3017}
30183019
return (item->type & 0xFF) == cJSON_Object;
3020}
30213022
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
3023{
3024if (item == NULL)
3025{
3026return false;
3027}
30283029
return (item->type & 0xFF) == cJSON_Raw;
3030}
30313032
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
3033{
3034if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
3035{
3036return false;
3037}
30383039
/* check if type is valid */
3040switch (a->type & 0xFF)
3041{
3042case cJSON_False:
3043case cJSON_True:
3044case cJSON_NULL:
3045case cJSON_Number:
3046case cJSON_String:
3047case cJSON_Raw:
3048case cJSON_Array:
3049case cJSON_Object:
3050break;
30513052
default:
3053return false;
3054}
30553056
/* identical objects are equal */
3057if (a == b)
3058{
3059return true;
3060}
30613062
switch (a->type & 0xFF)
3063{
3064/* in these cases and equal type is enough */
3065case cJSON_False:
3066case cJSON_True:
3067case cJSON_NULL:
3068return true;
30693070
case cJSON_Number:
3071if (compare_double(a->valuedouble, b->valuedouble))
3072{
3073return true;
3074}
3075return false;
30763077
case cJSON_String:
3078case cJSON_Raw:
3079if ((a->valuestring == NULL) || (b->valuestring == NULL))
3080{
3081return false;
3082}
3083if (strcmp(a->valuestring, b->valuestring) == 0)
3084{
3085return true;
3086}
30873088
return false;
30893090
case cJSON_Array:
3091{
3092cJSON *a_element = a->child;
3093cJSON *b_element = b->child;
30943095
for (; (a_element != NULL) && (b_element != NULL);)
3096{
3097if (!cJSON_Compare(a_element, b_element, case_sensitive))
3098{
3099return false;
3100}
31013102
a_element = a_element->next;
3103b_element = b_element->next;
3104}
31053106
/* one of the arrays is longer than the other */
3107if (a_element != b_element) {
3108return false;
3109}
31103111
return true;
3112}
31133114
case cJSON_Object:
3115{
3116cJSON *a_element = NULL;
3117cJSON *b_element = NULL;
3118cJSON_ArrayForEach(a_element, a)
3119{
3120/* TODO This has O(n^2) runtime, which is horrible! */
3121b_element = get_object_item(b, a_element->string, case_sensitive);
3122if (b_element == NULL)
3123{
3124return false;
3125}
31263127
if (!cJSON_Compare(a_element, b_element, case_sensitive))
3128{
3129return false;
3130}
3131}
31323133
/* doing this twice, once on a and b to prevent true comparison if a subset of b
3134* TODO: Do this the proper way, this is just a fix for now */
3135cJSON_ArrayForEach(b_element, b)
3136{
3137a_element = get_object_item(a, b_element->string, case_sensitive);
3138if (a_element == NULL)
3139{
3140return false;
3141}
31423143
if (!cJSON_Compare(b_element, a_element, case_sensitive))
3144{
3145return false;
3146}
3147}
31483149
return true;
3150}
31513152
default:
3153return false;
3154}
3155}
31563157
CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3158{
3159return global_hooks.allocate(size);
3160}
31613162
CJSON_PUBLIC(void) cJSON_free(void *object)
3163{
3164global_hooks.deallocate(object);
3165object = NULL;
3166}