in libs/tinycbor/src/cborpretty.c [339:553]
static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft)
{
CborError err = CborNoError;
CborType type = cbor_value_get_type(it);
switch (type) {
case CborArrayType:
case CborMapType: {
/* recursive type */
CborValue recursed;
const char *indicator = get_indicator(it, flags);
const char *space = *indicator ? " " : indicator;
err = stream(out, "%c%s%s", type == CborArrayType ? '[' : '{', indicator, space);
if (err)
return err;
err = cbor_value_enter_container(it, &recursed);
if (err) {
it->ptr = recursed.ptr;
return err; /* parse error */
}
err = container_to_pretty(stream, out, &recursed, type, flags, recursionsLeft - 1);
if (err) {
it->ptr = recursed.ptr;
return err; /* parse error */
}
err = cbor_value_leave_container(it, &recursed);
if (err)
return err; /* parse error */
return stream(out, type == CborArrayType ? "]" : "}");
}
case CborIntegerType: {
uint64_t val;
cbor_value_get_raw_integer(it, &val); /* can't fail */
if (cbor_value_is_unsigned_integer(it)) {
err = stream(out, "%" PRIu64, val);
} else {
/* CBOR stores the negative number X as -1 - X
* (that is, -1 is stored as 0, -2 as 1 and so forth) */
if (++val) { /* unsigned overflow may happen */
err = stream(out, "-%" PRIu64, val);
} else {
/* overflown
* 0xffff`ffff`ffff`ffff + 1 =
* 0x1`0000`0000`0000`0000 = 18446744073709551616 (2^64) */
err = stream(out, "-18446744073709551616");
}
}
if (!err)
err = stream(out, "%s", get_indicator(it, flags));
break;
}
case CborByteStringType:
case CborTextStringType: {
size_t n = 0;
const void *ptr;
bool showingFragments = (flags & CborPrettyShowStringFragments) && !cbor_value_is_length_known(it);
const char *separator = "";
char close = '\'';
char open[3] = "h'";
const char *indicator = NULL;
if (type == CborTextStringType) {
close = open[0] = '"';
open[1] = '\0';
}
if (showingFragments) {
err = stream(out, "(_ ");
if (!err)
err = _cbor_value_prepare_string_iteration(it);
} else {
err = stream(out, "%s", open);
}
while (!err) {
if (showingFragments || indicator == NULL) {
/* any iteration, except the second for a non-chunked string */
indicator = resolve_indicator(it->ptr, it->parser->end, flags);
}
err = _cbor_value_get_string_chunk(it, &ptr, &n, it);
if (err)
return err;
if (!ptr)
break;
if (!err && showingFragments)
err = stream(out, "%s%s", separator, open);
if (!err)
err = (type == CborByteStringType ?
hexDump(stream, out, ptr, n) :
utf8EscapedDump(stream, out, ptr, n));
if (!err && showingFragments) {
err = stream(out, "%c%s", close, indicator);
separator = ", ";
}
}
if (!err) {
if (showingFragments)
err = stream(out, ")");
else
err = stream(out, "%c%s", close, indicator);
}
return err;
}
case CborTagType: {
CborTag tag;
cbor_value_get_tag(it, &tag); /* can't fail */
err = stream(out, "%" PRIu64 "%s(", tag, get_indicator(it, flags));
if (!err)
err = cbor_value_advance_fixed(it);
if (!err && recursionsLeft)
err = value_to_pretty(stream, out, it, flags, recursionsLeft - 1);
else if (!err)
printRecursionLimit(stream, out);
if (!err)
err = stream(out, ")");
return err;
}
case CborSimpleType: {
/* simple types can't fail and can't have overlong encoding */
uint8_t simple_type;
cbor_value_get_simple_type(it, &simple_type);
err = stream(out, "simple(%" PRIu8 ")", simple_type);
break;
}
case CborNullType:
err = stream(out, "null");
break;
case CborUndefinedType:
err = stream(out, "undefined");
break;
case CborBooleanType: {
bool val;
cbor_value_get_boolean(it, &val); /* can't fail */
err = stream(out, val ? "true" : "false");
break;
}
#ifndef CBOR_NO_FLOATING_POINT
case CborDoubleType: {
const char *suffix;
double val;
int r;
uint64_t ival;
if (false) {
float f;
case CborFloatType:
cbor_value_get_float(it, &f);
val = f;
suffix = flags & CborPrettyNumericEncodingIndicators ? "_2" : "f";
} else if (false) {
uint16_t f16;
case CborHalfFloatType:
#ifndef CBOR_NO_HALF_FLOAT_TYPE
cbor_value_get_half_float(it, &f16);
val = decode_half(f16);
suffix = flags & CborPrettyNumericEncodingIndicators ? "_1" : "f16";
#else
(void)f16;
err = CborErrorUnsupportedType;
break;
#endif
} else {
cbor_value_get_double(it, &val);
suffix = "";
}
if ((flags & CborPrettyNumericEncodingIndicators) == 0) {
r = fpclassify(val);
if (r == FP_NAN || r == FP_INFINITE)
suffix = "";
}
if (convertToUint64(val, &ival)) {
/* this double value fits in a 64-bit integer, so show it as such
* (followed by a floating point suffix, to disambiguate) */
err = stream(out, "%s%" PRIu64 ".%s", val < 0 ? "-" : "", ival, suffix);
} else {
/* this number is definitely not a 64-bit integer */
err = stream(out, "%." DBL_DECIMAL_DIG_STR "g%s", val, suffix);
}
break;
}
#else
case CborDoubleType:
case CborFloatType:
case CborHalfFloatType:
err = CborErrorUnsupportedType;
break;
#endif /* !CBOR_NO_FLOATING_POINT */
case CborInvalidType:
err = stream(out, "invalid");
if (err)
return err;
return CborErrorUnknownType;
}
if (!err)
err = cbor_value_advance_fixed(it);
return err;
}