diff options
Diffstat (limited to 'usr/src/lib/libnvpair/nvpair_json.c')
| -rw-r--r-- | usr/src/lib/libnvpair/nvpair_json.c | 366 |
1 files changed, 238 insertions, 128 deletions
diff --git a/usr/src/lib/libnvpair/nvpair_json.c b/usr/src/lib/libnvpair/nvpair_json.c index 7ebd1be7a0..559010bd51 100644 --- a/usr/src/lib/libnvpair/nvpair_json.c +++ b/usr/src/lib/libnvpair/nvpair_json.c @@ -9,7 +9,7 @@ * http://www.illumos.org/license/CDDL. */ /* - * Copyright (c) 2014, Joyent, Inc. + * Copyright (c) 2017, Joyent, Inc. */ #include <stdio.h> @@ -29,6 +29,35 @@ return (-1); \ } while (0) +#define FPRINTF_JSON_ARRAY(val, valsz, func, level, indent, bufp, \ + blen, offp) \ + do { \ + int i, j; \ + FPRINTF(bufp, blen, offp, "["); \ + for (i = 0; i < valsz; i++) { \ + if (i > 0) { \ + FPRINTF(bufp, blen, offp, ","); \ + } \ + if (indent != NULL) { \ + FPRINTF(bufp, blen, offp, "\n"); \ + for (j = 0; j <= level + 1; j++) \ + FPRINTF(bufp, blen, offp, \ + "%s", indent); \ + } \ + if (func(val[i], bufp, blen, offp) == -1) { \ + return (-1); \ + } \ + } \ + if (indent != NULL) { \ + FPRINTF(bufp, blen, offp, "\n"); \ + for (j = 0; j <= level; j++) { \ + FPRINTF(bufp, blen, offp, "%s", \ + indent); \ + } \ + } \ + FPRINTF(bufp, blen, offp, "]"); \ + } while (0) + /* * A realloc-aware snprintf/asprintf like function. */ @@ -167,7 +196,93 @@ nvlist_print_json_string(const char *input, char **bufp, size_t *blen, } static int -nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp) +nvlist_print_json_boolean_value(boolean_t b, char **bufp, size_t *blen, + off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%s", b == B_TRUE ? "true" : "false"); + return (0); +} + +static int +nvlist_print_json_byte(char byte, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%hhu", byte); + return (0); +} + +static int +nvlist_print_json_int8(int8_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%hhd", num); + return (0); +} + +static int +nvlist_print_json_uint8(uint8_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%hhu", num); + return (0); +} + +static int +nvlist_print_json_int16(int16_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%hd", num); + return (0); +} + +static int +nvlist_print_json_uint16(uint16_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%hu", num); + return (0); +} + +static int +nvlist_print_json_int32(int32_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%d", num); + return (0); +} + +static int +nvlist_print_json_uint32(uint32_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%u", num); + return (0); +} + +static int +nvlist_print_json_int64(int64_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%lld", (long long)num); + return (0); +} + +static int +nvlist_print_json_uint64(uint64_t num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%llu", (unsigned long long)num); + return (0); +} + +static int +nvlist_print_json_hrtime(hrtime_t val, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%llu", (unsigned long long)val); + return (0); +} + +static int +nvlist_print_json_double(double num, char **bufp, size_t *blen, off_t *offp) +{ + FPRINTF(bufp, blen, offp, "%f", num); + return (0); +} + +static int +nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp, + char *indent, int level) { nvpair_t *curr; boolean_t first = B_TRUE; @@ -176,6 +291,7 @@ nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp) for (curr = nvlist_next_nvpair(nvl, NULL); curr; curr = nvlist_next_nvpair(nvl, curr)) { + int i; data_type_t type = nvpair_type(curr); if (!first) @@ -183,121 +299,138 @@ nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp) else first = B_FALSE; + if (indent != NULL) { + FPRINTF(bufp, blen, offp, "\n"); + for (i = 0; i <= level; i++) { + FPRINTF(bufp, blen, offp, "%s", indent); + } + } + if (nvlist_print_json_string(nvpair_name(curr), bufp, blen, offp) == -1) return (-1); - FPRINTF(bufp, blen, offp, ":"); + FPRINTF(bufp, blen, offp, indent == NULL ? ":" : ": "); switch (type) { case DATA_TYPE_STRING: { - char *string = fnvpair_value_string(curr); - if (nvlist_print_json_string(string, bufp, blen, - offp) == -1) + if (nvlist_print_json_string( + fnvpair_value_string(curr), bufp, blen, offp) != 0) return (-1); break; } case DATA_TYPE_BOOLEAN: { - FPRINTF(bufp, blen, offp, "true"); + if (nvlist_print_json_boolean_value(B_TRUE, bufp, blen, + offp) != 0) + return (-1); break; } case DATA_TYPE_BOOLEAN_VALUE: { - FPRINTF(bufp, blen, offp, "%s", - fnvpair_value_boolean_value(curr) == B_TRUE ? - "true" : "false"); + if (nvlist_print_json_boolean_value( + fnvpair_value_boolean_value(curr), bufp, blen, + offp) != 0) + return (-1); break; } case DATA_TYPE_BYTE: { - FPRINTF(bufp, blen, offp, "%hhu", - fnvpair_value_byte(curr)); + if (nvlist_print_json_byte( + fnvpair_value_byte(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_INT8: { - FPRINTF(bufp, blen, offp, "%hhd", - fnvpair_value_int8(curr)); + if (nvlist_print_json_int8( + fnvpair_value_int8(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_UINT8: { - FPRINTF(bufp, blen, offp, "%hhu", - fnvpair_value_uint8_t(curr)); + if (nvlist_print_json_uint8( + fnvpair_value_uint8_t(curr), bufp, blen, + offp) != 0) + return (-1); break; } case DATA_TYPE_INT16: { - FPRINTF(bufp, blen, offp, "%hd", - fnvpair_value_int16(curr)); + if (nvlist_print_json_int16( + fnvpair_value_int16(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_UINT16: { - FPRINTF(bufp, blen, offp, "%hu", - fnvpair_value_uint16(curr)); + if (nvlist_print_json_uint16( + fnvpair_value_uint16(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_INT32: { - FPRINTF(bufp, blen, offp, "%d", - fnvpair_value_int32(curr)); + if (nvlist_print_json_int32( + fnvpair_value_int32(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_UINT32: { - FPRINTF(bufp, blen, offp, "%u", - fnvpair_value_uint32(curr)); + if (nvlist_print_json_uint32( + fnvpair_value_uint32(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_INT64: { - FPRINTF(bufp, blen, offp, "%lld", - (long long)fnvpair_value_int64(curr)); + if (nvlist_print_json_int64( + fnvpair_value_int64(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_UINT64: { - FPRINTF(bufp, blen, offp, "%llu", - (unsigned long long)fnvpair_value_uint64(curr)); + if (nvlist_print_json_uint64( + fnvpair_value_uint64(curr), bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_HRTIME: { hrtime_t val; VERIFY0(nvpair_value_hrtime(curr, &val)); - FPRINTF(bufp, blen, offp, "%llu", - (unsigned long long)val); + + if (nvlist_print_json_hrtime(val, bufp, blen, + offp) != 0) + return (-1); break; } case DATA_TYPE_DOUBLE: { double val; VERIFY0(nvpair_value_double(curr, &val)); - FPRINTF(bufp, blen, offp, "%f", val); + + if (nvlist_print_json_double( + val, bufp, blen, offp) != 0) + return (-1); break; } case DATA_TYPE_NVLIST: { if (nvlist_do_json(fnvpair_value_nvlist(curr), bufp, - blen, offp) == -1) + blen, offp, indent, level + 1) == -1) return (-1); break; } case DATA_TYPE_STRING_ARRAY: { char **val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_string_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - if (nvlist_print_json_string(val[i], bufp, - blen, offp) == -1) - return (-1); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_string, + level, indent, bufp, blen, offp); break; } @@ -310,7 +443,7 @@ nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp) if (i > 0) FPRINTF(bufp, blen, offp, ","); if (nvlist_do_json(val[i], bufp, blen, - offp) == -1) + offp, indent, level + 1) == -1) return (-1); } FPRINTF(bufp, blen, offp, "]"); @@ -319,144 +452,92 @@ nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp) case DATA_TYPE_BOOLEAN_ARRAY: { boolean_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_boolean_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, val[i] == B_TRUE ? - "true" : "false"); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, + nvlist_print_json_boolean_value, level, indent, + bufp, blen, offp); break; } case DATA_TYPE_BYTE_ARRAY: { uchar_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_byte_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%hhu", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_byte, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_UINT8_ARRAY: { uint8_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_uint8_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%hhu", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_uint8, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_INT8_ARRAY: { int8_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_int8_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%hd", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_int8, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_UINT16_ARRAY: { uint16_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_uint16_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%hu", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_uint16, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_INT16_ARRAY: { int16_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_int16_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%hd", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_int16, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_UINT32_ARRAY: { uint32_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_uint32_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%u", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_uint32, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_INT32_ARRAY: { int32_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_int32_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%d", val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_int32, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_UINT64_ARRAY: { uint64_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_uint64_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%llu", - (unsigned long long)val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_uint64, + level, indent, bufp, blen, offp); break; } case DATA_TYPE_INT64_ARRAY: { int64_t *val; - uint_t valsz, i; + uint_t valsz; VERIFY0(nvpair_value_int64_array(curr, &val, &valsz)); - FPRINTF(bufp, blen, offp, "["); - for (i = 0; i < valsz; i++) { - if (i > 0) - FPRINTF(bufp, blen, offp, ","); - FPRINTF(bufp, blen, offp, "%lld", - (long long)val[i]); - } - FPRINTF(bufp, blen, offp, "]"); + FPRINTF_JSON_ARRAY(val, valsz, nvlist_print_json_int64, + level, indent, bufp, blen, offp); break; } @@ -465,18 +546,33 @@ nvlist_do_json(nvlist_t *nvl, char **bufp, size_t *blen, off_t *offp) } } + if (indent != NULL) { + FPRINTF(bufp, blen, offp, "\n"); + } + FPRINTF(bufp, blen, offp, "}"); + + if (indent != NULL) { + FPRINTF(bufp, blen, offp, "\n"); + } + return (0); } int nvlist_dump_json(nvlist_t *nvl, char **bufp) { + return (nvlist_dump_json_pretty(nvl, bufp, NULL)); +} + +int +nvlist_dump_json_pretty(nvlist_t *nvl, char **bufp, char *indent) +{ off_t off = 0; size_t l = 0; *bufp = NULL; - return (nvlist_do_json(nvl, bufp, &l, &off)); + return (nvlist_do_json(nvl, bufp, &l, &off, indent, 0)); } /* ARGSUSED */ @@ -494,10 +590,24 @@ nvlist_dump_json_free(nvlist_t *nvl, char *buf) int nvlist_print_json(FILE *fp, nvlist_t *nvl) { + return (nvlist_print_json_pretty(fp, nvl, NULL)); +} + +/* + * Dump a JSON-formatted representation of an nvlist to the provided FILE *. + * This routine outputs newlines and extra whitespace to make the output + * "pretty". The string given in `indent` will be used to indent the + * output. For example, give " " for 2 space indentation, " " for 4 + * space indentation, "\t" for tabbed indentation, etc. An indent of NULL + * will disable pretty-printing. + */ +int +nvlist_print_json_pretty(FILE *fp, nvlist_t *nvl, char *indent) +{ int ret; char *buf; - if ((ret = nvlist_dump_json(nvl, &buf)) < 0) + if ((ret = nvlist_dump_json_pretty(nvl, &buf, indent)) < 0) return (ret); ret = fprintf(fp, "%s", buf); nvlist_dump_json_free(nvl, buf); |
