CBOR-to-JSON: print integers with full precision

Instead of performing a lossy conversion to double and printing that.
It's irrelevant whether the parser on the other side can store this
precision, only that it can parse this. That includes numbers outside
the range of int64_t, which CBOR does support.

We do this by simply removing code from cbortojson.c and instead just
relying on what cborpretty.c already has.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira
2026-02-05 14:15:50 -08:00
parent ef6f92349f
commit 64da0f471a
2 changed files with 14 additions and 47 deletions
+5 -35
View File
@@ -644,28 +644,11 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
return CborNoError;
}
case CborIntegerType: {
double num; /* JS numbers are IEEE double precision */
uint64_t val;
cbor_value_get_raw_integer(it, &val); /* can't fail */
num = (double)val;
if (cbor_value_is_negative_integer(it)) {
num = -num - 1; /* convert to negative */
if ((uint64_t)(-num - 1) != val) {
status->flags = NumberPrecisionWasLost | NumberWasNegative;
status->originalNumber = val;
}
} else {
if ((uint64_t)num != val) {
status->flags = NumberPrecisionWasLost;
status->originalNumber = val;
}
}
if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */
return CborErrorIO;
break;
}
case CborIntegerType:
case CborNullType:
case CborBooleanType:
/* just use cborpretty.c */
return cbor_value_to_pretty_advance(out, it);
case CborByteStringType:
case CborTextStringType: {
@@ -696,25 +679,12 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
break;
}
case CborNullType:
if (fprintf(out, "null") < 0)
return CborErrorIO;
break;
case CborUndefinedType:
status->flags = TypeWasNotNative;
if (fprintf(out, "\"undefined\"") < 0)
return CborErrorIO;
break;
case CborBooleanType: {
bool val;
cbor_value_get_boolean(it, &val); /* can't fail */
if (fprintf(out, val ? "true" : "false") < 0)
return CborErrorIO;
break;
}
#ifndef CBOR_NO_FLOATING_POINT
case CborDoubleType: {
double val;
+9 -12
View File
@@ -100,13 +100,20 @@ void addFixedData()
QTest::newRow("0") << raw("\x00") << "0";
QTest::newRow("1") << raw("\x01") << "1";
QTest::newRow("2^53-1") << raw("\x1b\0\x1f\xff\xff""\xff\xff\xff\xff") << "9007199254740991";
QTest::newRow("2^64-epsilon") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "18446744073709549568";
QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1") << "9007199254740993";
QTest::newRow("2^63-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xff") << "9223372036854775807";
QTest::newRow("2^64-1") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xff\xff") << "18446744073709551615";
// negative integers
QTest::newRow("-1") << raw("\x20") << "-1";
QTest::newRow("-2") << raw("\x21") << "-2";
QTest::newRow("-2^53+1") << raw("\x3b\0\x1f\xff\xff""\xff\xff\xff\xfe") << "-9007199254740991";
QTest::newRow("-2^64+epsilon") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "-18446744073709549568";
QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0") << "-9007199254740993";
QTest::newRow("-2^63+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe") << "-9223372036854775807";
QTest::newRow("-2^63") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff") << "-9223372036854775808";
QTest::newRow("-2^63-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809";
QTest::newRow("-2^64+1") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xff\xfe") << "-18446744073709551615";
QTest::newRow("-2^64") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xff\xff") << "-18446744073709551616";
QTest::newRow("false") << raw("\xf4") << "false";
QTest::newRow("true") << raw("\xf5") << "true";
@@ -618,16 +625,6 @@ void tst_ToJson::metaData_data()
QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "\"t\":251";
QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "\"t\":251";
// integers that are too precise for double
QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1")
<< "\"t\":0,\"v\":\"+20000000000001\"";
QTest::newRow("INT64_MAX-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
<< "\"t\":0,\"v\":\"+7ffffffffffffffe\"";
QTest::newRow("INT64_MAX+1") << raw("\x1b\x80\0\0\0""\0\0\0\1")
<< "\"t\":0,\"v\":\"+8000000000000001\"";
QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0")
<< "\"t\":0,\"v\":\"-20000000000000\"";
// simple values
QTest::newRow("simple0") << raw("\xe0") << "\"t\":224,\"v\":0";
QTest::newRow("simple19") << raw("\xf3") << "\"t\":224,\"v\":19";