d3302037b9c26219dd445f03cb04596dbdcafa2b
[jansson.git] / src / value.c
1 #define _GNU_SOURCE
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include <jansson.h>
6 #include "hashtable.h"
7
8 #define max(a, b)  ((a) > (b) ? (a) : (b))
9
10 #define container_of(ptr_, type_, member_)  \
11     ((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_))
12
13 typedef struct {
14     json_t json;
15     hashtable_t *hashtable;
16 } json_object_t;
17
18 typedef struct {
19     json_t json;
20     unsigned int size;
21     unsigned int entries;
22     json_t **table;
23 } json_array_t;
24
25 typedef struct {
26     json_t json;
27     char *value;
28 } json_string_t;
29
30 typedef struct {
31     json_t json;
32     double value;
33 } json_number_t;
34
35 #define json_to_object(json_)  container_of(json_, json_object_t, json)
36 #define json_to_array(json_)   container_of(json_, json_array_t, json)
37 #define json_to_string(json_)  container_of(json_, json_string_t, json)
38 #define json_to_number(json_)  container_of(json_, json_number_t, json)
39
40 static inline void json_init(json_t *json, json_type type)
41 {
42     json->type = type;
43     json->refcount = 1;
44 }
45
46
47 /*** object ***/
48
49 static unsigned int hash_string(const void *key)
50 {
51     const char *str = (const char *)key;
52     unsigned int hash = 5381;
53     unsigned int c;
54
55     while((c = (unsigned int)*str))
56     {
57         hash = ((hash << 5) + hash) + c;
58         str++;
59     }
60
61     return hash;
62 }
63
64 static int string_equal(const void *key1, const void *key2)
65 {
66     return strcmp((const char *)key1, (const char *)key2) == 0;
67 }
68
69 static void value_decref(void *value)
70 {
71     json_decref((json_t *)value);
72 }
73
74 json_t *json_object(void)
75 {
76     json_object_t *object = malloc(sizeof(json_object_t));
77     if(!object)
78         return NULL;
79     json_init(&object->json, JSON_OBJECT);
80
81     object->hashtable =
82       hashtable_new(hash_string, string_equal, free, value_decref);
83     if(!object->hashtable)
84     {
85         free(object);
86         return NULL;
87     }
88     return &object->json;
89 }
90
91 static void json_delete_object(json_object_t *object)
92 {
93     hashtable_free(object->hashtable);
94     free(object);
95 }
96
97 json_t *json_object_get(const json_t *json, const char *key)
98 {
99     json_object_t *object;
100
101     if(!json_is_object(json))
102         return NULL;
103
104     return hashtable_get(object->hashtable, key);
105 }
106
107 int json_object_set(json_t *json, const char *key, json_t *value)
108 {
109     json_object_t *object;
110
111     if(!json_is_object(json))
112         return -1;
113
114     object = json_to_object(json);
115     return hashtable_set(object->hashtable, strdup(key), json_incref(value));
116 }
117
118 int json_object_del(json_t *json, const char *key)
119 {
120     json_object_t *object;
121
122     if(!json_is_object(json))
123         return -1;
124
125     object = json_to_object(json);
126     return hashtable_del(object->hashtable, key);
127 }
128
129 void *json_object_iter(json_t *json)
130 {
131     json_object_t *object;
132
133     if(!json_is_object(json))
134         return NULL;
135
136     object = json_to_object(json);
137     return hashtable_iter(object->hashtable);
138 }
139
140 void *json_object_iter_next(json_t *json, void *iter)
141 {
142     json_object_t *object;
143
144     if(!json_is_object(json) || iter == NULL)
145         return NULL;
146
147     object = json_to_object(json);
148     return hashtable_iter_next(object->hashtable, iter);
149 }
150
151 const char *json_object_iter_key(void *iter)
152 {
153     if(!iter)
154         return NULL;
155
156     return (const char *)hashtable_iter_key(iter);
157 }
158
159 json_t *json_object_iter_value(void *iter)
160 {
161     if(!iter)
162         return NULL;
163
164     return (json_t *)hashtable_iter_value(iter);
165 }
166
167
168 /*** array ***/
169
170 json_t *json_array(void)
171 {
172     json_array_t *array = malloc(sizeof(json_array_t));
173     if(!array)
174       return NULL;
175     json_init(&array->json, JSON_ARRAY);
176
177     array->entries = 0;
178     array->size = 0;
179     array->table = NULL;
180
181     return &array->json;
182 }
183
184 static void json_delete_array(json_array_t *array)
185 {
186     unsigned int i;
187
188     for(i = 0; i < array->entries; i++)
189         json_decref(array->table[i]);
190
191     free(array->table);
192     free(array);
193 }
194
195 unsigned int json_array_size(const json_t *json)
196 {
197     if(!json_is_array(json))
198         return 0;
199
200     return json_to_array(json)->entries;
201 }
202
203 json_t *json_array_get(const json_t *json, unsigned int index)
204 {
205     json_array_t *array;
206     if(!json_is_array(json))
207         return NULL;
208     array = json_to_array(json);
209
210     if(index >= array->size)
211         return NULL;
212
213     return array->table[index];
214 }
215
216 int json_array_set(json_t *json, unsigned int index, json_t *value)
217 {
218     json_array_t *array;
219     if(!json_is_array(json))
220         return -1;
221     array = json_to_array(json);
222
223     if(index >= array->size)
224         return -1;
225
226     array->table[index] = json_incref(value);
227     return 0;
228 }
229
230 int json_array_append(json_t *json, json_t *value)
231 {
232     json_array_t *array;
233     if(!json_is_array(json))
234         return -1;
235     array = json_to_array(json);
236
237     if(array->entries == array->size) {
238         array->size = max(8, array->size * 2);
239         array->table = realloc(array->table, array->size * sizeof(json_t *));
240         if(!array->table)
241             return -1;
242     }
243
244     array->table[array->entries] = json_incref(value);
245     array->entries++;
246
247     return 0;
248 }
249
250
251 /*** string ***/
252
253 json_t *json_string(const char *value)
254 {
255     json_string_t *string = malloc(sizeof(json_string_t));
256     if(!string)
257        return NULL;
258     json_init(&string->json, JSON_STRING);
259
260     string->value = strdup(value);
261     return &string->json;
262 }
263
264 const char *json_string_value(const json_t *json)
265 {
266     if(!json_is_string(json))
267         return NULL;
268
269     return json_to_string(json)->value;
270 }
271
272 static void json_delete_string(json_string_t *string)
273 {
274     free(string->value);
275     free(string);
276 }
277
278 json_t *json_number(double value)
279 {
280     json_number_t *number = malloc(sizeof(json_number_t));
281     if(!number)
282        return NULL;
283     json_init(&number->json, JSON_NUMBER);
284
285     number->value = value;
286     return &number->json;
287 }
288
289
290 /*** number ***/
291
292 double json_number_value(const json_t *json)
293 {
294     if(!json_is_number(json))
295         return 0.0;
296
297     return json_to_number(json)->value;
298 }
299
300 static void json_delete_number(json_number_t *number)
301 {
302     free(number);
303 }
304
305
306 /*** simple values ***/
307
308 json_t *json_true(void)
309 {
310     static json_t the_true = {
311         .type = JSON_TRUE,
312         .refcount = 1
313     };
314     return json_incref(&the_true);
315 }
316
317
318 json_t *json_false(void)
319 {
320     static json_t the_false = {
321         .type = JSON_FALSE,
322         .refcount = 1
323     };
324     return json_incref(&the_false);
325 }
326
327
328 json_t *json_null(void)
329 {
330     static json_t the_null = {
331         .type = JSON_NULL,
332         .refcount = 1
333     };
334     return json_incref(&the_null);
335 }
336
337
338 /*** deletion ***/
339
340 void json_delete(json_t *json)
341 {
342     if(json_is_object(json))
343         json_delete_object(json_to_object(json));
344
345     else if(json_is_array(json))
346         json_delete_array(json_to_array(json));
347
348     else if(json_is_string(json))
349         json_delete_string(json_to_string(json));
350
351     else if(json_is_number(json))
352         json_delete_number(json_to_number(json));
353
354     /* json_delete is not called for true, false or null */
355 }