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