1 /* JSON Printer
2 * ZZJSON - Copyright (C) 2008 by Ivo van Poorten
3 * License: GNU Lesser General Public License version 2.1
4 */
5
6 #include "zzjson.h"
7
8 #define PRINT(fmt...) if (config->print(config->ohandle, ##fmt) < 0) return -1;
9 //#define PUTC(c) if (config->putchar(c, config->ohandle) < 0) return -1;
10 #define PUTC(c) PRINT("%c",c)
11 #define INC 4
12
print_string(ZZJSON_CONFIG * config,char * s)13 static int print_string(ZZJSON_CONFIG *config, char *s) {
14 int c, bs;
15 if (!s) return 0;
16 while ((c = *s++)) {
17 bs = 1;
18 switch (c) {
19 // case '/': // useless escape of forward slash
20 case '\\':
21 if (*s == 'u') bs = 0; // copy \uHHHH verbatim
22 break;
23 case '"': break;
24 case '\b': c = 'b'; break;
25 case '\f': c = 'f'; break;
26 case '\n': c = 'n'; break;
27 case '\r': c = 'r'; break;
28 case '\t': c = 't'; break;
29 default: bs = 0; break;
30 }
31 if (bs) PUTC('\\');
32 PUTC(c);
33 }
34 return 0;
35 }
36
zzjson_print2(ZZJSON_CONFIG * config,ZZJSON * zzjson,unsigned int indent,unsigned int objval)37 static int zzjson_print2(ZZJSON_CONFIG *config, ZZJSON *zzjson,
38 unsigned int indent, unsigned int objval) {
39 char c = 0, d = 0;
40 if (!zzjson) return -1;
41
42 switch(zzjson->type) {
43 case ZZJSON_OBJECT: c = '{'; d = '}'; break;
44 case ZZJSON_ARRAY: c = '['; d = ']'; break;
45 default: break;
46 }
47
48 if (c) PRINT("%s%*s%c", indent ? "\n" : "", indent, "", c);
49
50 while (zzjson) {
51 switch(zzjson->type) {
52 case ZZJSON_OBJECT:
53 if (zzjson->value.object.val) {
54 PRINT("\n%*s\"", indent+INC, "");
55 if (print_string(config, zzjson->value.object.label) < 0)
56 return -1;
57 PRINT("\" :");
58 if (zzjson_print2(config, zzjson->value.object.val,
59 indent+INC, 1) < 0) return -1;
60 }
61 break;
62 case ZZJSON_ARRAY:
63 if (zzjson->value.array.val)
64 if (zzjson_print2(config, zzjson->value.array.val,
65 indent+INC, 0) < 0) return -1;
66 break;
67 case ZZJSON_STRING:
68 PRINT(objval ? " \"" : "\n%*s\"", indent, "");
69 if (print_string(config, zzjson->value.string.string)<0) return -1;
70 PUTC('"');
71 break;
72 case ZZJSON_FALSE:
73 PRINT(objval ? " false" : "\n%*sfalse", indent, "");
74 break;
75 case ZZJSON_NULL:
76 PRINT(objval ? " null" : "\n%*snull", indent, "");
77 break;
78 case ZZJSON_TRUE:
79 PRINT(objval ? " true" : "\n%*strue", indent, "");
80 break;
81 case ZZJSON_NUMBER_NEGINT:
82 case ZZJSON_NUMBER_POSINT:
83 case ZZJSON_NUMBER_DOUBLE:
84 PRINT(objval ? " " : "\n%*s", indent, "");
85 if (zzjson->type == ZZJSON_NUMBER_DOUBLE) {
86 PRINT("%16.16e", zzjson->value.number.val.dval);
87 } else {
88 if (zzjson->type == ZZJSON_NUMBER_NEGINT) PUTC('-');
89 PRINT("%llu", zzjson->value.number.val.ival);
90 }
91 default:
92 break;
93 }
94 zzjson = zzjson->next;
95 if (zzjson) PUTC(',');
96 }
97
98 if (d) PRINT("\n%*s%c", indent, "", d);
99
100 return 0;
101 }
102
zzjson_print(ZZJSON_CONFIG * config,ZZJSON * zzjson)103 int zzjson_print(ZZJSON_CONFIG *config, ZZJSON *zzjson) {
104 int retval = zzjson_print2(config, zzjson, 0, 0);
105 // if (retval >= 0) retval = config->putchar('\n', config->ohandle);
106 #ifndef CONFIG_NO_ERROR_MESSAGES
107 if (retval < 0) config->error(config->ehandle, "print: unable to print");
108 #endif
109 return retval;
110 }
111