• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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