Rather than depending on yajl bits for creating the JSON structure replace it by few virBuffer bits. This will make the JSON formatter libary agnostic. Additionally remove the debug statement from the worker function since it was not very useful. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/util/virjson.c | 188 ++++++++++++++++++++++++++++------------------------- 1 file changed, 101 insertions(+), 87 deletions(-) diff --git a/src/util/virjson.c b/src/util/virjson.c index 6a02ddf0cc..772a205e9e 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -1834,144 +1834,158 @@ virJSONValueFromString(const char *jsonstring) return ret; } +#else +virJSONValuePtr +virJSONValueFromString(const char *jsonstring ATTRIBUTE_UNUSED) +{ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No JSON parser implementation is available")); + return NULL; +} +#endif + + +static void +virJSONValueToStringAddString(virBufferPtr buf, + virJSONValuePtr string) +{ + const char *t; + + virBufferAddLit(buf, "\""); + + for (t = string->data.string; *t; t++) { + switch (*t) { + case '"': + virBufferAddLit(buf, "\\\""); + break; + case '\\': + virBufferAddLit(buf, "\\\\"); + break; + case '\n': + virBufferAddLit(buf, "\\n"); + break; + case '\t': + virBufferAddLit(buf, "\\t"); + break; + default: + virBufferAdd(buf, t, 1); + break; + } + } + + virBufferAddLit(buf, "\""); +} + + +#define VIR_JSON_PRETTY_NEWLINE \ + if (pretty) \ + virBufferAddLit(buf, "\n") static int virJSONValueToStringOne(virJSONValuePtr object, - yajl_gen g) + virBufferPtr buf, + bool pretty) { size_t i; - VIR_DEBUG("object=%p type=%d gen=%p", object, object->type, g); - - switch (object->type) { + switch ((virJSONType) object->type) { case VIR_JSON_TYPE_OBJECT: - if (yajl_gen_map_open(g) != yajl_gen_status_ok) - return -1; + virBufferAddLit(buf, "{"); + VIR_JSON_PRETTY_NEWLINE; + virBufferAdjustIndent(buf, 2); + for (i = 0; i < object->data.object.npairs; i++) { - if (yajl_gen_string(g, - (unsigned char *)object->data.object.pairs[i].key, - strlen(object->data.object.pairs[i].key)) - != yajl_gen_status_ok) - return -1; - if (virJSONValueToStringOne(object->data.object.pairs[i].value, g) < 0) + virBufferStrcat(buf, "\"", object->data.object.pairs[i].key, "\":", NULL); + + if (pretty) + virBufferAddLit(buf, " "); + + if (virJSONValueToStringOne(object->data.object.pairs[i].value, + buf, pretty) < 0) return -1; + + if (i != object->data.object.npairs - 1) { + virBufferAddLit(buf, ","); + VIR_JSON_PRETTY_NEWLINE; + } } - if (yajl_gen_map_close(g) != yajl_gen_status_ok) - return -1; + + virBufferAdjustIndent(buf, -2); + VIR_JSON_PRETTY_NEWLINE; + virBufferAddLit(buf, "}"); break; + case VIR_JSON_TYPE_ARRAY: - if (yajl_gen_array_open(g) != yajl_gen_status_ok) - return -1; + virBufferAddLit(buf, "["); + VIR_JSON_PRETTY_NEWLINE; + virBufferAdjustIndent(buf, 2); + for (i = 0; i < object->data.array.nvalues; i++) { - if (virJSONValueToStringOne(object->data.array.values[i], g) < 0) + if (virJSONValueToStringOne(object->data.array.values[i], buf, pretty) < 0) return -1; + + if (i != object->data.array.nvalues - 1) { + virBufferAddLit(buf, ","); + VIR_JSON_PRETTY_NEWLINE; + } } - if (yajl_gen_array_close(g) != yajl_gen_status_ok) - return -1; + + virBufferAdjustIndent(buf, -2); + VIR_JSON_PRETTY_NEWLINE; + virBufferAddLit(buf, "]"); break; case VIR_JSON_TYPE_STRING: - if (yajl_gen_string(g, (unsigned char *)object->data.string, - strlen(object->data.string)) != yajl_gen_status_ok) - return -1; + virJSONValueToStringAddString(buf, object); break; case VIR_JSON_TYPE_NUMBER: - if (yajl_gen_number(g, object->data.number, - strlen(object->data.number)) != yajl_gen_status_ok) - return -1; + virBufferAdd(buf, object->data.number, -1); break; case VIR_JSON_TYPE_BOOLEAN: - if (yajl_gen_bool(g, object->data.boolean) != yajl_gen_status_ok) - return -1; + if (object->data.boolean) + virBufferAddLit(buf, "true"); + else + virBufferAddLit(buf, "false"); break; case VIR_JSON_TYPE_NULL: - if (yajl_gen_null(g) != yajl_gen_status_ok) - return -1; + virBufferAddLit(buf, "null"); break; default: + virReportEnumRangeError(virJSONType, object->type); return -1; } return 0; } +#undef VIR_JSON_PRETTY_NEWLINE + char * virJSONValueToString(virJSONValuePtr object, bool pretty) { - yajl_gen g; - const unsigned char *str; + virBuffer buf = VIR_BUFFER_INITIALIZER; char *ret = NULL; - yajl_size_t len; -# ifndef WITH_YAJL2 - yajl_gen_config conf = { pretty ? 1 : 0, pretty ? " " : " "}; -# endif VIR_DEBUG("object=%p", object); -# ifdef WITH_YAJL2 - g = yajl_gen_alloc(NULL); - if (g) { - yajl_gen_config(g, yajl_gen_beautify, pretty ? 1 : 0); - yajl_gen_config(g, yajl_gen_indent_string, pretty ? " " : " "); - yajl_gen_config(g, yajl_gen_validate_utf8, 1); - } -# else - g = yajl_gen_alloc(&conf, NULL); -# endif - if (!g) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Unable to create JSON formatter")); - goto cleanup; - } - - if (virJSONValueToStringOne(object, g) < 0) { - virReportOOMError(); - goto cleanup; - } - - if (yajl_gen_get_buf(g, &str, &len) != yajl_gen_status_ok) { - virReportOOMError(); - goto cleanup; + if (virJSONValueToStringOne(object, &buf, pretty) < 0 || + virBufferCheckError(&buf) < 0) { + virBufferFreeAndReset(&buf); + return NULL; } - ignore_value(VIR_STRDUP(ret, (const char *)str)); - - cleanup: - yajl_gen_free(g); - - VIR_DEBUG("result=%s", NULLSTR(ret)); - + ret = virBufferContentAndReset(&buf); + VIR_DEBUG("result=%s", ret); return ret; } -#else -virJSONValuePtr -virJSONValueFromString(const char *jsonstring ATTRIBUTE_UNUSED) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("No JSON parser implementation is available")); - return NULL; -} - - -char * -virJSONValueToString(virJSONValuePtr object ATTRIBUTE_UNUSED, - bool pretty ATTRIBUTE_UNUSED) -{ - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("No JSON parser implementation is available")); - return NULL; -} -#endif - - /** * virJSONStringReformat: * @jsonstr: string to reformat -- 2.14.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list