1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2019 Cyril Hrubis <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker */
5*49cdfc7eSAndroid Build Coastguard Worker
6*49cdfc7eSAndroid Build Coastguard Worker #ifndef DATA_STORAGE_H__
7*49cdfc7eSAndroid Build Coastguard Worker #define DATA_STORAGE_H__
8*49cdfc7eSAndroid Build Coastguard Worker
9*49cdfc7eSAndroid Build Coastguard Worker #include <stdarg.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
13*49cdfc7eSAndroid Build Coastguard Worker
14*49cdfc7eSAndroid Build Coastguard Worker enum data_type {
15*49cdfc7eSAndroid Build Coastguard Worker DATA_ARRAY,
16*49cdfc7eSAndroid Build Coastguard Worker DATA_HASH,
17*49cdfc7eSAndroid Build Coastguard Worker DATA_STRING,
18*49cdfc7eSAndroid Build Coastguard Worker DATA_INT,
19*49cdfc7eSAndroid Build Coastguard Worker };
20*49cdfc7eSAndroid Build Coastguard Worker
21*49cdfc7eSAndroid Build Coastguard Worker struct data_node_array {
22*49cdfc7eSAndroid Build Coastguard Worker enum data_type type;
23*49cdfc7eSAndroid Build Coastguard Worker unsigned int array_len;
24*49cdfc7eSAndroid Build Coastguard Worker unsigned int array_used;
25*49cdfc7eSAndroid Build Coastguard Worker struct data_node *array[];
26*49cdfc7eSAndroid Build Coastguard Worker };
27*49cdfc7eSAndroid Build Coastguard Worker
28*49cdfc7eSAndroid Build Coastguard Worker struct data_hash_elem {
29*49cdfc7eSAndroid Build Coastguard Worker struct data_node *node;
30*49cdfc7eSAndroid Build Coastguard Worker char *id;
31*49cdfc7eSAndroid Build Coastguard Worker };
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker struct data_node_hash {
34*49cdfc7eSAndroid Build Coastguard Worker enum data_type type;
35*49cdfc7eSAndroid Build Coastguard Worker unsigned int elems_len;
36*49cdfc7eSAndroid Build Coastguard Worker unsigned int elems_used;
37*49cdfc7eSAndroid Build Coastguard Worker struct data_hash_elem elems[];
38*49cdfc7eSAndroid Build Coastguard Worker };
39*49cdfc7eSAndroid Build Coastguard Worker
40*49cdfc7eSAndroid Build Coastguard Worker struct data_node_string {
41*49cdfc7eSAndroid Build Coastguard Worker enum data_type type;
42*49cdfc7eSAndroid Build Coastguard Worker char val[];
43*49cdfc7eSAndroid Build Coastguard Worker };
44*49cdfc7eSAndroid Build Coastguard Worker
45*49cdfc7eSAndroid Build Coastguard Worker struct data_node_int {
46*49cdfc7eSAndroid Build Coastguard Worker enum data_type type;
47*49cdfc7eSAndroid Build Coastguard Worker long val;
48*49cdfc7eSAndroid Build Coastguard Worker };
49*49cdfc7eSAndroid Build Coastguard Worker
50*49cdfc7eSAndroid Build Coastguard Worker struct data_node {
51*49cdfc7eSAndroid Build Coastguard Worker union {
52*49cdfc7eSAndroid Build Coastguard Worker enum data_type type;
53*49cdfc7eSAndroid Build Coastguard Worker struct data_node_hash hash;
54*49cdfc7eSAndroid Build Coastguard Worker struct data_node_array array;
55*49cdfc7eSAndroid Build Coastguard Worker struct data_node_string string;
56*49cdfc7eSAndroid Build Coastguard Worker struct data_node_int i;
57*49cdfc7eSAndroid Build Coastguard Worker };
58*49cdfc7eSAndroid Build Coastguard Worker };
59*49cdfc7eSAndroid Build Coastguard Worker
data_type_name(enum data_type type)60*49cdfc7eSAndroid Build Coastguard Worker static inline const char* data_type_name(enum data_type type)
61*49cdfc7eSAndroid Build Coastguard Worker {
62*49cdfc7eSAndroid Build Coastguard Worker switch (type) {
63*49cdfc7eSAndroid Build Coastguard Worker case DATA_ARRAY:
64*49cdfc7eSAndroid Build Coastguard Worker return "array";
65*49cdfc7eSAndroid Build Coastguard Worker case DATA_HASH:
66*49cdfc7eSAndroid Build Coastguard Worker return "hash";
67*49cdfc7eSAndroid Build Coastguard Worker case DATA_STRING:
68*49cdfc7eSAndroid Build Coastguard Worker return "string";
69*49cdfc7eSAndroid Build Coastguard Worker case DATA_INT:
70*49cdfc7eSAndroid Build Coastguard Worker return "int";
71*49cdfc7eSAndroid Build Coastguard Worker default:
72*49cdfc7eSAndroid Build Coastguard Worker return "???";
73*49cdfc7eSAndroid Build Coastguard Worker }
74*49cdfc7eSAndroid Build Coastguard Worker }
75*49cdfc7eSAndroid Build Coastguard Worker
data_node_string(const char * string)76*49cdfc7eSAndroid Build Coastguard Worker static inline struct data_node *data_node_string(const char *string)
77*49cdfc7eSAndroid Build Coastguard Worker {
78*49cdfc7eSAndroid Build Coastguard Worker size_t size = sizeof(struct data_node_string) + strlen(string) + 1;
79*49cdfc7eSAndroid Build Coastguard Worker struct data_node *node = malloc(size);
80*49cdfc7eSAndroid Build Coastguard Worker
81*49cdfc7eSAndroid Build Coastguard Worker if (!node)
82*49cdfc7eSAndroid Build Coastguard Worker return NULL;
83*49cdfc7eSAndroid Build Coastguard Worker
84*49cdfc7eSAndroid Build Coastguard Worker node->type = DATA_STRING;
85*49cdfc7eSAndroid Build Coastguard Worker strcpy(node->string.val, string);
86*49cdfc7eSAndroid Build Coastguard Worker
87*49cdfc7eSAndroid Build Coastguard Worker return node;
88*49cdfc7eSAndroid Build Coastguard Worker }
89*49cdfc7eSAndroid Build Coastguard Worker
data_node_int(long i)90*49cdfc7eSAndroid Build Coastguard Worker static inline struct data_node *data_node_int(long i)
91*49cdfc7eSAndroid Build Coastguard Worker {
92*49cdfc7eSAndroid Build Coastguard Worker struct data_node *node = malloc(sizeof(struct data_node_int));
93*49cdfc7eSAndroid Build Coastguard Worker
94*49cdfc7eSAndroid Build Coastguard Worker if (!node)
95*49cdfc7eSAndroid Build Coastguard Worker return NULL;
96*49cdfc7eSAndroid Build Coastguard Worker
97*49cdfc7eSAndroid Build Coastguard Worker node->type = DATA_INT;
98*49cdfc7eSAndroid Build Coastguard Worker node->i.val = i;
99*49cdfc7eSAndroid Build Coastguard Worker
100*49cdfc7eSAndroid Build Coastguard Worker return node;
101*49cdfc7eSAndroid Build Coastguard Worker }
102*49cdfc7eSAndroid Build Coastguard Worker
103*49cdfc7eSAndroid Build Coastguard Worker #define MAX_ELEMS 100
104*49cdfc7eSAndroid Build Coastguard Worker
data_node_hash(void)105*49cdfc7eSAndroid Build Coastguard Worker static inline struct data_node *data_node_hash(void)
106*49cdfc7eSAndroid Build Coastguard Worker {
107*49cdfc7eSAndroid Build Coastguard Worker size_t size = sizeof(struct data_node_hash)
108*49cdfc7eSAndroid Build Coastguard Worker + MAX_ELEMS * sizeof(struct data_hash_elem);
109*49cdfc7eSAndroid Build Coastguard Worker struct data_node *node = malloc(size);
110*49cdfc7eSAndroid Build Coastguard Worker
111*49cdfc7eSAndroid Build Coastguard Worker if (!node)
112*49cdfc7eSAndroid Build Coastguard Worker return NULL;
113*49cdfc7eSAndroid Build Coastguard Worker
114*49cdfc7eSAndroid Build Coastguard Worker node->type = DATA_HASH;
115*49cdfc7eSAndroid Build Coastguard Worker node->hash.elems_len = MAX_ELEMS;
116*49cdfc7eSAndroid Build Coastguard Worker node->hash.elems_used = 0;
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker return node;
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker
data_node_array(void)121*49cdfc7eSAndroid Build Coastguard Worker static inline struct data_node *data_node_array(void)
122*49cdfc7eSAndroid Build Coastguard Worker {
123*49cdfc7eSAndroid Build Coastguard Worker size_t size = sizeof(struct data_node_array) +
124*49cdfc7eSAndroid Build Coastguard Worker + MAX_ELEMS * sizeof(struct data_node*);
125*49cdfc7eSAndroid Build Coastguard Worker struct data_node *node = malloc(size);
126*49cdfc7eSAndroid Build Coastguard Worker
127*49cdfc7eSAndroid Build Coastguard Worker if (!node)
128*49cdfc7eSAndroid Build Coastguard Worker return NULL;
129*49cdfc7eSAndroid Build Coastguard Worker
130*49cdfc7eSAndroid Build Coastguard Worker node->type = DATA_ARRAY;
131*49cdfc7eSAndroid Build Coastguard Worker node->array.array_len = MAX_ELEMS;
132*49cdfc7eSAndroid Build Coastguard Worker node->array.array_used = 0;
133*49cdfc7eSAndroid Build Coastguard Worker
134*49cdfc7eSAndroid Build Coastguard Worker return node;
135*49cdfc7eSAndroid Build Coastguard Worker }
136*49cdfc7eSAndroid Build Coastguard Worker
data_node_hash_add(struct data_node * self,const char * id,struct data_node * payload)137*49cdfc7eSAndroid Build Coastguard Worker static inline int data_node_hash_add(struct data_node *self, const char *id, struct data_node *payload)
138*49cdfc7eSAndroid Build Coastguard Worker {
139*49cdfc7eSAndroid Build Coastguard Worker if (self->type != DATA_HASH)
140*49cdfc7eSAndroid Build Coastguard Worker return 1;
141*49cdfc7eSAndroid Build Coastguard Worker
142*49cdfc7eSAndroid Build Coastguard Worker struct data_node_hash *hash = &self->hash;
143*49cdfc7eSAndroid Build Coastguard Worker
144*49cdfc7eSAndroid Build Coastguard Worker if (hash->elems_used == hash->elems_len)
145*49cdfc7eSAndroid Build Coastguard Worker return 1;
146*49cdfc7eSAndroid Build Coastguard Worker
147*49cdfc7eSAndroid Build Coastguard Worker struct data_hash_elem *elem = &hash->elems[hash->elems_used++];
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker elem->node = payload;
150*49cdfc7eSAndroid Build Coastguard Worker elem->id = strdup(id);
151*49cdfc7eSAndroid Build Coastguard Worker
152*49cdfc7eSAndroid Build Coastguard Worker return 0;
153*49cdfc7eSAndroid Build Coastguard Worker }
154*49cdfc7eSAndroid Build Coastguard Worker
data_node_free(struct data_node * self)155*49cdfc7eSAndroid Build Coastguard Worker static inline void data_node_free(struct data_node *self)
156*49cdfc7eSAndroid Build Coastguard Worker {
157*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
158*49cdfc7eSAndroid Build Coastguard Worker
159*49cdfc7eSAndroid Build Coastguard Worker switch (self->type) {
160*49cdfc7eSAndroid Build Coastguard Worker case DATA_STRING:
161*49cdfc7eSAndroid Build Coastguard Worker case DATA_INT:
162*49cdfc7eSAndroid Build Coastguard Worker break;
163*49cdfc7eSAndroid Build Coastguard Worker case DATA_HASH:
164*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < self->hash.elems_used; i++) {
165*49cdfc7eSAndroid Build Coastguard Worker data_node_free(self->hash.elems[i].node);
166*49cdfc7eSAndroid Build Coastguard Worker free(self->hash.elems[i].id);
167*49cdfc7eSAndroid Build Coastguard Worker }
168*49cdfc7eSAndroid Build Coastguard Worker break;
169*49cdfc7eSAndroid Build Coastguard Worker case DATA_ARRAY:
170*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < self->array.array_used; i++)
171*49cdfc7eSAndroid Build Coastguard Worker data_node_free(self->array.array[i]);
172*49cdfc7eSAndroid Build Coastguard Worker break;
173*49cdfc7eSAndroid Build Coastguard Worker }
174*49cdfc7eSAndroid Build Coastguard Worker
175*49cdfc7eSAndroid Build Coastguard Worker free(self);
176*49cdfc7eSAndroid Build Coastguard Worker }
177*49cdfc7eSAndroid Build Coastguard Worker
data_node_hash_del(struct data_node * self,const char * id)178*49cdfc7eSAndroid Build Coastguard Worker static inline int data_node_hash_del(struct data_node *self, const char *id)
179*49cdfc7eSAndroid Build Coastguard Worker {
180*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
181*49cdfc7eSAndroid Build Coastguard Worker struct data_node_hash *hash = &self->hash;
182*49cdfc7eSAndroid Build Coastguard Worker
183*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < hash->elems_used; i++) {
184*49cdfc7eSAndroid Build Coastguard Worker if (!strcmp(hash->elems[i].id, id))
185*49cdfc7eSAndroid Build Coastguard Worker break;
186*49cdfc7eSAndroid Build Coastguard Worker }
187*49cdfc7eSAndroid Build Coastguard Worker
188*49cdfc7eSAndroid Build Coastguard Worker if (i >= hash->elems_used)
189*49cdfc7eSAndroid Build Coastguard Worker return 0;
190*49cdfc7eSAndroid Build Coastguard Worker
191*49cdfc7eSAndroid Build Coastguard Worker data_node_free(hash->elems[i].node);
192*49cdfc7eSAndroid Build Coastguard Worker free(hash->elems[i].id);
193*49cdfc7eSAndroid Build Coastguard Worker
194*49cdfc7eSAndroid Build Coastguard Worker hash->elems[i] = hash->elems[--hash->elems_used];
195*49cdfc7eSAndroid Build Coastguard Worker
196*49cdfc7eSAndroid Build Coastguard Worker return 1;
197*49cdfc7eSAndroid Build Coastguard Worker }
198*49cdfc7eSAndroid Build Coastguard Worker
data_node_hash_get(struct data_node * self,const char * id)199*49cdfc7eSAndroid Build Coastguard Worker static struct data_node *data_node_hash_get(struct data_node *self, const char *id)
200*49cdfc7eSAndroid Build Coastguard Worker {
201*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
202*49cdfc7eSAndroid Build Coastguard Worker struct data_node_hash *hash = &self->hash;
203*49cdfc7eSAndroid Build Coastguard Worker
204*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < hash->elems_used; i++) {
205*49cdfc7eSAndroid Build Coastguard Worker if (!strcmp(hash->elems[i].id, id))
206*49cdfc7eSAndroid Build Coastguard Worker break;
207*49cdfc7eSAndroid Build Coastguard Worker }
208*49cdfc7eSAndroid Build Coastguard Worker
209*49cdfc7eSAndroid Build Coastguard Worker if (i >= hash->elems_used)
210*49cdfc7eSAndroid Build Coastguard Worker return NULL;
211*49cdfc7eSAndroid Build Coastguard Worker
212*49cdfc7eSAndroid Build Coastguard Worker return hash->elems[i].node;
213*49cdfc7eSAndroid Build Coastguard Worker }
214*49cdfc7eSAndroid Build Coastguard Worker
data_node_array_add(struct data_node * self,struct data_node * payload)215*49cdfc7eSAndroid Build Coastguard Worker static inline int data_node_array_add(struct data_node *self, struct data_node *payload)
216*49cdfc7eSAndroid Build Coastguard Worker {
217*49cdfc7eSAndroid Build Coastguard Worker if (self->type != DATA_ARRAY)
218*49cdfc7eSAndroid Build Coastguard Worker return 1;
219*49cdfc7eSAndroid Build Coastguard Worker
220*49cdfc7eSAndroid Build Coastguard Worker struct data_node_array *array = &self->array;
221*49cdfc7eSAndroid Build Coastguard Worker
222*49cdfc7eSAndroid Build Coastguard Worker if (array->array_used == array->array_len)
223*49cdfc7eSAndroid Build Coastguard Worker return 1;
224*49cdfc7eSAndroid Build Coastguard Worker
225*49cdfc7eSAndroid Build Coastguard Worker array->array[array->array_used++] = payload;
226*49cdfc7eSAndroid Build Coastguard Worker
227*49cdfc7eSAndroid Build Coastguard Worker return 0;
228*49cdfc7eSAndroid Build Coastguard Worker }
229*49cdfc7eSAndroid Build Coastguard Worker
data_node_array_len(struct data_node * self)230*49cdfc7eSAndroid Build Coastguard Worker static inline unsigned int data_node_array_len(struct data_node *self)
231*49cdfc7eSAndroid Build Coastguard Worker {
232*49cdfc7eSAndroid Build Coastguard Worker if (self->type != DATA_ARRAY)
233*49cdfc7eSAndroid Build Coastguard Worker return 0;
234*49cdfc7eSAndroid Build Coastguard Worker
235*49cdfc7eSAndroid Build Coastguard Worker return self->array.array_used;
236*49cdfc7eSAndroid Build Coastguard Worker }
237*49cdfc7eSAndroid Build Coastguard Worker
data_print_padd(unsigned int i)238*49cdfc7eSAndroid Build Coastguard Worker static inline void data_print_padd(unsigned int i)
239*49cdfc7eSAndroid Build Coastguard Worker {
240*49cdfc7eSAndroid Build Coastguard Worker while (i-- > 0)
241*49cdfc7eSAndroid Build Coastguard Worker putchar(' ');
242*49cdfc7eSAndroid Build Coastguard Worker }
243*49cdfc7eSAndroid Build Coastguard Worker
data_node_print_(struct data_node * self,unsigned int padd)244*49cdfc7eSAndroid Build Coastguard Worker static inline void data_node_print_(struct data_node *self, unsigned int padd)
245*49cdfc7eSAndroid Build Coastguard Worker {
246*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
247*49cdfc7eSAndroid Build Coastguard Worker
248*49cdfc7eSAndroid Build Coastguard Worker switch (self->type) {
249*49cdfc7eSAndroid Build Coastguard Worker case DATA_INT:
250*49cdfc7eSAndroid Build Coastguard Worker data_print_padd(padd);
251*49cdfc7eSAndroid Build Coastguard Worker printf("%li\n", self->i.val);
252*49cdfc7eSAndroid Build Coastguard Worker break;
253*49cdfc7eSAndroid Build Coastguard Worker case DATA_STRING:
254*49cdfc7eSAndroid Build Coastguard Worker data_print_padd(padd);
255*49cdfc7eSAndroid Build Coastguard Worker printf("'%s'\n", self->string.val);
256*49cdfc7eSAndroid Build Coastguard Worker break;
257*49cdfc7eSAndroid Build Coastguard Worker case DATA_HASH:
258*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < self->hash.elems_used; i++) {
259*49cdfc7eSAndroid Build Coastguard Worker data_print_padd(padd);
260*49cdfc7eSAndroid Build Coastguard Worker printf("%s = {\n", self->hash.elems[i].id);
261*49cdfc7eSAndroid Build Coastguard Worker data_node_print_(self->hash.elems[i].node, padd+1);
262*49cdfc7eSAndroid Build Coastguard Worker data_print_padd(padd);
263*49cdfc7eSAndroid Build Coastguard Worker printf("},\n");
264*49cdfc7eSAndroid Build Coastguard Worker }
265*49cdfc7eSAndroid Build Coastguard Worker break;
266*49cdfc7eSAndroid Build Coastguard Worker case DATA_ARRAY:
267*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < self->array.array_used; i++) {
268*49cdfc7eSAndroid Build Coastguard Worker data_print_padd(padd);
269*49cdfc7eSAndroid Build Coastguard Worker printf("{\n");
270*49cdfc7eSAndroid Build Coastguard Worker data_node_print_(self->array.array[i], padd+1);
271*49cdfc7eSAndroid Build Coastguard Worker data_print_padd(padd);
272*49cdfc7eSAndroid Build Coastguard Worker printf("},\n");
273*49cdfc7eSAndroid Build Coastguard Worker }
274*49cdfc7eSAndroid Build Coastguard Worker break;
275*49cdfc7eSAndroid Build Coastguard Worker }
276*49cdfc7eSAndroid Build Coastguard Worker }
277*49cdfc7eSAndroid Build Coastguard Worker
data_node_print(struct data_node * self)278*49cdfc7eSAndroid Build Coastguard Worker static inline void data_node_print(struct data_node *self)
279*49cdfc7eSAndroid Build Coastguard Worker {
280*49cdfc7eSAndroid Build Coastguard Worker printf("{\n");
281*49cdfc7eSAndroid Build Coastguard Worker data_node_print_(self, 1);
282*49cdfc7eSAndroid Build Coastguard Worker printf("}\n");
283*49cdfc7eSAndroid Build Coastguard Worker }
284*49cdfc7eSAndroid Build Coastguard Worker
285*49cdfc7eSAndroid Build Coastguard Worker static inline void data_fprintf(FILE *f, unsigned int padd, const char *fmt, ...)
286*49cdfc7eSAndroid Build Coastguard Worker __attribute__((format (printf, 3, 4)));
287*49cdfc7eSAndroid Build Coastguard Worker
data_fprintf(FILE * f,unsigned int padd,const char * fmt,...)288*49cdfc7eSAndroid Build Coastguard Worker static inline void data_fprintf(FILE *f, unsigned int padd, const char *fmt, ...)
289*49cdfc7eSAndroid Build Coastguard Worker {
290*49cdfc7eSAndroid Build Coastguard Worker va_list va;
291*49cdfc7eSAndroid Build Coastguard Worker
292*49cdfc7eSAndroid Build Coastguard Worker while (padd-- > 0)
293*49cdfc7eSAndroid Build Coastguard Worker putc(' ', f);
294*49cdfc7eSAndroid Build Coastguard Worker
295*49cdfc7eSAndroid Build Coastguard Worker va_start(va, fmt);
296*49cdfc7eSAndroid Build Coastguard Worker vfprintf(f, fmt, va);
297*49cdfc7eSAndroid Build Coastguard Worker va_end(va);
298*49cdfc7eSAndroid Build Coastguard Worker }
299*49cdfc7eSAndroid Build Coastguard Worker
300*49cdfc7eSAndroid Build Coastguard Worker
data_fprintf_esc(FILE * f,unsigned int padd,const char * str)301*49cdfc7eSAndroid Build Coastguard Worker static inline void data_fprintf_esc(FILE *f, unsigned int padd, const char *str)
302*49cdfc7eSAndroid Build Coastguard Worker {
303*49cdfc7eSAndroid Build Coastguard Worker while (padd-- > 0)
304*49cdfc7eSAndroid Build Coastguard Worker fputc(' ', f);
305*49cdfc7eSAndroid Build Coastguard Worker
306*49cdfc7eSAndroid Build Coastguard Worker fputc('"', f);
307*49cdfc7eSAndroid Build Coastguard Worker
308*49cdfc7eSAndroid Build Coastguard Worker while (*str) {
309*49cdfc7eSAndroid Build Coastguard Worker switch (*str) {
310*49cdfc7eSAndroid Build Coastguard Worker case '\\':
311*49cdfc7eSAndroid Build Coastguard Worker fputs("\\\\", f);
312*49cdfc7eSAndroid Build Coastguard Worker break;
313*49cdfc7eSAndroid Build Coastguard Worker case '"':
314*49cdfc7eSAndroid Build Coastguard Worker fputs("\\\"", f);
315*49cdfc7eSAndroid Build Coastguard Worker break;
316*49cdfc7eSAndroid Build Coastguard Worker case '\t':
317*49cdfc7eSAndroid Build Coastguard Worker fputs(" ", f);
318*49cdfc7eSAndroid Build Coastguard Worker break;
319*49cdfc7eSAndroid Build Coastguard Worker default:
320*49cdfc7eSAndroid Build Coastguard Worker /* RFC 8259 specify chars before 0x20 as invalid */
321*49cdfc7eSAndroid Build Coastguard Worker if (*str >= 0x20)
322*49cdfc7eSAndroid Build Coastguard Worker putc(*str, f);
323*49cdfc7eSAndroid Build Coastguard Worker else
324*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr, "%s:%d: WARNING: invalid character for JSON: %x\n",
325*49cdfc7eSAndroid Build Coastguard Worker __FILE__, __LINE__, *str);
326*49cdfc7eSAndroid Build Coastguard Worker break;
327*49cdfc7eSAndroid Build Coastguard Worker }
328*49cdfc7eSAndroid Build Coastguard Worker str++;
329*49cdfc7eSAndroid Build Coastguard Worker }
330*49cdfc7eSAndroid Build Coastguard Worker
331*49cdfc7eSAndroid Build Coastguard Worker fputc('"', f);
332*49cdfc7eSAndroid Build Coastguard Worker }
333*49cdfc7eSAndroid Build Coastguard Worker
data_to_json_(struct data_node * self,FILE * f,unsigned int padd,int do_padd)334*49cdfc7eSAndroid Build Coastguard Worker static inline void data_to_json_(struct data_node *self, FILE *f, unsigned int padd, int do_padd)
335*49cdfc7eSAndroid Build Coastguard Worker {
336*49cdfc7eSAndroid Build Coastguard Worker unsigned int i;
337*49cdfc7eSAndroid Build Coastguard Worker
338*49cdfc7eSAndroid Build Coastguard Worker switch (self->type) {
339*49cdfc7eSAndroid Build Coastguard Worker case DATA_INT:
340*49cdfc7eSAndroid Build Coastguard Worker padd = do_padd ? padd : 0;
341*49cdfc7eSAndroid Build Coastguard Worker data_fprintf(f, padd, "%li", self->i.val);
342*49cdfc7eSAndroid Build Coastguard Worker break;
343*49cdfc7eSAndroid Build Coastguard Worker case DATA_STRING:
344*49cdfc7eSAndroid Build Coastguard Worker padd = do_padd ? padd : 0;
345*49cdfc7eSAndroid Build Coastguard Worker data_fprintf_esc(f, padd, self->string.val);
346*49cdfc7eSAndroid Build Coastguard Worker break;
347*49cdfc7eSAndroid Build Coastguard Worker case DATA_HASH:
348*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < self->hash.elems_used; i++) {
349*49cdfc7eSAndroid Build Coastguard Worker data_fprintf(f, padd, "\"%s\": ", self->hash.elems[i].id);
350*49cdfc7eSAndroid Build Coastguard Worker data_to_json_(self->hash.elems[i].node, f, padd+1, 0);
351*49cdfc7eSAndroid Build Coastguard Worker if (i < self->hash.elems_used - 1)
352*49cdfc7eSAndroid Build Coastguard Worker fprintf(f, ",\n");
353*49cdfc7eSAndroid Build Coastguard Worker else
354*49cdfc7eSAndroid Build Coastguard Worker fprintf(f, "\n");
355*49cdfc7eSAndroid Build Coastguard Worker }
356*49cdfc7eSAndroid Build Coastguard Worker break;
357*49cdfc7eSAndroid Build Coastguard Worker case DATA_ARRAY:
358*49cdfc7eSAndroid Build Coastguard Worker data_fprintf(f, do_padd ? padd : 0, "[\n");
359*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < self->array.array_used; i++) {
360*49cdfc7eSAndroid Build Coastguard Worker data_to_json_(self->array.array[i], f, padd+1, 1);
361*49cdfc7eSAndroid Build Coastguard Worker if (i < self->array.array_used - 1)
362*49cdfc7eSAndroid Build Coastguard Worker fprintf(f, ",\n");
363*49cdfc7eSAndroid Build Coastguard Worker else
364*49cdfc7eSAndroid Build Coastguard Worker fprintf(f, "\n");
365*49cdfc7eSAndroid Build Coastguard Worker }
366*49cdfc7eSAndroid Build Coastguard Worker data_fprintf(f, padd, "]");
367*49cdfc7eSAndroid Build Coastguard Worker break;
368*49cdfc7eSAndroid Build Coastguard Worker }
369*49cdfc7eSAndroid Build Coastguard Worker }
370*49cdfc7eSAndroid Build Coastguard Worker
data_to_json(struct data_node * self,FILE * f,unsigned int padd)371*49cdfc7eSAndroid Build Coastguard Worker static inline void data_to_json(struct data_node *self, FILE *f, unsigned int padd)
372*49cdfc7eSAndroid Build Coastguard Worker {
373*49cdfc7eSAndroid Build Coastguard Worker fprintf(f, "{\n");
374*49cdfc7eSAndroid Build Coastguard Worker data_to_json_(self, f, padd + 1, 1);
375*49cdfc7eSAndroid Build Coastguard Worker data_fprintf(f, padd, "}");
376*49cdfc7eSAndroid Build Coastguard Worker }
377*49cdfc7eSAndroid Build Coastguard Worker
378*49cdfc7eSAndroid Build Coastguard Worker #endif /* DATA_STORAGE_H__ */
379