static int json_append(bstr *b, const struct mpv_node *src, int indent) { switch (src->format) { case MPV_FORMAT_NONE: APPEND(b, "null"); return 0; case MPV_FORMAT_FLAG: APPEND(b, src->u.flag ? "true" : "false"); return 0; case MPV_FORMAT_INT64: bstr_xappend_asprintf(NULL, b, "%"PRId64, src->u.int64); return 0; case MPV_FORMAT_DOUBLE: bstr_xappend_asprintf(NULL, b, "%f", src->u.double_); return 0; case MPV_FORMAT_STRING: write_json_str(b, src->u.string); return 0; case MPV_FORMAT_NODE_ARRAY: case MPV_FORMAT_NODE_MAP: { struct mpv_node_list *list = src->u.list; bool is_obj = src->format == MPV_FORMAT_NODE_MAP; APPEND(b, is_obj ? "{" : "["); int next_indent = indent >= 0 ? indent + 1 : -1; for (int n = 0; n < list->num; n++) { if (n) APPEND(b, ","); add_indent(b, next_indent); if (is_obj) { write_json_str(b, list->keys[n]); APPEND(b, ":"); } json_append(b, &list->values[n], next_indent); } add_indent(b, indent); APPEND(b, is_obj ? "}" : "]"); return 0; } } return -1; // unknown format }
static void write_json_str(bstr *b, unsigned char *str) { APPEND(b, "\""); while (1) { unsigned char *cur = str; while (cur[0] >= 32 && cur[0] != '"' && cur[0] != '\\') cur++; if (!cur[0]) break; bstr_xappend(NULL, b, (bstr){str, cur - str}); if (cur[0] == '\"') { bstr_xappend(NULL, b, (bstr){"\\\"", 2}); } else if (cur[0] == '\\') { bstr_xappend(NULL, b, (bstr){"\\\\", 2}); } else if (cur[0] < sizeof(special_escape) && special_escape[cur[0]]) { bstr_xappend_asprintf(NULL, b, "\\%c", special_escape[cur[0]]); } else { bstr_xappend_asprintf(NULL, b, "\\u%04x", (unsigned char)cur[0]); } str = cur + 1; } APPEND(b, str); APPEND(b, "\""); }
static void write_json_str(bstr *b, char *str) { APPEND(b, "\""); while (1) { char *cur = str; while (cur[0] && cur[0] >= 32 && cur[0] != '"' && cur[0] != '\\') cur++; if (!cur[0]) break; bstr_xappend(NULL, b, (bstr){str, cur - str}); bstr_xappend_asprintf(NULL, b, "\\u%04x", (unsigned char)cur[0]); str = cur + 1; } APPEND(b, str); APPEND(b, "\""); }