webxos commited on
Commit
1d0c1f1
·
verified ·
1 Parent(s): a1c732a

Upload 4 files

Browse files
Files changed (4) hide show
  1. Makefile +22 -0
  2. cJSON.c +3174 -0
  3. cJSON.h +290 -0
  4. shadowclaw.c +653 -0
Makefile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CC = gcc
2
+ CFLAGS = -O2 -Wall -Wextra -std=gnu99
3
+ LDFLAGS = -lcurl -lm
4
+
5
+ TARGET = shadowclaw
6
+ OBJS = shadowclaw.o cJSON.o
7
+
8
+ all: $(TARGET)
9
+
10
+ $(TARGET): $(OBJS)
11
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
12
+
13
+ %.o: %.c
14
+ $(CC) $(CFLAGS) -c $< -o $@
15
+
16
+ clean:
17
+ rm -f $(OBJS) $(TARGET)
18
+
19
+ strip: $(TARGET)
20
+ strip $(TARGET)
21
+
22
+ .PHONY: all clean strip
cJSON.c ADDED
@@ -0,0 +1,3174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+ */
22
+
23
+ /* cJSON */
24
+ /* JSON parser in C. */
25
+
26
+ /* disable warnings about old C89 functions in MSVC */
27
+ #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
+ #define _CRT_SECURE_NO_DEPRECATE
29
+ #endif
30
+
31
+ #ifdef __GNUC__
32
+ #pragma GCC visibility push(default)
33
+ #endif
34
+ #if defined(_MSC_VER)
35
+ #pragma warning (push)
36
+ /* disable warning about single line comments in system headers */
37
+ #pragma warning (disable : 4001)
38
+ #endif
39
+
40
+ #include <string.h>
41
+ #include <stdio.h>
42
+ #include <math.h>
43
+ #include <stdlib.h>
44
+ #include <limits.h>
45
+ #include <ctype.h>
46
+ #include <float.h>
47
+
48
+ #ifdef ENABLE_LOCALES
49
+ #include <locale.h>
50
+ #endif
51
+
52
+ #if defined(_MSC_VER)
53
+ #pragma warning (pop)
54
+ #endif
55
+ #ifdef __GNUC__
56
+ #pragma GCC visibility pop
57
+ #endif
58
+
59
+ #include "cJSON.h"
60
+
61
+ /* define our own boolean type */
62
+ #ifdef true
63
+ #undef true
64
+ #endif
65
+ #define true ((cJSON_bool)1)
66
+
67
+ #ifdef false
68
+ #undef false
69
+ #endif
70
+ #define false ((cJSON_bool)0)
71
+
72
+ /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
73
+ #ifndef isinf
74
+ #define isinf(d) (isnan((d - d)) && !isnan(d))
75
+ #endif
76
+ #ifndef isnan
77
+ #define isnan(d) (d != d)
78
+ #endif
79
+
80
+ #ifndef NAN
81
+ #ifdef _WIN32
82
+ #define NAN sqrt(-1.0)
83
+ #else
84
+ #define NAN 0.0/0.0
85
+ #endif
86
+ #endif
87
+
88
+ typedef struct {
89
+ const unsigned char *json;
90
+ size_t position;
91
+ } error;
92
+ static error global_error = { NULL, 0 };
93
+
94
+ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
95
+ {
96
+ return (const char*) (global_error.json + global_error.position);
97
+ }
98
+
99
+ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
100
+ {
101
+ if (!cJSON_IsString(item))
102
+ {
103
+ return NULL;
104
+ }
105
+
106
+ return item->valuestring;
107
+ }
108
+
109
+ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
110
+ {
111
+ if (!cJSON_IsNumber(item))
112
+ {
113
+ return (double) NAN;
114
+ }
115
+
116
+ return item->valuedouble;
117
+ }
118
+
119
+ /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
120
+ #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
121
+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
122
+ #endif
123
+
124
+ CJSON_PUBLIC(const char*) cJSON_Version(void)
125
+ {
126
+ static char version[15];
127
+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
128
+
129
+ return version;
130
+ }
131
+
132
+ /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
133
+ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
134
+ {
135
+ if ((string1 == NULL) || (string2 == NULL))
136
+ {
137
+ return 1;
138
+ }
139
+
140
+ if (string1 == string2)
141
+ {
142
+ return 0;
143
+ }
144
+
145
+ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
146
+ {
147
+ if (*string1 == '\0')
148
+ {
149
+ return 0;
150
+ }
151
+ }
152
+
153
+ return tolower(*string1) - tolower(*string2);
154
+ }
155
+
156
+ typedef struct internal_hooks
157
+ {
158
+ void *(CJSON_CDECL *allocate)(size_t size);
159
+ void (CJSON_CDECL *deallocate)(void *pointer);
160
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
161
+ } internal_hooks;
162
+
163
+ #if defined(_MSC_VER)
164
+ /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
165
+ static void * CJSON_CDECL internal_malloc(size_t size)
166
+ {
167
+ return malloc(size);
168
+ }
169
+ static void CJSON_CDECL internal_free(void *pointer)
170
+ {
171
+ free(pointer);
172
+ }
173
+ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
174
+ {
175
+ return realloc(pointer, size);
176
+ }
177
+ #else
178
+ #define internal_malloc malloc
179
+ #define internal_free free
180
+ #define internal_realloc realloc
181
+ #endif
182
+
183
+ /* strlen of character literals resolved at compile time */
184
+ #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
185
+
186
+ static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
187
+
188
+ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
189
+ {
190
+ size_t length = 0;
191
+ unsigned char *copy = NULL;
192
+
193
+ if (string == NULL)
194
+ {
195
+ return NULL;
196
+ }
197
+
198
+ length = strlen((const char*)string) + sizeof("");
199
+ copy = (unsigned char*)hooks->allocate(length);
200
+ if (copy == NULL)
201
+ {
202
+ return NULL;
203
+ }
204
+ memcpy(copy, string, length);
205
+
206
+ return copy;
207
+ }
208
+
209
+ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
210
+ {
211
+ if (hooks == NULL)
212
+ {
213
+ /* Reset hooks */
214
+ global_hooks.allocate = malloc;
215
+ global_hooks.deallocate = free;
216
+ global_hooks.reallocate = realloc;
217
+ return;
218
+ }
219
+
220
+ global_hooks.allocate = malloc;
221
+ if (hooks->malloc_fn != NULL)
222
+ {
223
+ global_hooks.allocate = hooks->malloc_fn;
224
+ }
225
+
226
+ global_hooks.deallocate = free;
227
+ if (hooks->free_fn != NULL)
228
+ {
229
+ global_hooks.deallocate = hooks->free_fn;
230
+ }
231
+
232
+ /* use realloc only if both free and malloc are used */
233
+ global_hooks.reallocate = NULL;
234
+ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
235
+ {
236
+ global_hooks.reallocate = realloc;
237
+ }
238
+ }
239
+
240
+ /* Internal constructor. */
241
+ static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
242
+ {
243
+ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
+ if (node)
245
+ {
246
+ memset(node, '\0', sizeof(cJSON));
247
+ }
248
+
249
+ return node;
250
+ }
251
+
252
+ /* Delete a cJSON structure. */
253
+ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
+ {
255
+ cJSON *next = NULL;
256
+ while (item != NULL)
257
+ {
258
+ next = item->next;
259
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
+ {
261
+ cJSON_Delete(item->child);
262
+ }
263
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
+ {
265
+ global_hooks.deallocate(item->valuestring);
266
+ item->valuestring = NULL;
267
+ }
268
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
+ {
270
+ global_hooks.deallocate(item->string);
271
+ item->string = NULL;
272
+ }
273
+ global_hooks.deallocate(item);
274
+ item = next;
275
+ }
276
+ }
277
+
278
+ /* get the decimal point character of the current locale */
279
+ static unsigned char get_decimal_point(void)
280
+ {
281
+ #ifdef ENABLE_LOCALES
282
+ struct lconv *lconv = localeconv();
283
+ return (unsigned char) lconv->decimal_point[0];
284
+ #else
285
+ return '.';
286
+ #endif
287
+ }
288
+
289
+ typedef struct
290
+ {
291
+ const unsigned char *content;
292
+ size_t length;
293
+ size_t offset;
294
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
295
+ internal_hooks hooks;
296
+ } parse_buffer;
297
+
298
+ /* check if the given size is left to read in a given parse buffer (starting with 1) */
299
+ #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
300
+ /* check if the buffer can be accessed at the given index (starting with 0) */
301
+ #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
+ #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
303
+ /* get a pointer to the buffer at the position */
304
+ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
305
+
306
+ /* Parse the input text to generate a number, and populate the result into item. */
307
+ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
308
+ {
309
+ double number = 0;
310
+ unsigned char *after_end = NULL;
311
+ unsigned char number_c_string[64];
312
+ unsigned char decimal_point = get_decimal_point();
313
+ size_t i = 0;
314
+
315
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
316
+ {
317
+ return false;
318
+ }
319
+
320
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
321
+ * of the current locale (for strtod)
322
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
323
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
324
+ {
325
+ switch (buffer_at_offset(input_buffer)[i])
326
+ {
327
+ case '0':
328
+ case '1':
329
+ case '2':
330
+ case '3':
331
+ case '4':
332
+ case '5':
333
+ case '6':
334
+ case '7':
335
+ case '8':
336
+ case '9':
337
+ case '+':
338
+ case '-':
339
+ case 'e':
340
+ case 'E':
341
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
342
+ break;
343
+
344
+ case '.':
345
+ number_c_string[i] = decimal_point;
346
+ break;
347
+
348
+ default:
349
+ goto loop_end;
350
+ }
351
+ }
352
+ loop_end:
353
+ number_c_string[i] = '\0';
354
+
355
+ number = strtod((const char*)number_c_string, (char**)&after_end);
356
+ if (number_c_string == after_end)
357
+ {
358
+ return false; /* parse_error */
359
+ }
360
+
361
+ item->valuedouble = number;
362
+
363
+ /* use saturation in case of overflow */
364
+ if (number >= INT_MAX)
365
+ {
366
+ item->valueint = INT_MAX;
367
+ }
368
+ else if (number <= (double)INT_MIN)
369
+ {
370
+ item->valueint = INT_MIN;
371
+ }
372
+ else
373
+ {
374
+ item->valueint = (int)number;
375
+ }
376
+
377
+ item->type = cJSON_Number;
378
+
379
+ input_buffer->offset += (size_t)(after_end - number_c_string);
380
+ return true;
381
+ }
382
+
383
+ /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
384
+ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
385
+ {
386
+ if (number >= INT_MAX)
387
+ {
388
+ object->valueint = INT_MAX;
389
+ }
390
+ else if (number <= (double)INT_MIN)
391
+ {
392
+ object->valueint = INT_MIN;
393
+ }
394
+ else
395
+ {
396
+ object->valueint = (int)number;
397
+ }
398
+
399
+ return object->valuedouble = number;
400
+ }
401
+
402
+ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
403
+ {
404
+ char *copy = NULL;
405
+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
406
+ if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
407
+ {
408
+ return NULL;
409
+ }
410
+ /* return NULL if the object is corrupted */
411
+ if (object->valuestring == NULL)
412
+ {
413
+ return NULL;
414
+ }
415
+ if (strlen(valuestring) <= strlen(object->valuestring))
416
+ {
417
+ strcpy(object->valuestring, valuestring);
418
+ return object->valuestring;
419
+ }
420
+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
421
+ if (copy == NULL)
422
+ {
423
+ return NULL;
424
+ }
425
+ if (object->valuestring != NULL)
426
+ {
427
+ cJSON_free(object->valuestring);
428
+ }
429
+ object->valuestring = copy;
430
+
431
+ return copy;
432
+ }
433
+
434
+ typedef struct
435
+ {
436
+ unsigned char *buffer;
437
+ size_t length;
438
+ size_t offset;
439
+ size_t depth; /* current nesting depth (for formatted printing) */
440
+ cJSON_bool noalloc;
441
+ cJSON_bool format; /* is this print a formatted print */
442
+ internal_hooks hooks;
443
+ } printbuffer;
444
+
445
+ /* realloc printbuffer if necessary to have at least "needed" bytes more */
446
+ static unsigned char* ensure(printbuffer * const p, size_t needed)
447
+ {
448
+ unsigned char *newbuffer = NULL;
449
+ size_t newsize = 0;
450
+
451
+ if ((p == NULL) || (p->buffer == NULL))
452
+ {
453
+ return NULL;
454
+ }
455
+
456
+ if ((p->length > 0) && (p->offset >= p->length))
457
+ {
458
+ /* make sure that offset is valid */
459
+ return NULL;
460
+ }
461
+
462
+ if (needed > INT_MAX)
463
+ {
464
+ /* sizes bigger than INT_MAX are currently not supported */
465
+ return NULL;
466
+ }
467
+
468
+ needed += p->offset + 1;
469
+ if (needed <= p->length)
470
+ {
471
+ return p->buffer + p->offset;
472
+ }
473
+
474
+ if (p->noalloc) {
475
+ return NULL;
476
+ }
477
+
478
+ /* calculate new buffer size */
479
+ if (needed > (INT_MAX / 2))
480
+ {
481
+ /* overflow of int, use INT_MAX if possible */
482
+ if (needed <= INT_MAX)
483
+ {
484
+ newsize = INT_MAX;
485
+ }
486
+ else
487
+ {
488
+ return NULL;
489
+ }
490
+ }
491
+ else
492
+ {
493
+ newsize = needed * 2;
494
+ }
495
+
496
+ if (p->hooks.reallocate != NULL)
497
+ {
498
+ /* reallocate with realloc if available */
499
+ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
500
+ if (newbuffer == NULL)
501
+ {
502
+ p->hooks.deallocate(p->buffer);
503
+ p->length = 0;
504
+ p->buffer = NULL;
505
+
506
+ return NULL;
507
+ }
508
+ }
509
+ else
510
+ {
511
+ /* otherwise reallocate manually */
512
+ newbuffer = (unsigned char*)p->hooks.allocate(newsize);
513
+ if (!newbuffer)
514
+ {
515
+ p->hooks.deallocate(p->buffer);
516
+ p->length = 0;
517
+ p->buffer = NULL;
518
+
519
+ return NULL;
520
+ }
521
+
522
+ memcpy(newbuffer, p->buffer, p->offset + 1);
523
+ p->hooks.deallocate(p->buffer);
524
+ }
525
+ p->length = newsize;
526
+ p->buffer = newbuffer;
527
+
528
+ return newbuffer + p->offset;
529
+ }
530
+
531
+ /* calculate the new length of the string in a printbuffer and update the offset */
532
+ static void update_offset(printbuffer * const p)
533
+ {
534
+ const unsigned char *buffer = NULL;
535
+ if ((p == NULL) || (p->buffer == NULL))
536
+ {
537
+ return;
538
+ }
539
+ buffer = p->buffer + p->offset;
540
+
541
+ p->offset += strlen((const char*)buffer);
542
+ }
543
+
544
+ /* securely comparison of floating-point variables */
545
+ static cJSON_bool compare_double(double a, double b)
546
+ {
547
+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
548
+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
549
+ }
550
+
551
+ /* Render the number nicely from the given item into a string. */
552
+ static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
553
+ {
554
+ unsigned char *output_pointer = NULL;
555
+ double d = item->valuedouble;
556
+ int length = 0;
557
+ size_t i = 0;
558
+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
559
+ unsigned char decimal_point = get_decimal_point();
560
+ double test = 0.0;
561
+
562
+ if (output_buffer == NULL)
563
+ {
564
+ return false;
565
+ }
566
+
567
+ /* This checks for NaN and Infinity */
568
+ if (isnan(d) || isinf(d))
569
+ {
570
+ length = sprintf((char*)number_buffer, "null");
571
+ }
572
+ else if (d == (double)item->valueint)
573
+ {
574
+ length = sprintf((char*)number_buffer, "%d", item->valueint);
575
+ }
576
+ else
577
+ {
578
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
579
+ length = sprintf((char*)number_buffer, "%1.15g", d);
580
+
581
+ /* Check whether the original double can be recovered */
582
+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
583
+ {
584
+ /* If not, print with 17 decimal places of precision */
585
+ length = sprintf((char*)number_buffer, "%1.17g", d);
586
+ }
587
+ }
588
+
589
+ /* sprintf failed or buffer overrun occurred */
590
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
591
+ {
592
+ return false;
593
+ }
594
+
595
+ /* reserve appropriate space in the output */
596
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
597
+ if (output_pointer == NULL)
598
+ {
599
+ return false;
600
+ }
601
+
602
+ /* copy the printed number to the output and replace locale
603
+ * dependent decimal point with '.' */
604
+ for (i = 0; i < ((size_t)length); i++)
605
+ {
606
+ if (number_buffer[i] == decimal_point)
607
+ {
608
+ output_pointer[i] = '.';
609
+ continue;
610
+ }
611
+
612
+ output_pointer[i] = number_buffer[i];
613
+ }
614
+ output_pointer[i] = '\0';
615
+
616
+ output_buffer->offset += (size_t)length;
617
+
618
+ return true;
619
+ }
620
+
621
+ /* parse 4 digit hexadecimal number */
622
+ static unsigned parse_hex4(const unsigned char * const input)
623
+ {
624
+ unsigned int h = 0;
625
+ size_t i = 0;
626
+
627
+ for (i = 0; i < 4; i++)
628
+ {
629
+ /* parse digit */
630
+ if ((input[i] >= '0') && (input[i] <= '9'))
631
+ {
632
+ h += (unsigned int) input[i] - '0';
633
+ }
634
+ else if ((input[i] >= 'A') && (input[i] <= 'F'))
635
+ {
636
+ h += (unsigned int) 10 + input[i] - 'A';
637
+ }
638
+ else if ((input[i] >= 'a') && (input[i] <= 'f'))
639
+ {
640
+ h += (unsigned int) 10 + input[i] - 'a';
641
+ }
642
+ else /* invalid */
643
+ {
644
+ return 0;
645
+ }
646
+
647
+ if (i < 3)
648
+ {
649
+ /* shift left to make place for the next nibble */
650
+ h = h << 4;
651
+ }
652
+ }
653
+
654
+ return h;
655
+ }
656
+
657
+ /* converts a UTF-16 literal to UTF-8
658
+ * A literal can be one or two sequences of the form \uXXXX */
659
+ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
660
+ {
661
+ long unsigned int codepoint = 0;
662
+ unsigned int first_code = 0;
663
+ const unsigned char *first_sequence = input_pointer;
664
+ unsigned char utf8_length = 0;
665
+ unsigned char utf8_position = 0;
666
+ unsigned char sequence_length = 0;
667
+ unsigned char first_byte_mark = 0;
668
+
669
+ if ((input_end - first_sequence) < 6)
670
+ {
671
+ /* input ends unexpectedly */
672
+ goto fail;
673
+ }
674
+
675
+ /* get the first utf16 sequence */
676
+ first_code = parse_hex4(first_sequence + 2);
677
+
678
+ /* check that the code is valid */
679
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
680
+ {
681
+ goto fail;
682
+ }
683
+
684
+ /* UTF16 surrogate pair */
685
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
686
+ {
687
+ const unsigned char *second_sequence = first_sequence + 6;
688
+ unsigned int second_code = 0;
689
+ sequence_length = 12; /* \uXXXX\uXXXX */
690
+
691
+ if ((input_end - second_sequence) < 6)
692
+ {
693
+ /* input ends unexpectedly */
694
+ goto fail;
695
+ }
696
+
697
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
698
+ {
699
+ /* missing second half of the surrogate pair */
700
+ goto fail;
701
+ }
702
+
703
+ /* get the second utf16 sequence */
704
+ second_code = parse_hex4(second_sequence + 2);
705
+ /* check that the code is valid */
706
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF))
707
+ {
708
+ /* invalid second half of the surrogate pair */
709
+ goto fail;
710
+ }
711
+
712
+
713
+ /* calculate the unicode codepoint from the surrogate pair */
714
+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
715
+ }
716
+ else
717
+ {
718
+ sequence_length = 6; /* \uXXXX */
719
+ codepoint = first_code;
720
+ }
721
+
722
+ /* encode as UTF-8
723
+ * takes at maximum 4 bytes to encode:
724
+ * 0 - 0x7F: 0xxxxxxx
725
+ * 0x80 - 0x7FF: 110xxxxx 10xxxxxx
726
+ * 0x800 - 0xFFFF: 1110xxxx 10xxxxxx 10xxxxxx
727
+ * 0x10000 - 0x10FFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
728
+
729
+ if (codepoint < 0x80)
730
+ {
731
+ /* one byte symbol */
732
+ utf8_length = 1;
733
+ }
734
+ else if (codepoint < 0x800)
735
+ {
736
+ /* two byte symbol */
737
+ utf8_length = 2;
738
+ }
739
+ else if (codepoint < 0x10000)
740
+ {
741
+ /* three byte symbol */
742
+ utf8_length = 3;
743
+ }
744
+ else if (codepoint <= 0x10FFFF)
745
+ {
746
+ /* four byte symbol */
747
+ utf8_length = 4;
748
+ }
749
+ else
750
+ {
751
+ /* invalid unicode codepoint */
752
+ goto fail;
753
+ }
754
+
755
+ /* encode as utf8 */
756
+ switch (utf8_length)
757
+ {
758
+ case 1:
759
+ /* first byte */
760
+ (*output_pointer)[0] = (unsigned char)(codepoint);
761
+ break;
762
+ case 2:
763
+ first_byte_mark = 0xC0; /* 11000000 */
764
+ (*output_pointer)[0] = (unsigned char)(codepoint >> 6) | first_byte_mark;
765
+ (*output_pointer)[1] = (unsigned char)(codepoint & 0x3F) | 0x80;
766
+ break;
767
+ case 3:
768
+ first_byte_mark = 0xE0; /* 11100000 */
769
+ (*output_pointer)[0] = (unsigned char)(codepoint >> 12) | first_byte_mark;
770
+ (*output_pointer)[1] = (unsigned char)((codepoint >> 6) & 0x3F) | 0x80;
771
+ (*output_pointer)[2] = (unsigned char)(codepoint & 0x3F) | 0x80;
772
+ break;
773
+ case 4:
774
+ first_byte_mark = 0xF0; /* 11110000 */
775
+ (*output_pointer)[0] = (unsigned char)(codepoint >> 18) | first_byte_mark;
776
+ (*output_pointer)[1] = (unsigned char)((codepoint >> 12) & 0x3F) | 0x80;
777
+ (*output_pointer)[2] = (unsigned char)((codepoint >> 6) & 0x3F) | 0x80;
778
+ (*output_pointer)[3] = (unsigned char)(codepoint & 0x3F) | 0x80;
779
+ break;
780
+ default:
781
+ /* Should not execute */
782
+ goto fail;
783
+ }
784
+
785
+ utf8_position = utf8_length;
786
+ /* skip the \u characters */
787
+ sequence_length = (sequence_length > 0) ? sequence_length : 0;
788
+
789
+ *output_pointer += utf8_position;
790
+ return sequence_length;
791
+
792
+ fail:
793
+ return 0;
794
+ }
795
+
796
+ /* Parse the input text into an unescaped cinput, and populate item. */
797
+ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
798
+ {
799
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
800
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
801
+ unsigned char *output_pointer = NULL;
802
+ unsigned char *output = NULL;
803
+
804
+ /* not a string */
805
+ if (buffer_at_offset(input_buffer)[0] != '\"')
806
+ {
807
+ goto fail;
808
+ }
809
+
810
+ {
811
+ /* calculate approximate size of the output (overestimate) */
812
+ size_t allocation_length = 0;
813
+ size_t skipped_bytes = 0;
814
+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
815
+ {
816
+ /* Is escape sequence */
817
+ if (input_end[0] == '\\')
818
+ {
819
+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
820
+ {
821
+ /* prevent buffer overflow when last input character is a backslash */
822
+ goto fail;
823
+ }
824
+ skipped_bytes++;
825
+ input_end++;
826
+ }
827
+ input_end++;
828
+ }
829
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
830
+ {
831
+ goto fail; /* string ended unexpectedly */
832
+ }
833
+
834
+ /* This is at most how much we need for the output */
835
+ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
836
+ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
837
+ if (output == NULL)
838
+ {
839
+ goto fail; /* allocation failure */
840
+ }
841
+ }
842
+
843
+ output_pointer = output;
844
+ /* loop through the string literal */
845
+ while (input_pointer < input_end)
846
+ {
847
+ if (*input_pointer != '\\')
848
+ {
849
+ *output_pointer++ = *input_pointer++;
850
+ }
851
+ /* escape sequence */
852
+ else
853
+ {
854
+ unsigned char sequence_length = 2;
855
+ if ((input_end - input_pointer) < 1)
856
+ {
857
+ goto fail;
858
+ }
859
+
860
+ switch (input_pointer[1])
861
+ {
862
+ case 'b':
863
+ *output_pointer++ = '\b';
864
+ break;
865
+ case 'f':
866
+ *output_pointer++ = '\f';
867
+ break;
868
+ case 'n':
869
+ *output_pointer++ = '\n';
870
+ break;
871
+ case 'r':
872
+ *output_pointer++ = '\r';
873
+ break;
874
+ case 't':
875
+ *output_pointer++ = '\t';
876
+ break;
877
+ case '\"':
878
+ case '\\':
879
+ case '/':
880
+ *output_pointer++ = input_pointer[1];
881
+ break;
882
+
883
+ /* UTF-16 literal */
884
+ case 'u':
885
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
886
+ if (sequence_length == 0)
887
+ {
888
+ /* failed to convert UTF-16-literal to UTF-8 */
889
+ goto fail;
890
+ }
891
+ break;
892
+
893
+ default:
894
+ goto fail;
895
+ }
896
+ input_pointer += sequence_length;
897
+ }
898
+ }
899
+
900
+ /* zero terminate the output */
901
+ *output_pointer = '\0';
902
+
903
+ item->type = cJSON_String;
904
+ item->valuestring = (char*)output;
905
+
906
+ input_buffer->offset = (size_t) (input_end - input_buffer->content);
907
+ input_buffer->offset++;
908
+
909
+ return true;
910
+
911
+ fail:
912
+ if (output != NULL)
913
+ {
914
+ input_buffer->hooks.deallocate(output);
915
+ output = NULL;
916
+ }
917
+
918
+ if (input_pointer != NULL)
919
+ {
920
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
921
+ }
922
+
923
+ return false;
924
+ }
925
+
926
+ /* Render the cstring provided to an escaped version that can be printed. */
927
+ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
928
+ {
929
+ const unsigned char *input_pointer = NULL;
930
+ unsigned char *output = NULL;
931
+ unsigned char *output_pointer = NULL;
932
+ size_t output_length = 0;
933
+ /* numbers of additional characters needed for escaping */
934
+ size_t escape_characters = 0;
935
+
936
+ if (output_buffer == NULL)
937
+ {
938
+ return false;
939
+ }
940
+
941
+ /* empty string */
942
+ if (input == NULL)
943
+ {
944
+ output = ensure(output_buffer, sizeof("\"\""));
945
+ if (output == NULL)
946
+ {
947
+ return false;
948
+ }
949
+ strcpy((char*)output, "\"\"");
950
+
951
+ output_buffer->offset += 2;
952
+
953
+ return true;
954
+ }
955
+
956
+ /* calculate "escape" characters and final string length */
957
+ for (input_pointer = input; *input_pointer; input_pointer++)
958
+ {
959
+ switch (*input_pointer)
960
+ {
961
+ case '\"':
962
+ case '\\':
963
+ case '\b':
964
+ case '\f':
965
+ case '\n':
966
+ case '\r':
967
+ case '\t':
968
+ /* one character escape needed */
969
+ escape_characters++;
970
+ break;
971
+ default:
972
+ if (*input_pointer < 32)
973
+ {
974
+ /* UTF-16 escape sequence \uXXXX should be printed */
975
+ escape_characters += 5;
976
+ }
977
+ break;
978
+ }
979
+ }
980
+ output_length = (size_t)(input_pointer - input) + escape_characters;
981
+
982
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
983
+ if (output == NULL)
984
+ {
985
+ return false;
986
+ }
987
+
988
+ /* no characters have to be escaped */
989
+ if (escape_characters == 0)
990
+ {
991
+ output[0] = '\"';
992
+ memcpy(output + 1, input, output_length);
993
+ output[output_length + 1] = '\"';
994
+ output[output_length + 2] = '\0';
995
+
996
+ output_buffer->offset += output_length + 2;
997
+
998
+ return true;
999
+ }
1000
+
1001
+ output[0] = '\"';
1002
+ output_pointer = output + 1;
1003
+ /* copy the string */
1004
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1005
+ {
1006
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1007
+ {
1008
+ /* normal character, copy */
1009
+ *output_pointer = *input_pointer;
1010
+ }
1011
+ else
1012
+ {
1013
+ /* character needs to be escaped */
1014
+ *output_pointer++ = '\\';
1015
+ switch (*input_pointer)
1016
+ {
1017
+ case '\\':
1018
+ *output_pointer = '\\';
1019
+ break;
1020
+ case '\"':
1021
+ *output_pointer = '\"';
1022
+ break;
1023
+ case '\b':
1024
+ *output_pointer = 'b';
1025
+ break;
1026
+ case '\f':
1027
+ *output_pointer = 'f';
1028
+ break;
1029
+ case '\n':
1030
+ *output_pointer = 'n';
1031
+ break;
1032
+ case '\r':
1033
+ *output_pointer = 'r';
1034
+ break;
1035
+ case '\t':
1036
+ *output_pointer = 't';
1037
+ break;
1038
+ default:
1039
+ /* escape and print as unicode codepoint */
1040
+ sprintf((char*)output_pointer, "u%04x", *input_pointer);
1041
+ output_pointer += 4;
1042
+ break;
1043
+ }
1044
+ }
1045
+ }
1046
+ output[output_length + 1] = '\"';
1047
+ output[output_length + 2] = '\0';
1048
+
1049
+ output_buffer->offset += output_length + 2;
1050
+
1051
+ return true;
1052
+ }
1053
+
1054
+ /* Invoke print_string_ptr (which is useful) on an item. */
1055
+ static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1056
+ {
1057
+ return print_string_ptr((unsigned char*)item->valuestring, p);
1058
+ }
1059
+
1060
+ /* Predeclare these prototypes. */
1061
+ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1062
+ static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1063
+ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1064
+ static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1065
+ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1066
+ static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1067
+
1068
+ /* Utility to jump whitespace and cr/lf */
1069
+ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1070
+ {
1071
+ if ((buffer == NULL) || (buffer->content == NULL))
1072
+ {
1073
+ return NULL;
1074
+ }
1075
+
1076
+ if (cannot_access_at_index(buffer, 0))
1077
+ {
1078
+ return buffer;
1079
+ }
1080
+
1081
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1082
+ {
1083
+ buffer->offset++;
1084
+ }
1085
+
1086
+ if (buffer->offset == buffer->length)
1087
+ {
1088
+ buffer->offset--;
1089
+ }
1090
+
1091
+ return buffer;
1092
+ }
1093
+
1094
+ /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1095
+ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1096
+ {
1097
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1098
+ {
1099
+ return NULL;
1100
+ }
1101
+
1102
+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1103
+ {
1104
+ buffer->offset += 3;
1105
+ }
1106
+
1107
+ return buffer;
1108
+ }
1109
+
1110
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1111
+ {
1112
+ size_t buffer_length;
1113
+
1114
+ if (NULL == value)
1115
+ {
1116
+ return NULL;
1117
+ }
1118
+
1119
+ /* Adding null character detection due to parse_parse_string and the way cJSON works */
1120
+ buffer_length = strlen(value) + sizeof("");
1121
+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1122
+ }
1123
+
1124
+ /* Parse an object - create a new root, and populate. */
1125
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1126
+ {
1127
+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1128
+ cJSON *item = NULL;
1129
+
1130
+ /* reset error position */
1131
+ global_error.json = NULL;
1132
+ global_error.position = 0;
1133
+
1134
+ if (value == NULL || 0 == buffer_length)
1135
+ {
1136
+ goto fail;
1137
+ }
1138
+
1139
+ buffer.content = (const unsigned char*)value;
1140
+ buffer.length = buffer_length;
1141
+ buffer.offset = 0;
1142
+ buffer.hooks = global_hooks;
1143
+
1144
+ item = cJSON_New_Item(&global_hooks);
1145
+ if (item == NULL) /* memory fail */
1146
+ {
1147
+ goto fail;
1148
+ }
1149
+
1150
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1151
+ {
1152
+ /* parse failure. ep is set. */
1153
+ goto fail;
1154
+ }
1155
+
1156
+ /* if we require null-terminated JSON without appended garbage, skip then and check for a null terminator */
1157
+ if (require_null_terminated)
1158
+ {
1159
+ buffer_skip_whitespace(&buffer);
1160
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1161
+ {
1162
+ goto fail;
1163
+ }
1164
+ }
1165
+ if (return_parse_end)
1166
+ {
1167
+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
1168
+ }
1169
+
1170
+ return item;
1171
+
1172
+ fail:
1173
+ if (item != NULL)
1174
+ {
1175
+ cJSON_Delete(item);
1176
+ }
1177
+
1178
+ if (value != NULL)
1179
+ {
1180
+ error local_error;
1181
+ local_error.json = (const unsigned char*)value;
1182
+ local_error.position = 0;
1183
+
1184
+ if (buffer.offset < buffer.length)
1185
+ {
1186
+ local_error.position = buffer.offset;
1187
+ }
1188
+ else if (buffer.length > 0)
1189
+ {
1190
+ local_error.position = buffer.length - 1;
1191
+ }
1192
+
1193
+ if (return_parse_end != NULL)
1194
+ {
1195
+ *return_parse_end = (const char*)local_error.json + local_error.position;
1196
+ }
1197
+
1198
+ global_error = local_error;
1199
+ }
1200
+
1201
+ return NULL;
1202
+ }
1203
+
1204
+ /* Default options for cJSON_Parse */
1205
+ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1206
+ {
1207
+ return cJSON_ParseWithOpts(value, 0, 0);
1208
+ }
1209
+
1210
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1211
+ {
1212
+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1213
+ }
1214
+
1215
+ #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1216
+
1217
+ static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1218
+ {
1219
+ static const size_t default_buffer_size = 256;
1220
+ printbuffer buffer[1];
1221
+ unsigned char *printed = NULL;
1222
+
1223
+ memset(buffer, 0, sizeof(buffer));
1224
+
1225
+ /* create buffer */
1226
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1227
+ buffer->length = default_buffer_size;
1228
+ buffer->format = format;
1229
+ buffer->hooks = *hooks;
1230
+ if (buffer->buffer == NULL)
1231
+ {
1232
+ goto fail;
1233
+ }
1234
+
1235
+ /* print the value */
1236
+ if (!print_value(item, buffer))
1237
+ {
1238
+ goto fail;
1239
+ }
1240
+ update_offset(buffer);
1241
+
1242
+ /* check if reallocate is available */
1243
+ if (hooks->reallocate != NULL)
1244
+ {
1245
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1246
+ if (printed == NULL) {
1247
+ goto fail;
1248
+ }
1249
+ buffer->buffer = NULL;
1250
+ }
1251
+ else /* otherwise copy the JSON over to a new buffer */
1252
+ {
1253
+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1254
+ if (printed == NULL)
1255
+ {
1256
+ goto fail;
1257
+ }
1258
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1259
+ printed[buffer->offset] = '\0'; /* just to be sure */
1260
+
1261
+ /* free the buffer */
1262
+ hooks->deallocate(buffer->buffer);
1263
+ buffer->buffer = NULL;
1264
+ }
1265
+
1266
+ return printed;
1267
+
1268
+ fail:
1269
+ if (buffer->buffer != NULL)
1270
+ {
1271
+ hooks->deallocate(buffer->buffer);
1272
+ buffer->buffer = NULL;
1273
+ }
1274
+
1275
+ if (printed != NULL)
1276
+ {
1277
+ hooks->deallocate(printed);
1278
+ printed = NULL;
1279
+ }
1280
+
1281
+ return NULL;
1282
+ }
1283
+
1284
+ /* Render a cJSON item/entity/structure to text. */
1285
+ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1286
+ {
1287
+ return (char*)print(item, true, &global_hooks);
1288
+ }
1289
+
1290
+ CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1291
+ {
1292
+ return (char*)print(item, false, &global_hooks);
1293
+ }
1294
+
1295
+ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1296
+ {
1297
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1298
+
1299
+ if (prebuffer < 0)
1300
+ {
1301
+ return NULL;
1302
+ }
1303
+
1304
+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1305
+ if (!p.buffer)
1306
+ {
1307
+ return NULL;
1308
+ }
1309
+
1310
+ p.length = (size_t)prebuffer;
1311
+ p.offset = 0;
1312
+ p.noalloc = false;
1313
+ p.format = fmt;
1314
+ p.hooks = global_hooks;
1315
+
1316
+ if (!print_value(item, &p))
1317
+ {
1318
+ global_hooks.deallocate(p.buffer);
1319
+ p.buffer = NULL;
1320
+ return NULL;
1321
+ }
1322
+
1323
+ update_offset(&p);
1324
+
1325
+ return (char*)p.buffer;
1326
+ }
1327
+
1328
+ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1329
+ {
1330
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1331
+
1332
+ if ((length < 0) || (buffer == NULL))
1333
+ {
1334
+ return false;
1335
+ }
1336
+
1337
+ p.buffer = (unsigned char*)buffer;
1338
+ p.length = (size_t)length;
1339
+ p.offset = 0;
1340
+ p.noalloc = true;
1341
+ p.format = format;
1342
+ p.hooks = global_hooks;
1343
+
1344
+ return print_value(item, &p);
1345
+ }
1346
+
1347
+ /* Parser core - when encountering text, process appropriately. */
1348
+ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1349
+ {
1350
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
1351
+ {
1352
+ return false; /* no input */
1353
+ }
1354
+
1355
+ /* parse the different types of values */
1356
+ /* null */
1357
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1358
+ {
1359
+ item->type = cJSON_NULL;
1360
+ input_buffer->offset += 4;
1361
+ return true;
1362
+ }
1363
+ /* false */
1364
+ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1365
+ {
1366
+ item->type = cJSON_False;
1367
+ input_buffer->offset += 5;
1368
+ return true;
1369
+ }
1370
+ /* true */
1371
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1372
+ {
1373
+ item->type = cJSON_True;
1374
+ item->valueint = 1;
1375
+ input_buffer->offset += 4;
1376
+ return true;
1377
+ }
1378
+ /* string */
1379
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1380
+ {
1381
+ return parse_string(item, input_buffer);
1382
+ }
1383
+ /* number */
1384
+ if (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'))))
1385
+ {
1386
+ return parse_number(item, input_buffer);
1387
+ }
1388
+ /* array */
1389
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1390
+ {
1391
+ return parse_array(item, input_buffer);
1392
+ }
1393
+ /* object */
1394
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1395
+ {
1396
+ return parse_object(item, input_buffer);
1397
+ }
1398
+
1399
+ return false;
1400
+ }
1401
+
1402
+ /* Render a value to text. */
1403
+ static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1404
+ {
1405
+ unsigned char *output = NULL;
1406
+
1407
+ if ((item == NULL) || (output_buffer == NULL))
1408
+ {
1409
+ return false;
1410
+ }
1411
+
1412
+ switch ((item->type) & 0xFF)
1413
+ {
1414
+ case cJSON_NULL:
1415
+ output = ensure(output_buffer, 5);
1416
+ if (output == NULL)
1417
+ {
1418
+ return false;
1419
+ }
1420
+ strcpy((char*)output, "null");
1421
+ output_buffer->offset += 4;
1422
+ return true;
1423
+
1424
+ case cJSON_False:
1425
+ output = ensure(output_buffer, 6);
1426
+ if (output == NULL)
1427
+ {
1428
+ return false;
1429
+ }
1430
+ strcpy((char*)output, "false");
1431
+ output_buffer->offset += 5;
1432
+ return true;
1433
+
1434
+ case cJSON_True:
1435
+ output = ensure(output_buffer, 5);
1436
+ if (output == NULL)
1437
+ {
1438
+ return false;
1439
+ }
1440
+ strcpy((char*)output, "true");
1441
+ output_buffer->offset += 4;
1442
+ return true;
1443
+
1444
+ case cJSON_Number:
1445
+ return print_number(item, output_buffer);
1446
+
1447
+ case cJSON_Raw:
1448
+ {
1449
+ size_t raw_length = 0;
1450
+ if (item->valuestring == NULL)
1451
+ {
1452
+ return false;
1453
+ }
1454
+
1455
+ raw_length = strlen(item->valuestring) + sizeof("");
1456
+ output = ensure(output_buffer, raw_length);
1457
+ if (output == NULL)
1458
+ {
1459
+ return false;
1460
+ }
1461
+ memcpy(output, item->valuestring, raw_length);
1462
+ output_buffer->offset += raw_length - 1;
1463
+ return true;
1464
+ }
1465
+
1466
+ case cJSON_String:
1467
+ return print_string(item, output_buffer);
1468
+
1469
+ case cJSON_Array:
1470
+ return print_array(item, output_buffer);
1471
+
1472
+ case cJSON_Object:
1473
+ return print_object(item, output_buffer);
1474
+
1475
+ default:
1476
+ return false;
1477
+ }
1478
+ }
1479
+
1480
+ /* Build an array from input text. */
1481
+ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1482
+ {
1483
+ cJSON *head = NULL; /* head of the linked list */
1484
+ cJSON *current_item = NULL;
1485
+
1486
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1487
+ {
1488
+ return false; /* to deeply nested */
1489
+ }
1490
+ input_buffer->depth++;
1491
+
1492
+ if (buffer_at_offset(input_buffer)[0] != '[')
1493
+ {
1494
+ /* not an array */
1495
+ goto fail;
1496
+ }
1497
+
1498
+ input_buffer->offset++;
1499
+ buffer_skip_whitespace(input_buffer);
1500
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1501
+ {
1502
+ /* empty array */
1503
+ goto success;
1504
+ }
1505
+
1506
+ /* check if we skipped to the end of the buffer */
1507
+ if (cannot_access_at_index(input_buffer, 0))
1508
+ {
1509
+ input_buffer->offset--;
1510
+ goto fail;
1511
+ }
1512
+
1513
+ /* step back to character in front of the first element */
1514
+ input_buffer->offset--;
1515
+ /* loop through the comma separated array elements */
1516
+ do
1517
+ {
1518
+ /* allocate next item */
1519
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1520
+ if (new_item == NULL)
1521
+ {
1522
+ goto fail; /* allocation failure */
1523
+ }
1524
+
1525
+ /* attach next item to list */
1526
+ if (head == NULL)
1527
+ {
1528
+ /* start the linked list */
1529
+ current_item = head = new_item;
1530
+ }
1531
+ else
1532
+ {
1533
+ /* add to the end and advance */
1534
+ current_item->next = new_item;
1535
+ new_item->prev = current_item;
1536
+ current_item = new_item;
1537
+ }
1538
+
1539
+ /* parse next value */
1540
+ input_buffer->offset++;
1541
+ buffer_skip_whitespace(input_buffer);
1542
+ if (!parse_value(current_item, input_buffer))
1543
+ {
1544
+ goto fail; /* failed to parse value */
1545
+ }
1546
+ buffer_skip_whitespace(input_buffer);
1547
+ }
1548
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1549
+
1550
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1551
+ {
1552
+ goto fail; /* expected end of array */
1553
+ }
1554
+
1555
+ success:
1556
+ input_buffer->depth--;
1557
+
1558
+ if (head != NULL) {
1559
+ head->prev = current_item;
1560
+ }
1561
+
1562
+ item->type = cJSON_Array;
1563
+ item->child = head;
1564
+
1565
+ input_buffer->offset++;
1566
+
1567
+ return true;
1568
+
1569
+ fail:
1570
+ if (head != NULL)
1571
+ {
1572
+ cJSON_Delete(head);
1573
+ }
1574
+
1575
+ return false;
1576
+ }
1577
+
1578
+ /* Render an array to text */
1579
+ static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1580
+ {
1581
+ unsigned char *output_pointer = NULL;
1582
+ size_t length = 0;
1583
+ cJSON *current_element = item->child;
1584
+
1585
+ if (output_buffer == NULL)
1586
+ {
1587
+ return false;
1588
+ }
1589
+
1590
+ /* Compose the output array. */
1591
+ /* opening square bracket */
1592
+ output_pointer = ensure(output_buffer, 1);
1593
+ if (output_pointer == NULL)
1594
+ {
1595
+ return false;
1596
+ }
1597
+
1598
+ *output_pointer = '[';
1599
+ output_buffer->offset++;
1600
+ output_buffer->depth++;
1601
+
1602
+ while (current_element != NULL)
1603
+ {
1604
+ if (!print_value(current_element, output_buffer))
1605
+ {
1606
+ return false;
1607
+ }
1608
+ update_offset(output_buffer);
1609
+ if (current_element->next)
1610
+ {
1611
+ length = (size_t) (output_buffer->format ? 2 : 1);
1612
+ output_pointer = ensure(output_buffer, length + 1);
1613
+ if (output_pointer == NULL)
1614
+ {
1615
+ return false;
1616
+ }
1617
+ *output_pointer++ = ',';
1618
+ if(output_buffer->format)
1619
+ {
1620
+ *output_pointer++ = ' ';
1621
+ }
1622
+ *output_pointer = '\0';
1623
+ output_buffer->offset += length;
1624
+ }
1625
+ current_element = current_element->next;
1626
+ }
1627
+
1628
+ output_pointer = ensure(output_buffer, 2);
1629
+ if (output_pointer == NULL)
1630
+ {
1631
+ return false;
1632
+ }
1633
+ *output_pointer++ = ']';
1634
+ *output_pointer = '\0';
1635
+ output_buffer->depth--;
1636
+
1637
+ return true;
1638
+ }
1639
+
1640
+ /* Build an object from the text. */
1641
+ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1642
+ {
1643
+ cJSON *head = NULL; /* linked list head */
1644
+ cJSON *current_item = NULL;
1645
+
1646
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1647
+ {
1648
+ return false; /* to deeply nested */
1649
+ }
1650
+ input_buffer->depth++;
1651
+
1652
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1653
+ {
1654
+ goto fail; /* not an object */
1655
+ }
1656
+
1657
+ input_buffer->offset++;
1658
+ buffer_skip_whitespace(input_buffer);
1659
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1660
+ {
1661
+ goto success; /* empty object */
1662
+ }
1663
+
1664
+ /* check if we skipped to the end of the buffer */
1665
+ if (cannot_access_at_index(input_buffer, 0))
1666
+ {
1667
+ input_buffer->offset--;
1668
+ goto fail;
1669
+ }
1670
+
1671
+ /* step back to character in front of the first element */
1672
+ input_buffer->offset--;
1673
+ /* loop through the comma separated array elements */
1674
+ do
1675
+ {
1676
+ /* allocate next item */
1677
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1678
+ if (new_item == NULL)
1679
+ {
1680
+ goto fail; /* allocation failure */
1681
+ }
1682
+
1683
+ /* attach next item to list */
1684
+ if (head == NULL)
1685
+ {
1686
+ /* start the linked list */
1687
+ current_item = head = new_item;
1688
+ }
1689
+ else
1690
+ {
1691
+ /* add to the end and advance */
1692
+ current_item->next = new_item;
1693
+ new_item->prev = current_item;
1694
+ current_item = new_item;
1695
+ }
1696
+
1697
+ if (cannot_access_at_index(input_buffer, 1))
1698
+ {
1699
+ goto fail; /* nothing comes after the comma */
1700
+ }
1701
+
1702
+ /* parse the name of the child */
1703
+ input_buffer->offset++;
1704
+ buffer_skip_whitespace(input_buffer);
1705
+ if (!parse_string(current_item, input_buffer))
1706
+ {
1707
+ goto fail; /* failed to parse name */
1708
+ }
1709
+ buffer_skip_whitespace(input_buffer);
1710
+
1711
+ /* swap valuestring and string, because we parsed the name */
1712
+ current_item->string = current_item->valuestring;
1713
+ current_item->valuestring = NULL;
1714
+
1715
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1716
+ {
1717
+ goto fail; /* invalid object */
1718
+ }
1719
+
1720
+ /* parse the value */
1721
+ input_buffer->offset++;
1722
+ buffer_skip_whitespace(input_buffer);
1723
+ if (!parse_value(current_item, input_buffer))
1724
+ {
1725
+ goto fail; /* failed to parse value */
1726
+ }
1727
+ buffer_skip_whitespace(input_buffer);
1728
+ }
1729
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1730
+
1731
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1732
+ {
1733
+ goto fail; /* expected end of object */
1734
+ }
1735
+
1736
+ success:
1737
+ input_buffer->depth--;
1738
+
1739
+ if (head != NULL) {
1740
+ head->prev = current_item;
1741
+ }
1742
+
1743
+ item->type = cJSON_Object;
1744
+ item->child = head;
1745
+
1746
+ input_buffer->offset++;
1747
+
1748
+ return true;
1749
+
1750
+ fail:
1751
+ if (head != NULL)
1752
+ {
1753
+ cJSON_Delete(head);
1754
+ }
1755
+
1756
+ return false;
1757
+ }
1758
+
1759
+ /* Render an object to text. */
1760
+ static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1761
+ {
1762
+ unsigned char *output_pointer = NULL;
1763
+ size_t length = 0;
1764
+ cJSON *current_item = item->child;
1765
+
1766
+ if (output_buffer == NULL)
1767
+ {
1768
+ return false;
1769
+ }
1770
+
1771
+ /* Compose the output: */
1772
+ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1773
+ output_pointer = ensure(output_buffer, length + 1);
1774
+ if (output_pointer == NULL)
1775
+ {
1776
+ return false;
1777
+ }
1778
+
1779
+ *output_pointer++ = '{';
1780
+ output_buffer->depth++;
1781
+ if (output_buffer->format)
1782
+ {
1783
+ *output_pointer++ = '\n';
1784
+ }
1785
+ output_buffer->offset += length;
1786
+
1787
+ while (current_item)
1788
+ {
1789
+ if (output_buffer->format)
1790
+ {
1791
+ size_t i;
1792
+ output_pointer = ensure(output_buffer, output_buffer->depth);
1793
+ if (output_pointer == NULL)
1794
+ {
1795
+ return false;
1796
+ }
1797
+ for (i = 0; i < output_buffer->depth; i++)
1798
+ {
1799
+ *output_pointer++ = '\t';
1800
+ }
1801
+ output_buffer->offset += output_buffer->depth;
1802
+ }
1803
+
1804
+ /* print key */
1805
+ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1806
+ {
1807
+ return false;
1808
+ }
1809
+ update_offset(output_buffer);
1810
+
1811
+ length = (size_t) (output_buffer->format ? 2 : 1);
1812
+ output_pointer = ensure(output_buffer, length);
1813
+ if (output_pointer == NULL)
1814
+ {
1815
+ return false;
1816
+ }
1817
+ *output_pointer++ = ':';
1818
+ if (output_buffer->format)
1819
+ {
1820
+ *output_pointer++ = '\t';
1821
+ }
1822
+ output_buffer->offset += length;
1823
+
1824
+ /* print value */
1825
+ if (!print_value(current_item, output_buffer))
1826
+ {
1827
+ return false;
1828
+ }
1829
+ update_offset(output_buffer);
1830
+
1831
+ /* print comma if not last */
1832
+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1833
+ output_pointer = ensure(output_buffer, length + 1);
1834
+ if (output_pointer == NULL)
1835
+ {
1836
+ return false;
1837
+ }
1838
+ if (current_item->next)
1839
+ {
1840
+ *output_pointer++ = ',';
1841
+ }
1842
+
1843
+ if (output_buffer->format)
1844
+ {
1845
+ *output_pointer++ = '\n';
1846
+ }
1847
+ *output_pointer = '\0';
1848
+ output_buffer->offset += length;
1849
+
1850
+ current_item = current_item->next;
1851
+ }
1852
+
1853
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1854
+ if (output_pointer == NULL)
1855
+ {
1856
+ return false;
1857
+ }
1858
+ if (output_buffer->format)
1859
+ {
1860
+ size_t i;
1861
+ for (i = 0; i < (output_buffer->depth - 1); i++)
1862
+ {
1863
+ *output_pointer++ = '\t';
1864
+ }
1865
+ }
1866
+ *output_pointer++ = '}';
1867
+ *output_pointer = '\0';
1868
+ output_buffer->depth--;
1869
+
1870
+ return true;
1871
+ }
1872
+
1873
+ /* Get Array size/item / object item. */
1874
+ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1875
+ {
1876
+ cJSON *child = NULL;
1877
+ size_t size = 0;
1878
+
1879
+ if (array == NULL)
1880
+ {
1881
+ return 0;
1882
+ }
1883
+
1884
+ child = array->child;
1885
+
1886
+ while(child != NULL)
1887
+ {
1888
+ size++;
1889
+ child = child->next;
1890
+ }
1891
+
1892
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1893
+
1894
+ return (int)size;
1895
+ }
1896
+
1897
+ static cJSON* get_array_item(const cJSON *array, size_t index)
1898
+ {
1899
+ cJSON *current_child = NULL;
1900
+
1901
+ if (array == NULL)
1902
+ {
1903
+ return NULL;
1904
+ }
1905
+
1906
+ current_child = array->child;
1907
+ while ((current_child != NULL) && (index > 0))
1908
+ {
1909
+ index--;
1910
+ current_child = current_child->next;
1911
+ }
1912
+
1913
+ return current_child;
1914
+ }
1915
+
1916
+ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1917
+ {
1918
+ if (index < 0)
1919
+ {
1920
+ return NULL;
1921
+ }
1922
+
1923
+ return get_array_item(array, (size_t)index);
1924
+ }
1925
+
1926
+ static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1927
+ {
1928
+ cJSON *current_element = NULL;
1929
+
1930
+ if ((object == NULL) || (name == NULL))
1931
+ {
1932
+ return NULL;
1933
+ }
1934
+
1935
+ current_element = object->child;
1936
+ if (case_sensitive)
1937
+ {
1938
+ while (current_element != NULL)
1939
+ {
1940
+ if (current_element->string && (strcmp(name, current_element->string) == 0))
1941
+ {
1942
+ return current_element;
1943
+ }
1944
+ current_element = current_element->next;
1945
+ }
1946
+ }
1947
+ else
1948
+ {
1949
+ while (current_element != NULL)
1950
+ {
1951
+ if (current_element->string && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) == 0))
1952
+ {
1953
+ return current_element;
1954
+ }
1955
+ current_element = current_element->next;
1956
+ }
1957
+ }
1958
+
1959
+ return NULL;
1960
+ }
1961
+
1962
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1963
+ {
1964
+ return get_object_item(object, string, false);
1965
+ }
1966
+
1967
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1968
+ {
1969
+ return get_object_item(object, string, true);
1970
+ }
1971
+
1972
+ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1973
+ {
1974
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
1975
+ }
1976
+
1977
+ /* Utility for array list handling. */
1978
+ static void suffix_object(cJSON *prev, cJSON *item)
1979
+ {
1980
+ prev->next = item;
1981
+ item->prev = prev;
1982
+ }
1983
+
1984
+ /* Utility for handling references. */
1985
+ static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1986
+ {
1987
+ cJSON *reference = NULL;
1988
+ if (item == NULL)
1989
+ {
1990
+ return NULL;
1991
+ }
1992
+
1993
+ reference = cJSON_New_Item(hooks);
1994
+ if (reference == NULL)
1995
+ {
1996
+ return NULL;
1997
+ }
1998
+
1999
+ memcpy(reference, item, sizeof(cJSON));
2000
+ reference->string = NULL;
2001
+ reference->type |= cJSON_IsReference;
2002
+ reference->next = reference->prev = NULL;
2003
+ return reference;
2004
+ }
2005
+
2006
+ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
2007
+ {
2008
+ cJSON *child = NULL;
2009
+
2010
+ if ((item == NULL) || (array == NULL) || (array == item))
2011
+ {
2012
+ return false;
2013
+ }
2014
+
2015
+ child = array->child;
2016
+ /*
2017
+ * To find the last item in array quickly, we use prev in array
2018
+ */
2019
+ if (child == NULL)
2020
+ {
2021
+ /* list is empty, start new one */
2022
+ array->child = item;
2023
+ item->prev = item;
2024
+ item->next = NULL;
2025
+ }
2026
+ else
2027
+ {
2028
+ /* append to the end */
2029
+ if (child->prev)
2030
+ {
2031
+ suffix_object(child->prev, item);
2032
+ array->child->prev = item;
2033
+ }
2034
+ }
2035
+
2036
+ return true;
2037
+ }
2038
+
2039
+ /* Add item to array/object. */
2040
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2041
+ {
2042
+ return add_item_to_array(array, item);
2043
+ }
2044
+
2045
+ #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2046
+ #pragma GCC diagnostic push
2047
+ #endif
2048
+ #ifdef __GNUC__
2049
+ #pragma GCC diagnostic ignored "-Wcast-qual"
2050
+ #endif
2051
+ /* helper function to cast away const */
2052
+ static void* cast_away_const(const void* string)
2053
+ {
2054
+ return (void*)string;
2055
+ }
2056
+ #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2057
+ #pragma GCC diagnostic pop
2058
+ #endif
2059
+
2060
+
2061
+ 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)
2062
+ {
2063
+ char *new_key = NULL;
2064
+ int new_type = cJSON_Invalid;
2065
+
2066
+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2067
+ {
2068
+ return false;
2069
+ }
2070
+
2071
+ if (constant_key)
2072
+ {
2073
+ new_key = (char*)cast_away_const(string);
2074
+ new_type = item->type | cJSON_StringIsConst;
2075
+ }
2076
+ else
2077
+ {
2078
+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2079
+ if (new_key == NULL)
2080
+ {
2081
+ return false;
2082
+ }
2083
+
2084
+ new_type = item->type & ~cJSON_StringIsConst;
2085
+ }
2086
+
2087
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2088
+ {
2089
+ hooks->deallocate(item->string);
2090
+ }
2091
+
2092
+ item->string = new_key;
2093
+ item->type = new_type;
2094
+
2095
+ return add_item_to_array(object, item);
2096
+ }
2097
+
2098
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2099
+ {
2100
+ return add_item_to_object(object, string, item, &global_hooks, false);
2101
+ }
2102
+
2103
+ /* Add an item to an object with constant string as key */
2104
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2105
+ {
2106
+ return add_item_to_object(object, string, item, &global_hooks, true);
2107
+ }
2108
+
2109
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2110
+ {
2111
+ if (array == NULL)
2112
+ {
2113
+ return false;
2114
+ }
2115
+
2116
+ return add_item_to_array(array, create_reference(item, &global_hooks));
2117
+ }
2118
+
2119
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2120
+ {
2121
+ if ((object == NULL) || (string == NULL))
2122
+ {
2123
+ return false;
2124
+ }
2125
+
2126
+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2127
+ }
2128
+
2129
+ CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2130
+ {
2131
+ cJSON *null = cJSON_CreateNull();
2132
+ if (add_item_to_object(object, name, null, &global_hooks, false))
2133
+ {
2134
+ return null;
2135
+ }
2136
+
2137
+ cJSON_Delete(null);
2138
+ return NULL;
2139
+ }
2140
+
2141
+ CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2142
+ {
2143
+ cJSON *true_item = cJSON_CreateTrue();
2144
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
2145
+ {
2146
+ return true_item;
2147
+ }
2148
+
2149
+ cJSON_Delete(true_item);
2150
+ return NULL;
2151
+ }
2152
+
2153
+ CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2154
+ {
2155
+ cJSON *false_item = cJSON_CreateFalse();
2156
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
2157
+ {
2158
+ return false_item;
2159
+ }
2160
+
2161
+ cJSON_Delete(false_item);
2162
+ return NULL;
2163
+ }
2164
+
2165
+ CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2166
+ {
2167
+ cJSON *bool_item = cJSON_CreateBool(boolean);
2168
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2169
+ {
2170
+ return bool_item;
2171
+ }
2172
+
2173
+ cJSON_Delete(bool_item);
2174
+ return NULL;
2175
+ }
2176
+
2177
+ CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2178
+ {
2179
+ cJSON *number_item = cJSON_CreateNumber(number);
2180
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
2181
+ {
2182
+ return number_item;
2183
+ }
2184
+
2185
+ cJSON_Delete(number_item);
2186
+ return NULL;
2187
+ }
2188
+
2189
+ CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2190
+ {
2191
+ cJSON *string_item = cJSON_CreateString(string);
2192
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
2193
+ {
2194
+ return string_item;
2195
+ }
2196
+
2197
+ cJSON_Delete(string_item);
2198
+ return NULL;
2199
+ }
2200
+
2201
+ CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2202
+ {
2203
+ cJSON *raw_item = cJSON_CreateRaw(raw);
2204
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2205
+ {
2206
+ return raw_item;
2207
+ }
2208
+
2209
+ cJSON_Delete(raw_item);
2210
+ return NULL;
2211
+ }
2212
+
2213
+ CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2214
+ {
2215
+ cJSON *object_item = cJSON_CreateObject();
2216
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
2217
+ {
2218
+ return object_item;
2219
+ }
2220
+
2221
+ cJSON_Delete(object_item);
2222
+ return NULL;
2223
+ }
2224
+
2225
+ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2226
+ {
2227
+ cJSON *array = cJSON_CreateArray();
2228
+ if (add_item_to_object(object, name, array, &global_hooks, false))
2229
+ {
2230
+ return array;
2231
+ }
2232
+
2233
+ cJSON_Delete(array);
2234
+ return NULL;
2235
+ }
2236
+
2237
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2238
+ {
2239
+ if ((parent == NULL) || (item == NULL))
2240
+ {
2241
+ return NULL;
2242
+ }
2243
+
2244
+ if (item != parent->child)
2245
+ {
2246
+ /* not the first element */
2247
+ item->prev->next = item->next;
2248
+ }
2249
+ if (item->next != NULL)
2250
+ {
2251
+ /* not the last element */
2252
+ item->next->prev = item->prev;
2253
+ }
2254
+
2255
+ if (item == parent->child)
2256
+ {
2257
+ /* first element */
2258
+ parent->child = item->next;
2259
+ }
2260
+ else if (item->next == NULL)
2261
+ {
2262
+ /* last element */
2263
+ parent->child->prev = item->prev;
2264
+ }
2265
+
2266
+ /* make sure the detached item doesn't point anywhere anymore */
2267
+ item->prev = NULL;
2268
+ item->next = NULL;
2269
+
2270
+ return item;
2271
+ }
2272
+
2273
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2274
+ {
2275
+ if (which < 0)
2276
+ {
2277
+ return NULL;
2278
+ }
2279
+
2280
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2281
+ }
2282
+
2283
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2284
+ {
2285
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2286
+ }
2287
+
2288
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2289
+ {
2290
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
2291
+
2292
+ return cJSON_DetachItemViaPointer(object, to_detach);
2293
+ }
2294
+
2295
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2296
+ {
2297
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2298
+
2299
+ return cJSON_DetachItemViaPointer(object, to_detach);
2300
+ }
2301
+
2302
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2303
+ {
2304
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2305
+ }
2306
+
2307
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2308
+ {
2309
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2310
+ }
2311
+
2312
+ /* Replace array/object items with new ones. */
2313
+ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2314
+ {
2315
+ cJSON *after_inserted = NULL;
2316
+
2317
+ if (which < 0 || newitem == NULL)
2318
+ {
2319
+ return false;
2320
+ }
2321
+
2322
+ after_inserted = get_array_item(array, (size_t)which);
2323
+ if (after_inserted == NULL)
2324
+ {
2325
+ return add_item_to_array(array, newitem);
2326
+ }
2327
+
2328
+ if (after_inserted != array->child && after_inserted->prev == NULL) {
2329
+ /* return false if after_inserted is a corrupted array item */
2330
+ return false;
2331
+ }
2332
+
2333
+ newitem->next = after_inserted;
2334
+ newitem->prev = after_inserted->prev;
2335
+ after_inserted->prev = newitem;
2336
+ if (after_inserted == array->child)
2337
+ {
2338
+ array->child = newitem;
2339
+ }
2340
+ else
2341
+ {
2342
+ newitem->prev->next = newitem;
2343
+ }
2344
+ return true;
2345
+ }
2346
+
2347
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2348
+ {
2349
+ if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
2350
+ {
2351
+ return false;
2352
+ }
2353
+
2354
+ if (replacement == item)
2355
+ {
2356
+ return true;
2357
+ }
2358
+
2359
+ replacement->next = item->next;
2360
+ replacement->prev = item->prev;
2361
+
2362
+ if (replacement->next != NULL)
2363
+ {
2364
+ replacement->next->prev = replacement;
2365
+ }
2366
+ if (parent->child == item)
2367
+ {
2368
+ if (parent->child->prev == parent->child)
2369
+ {
2370
+ replacement->prev = replacement;
2371
+ }
2372
+ parent->child = replacement;
2373
+ }
2374
+ else
2375
+ { /*
2376
+ * To find the last item in array quickly, we use prev in array.
2377
+ * We can't modify the last item's prev pointer from pointer to pointer conversion.
2378
+ */
2379
+ if (replacement->prev != NULL)
2380
+ {
2381
+ replacement->prev->next = replacement;
2382
+ }
2383
+ if (replacement->next == NULL)
2384
+ {
2385
+ parent->child->prev = replacement;
2386
+ }
2387
+ }
2388
+
2389
+ item->next = NULL;
2390
+ item->prev = NULL;
2391
+ cJSON_Delete(item);
2392
+
2393
+ return true;
2394
+ }
2395
+
2396
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2397
+ {
2398
+ if (which < 0)
2399
+ {
2400
+ return false;
2401
+ }
2402
+
2403
+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2404
+ }
2405
+
2406
+ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2407
+ {
2408
+ if ((replacement == NULL) || (string == NULL))
2409
+ {
2410
+ return false;
2411
+ }
2412
+
2413
+ /* replace the name in the replacement */
2414
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2415
+ {
2416
+ cJSON_free(replacement->string);
2417
+ }
2418
+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2419
+ if (replacement->string == NULL)
2420
+ {
2421
+ return false;
2422
+ }
2423
+
2424
+ replacement->type &= ~cJSON_StringIsConst;
2425
+
2426
+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2427
+ }
2428
+
2429
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2430
+ {
2431
+ return replace_item_in_object(object, string, newitem, false);
2432
+ }
2433
+
2434
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2435
+ {
2436
+ return replace_item_in_object(object, string, newitem, true);
2437
+ }
2438
+
2439
+ /* Create basic types: */
2440
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2441
+ {
2442
+ cJSON *item = cJSON_New_Item(&global_hooks);
2443
+ if(item)
2444
+ {
2445
+ item->type = cJSON_NULL;
2446
+ }
2447
+
2448
+ return item;
2449
+ }
2450
+
2451
+ CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2452
+ {
2453
+ cJSON *item = cJSON_New_Item(&global_hooks);
2454
+ if(item)
2455
+ {
2456
+ item->type = cJSON_True;
2457
+ }
2458
+
2459
+ return item;
2460
+ }
2461
+
2462
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2463
+ {
2464
+ cJSON *item = cJSON_New_Item(&global_hooks);
2465
+ if(item)
2466
+ {
2467
+ item->type = cJSON_False;
2468
+ }
2469
+
2470
+ return item;
2471
+ }
2472
+
2473
+ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2474
+ {
2475
+ cJSON *item = cJSON_New_Item(&global_hooks);
2476
+ if(item)
2477
+ {
2478
+ item->type = boolean ? cJSON_True : cJSON_False;
2479
+ }
2480
+
2481
+ return item;
2482
+ }
2483
+
2484
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2485
+ {
2486
+ cJSON *item = cJSON_New_Item(&global_hooks);
2487
+ if(item)
2488
+ {
2489
+ item->type = cJSON_Number;
2490
+ item->valuedouble = num;
2491
+
2492
+ /* use saturation in case of overflow */
2493
+ if (num >= INT_MAX)
2494
+ {
2495
+ item->valueint = INT_MAX;
2496
+ }
2497
+ else if (num <= (double)INT_MIN)
2498
+ {
2499
+ item->valueint = INT_MIN;
2500
+ }
2501
+ else
2502
+ {
2503
+ item->valueint = (int)num;
2504
+ }
2505
+ }
2506
+
2507
+ return item;
2508
+ }
2509
+
2510
+ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2511
+ {
2512
+ cJSON *item = cJSON_New_Item(&global_hooks);
2513
+ if(item)
2514
+ {
2515
+ item->type = cJSON_String;
2516
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2517
+ if(!item->valuestring)
2518
+ {
2519
+ cJSON_Delete(item);
2520
+ return NULL;
2521
+ }
2522
+ }
2523
+
2524
+ return item;
2525
+ }
2526
+
2527
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2528
+ {
2529
+ cJSON *item = cJSON_New_Item(&global_hooks);
2530
+ if (item != NULL)
2531
+ {
2532
+ item->type = cJSON_String | cJSON_IsReference;
2533
+ item->valuestring = (char*)cast_away_const(string);
2534
+ }
2535
+
2536
+ return item;
2537
+ }
2538
+
2539
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2540
+ {
2541
+ cJSON *item = cJSON_New_Item(&global_hooks);
2542
+ if (item != NULL) {
2543
+ item->type = cJSON_Object | cJSON_IsReference;
2544
+ item->child = (cJSON*)cast_away_const(child);
2545
+ }
2546
+
2547
+ return item;
2548
+ }
2549
+
2550
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2551
+ cJSON *item = cJSON_New_Item(&global_hooks);
2552
+ if (item != NULL) {
2553
+ item->type = cJSON_Array | cJSON_IsReference;
2554
+ item->child = (cJSON*)cast_away_const(child);
2555
+ }
2556
+
2557
+ return item;
2558
+ }
2559
+
2560
+ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2561
+ {
2562
+ cJSON *item = cJSON_New_Item(&global_hooks);
2563
+ if(item)
2564
+ {
2565
+ item->type = cJSON_Raw;
2566
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2567
+ if(!item->valuestring)
2568
+ {
2569
+ cJSON_Delete(item);
2570
+ return NULL;
2571
+ }
2572
+ }
2573
+
2574
+ return item;
2575
+ }
2576
+
2577
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2578
+ {
2579
+ cJSON *item = cJSON_New_Item(&global_hooks);
2580
+ if(item)
2581
+ {
2582
+ item->type=cJSON_Array;
2583
+ }
2584
+
2585
+ return item;
2586
+ }
2587
+
2588
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2589
+ {
2590
+ cJSON *item = cJSON_New_Item(&global_hooks);
2591
+ if(item)
2592
+ {
2593
+ item->type = cJSON_Object;
2594
+ }
2595
+
2596
+ return item;
2597
+ }
2598
+
2599
+ /* Create Arrays: */
2600
+ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2601
+ {
2602
+ size_t i = 0;
2603
+ cJSON *n = NULL;
2604
+ cJSON *p = NULL;
2605
+ cJSON *a = NULL;
2606
+
2607
+ if ((count < 0) || (numbers == NULL))
2608
+ {
2609
+ return NULL;
2610
+ }
2611
+
2612
+ a = cJSON_CreateArray();
2613
+
2614
+ for(i = 0; a && (i < (size_t)count); i++)
2615
+ {
2616
+ n = cJSON_CreateNumber((double)numbers[i]);
2617
+ if (!n)
2618
+ {
2619
+ cJSON_Delete(a);
2620
+ return NULL;
2621
+ }
2622
+ if(!i)
2623
+ {
2624
+ a->child = n;
2625
+ }
2626
+ else
2627
+ {
2628
+ suffix_object(p, n);
2629
+ }
2630
+ p = n;
2631
+ }
2632
+
2633
+ if (a && a->child) {
2634
+ a->child->prev = n;
2635
+ }
2636
+
2637
+ return a;
2638
+ }
2639
+
2640
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2641
+ {
2642
+ size_t i = 0;
2643
+ cJSON *n = NULL;
2644
+ cJSON *p = NULL;
2645
+ cJSON *a = NULL;
2646
+
2647
+ if ((count < 0) || (numbers == NULL))
2648
+ {
2649
+ return NULL;
2650
+ }
2651
+
2652
+ a = cJSON_CreateArray();
2653
+
2654
+ for(i = 0; a && (i < (size_t)count); i++)
2655
+ {
2656
+ n = cJSON_CreateNumber((double)numbers[i]);
2657
+ if(!n)
2658
+ {
2659
+ cJSON_Delete(a);
2660
+ return NULL;
2661
+ }
2662
+ if(!i)
2663
+ {
2664
+ a->child = n;
2665
+ }
2666
+ else
2667
+ {
2668
+ suffix_object(p, n);
2669
+ }
2670
+ p = n;
2671
+ }
2672
+
2673
+ if (a && a->child) {
2674
+ a->child->prev = n;
2675
+ }
2676
+
2677
+ return a;
2678
+ }
2679
+
2680
+ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2681
+ {
2682
+ size_t i = 0;
2683
+ cJSON *n = NULL;
2684
+ cJSON *p = NULL;
2685
+ cJSON *a = NULL;
2686
+
2687
+ if ((count < 0) || (numbers == NULL))
2688
+ {
2689
+ return NULL;
2690
+ }
2691
+
2692
+ a = cJSON_CreateArray();
2693
+
2694
+ for(i = 0; a && (i < (size_t)count); i++)
2695
+ {
2696
+ n = cJSON_CreateNumber(numbers[i]);
2697
+ if(!n)
2698
+ {
2699
+ cJSON_Delete(a);
2700
+ return NULL;
2701
+ }
2702
+ if(!i)
2703
+ {
2704
+ a->child = n;
2705
+ }
2706
+ else
2707
+ {
2708
+ suffix_object(p, n);
2709
+ }
2710
+ p = n;
2711
+ }
2712
+
2713
+ if (a && a->child) {
2714
+ a->child->prev = n;
2715
+ }
2716
+
2717
+ return a;
2718
+ }
2719
+
2720
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2721
+ {
2722
+ size_t i = 0;
2723
+ cJSON *n = NULL;
2724
+ cJSON *p = NULL;
2725
+ cJSON *a = NULL;
2726
+
2727
+ if ((count < 0) || (strings == NULL))
2728
+ {
2729
+ return NULL;
2730
+ }
2731
+
2732
+ a = cJSON_CreateArray();
2733
+
2734
+ for(i = 0; a && (i < (size_t)count); i++)
2735
+ {
2736
+ n = cJSON_CreateString(strings[i]);
2737
+ if(!n)
2738
+ {
2739
+ cJSON_Delete(a);
2740
+ return NULL;
2741
+ }
2742
+ if(!i)
2743
+ {
2744
+ a->child = n;
2745
+ }
2746
+ else
2747
+ {
2748
+ suffix_object(p, n);
2749
+ }
2750
+ p = n;
2751
+ }
2752
+
2753
+ if (a && a->child) {
2754
+ a->child->prev = n;
2755
+ }
2756
+
2757
+ return a;
2758
+ }
2759
+
2760
+ /* Duplication */
2761
+ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2762
+ {
2763
+ cJSON *newitem = NULL;
2764
+ cJSON *child = NULL;
2765
+ cJSON *next = NULL;
2766
+ cJSON *newchild = NULL;
2767
+
2768
+ /* Bail on bad ptr */
2769
+ if (!item)
2770
+ {
2771
+ goto fail;
2772
+ }
2773
+ /* Create new item */
2774
+ newitem = cJSON_New_Item(&global_hooks);
2775
+ if (!newitem)
2776
+ {
2777
+ goto fail;
2778
+ }
2779
+ /* Copy over all vars */
2780
+ newitem->type = item->type & (~cJSON_IsReference);
2781
+ newitem->valueint = item->valueint;
2782
+ newitem->valuedouble = item->valuedouble;
2783
+ if (item->valuestring)
2784
+ {
2785
+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2786
+ if (!newitem->valuestring)
2787
+ {
2788
+ goto fail;
2789
+ }
2790
+ }
2791
+ if (item->string)
2792
+ {
2793
+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2794
+ if (!newitem->string)
2795
+ {
2796
+ goto fail;
2797
+ }
2798
+ }
2799
+ /* If non recurse, then we're done! */
2800
+ if (!recurse)
2801
+ {
2802
+ return newitem;
2803
+ }
2804
+ /* Walk the ->next chain for the child. */
2805
+ child = item->child;
2806
+ while (child != NULL)
2807
+ {
2808
+ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the chain */
2809
+ if (!newchild)
2810
+ {
2811
+ goto fail;
2812
+ }
2813
+ if (next != NULL)
2814
+ {
2815
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2816
+ next->next = newchild;
2817
+ newchild->prev = next;
2818
+ next = newchild;
2819
+ }
2820
+ else
2821
+ {
2822
+ /* Set newitem->child and move to it */
2823
+ newitem->child = newchild;
2824
+ next = newchild;
2825
+ }
2826
+ child = child->next;
2827
+ }
2828
+ if (newitem && newitem->child)
2829
+ {
2830
+ newitem->child->prev = newchild;
2831
+ }
2832
+
2833
+ return newitem;
2834
+
2835
+ fail:
2836
+ if (newitem != NULL)
2837
+ {
2838
+ cJSON_Delete(newitem);
2839
+ }
2840
+
2841
+ return NULL;
2842
+ }
2843
+
2844
+ static void skip_oneline_comment(char **input)
2845
+ {
2846
+ *input += static_strlen("//");
2847
+
2848
+ for (; (*input)[0] != '\0'; ++(*input))
2849
+ {
2850
+ if ((*input)[0] == '\n') {
2851
+ *input += static_strlen("\n");
2852
+ return;
2853
+ }
2854
+ }
2855
+ }
2856
+
2857
+ static void skip_multiline_comment(char **input)
2858
+ {
2859
+ *input += static_strlen("/*");
2860
+
2861
+ for (; (*input)[0] != '\0'; ++(*input))
2862
+ {
2863
+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
2864
+ {
2865
+ *input += static_strlen("*/");
2866
+ return;
2867
+ }
2868
+ }
2869
+ }
2870
+
2871
+ static void minify_string(char **input, char **output) {
2872
+ (*output)[0] = (*input)[0];
2873
+ *input += static_strlen("\"");
2874
+ *output += static_strlen("\"");
2875
+
2876
+
2877
+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2878
+ (*output)[0] = (*input)[0];
2879
+
2880
+ if ((*input)[0] == '\"') {
2881
+ (*output)[0] = '\"';
2882
+ *input += static_strlen("\"");
2883
+ *output += static_strlen("\"");
2884
+ return;
2885
+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2886
+ (*output)[1] = (*input)[1];
2887
+ *input += static_strlen("\"");
2888
+ *output += static_strlen("\"");
2889
+ }
2890
+ }
2891
+ }
2892
+
2893
+ CJSON_PUBLIC(void) cJSON_Minify(char *json)
2894
+ {
2895
+ char *into = json;
2896
+
2897
+ if (json == NULL)
2898
+ {
2899
+ return;
2900
+ }
2901
+
2902
+ while (json[0] != '\0')
2903
+ {
2904
+ switch (json[0])
2905
+ {
2906
+ case ' ':
2907
+ case '\t':
2908
+ case '\r':
2909
+ case '\n':
2910
+ json++;
2911
+ break;
2912
+
2913
+ case '/':
2914
+ if (json[1] == '/')
2915
+ {
2916
+ skip_oneline_comment(&json);
2917
+ }
2918
+ else if (json[1] == '*')
2919
+ {
2920
+ skip_multiline_comment(&json);
2921
+ } else {
2922
+ json++;
2923
+ }
2924
+ break;
2925
+
2926
+ case '\"':
2927
+ minify_string(&json, (char**)&into);
2928
+ break;
2929
+
2930
+ default:
2931
+ into[0] = json[0];
2932
+ json++;
2933
+ into++;
2934
+ }
2935
+ }
2936
+
2937
+ /* and null-terminate. */
2938
+ *into = '\0';
2939
+ }
2940
+
2941
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2942
+ {
2943
+ if (item == NULL)
2944
+ {
2945
+ return false;
2946
+ }
2947
+
2948
+ return (item->type & 0xFF) == cJSON_Invalid;
2949
+ }
2950
+
2951
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2952
+ {
2953
+ if (item == NULL)
2954
+ {
2955
+ return false;
2956
+ }
2957
+
2958
+ return (item->type & 0xFF) == cJSON_False;
2959
+ }
2960
+
2961
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2962
+ {
2963
+ if (item == NULL)
2964
+ {
2965
+ return false;
2966
+ }
2967
+
2968
+ return (item->type & 0xff) == cJSON_True;
2969
+ }
2970
+
2971
+
2972
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2973
+ {
2974
+ if (item == NULL)
2975
+ {
2976
+ return false;
2977
+ }
2978
+
2979
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
2980
+ }
2981
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2982
+ {
2983
+ if (item == NULL)
2984
+ {
2985
+ return false;
2986
+ }
2987
+
2988
+ return (item->type & 0xFF) == cJSON_NULL;
2989
+ }
2990
+
2991
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2992
+ {
2993
+ if (item == NULL)
2994
+ {
2995
+ return false;
2996
+ }
2997
+
2998
+ return (item->type & 0xFF) == cJSON_Number;
2999
+ }
3000
+
3001
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
3002
+ {
3003
+ if (item == NULL)
3004
+ {
3005
+ return false;
3006
+ }
3007
+
3008
+ return (item->type & 0xFF) == cJSON_String;
3009
+ }
3010
+
3011
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
3012
+ {
3013
+ if (item == NULL)
3014
+ {
3015
+ return false;
3016
+ }
3017
+
3018
+ return (item->type & 0xFF) == cJSON_Array;
3019
+ }
3020
+
3021
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
3022
+ {
3023
+ if (item == NULL)
3024
+ {
3025
+ return false;
3026
+ }
3027
+
3028
+ return (item->type & 0xFF) == cJSON_Object;
3029
+ }
3030
+
3031
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
3032
+ {
3033
+ if (item == NULL)
3034
+ {
3035
+ return false;
3036
+ }
3037
+
3038
+ return (item->type & 0xFF) == cJSON_Raw;
3039
+ }
3040
+
3041
+ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
3042
+ {
3043
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
3044
+ {
3045
+ return false;
3046
+ }
3047
+
3048
+ /* check if type is valid */
3049
+ switch (a->type & 0xFF)
3050
+ {
3051
+ case cJSON_False:
3052
+ case cJSON_True:
3053
+ case cJSON_NULL:
3054
+ case cJSON_Number:
3055
+ case cJSON_String:
3056
+ case cJSON_Raw:
3057
+ case cJSON_Array:
3058
+ case cJSON_Object:
3059
+ break;
3060
+
3061
+ default:
3062
+ return false;
3063
+ }
3064
+
3065
+ /* identical objects are equal */
3066
+ if (a == b)
3067
+ {
3068
+ return true;
3069
+ }
3070
+
3071
+ switch (a->type & 0xFF)
3072
+ {
3073
+ /* in these cases and equal type is enough */
3074
+ case cJSON_False:
3075
+ case cJSON_True:
3076
+ case cJSON_NULL:
3077
+ return true;
3078
+
3079
+ case cJSON_Number:
3080
+ if (compare_double(a->valuedouble, b->valuedouble))
3081
+ {
3082
+ return true;
3083
+ }
3084
+ return false;
3085
+
3086
+ case cJSON_String:
3087
+ case cJSON_Raw:
3088
+ if ((a->valuestring == NULL) || (b->valuestring == NULL))
3089
+ {
3090
+ return false;
3091
+ }
3092
+ if (strcmp(a->valuestring, b->valuestring) == 0)
3093
+ {
3094
+ return true;
3095
+ }
3096
+
3097
+ return false;
3098
+
3099
+ case cJSON_Array:
3100
+ {
3101
+ cJSON *a_element = a->child;
3102
+ cJSON *b_element = b->child;
3103
+
3104
+ for (; (a_element != NULL) && (b_element != NULL);)
3105
+ {
3106
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
3107
+ {
3108
+ return false;
3109
+ }
3110
+
3111
+ a_element = a_element->next;
3112
+ b_element = b_element->next;
3113
+ }
3114
+
3115
+ /* one of the arrays is longer than the other */
3116
+ if (a_element != b_element) {
3117
+ return false;
3118
+ }
3119
+
3120
+ return true;
3121
+ }
3122
+
3123
+ case cJSON_Object:
3124
+ {
3125
+ cJSON *a_element = NULL;
3126
+ cJSON *b_element = NULL;
3127
+ cJSON_ArrayForEach(a_element, a)
3128
+ {
3129
+ /* TODO This has O(n^2) runtime, which is horrible! */
3130
+ b_element = get_object_item(b, a_element->string, case_sensitive);
3131
+ if (b_element == NULL)
3132
+ {
3133
+ return false;
3134
+ }
3135
+
3136
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
3137
+ {
3138
+ return false;
3139
+ }
3140
+ }
3141
+
3142
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
3143
+ * TODO: Do this the proper way. */
3144
+ cJSON_ArrayForEach(b_element, b)
3145
+ {
3146
+ a_element = get_object_item(a, b_element->string, case_sensitive);
3147
+ if (a_element == NULL)
3148
+ {
3149
+ return false;
3150
+ }
3151
+
3152
+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
3153
+ {
3154
+ return false;
3155
+ }
3156
+ }
3157
+
3158
+ return true;
3159
+ }
3160
+
3161
+ default:
3162
+ return false;
3163
+ }
3164
+ }
3165
+
3166
+ CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3167
+ {
3168
+ return global_hooks.allocate(size);
3169
+ }
3170
+
3171
+ CJSON_PUBLIC(void) cJSON_free(void *object)
3172
+ {
3173
+ global_hooks.deallocate(object);
3174
+ }
cJSON.h ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+ */
22
+
23
+ #ifndef cJSON__h
24
+ #define cJSON__h
25
+
26
+ #ifdef __cplusplus
27
+ extern "C"
28
+ {
29
+ #endif
30
+
31
+ #if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
32
+ #define __WINDOWS__
33
+ #endif
34
+
35
+ #ifdef __WINDOWS__
36
+
37
+ /* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
38
+
39
+ CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
40
+ CJSON_EXPORT_SYMBOLS - Define this on build when you want to dllexport symbols (default)
41
+ CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
42
+
43
+ For *nix builds that support visibility attribute, you can define similar behavior by setting default visibility to hidden by adding
44
+ -fvisibility=hidden (for gcc) or -xldscope=hidden (for sun cc) to CFLAGS
45
+ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
46
+
47
+ */
48
+
49
+ #define CJSON_CDECL __cdecl
50
+ #define CJSON_STDCALL __stdcall
51
+
52
+ /* export symbols by default, this is necessary for copy pasting the C and header file */
53
+ #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
54
+ #define CJSON_EXPORT_SYMBOLS
55
+ #endif
56
+
57
+ #if defined(CJSON_HIDE_SYMBOLS)
58
+ #define CJSON_PUBLIC(type) type CJSON_STDCALL
59
+ #elif defined(CJSON_EXPORT_SYMBOLS)
60
+ #define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
61
+ #elif defined(CJSON_IMPORT_SYMBOLS)
62
+ #define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
63
+ #endif
64
+ #else /* !__WINDOWS__ */
65
+ #define CJSON_CDECL
66
+ #define CJSON_STDCALL
67
+
68
+ #if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
69
+ #define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
70
+ #else
71
+ #define CJSON_PUBLIC(type) type
72
+ #endif
73
+ #endif
74
+
75
+ /* project version */
76
+ #define CJSON_VERSION_MAJOR 1
77
+ #define CJSON_VERSION_MINOR 7
78
+ #define CJSON_VERSION_PATCH 18
79
+
80
+ #include <stddef.h>
81
+
82
+ /* cJSON Types: */
83
+ #define cJSON_Invalid (0)
84
+ #define cJSON_False (1 << 0)
85
+ #define cJSON_True (1 << 1)
86
+ #define cJSON_NULL (1 << 2)
87
+ #define cJSON_Number (1 << 3)
88
+ #define cJSON_String (1 << 4)
89
+ #define cJSON_Array (1 << 5)
90
+ #define cJSON_Object (1 << 6)
91
+ #define cJSON_Raw (1 << 7) /* raw json */
92
+
93
+ #define cJSON_IsReference 256
94
+ #define cJSON_StringIsConst 512
95
+
96
+ /* The cJSON structure: */
97
+ typedef struct cJSON
98
+ {
99
+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
100
+ struct cJSON *next;
101
+ struct cJSON *prev;
102
+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
103
+ struct cJSON *child;
104
+
105
+ /* The type of the item, as above. */
106
+ int type;
107
+
108
+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
109
+ char *valuestring;
110
+ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
111
+ int valueint;
112
+ /* The item's number, if type==cJSON_Number */
113
+ double valuedouble;
114
+
115
+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
116
+ char *string;
117
+ } cJSON;
118
+
119
+ typedef struct cJSON_Hooks
120
+ {
121
+ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
122
+ void *(CJSON_CDECL *malloc_fn)(size_t sz);
123
+ void (CJSON_CDECL *free_fn)(void *ptr);
124
+ } cJSON_Hooks;
125
+
126
+ typedef int cJSON_bool;
127
+
128
+ /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
129
+ * This is to prevent stack overflows. */
130
+ #ifndef CJSON_NESTING_LIMIT
131
+ #define CJSON_NESTING_LIMIT 1000
132
+ #endif
133
+
134
+ /* returns the version of cJSON as a string */
135
+ CJSON_PUBLIC(const char*) cJSON_Version(void);
136
+
137
+ /* Supply malloc, realloc and free functions to cJSON */
138
+ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
139
+
140
+ /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
141
+ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
142
+ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
143
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
144
+ /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
145
+ /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
146
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
147
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
148
+
149
+ /* Render a cJSON entity to text for transfer/storage. */
150
+ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
151
+ /* Render a cJSON entity to text for transfer/storage without any formatting. */
152
+ CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
153
+ /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
154
+ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
155
+ /* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
156
+ /* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
157
+ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
158
+ /* Delete a cJSON entity and all subentities. */
159
+ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
160
+
161
+ /* Returns the number of items in an array (or object). */
162
+ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
163
+ /* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
164
+ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
165
+ /* Get item "string" from object. Case insensitive. */
166
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
167
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
168
+ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
169
+ /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when no error. */
170
+ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
171
+
172
+ /* Check item type */
173
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
174
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
175
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
176
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
177
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
178
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
179
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
180
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
181
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
182
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
183
+
184
+ /* These calls create a cJSON item of the appropriate type. */
185
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
186
+ CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
187
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
188
+ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
189
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
190
+ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
191
+ /* raw json */
192
+ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
193
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
194
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
195
+
196
+ /* Create a string where valuestring references a string so
197
+ * it will not be freed by cJSON_Delete */
198
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
199
+ /* Create an object/array that only references it's elements so
200
+ * they will not be freed by cJSON_Delete */
201
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
202
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
203
+
204
+ /* These utilities create an Array of count items.
205
+ * The parameter count cannot be greater than the number of elements in the number list, otherwise array access will be out of bounds.*/
206
+ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
207
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
208
+ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
209
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
210
+
211
+ /* Append item to the specified array/object. */
212
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
213
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
214
+ /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
215
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
216
+ * writing to `item->string` */
217
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
218
+ /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing item. */
219
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
220
+ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
221
+
222
+ /* Remove/Detach items from Arrays/Objects. */
223
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
224
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
225
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
226
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
227
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
228
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
229
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
230
+
231
+ /* Update array items. */
232
+ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
233
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
234
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
235
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
236
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem);
237
+
238
+ /* Duplicate a cJSON item */
239
+ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
240
+ /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
241
+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
242
+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
243
+ /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
244
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
245
+ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
246
+
247
+ /* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
248
+ * The input pointer json cannot point to a read-only address area, such as a string constant,
249
+ * but should point to a readable and writable address area. */
250
+ CJSON_PUBLIC(void) cJSON_Minify(char *json);
251
+
252
+ /* Helper functions for creating and adding items to an object at the same time.
253
+ * They return the added item or NULL on failure. */
254
+ CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
255
+ CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
256
+ CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
257
+ CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
258
+ CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
259
+ CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
260
+ CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
261
+ CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
262
+ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
263
+
264
+ /* When assigning an integer value, it needs to be propagated to valuedouble too. */
265
+ #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
266
+ /* helper for the cJSON_SetNumberValue macro */
267
+ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
268
+ #define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
269
+ /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
270
+ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
271
+
272
+ /* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
273
+ #define cJSON_SetBoolValue(object, boolValue) ( \
274
+ (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
275
+ (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
276
+ cJSON_Invalid\
277
+ )
278
+
279
+ /* Macro for iterating over an array or object */
280
+ #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
281
+
282
+ /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
283
+ CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
284
+ CJSON_PUBLIC(void) cJSON_free(void *object);
285
+
286
+ #ifdef __cplusplus
287
+ }
288
+ #endif
289
+
290
+ #endif
shadowclaw.c ADDED
@@ -0,0 +1,653 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #define _GNU_SOURCE
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <stdint.h>
5
+ #include <string.h>
6
+ #include <stdbool.h>
7
+ #include <unistd.h>
8
+ #include <time.h>
9
+ #include <curl/curl.h>
10
+ #include <dirent.h>
11
+ #include "cJSON.h"
12
+
13
+ // --------------------------------------------------------------------
14
+ // Shadow Header + Arena (Tsoding/stb_ds style)
15
+ // --------------------------------------------------------------------
16
+ typedef struct {
17
+ size_t capacity; // bytes available AFTER header
18
+ size_t length; // bytes used AFTER header
19
+ uint64_t tag; // magic: 0x534841444F57434C = "SHADOWCL"
20
+ uint32_t version;
21
+ uint32_t flags; // bit 0 = dirty
22
+ } ShadowHeader;
23
+
24
+ #define SHADOW_MAGIC 0x534841444F57434CULL
25
+ #define SHADOW_SIZE (sizeof(ShadowHeader))
26
+ #define ALIGN_UP(x, a) (((x) + (a)-1) & ~((a)-1))
27
+
28
+ static inline ShadowHeader* shadow_header(void *data) {
29
+ return (ShadowHeader*)((char*)data - SHADOW_SIZE);
30
+ }
31
+
32
+ typedef struct {
33
+ void *data; // user‑facing payload pointer
34
+ size_t reserved; // total malloc size (header + capacity)
35
+ } ShadowArena;
36
+
37
+ ShadowArena shadow_arena_create(size_t initial_capacity) {
38
+ ShadowArena a = {0};
39
+ size_t total = SHADOW_SIZE + initial_capacity;
40
+ total = ALIGN_UP(total, 64);
41
+
42
+ ShadowHeader *h = malloc(total);
43
+ if (!h) abort();
44
+
45
+ *h = (ShadowHeader){
46
+ .capacity = initial_capacity,
47
+ .length = 0,
48
+ .tag = SHADOW_MAGIC,
49
+ .version = 1,
50
+ .flags = 0
51
+ };
52
+ a.data = (char*)h + SHADOW_SIZE;
53
+ a.reserved = total;
54
+ return a;
55
+ }
56
+
57
+ void shadow_arena_destroy(ShadowArena *a) {
58
+ if (a->data) {
59
+ free(shadow_header(a->data));
60
+ a->data = NULL;
61
+ }
62
+ }
63
+
64
+ void* shadow_arena_push(ShadowArena *a, const void *src, size_t bytes) {
65
+ ShadowHeader *h = shadow_header(a->data);
66
+
67
+ if (h->length + bytes > h->capacity) {
68
+ size_t new_cap = h->capacity ? h->capacity * 2 : 4096;
69
+ while (new_cap < h->length + bytes) new_cap *= 2;
70
+ size_t new_total = SHADOW_SIZE + new_cap;
71
+ new_total = ALIGN_UP(new_total, 64);
72
+
73
+ ShadowHeader *new_h = realloc(h, new_total);
74
+ if (!new_h) abort();
75
+
76
+ new_h->capacity = new_cap;
77
+ a->data = (char*)new_h + SHADOW_SIZE;
78
+ a->reserved = new_total;
79
+ h = new_h;
80
+ }
81
+
82
+ char *dst = (char*)a->data + h->length;
83
+ if (src) memcpy(dst, src, bytes);
84
+ else memset(dst, 0, bytes);
85
+
86
+ h->length += bytes;
87
+ h->flags |= 1; // dirty
88
+ return dst;
89
+ }
90
+
91
+ size_t shadow_arena_len(const ShadowArena *a) {
92
+ return shadow_header(a->data)->length;
93
+ }
94
+
95
+ void shadow_arena_clear(ShadowArena *a) {
96
+ ShadowHeader *h = shadow_header(a->data);
97
+ h->length = 0;
98
+ h->flags &= ~1;
99
+ }
100
+
101
+ // --------------------------------------------------------------------
102
+ // Blob Format (tagged, length‑prefixed items)
103
+ // --------------------------------------------------------------------
104
+ typedef struct {
105
+ uint32_t size; // payload size (excluding this header)
106
+ uint32_t kind; // 1=system,2=user,3=assistant,4=tool_call,5=tool_result,6=memory
107
+ uint64_t id; // unique id (timestamp or counter)
108
+ } BlobHeader;
109
+
110
+ // Append a typed blob – returns offset from arena->data start
111
+ ptrdiff_t blob_append(ShadowArena *a, uint32_t kind, uint64_t id,
112
+ const void *payload, size_t payload_bytes)
113
+ {
114
+ size_t total = sizeof(BlobHeader) + payload_bytes;
115
+ char *p = shadow_arena_push(a, NULL, total);
116
+
117
+ BlobHeader bh = {
118
+ .size = (uint32_t)payload_bytes,
119
+ .kind = kind,
120
+ .id = id
121
+ };
122
+ memcpy(p, &bh, sizeof(bh));
123
+ if (payload_bytes) memcpy(p + sizeof(bh), payload, payload_bytes);
124
+ return p - (char*)a->data;
125
+ }
126
+
127
+ // Iterate over all blobs: calls `f(blob_header, payload, userdata)`
128
+ void blob_foreach(ShadowArena *a,
129
+ void (*f)(const BlobHeader*, const char*, void*),
130
+ void *userdata)
131
+ {
132
+ char *start = a->data;
133
+ size_t len = shadow_header(a->data)->length;
134
+ char *end = start + len;
135
+ char *p = start;
136
+ while (p < end) {
137
+ BlobHeader *bh = (BlobHeader*)p;
138
+ char *payload = p + sizeof(BlobHeader);
139
+ f(bh, payload, userdata);
140
+ p += sizeof(BlobHeader) + bh->size;
141
+ }
142
+ }
143
+
144
+ // --------------------------------------------------------------------
145
+ // Persistence: save / load the whole arena to a file
146
+ // --------------------------------------------------------------------
147
+ bool arena_save(const ShadowArena *a, const char *filename) {
148
+ FILE *f = fopen(filename, "wb");
149
+ if (!f) return false;
150
+ size_t n = fwrite(shadow_header(a->data), 1, a->reserved, f);
151
+ fclose(f);
152
+ return n == a->reserved;
153
+ }
154
+
155
+ bool arena_load(ShadowArena *a, const char *filename) {
156
+ FILE *f = fopen(filename, "rb");
157
+ if (!f) return false;
158
+
159
+ fseek(f, 0, SEEK_END);
160
+ long size = ftell(f);
161
+ fseek(f, 0, SEEK_SET);
162
+ if (size < (long)SHADOW_SIZE) {
163
+ fclose(f);
164
+ return false;
165
+ }
166
+
167
+ void *block = malloc(size);
168
+ if (!block) { fclose(f); return false; }
169
+ if (fread(block, 1, size, f) != (size_t)size) {
170
+ free(block);
171
+ fclose(f);
172
+ return false;
173
+ }
174
+ fclose(f);
175
+
176
+ ShadowHeader *h = (ShadowHeader*)block;
177
+ if (h->tag != SHADOW_MAGIC || h->version != 1) {
178
+ free(block);
179
+ return false;
180
+ }
181
+
182
+ shadow_arena_destroy(a);
183
+ a->data = (char*)block + SHADOW_SIZE;
184
+ a->reserved = size;
185
+ return true;
186
+ }
187
+
188
+ // --------------------------------------------------------------------
189
+ // Tools
190
+ // --------------------------------------------------------------------
191
+ typedef struct {
192
+ char *name;
193
+ char *(*func)(const char *args); // returns newly allocated string
194
+ } Tool;
195
+
196
+ // tool: shell command execution
197
+ char* tool_shell(const char *args) {
198
+ FILE *fp = popen(args, "r");
199
+ if (!fp) return strdup("error: popen failed");
200
+ char *result = NULL;
201
+ size_t len = 0;
202
+ FILE *out = open_memstream(&result, &len);
203
+ char buf[256];
204
+ while (fgets(buf, sizeof(buf), fp)) fputs(buf, out);
205
+ pclose(fp);
206
+ fclose(out);
207
+ return result ? result : strdup("");
208
+ }
209
+
210
+ // tool: read file
211
+ char* tool_read_file(const char *args) {
212
+ FILE *fp = fopen(args, "rb");
213
+ if (!fp) return strdup("error: cannot open file");
214
+ char *content = NULL;
215
+ size_t len = 0;
216
+ FILE *out = open_memstream(&content, &len);
217
+ char buf[4096];
218
+ size_t n;
219
+ while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
220
+ fwrite(buf, 1, n, out);
221
+ fclose(fp);
222
+ fclose(out);
223
+ return content ? content : strdup("");
224
+ }
225
+
226
+ // tool: write file (args: "filename\ncontent")
227
+ char* tool_write_file(const char *args) {
228
+ char *filename = strdup(args);
229
+ char *newline = strchr(filename, '\n');
230
+ if (!newline) {
231
+ free(filename);
232
+ return strdup("error: missing newline separator");
233
+ }
234
+ *newline = '\0';
235
+ char *content = newline + 1;
236
+ FILE *fp = fopen(filename, "wb");
237
+ if (!fp) {
238
+ free(filename);
239
+ return strdup("error: cannot write file");
240
+ }
241
+ fwrite(content, 1, strlen(content), fp);
242
+ fclose(fp);
243
+ free(filename);
244
+ return strdup("ok");
245
+ }
246
+
247
+ // tool: HTTP GET (args = URL)
248
+ size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) {
249
+ size_t total = size * nmemb;
250
+ fwrite(ptr, 1, total, (FILE*)stream);
251
+ return total;
252
+ }
253
+ char* tool_http_get(const char *args) {
254
+ CURL *curl = curl_easy_init();
255
+ if (!curl) return strdup("error: curl init failed");
256
+
257
+ char *response = NULL;
258
+ size_t len = 0;
259
+ FILE *out = open_memstream(&response, &len);
260
+
261
+ curl_easy_setopt(curl, CURLOPT_URL, args);
262
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
263
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, out);
264
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
265
+ CURLcode res = curl_easy_perform(curl);
266
+ if (res != CURLE_OK) {
267
+ fclose(out);
268
+ curl_easy_cleanup(curl);
269
+ return strdup("error: curl failed");
270
+ }
271
+ fclose(out);
272
+ curl_easy_cleanup(curl);
273
+ return response ? response : strdup("");
274
+ }
275
+
276
+ // tool: math expression (using bc)
277
+ char* tool_math(const char *args) {
278
+ char cmd[4096];
279
+ snprintf(cmd, sizeof(cmd), "echo '%s' | bc 2>/dev/null", args);
280
+ FILE *fp = popen(cmd, "r");
281
+ if (!fp) return strdup("error: bc failed");
282
+ char *result = NULL;
283
+ size_t len = 0;
284
+ FILE *out = open_memstream(&result, &len);
285
+ char buf[256];
286
+ while (fgets(buf, sizeof(buf), fp)) fputs(buf, out);
287
+ pclose(fp);
288
+ fclose(out);
289
+ return result ? result : strdup("");
290
+ }
291
+
292
+ // tool: list directory
293
+ char* tool_list_dir(const char *args) {
294
+ DIR *d = opendir(args);
295
+ if (!d) return strdup("error: cannot open directory");
296
+ char *result = NULL;
297
+ size_t len = 0;
298
+ FILE *out = open_memstream(&result, &len);
299
+ struct dirent *entry;
300
+ while ((entry = readdir(d)) != NULL) {
301
+ fprintf(out, "%s\n", entry->d_name);
302
+ }
303
+ closedir(d);
304
+ fclose(out);
305
+ return result ? result : strdup("");
306
+ }
307
+
308
+ // tool registry
309
+ Tool tools[] = {
310
+ {"shell", tool_shell},
311
+ {"read_file", tool_read_file},
312
+ {"write_file", tool_write_file},
313
+ {"http_get", tool_http_get},
314
+ {"math", tool_math},
315
+ {"list_dir", tool_list_dir},
316
+ {NULL, NULL}
317
+ };
318
+
319
+ char* execute_tool(const char *name, const char *args) {
320
+ for (Tool *t = tools; t->name; t++) {
321
+ if (strcmp(t->name, name) == 0) {
322
+ return t->func(args);
323
+ }
324
+ }
325
+ return strdup("error: unknown tool");
326
+ }
327
+
328
+ // --------------------------------------------------------------------
329
+ // LLM interaction (Ollama)
330
+ // --------------------------------------------------------------------
331
+ typedef struct {
332
+ char *data;
333
+ size_t len;
334
+ } ResponseBuffer;
335
+
336
+ size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) {
337
+ ResponseBuffer *buf = (ResponseBuffer*)stream;
338
+ size_t total = size * nmemb;
339
+ buf->data = realloc(buf->data, buf->len + total + 1);
340
+ if (!buf->data) return 0;
341
+ memcpy(buf->data + buf->len, ptr, total);
342
+ buf->len += total;
343
+ buf->data[buf->len] = '\0';
344
+ return total;
345
+ }
346
+
347
+ // call Ollama generate endpoint, return JSON string (malloced)
348
+ char* ollama_generate(const char *prompt, const char *model, const char *endpoint) {
349
+ CURL *curl = curl_easy_init();
350
+ if (!curl) return NULL;
351
+
352
+ char url[256];
353
+ snprintf(url, sizeof(url), "%s/api/generate", endpoint);
354
+
355
+ cJSON *req_json = cJSON_CreateObject();
356
+ cJSON_AddStringToObject(req_json, "model", model);
357
+ cJSON_AddStringToObject(req_json, "prompt", prompt);
358
+ cJSON_AddBoolToObject(req_json, "stream", false);
359
+ char *req_str = cJSON_PrintUnformatted(req_json);
360
+ cJSON_Delete(req_json);
361
+
362
+ struct curl_slist *headers = NULL;
363
+ headers = curl_slist_append(headers, "Content-Type: application/json");
364
+
365
+ ResponseBuffer resp = {0};
366
+ curl_easy_setopt(curl, CURLOPT_URL, url);
367
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
368
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
369
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_str);
370
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
371
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
372
+
373
+ CURLcode res = curl_easy_perform(curl);
374
+ free(req_str);
375
+ curl_slist_free_all(headers);
376
+ curl_easy_cleanup(curl);
377
+
378
+ if (res != CURLE_OK) {
379
+ free(resp.data);
380
+ return NULL;
381
+ }
382
+ return resp.data; // caller must free
383
+ }
384
+
385
+ // --------------------------------------------------------------------
386
+ // Prompt builder (exactly as in beta10)
387
+ // --------------------------------------------------------------------
388
+ typedef struct {
389
+ char *text;
390
+ size_t cap;
391
+ size_t len;
392
+ } StringBuilder;
393
+
394
+ void sb_append(StringBuilder *sb, const char *s) {
395
+ size_t add = strlen(s);
396
+ if (sb->len + add + 1 > sb->cap) {
397
+ sb->cap = sb->cap ? sb->cap * 2 : 1024;
398
+ while (sb->len + add + 1 > sb->cap) sb->cap *= 2;
399
+ sb->text = realloc(sb->text, sb->cap);
400
+ }
401
+ memcpy(sb->text + sb->len, s, add);
402
+ sb->len += add;
403
+ sb->text[sb->len] = '\0';
404
+ }
405
+
406
+ void collect_blob(const BlobHeader *bh, const char *payload, void *user) {
407
+ StringBuilder *sb = (StringBuilder*)user;
408
+ static int count = 0;
409
+ // keep only system (kind 1) and last 10 user/assistant/tool messages
410
+ if (bh->kind == 1) {
411
+ sb_append(sb, "[System]\n");
412
+ sb_append(sb, payload);
413
+ sb_append(sb, "\n\n");
414
+ } else if (bh->kind == 2 || bh->kind == 3 || bh->kind == 5) {
415
+ if (count < 10) {
416
+ const char *role = bh->kind==2 ? "User" : (bh->kind==3 ? "Assistant" : "Tool");
417
+ sb_append(sb, "[");
418
+ sb_append(sb, role);
419
+ sb_append(sb, "]\n");
420
+ sb_append(sb, payload);
421
+ sb_append(sb, "\n\n");
422
+ count++;
423
+ }
424
+ }
425
+ }
426
+
427
+ char* build_prompt(ShadowArena *arena) {
428
+ StringBuilder sb = {0};
429
+ // include system prompt and recent conversation
430
+ blob_foreach(arena, collect_blob, &sb);
431
+ // add instructions for tool use (exactly as beta10)
432
+ sb_append(&sb,
433
+ "[Instruction]\n"
434
+ "You are ShadowClaw, a tiny AI agent. You can use tools by outputting a JSON block like:\n"
435
+ "```tool\n{\"tool\":\"name\",\"args\":\"arguments\"}\n```\n"
436
+ "Available tools: shell, read_file, write_file, http_get, math, list_dir.\n"
437
+ "After using a tool, you'll see its result. Continue the conversation.\n\n"
438
+ "[User]\n");
439
+ return sb.text; // caller must free
440
+ }
441
+
442
+ // --------------------------------------------------------------------
443
+ // Parse tool call from assistant text (look for ```tool ... ```)
444
+ // Enhanced to handle both string and array args
445
+ // --------------------------------------------------------------------
446
+ char* parse_tool_call(const char *text, char **tool_name, char **tool_args) {
447
+ const char *start = strstr(text, "```tool");
448
+ if (!start) return NULL;
449
+ start += 7; // skip ```tool
450
+ while (*start == ' ' || *start == '\n') start++;
451
+ const char *end = strstr(start, "```");
452
+ if (!end) return NULL;
453
+
454
+ size_t len = end - start;
455
+ char *json_str = malloc(len + 1);
456
+ memcpy(json_str, start, len);
457
+ json_str[len] = '\0';
458
+
459
+ cJSON *root = cJSON_Parse(json_str);
460
+ free(json_str);
461
+ if (!root) return NULL;
462
+
463
+ cJSON *name = cJSON_GetObjectItem(root, "tool");
464
+ if (!cJSON_IsString(name)) {
465
+ cJSON_Delete(root);
466
+ return NULL;
467
+ }
468
+
469
+ cJSON *args = cJSON_GetObjectItem(root, "args");
470
+ char *args_str = NULL;
471
+ if (cJSON_IsString(args)) {
472
+ args_str = strdup(args->valuestring);
473
+ } else if (cJSON_IsArray(args)) {
474
+ int count = cJSON_GetArraySize(args);
475
+ size_t total_len = 0;
476
+ for (int i = 0; i < count; i++) {
477
+ cJSON *elem = cJSON_GetArrayItem(args, i);
478
+ if (cJSON_IsString(elem)) {
479
+ if (i > 0) total_len++; // space
480
+ total_len += strlen(elem->valuestring);
481
+ }
482
+ }
483
+ args_str = malloc(total_len + 1);
484
+ if (args_str) {
485
+ args_str[0] = '\0';
486
+ for (int i = 0; i < count; i++) {
487
+ cJSON *elem = cJSON_GetArrayItem(args, i);
488
+ if (cJSON_IsString(elem)) {
489
+ if (i > 0) strcat(args_str, " ");
490
+ strcat(args_str, elem->valuestring);
491
+ }
492
+ }
493
+ } else {
494
+ args_str = strdup("");
495
+ }
496
+ } else {
497
+ args_str = strdup("");
498
+ }
499
+
500
+ *tool_name = strdup(name->valuestring);
501
+ *tool_args = args_str;
502
+ cJSON_Delete(root);
503
+ return (char*)end + 3; // pointer after the closing ```
504
+ }
505
+
506
+ // --------------------------------------------------------------------
507
+ // Main (with slash commands from v1.2.2)
508
+ // --------------------------------------------------------------------
509
+ int main(int argc, char **argv) {
510
+ const char *state_file = "shadowclaw.bin";
511
+ const char *ollama_endpoint = "http://localhost:11434";
512
+ const char *ollama_model = "qwen2.5:0.5b"; // change as needed
513
+
514
+ ShadowArena arena = shadow_arena_create(128 * 1024); // 128KB start
515
+
516
+ // load previous state if exists
517
+ if (access(state_file, F_OK) == 0) {
518
+ if (arena_load(&arena, state_file)) {
519
+ printf("[ShadowClaw] loaded state from %s\n", state_file);
520
+ } else {
521
+ printf("[ShadowClaw] failed to load %s, starting fresh\n", state_file);
522
+ }
523
+ } else {
524
+ // bootstrap system prompt (includes list_dir)
525
+ const char *sys = "You are ShadowClaw – tiny, shadowy, Unix‑punk AI agent. Use tools when helpful. Stay minimal.\n"
526
+ "Available tools: shell, read_file, write_file, http_get, math, list_dir.";
527
+ blob_append(&arena, 1, 1, sys, strlen(sys)+1);
528
+ }
529
+
530
+ uint64_t msg_id = time(NULL); // simple id
531
+
532
+ printf("ShadowClaw ready. Type your message (Ctrl-D to exit)\n");
533
+ char line[4096];
534
+ while (fgets(line, sizeof(line), stdin)) {
535
+ // remove trailing newline
536
+ line[strcspn(line, "\n")] = 0;
537
+ if (strlen(line) == 0) continue;
538
+
539
+ // ----- Slash commands (always available) -----
540
+ if (line[0] == '/') {
541
+ if (strcmp(line, "/help") == 0) {
542
+ printf("Shadowclaw commands:\n"
543
+ " /help Show this help\n"
544
+ " /tools List available tools\n"
545
+ " /state Show arena memory stats\n"
546
+ " /clear Clear conversation history (keeps system prompt)\n"
547
+ " /chat Remind you that chat mode is active\n"
548
+ " /exit Exit Shadowclaw\n");
549
+ } else if (strcmp(line, "/tools") == 0) {
550
+ printf("Available tools:\n");
551
+ for (Tool *t = tools; t->name; t++) {
552
+ printf(" %s\n", t->name);
553
+ }
554
+ } else if (strcmp(line, "/state") == 0) {
555
+ ShadowHeader *h = shadow_header(arena.data);
556
+ printf("Arena capacity: %zu bytes\n", h->capacity);
557
+ printf("Arena used: %zu bytes\n", h->length);
558
+ printf("Reserved total: %zu bytes\n", arena.reserved);
559
+ printf("Dirty flag: %d\n", h->flags & 1);
560
+ } else if (strcmp(line, "/clear") == 0) {
561
+ shadow_arena_clear(&arena);
562
+ // Re-add system prompt
563
+ const char *sys = "You are ShadowClaw – tiny, shadowy, Unix‑punk AI agent. Use tools when helpful. Stay minimal.\n"
564
+ "Available tools: shell, read_file, write_file, http_get, math, list_dir.";
565
+ blob_append(&arena, 1, 1, sys, strlen(sys)+1);
566
+ printf("Conversation cleared.\n");
567
+ } else if (strcmp(line, "/chat") == 0) {
568
+ printf("You are already in chat mode. Type your message.\n");
569
+ } else if (strcmp(line, "/exit") == 0) {
570
+ break;
571
+ } else {
572
+ printf("Unknown command. Try /help\n");
573
+ }
574
+ continue;
575
+ }
576
+
577
+ // ----- Normal LLM mode (exactly like beta10) -----
578
+ // store user message
579
+ blob_append(&arena, 2, msg_id++, line, strlen(line)+1);
580
+
581
+ // build prompt from arena
582
+ char *prompt = build_prompt(&arena);
583
+ if (!prompt) {
584
+ fprintf(stderr, "error building prompt\n");
585
+ break;
586
+ }
587
+
588
+ // call ollama
589
+ char *response_json = ollama_generate(prompt, ollama_model, ollama_endpoint);
590
+ free(prompt);
591
+ if (!response_json) {
592
+ fprintf(stderr, "LLM call failed\n");
593
+ continue;
594
+ }
595
+
596
+ // parse response
597
+ cJSON *root = cJSON_Parse(response_json);
598
+ if (!root) {
599
+ fprintf(stderr, "JSON parse error. Raw response: %s\n", response_json);
600
+ free(response_json);
601
+ continue;
602
+ }
603
+
604
+ // Check for error field (Ollama error response)
605
+ cJSON *err = cJSON_GetObjectItem(root, "error");
606
+ if (err && cJSON_IsString(err)) {
607
+ fprintf(stderr, "Ollama error: %s\n", err->valuestring);
608
+ cJSON_Delete(root);
609
+ free(response_json);
610
+ continue;
611
+ }
612
+
613
+ cJSON *resp_text = cJSON_GetObjectItem(root, "response");
614
+ if (!cJSON_IsString(resp_text)) {
615
+ fprintf(stderr, "no 'response' field in LLM output. Full JSON: %s\n", response_json);
616
+ cJSON_Delete(root);
617
+ free(response_json);
618
+ continue;
619
+ }
620
+ const char *assistant_msg = resp_text->valuestring;
621
+
622
+ // check for tool call
623
+ char *tool_name = NULL, *tool_args = NULL;
624
+ char *after_tool = parse_tool_call(assistant_msg, &tool_name, &tool_args);
625
+ if (tool_name && tool_args) {
626
+ // execute tool
627
+ char *tool_result = execute_tool(tool_name, tool_args);
628
+ // store tool call and result
629
+ blob_append(&arena, 4, msg_id++, assistant_msg, after_tool - assistant_msg);
630
+ blob_append(&arena, 5, msg_id++, tool_result, strlen(tool_result)+1);
631
+ // print result and continue (LLM will see it in next round)
632
+ printf("\n[Tool %s] → %s\n", tool_name, tool_result);
633
+ free(tool_result);
634
+ free(tool_name);
635
+ free(tool_args);
636
+ } else {
637
+ // normal assistant response
638
+ printf("\n[ShadowClaw] %s\n", assistant_msg);
639
+ blob_append(&arena, 3, msg_id++, assistant_msg, strlen(assistant_msg)+1);
640
+ }
641
+
642
+ cJSON_Delete(root);
643
+ free(response_json);
644
+
645
+ // save arena after each interaction
646
+ if (!arena_save(&arena, state_file)) {
647
+ fprintf(stderr, "warning: could not save state\n");
648
+ }
649
+ }
650
+
651
+ shadow_arena_destroy(&arena);
652
+ return 0;
653
+ }