]> mj.ucw.cz Git - libucw.git/blob - ucw-json/json.c
JSON: Checks for INF/NAN moved to json_new_number()
[libucw.git] / ucw-json / json.c
1 /*
2  *      UCW JSON Library -- Data Representation
3  *
4  *      (c) 2015 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/gary.h>
12 #include <ucw/mempool.h>
13 #include <ucw-json/json.h>
14
15 #include <math.h>
16
17 static void json_init(struct json_context *js)
18 {
19   mp_save(js->pool, &js->init_state);
20   js->trivial_token = json_new_node(js, JSON_INVALID);
21 }
22
23 struct json_context *json_new(void)
24 {
25   struct mempool *mp = mp_new(4096);
26   struct json_context *js = mp_alloc_zero(mp, sizeof(*js));
27   js->pool = mp;
28   json_init(js);
29   return js;
30 }
31
32 void json_delete(struct json_context *js)
33 {
34   mp_delete(js->pool);
35 }
36
37 void json_reset(struct json_context *js)
38 {
39   struct mempool *mp = js->pool;
40   mp_restore(mp, &js->init_state);
41   bzero(js, sizeof(*js));
42   js->pool = mp;
43   json_init(js);
44 }
45
46 void json_push(struct json_context *js)
47 {
48   ASSERT(!js->next_token);
49   mp_push(js->pool);
50 }
51
52 void json_pop(struct json_context *js)
53 {
54   ASSERT(!js->next_token);
55   mp_pop(js->pool);
56 }
57
58 struct json_node *json_new_node(struct json_context *js, enum json_node_type type)
59 {
60   struct json_node *n = mp_alloc_fast(js->pool, sizeof(*n));
61   n->type = type;
62   return n;
63 }
64
65 struct json_node *json_new_number(struct json_context *js, double value)
66 {
67   ASSERT(isfinite(value));
68   struct json_node *n = json_new_node(js, JSON_NUMBER);
69   n->number = value;
70   return n;
71 }
72
73 struct json_node *json_new_array(struct json_context *js)
74 {
75   struct json_node *n = json_new_node(js, JSON_ARRAY);
76   GARY_INIT_SPACE_ALLOC(n->elements, 4, mp_get_allocator(js->pool));
77   return n;
78 }
79
80 void json_array_append(struct json_node *array, struct json_node *elt)
81 {
82   ASSERT(array->type == JSON_ARRAY);
83   *GARY_PUSH(array->elements) = elt;
84 }
85
86 struct json_node *json_new_object(struct json_context *js)
87 {
88   struct json_node *n = json_new_node(js, JSON_OBJECT);
89   GARY_INIT_SPACE_ALLOC(n->pairs, 4, mp_get_allocator(js->pool));
90   return n;
91 }
92
93 void json_object_set(struct json_node *n, const char *key, struct json_node *value)
94 {
95   for (size_t i=0; i < GARY_SIZE(n->pairs); i++)
96     if (!strcmp(n->pairs[i].key, key))
97       {
98         if (value)
99           n->pairs[i].value = value;
100         else
101           {
102             n->pairs[i] = n->pairs[GARY_SIZE(n->pairs) - 1];
103             GARY_POP(n->pairs);
104           }
105         return;
106       }
107
108   if (value)
109     {
110       struct json_pair *p = GARY_PUSH(n->pairs);
111       p->key = key;
112       p->value = value;
113     }
114 }
115
116 struct json_node *json_object_get(struct json_node *n, const char *key)
117 {
118   for (size_t i=0; i < GARY_SIZE(n->pairs); i++)
119     if (!strcmp(n->pairs[i].key, key))
120       return n->pairs[i].value;
121   return NULL;
122 }