Skip to content

Commit 64da0f4

Browse files
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>
1 parent ef6f923 commit 64da0f4

2 files changed

Lines changed: 14 additions & 47 deletions

File tree

src/cbortojson.c

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -644,28 +644,11 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
644644
return CborNoError;
645645
}
646646

647-
case CborIntegerType: {
648-
double num; /* JS numbers are IEEE double precision */
649-
uint64_t val;
650-
cbor_value_get_raw_integer(it, &val); /* can't fail */
651-
num = (double)val;
652-
653-
if (cbor_value_is_negative_integer(it)) {
654-
num = -num - 1; /* convert to negative */
655-
if ((uint64_t)(-num - 1) != val) {
656-
status->flags = NumberPrecisionWasLost | NumberWasNegative;
657-
status->originalNumber = val;
658-
}
659-
} else {
660-
if ((uint64_t)num != val) {
661-
status->flags = NumberPrecisionWasLost;
662-
status->originalNumber = val;
663-
}
664-
}
665-
if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */
666-
return CborErrorIO;
667-
break;
668-
}
647+
case CborIntegerType:
648+
case CborNullType:
649+
case CborBooleanType:
650+
/* just use cborpretty.c */
651+
return cbor_value_to_pretty_advance(out, it);
669652

670653
case CborByteStringType:
671654
case CborTextStringType: {
@@ -696,25 +679,12 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
696679
break;
697680
}
698681

699-
case CborNullType:
700-
if (fprintf(out, "null") < 0)
701-
return CborErrorIO;
702-
break;
703-
704682
case CborUndefinedType:
705683
status->flags = TypeWasNotNative;
706684
if (fprintf(out, "\"undefined\"") < 0)
707685
return CborErrorIO;
708686
break;
709687

710-
case CborBooleanType: {
711-
bool val;
712-
cbor_value_get_boolean(it, &val); /* can't fail */
713-
if (fprintf(out, val ? "true" : "false") < 0)
714-
return CborErrorIO;
715-
break;
716-
}
717-
718688
#ifndef CBOR_NO_FLOATING_POINT
719689
case CborDoubleType: {
720690
double val;

tests/tojson/tst_tojson.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,20 @@ void addFixedData()
100100
QTest::newRow("0") << raw("\x00") << "0";
101101
QTest::newRow("1") << raw("\x01") << "1";
102102
QTest::newRow("2^53-1") << raw("\x1b\0\x1f\xff\xff""\xff\xff\xff\xff") << "9007199254740991";
103-
QTest::newRow("2^64-epsilon") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "18446744073709549568";
103+
QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1") << "9007199254740993";
104+
QTest::newRow("2^63-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xff") << "9223372036854775807";
105+
QTest::newRow("2^64-1") << raw("\x1b\xff\xff\xff\xff""\xff\xff\xff\xff") << "18446744073709551615";
104106

105107
// negative integers
106108
QTest::newRow("-1") << raw("\x20") << "-1";
107109
QTest::newRow("-2") << raw("\x21") << "-2";
108110
QTest::newRow("-2^53+1") << raw("\x3b\0\x1f\xff\xff""\xff\xff\xff\xfe") << "-9007199254740991";
109-
QTest::newRow("-2^64+epsilon") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf8\x00") << "-18446744073709549568";
111+
QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0") << "-9007199254740993";
112+
QTest::newRow("-2^63+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe") << "-9223372036854775807";
113+
QTest::newRow("-2^63") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff") << "-9223372036854775808";
114+
QTest::newRow("-2^63-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809";
115+
QTest::newRow("-2^64+1") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xff\xfe") << "-18446744073709551615";
116+
QTest::newRow("-2^64") << raw("\x3b\xff\xff\xff\xff""\xff\xff\xff\xff") << "-18446744073709551616";
110117

111118
QTest::newRow("false") << raw("\xf4") << "false";
112119
QTest::newRow("true") << raw("\xf5") << "true";
@@ -618,16 +625,6 @@ void tst_ToJson::metaData_data()
618625
QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "\"t\":251";
619626
QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "\"t\":251";
620627

621-
// integers that are too precise for double
622-
QTest::newRow("2^53+1") << raw("\x1b\0\x20\0\0""\0\0\0\1")
623-
<< "\"t\":0,\"v\":\"+20000000000001\"";
624-
QTest::newRow("INT64_MAX-1") << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
625-
<< "\"t\":0,\"v\":\"+7ffffffffffffffe\"";
626-
QTest::newRow("INT64_MAX+1") << raw("\x1b\x80\0\0\0""\0\0\0\1")
627-
<< "\"t\":0,\"v\":\"+8000000000000001\"";
628-
QTest::newRow("-2^53-1") << raw("\x3b\0\x20\0\0""\0\0\0\0")
629-
<< "\"t\":0,\"v\":\"-20000000000000\"";
630-
631628
// simple values
632629
QTest::newRow("simple0") << raw("\xe0") << "\"t\":224,\"v\":0";
633630
QTest::newRow("simple19") << raw("\xf3") << "\"t\":224,\"v\":19";

0 commit comments

Comments
 (0)