Better argument validation
[jansson.git] / src / value.c
1 /*
2  * Copyright (c) 2009 Petri Lehtinen <petri@digip.org>
3  *
4  * Jansson is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7
8 #define _GNU_SOURCE
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include <jansson.h>
13 #include "hashtable.h"
14 #include "jansson_private.h"
15 #include "utf.h"
16 #include "util.h"
17
18 #define container_of(ptr_, type_, member_)  \
19     ((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_))
20
21 typedef struct {
22     json_t json;
23     hashtable_t hashtable;
24 } json_object_t;
25
26 typedef struct {
27     json_t json;
28     unsigned int size;
29     unsigned int entries;
30     json_t **table;
31 } json_array_t;
32
33 typedef struct {
34     json_t json;
35     char *value;
36 } json_string_t;
37
38 typedef struct {
39     json_t json;
40     double value;
41 } json_real_t;
42
43 typedef struct {
44     json_t json;
45     int value;
46 } json_integer_t;
47
48 #define json_to_object(json_)  container_of(json_, json_object_t, json)
49 #define json_to_array(json_)   container_of(json_, json_array_t, json)
50 #define json_to_string(json_)  container_of(json_, json_string_t, json)
51 #define json_to_real(json_)   container_of(json_, json_real_t, json)
52 #define json_to_integer(json_) container_of(json_, json_integer_t, json)
53
54 static inline void json_init(json_t *json, json_type type)
55 {
56     json->type = type;
57     json->refcount = 1;
58 }
59
60
61 /*** object ***/
62
63 static unsigned int hash_string(const void *key)
64 {
65     const char *str = (const char *)key;
66     unsigned int hash = 5381;
67     unsigned int c;
68
69     while((c = (unsigned int)*str))
70     {
71         hash = ((hash << 5) + hash) + c;
72         str++;
73     }
74
75     return hash;
76 }
77
78 static int string_equal(const void *key1, const void *key2)
79 {
80     return strcmp((const char *)key1, (const char *)key2) == 0;
81 }
82
83 static void value_decref(void *value)
84 {
85     json_decref((json_t *)value);
86 }
87
88 json_t *json_object(void)
89 {
90     json_object_t *object = malloc(sizeof(json_object_t));
91     if(!object)
92         return NULL;
93     json_init(&object->json, JSON_OBJECT);
94
95     if(hashtable_init(&object->hashtable, hash_string, string_equal,
96                       free, value_decref))
97     {
98         free(object);
99         return NULL;
100     }
101     return &object->json;
102 }
103
104 static void json_delete_object(json_object_t *object)
105 {
106     hashtable_close(&object->hashtable);
107     free(object);
108 }
109
110 json_t *json_object_get(const json_t *json, const char *key)
111 {
112     json_object_t *object;
113
114     if(!json_is_object(json))
115         return NULL;
116
117     object = json_to_object(json);
118     return hashtable_get(&object->hashtable, key);
119 }
120
121 int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)
122 {
123     json_object_t *object;
124
125     if(!key || !value)
126         return -1;
127
128     if(!json_is_object(json))
129     {
130         json_decref(value);
131         return -1;
132     }
133     object = json_to_object(json);
134
135     if(hashtable_set(&object->hashtable, strdup(key), value))
136     {
137         json_decref(value);
138         return -1;
139     }
140
141     return 0;
142 }
143
144 int json_object_set_nocheck(json_t *json, const char *key, json_t *value)
145 {
146     return json_object_set_new_nocheck(json, key, json_incref(value));
147 }
148
149 int json_object_set_new(json_t *json, const char *key, json_t *value)
150 {
151     if(!utf8_check_string(key, -1))
152     {
153         json_decref(value);
154         return -1;
155     }
156
157     return json_object_set_new_nocheck(json, key, value);
158 }
159
160 int json_object_del(json_t *json, const char *key)
161 {
162     json_object_t *object;
163
164     if(!json_is_object(json))
165         return -1;
166
167     object = json_to_object(json);
168     return hashtable_del(&object->hashtable, key);
169 }
170
171 void *json_object_iter(json_t *json)
172 {
173     json_object_t *object;
174
175     if(!json_is_object(json))
176         return NULL;
177
178     object = json_to_object(json);
179     return hashtable_iter(&object->hashtable);
180 }
181
182 void *json_object_iter_next(json_t *json, void *iter)
183 {
184     json_object_t *object;
185
186     if(!json_is_object(json) || iter == NULL)
187         return NULL;
188
189     object = json_to_object(json);
190     return hashtable_iter_next(&object->hashtable, iter);
191 }
192
193 const char *json_object_iter_key(void *iter)
194 {
195     if(!iter)
196         return NULL;
197
198     return (const char *)hashtable_iter_key(iter);
199 }
200
201 json_t *json_object_iter_value(void *iter)
202 {
203     if(!iter)
204         return NULL;
205
206     return (json_t *)hashtable_iter_value(iter);
207 }
208
209
210 /*** array ***/
211
212 json_t *json_array(void)
213 {
214     json_array_t *array = malloc(sizeof(json_array_t));
215     if(!array)
216       return NULL;
217     json_init(&array->json, JSON_ARRAY);
218
219     array->entries = 0;
220     array->size = 0;
221     array->table = NULL;
222
223     return &array->json;
224 }
225
226 static void json_delete_array(json_array_t *array)
227 {
228     unsigned int i;
229
230     for(i = 0; i < array->entries; i++)
231         json_decref(array->table[i]);
232
233     free(array->table);
234     free(array);
235 }
236
237 unsigned int json_array_size(const json_t *json)
238 {
239     if(!json_is_array(json))
240         return 0;
241
242     return json_to_array(json)->entries;
243 }
244
245 json_t *json_array_get(const json_t *json, unsigned int index)
246 {
247     json_array_t *array;
248     if(!json_is_array(json))
249         return NULL;
250     array = json_to_array(json);
251
252     if(index >= array->entries)
253         return NULL;
254
255     return array->table[index];
256 }
257
258 int json_array_set_new(json_t *json, unsigned int index, json_t *value)
259 {
260     json_array_t *array;
261
262     if(!value)
263         return -1;
264
265     if(!json_is_array(json))
266     {
267         json_decref(value);
268         return -1;
269     }
270     array = json_to_array(json);
271
272     if(index >= array->entries)
273     {
274         json_decref(value);
275         return -1;
276     }
277
278     json_decref(array->table[index]);
279     array->table[index] = value;
280
281     return 0;
282 }
283
284 int json_array_append_new(json_t *json, json_t *value)
285 {
286     json_array_t *array;
287
288     if(!value)
289         return -1;
290
291     if(!json_is_array(json))
292     {
293         json_decref(value);
294         return -1;
295     }
296     array = json_to_array(json);
297
298     if(array->entries == array->size) {
299         array->size = max(8, array->size * 2);
300         array->table = realloc(array->table, array->size * sizeof(json_t *));
301         if(!array->table)
302         {
303             json_decref(value);
304             return -1;
305         }
306     }
307
308     array->table[array->entries] = value;
309     array->entries++;
310
311     return 0;
312 }
313
314
315 /*** string ***/
316
317 json_t *json_string_nocheck(const char *value)
318 {
319     json_string_t *string;
320
321     if(!value)
322         return NULL;
323
324     string = malloc(sizeof(json_string_t));
325     if(!string)
326        return NULL;
327     json_init(&string->json, JSON_STRING);
328
329     string->value = strdup(value);
330     if(!string->value) {
331         free(string);
332         return NULL;
333     }
334
335     return &string->json;
336 }
337
338 json_t *json_string(const char *value)
339 {
340     if(!value || !utf8_check_string(value, -1))
341         return NULL;
342
343     return json_string_nocheck(value);
344 }
345
346 const char *json_string_value(const json_t *json)
347 {
348     if(!json_is_string(json))
349         return NULL;
350
351     return json_to_string(json)->value;
352 }
353
354 static void json_delete_string(json_string_t *string)
355 {
356     free(string->value);
357     free(string);
358 }
359
360
361 /*** integer ***/
362
363 json_t *json_integer(int value)
364 {
365     json_integer_t *integer = malloc(sizeof(json_integer_t));
366     if(!integer)
367        return NULL;
368     json_init(&integer->json, JSON_INTEGER);
369
370     integer->value = value;
371     return &integer->json;
372 }
373
374 int json_integer_value(const json_t *json)
375 {
376     if(!json_is_integer(json))
377         return 0;
378
379     return json_to_integer(json)->value;
380 }
381
382 static void json_delete_integer(json_integer_t *integer)
383 {
384     free(integer);
385 }
386
387
388 /*** real ***/
389
390 json_t *json_real(double value)
391 {
392     json_real_t *real = malloc(sizeof(json_real_t));
393     if(!real)
394        return NULL;
395     json_init(&real->json, JSON_REAL);
396
397     real->value = value;
398     return &real->json;
399 }
400
401 double json_real_value(const json_t *json)
402 {
403     if(!json_is_real(json))
404         return 0;
405
406     return json_to_real(json)->value;
407 }
408
409 static void json_delete_real (json_real_t *real)
410 {
411     free(real);
412 }
413
414
415 /*** number ***/
416
417 double json_number_value(const json_t *json)
418 {
419     if(json_is_integer(json))
420         return json_integer_value(json);
421     else if(json_is_real(json))
422         return json_real_value(json);
423     else
424         return 0.0;
425 }
426
427
428 /*** simple values ***/
429
430 json_t *json_true(void)
431 {
432     static json_t the_true = {
433         .type = JSON_TRUE,
434         .refcount = 1
435     };
436     return json_incref(&the_true);
437 }
438
439
440 json_t *json_false(void)
441 {
442     static json_t the_false = {
443         .type = JSON_FALSE,
444         .refcount = 1
445     };
446     return json_incref(&the_false);
447 }
448
449
450 json_t *json_null(void)
451 {
452     static json_t the_null = {
453         .type = JSON_NULL,
454         .refcount = 1
455     };
456     return json_incref(&the_null);
457 }
458
459
460 /*** deletion ***/
461
462 void json_delete(json_t *json)
463 {
464     if(json_is_object(json))
465         json_delete_object(json_to_object(json));
466
467     else if(json_is_array(json))
468         json_delete_array(json_to_array(json));
469
470     else if(json_is_string(json))
471         json_delete_string(json_to_string(json));
472
473     else if(json_is_integer(json))
474         json_delete_integer(json_to_integer(json));
475
476     else if(json_is_real(json))
477         json_delete_real(json_to_real(json));
478
479     /* json_delete is not called for true, false or null */
480 }