/*------------------------------------------------------------------------- * * json.c: - make json document. * * Copyright (c) 2018-2019, Postgres Professional * *------------------------------------------------------------------------- */ #include "json.h" static void json_add_indent(PQExpBuffer buf, int32 level); static void json_add_escaped(PQExpBuffer buf, const char *str); static bool add_comma = false; /* * Start or end json token. Currently it is a json object or array. * * Function modifies level value and adds indent if it appropriate. */ void json_add(PQExpBuffer buf, JsonToken type, int32 *level) { switch (type) { case JT_BEGIN_ARRAY: appendPQExpBufferChar(buf, '['); *level += 1; add_comma = false; break; case JT_END_ARRAY: *level -= 1; if (*level == 0) appendPQExpBufferChar(buf, '\n'); else json_add_indent(buf, *level); appendPQExpBufferChar(buf, ']'); add_comma = true; break; case JT_BEGIN_OBJECT: json_add_indent(buf, *level); appendPQExpBufferChar(buf, '{'); *level += 1; add_comma = false; break; case JT_END_OBJECT: *level -= 1; if (*level == 0) appendPQExpBufferChar(buf, '\n'); else json_add_indent(buf, *level); appendPQExpBufferChar(buf, '}'); add_comma = true; break; default: break; } } /* * Add json object's key. If it isn't first key we need to add a comma. */ void json_add_key(PQExpBuffer buf, const char *name, int32 level) { if (add_comma) appendPQExpBufferChar(buf, ','); json_add_indent(buf, level); json_add_escaped(buf, name); appendPQExpBufferStr(buf, ": "); add_comma = true; } /* * Add json object's key and value. If it isn't first key we need to add a * comma. */ void json_add_value(PQExpBuffer buf, const char *name, const char *value, int32 level, bool escaped) { json_add_key(buf, name, level); if (escaped) json_add_escaped(buf, value); else appendPQExpBufferStr(buf, value); } static void json_add_indent(PQExpBuffer buf, int32 level) { uint16 i; if (level == 0) return; appendPQExpBufferChar(buf, '\n'); for (i = 0; i < level; i++) appendPQExpBufferStr(buf, " "); } static void json_add_escaped(PQExpBuffer buf, const char *str) { const char *p; appendPQExpBufferChar(buf, '"'); for (p = str; *p; p++) { switch (*p) { case '\b': appendPQExpBufferStr(buf, "\\b"); break; case '\f': appendPQExpBufferStr(buf, "\\f"); break; case '\n': appendPQExpBufferStr(buf, "\\n"); break; case '\r': appendPQExpBufferStr(buf, "\\r"); break; case '\t': appendPQExpBufferStr(buf, "\\t"); break; case '"': appendPQExpBufferStr(buf, "\\\""); break; case '\\': appendPQExpBufferStr(buf, "\\\\"); break; default: if ((unsigned char) *p < ' ') appendPQExpBuffer(buf, "\\u%04x", (int) *p); else appendPQExpBufferChar(buf, *p); break; } } appendPQExpBufferChar(buf, '"'); }