1 /* JSON Create ZZJSON structures
2 * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
3 * License: GNU Lesser General Public License version 2.1
11 #ifdef CONFIG_NO_ERROR_MESSAGES
14 #define ERROR(x...) config->error(config->ehandle, ##x)
16 #define MEMERROR() ERROR("out of memory")
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
;
25 ZZJSON
*zzjson_create_true(ZZJSON_CONFIG
*config
) {
26 return zzjson_create_templ(config
, ZZJSON_TRUE
);
29 ZZJSON
*zzjson_create_false(ZZJSON_CONFIG
*config
) {
30 return zzjson_create_templ(config
, ZZJSON_FALSE
);
33 ZZJSON
*zzjson_create_null(ZZJSON_CONFIG
*config
) {
34 return zzjson_create_templ(config
, ZZJSON_NULL
);
37 ZZJSON
*zzjson_create_number_d(ZZJSON_CONFIG
*config
, double d
) {
38 ZZJSON
*zzjson
= zzjson_create_templ(config
, ZZJSON_NUMBER_DOUBLE
);
40 zzjson
->value
.number
.val
.dval
= d
;
44 ZZJSON
*zzjson_create_number_i(ZZJSON_CONFIG
*config
, long long i
) {
45 ZZJSON
*zzjson
= zzjson_create_templ(config
, ZZJSON_NUMBER_NEGINT
);
47 zzjson
->type
= i
<0LL ? ZZJSON_NUMBER_NEGINT
: ZZJSON_NUMBER_POSINT
;
48 zzjson
->value
.number
.val
.ival
= llabs(i
);
53 /* sdup mimics strdup, but avoids having another function pointer in config */
54 static char *sdup(ZZJSON_CONFIG
*config
, char *s
) {
55 size_t slen
= strlen(s
)+1;
56 char *scopy
= config
->malloc(slen
);
58 if (!scopy
) MEMERROR();
59 else memcpy(scopy
, s
, slen
);
63 ZZJSON
*zzjson_create_string(ZZJSON_CONFIG
*config
, char *s
) {
64 ZZJSON
*zzjson
= NULL
;
67 if (!(scopy
= sdup(config
,s
))) return zzjson
;
69 if ((zzjson
= zzjson_create_templ(config
, ZZJSON_STRING
)))
70 zzjson
->value
.string
.string
= scopy
;
77 ZZJSON
*zzjson_create_array(ZZJSON_CONFIG
*config
, ...) {
78 ZZJSON
*zzjson
, *retval
, *val
;
81 if (!(zzjson
= zzjson_create_templ(config
, ZZJSON_ARRAY
))) return zzjson
;
85 val
= va_arg(ap
, ZZJSON
*);
87 zzjson
->value
.array
.val
= val
;
88 val
= va_arg(ap
, ZZJSON
*);
91 ZZJSON
*next
= zzjson_create_templ(config
, ZZJSON_ARRAY
);
108 ZZJSON
*zzjson_create_object(ZZJSON_CONFIG
*config
, ...) {
109 ZZJSON
*zzjson
, *retval
, *val
;
110 char *label
, *labelcopy
;
113 if (!(zzjson
= zzjson_create_templ(config
, ZZJSON_OBJECT
))) return zzjson
;
116 va_start(ap
, config
);
117 label
= va_arg(ap
, char *);
119 val
= va_arg(ap
, ZZJSON
*);
120 labelcopy
= sdup(config
, label
);
123 zzjson_free(config
, retval
);
128 zzjson
->value
.object
.label
= labelcopy
;
129 zzjson
->value
.object
.val
= val
;
131 label
= va_arg(ap
, char *);
134 ZZJSON
*next
= zzjson_create_templ(config
, ZZJSON_OBJECT
);
138 config
->free(retval
->value
.object
.label
);
139 config
->free(retval
);
152 ZZJSON
*zzjson_array_prepend(ZZJSON_CONFIG
*config
, ZZJSON
*array
,
156 if (!array
->value
.array
.val
) { /* empty array */
157 array
->value
.array
.val
= val
;
161 zzjson
= zzjson_create_templ(config
, ZZJSON_ARRAY
);
163 zzjson
->value
.array
.val
= val
;
164 zzjson
->next
= array
;
169 ZZJSON
*zzjson_array_append(ZZJSON_CONFIG
*config
, ZZJSON
*array
,
171 ZZJSON
*retval
= array
, *zzjson
;
173 if (!array
->value
.array
.val
) { /* empty array */
174 array
->value
.array
.val
= val
;
178 zzjson
= zzjson_create_templ(config
, ZZJSON_ARRAY
);
179 if (!zzjson
) return NULL
;
181 while (array
->next
) array
= array
->next
;
183 zzjson
->value
.array
.val
= val
;
184 array
->next
= zzjson
;
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
);
194 if (!labelcopy
) return zzjson
;
196 if (!object
->value
.object
.label
) { /* empty object */
197 object
->value
.object
.label
= labelcopy
;
198 object
->value
.object
.val
= val
;
202 zzjson
= zzjson_create_templ(config
, ZZJSON_OBJECT
);
204 zzjson
->value
.object
.label
= labelcopy
;
205 zzjson
->value
.object
.val
= val
;
206 zzjson
->next
= object
;
208 config
->free(labelcopy
);
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
);
218 if (!labelcopy
) return zzjson
;
220 if (!object
->value
.object
.label
) { /* empty object */
221 object
->value
.object
.label
= labelcopy
;
222 object
->value
.object
.val
= val
;
226 zzjson
= zzjson_create_templ(config
, ZZJSON_OBJECT
);
228 config
->free(labelcopy
);
232 while (object
->next
) object
= object
->next
;
234 zzjson
->value
.object
.label
= labelcopy
;
235 zzjson
->value
.object
.val
= val
;
236 object
->next
= zzjson
;