Extend array API
[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 = 8;
221
222     array->table = malloc(array->size * sizeof(json_t *));
223     if(!array->table) {
224         free(array);
225         return NULL;
226     }
227
228     return &array->json;
229 }
230
231 static void json_delete_array(json_array_t *array)
232 {
233     unsigned int i;
234
235     for(i = 0; i < array->entries; i++)
236         json_decref(array->table[i]);
237
238     free(array->table);
239     free(array);
240 }
241
242 unsigned int json_array_size(const json_t *json)
243 {
244     if(!json_is_array(json))
245         return 0;
246
247     return json_to_array(json)->entries;
248 }
249
250 json_t *json_array_get(const json_t *json, unsigned int index)
251 {
252     json_array_t *array;
253     if(!json_is_array(json))
254         return NULL;
255     array = json_to_array(json);
256
257     if(index >= array->entries)
258         return NULL;
259
260     return array->table[index];
261 }
262
263 int json_array_set_new(json_t *json, unsigned int index, json_t *value)
264 {
265     json_array_t *array;
266
267     if(!value)
268         return -1;
269
270     if(!json_is_array(json))
271     {
272         json_decref(value);
273         return -1;
274     }
275     array = json_to_array(json);
276
277     if(index >= array->entries)
278     {
279         json_decref(value);
280         return -1;
281     }
282
283     json_decref(array->table[index]);
284     array->table[index] = value;
285
286     return 0;
287 }
288
289 static void array_move(json_array_t *array, unsigned int dest,
290                        unsigned int src, unsigned int count)
291 {
292     memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *));
293 }
294
295 static void array_copy(json_t **dest, unsigned int dpos,
296                        json_t **src, unsigned int spos,
297                        unsigned int count)
298 {
299     memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *));
300 }
301
302 static json_t **json_array_grow(json_array_t *array,
303                                 unsigned int amount,
304                                 int copy)
305 {
306     unsigned int new_size;
307     json_t **old_table, **new_table;
308
309     if(array->entries + amount <= array->size)
310         return array->table;
311
312     old_table = array->table;
313
314     new_size = max(array->size + amount, array->size * 2);
315     new_table = malloc(new_size * sizeof(json_t *));
316     if(!new_table)
317         return NULL;
318
319     array->size = new_size;
320     array->table = new_table;
321
322     if(copy) {
323         array_copy(array->table, 0, old_table, 0, array->entries);
324         free(old_table);
325         return array->table;
326     }
327
328     return old_table;
329 }
330
331 int json_array_append_new(json_t *json, json_t *value)
332 {
333     json_array_t *array;
334
335     if(!value)
336         return -1;
337
338     if(!json_is_array(json))
339     {
340         json_decref(value);
341         return -1;
342     }
343     array = json_to_array(json);
344
345     if(!json_array_grow(array, 1, 1)) {
346         json_decref(value);
347         return -1;
348     }
349
350     array->table[array->entries] = value;
351     array->entries++;
352
353     return 0;
354 }
355
356 int json_array_insert_new(json_t *json, unsigned int index, json_t *value)
357 {
358     json_array_t *array;
359     json_t **old_table;
360
361     if(!value)
362         return -1;
363
364     if(!json_is_array(json)) {
365         json_decref(value);
366         return -1;
367     }
368     array = json_to_array(json);
369
370     if(index > array->entries) {
371         json_decref(value);
372         return -1;
373     }
374
375     old_table = json_array_grow(array, 1, 0);
376     if(!old_table) {
377         json_decref(value);
378         return -1;
379     }
380
381     if(old_table != array->table) {
382         array_copy(array->table, 0, old_table, 0, index);
383         array_copy(array->table, index + 1, old_table, index,
384                    array->entries - index);
385         free(old_table);
386     }
387     else
388         array_move(array, index + 1, index, array->entries - index);
389
390     array->table[index] = value;
391     array->entries++;
392
393     return 0;
394 }
395
396 int json_array_remove(json_t *json, unsigned int index)
397 {
398     json_array_t *array;
399
400     if(!json_is_array(json))
401         return -1;
402     array = json_to_array(json);
403
404     if(index >= array->entries)
405         return -1;
406
407     json_decref(array->table[index]);
408
409     array_move(array, index, index + 1, array->entries - index);
410     array->entries--;
411
412     return 0;
413 }
414
415 int json_array_clear(json_t *json)
416 {
417     json_array_t *array;
418     unsigned int i;
419
420     if(!json_is_array(json))
421         return -1;
422     array = json_to_array(json);
423
424     for(i = 0; i < array->entries; i++)
425         json_decref(array->table[i]);
426
427     array->entries = 0;
428     return 0;
429 }
430
431 int json_array_extend(json_t *json, json_t *other_json)
432 {
433     json_array_t *array, *other;
434     unsigned int i;
435
436     if(!json_is_array(json) || !json_is_array(other_json))
437         return -1;
438     array = json_to_array(json);
439     other = json_to_array(other_json);
440
441     if(!json_array_grow(array, other->entries, 1))
442         return -1;
443
444     for(i = 0; i < other->entries; i++)
445         json_incref(other->table[i]);
446
447     array_copy(array->table, array->entries, other->table, 0, other->entries);
448
449     array->entries += other->entries;
450     return 0;
451 }
452
453
454 /*** string ***/
455
456 json_t *json_string_nocheck(const char *value)
457 {
458     json_string_t *string;
459
460     if(!value)
461         return NULL;
462
463     string = malloc(sizeof(json_string_t));
464     if(!string)
465        return NULL;
466     json_init(&string->json, JSON_STRING);
467
468     string->value = strdup(value);
469     if(!string->value) {
470         free(string);
471         return NULL;
472     }
473
474     return &string->json;
475 }
476
477 json_t *json_string(const char *value)
478 {
479     if(!value || !utf8_check_string(value, -1))
480         return NULL;
481
482     return json_string_nocheck(value);
483 }
484
485 const char *json_string_value(const json_t *json)
486 {
487     if(!json_is_string(json))
488         return NULL;
489
490     return json_to_string(json)->value;
491 }
492
493 static void json_delete_string(json_string_t *string)
494 {
495     free(string->value);
496     free(string);
497 }
498
499
500 /*** integer ***/
501
502 json_t *json_integer(int value)
503 {
504     json_integer_t *integer = malloc(sizeof(json_integer_t));
505     if(!integer)
506        return NULL;
507     json_init(&integer->json, JSON_INTEGER);
508
509     integer->value = value;
510     return &integer->json;
511 }
512
513 int json_integer_value(const json_t *json)
514 {
515     if(!json_is_integer(json))
516         return 0;
517
518     return json_to_integer(json)->value;
519 }
520
521 static void json_delete_integer(json_integer_t *integer)
522 {
523     free(integer);
524 }
525
526
527 /*** real ***/
528
529 json_t *json_real(double value)
530 {
531     json_real_t *real = malloc(sizeof(json_real_t));
532     if(!real)
533        return NULL;
534     json_init(&real->json, JSON_REAL);
535
536     real->value = value;
537     return &real->json;
538 }
539
540 double json_real_value(const json_t *json)
541 {
542     if(!json_is_real(json))
543         return 0;
544
545     return json_to_real(json)->value;
546 }
547
548 static void json_delete_real (json_real_t *real)
549 {
550     free(real);
551 }
552
553
554 /*** number ***/
555
556 double json_number_value(const json_t *json)
557 {
558     if(json_is_integer(json))
559         return json_integer_value(json);
560     else if(json_is_real(json))
561         return json_real_value(json);
562     else
563         return 0.0;
564 }
565
566
567 /*** simple values ***/
568
569 json_t *json_true(void)
570 {
571     static json_t the_true = {
572         .type = JSON_TRUE,
573         .refcount = (unsigned int)1
574     };
575     return &the_true;
576 }
577
578
579 json_t *json_false(void)
580 {
581     static json_t the_false = {
582         .type = JSON_FALSE,
583         .refcount = (unsigned int)1
584     };
585     return &the_false;
586 }
587
588
589 json_t *json_null(void)
590 {
591     static json_t the_null = {
592         .type = JSON_NULL,
593         .refcount = (unsigned int)1
594     };
595     return &the_null;
596 }
597
598
599 /*** deletion ***/
600
601 void json_delete(json_t *json)
602 {
603     if(json_is_object(json))
604         json_delete_object(json_to_object(json));
605
606     else if(json_is_array(json))
607         json_delete_array(json_to_array(json));
608
609     else if(json_is_string(json))
610         json_delete_string(json_to_string(json));
611
612     else if(json_is_integer(json))
613         json_delete_integer(json_to_integer(json));
614
615     else if(json_is_real(json))
616         json_delete_real(json_to_real(json));
617
618     /* json_delete is not called for true, false or null */
619 }