• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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