Archived
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:
+5
-35
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user