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 13static 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 37static 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 103int 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