111 lines
3.6 KiB
C
111 lines
3.6 KiB
C
/* 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;
|
|
}
|