/* JSON Printer * ZZJSON - Copyright (C) 2008 by Ivo van Poorten * License: GNU Lesser General Public License version 2.1 */ #include "zzjson.h" #define PRINT(fmt...) if (config->print(config->ohandle, ##fmt) < 0) return -1; //#define PUTC(c) if (config->putchar(c, config->ohandle) < 0) return -1; #define PUTC(c) PRINT("%c",c) #define INC 4 static int print_string(ZZJSON_CONFIG *config, char *s) { int c, bs; if (!s) return 0; while ((c = *s++)) { bs = 1; switch (c) { // case '/': // useless escape of forward slash case '\\': if (*s == 'u') bs = 0; // copy \uHHHH verbatim break; case '"': break; case '\b': c = 'b'; break; case '\f': c = 'f'; break; case '\n': c = 'n'; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; default: bs = 0; break; } if (bs) PUTC('\\'); PUTC(c); } return 0; } static int zzjson_print2(ZZJSON_CONFIG *config, ZZJSON *zzjson, unsigned int indent, unsigned int objval) { char c = 0, d = 0; if (!zzjson) return -1; switch(zzjson->type) { case ZZJSON_OBJECT: c = '{'; d = '}'; break; case ZZJSON_ARRAY: c = '['; d = ']'; break; default: break; } if (c) PRINT("%s%*s%c", indent ? "\n" : "", indent, "", c); while (zzjson) { switch(zzjson->type) { case ZZJSON_OBJECT: if (zzjson->value.object.val) { PRINT("\n%*s\"", indent+INC, ""); if (print_string(config, zzjson->value.object.label) < 0) return -1; PRINT("\" :"); if (zzjson_print2(config, zzjson->value.object.val, indent+INC, 1) < 0) return -1; } break; case ZZJSON_ARRAY: if (zzjson->value.array.val) if (zzjson_print2(config, zzjson->value.array.val, indent+INC, 0) < 0) return -1; break; case ZZJSON_STRING: PRINT(objval ? " \"" : "\n%*s\"", indent, ""); if (print_string(config, zzjson->value.string.string)<0) return -1; PUTC('"'); break; case ZZJSON_FALSE: PRINT(objval ? " false" : "\n%*sfalse", indent, ""); break; case ZZJSON_NULL: PRINT(objval ? " null" : "\n%*snull", indent, ""); break; case ZZJSON_TRUE: PRINT(objval ? " true" : "\n%*strue", indent, ""); break; case ZZJSON_NUMBER_NEGINT: case ZZJSON_NUMBER_POSINT: case ZZJSON_NUMBER_DOUBLE: PRINT(objval ? " " : "\n%*s", indent, ""); if (zzjson->type == ZZJSON_NUMBER_DOUBLE) { PRINT("%16.16e", zzjson->value.number.val.dval); } else { if (zzjson->type == ZZJSON_NUMBER_NEGINT) PUTC('-'); PRINT("%llu", zzjson->value.number.val.ival); } default: break; } zzjson = zzjson->next; if (zzjson) PUTC(','); } if (d) PRINT("\n%*s%c", indent, "", d); return 0; } int zzjson_print(ZZJSON_CONFIG *config, ZZJSON *zzjson) { int retval = zzjson_print2(config, zzjson, 0, 0); // if (retval >= 0) retval = config->putchar('\n', config->ohandle); #ifndef CONFIG_NO_ERROR_MESSAGES if (retval < 0) config->error(config->ehandle, "print: unable to print"); #endif return retval; }