Skip to content

Commit

Permalink
Merge pull request #2695 from particle-iot/feature/wiring-json-64-bit…
Browse files Browse the repository at this point in the history
…-int

[wiring] json: 64-bit support
  • Loading branch information
avtolstoy authored and technobly committed Sep 20, 2023
1 parent 489a523 commit ca07788
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 2 deletions.
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

0 comments on commit ca07788

Please sign in to comment.