Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wiring] json: 64-bit support #2695

Merged
merged 1 commit into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 157 additions & 2 deletions test/unit_tests/wiring/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,30 @@ class Checker {
return *this;
}

Checker& number64(long long val) {
const JSONValue v = value();
REQUIRE(v.type() == JSON_TYPE_NUMBER);
CHECK(v.isNumber());
CHECK(v.toInt64() == val);
return *this;
}

Checker& number(unsigned val) {
const JSONValue v = value();
REQUIRE(v.type() == JSON_TYPE_NUMBER);
CHECK(v.isNumber());
CHECK(v.toUInt() == val);
return *this;
}

Checker& number64(unsigned long long val) {
const JSONValue v = value();
REQUIRE(v.type() == JSON_TYPE_NUMBER);
CHECK(v.isNumber());
CHECK(v.toUInt64() == val);
return *this;
}

Checker& number(double val) {
const JSONValue v = value();
REQUIRE(v.type() == JSON_TYPE_NUMBER);
Expand Down Expand Up @@ -208,6 +232,29 @@ TEST_CASE("Parsing JSON") {
check("-2147483648").number((int)-2147483648); // INT_MIN
check("2147483647").number((int)2147483647); // INT_MAX
}
SECTION("int64") {
check("0").number64((long long)0);
check("1").number64((long long)1);
check("-1").number64((long long)-1);
check("12345").number64((long long)12345);
check("-12345").number64((long long)-12345);
check("4294967295").number64((long long)UINT32_MAX); // UINT32_MAX
check("-9223372036854775808").number64((long long)INT64_MIN); // INT64_MIN
check("9223372036854775807").number64((long long)INT64_MAX); // INT64_MAX
}
SECTION("uint") {
check("0").number((unsigned)0);
check("1").number((unsigned)1);
check("12345").number((unsigned)12345);
check("4294967295").number((unsigned)UINT32_MAX); // UINT32_MAX
}
SECTION("uint64") {
check("0").number64((unsigned long long)0);
check("1").number64((unsigned long long)1);
check("12345").number64((unsigned long long)12345);
check("4294967295").number64((unsigned long long)UINT32_MAX); // UINT32_MAX
check("18446744073709551615").number64((unsigned long long)UINT64_MAX); // UINT64_MAX
}
SECTION("float") {
check("0.0").number(0.0);
check("1.0").number(1.0);
Expand Down Expand Up @@ -413,6 +460,96 @@ TEST_CASE("Writing JSON") {
check(data).equals("2147483647");
}
}
SECTION("int64") {
SECTION("0") {
json.value((long long)0);
check(data).equals("0");
}
SECTION("1") {
json.value((long long)1);
check(data).equals("1");
}
SECTION("-1") {
json.value((long long)-1);
check(data).equals("-1");
}
SECTION("12345") {
json.value((long long)12345);
check(data).equals("12345");
}
SECTION("-12345") {
json.value((long long)-12345);
check(data).equals("-12345");
}
SECTION("-2147483648") {
json.value((long long)-2147483648); // INT_MIN
check(data).equals("-2147483648");
}
SECTION("2147483647") {
json.value((long long)2147483647); // INT_MAX
check(data).equals("2147483647");
}
SECTION("-9223372036854775808") {
json.value((long long)INT64_MIN); // INT64_MIN
check(data).equals("-9223372036854775808");
}
SECTION("9223372036854775807") {
json.value((long long)INT64_MAX); // INT64_MAX
check(data).equals("9223372036854775807");
}
}
SECTION("uint") {
SECTION("0") {
json.value((unsigned)0);
check(data).equals("0");
}
SECTION("1") {
json.value((unsigned)1);
check(data).equals("1");
}
SECTION("12345") {
json.value((unsigned)12345);
check(data).equals("12345");
}
SECTION("2147483647") {
json.value((unsigned)2147483647); // INT_MAX
check(data).equals("2147483647");
}
SECTION("4294967295") {
json.value((unsigned)UINT32_MAX); // UINT32_MAX
check(data).equals("4294967295");
}
}
SECTION("uint64") {
SECTION("0") {
json.value((unsigned long long)0);
check(data).equals("0");
}
SECTION("1") {
json.value((unsigned long long)1);
check(data).equals("1");
}
SECTION("12345") {
json.value((unsigned long long)12345);
check(data).equals("12345");
}
SECTION("2147483647") {
json.value((unsigned long long)2147483647); // INT_MAX
check(data).equals("2147483647");
}
SECTION("4294967295") {
json.value((unsigned long long)UINT32_MAX); // UINT32_MAX
check(data).equals("4294967295");
}
SECTION("9223372036854775807") {
json.value((unsigned long long)INT64_MAX); // INT64_MAX
check(data).equals("9223372036854775807");
}
SECTION("18446744073709551615") {
json.value((unsigned long long)UINT64_MAX); // UINT64_MAX
check(data).equals("18446744073709551615");
}
}
SECTION("float") {
SECTION("0.0") {
json.value(0.0);
Expand Down Expand Up @@ -864,6 +1001,9 @@ TEST_CASE("JSONValue") {
check(v).invalid();
CHECK(v.toBool() == false);
CHECK(v.toInt() == 0);
CHECK(v.toInt64() == 0);
CHECK(v.toUInt() == 0);
CHECK(v.toUInt64() == 0);
CHECK(v.toDouble() == 0.0);
CHECK(v.toString() == "");
}
Expand All @@ -872,6 +1012,9 @@ TEST_CASE("JSONValue") {
check(v).null();
CHECK(v.toBool() == false);
CHECK(v.toInt() == 0);
CHECK(v.toInt64() == 0);
CHECK(v.toUInt() == 0);
CHECK(v.toUInt64() == 0);
CHECK(v.toDouble() == 0.0);
CHECK(v.toString() == "");
}
Expand All @@ -880,13 +1023,19 @@ TEST_CASE("JSONValue") {
const JSONValue v = parse("true");
check(v).boolean(true);
CHECK(v.toInt() == 1);
CHECK(v.toInt64() == 1);
CHECK(v.toUInt() == 1);
CHECK(v.toUInt64() == 1);
CHECK(v.toDouble() == 1.0);
CHECK(v.toString() == "true");
}
SECTION("false") {
const JSONValue v = parse("false");
check(v).boolean(false);
CHECK(v.toInt() == 0);
CHECK(v.toInt64() == 0);
CHECK(v.toUInt() == 0);
CHECK(v.toUInt64() == 0);
CHECK(v.toDouble() == 0.0);
CHECK(v.toString() == "false");
}
Expand All @@ -895,14 +1044,20 @@ TEST_CASE("JSONValue") {
SECTION("int") {
SECTION("0") {
const JSONValue v = parse("0");
check(v).number(0);
check(v).number((int)0);
check(v).number64((long long)0);
check(v).number((unsigned)0);
check(v).number64((unsigned long long)0);
CHECK(v.toBool() == false);
CHECK(v.toDouble() == 0.0);
CHECK(v.toString() == "0");
}
SECTION("12345") {
const JSONValue v = parse("12345");
check(v).number(12345);
check(v).number((int)12345);
check(v).number64((long long)12345);
check(v).number((unsigned)12345);
check(v).number64((unsigned long long)12345);
CHECK(v.toBool() == true);
CHECK(v.toDouble() == 12345.0);
CHECK(v.toString() == "12345");
Expand Down
5 changes: 5 additions & 0 deletions wiring/inc/spark_wiring_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class JSONValue {

bool toBool() const;
int toInt() const;
unsigned toUInt() const;
long long toInt64() const;
unsigned long long toUInt64() const;
double toDouble() const;
JSONString toString() const;

Expand Down Expand Up @@ -176,7 +179,9 @@ class JSONWriter {
JSONWriter& value(int val);
JSONWriter& value(unsigned val);
JSONWriter& value(long val);
JSONWriter& value(long long val);
JSONWriter& value(unsigned long val);
JSONWriter& value(unsigned long long val);
JSONWriter& value(double val, int precision);
JSONWriter& value(double val);
JSONWriter& value(const char *val);
Expand Down
68 changes: 68 additions & 0 deletions wiring/src/spark_wiring_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,60 @@ int spark::JSONValue::toInt() const {
}
}

unsigned spark::JSONValue::toUInt() const {
switch (type()) {
case JSON_TYPE_BOOL: {
const char* const s = d_->json + t_->start;
return *s == 't';
}
case JSON_TYPE_NUMBER:
case JSON_TYPE_STRING: {
// toInt() may produce incorrect results for floating point numbers, since we want to keep
// compile-time dependency on strtod() optional
const char* const s = d_->json + t_->start;
return strtoul(s, nullptr, 10);
}
default:
return 0;
}
}

long long spark::JSONValue::toInt64() const {
switch (type()) {
case JSON_TYPE_BOOL: {
const char* const s = d_->json + t_->start;
return *s == 't';
}
case JSON_TYPE_NUMBER:
case JSON_TYPE_STRING: {
// toInt() may produce incorrect results for floating point numbers, since we want to keep
// compile-time dependency on strtod() optional
const char* const s = d_->json + t_->start;
return strtoll(s, nullptr, 10);
}
default:
return 0;
}
}

unsigned long long spark::JSONValue::toUInt64() const {
switch (type()) {
case JSON_TYPE_BOOL: {
const char* const s = d_->json + t_->start;
return *s == 't';
}
case JSON_TYPE_NUMBER:
case JSON_TYPE_STRING: {
// toInt() may produce incorrect results for floating point numbers, since we want to keep
// compile-time dependency on strtod() optional
const char* const s = d_->json + t_->start;
return strtoull(s, nullptr, 10);
}
default:
return 0;
}
}

double spark::JSONValue::toDouble() const {
switch (type()) {
case JSON_TYPE_BOOL: {
Expand Down Expand Up @@ -477,6 +531,20 @@ spark::JSONWriter& spark::JSONWriter::value(unsigned long val) {
return *this;
}

spark::JSONWriter& spark::JSONWriter::value(long long val) {
writeSeparator();
printf("%lld", val);
state_ = NEXT;
return *this;
}

spark::JSONWriter& spark::JSONWriter::value(unsigned long long val) {
writeSeparator();
printf("%llu", val);
state_ = NEXT;
return *this;
}

spark::JSONWriter& spark::JSONWriter::value(double val, int precision) {
writeSeparator();
printf("%.*lf", precision, val);
Expand Down