1 /* JSON Create ZZJSON structures
2 * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
3 * License: GNU Lesser General Public License version 2.1
4 */
5
6 #include "zzjson.h"
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdarg.h>
10
11 #ifdef CONFIG_NO_ERROR_MESSAGES
12 #define ERROR(x...)
13 #else
14 #define ERROR(x...) config->error(config->ehandle, ##x)
15 #endif
16 #define MEMERROR() ERROR("out of memory")
17
zzjson_create_templ(ZZJSON_CONFIG * config,ZZJSON_TYPE type)18 static ZZJSON *zzjson_create_templ(ZZJSON_CONFIG *config, ZZJSON_TYPE type) {
19 ZZJSON *zzjson = config->calloc(1, sizeof(ZZJSON));
20 if (!zzjson) MEMERROR();
21 else zzjson->type = type;
22 return zzjson;
23 }
24
zzjson_create_true(ZZJSON_CONFIG * config)25 ZZJSON *zzjson_create_true(ZZJSON_CONFIG *config) {
26 return zzjson_create_templ(config, ZZJSON_TRUE);
27 }
28
zzjson_create_false(ZZJSON_CONFIG * config)29 ZZJSON *zzjson_create_false(ZZJSON_CONFIG *config) {
30 return zzjson_create_templ(config, ZZJSON_FALSE);
31 }
32
zzjson_create_null(ZZJSON_CONFIG * config)33 ZZJSON *zzjson_create_null(ZZJSON_CONFIG *config) {
34 return zzjson_create_templ(config, ZZJSON_NULL);
35 }
36
zzjson_create_number_d(ZZJSON_CONFIG * config,double d)37 ZZJSON *zzjson_create_number_d(ZZJSON_CONFIG *config, double d) {
38 ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_DOUBLE);
39 if (zzjson)
40 zzjson->value.number.val.dval = d;
41 return zzjson;
42 }
43
zzjson_create_number_i(ZZJSON_CONFIG * config,long long i)44 ZZJSON *zzjson_create_number_i(ZZJSON_CONFIG *config, long long i) {
45 ZZJSON *zzjson = zzjson_create_templ(config, ZZJSON_NUMBER_NEGINT);
46 if (zzjson) {
47 zzjson->type = i<0LL ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT;
48 zzjson->value.number.val.ival = llabs(i);
49 }
50 return zzjson;
51 }
52
53 /* sdup mimics strdup, but avoids having another function pointer in config */
sdup(ZZJSON_CONFIG * config,char * s)54 static char *sdup(ZZJSON_CONFIG *config, char *s) {
55 size_t slen = strlen(s)+1;
56 char *scopy = config->malloc(slen);
57
58 if (!scopy) MEMERROR();
59 else memcpy(scopy, s, slen);
60 return scopy;
61 }
62
zzjson_create_string(ZZJSON_CONFIG * config,char * s)63 ZZJSON *zzjson_create_string(ZZJSON_CONFIG *config, char *s) {
64 ZZJSON *zzjson = NULL;
65 char *scopy;
66
67 if (!(scopy = sdup(config,s))) return zzjson;
68
69 if ((zzjson = zzjson_create_templ(config, ZZJSON_STRING)))
70 zzjson->value.string.string = scopy;
71 else
72 config->free(scopy);
73
74 return zzjson;
75 }
76
zzjson_create_array(ZZJSON_CONFIG * config,...)77 ZZJSON *zzjson_create_array(ZZJSON_CONFIG *config, ...) {
78 ZZJSON *zzjson, *retval, *val;
79 va_list ap;
80
81 if (!(zzjson = zzjson_create_templ(config, ZZJSON_ARRAY))) return zzjson;
82 retval = zzjson;
83
84 va_start(ap, config);
85 val = va_arg(ap, ZZJSON *);
86 while (val) {
87 zzjson->value.array.val = val;
88 val = va_arg(ap, ZZJSON *);
89
90 if (val) {
91 ZZJSON *next = zzjson_create_templ(config, ZZJSON_ARRAY);
92 if (!next) {
93 while (retval) {
94 next = retval->next;
95 config->free(retval);
96 retval = next;
97 }
98 break;
99 }
100 zzjson->next = next;
101 zzjson = next;
102 }
103 }
104 va_end(ap);
105 return retval;
106 }
107
zzjson_create_object(ZZJSON_CONFIG * config,...)108 ZZJSON *zzjson_create_object(ZZJSON_CONFIG *config, ...) {
109 ZZJSON *zzjson, *retval, *val;
110 char *label, *labelcopy;
111 va_list ap;
112
113 if (!(zzjson = zzjson_create_templ(config, ZZJSON_OBJECT))) return zzjson;
114 retval = zzjson;
115
116 va_start(ap, config);
117 label = va_arg(ap, char *);
118 while (label) {
119 val = va_arg(ap, ZZJSON *);
120 labelcopy = sdup(config, label);
121
122 if (!labelcopy) {
123 zzjson_free(config, retval);
124 retval = NULL;
125 break;
126 }
127
128 zzjson->value.object.label = labelcopy;
129 zzjson->value.object.val = val;
130
131 label = va_arg(ap, char *);
132
133 if (label) {
134 ZZJSON *next = zzjson_create_templ(config, ZZJSON_OBJECT);
135 if (!next) {
136 while (retval) {
137 next = retval->next;
138 config->free(retval->value.object.label);
139 config->free(retval);
140 retval = next;
141 }
142 break;
143 }
144 zzjson->next = next;
145 zzjson = next;
146 }
147 }
148 va_end(ap);
149 return retval;
150 }
151
zzjson_array_prepend(ZZJSON_CONFIG * config,ZZJSON * array,ZZJSON * val)152 ZZJSON *zzjson_array_prepend(ZZJSON_CONFIG *config, ZZJSON *array,
153 ZZJSON *val) {
154 ZZJSON *zzjson;
155
156 if (!array->value.array.val) { /* empty array */
157 array->value.array.val = val;
158 return array;
159 }
160
161 zzjson = zzjson_create_templ(config, ZZJSON_ARRAY);
162 if (zzjson) {
163 zzjson->value.array.val = val;
164 zzjson->next = array;
165 }
166 return zzjson;
167 }
168
zzjson_array_append(ZZJSON_CONFIG * config,ZZJSON * array,ZZJSON * val)169 ZZJSON *zzjson_array_append(ZZJSON_CONFIG *config, ZZJSON *array,
170 ZZJSON *val) {
171 ZZJSON *retval = array, *zzjson;
172
173 if (!array->value.array.val) { /* empty array */
174 array->value.array.val = val;
175 return array;
176 }
177
178 zzjson = zzjson_create_templ(config, ZZJSON_ARRAY);
179 if (!zzjson) return NULL;
180
181 while (array->next) array = array->next;
182
183 zzjson->value.array.val = val;
184 array->next = zzjson;
185
186 return retval;
187 }
188
zzjson_object_prepend(ZZJSON_CONFIG * config,ZZJSON * object,char * label,ZZJSON * val)189 ZZJSON *zzjson_object_prepend(ZZJSON_CONFIG *config, ZZJSON *object,
190 char *label, ZZJSON *val) {
191 ZZJSON *zzjson = NULL;
192 char *labelcopy = sdup(config, label);
193
194 if (!labelcopy) return zzjson;
195
196 if (!object->value.object.label) { /* empty object */
197 object->value.object.label = labelcopy;
198 object->value.object.val = val;
199 return object;
200 }
201
202 zzjson = zzjson_create_templ(config, ZZJSON_OBJECT);
203 if (zzjson) {
204 zzjson->value.object.label = labelcopy;
205 zzjson->value.object.val = val;
206 zzjson->next = object;
207 } else {
208 config->free(labelcopy);
209 }
210 return zzjson;
211 }
212
zzjson_object_append(ZZJSON_CONFIG * config,ZZJSON * object,char * label,ZZJSON * val)213 ZZJSON *zzjson_object_append(ZZJSON_CONFIG *config, ZZJSON *object,
214 char *label, ZZJSON *val) {
215 ZZJSON *retval = object, *zzjson = NULL;
216 char *labelcopy = sdup(config, label);
217
218 if (!labelcopy) return zzjson;
219
220 if (!object->value.object.label) { /* empty object */
221 object->value.object.label = labelcopy;
222 object->value.object.val = val;
223 return object;
224 }
225
226 zzjson = zzjson_create_templ(config, ZZJSON_OBJECT);
227 if (!zzjson) {
228 config->free(labelcopy);
229 return NULL;
230 }
231
232 while (object->next) object = object->next;
233
234 zzjson->value.object.label = labelcopy;
235 zzjson->value.object.val = val;
236 object->next = zzjson;
237
238 return retval;
239 }
240
241