Home | History | Annotate | Download | only in zzjson
      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 
     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 
     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 
    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