xref: /aosp_15_r20/external/ltp/metadata/data_storage.h (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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