mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[upstream_utils] Add jart/json.cpp
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sun, 29 Mar 2026 16:46:09 -0700
|
||||
Subject: [PATCH 01/25] Move to wpi::util namespace
|
||||
|
||||
---
|
||||
json.cpp | 4 ++--
|
||||
json.h | 4 ++--
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 0b3e3730406ecf3bf283a56d93b7cc8c3052d61d..645266767781cb3ebdb700bf6761e6928806806e 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -83,7 +83,7 @@
|
||||
#define ON_LOGIC_ERROR(s) abort()
|
||||
#endif
|
||||
|
||||
-namespace jt {
|
||||
+namespace wpi::util {
|
||||
|
||||
static const char kJsonStr[256] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, // 0000 ascii (0)
|
||||
@@ -1313,4 +1313,4 @@ Json::StatusToString(Json::Status status)
|
||||
}
|
||||
}
|
||||
|
||||
-} // namespace jt
|
||||
+} // namespace wpi::util
|
||||
diff --git a/json.h b/json.h
|
||||
index 6bb9087f452ae18dfad7c52b95de27c39a886341..c676e651d7c2591a0fb07d8d8b28738cbd1defab 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
-namespace jt {
|
||||
+namespace wpi::util {
|
||||
|
||||
class Json
|
||||
{
|
||||
@@ -221,4 +221,4 @@ class Json
|
||||
static Status parse(Json&, const char*&, const char*, int, int);
|
||||
};
|
||||
|
||||
-} // namespace jt
|
||||
+} // namespace wpi::util
|
||||
@@ -0,0 +1,599 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sun, 29 Mar 2026 16:47:26 -0700
|
||||
Subject: [PATCH 02/25] Rename class from Json to json
|
||||
|
||||
---
|
||||
json.cpp | 142 +++++++++++++++++++++++++++----------------------------
|
||||
json.h | 54 ++++++++++-----------
|
||||
2 files changed, 98 insertions(+), 98 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 645266767781cb3ebdb700bf6761e6928806806e..3e59a885b55d3fddc418903112595fe5de223f34 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -242,7 +242,7 @@ LongToString(char* p, long long x)
|
||||
return UlongToString(p, x);
|
||||
}
|
||||
|
||||
-Json::Json(unsigned long value)
|
||||
+json::json(unsigned long value)
|
||||
{
|
||||
if (value <= LLONG_MAX) {
|
||||
type_ = Long;
|
||||
@@ -253,7 +253,7 @@ Json::Json(unsigned long value)
|
||||
}
|
||||
}
|
||||
|
||||
-Json::Json(unsigned long long value)
|
||||
+json::json(unsigned long long value)
|
||||
{
|
||||
if (value <= LLONG_MAX) {
|
||||
type_ = Long;
|
||||
@@ -264,7 +264,7 @@ Json::Json(unsigned long long value)
|
||||
}
|
||||
}
|
||||
|
||||
-Json::Json(const char* value)
|
||||
+json::json(const char* value)
|
||||
{
|
||||
if (value) {
|
||||
type_ = String;
|
||||
@@ -274,18 +274,18 @@ Json::Json(const char* value)
|
||||
}
|
||||
}
|
||||
|
||||
-Json::Json(const std::string& value) : type_(String), string_value(value)
|
||||
+json::json(const std::string& value) : type_(String), string_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
-Json::~Json()
|
||||
+json::~json()
|
||||
{
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
}
|
||||
|
||||
void
|
||||
-Json::clear()
|
||||
+json::clear()
|
||||
{
|
||||
switch (type_) {
|
||||
case String:
|
||||
@@ -303,7 +303,7 @@ Json::clear()
|
||||
type_ = Null;
|
||||
}
|
||||
|
||||
-Json::Json(const Json& other) : type_(other.type_)
|
||||
+json::json(const json& other) : type_(other.type_)
|
||||
{
|
||||
switch (type_) {
|
||||
case Null:
|
||||
@@ -324,18 +324,18 @@ Json::Json(const Json& other) : type_(other.type_)
|
||||
new (&string_value) std::string(other.string_value);
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value) std::vector<Json>(other.array_value);
|
||||
+ new (&array_value) std::vector<json>(other.array_value);
|
||||
break;
|
||||
case Object:
|
||||
- new (&object_value) std::map<std::string, Json>(other.object_value);
|
||||
+ new (&object_value) std::map<std::string, json>(other.object_value);
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
}
|
||||
}
|
||||
|
||||
-Json&
|
||||
-Json::operator=(const Json& other)
|
||||
+json&
|
||||
+json::operator=(const json& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (type_ >= String)
|
||||
@@ -360,11 +360,11 @@ Json::operator=(const Json& other)
|
||||
new (&string_value) std::string(other.string_value);
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value) std::vector<Json>(other.array_value);
|
||||
+ new (&array_value) std::vector<json>(other.array_value);
|
||||
break;
|
||||
case Object:
|
||||
new (&object_value)
|
||||
- std::map<std::string, Json>(other.object_value);
|
||||
+ std::map<std::string, json>(other.object_value);
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
@@ -373,7 +373,7 @@ Json::operator=(const Json& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
-Json::Json(Json&& other) : type_(other.type_)
|
||||
+json::json(json&& other) : type_(other.type_)
|
||||
{
|
||||
switch (type_) {
|
||||
case Null:
|
||||
@@ -394,11 +394,11 @@ Json::Json(Json&& other) : type_(other.type_)
|
||||
new (&string_value) std::string(std::move(other.string_value));
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value) std::vector<Json>(std::move(other.array_value));
|
||||
+ new (&array_value) std::vector<json>(std::move(other.array_value));
|
||||
break;
|
||||
case Object:
|
||||
new (&object_value)
|
||||
- std::map<std::string, Json>(std::move(other.object_value));
|
||||
+ std::map<std::string, json>(std::move(other.object_value));
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
@@ -406,8 +406,8 @@ Json::Json(Json&& other) : type_(other.type_)
|
||||
other.type_ = Null;
|
||||
}
|
||||
|
||||
-Json&
|
||||
-Json::operator=(Json&& other)
|
||||
+json&
|
||||
+json::operator=(json&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (type_ >= String)
|
||||
@@ -433,11 +433,11 @@ Json::operator=(Json&& other)
|
||||
break;
|
||||
case Array:
|
||||
new (&array_value)
|
||||
- std::vector<Json>(std::move(other.array_value));
|
||||
+ std::vector<json>(std::move(other.array_value));
|
||||
break;
|
||||
case Object:
|
||||
new (&object_value)
|
||||
- std::map<std::string, Json>(std::move(other.object_value));
|
||||
+ std::map<std::string, json>(std::move(other.object_value));
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");;
|
||||
@@ -448,7 +448,7 @@ Json::operator=(Json&& other)
|
||||
}
|
||||
|
||||
double
|
||||
-Json::getNumber() const
|
||||
+json::getNumber() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Long:
|
||||
@@ -463,7 +463,7 @@ Json::getNumber() const
|
||||
}
|
||||
|
||||
long long
|
||||
-Json::getLong() const
|
||||
+json::getLong() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Long:
|
||||
@@ -474,7 +474,7 @@ Json::getLong() const
|
||||
}
|
||||
|
||||
bool
|
||||
-Json::getBool() const
|
||||
+json::getBool() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Bool:
|
||||
@@ -485,7 +485,7 @@ Json::getBool() const
|
||||
}
|
||||
|
||||
float
|
||||
-Json::getFloat() const
|
||||
+json::getFloat() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Float:
|
||||
@@ -498,7 +498,7 @@ Json::getFloat() const
|
||||
}
|
||||
|
||||
double
|
||||
-Json::getDouble() const
|
||||
+json::getDouble() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Float:
|
||||
@@ -511,7 +511,7 @@ Json::getDouble() const
|
||||
}
|
||||
|
||||
std::string&
|
||||
-Json::getString()
|
||||
+json::getString()
|
||||
{
|
||||
switch (type_) {
|
||||
case String:
|
||||
@@ -521,8 +521,8 @@ Json::getString()
|
||||
}
|
||||
}
|
||||
|
||||
-std::vector<Json>&
|
||||
-Json::getArray()
|
||||
+std::vector<json>&
|
||||
+json::getArray()
|
||||
{
|
||||
switch (type_) {
|
||||
case Array:
|
||||
@@ -532,8 +532,8 @@ Json::getArray()
|
||||
}
|
||||
}
|
||||
|
||||
-std::map<std::string, Json>&
|
||||
-Json::getObject()
|
||||
+std::map<std::string, json>&
|
||||
+json::getObject()
|
||||
{
|
||||
switch (type_) {
|
||||
case Object:
|
||||
@@ -544,33 +544,33 @@ Json::getObject()
|
||||
}
|
||||
|
||||
void
|
||||
-Json::setArray()
|
||||
+json::setArray()
|
||||
{
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
type_ = Array;
|
||||
- new (&array_value) std::vector<Json>();
|
||||
+ new (&array_value) std::vector<json>();
|
||||
}
|
||||
|
||||
void
|
||||
-Json::setObject()
|
||||
+json::setObject()
|
||||
{
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
type_ = Object;
|
||||
- new (&object_value) std::map<std::string, Json>();
|
||||
+ new (&object_value) std::map<std::string, json>();
|
||||
}
|
||||
|
||||
bool
|
||||
-Json::contains(const std::string& key) const
|
||||
+json::contains(const std::string& key) const
|
||||
{
|
||||
if (!isObject())
|
||||
return false;
|
||||
return object_value.find(key) != object_value.end();
|
||||
}
|
||||
|
||||
-Json&
|
||||
-Json::operator[](size_t index)
|
||||
+json&
|
||||
+json::operator[](size_t index)
|
||||
{
|
||||
if (!isArray())
|
||||
setArray();
|
||||
@@ -580,8 +580,8 @@ Json::operator[](size_t index)
|
||||
return array_value[index];
|
||||
}
|
||||
|
||||
-Json&
|
||||
-Json::operator[](const std::string& key)
|
||||
+json&
|
||||
+json::operator[](const std::string& key)
|
||||
{
|
||||
if (!isObject())
|
||||
setObject();
|
||||
@@ -589,7 +589,7 @@ Json::operator[](const std::string& key)
|
||||
}
|
||||
|
||||
std::string
|
||||
-Json::toString() const
|
||||
+json::toString() const
|
||||
{
|
||||
std::string b;
|
||||
marshal(b, false, 0);
|
||||
@@ -597,7 +597,7 @@ Json::toString() const
|
||||
}
|
||||
|
||||
std::string
|
||||
-Json::toStringPretty() const
|
||||
+json::toStringPretty() const
|
||||
{
|
||||
std::string b;
|
||||
marshal(b, true, 0);
|
||||
@@ -605,7 +605,7 @@ Json::toStringPretty() const
|
||||
}
|
||||
|
||||
void
|
||||
-Json::marshal(std::string& b, bool pretty, int indent) const
|
||||
+json::marshal(std::string& b, bool pretty, int indent) const
|
||||
{
|
||||
switch (type_) {
|
||||
case Null:
|
||||
@@ -692,7 +692,7 @@ Json::marshal(std::string& b, bool pretty, int indent) const
|
||||
}
|
||||
|
||||
void
|
||||
-Json::stringify(std::string& b, const std::string& s)
|
||||
+json::stringify(std::string& b, const std::string& s)
|
||||
{
|
||||
b += '"';
|
||||
serialize(b, s);
|
||||
@@ -700,7 +700,7 @@ Json::stringify(std::string& b, const std::string& s)
|
||||
}
|
||||
|
||||
void
|
||||
-Json::serialize(std::string& sb, const std::string& s)
|
||||
+json::serialize(std::string& sb, const std::string& s)
|
||||
{
|
||||
size_t i, j, m;
|
||||
wint_t x, a, b;
|
||||
@@ -768,8 +768,8 @@ Json::serialize(std::string& sb, const std::string& s)
|
||||
}
|
||||
}
|
||||
|
||||
-Json::Status
|
||||
-Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
+json::Status
|
||||
+json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
{
|
||||
char w[4];
|
||||
long long x;
|
||||
@@ -818,8 +818,8 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
if (context & (KEY | COLON | COMMA))
|
||||
goto OnColonCommaKey;
|
||||
if (p + 4 <= e && READ32LE(p) == READ32LE("alse")) {
|
||||
- json.type_ = Bool;
|
||||
- json.bool_value = false;
|
||||
+ j.type_ = Bool;
|
||||
+ j.bool_value = false;
|
||||
p += 4;
|
||||
return success;
|
||||
} else {
|
||||
@@ -830,8 +830,8 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
if (context & (KEY | COLON | COMMA))
|
||||
goto OnColonCommaKey;
|
||||
if (p + 3 <= e && READ32LE(p - 1) == READ32LE("true")) {
|
||||
- json.type_ = Bool;
|
||||
- json.bool_value = true;
|
||||
+ j.type_ = Bool;
|
||||
+ j.bool_value = true;
|
||||
p += 3;
|
||||
return success;
|
||||
} else {
|
||||
@@ -873,8 +873,8 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
return unexpected_octal;
|
||||
}
|
||||
}
|
||||
- json.type_ = Long;
|
||||
- json.long_value = 0;
|
||||
+ j.type_ = Long;
|
||||
+ j.long_value = 0;
|
||||
return success;
|
||||
|
||||
case '1':
|
||||
@@ -905,13 +905,13 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
- json.type_ = Long;
|
||||
- json.long_value = x;
|
||||
+ j.type_ = Long;
|
||||
+ j.long_value = x;
|
||||
return success;
|
||||
|
||||
UseDubble: // number
|
||||
- json.type_ = Double;
|
||||
- json.double_value = StringToDouble(a, e - a, &c);
|
||||
+ j.type_ = Double;
|
||||
+ j.double_value = StringToDouble(a, e - a, &c);
|
||||
if (c <= 0)
|
||||
return bad_double;
|
||||
if (a + c < e && (a[c] == 'e' || a[c] == 'E'))
|
||||
@@ -922,15 +922,15 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
case '[': { // Array
|
||||
if (context & (COLON | COMMA | KEY))
|
||||
goto OnColonCommaKey;
|
||||
- json.setArray();
|
||||
- Json value;
|
||||
+ j.setArray();
|
||||
+ json value;
|
||||
for (context = ARRAY, i = 0;;) {
|
||||
Status status = parse(value, p, e, context, depth - 1);
|
||||
if (status == absent_value)
|
||||
return success;
|
||||
if (status != success)
|
||||
return status;
|
||||
- json.array_value.emplace_back(std::move(value));
|
||||
+ j.array_value.emplace_back(std::move(value));
|
||||
context = ARRAY | COMMA;
|
||||
}
|
||||
}
|
||||
@@ -948,9 +948,9 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
case '{': { // Object
|
||||
if (context & (COLON | COMMA | KEY))
|
||||
goto OnColonCommaKey;
|
||||
- json.setObject();
|
||||
+ j.setObject();
|
||||
context = KEY | OBJECT;
|
||||
- Json key, value;
|
||||
+ json key, value;
|
||||
for (;;) {
|
||||
Status status = parse(key, p, e, context, depth - 1);
|
||||
if (status == absent_value)
|
||||
@@ -964,7 +964,7 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
return object_missing_value;
|
||||
if (status != success)
|
||||
return status;
|
||||
- json.object_value.emplace(std::move(key.string_value),
|
||||
+ j.object_value.emplace(std::move(key.string_value),
|
||||
std::move(value));
|
||||
context = KEY | COMMA | OBJECT;
|
||||
key.clear();
|
||||
@@ -985,8 +985,8 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
break;
|
||||
|
||||
case DQUOTE:
|
||||
- json.type_ = String;
|
||||
- new (&json.string_value) std::string(std::move(b));
|
||||
+ j.type_ = String;
|
||||
+ new (&j.string_value) std::string(std::move(b));
|
||||
return success;
|
||||
|
||||
case BACKSLASH:
|
||||
@@ -1221,16 +1221,16 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
|
||||
return unexpected_eof;
|
||||
}
|
||||
|
||||
-std::pair<Json::Status, Json>
|
||||
-Json::parse(const std::string& s)
|
||||
+std::pair<json::Status, json>
|
||||
+json::parse(const std::string& s)
|
||||
{
|
||||
- Json::Status s2;
|
||||
- std::pair<Json::Status, Json> res;
|
||||
+ json::Status s2;
|
||||
+ std::pair<json::Status, json> res;
|
||||
const char* p = s.data();
|
||||
const char* e = s.data() + s.size();
|
||||
res.first = parse(res.second, p, e, 0, DEPTH);
|
||||
- if (res.first == Json::success) {
|
||||
- Json j2;
|
||||
+ if (res.first == json::success) {
|
||||
+ json j2;
|
||||
s2 = parse(j2, p, e, 0, DEPTH);
|
||||
if (s2 != absent_value)
|
||||
res.first = trailing_content;
|
||||
@@ -1239,7 +1239,7 @@ Json::parse(const std::string& s)
|
||||
}
|
||||
|
||||
const char*
|
||||
-Json::StatusToString(Json::Status status)
|
||||
+json::StatusToString(json::Status status)
|
||||
{
|
||||
switch (status) {
|
||||
case success:
|
||||
diff --git a/json.h b/json.h
|
||||
index c676e651d7c2591a0fb07d8d8b28738cbd1defab..b1f175cf070c6b0dbebffdc60c38954c14f77745 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace wpi::util {
|
||||
|
||||
-class Json
|
||||
+class json
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
@@ -83,55 +83,55 @@ class Json
|
||||
double double_value;
|
||||
long long long_value;
|
||||
std::string string_value;
|
||||
- std::vector<Json> array_value;
|
||||
- std::map<std::string, Json> object_value;
|
||||
+ std::vector<json> array_value;
|
||||
+ std::map<std::string, json> object_value;
|
||||
};
|
||||
|
||||
public:
|
||||
static const char* StatusToString(Status);
|
||||
- static std::pair<Status, Json> parse(const std::string&);
|
||||
+ static std::pair<Status, json> parse(const std::string&);
|
||||
|
||||
- Json(const Json&);
|
||||
- Json(Json&&);
|
||||
- Json(unsigned long);
|
||||
- Json(unsigned long long);
|
||||
- Json(const char*);
|
||||
- Json(const std::string&);
|
||||
- ~Json();
|
||||
+ json(const json&);
|
||||
+ json(json&&);
|
||||
+ json(unsigned long);
|
||||
+ json(unsigned long long);
|
||||
+ json(const char*);
|
||||
+ json(const std::string&);
|
||||
+ ~json();
|
||||
|
||||
- Json(const std::nullptr_t = nullptr) : type_(Null)
|
||||
+ json(const std::nullptr_t = nullptr) : type_(Null)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(bool value) : type_(Bool), bool_value(value)
|
||||
+ json(bool value) : type_(Bool), bool_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(int value) : type_(Long), long_value(value)
|
||||
+ json(int value) : type_(Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(float value) : type_(Float), float_value(value)
|
||||
+ json(float value) : type_(Float), float_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(unsigned value) : type_(Long), long_value(value)
|
||||
+ json(unsigned value) : type_(Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(long value) : type_(Long), long_value(value)
|
||||
+ json(long value) : type_(Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(long long value) : type_(Long), long_value(value)
|
||||
+ json(long long value) : type_(Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(double value) : type_(Double), double_value(value)
|
||||
+ json(double value) : type_(Double), double_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- Json(std::string&& value) : type_(String), string_value(std::move(value))
|
||||
+ json(std::string&& value) : type_(String), string_value(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -191,8 +191,8 @@ class Json
|
||||
double getNumber() const;
|
||||
long long getLong() const;
|
||||
std::string& getString();
|
||||
- std::vector<Json>& getArray();
|
||||
- std::map<std::string, Json>& getObject();
|
||||
+ std::vector<json>& getArray();
|
||||
+ std::map<std::string, json>& getObject();
|
||||
|
||||
bool contains(const std::string&) const;
|
||||
|
||||
@@ -202,11 +202,11 @@ class Json
|
||||
std::string toString() const;
|
||||
std::string toStringPretty() const;
|
||||
|
||||
- Json& operator=(const Json&);
|
||||
- Json& operator=(Json&&);
|
||||
+ json& operator=(const json&);
|
||||
+ json& operator=(json&&);
|
||||
|
||||
- Json& operator[](size_t);
|
||||
- Json& operator[](const std::string&);
|
||||
+ json& operator[](size_t);
|
||||
+ json& operator[](const std::string&);
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
@@ -218,7 +218,7 @@ class Json
|
||||
void marshal(std::string&, bool, int) const;
|
||||
static void stringify(std::string&, const std::string&);
|
||||
static void serialize(std::string&, const std::string&);
|
||||
- static Status parse(Json&, const char*&, const char*, int, int);
|
||||
+ static Status parse(json&, const char*&, const char*, int, int);
|
||||
};
|
||||
|
||||
} // namespace wpi::util
|
||||
286
upstream_utils/json_patches/0003-Use-snake_case-names.patch
Normal file
286
upstream_utils/json_patches/0003-Use-snake_case-names.patch
Normal file
@@ -0,0 +1,286 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sun, 29 Mar 2026 16:50:21 -0700
|
||||
Subject: [PATCH 03/25] Use snake_case names
|
||||
|
||||
---
|
||||
json.cpp | 40 ++++++++++++++++++++--------------------
|
||||
json.h | 48 ++++++++++++++++++++++++------------------------
|
||||
2 files changed, 44 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 3e59a885b55d3fddc418903112595fe5de223f34..939efbcf8e550e7c48d180f81be39b476c5990fe 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -448,7 +448,7 @@ json::operator=(json&& other)
|
||||
}
|
||||
|
||||
double
|
||||
-json::getNumber() const
|
||||
+json::get_number() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Long:
|
||||
@@ -463,7 +463,7 @@ json::getNumber() const
|
||||
}
|
||||
|
||||
long long
|
||||
-json::getLong() const
|
||||
+json::get_long() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Long:
|
||||
@@ -474,7 +474,7 @@ json::getLong() const
|
||||
}
|
||||
|
||||
bool
|
||||
-json::getBool() const
|
||||
+json::get_bool() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Bool:
|
||||
@@ -485,7 +485,7 @@ json::getBool() const
|
||||
}
|
||||
|
||||
float
|
||||
-json::getFloat() const
|
||||
+json::get_float() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Float:
|
||||
@@ -498,7 +498,7 @@ json::getFloat() const
|
||||
}
|
||||
|
||||
double
|
||||
-json::getDouble() const
|
||||
+json::get_double() const
|
||||
{
|
||||
switch (type_) {
|
||||
case Float:
|
||||
@@ -511,7 +511,7 @@ json::getDouble() const
|
||||
}
|
||||
|
||||
std::string&
|
||||
-json::getString()
|
||||
+json::get_string()
|
||||
{
|
||||
switch (type_) {
|
||||
case String:
|
||||
@@ -522,7 +522,7 @@ json::getString()
|
||||
}
|
||||
|
||||
std::vector<json>&
|
||||
-json::getArray()
|
||||
+json::get_array()
|
||||
{
|
||||
switch (type_) {
|
||||
case Array:
|
||||
@@ -533,7 +533,7 @@ json::getArray()
|
||||
}
|
||||
|
||||
std::map<std::string, json>&
|
||||
-json::getObject()
|
||||
+json::get_object()
|
||||
{
|
||||
switch (type_) {
|
||||
case Object:
|
||||
@@ -544,7 +544,7 @@ json::getObject()
|
||||
}
|
||||
|
||||
void
|
||||
-json::setArray()
|
||||
+json::set_array()
|
||||
{
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
@@ -553,7 +553,7 @@ json::setArray()
|
||||
}
|
||||
|
||||
void
|
||||
-json::setObject()
|
||||
+json::set_object()
|
||||
{
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
@@ -564,7 +564,7 @@ json::setObject()
|
||||
bool
|
||||
json::contains(const std::string& key) const
|
||||
{
|
||||
- if (!isObject())
|
||||
+ if (!is_object())
|
||||
return false;
|
||||
return object_value.find(key) != object_value.end();
|
||||
}
|
||||
@@ -572,8 +572,8 @@ json::contains(const std::string& key) const
|
||||
json&
|
||||
json::operator[](size_t index)
|
||||
{
|
||||
- if (!isArray())
|
||||
- setArray();
|
||||
+ if (!is_array())
|
||||
+ set_array();
|
||||
if (index >= array_value.size()) {
|
||||
array_value.resize(index + 1);
|
||||
}
|
||||
@@ -583,13 +583,13 @@ json::operator[](size_t index)
|
||||
json&
|
||||
json::operator[](const std::string& key)
|
||||
{
|
||||
- if (!isObject())
|
||||
- setObject();
|
||||
+ if (!is_object())
|
||||
+ set_object();
|
||||
return object_value[key];
|
||||
}
|
||||
|
||||
std::string
|
||||
-json::toString() const
|
||||
+json::to_string() const
|
||||
{
|
||||
std::string b;
|
||||
marshal(b, false, 0);
|
||||
@@ -597,7 +597,7 @@ json::toString() const
|
||||
}
|
||||
|
||||
std::string
|
||||
-json::toStringPretty() const
|
||||
+json::to_string_pretty() const
|
||||
{
|
||||
std::string b;
|
||||
marshal(b, true, 0);
|
||||
@@ -922,7 +922,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
case '[': { // Array
|
||||
if (context & (COLON | COMMA | KEY))
|
||||
goto OnColonCommaKey;
|
||||
- j.setArray();
|
||||
+ j.set_array();
|
||||
json value;
|
||||
for (context = ARRAY, i = 0;;) {
|
||||
Status status = parse(value, p, e, context, depth - 1);
|
||||
@@ -948,7 +948,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
case '{': { // Object
|
||||
if (context & (COLON | COMMA | KEY))
|
||||
goto OnColonCommaKey;
|
||||
- j.setObject();
|
||||
+ j.set_object();
|
||||
context = KEY | OBJECT;
|
||||
json key, value;
|
||||
for (;;) {
|
||||
@@ -957,7 +957,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
return success;
|
||||
if (status != success)
|
||||
return status;
|
||||
- if (!key.isString())
|
||||
+ if (!key.is_string())
|
||||
return object_key_must_be_string;
|
||||
status = parse(value, p, e, COLON, depth - 1);
|
||||
if (status == absent_value)
|
||||
diff --git a/json.h b/json.h
|
||||
index b1f175cf070c6b0dbebffdc60c38954c14f77745..bf250d3aacb3508601e1e5d61531ec5e8248ebdb 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -135,72 +135,72 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
- Type getType() const
|
||||
+ Type type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
- bool isNull() const
|
||||
+ bool is_null() const
|
||||
{
|
||||
return type_ == Null;
|
||||
}
|
||||
|
||||
- bool isBool() const
|
||||
+ bool is_bool() const
|
||||
{
|
||||
return type_ == Bool;
|
||||
}
|
||||
|
||||
- bool isNumber() const
|
||||
+ bool is_number() const
|
||||
{
|
||||
- return isFloat() || isDouble() || isLong();
|
||||
+ return is_float() || is_double() || is_long();
|
||||
}
|
||||
|
||||
- bool isLong() const
|
||||
+ bool is_long() const
|
||||
{
|
||||
return type_ == Long;
|
||||
}
|
||||
|
||||
- bool isFloat() const
|
||||
+ bool is_float() const
|
||||
{
|
||||
return type_ == Float;
|
||||
}
|
||||
|
||||
- bool isDouble() const
|
||||
+ bool is_double() const
|
||||
{
|
||||
return type_ == Double;
|
||||
}
|
||||
|
||||
- bool isString() const
|
||||
+ bool is_string() const
|
||||
{
|
||||
return type_ == String;
|
||||
}
|
||||
|
||||
- bool isArray() const
|
||||
+ bool is_array() const
|
||||
{
|
||||
return type_ == Array;
|
||||
}
|
||||
|
||||
- bool isObject() const
|
||||
+ bool is_object() const
|
||||
{
|
||||
return type_ == Object;
|
||||
}
|
||||
|
||||
- bool getBool() const;
|
||||
- float getFloat() const;
|
||||
- double getDouble() const;
|
||||
- double getNumber() const;
|
||||
- long long getLong() const;
|
||||
- std::string& getString();
|
||||
- std::vector<json>& getArray();
|
||||
- std::map<std::string, json>& getObject();
|
||||
+ bool get_bool() const;
|
||||
+ float get_float() const;
|
||||
+ double get_double() const;
|
||||
+ double get_number() const;
|
||||
+ long long get_long() const;
|
||||
+ std::string& get_string();
|
||||
+ std::vector<json>& get_array();
|
||||
+ std::map<std::string, json>& get_object();
|
||||
|
||||
bool contains(const std::string&) const;
|
||||
|
||||
- void setArray();
|
||||
- void setObject();
|
||||
+ void set_array();
|
||||
+ void set_object();
|
||||
|
||||
- std::string toString() const;
|
||||
- std::string toStringPretty() const;
|
||||
+ std::string to_string() const;
|
||||
+ std::string to_string_pretty() const;
|
||||
|
||||
json& operator=(const json&);
|
||||
json& operator=(json&&);
|
||||
@@ -210,7 +210,7 @@ class json
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
- return toString();
|
||||
+ return to_string();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 07:31:40 -0700
|
||||
Subject: [PATCH 04/25] Suppress pedantic warning
|
||||
|
||||
---
|
||||
jtckdint.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/jtckdint.h b/jtckdint.h
|
||||
index 4c71d9990ca233017332f3ede71b092da48b474f..ac6a52e5aab04116defe1d06b3831d3509fea8a2 100644
|
||||
--- a/jtckdint.h
|
||||
+++ b/jtckdint.h
|
||||
@@ -57,6 +57,10 @@
|
||||
#ifndef JTCKDINT_H_
|
||||
#define JTCKDINT_H_
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
+#endif
|
||||
+
|
||||
#ifdef __has_include
|
||||
#define __ckd_has_include(x) __has_include(x)
|
||||
#else
|
||||
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 07:32:33 -0700
|
||||
Subject: [PATCH 05/25] Suppress type limits warning
|
||||
|
||||
---
|
||||
json.cpp | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 939efbcf8e550e7c48d180f81be39b476c5990fe..8f45bb573deed5b8c7afaf3fe2b6b40fa21555c1 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -28,6 +28,10 @@
|
||||
#include "double-conversion/double-to-string.h"
|
||||
#include "double-conversion/string-to-double.h"
|
||||
|
||||
+#ifdef __GNUC__
|
||||
+#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
+#endif
|
||||
+
|
||||
#define KEY 1
|
||||
#define COMMA 2
|
||||
#define COLON 4
|
||||
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 07:33:06 -0700
|
||||
Subject: [PATCH 06/25] Update double-conversion include for wpi
|
||||
|
||||
---
|
||||
json.cpp | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 8f45bb573deed5b8c7afaf3fe2b6b40fa21555c1..87433664d2caf96b1c8f5b80eb4f4cc8d3d34f7e 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -25,8 +25,8 @@
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
|
||||
-#include "double-conversion/double-to-string.h"
|
||||
-#include "double-conversion/string-to-double.h"
|
||||
+#include "wpi/double-conversion/double-to-string.h"
|
||||
+#include "wpi/double-conversion/string-to-double.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
@@ -0,0 +1,155 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 07:51:30 -0700
|
||||
Subject: [PATCH 07/25] Use typedefs for array and object types
|
||||
|
||||
---
|
||||
json.cpp | 32 ++++++++++++++------------------
|
||||
json.h | 11 +++++++----
|
||||
2 files changed, 21 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 87433664d2caf96b1c8f5b80eb4f4cc8d3d34f7e..8fd64748250d9cd71fd31b8caf4281183e31b053 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -296,10 +296,10 @@ json::clear()
|
||||
string_value.~basic_string();
|
||||
break;
|
||||
case Array:
|
||||
- array_value.~vector();
|
||||
+ array_value.~array_t();
|
||||
break;
|
||||
case Object:
|
||||
- object_value.~map();
|
||||
+ object_value.~object_t();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -328,10 +328,10 @@ json::json(const json& other) : type_(other.type_)
|
||||
new (&string_value) std::string(other.string_value);
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value) std::vector<json>(other.array_value);
|
||||
+ new (&array_value) array_t(other.array_value);
|
||||
break;
|
||||
case Object:
|
||||
- new (&object_value) std::map<std::string, json>(other.object_value);
|
||||
+ new (&object_value) object_t(other.object_value);
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
@@ -364,11 +364,10 @@ json::operator=(const json& other)
|
||||
new (&string_value) std::string(other.string_value);
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value) std::vector<json>(other.array_value);
|
||||
+ new (&array_value) array_t(other.array_value);
|
||||
break;
|
||||
case Object:
|
||||
- new (&object_value)
|
||||
- std::map<std::string, json>(other.object_value);
|
||||
+ new (&object_value) object_t(other.object_value);
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
@@ -398,11 +397,10 @@ json::json(json&& other) : type_(other.type_)
|
||||
new (&string_value) std::string(std::move(other.string_value));
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value) std::vector<json>(std::move(other.array_value));
|
||||
+ new (&array_value) array_t(std::move(other.array_value));
|
||||
break;
|
||||
case Object:
|
||||
- new (&object_value)
|
||||
- std::map<std::string, json>(std::move(other.object_value));
|
||||
+ new (&object_value) object_t(std::move(other.object_value));
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
@@ -436,12 +434,10 @@ json::operator=(json&& other)
|
||||
new (&string_value) std::string(std::move(other.string_value));
|
||||
break;
|
||||
case Array:
|
||||
- new (&array_value)
|
||||
- std::vector<json>(std::move(other.array_value));
|
||||
+ new (&array_value) array_t(std::move(other.array_value));
|
||||
break;
|
||||
case Object:
|
||||
- new (&object_value)
|
||||
- std::map<std::string, json>(std::move(other.object_value));
|
||||
+ new (&object_value) object_t(std::move(other.object_value));
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");;
|
||||
@@ -525,7 +521,7 @@ json::get_string()
|
||||
}
|
||||
}
|
||||
|
||||
-std::vector<json>&
|
||||
+json::array_t&
|
||||
json::get_array()
|
||||
{
|
||||
switch (type_) {
|
||||
@@ -536,7 +532,7 @@ json::get_array()
|
||||
}
|
||||
}
|
||||
|
||||
-std::map<std::string, json>&
|
||||
+json::object_t&
|
||||
json::get_object()
|
||||
{
|
||||
switch (type_) {
|
||||
@@ -553,7 +549,7 @@ json::set_array()
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
type_ = Array;
|
||||
- new (&array_value) std::vector<json>();
|
||||
+ new (&array_value) array_t();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -562,7 +558,7 @@ json::set_object()
|
||||
if (type_ >= String)
|
||||
clear();
|
||||
type_ = Object;
|
||||
- new (&object_value) std::map<std::string, json>();
|
||||
+ new (&object_value) object_t();
|
||||
}
|
||||
|
||||
bool
|
||||
diff --git a/json.h b/json.h
|
||||
index bf250d3aacb3508601e1e5d61531ec5e8248ebdb..e25116a7f7c26525028b11928e665c1883b3ba65 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -25,6 +25,9 @@ namespace wpi::util {
|
||||
class json
|
||||
{
|
||||
public:
|
||||
+ using array_t = std::vector<json>;
|
||||
+ using object_t = std::map<std::string, json>;
|
||||
+
|
||||
enum Type
|
||||
{
|
||||
Null,
|
||||
@@ -83,8 +86,8 @@ class json
|
||||
double double_value;
|
||||
long long long_value;
|
||||
std::string string_value;
|
||||
- std::vector<json> array_value;
|
||||
- std::map<std::string, json> object_value;
|
||||
+ array_t array_value;
|
||||
+ object_t object_value;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -191,8 +194,8 @@ class json
|
||||
double get_number() const;
|
||||
long long get_long() const;
|
||||
std::string& get_string();
|
||||
- std::vector<json>& get_array();
|
||||
- std::map<std::string, json>& get_object();
|
||||
+ array_t& get_array();
|
||||
+ object_t& get_object();
|
||||
|
||||
bool contains(const std::string&) const;
|
||||
|
||||
@@ -0,0 +1,582 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 07:56:14 -0700
|
||||
Subject: [PATCH 08/25] Change Type to an enum class
|
||||
|
||||
---
|
||||
json.cpp | 156 +++++++++++++++++++++++++++----------------------------
|
||||
json.h | 36 ++++++-------
|
||||
2 files changed, 96 insertions(+), 96 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 8fd64748250d9cd71fd31b8caf4281183e31b053..88ce30f8669a02cdc54e741a2a5a0663953d4acb 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -249,10 +249,10 @@ LongToString(char* p, long long x)
|
||||
json::json(unsigned long value)
|
||||
{
|
||||
if (value <= LLONG_MAX) {
|
||||
- type_ = Long;
|
||||
+ type_ = Type::Long;
|
||||
long_value = value;
|
||||
} else {
|
||||
- type_ = Double;
|
||||
+ type_ = Type::Double;
|
||||
double_value = value;
|
||||
}
|
||||
}
|
||||
@@ -260,10 +260,10 @@ json::json(unsigned long value)
|
||||
json::json(unsigned long long value)
|
||||
{
|
||||
if (value <= LLONG_MAX) {
|
||||
- type_ = Long;
|
||||
+ type_ = Type::Long;
|
||||
long_value = value;
|
||||
} else {
|
||||
- type_ = Double;
|
||||
+ type_ = Type::Double;
|
||||
double_value = value;
|
||||
}
|
||||
}
|
||||
@@ -271,20 +271,20 @@ json::json(unsigned long long value)
|
||||
json::json(const char* value)
|
||||
{
|
||||
if (value) {
|
||||
- type_ = String;
|
||||
+ type_ = Type::String;
|
||||
new (&string_value) std::string(value);
|
||||
} else {
|
||||
- type_ = Null;
|
||||
+ type_ = Type::Null;
|
||||
}
|
||||
}
|
||||
|
||||
-json::json(const std::string& value) : type_(String), string_value(value)
|
||||
+json::json(const std::string& value) : type_(Type::String), string_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
json::~json()
|
||||
{
|
||||
- if (type_ >= String)
|
||||
+ if (type_ >= Type::String)
|
||||
clear();
|
||||
}
|
||||
|
||||
@@ -292,45 +292,45 @@ void
|
||||
json::clear()
|
||||
{
|
||||
switch (type_) {
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
string_value.~basic_string();
|
||||
break;
|
||||
- case Array:
|
||||
+ case Type::Array:
|
||||
array_value.~array_t();
|
||||
break;
|
||||
- case Object:
|
||||
+ case Type::Object:
|
||||
object_value.~object_t();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
- type_ = Null;
|
||||
+ type_ = Type::Null;
|
||||
}
|
||||
|
||||
json::json(const json& other) : type_(other.type_)
|
||||
{
|
||||
switch (type_) {
|
||||
- case Null:
|
||||
+ case Type::Null:
|
||||
break;
|
||||
- case Bool:
|
||||
+ case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Long:
|
||||
+ case Type::Long:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
double_value = other.double_value;
|
||||
break;
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
new (&string_value) std::string(other.string_value);
|
||||
break;
|
||||
- case Array:
|
||||
+ case Type::Array:
|
||||
new (&array_value) array_t(other.array_value);
|
||||
break;
|
||||
- case Object:
|
||||
+ case Type::Object:
|
||||
new (&object_value) object_t(other.object_value);
|
||||
break;
|
||||
default:
|
||||
@@ -342,31 +342,31 @@ json&
|
||||
json::operator=(const json& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
- if (type_ >= String)
|
||||
+ if (type_ >= Type::String)
|
||||
clear();
|
||||
type_ = other.type_;
|
||||
switch (type_) {
|
||||
- case Null:
|
||||
+ case Type::Null:
|
||||
break;
|
||||
- case Bool:
|
||||
+ case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Long:
|
||||
+ case Type::Long:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
double_value = other.double_value;
|
||||
break;
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
new (&string_value) std::string(other.string_value);
|
||||
break;
|
||||
- case Array:
|
||||
+ case Type::Array:
|
||||
new (&array_value) array_t(other.array_value);
|
||||
break;
|
||||
- case Object:
|
||||
+ case Type::Object:
|
||||
new (&object_value) object_t(other.object_value);
|
||||
break;
|
||||
default:
|
||||
@@ -379,70 +379,70 @@ json::operator=(const json& other)
|
||||
json::json(json&& other) : type_(other.type_)
|
||||
{
|
||||
switch (type_) {
|
||||
- case Null:
|
||||
+ case Type::Null:
|
||||
break;
|
||||
- case Bool:
|
||||
+ case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Long:
|
||||
+ case Type::Long:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
double_value = other.double_value;
|
||||
break;
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
new (&string_value) std::string(std::move(other.string_value));
|
||||
break;
|
||||
- case Array:
|
||||
+ case Type::Array:
|
||||
new (&array_value) array_t(std::move(other.array_value));
|
||||
break;
|
||||
- case Object:
|
||||
+ case Type::Object:
|
||||
new (&object_value) object_t(std::move(other.object_value));
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
}
|
||||
- other.type_ = Null;
|
||||
+ other.type_ = Type::Null;
|
||||
}
|
||||
|
||||
json&
|
||||
json::operator=(json&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
- if (type_ >= String)
|
||||
+ if (type_ >= Type::String)
|
||||
clear();
|
||||
type_ = other.type_;
|
||||
switch (type_) {
|
||||
- case Null:
|
||||
+ case Type::Null:
|
||||
break;
|
||||
- case Bool:
|
||||
+ case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Long:
|
||||
+ case Type::Long:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
double_value = other.double_value;
|
||||
break;
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
new (&string_value) std::string(std::move(other.string_value));
|
||||
break;
|
||||
- case Array:
|
||||
+ case Type::Array:
|
||||
new (&array_value) array_t(std::move(other.array_value));
|
||||
break;
|
||||
- case Object:
|
||||
+ case Type::Object:
|
||||
new (&object_value) object_t(std::move(other.object_value));
|
||||
break;
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");;
|
||||
}
|
||||
- other.type_ = Null;
|
||||
+ other.type_ = Type::Null;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -451,11 +451,11 @@ double
|
||||
json::get_number() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Long:
|
||||
+ case Type::Long:
|
||||
return long_value;
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
return float_value;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
return double_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a number.");
|
||||
@@ -466,7 +466,7 @@ long long
|
||||
json::get_long() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Long:
|
||||
+ case Type::Long:
|
||||
return long_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a long.");
|
||||
@@ -477,7 +477,7 @@ bool
|
||||
json::get_bool() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Bool:
|
||||
+ case Type::Bool:
|
||||
return bool_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a bool.");
|
||||
@@ -488,9 +488,9 @@ float
|
||||
json::get_float() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
return float_value;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
return double_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a floating-point number.");
|
||||
@@ -501,9 +501,9 @@ double
|
||||
json::get_double() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Float:
|
||||
+ case Type::Float:
|
||||
return float_value;
|
||||
- case Double:
|
||||
+ case Type::Double:
|
||||
return double_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a floating-point number.");
|
||||
@@ -514,7 +514,7 @@ std::string&
|
||||
json::get_string()
|
||||
{
|
||||
switch (type_) {
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
return string_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a string.");
|
||||
@@ -525,7 +525,7 @@ json::array_t&
|
||||
json::get_array()
|
||||
{
|
||||
switch (type_) {
|
||||
- case Array:
|
||||
+ case Type::Array:
|
||||
return array_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not an array.");
|
||||
@@ -536,7 +536,7 @@ json::object_t&
|
||||
json::get_object()
|
||||
{
|
||||
switch (type_) {
|
||||
- case Object:
|
||||
+ case Type::Object:
|
||||
return object_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not an object.");
|
||||
@@ -546,18 +546,18 @@ json::get_object()
|
||||
void
|
||||
json::set_array()
|
||||
{
|
||||
- if (type_ >= String)
|
||||
+ if (type_ >= Type::String)
|
||||
clear();
|
||||
- type_ = Array;
|
||||
+ type_ = Type::Array;
|
||||
new (&array_value) array_t();
|
||||
}
|
||||
|
||||
void
|
||||
json::set_object()
|
||||
{
|
||||
- if (type_ >= String)
|
||||
+ if (type_ >= Type::String)
|
||||
clear();
|
||||
- type_ = Object;
|
||||
+ type_ = Type::Object;
|
||||
new (&object_value) object_t();
|
||||
}
|
||||
|
||||
@@ -608,21 +608,21 @@ void
|
||||
json::marshal(std::string& b, bool pretty, int indent) const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Null:
|
||||
+ case Type::Null:
|
||||
b += "null";
|
||||
break;
|
||||
- case String:
|
||||
+ case Type::String:
|
||||
stringify(b, string_value);
|
||||
break;
|
||||
- case Bool:
|
||||
+ case Type::Bool:
|
||||
b += bool_value ? "true" : "false";
|
||||
break;
|
||||
- case Long: {
|
||||
+ case Type::Long: {
|
||||
char buf[64];
|
||||
b.append(buf, LongToString(buf, long_value) - buf);
|
||||
break;
|
||||
}
|
||||
- case Float: {
|
||||
+ case Type::Float: {
|
||||
char buf[128];
|
||||
double_conversion::StringBuilder db(buf, 128);
|
||||
kDoubleToJson.ToShortestSingle(float_value, &db);
|
||||
@@ -630,7 +630,7 @@ json::marshal(std::string& b, bool pretty, int indent) const
|
||||
b += buf;
|
||||
break;
|
||||
}
|
||||
- case Double: {
|
||||
+ case Type::Double: {
|
||||
char buf[128];
|
||||
double_conversion::StringBuilder db(buf, 128);
|
||||
kDoubleToJson.ToShortest(double_value, &db);
|
||||
@@ -638,7 +638,7 @@ json::marshal(std::string& b, bool pretty, int indent) const
|
||||
b += buf;
|
||||
break;
|
||||
}
|
||||
- case Array: {
|
||||
+ case Type::Array: {
|
||||
bool once = false;
|
||||
b += '[';
|
||||
for (auto i = array_value.begin(); i != array_value.end(); ++i) {
|
||||
@@ -654,7 +654,7 @@ json::marshal(std::string& b, bool pretty, int indent) const
|
||||
b += ']';
|
||||
break;
|
||||
}
|
||||
- case Object: {
|
||||
+ case Type::Object: {
|
||||
bool once = false;
|
||||
b += '{';
|
||||
for (auto i = object_value.begin(); i != object_value.end(); ++i) {
|
||||
@@ -818,7 +818,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
if (context & (KEY | COLON | COMMA))
|
||||
goto OnColonCommaKey;
|
||||
if (p + 4 <= e && READ32LE(p) == READ32LE("alse")) {
|
||||
- j.type_ = Bool;
|
||||
+ j.type_ = Type::Bool;
|
||||
j.bool_value = false;
|
||||
p += 4;
|
||||
return success;
|
||||
@@ -830,7 +830,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
if (context & (KEY | COLON | COMMA))
|
||||
goto OnColonCommaKey;
|
||||
if (p + 3 <= e && READ32LE(p - 1) == READ32LE("true")) {
|
||||
- j.type_ = Bool;
|
||||
+ j.type_ = Type::Bool;
|
||||
j.bool_value = true;
|
||||
p += 3;
|
||||
return success;
|
||||
@@ -873,7 +873,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
return unexpected_octal;
|
||||
}
|
||||
}
|
||||
- j.type_ = Long;
|
||||
+ j.type_ = Type::Long;
|
||||
j.long_value = 0;
|
||||
return success;
|
||||
|
||||
@@ -905,12 +905,12 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
- j.type_ = Long;
|
||||
+ j.type_ = Type::Long;
|
||||
j.long_value = x;
|
||||
return success;
|
||||
|
||||
UseDubble: // number
|
||||
- j.type_ = Double;
|
||||
+ j.type_ = Type::Double;
|
||||
j.double_value = StringToDouble(a, e - a, &c);
|
||||
if (c <= 0)
|
||||
return bad_double;
|
||||
@@ -985,7 +985,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
break;
|
||||
|
||||
case DQUOTE:
|
||||
- j.type_ = String;
|
||||
+ j.type_ = Type::String;
|
||||
new (&j.string_value) std::string(std::move(b));
|
||||
return success;
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index e25116a7f7c26525028b11928e665c1883b3ba65..3d2cb52a1bfeafb5f1a8a1e9c6057a2611cbb41e 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -28,7 +28,7 @@ class json
|
||||
using array_t = std::vector<json>;
|
||||
using object_t = std::map<std::string, json>;
|
||||
|
||||
- enum Type
|
||||
+ enum class Type
|
||||
{
|
||||
Null,
|
||||
Bool,
|
||||
@@ -102,39 +102,39 @@ class json
|
||||
json(const std::string&);
|
||||
~json();
|
||||
|
||||
- json(const std::nullptr_t = nullptr) : type_(Null)
|
||||
+ json(const std::nullptr_t = nullptr) : type_(Type::Null)
|
||||
{
|
||||
}
|
||||
|
||||
- json(bool value) : type_(Bool), bool_value(value)
|
||||
+ json(bool value) : type_(Type::Bool), bool_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(int value) : type_(Long), long_value(value)
|
||||
+ json(int value) : type_(Type::Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(float value) : type_(Float), float_value(value)
|
||||
+ json(float value) : type_(Type::Float), float_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(unsigned value) : type_(Long), long_value(value)
|
||||
+ json(unsigned value) : type_(Type::Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(long value) : type_(Long), long_value(value)
|
||||
+ json(long value) : type_(Type::Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(long long value) : type_(Long), long_value(value)
|
||||
+ json(long long value) : type_(Type::Long), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(double value) : type_(Double), double_value(value)
|
||||
+ json(double value) : type_(Type::Double), double_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(std::string&& value) : type_(String), string_value(std::move(value))
|
||||
+ json(std::string&& value) : type_(Type::String), string_value(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -145,12 +145,12 @@ class json
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
- return type_ == Null;
|
||||
+ return type_ == Type::Null;
|
||||
}
|
||||
|
||||
bool is_bool() const
|
||||
{
|
||||
- return type_ == Bool;
|
||||
+ return type_ == Type::Bool;
|
||||
}
|
||||
|
||||
bool is_number() const
|
||||
@@ -160,32 +160,32 @@ class json
|
||||
|
||||
bool is_long() const
|
||||
{
|
||||
- return type_ == Long;
|
||||
+ return type_ == Type::Long;
|
||||
}
|
||||
|
||||
bool is_float() const
|
||||
{
|
||||
- return type_ == Float;
|
||||
+ return type_ == Type::Float;
|
||||
}
|
||||
|
||||
bool is_double() const
|
||||
{
|
||||
- return type_ == Double;
|
||||
+ return type_ == Type::Double;
|
||||
}
|
||||
|
||||
bool is_string() const
|
||||
{
|
||||
- return type_ == String;
|
||||
+ return type_ == Type::String;
|
||||
}
|
||||
|
||||
bool is_array() const
|
||||
{
|
||||
- return type_ == Array;
|
||||
+ return type_ == Type::Array;
|
||||
}
|
||||
|
||||
bool is_object() const
|
||||
{
|
||||
- return type_ == Object;
|
||||
+ return type_ == Type::Object;
|
||||
}
|
||||
|
||||
bool get_bool() const;
|
||||
183
upstream_utils/json_patches/0009-Rename-long-to-int.patch
Normal file
183
upstream_utils/json_patches/0009-Rename-long-to-int.patch
Normal file
@@ -0,0 +1,183 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 08:02:21 -0700
|
||||
Subject: [PATCH 09/25] Rename long to int
|
||||
|
||||
---
|
||||
json.cpp | 24 ++++++++++++------------
|
||||
json.h | 18 +++++++++---------
|
||||
2 files changed, 21 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 88ce30f8669a02cdc54e741a2a5a0663953d4acb..1266aa36b43155cbab6fe8d918fed2c56596f7a8 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -249,7 +249,7 @@ LongToString(char* p, long long x)
|
||||
json::json(unsigned long value)
|
||||
{
|
||||
if (value <= LLONG_MAX) {
|
||||
- type_ = Type::Long;
|
||||
+ type_ = Type::Int;
|
||||
long_value = value;
|
||||
} else {
|
||||
type_ = Type::Double;
|
||||
@@ -260,7 +260,7 @@ json::json(unsigned long value)
|
||||
json::json(unsigned long long value)
|
||||
{
|
||||
if (value <= LLONG_MAX) {
|
||||
- type_ = Type::Long;
|
||||
+ type_ = Type::Int;
|
||||
long_value = value;
|
||||
} else {
|
||||
type_ = Type::Double;
|
||||
@@ -315,7 +315,7 @@ json::json(const json& other) : type_(other.type_)
|
||||
case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Type::Long:
|
||||
+ case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
case Type::Float:
|
||||
@@ -351,7 +351,7 @@ json::operator=(const json& other)
|
||||
case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Type::Long:
|
||||
+ case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
case Type::Float:
|
||||
@@ -384,7 +384,7 @@ json::json(json&& other) : type_(other.type_)
|
||||
case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Type::Long:
|
||||
+ case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
case Type::Float:
|
||||
@@ -421,7 +421,7 @@ json::operator=(json&& other)
|
||||
case Type::Bool:
|
||||
bool_value = other.bool_value;
|
||||
break;
|
||||
- case Type::Long:
|
||||
+ case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
case Type::Float:
|
||||
@@ -451,7 +451,7 @@ double
|
||||
json::get_number() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Type::Long:
|
||||
+ case Type::Int:
|
||||
return long_value;
|
||||
case Type::Float:
|
||||
return float_value;
|
||||
@@ -463,10 +463,10 @@ json::get_number() const
|
||||
}
|
||||
|
||||
long long
|
||||
-json::get_long() const
|
||||
+json::get_int() const
|
||||
{
|
||||
switch (type_) {
|
||||
- case Type::Long:
|
||||
+ case Type::Int:
|
||||
return long_value;
|
||||
default:
|
||||
ON_LOGIC_ERROR("JSON value is not a long.");
|
||||
@@ -617,7 +617,7 @@ json::marshal(std::string& b, bool pretty, int indent) const
|
||||
case Type::Bool:
|
||||
b += bool_value ? "true" : "false";
|
||||
break;
|
||||
- case Type::Long: {
|
||||
+ case Type::Int: {
|
||||
char buf[64];
|
||||
b.append(buf, LongToString(buf, long_value) - buf);
|
||||
break;
|
||||
@@ -873,7 +873,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
return unexpected_octal;
|
||||
}
|
||||
}
|
||||
- j.type_ = Type::Long;
|
||||
+ j.type_ = Type::Int;
|
||||
j.long_value = 0;
|
||||
return success;
|
||||
|
||||
@@ -905,7 +905,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
- j.type_ = Type::Long;
|
||||
+ j.type_ = Type::Int;
|
||||
j.long_value = x;
|
||||
return success;
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index 3d2cb52a1bfeafb5f1a8a1e9c6057a2611cbb41e..d9fdfe40c5cce5b306eee42668f9944e11f6aacd 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -32,7 +32,7 @@ class json
|
||||
{
|
||||
Null,
|
||||
Bool,
|
||||
- Long,
|
||||
+ Int,
|
||||
Float,
|
||||
Double,
|
||||
String,
|
||||
@@ -110,7 +110,7 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
- json(int value) : type_(Type::Long), long_value(value)
|
||||
+ json(int value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -118,15 +118,15 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
- json(unsigned value) : type_(Type::Long), long_value(value)
|
||||
+ json(unsigned value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(long value) : type_(Type::Long), long_value(value)
|
||||
+ json(long value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(long long value) : type_(Type::Long), long_value(value)
|
||||
+ json(long long value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ class json
|
||||
|
||||
bool is_number() const
|
||||
{
|
||||
- return is_float() || is_double() || is_long();
|
||||
+ return is_float() || is_double() || is_int();
|
||||
}
|
||||
|
||||
- bool is_long() const
|
||||
+ bool is_int() const
|
||||
{
|
||||
- return type_ == Type::Long;
|
||||
+ return type_ == Type::Int;
|
||||
}
|
||||
|
||||
bool is_float() const
|
||||
@@ -192,7 +192,7 @@ class json
|
||||
float get_float() const;
|
||||
double get_double() const;
|
||||
double get_number() const;
|
||||
- long long get_long() const;
|
||||
+ long long get_int() const;
|
||||
std::string& get_string();
|
||||
array_t& get_array();
|
||||
object_t& get_object();
|
||||
@@ -0,0 +1,102 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 08:04:27 -0700
|
||||
Subject: [PATCH 10/25] Make non-object functions constexpr
|
||||
|
||||
---
|
||||
json.h | 30 +++++++++++++++---------------
|
||||
1 file changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index d9fdfe40c5cce5b306eee42668f9944e11f6aacd..8b09d001acd0a966328301bc89ff72616f106a4b 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -102,35 +102,35 @@ class json
|
||||
json(const std::string&);
|
||||
~json();
|
||||
|
||||
- json(const std::nullptr_t = nullptr) : type_(Type::Null)
|
||||
+ constexpr json(const std::nullptr_t = nullptr) : type_(Type::Null)
|
||||
{
|
||||
}
|
||||
|
||||
- json(bool value) : type_(Type::Bool), bool_value(value)
|
||||
+ constexpr json(bool value) : type_(Type::Bool), bool_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(int value) : type_(Type::Int), long_value(value)
|
||||
+ constexpr json(int value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(float value) : type_(Type::Float), float_value(value)
|
||||
+ constexpr json(float value) : type_(Type::Float), float_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(unsigned value) : type_(Type::Int), long_value(value)
|
||||
+ constexpr json(unsigned value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(long value) : type_(Type::Int), long_value(value)
|
||||
+ constexpr json(long value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(long long value) : type_(Type::Int), long_value(value)
|
||||
+ constexpr json(long long value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
- json(double value) : type_(Type::Double), double_value(value)
|
||||
+ constexpr json(double value) : type_(Type::Double), double_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -138,37 +138,37 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
- Type type() const
|
||||
+ constexpr Type type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
- bool is_null() const
|
||||
+ constexpr bool is_null() const
|
||||
{
|
||||
return type_ == Type::Null;
|
||||
}
|
||||
|
||||
- bool is_bool() const
|
||||
+ constexpr bool is_bool() const
|
||||
{
|
||||
return type_ == Type::Bool;
|
||||
}
|
||||
|
||||
- bool is_number() const
|
||||
+ constexpr bool is_number() const
|
||||
{
|
||||
return is_float() || is_double() || is_int();
|
||||
}
|
||||
|
||||
- bool is_int() const
|
||||
+ constexpr bool is_int() const
|
||||
{
|
||||
return type_ == Type::Int;
|
||||
}
|
||||
|
||||
- bool is_float() const
|
||||
+ constexpr bool is_float() const
|
||||
{
|
||||
return type_ == Type::Float;
|
||||
}
|
||||
|
||||
- bool is_double() const
|
||||
+ constexpr bool is_double() const
|
||||
{
|
||||
return type_ == Type::Double;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 08:13:25 -0700
|
||||
Subject: [PATCH 11/25] Add array and object constructors
|
||||
|
||||
---
|
||||
json.h | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index 8b09d001acd0a966328301bc89ff72616f106a4b..9aa5c889932e720746972d9e8ef1dd8b095e0fb1 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -138,6 +138,14 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
+ json(array_t&& value) : type_(Type::Array), array_value(std::move(value))
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ json(object_t&& value) : type_(Type::Object), object_value(std::move(value))
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
constexpr Type type() const
|
||||
{
|
||||
return type_;
|
||||
@@ -0,0 +1,84 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 08:15:04 -0700
|
||||
Subject: [PATCH 12/25] Add const getters for string, array, and object
|
||||
|
||||
---
|
||||
json.cpp | 33 +++++++++++++++++++++++++++++++++
|
||||
json.h | 3 +++
|
||||
2 files changed, 36 insertions(+)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 1266aa36b43155cbab6fe8d918fed2c56596f7a8..4aebebec76de7628792afbf176f46d61e2f67c43 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -521,6 +521,17 @@ json::get_string()
|
||||
}
|
||||
}
|
||||
|
||||
+const std::string&
|
||||
+json::get_string() const
|
||||
+{
|
||||
+ switch (type_) {
|
||||
+ case Type::String:
|
||||
+ return string_value;
|
||||
+ default:
|
||||
+ ON_LOGIC_ERROR("JSON value is not a string.");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
json::array_t&
|
||||
json::get_array()
|
||||
{
|
||||
@@ -532,6 +543,17 @@ json::get_array()
|
||||
}
|
||||
}
|
||||
|
||||
+const json::array_t&
|
||||
+json::get_array() const
|
||||
+{
|
||||
+ switch (type_) {
|
||||
+ case Type::Array:
|
||||
+ return array_value;
|
||||
+ default:
|
||||
+ ON_LOGIC_ERROR("JSON value is not an array.");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
json::object_t&
|
||||
json::get_object()
|
||||
{
|
||||
@@ -543,6 +565,17 @@ json::get_object()
|
||||
}
|
||||
}
|
||||
|
||||
+const json::object_t&
|
||||
+json::get_object() const
|
||||
+{
|
||||
+ switch (type_) {
|
||||
+ case Type::Object:
|
||||
+ return object_value;
|
||||
+ default:
|
||||
+ ON_LOGIC_ERROR("JSON value is not an object.");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void
|
||||
json::set_array()
|
||||
{
|
||||
diff --git a/json.h b/json.h
|
||||
index 9aa5c889932e720746972d9e8ef1dd8b095e0fb1..2a4c009e4b3cf7f1ccac8b09986853ccd3540f9d 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -202,8 +202,11 @@ class json
|
||||
double get_number() const;
|
||||
long long get_int() const;
|
||||
std::string& get_string();
|
||||
+ const std::string& get_string() const;
|
||||
array_t& get_array();
|
||||
+ const array_t& get_array() const;
|
||||
object_t& get_object();
|
||||
+ const object_t& get_object() const;
|
||||
|
||||
bool contains(const std::string&) const;
|
||||
|
||||
35
upstream_utils/json_patches/0013-Use-wpi-StringMap.patch
Normal file
35
upstream_utils/json_patches/0013-Use-wpi-StringMap.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 08:20:16 -0700
|
||||
Subject: [PATCH 13/25] Use wpi StringMap
|
||||
|
||||
---
|
||||
json.h | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index 2a4c009e4b3cf7f1ccac8b09986853ccd3540f9d..662a3f2f68a04dc4e7faf5e4bd5a984ffd3705a9 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -16,17 +16,19 @@
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
-#include <map>
|
||||
+
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
+#include "wpi/util/StringMap.hpp"
|
||||
+
|
||||
namespace wpi::util {
|
||||
|
||||
class json
|
||||
{
|
||||
public:
|
||||
using array_t = std::vector<json>;
|
||||
- using object_t = std::map<std::string, json>;
|
||||
+ using object_t = wpi::util::StringMap<json>;
|
||||
|
||||
enum class Type
|
||||
{
|
||||
128
upstream_utils/json_patches/0014-Use-std-string_view.patch
Normal file
128
upstream_utils/json_patches/0014-Use-std-string_view.patch
Normal file
@@ -0,0 +1,128 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Wed, 1 Apr 2026 08:19:39 -0700
|
||||
Subject: [PATCH 14/25] Use std::string_view
|
||||
|
||||
---
|
||||
json.cpp | 14 +++++++++-----
|
||||
json.h | 12 +++++++-----
|
||||
2 files changed, 16 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 4aebebec76de7628792afbf176f46d61e2f67c43..2b4191865e84f4c160450fa8380ad578d37e1cd1 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -282,6 +282,10 @@ json::json(const std::string& value) : type_(Type::String), string_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
+json::json(std::string_view value) : type_(Type::String), string_value(value)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
json::~json()
|
||||
{
|
||||
if (type_ >= Type::String)
|
||||
@@ -595,7 +599,7 @@ json::set_object()
|
||||
}
|
||||
|
||||
bool
|
||||
-json::contains(const std::string& key) const
|
||||
+json::contains(std::string_view key) const
|
||||
{
|
||||
if (!is_object())
|
||||
return false;
|
||||
@@ -614,7 +618,7 @@ json::operator[](size_t index)
|
||||
}
|
||||
|
||||
json&
|
||||
-json::operator[](const std::string& key)
|
||||
+json::operator[](std::string_view key)
|
||||
{
|
||||
if (!is_object())
|
||||
set_object();
|
||||
@@ -725,7 +729,7 @@ json::marshal(std::string& b, bool pretty, int indent) const
|
||||
}
|
||||
|
||||
void
|
||||
-json::stringify(std::string& b, const std::string& s)
|
||||
+json::stringify(std::string& b, std::string_view s)
|
||||
{
|
||||
b += '"';
|
||||
serialize(b, s);
|
||||
@@ -733,7 +737,7 @@ json::stringify(std::string& b, const std::string& s)
|
||||
}
|
||||
|
||||
void
|
||||
-json::serialize(std::string& sb, const std::string& s)
|
||||
+json::serialize(std::string& sb, std::string_view s)
|
||||
{
|
||||
size_t i, j, m;
|
||||
wint_t x, a, b;
|
||||
@@ -1255,7 +1259,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
}
|
||||
|
||||
std::pair<json::Status, json>
|
||||
-json::parse(const std::string& s)
|
||||
+json::parse(std::string_view s)
|
||||
{
|
||||
json::Status s2;
|
||||
std::pair<json::Status, json> res;
|
||||
diff --git a/json.h b/json.h
|
||||
index 662a3f2f68a04dc4e7faf5e4bd5a984ffd3705a9..1c0dc26a460e17dab44f13d62059cf6e69f355c9 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
+#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
@@ -94,7 +95,7 @@ class json
|
||||
|
||||
public:
|
||||
static const char* StatusToString(Status);
|
||||
- static std::pair<Status, json> parse(const std::string&);
|
||||
+ static std::pair<Status, json> parse(std::string_view);
|
||||
|
||||
json(const json&);
|
||||
json(json&&);
|
||||
@@ -102,6 +103,7 @@ class json
|
||||
json(unsigned long long);
|
||||
json(const char*);
|
||||
json(const std::string&);
|
||||
+ json(std::string_view);
|
||||
~json();
|
||||
|
||||
constexpr json(const std::nullptr_t = nullptr) : type_(Type::Null)
|
||||
@@ -210,7 +212,7 @@ class json
|
||||
object_t& get_object();
|
||||
const object_t& get_object() const;
|
||||
|
||||
- bool contains(const std::string&) const;
|
||||
+ bool contains(std::string_view) const;
|
||||
|
||||
void set_array();
|
||||
void set_object();
|
||||
@@ -222,7 +224,7 @@ class json
|
||||
json& operator=(json&&);
|
||||
|
||||
json& operator[](size_t);
|
||||
- json& operator[](const std::string&);
|
||||
+ json& operator[](std::string_view);
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
@@ -232,8 +234,8 @@ class json
|
||||
private:
|
||||
void clear();
|
||||
void marshal(std::string&, bool, int) const;
|
||||
- static void stringify(std::string&, const std::string&);
|
||||
- static void serialize(std::string&, const std::string&);
|
||||
+ static void stringify(std::string&, std::string_view);
|
||||
+ static void serialize(std::string&, std::string_view);
|
||||
static Status parse(json&, const char*&, const char*, int, int);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 22:39:28 -0700
|
||||
Subject: [PATCH 15/25] Change parse to return expected with error string
|
||||
|
||||
---
|
||||
json.cpp | 21 +++++++++++----------
|
||||
json.h | 7 ++++---
|
||||
2 files changed, 15 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 2b4191865e84f4c160450fa8380ad578d37e1cd1..baefe6317126f95ec75fe9d9a896923d0a90e720 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -1258,21 +1258,22 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
return unexpected_eof;
|
||||
}
|
||||
|
||||
-std::pair<json::Status, json>
|
||||
+wpi::util::expected<json, const char*>
|
||||
json::parse(std::string_view s)
|
||||
{
|
||||
- json::Status s2;
|
||||
- std::pair<json::Status, json> res;
|
||||
const char* p = s.data();
|
||||
const char* e = s.data() + s.size();
|
||||
- res.first = parse(res.second, p, e, 0, DEPTH);
|
||||
- if (res.first == json::success) {
|
||||
- json j2;
|
||||
- s2 = parse(j2, p, e, 0, DEPTH);
|
||||
- if (s2 != absent_value)
|
||||
- res.first = trailing_content;
|
||||
+ json j;
|
||||
+ Status result = parse(j, p, e, 0, DEPTH);
|
||||
+ if (result != success) {
|
||||
+ return wpi::util::unexpected(StatusToString(result));
|
||||
}
|
||||
- return res;
|
||||
+ json j2;
|
||||
+ Status s2 = parse(j2, p, e, 0, DEPTH);
|
||||
+ if (s2 != absent_value) {
|
||||
+ return wpi::util::unexpected(StatusToString(trailing_content));
|
||||
+ }
|
||||
+ return j;
|
||||
}
|
||||
|
||||
const char*
|
||||
diff --git a/json.h b/json.h
|
||||
index 1c0dc26a460e17dab44f13d62059cf6e69f355c9..d2962c322678b0dd664707f34151094fec90d281 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
+#include "wpi/util/expected"
|
||||
|
||||
namespace wpi::util {
|
||||
|
||||
@@ -43,6 +44,7 @@ class json
|
||||
Object
|
||||
};
|
||||
|
||||
+ private:
|
||||
enum Status
|
||||
{
|
||||
success,
|
||||
@@ -80,7 +82,6 @@ class json
|
||||
non_del_c0_control_code_in_string,
|
||||
};
|
||||
|
||||
- private:
|
||||
Type type_;
|
||||
union
|
||||
{
|
||||
@@ -94,8 +95,7 @@ class json
|
||||
};
|
||||
|
||||
public:
|
||||
- static const char* StatusToString(Status);
|
||||
- static std::pair<Status, json> parse(std::string_view);
|
||||
+ static wpi::util::expected<json, const char*> parse(std::string_view);
|
||||
|
||||
json(const json&);
|
||||
json(json&&);
|
||||
@@ -232,6 +232,7 @@ class json
|
||||
}
|
||||
|
||||
private:
|
||||
+ static const char* StatusToString(Status);
|
||||
void clear();
|
||||
void marshal(std::string&, bool, int) const;
|
||||
static void stringify(std::string&, std::string_view);
|
||||
43
upstream_utils/json_patches/0016-Add-parse_or_throw.patch
Normal file
43
upstream_utils/json_patches/0016-Add-parse_or_throw.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 22:40:25 -0700
|
||||
Subject: [PATCH 16/25] Add parse_or_throw
|
||||
|
||||
---
|
||||
json.cpp | 10 ++++++++++
|
||||
json.h | 1 +
|
||||
2 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index baefe6317126f95ec75fe9d9a896923d0a90e720..49fbf92ea6e67e771f051f10b65ac795351c6f3d 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -1276,6 +1276,16 @@ json::parse(std::string_view s)
|
||||
return j;
|
||||
}
|
||||
|
||||
+json
|
||||
+json::parse_or_throw(std::string_view s)
|
||||
+{
|
||||
+ auto result = parse(s);
|
||||
+ if (!result) {
|
||||
+ ON_LOGIC_ERROR(result.error());
|
||||
+ }
|
||||
+ return *result;
|
||||
+}
|
||||
+
|
||||
const char*
|
||||
json::StatusToString(json::Status status)
|
||||
{
|
||||
diff --git a/json.h b/json.h
|
||||
index d2962c322678b0dd664707f34151094fec90d281..f42ba9c135cb76a1b0bc31f9e2c03b1ed7dce749 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -96,6 +96,7 @@ class json
|
||||
|
||||
public:
|
||||
static wpi::util::expected<json, const char*> parse(std::string_view);
|
||||
+ static json parse_or_throw(std::string_view);
|
||||
|
||||
json(const json&);
|
||||
json(json&&);
|
||||
67
upstream_utils/json_patches/0017-Add-operator.patch
Normal file
67
upstream_utils/json_patches/0017-Add-operator.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 22:54:14 -0700
|
||||
Subject: [PATCH 17/25] Add operator==
|
||||
|
||||
---
|
||||
json.cpp | 26 ++++++++++++++++++++++++++
|
||||
json.h | 6 ++++++
|
||||
2 files changed, 32 insertions(+)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 49fbf92ea6e67e771f051f10b65ac795351c6f3d..40479bc266390f015e291b737b5751522dac76ac 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -1361,4 +1361,30 @@ json::StatusToString(json::Status status)
|
||||
}
|
||||
}
|
||||
|
||||
+bool
|
||||
+operator==(const json& lhs, const json& rhs) {
|
||||
+ if (lhs.type_ != rhs.type_)
|
||||
+ return false;
|
||||
+ switch (lhs.type_) {
|
||||
+ case json::Type::Null:
|
||||
+ return true;
|
||||
+ case json::Type::String:
|
||||
+ return lhs.string_value == rhs.string_value;
|
||||
+ case json::Type::Bool:
|
||||
+ return lhs.bool_value == rhs.bool_value;
|
||||
+ case json::Type::Int:
|
||||
+ return lhs.long_value == rhs.long_value;
|
||||
+ case json::Type::Float:
|
||||
+ return lhs.float_value == rhs.float_value;
|
||||
+ case json::Type::Double:
|
||||
+ return lhs.double_value == rhs.double_value;
|
||||
+ case json::Type::Array:
|
||||
+ return lhs.array_value == rhs.array_value;
|
||||
+ case json::Type::Object:
|
||||
+ return lhs.object_value == rhs.object_value;
|
||||
+ default:
|
||||
+ ON_LOGIC_ERROR("Unhandled JSON type during equality comparison.");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
} // namespace wpi::util
|
||||
diff --git a/json.h b/json.h
|
||||
index f42ba9c135cb76a1b0bc31f9e2c03b1ed7dce749..fbc3fb959f71f6acc344f26247597959807d23bb 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -28,6 +28,7 @@ namespace wpi::util {
|
||||
|
||||
class json
|
||||
{
|
||||
+ friend bool operator==(const json& lhs, const json& rhs);
|
||||
public:
|
||||
using array_t = std::vector<json>;
|
||||
using object_t = wpi::util::StringMap<json>;
|
||||
@@ -241,4 +242,9 @@ class json
|
||||
static Status parse(json&, const char*&, const char*, int, int);
|
||||
};
|
||||
|
||||
+bool operator==(const json& lhs, const json& rhs);
|
||||
+inline bool operator!=(const json& lhs, const json& rhs) {
|
||||
+ return !(lhs == rhs);
|
||||
+}
|
||||
+
|
||||
} // namespace wpi::util
|
||||
166
upstream_utils/json_patches/0018-Add-container-functions.patch
Normal file
166
upstream_utils/json_patches/0018-Add-container-functions.patch
Normal file
@@ -0,0 +1,166 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 22:58:18 -0700
|
||||
Subject: [PATCH 18/25] Add container functions
|
||||
|
||||
---
|
||||
json.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
json.h | 18 ++++++++++
|
||||
2 files changed, 120 insertions(+)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 40479bc266390f015e291b737b5751522dac76ac..2307536b15be9aae19da4ec9370a5aa17d5150d1 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -606,6 +606,28 @@ json::contains(std::string_view key) const
|
||||
return object_value.find(key) != object_value.end();
|
||||
}
|
||||
|
||||
+json*
|
||||
+json::lookup(std::string_view key)
|
||||
+{
|
||||
+ if (!is_object())
|
||||
+ return nullptr;
|
||||
+ auto i = object_value.find(key);
|
||||
+ if (i == object_value.end())
|
||||
+ return nullptr;
|
||||
+ return &i->second;
|
||||
+}
|
||||
+
|
||||
+const json*
|
||||
+json::lookup(std::string_view key) const
|
||||
+{
|
||||
+ if (!is_object())
|
||||
+ return nullptr;
|
||||
+ auto i = object_value.find(key);
|
||||
+ if (i == object_value.end())
|
||||
+ return nullptr;
|
||||
+ return &i->second;
|
||||
+}
|
||||
+
|
||||
json&
|
||||
json::operator[](size_t index)
|
||||
{
|
||||
@@ -625,6 +647,86 @@ json::operator[](std::string_view key)
|
||||
return object_value[key];
|
||||
}
|
||||
|
||||
+json&
|
||||
+json::at(size_t index) {
|
||||
+ if (!is_array())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an array.");
|
||||
+ return array_value.at(index);
|
||||
+}
|
||||
+
|
||||
+json&
|
||||
+json::at(std::string_view key) {
|
||||
+ if (!is_object())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an object.");
|
||||
+ return object_value.at(key);
|
||||
+}
|
||||
+
|
||||
+const json&
|
||||
+json::at(size_t index) const {
|
||||
+ if (!is_array())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an array.");
|
||||
+ return array_value.at(index);
|
||||
+}
|
||||
+
|
||||
+const json&
|
||||
+json::at(std::string_view key) const {
|
||||
+ if (!is_object())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an object.");
|
||||
+ return object_value.at(key);
|
||||
+}
|
||||
+
|
||||
+json
|
||||
+json::value(size_t index, json&& default_value) {
|
||||
+ if (!is_array())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an array.");
|
||||
+ if (index < array_value.size())
|
||||
+ return array_value[index];
|
||||
+ return default_value;
|
||||
+}
|
||||
+
|
||||
+json
|
||||
+json::value(std::string_view key, json&& default_value)
|
||||
+{
|
||||
+ if (!is_object())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an object.");
|
||||
+ auto i = object_value.find(key);
|
||||
+ if (i != object_value.end())
|
||||
+ return i->second;
|
||||
+ return default_value;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::erase(std::string_view key)
|
||||
+{
|
||||
+ if (!is_object())
|
||||
+ ON_LOGIC_ERROR("JSON value is not an object.");
|
||||
+ object_value.erase(key);
|
||||
+}
|
||||
+
|
||||
+json&
|
||||
+json::emplace_back(json&& value)
|
||||
+{
|
||||
+ if (!is_array())
|
||||
+ set_array();
|
||||
+ array_value.emplace_back(std::move(value));
|
||||
+ return array_value.back();
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+json::empty() const
|
||||
+{
|
||||
+ switch (type_) {
|
||||
+ case Type::Null:
|
||||
+ return true;
|
||||
+ case Type::Array:
|
||||
+ return array_value.empty();
|
||||
+ case Type::Object:
|
||||
+ return object_value.empty();
|
||||
+ default:
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
std::string
|
||||
json::to_string() const
|
||||
{
|
||||
diff --git a/json.h b/json.h
|
||||
index fbc3fb959f71f6acc344f26247597959807d23bb..62af49cb18b713304ad95e89c52f5cc5bbc4b626 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -216,6 +216,9 @@ class json
|
||||
|
||||
bool contains(std::string_view) const;
|
||||
|
||||
+ json* lookup(std::string_view);
|
||||
+ const json* lookup(std::string_view) const;
|
||||
+
|
||||
void set_array();
|
||||
void set_object();
|
||||
|
||||
@@ -228,6 +231,21 @@ class json
|
||||
json& operator[](size_t);
|
||||
json& operator[](std::string_view);
|
||||
|
||||
+ json& at(size_t);
|
||||
+ json& at(std::string_view);
|
||||
+
|
||||
+ const json& at(size_t) const;
|
||||
+ const json& at(std::string_view) const;
|
||||
+
|
||||
+ json value(size_t, json&&);
|
||||
+ json value(std::string_view, json&&);
|
||||
+
|
||||
+ void erase(std::string_view);
|
||||
+
|
||||
+ json& emplace_back(json&& value);
|
||||
+
|
||||
+ bool empty() const;
|
||||
+
|
||||
operator std::string() const
|
||||
{
|
||||
return to_string();
|
||||
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 23:01:45 -0700
|
||||
Subject: [PATCH 19/25] Add to_json, from_json, and json_serializer struct
|
||||
|
||||
---
|
||||
json.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 65 insertions(+)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index 62af49cb18b713304ad95e89c52f5cc5bbc4b626..e52435a79ee7537928ba59fb146f635fc8511bfc 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -26,6 +26,35 @@
|
||||
|
||||
namespace wpi::util {
|
||||
|
||||
+class json;
|
||||
+
|
||||
+template <typename T>
|
||||
+struct json_serializer;
|
||||
+
|
||||
+namespace detail {
|
||||
+template <typename T>
|
||||
+concept HasToJson = requires(json& j, const T& val) {
|
||||
+ { to_json(j, val) };
|
||||
+};
|
||||
+
|
||||
+template <typename T>
|
||||
+concept HasFromJson = requires(const json& j, T& val) {
|
||||
+ { from_json(j, val) };
|
||||
+};
|
||||
+
|
||||
+template <typename T>
|
||||
+concept HasJsonSerializer = requires (json& j, const json& cj, const T& val) {
|
||||
+ typename json_serializer<typename std::remove_cvref_t<T>>;
|
||||
+ { json_serializer<typename std::remove_cvref_t<T>>::to(j, val) };
|
||||
+};
|
||||
+
|
||||
+template <typename T>
|
||||
+concept HasJsonDeserializer = requires (json& j, const json& cj, const T& val) {
|
||||
+ typename json_serializer<typename std::remove_cvref_t<T>>;
|
||||
+ { json_serializer<typename std::remove_cvref_t<T>>::from(cj) } -> std::convertible_to<typename std::remove_cvref_t<T>>;
|
||||
+};
|
||||
+} // namespace detail
|
||||
+
|
||||
class json
|
||||
{
|
||||
friend bool operator==(const json& lhs, const json& rhs);
|
||||
@@ -152,6 +181,18 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
+ template <detail::HasToJson T>
|
||||
+ json(const T& value) : type_(Type::Null)
|
||||
+ {
|
||||
+ to_json(*this, value);
|
||||
+ }
|
||||
+
|
||||
+ template <detail::HasJsonSerializer T>
|
||||
+ json(const T& value) : type_(Type::Null)
|
||||
+ {
|
||||
+ json_serializer<T>::to(*this, value);
|
||||
+ }
|
||||
+
|
||||
constexpr Type type() const
|
||||
{
|
||||
return type_;
|
||||
@@ -214,6 +255,18 @@ class json
|
||||
object_t& get_object();
|
||||
const object_t& get_object() const;
|
||||
|
||||
+ template <detail::HasFromJson T>
|
||||
+ T get() const {
|
||||
+ T value;
|
||||
+ from_json(*this, value);
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ template <detail::HasJsonDeserializer T>
|
||||
+ T get() const {
|
||||
+ return json_serializer<T>::from(*this);
|
||||
+ }
|
||||
+
|
||||
bool contains(std::string_view) const;
|
||||
|
||||
json* lookup(std::string_view);
|
||||
@@ -228,6 +281,18 @@ class json
|
||||
json& operator=(const json&);
|
||||
json& operator=(json&&);
|
||||
|
||||
+ template <detail::HasToJson T>
|
||||
+ json& operator=(const T& value) {
|
||||
+ to_json(*this, value);
|
||||
+ return *this;
|
||||
+ }
|
||||
+
|
||||
+ template <detail::HasJsonSerializer T>
|
||||
+ json& operator=(const T& value) {
|
||||
+ json_serializer<T>::to(*this, value);
|
||||
+ return *this;
|
||||
+ }
|
||||
+
|
||||
json& operator[](size_t);
|
||||
json& operator[](std::string_view);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 23:05:58 -0700
|
||||
Subject: [PATCH 20/25] Add array and object factory functions
|
||||
|
||||
---
|
||||
json.h | 30 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index e52435a79ee7537928ba59fb146f635fc8511bfc..6a52615ab3e1799ebcf51a3b5ca445b1e2e64b97 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
+#include <tuple>
|
||||
+#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
@@ -53,6 +55,13 @@ concept HasJsonDeserializer = requires (json& j, const json& cj, const T& val) {
|
||||
typename json_serializer<typename std::remove_cvref_t<T>>;
|
||||
{ json_serializer<typename std::remove_cvref_t<T>>::from(cj) } -> std::convertible_to<typename std::remove_cvref_t<T>>;
|
||||
};
|
||||
+
|
||||
+template <typename F, typename Tuple, size_t... I>
|
||||
+void apply_pairs_helper(F&& f, Tuple&& t, std::index_sequence<I...>) {
|
||||
+ // This fold expression creates a sequence of calls to f for each pair
|
||||
+ (f(std::get<I * 2>(std::forward<Tuple>(t)),
|
||||
+ std::get<I * 2 + 1>(std::forward<Tuple>(t))), ...);
|
||||
+}
|
||||
} // namespace detail
|
||||
|
||||
class json
|
||||
@@ -275,6 +284,27 @@ class json
|
||||
void set_array();
|
||||
void set_object();
|
||||
|
||||
+ template <typename... Args>
|
||||
+ static json array(Args&&... args) {
|
||||
+ json j;
|
||||
+ j.set_array();
|
||||
+ (j.array_value.emplace_back(std::forward<Args>(args)), ...);
|
||||
+ return j;
|
||||
+ }
|
||||
+
|
||||
+ template <typename... Args>
|
||||
+ static json object(Args&&... args) {
|
||||
+ json j;
|
||||
+ j.set_object();
|
||||
+ detail::apply_pairs_helper(
|
||||
+ [&](auto&& key, auto&& value) {
|
||||
+ j.object_value[std::forward<decltype(key)>(key)] = std::forward<decltype(value)>(value);
|
||||
+ },
|
||||
+ std::forward_as_tuple(args...),
|
||||
+ std::make_index_sequence<sizeof...(Args) / 2>{});
|
||||
+ return j;
|
||||
+ }
|
||||
+
|
||||
std::string to_string() const;
|
||||
std::string to_string_pretty() const;
|
||||
|
||||
55
upstream_utils/json_patches/0021-Add-array-constructor.patch
Normal file
55
upstream_utils/json_patches/0021-Add-array-constructor.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Fri, 3 Apr 2026 23:07:20 -0700
|
||||
Subject: [PATCH 21/25] Add array constructor
|
||||
|
||||
---
|
||||
json.h | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index 6a52615ab3e1799ebcf51a3b5ca445b1e2e64b97..ef3ea13b7cb147f0b383ff1ead496d495cfece32 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
+#include <concepts>
|
||||
+#include <ranges>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
@@ -56,6 +58,19 @@ concept HasJsonDeserializer = requires (json& j, const json& cj, const T& val) {
|
||||
{ json_serializer<typename std::remove_cvref_t<T>>::from(cj) } -> std::convertible_to<typename std::remove_cvref_t<T>>;
|
||||
};
|
||||
|
||||
+template <typename T>
|
||||
+concept JsonConvertible =
|
||||
+ HasToJson<T> ||
|
||||
+ HasJsonSerializer<T> ||
|
||||
+ std::is_same_v<T, std::nullptr_t> ||
|
||||
+ std::is_same_v<T, bool> ||
|
||||
+ std::is_floating_point_v<T> ||
|
||||
+ std::is_integral_v<T> ||
|
||||
+ std::convertible_to<T, std::string> ||
|
||||
+ std::convertible_to<T, std::string_view> ||
|
||||
+ std::is_same_v<T, std::vector<json>> ||
|
||||
+ std::is_same_v<T, wpi::util::StringMap<json>>;
|
||||
+
|
||||
template <typename F, typename Tuple, size_t... I>
|
||||
void apply_pairs_helper(F&& f, Tuple&& t, std::index_sequence<I...>) {
|
||||
// This fold expression creates a sequence of calls to f for each pair
|
||||
@@ -190,6 +205,12 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
+ template <std::ranges::input_range R>
|
||||
+ requires detail::JsonConvertible<std::ranges::range_value_t<R>>
|
||||
+ json(const R& range) : type_(Type::Array), array_value(std::ranges::cbegin(range), std::ranges::cend(range))
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
template <detail::HasToJson T>
|
||||
json(const T& value) : type_(Type::Null)
|
||||
{
|
||||
@@ -0,0 +1,329 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 4 Apr 2026 12:09:43 -0700
|
||||
Subject: [PATCH 22/25] Improve stringize and marshal and use raw_ostream
|
||||
|
||||
---
|
||||
json.cpp | 202 ++++++++++++++++++++++++++++++++-----------------------
|
||||
json.h | 16 ++++-
|
||||
2 files changed, 131 insertions(+), 87 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 2307536b15be9aae19da4ec9370a5aa17d5150d1..1beec7cc30e90ab2e31bc488ee15cedf9a9f32e5 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "wpi/double-conversion/double-to-string.h"
|
||||
#include "wpi/double-conversion/string-to-double.h"
|
||||
+#include "wpi/util/raw_ostream.hpp"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
@@ -731,7 +732,8 @@ std::string
|
||||
json::to_string() const
|
||||
{
|
||||
std::string b;
|
||||
- marshal(b, false, 0);
|
||||
+ wpi::util::raw_string_ostream os(b);
|
||||
+ marshal(os, false, 0);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -739,107 +741,139 @@ std::string
|
||||
json::to_string_pretty() const
|
||||
{
|
||||
std::string b;
|
||||
- marshal(b, true, 0);
|
||||
+ wpi::util::raw_string_ostream os(b);
|
||||
+ marshal(os, true, 0);
|
||||
return b;
|
||||
}
|
||||
|
||||
void
|
||||
-json::marshal(std::string& b, bool pretty, int indent) const
|
||||
+json::marshal(wpi::util::raw_ostream& os, bool pretty, int indent) const
|
||||
{
|
||||
switch (type_) {
|
||||
case Type::Null:
|
||||
- b += "null";
|
||||
+ stringify_null(os);
|
||||
break;
|
||||
case Type::String:
|
||||
- stringify(b, string_value);
|
||||
+ stringify_string(os, string_value);
|
||||
break;
|
||||
case Type::Bool:
|
||||
- b += bool_value ? "true" : "false";
|
||||
+ stringify_bool(os, bool_value);
|
||||
break;
|
||||
- case Type::Int: {
|
||||
- char buf[64];
|
||||
- b.append(buf, LongToString(buf, long_value) - buf);
|
||||
+ case Type::Int:
|
||||
+ stringify_int(os, long_value);
|
||||
break;
|
||||
- }
|
||||
- case Type::Float: {
|
||||
- char buf[128];
|
||||
- double_conversion::StringBuilder db(buf, 128);
|
||||
- kDoubleToJson.ToShortestSingle(float_value, &db);
|
||||
- db.Finalize();
|
||||
- b += buf;
|
||||
+ case Type::Float:
|
||||
+ stringify_float(os, float_value);
|
||||
break;
|
||||
- }
|
||||
- case Type::Double: {
|
||||
- char buf[128];
|
||||
- double_conversion::StringBuilder db(buf, 128);
|
||||
- kDoubleToJson.ToShortest(double_value, &db);
|
||||
- db.Finalize();
|
||||
- b += buf;
|
||||
+ case Type::Double:
|
||||
+ stringify_double(os, double_value);
|
||||
break;
|
||||
- }
|
||||
- case Type::Array: {
|
||||
- bool once = false;
|
||||
- b += '[';
|
||||
- for (auto i = array_value.begin(); i != array_value.end(); ++i) {
|
||||
- if (once) {
|
||||
- b += ',';
|
||||
- if (pretty)
|
||||
- b += ' ';
|
||||
- } else {
|
||||
- once = true;
|
||||
- }
|
||||
- i->marshal(b, pretty, indent);
|
||||
- }
|
||||
- b += ']';
|
||||
+ case Type::Array:
|
||||
+ stringify_array(os, array_value, pretty, indent);
|
||||
break;
|
||||
- }
|
||||
- case Type::Object: {
|
||||
- bool once = false;
|
||||
- b += '{';
|
||||
- for (auto i = object_value.begin(); i != object_value.end(); ++i) {
|
||||
- if (once) {
|
||||
- b += ',';
|
||||
- } else {
|
||||
- once = true;
|
||||
- }
|
||||
- if (pretty && object_value.size() > 1) {
|
||||
- b += '\n';
|
||||
- ++indent;
|
||||
- for (int j = 0; j < indent; ++j)
|
||||
- b += " ";
|
||||
- }
|
||||
- stringify(b, i->first);
|
||||
- b += ':';
|
||||
- if (pretty)
|
||||
- b += ' ';
|
||||
- i->second.marshal(b, pretty, indent);
|
||||
- if (pretty && object_value.size() > 1)
|
||||
- --indent;
|
||||
- }
|
||||
- if (pretty && object_value.size() > 1) {
|
||||
- b += '\n';
|
||||
- for (int j = 0; j < indent; ++j)
|
||||
- b += " ";
|
||||
- ++indent;
|
||||
- }
|
||||
- b += '}';
|
||||
+ case Type::Object:
|
||||
+ stringify_object(os, object_value, pretty, indent);
|
||||
break;
|
||||
- }
|
||||
default:
|
||||
ON_LOGIC_ERROR("Unhandled JSON type.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
-json::stringify(std::string& b, std::string_view s)
|
||||
+json::stringify_null(wpi::util::raw_ostream& os)
|
||||
{
|
||||
- b += '"';
|
||||
- serialize(b, s);
|
||||
- b += '"';
|
||||
+ os << "null";
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_string(wpi::util::raw_ostream& os, std::string_view s)
|
||||
+{
|
||||
+ os << '"';
|
||||
+ serialize(os, s);
|
||||
+ os << '"';
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_bool(wpi::util::raw_ostream& os, bool value) {
|
||||
+ os << (value ? "true" : "false");
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_float(wpi::util::raw_ostream& os, float value) {
|
||||
+ char buf[128];
|
||||
+ double_conversion::StringBuilder db(buf, 128);
|
||||
+ kDoubleToJson.ToShortestSingle(value, &db);
|
||||
+ db.Finalize();
|
||||
+ os << buf;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_double(wpi::util::raw_ostream& os, double value) {
|
||||
+ char buf[128];
|
||||
+ double_conversion::StringBuilder db(buf, 128);
|
||||
+ kDoubleToJson.ToShortest(value, &db);
|
||||
+ db.Finalize();
|
||||
+ os << buf;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_int(wpi::util::raw_ostream& os, long long value) {
|
||||
+ char buf[64];
|
||||
+ os.write(buf, LongToString(buf, value) - buf);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_array(wpi::util::raw_ostream& os, const array_t& value, bool pretty, int indent) {
|
||||
+ bool once = false;
|
||||
+ os << '[';
|
||||
+ for (auto i = value.begin(); i != value.end(); ++i) {
|
||||
+ if (once) {
|
||||
+ os << ',';
|
||||
+ if (pretty)
|
||||
+ os << ' ';
|
||||
+ } else {
|
||||
+ once = true;
|
||||
+ }
|
||||
+ i->marshal(os, pretty, indent);
|
||||
+ }
|
||||
+ os << ']';
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+json::stringify_object(wpi::util::raw_ostream& os, const object_t& value, bool pretty, int indent) {
|
||||
+ bool once = false;
|
||||
+ os << '{';
|
||||
+ for (auto i = value.begin(); i != value.end(); ++i) {
|
||||
+ if (once) {
|
||||
+ os << ',';
|
||||
+ } else {
|
||||
+ once = true;
|
||||
+ }
|
||||
+ if (pretty && value.size() > 1) {
|
||||
+ os << '\n';
|
||||
+ ++indent;
|
||||
+ for (int j = 0; j < indent; ++j)
|
||||
+ os << " ";
|
||||
+ }
|
||||
+ stringify_string(os, i->first);
|
||||
+ os << ':';
|
||||
+ if (pretty)
|
||||
+ os << ' ';
|
||||
+ i->second.marshal(os, pretty, indent);
|
||||
+ if (pretty && value.size() > 1)
|
||||
+ --indent;
|
||||
+ }
|
||||
+ if (pretty && value.size() > 1) {
|
||||
+ os << '\n';
|
||||
+ for (int j = 0; j < indent; ++j)
|
||||
+ os << " ";
|
||||
+ ++indent;
|
||||
+ }
|
||||
+ os << '}';
|
||||
}
|
||||
|
||||
void
|
||||
-json::serialize(std::string& sb, std::string_view s)
|
||||
+json::serialize(wpi::util::raw_ostream& os, std::string_view s)
|
||||
{
|
||||
size_t i, j, m;
|
||||
wint_t x, a, b;
|
||||
@@ -865,28 +899,28 @@ json::serialize(std::string& sb, std::string_view s)
|
||||
}
|
||||
switch (0 <= x && x <= 127 ? kEscapeLiteral[x] : 9) {
|
||||
case 0:
|
||||
- sb += x;
|
||||
+ os << static_cast<char>(x);
|
||||
break;
|
||||
case 1:
|
||||
- sb += "\\t";
|
||||
+ os << "\\t";
|
||||
break;
|
||||
case 2:
|
||||
- sb += "\\n";
|
||||
+ os << "\\n";
|
||||
break;
|
||||
case 3:
|
||||
- sb += "\\r";
|
||||
+ os << "\\r";
|
||||
break;
|
||||
case 4:
|
||||
- sb += "\\f";
|
||||
+ os << "\\f";
|
||||
break;
|
||||
case 5:
|
||||
- sb += "\\\\";
|
||||
+ os << "\\\\";
|
||||
break;
|
||||
case 6:
|
||||
- sb += "\\/";
|
||||
+ os << "\\/";
|
||||
break;
|
||||
case 7:
|
||||
- sb += "\\\"";
|
||||
+ os << "\\\"";
|
||||
break;
|
||||
case 9:
|
||||
w = EncodeUtf16(x);
|
||||
@@ -898,7 +932,7 @@ json::serialize(std::string& sb, std::string_view s)
|
||||
esc[3] = "0123456789abcdef"[(w & 0x0F00) >> 010];
|
||||
esc[4] = "0123456789abcdef"[(w & 0x00F0) >> 004];
|
||||
esc[5] = "0123456789abcdef"[(w & 0x000F) >> 000];
|
||||
- sb.append(esc, 6);
|
||||
+ os.write(esc, 6);
|
||||
} while ((w >>= 16));
|
||||
break;
|
||||
default:
|
||||
diff --git a/json.h b/json.h
|
||||
index ef3ea13b7cb147f0b383ff1ead496d495cfece32..e42ee96ac8697eaf17fd9d5298e877a45a4644a0 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -31,6 +31,7 @@
|
||||
namespace wpi::util {
|
||||
|
||||
class json;
|
||||
+class raw_ostream;
|
||||
|
||||
template <typename T>
|
||||
struct json_serializer;
|
||||
@@ -367,12 +368,21 @@ class json
|
||||
return to_string();
|
||||
}
|
||||
|
||||
+ void marshal(wpi::util::raw_ostream& os, bool pretty = false, int indent = 0) const;
|
||||
+
|
||||
+ static void stringify_null(wpi::util::raw_ostream&);
|
||||
+ static void stringify_string(wpi::util::raw_ostream&, std::string_view);
|
||||
+ static void stringify_bool(wpi::util::raw_ostream&, bool);
|
||||
+ static void stringify_float(wpi::util::raw_ostream&, float);
|
||||
+ static void stringify_double(wpi::util::raw_ostream&, double);
|
||||
+ static void stringify_int(wpi::util::raw_ostream&, long long);
|
||||
+ static void stringify_array(wpi::util::raw_ostream&, const array_t&, bool pretty = false, int indent = 0);
|
||||
+ static void stringify_object(wpi::util::raw_ostream&, const object_t&, bool pretty = false, int indent = 0);
|
||||
+
|
||||
private:
|
||||
static const char* StatusToString(Status);
|
||||
void clear();
|
||||
- void marshal(std::string&, bool, int) const;
|
||||
- static void stringify(std::string&, std::string_view);
|
||||
- static void serialize(std::string&, std::string_view);
|
||||
+ static void serialize(wpi::util::raw_ostream&, std::string_view);
|
||||
static Status parse(json&, const char*&, const char*, int, int);
|
||||
};
|
||||
|
||||
22
upstream_utils/json_patches/0023-Update-include-path.patch
Normal file
22
upstream_utils/json_patches/0023-Update-include-path.patch
Normal file
@@ -0,0 +1,22 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sat, 4 Apr 2026 12:24:46 -0700
|
||||
Subject: [PATCH 23/25] Update include path
|
||||
|
||||
---
|
||||
json.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index 1beec7cc30e90ab2e31bc488ee15cedf9a9f32e5..f8416f3723df70032d274f32cda36b4ef1c7ed90 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -15,7 +15,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
-#include "json.h"
|
||||
+#include "wpi/util/json.hpp"
|
||||
#include "jtckdint.h"
|
||||
|
||||
#include <cassert>
|
||||
@@ -0,0 +1,326 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Sun, 5 Apr 2026 17:19:33 -0700
|
||||
Subject: [PATCH 24/25] Add support for unsigned long long values
|
||||
|
||||
Make unsigned constructors constexpr
|
||||
---
|
||||
json.cpp | 115 ++++++++++++++++++++++++++++++++++++++-----------------
|
||||
json.h | 36 +++++++++++++++--
|
||||
2 files changed, 112 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/json.cpp b/json.cpp
|
||||
index f8416f3723df70032d274f32cda36b4ef1c7ed90..7f23ece0e8fa09ccb5fef8226de39c55ef70efdd 100644
|
||||
--- a/json.cpp
|
||||
+++ b/json.cpp
|
||||
@@ -247,28 +247,6 @@ LongToString(char* p, long long x)
|
||||
return UlongToString(p, x);
|
||||
}
|
||||
|
||||
-json::json(unsigned long value)
|
||||
-{
|
||||
- if (value <= LLONG_MAX) {
|
||||
- type_ = Type::Int;
|
||||
- long_value = value;
|
||||
- } else {
|
||||
- type_ = Type::Double;
|
||||
- double_value = value;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-json::json(unsigned long long value)
|
||||
-{
|
||||
- if (value <= LLONG_MAX) {
|
||||
- type_ = Type::Int;
|
||||
- long_value = value;
|
||||
- } else {
|
||||
- type_ = Type::Double;
|
||||
- double_value = value;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
json::json(const char* value)
|
||||
{
|
||||
if (value) {
|
||||
@@ -323,6 +301,9 @@ json::json(const json& other) : type_(other.type_)
|
||||
case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
+ case Type::Uint:
|
||||
+ ulong_value = other.ulong_value;
|
||||
+ break;
|
||||
case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
@@ -359,6 +340,9 @@ json::operator=(const json& other)
|
||||
case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
+ case Type::Uint:
|
||||
+ ulong_value = other.ulong_value;
|
||||
+ break;
|
||||
case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
@@ -392,6 +376,9 @@ json::json(json&& other) : type_(other.type_)
|
||||
case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
+ case Type::Uint:
|
||||
+ ulong_value = other.ulong_value;
|
||||
+ break;
|
||||
case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
@@ -429,6 +416,9 @@ json::operator=(json&& other)
|
||||
case Type::Int:
|
||||
long_value = other.long_value;
|
||||
break;
|
||||
+ case Type::Uint:
|
||||
+ ulong_value = other.ulong_value;
|
||||
+ break;
|
||||
case Type::Float:
|
||||
float_value = other.float_value;
|
||||
break;
|
||||
@@ -458,6 +448,8 @@ json::get_number() const
|
||||
switch (type_) {
|
||||
case Type::Int:
|
||||
return long_value;
|
||||
+ case Type::Uint:
|
||||
+ return ulong_value;
|
||||
case Type::Float:
|
||||
return float_value;
|
||||
case Type::Double:
|
||||
@@ -478,6 +470,17 @@ json::get_int() const
|
||||
}
|
||||
}
|
||||
|
||||
+unsigned long long
|
||||
+json::get_uint() const
|
||||
+{
|
||||
+ switch (type_) {
|
||||
+ case Type::Uint:
|
||||
+ return ulong_value;
|
||||
+ default:
|
||||
+ ON_LOGIC_ERROR("JSON value is not an unsigned long.");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
bool
|
||||
json::get_bool() const
|
||||
{
|
||||
@@ -762,6 +765,9 @@ json::marshal(wpi::util::raw_ostream& os, bool pretty, int indent) const
|
||||
case Type::Int:
|
||||
stringify_int(os, long_value);
|
||||
break;
|
||||
+ case Type::Uint:
|
||||
+ stringify_uint(os, ulong_value);
|
||||
+ break;
|
||||
case Type::Float:
|
||||
stringify_float(os, float_value);
|
||||
break;
|
||||
@@ -822,6 +828,12 @@ json::stringify_int(wpi::util::raw_ostream& os, long long value) {
|
||||
os.write(buf, LongToString(buf, value) - buf);
|
||||
}
|
||||
|
||||
+void
|
||||
+json::stringify_uint(wpi::util::raw_ostream& os, unsigned long long value) {
|
||||
+ char buf[64];
|
||||
+ os.write(buf, UlongToString(buf, value) - buf);
|
||||
+}
|
||||
+
|
||||
void
|
||||
json::stringify_array(wpi::util::raw_ostream& os, const array_t& value, bool pretty, int indent) {
|
||||
bool once = false;
|
||||
@@ -946,6 +958,7 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
{
|
||||
char w[4];
|
||||
long long x;
|
||||
+ unsigned long long ux;
|
||||
const char* a;
|
||||
int A, B, C, D, c, d, i, u;
|
||||
if (!depth)
|
||||
@@ -1061,25 +1074,53 @@ json::parse(json& j, const char*& p, const char* e, int context, int depth)
|
||||
case '9': // integer
|
||||
if (context & (COLON | COMMA | KEY))
|
||||
goto OnColonCommaKey;
|
||||
- for (x = (c - '0') * d; p < e; ++p) {
|
||||
- c = *p & 255;
|
||||
- if (isdigit(c)) {
|
||||
- if (ckd_mul(&x, x, 10) ||
|
||||
- ckd_add(&x, x, (c - '0') * d)) {
|
||||
+ if (d > 0) {
|
||||
+ for (ux = c - '0'; p < e; ++p) {
|
||||
+ c = *p & 255;
|
||||
+ if (isdigit(c)) {
|
||||
+ if (ckd_mul(&ux, ux, 10u) ||
|
||||
+ ckd_add(&ux, ux,
|
||||
+ static_cast<unsigned long long>(c - '0'))) {
|
||||
+ goto UseDubble;
|
||||
+ }
|
||||
+ } else if (c == '.') {
|
||||
+ if (p + 1 == e || !isdigit(p[1]))
|
||||
+ return bad_double;
|
||||
+ goto UseDubble;
|
||||
+ } else if (c == 'e' || c == 'E') {
|
||||
goto UseDubble;
|
||||
+ } else {
|
||||
+ break;
|
||||
}
|
||||
- } else if (c == '.') {
|
||||
- if (p + 1 == e || !isdigit(p[1]))
|
||||
- return bad_double;
|
||||
- goto UseDubble;
|
||||
- } else if (c == 'e' || c == 'E') {
|
||||
- goto UseDubble;
|
||||
+ }
|
||||
+ if (ux <= static_cast<unsigned long long>(LLONG_MAX)) {
|
||||
+ j.type_ = Type::Int;
|
||||
+ j.long_value = ux;
|
||||
} else {
|
||||
- break;
|
||||
+ j.type_ = Type::Uint;
|
||||
+ j.ulong_value = ux;
|
||||
+ }
|
||||
+ } else {
|
||||
+ for (x = (c - '0') * d; p < e; ++p) {
|
||||
+ c = *p & 255;
|
||||
+ if (isdigit(c)) {
|
||||
+ if (ckd_mul(&x, x, 10) ||
|
||||
+ ckd_add(&x, x, (c - '0') * d)) {
|
||||
+ goto UseDubble;
|
||||
+ }
|
||||
+ } else if (c == '.') {
|
||||
+ if (p + 1 == e || !isdigit(p[1]))
|
||||
+ return bad_double;
|
||||
+ goto UseDubble;
|
||||
+ } else if (c == 'e' || c == 'E') {
|
||||
+ goto UseDubble;
|
||||
+ } else {
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
+ j.type_ = Type::Int;
|
||||
+ j.long_value = x;
|
||||
}
|
||||
- j.type_ = Type::Int;
|
||||
- j.long_value = x;
|
||||
return success;
|
||||
|
||||
UseDubble: // number
|
||||
@@ -1510,6 +1551,8 @@ operator==(const json& lhs, const json& rhs) {
|
||||
return lhs.bool_value == rhs.bool_value;
|
||||
case json::Type::Int:
|
||||
return lhs.long_value == rhs.long_value;
|
||||
+ case json::Type::Uint:
|
||||
+ return lhs.ulong_value == rhs.ulong_value;
|
||||
case json::Type::Float:
|
||||
return lhs.float_value == rhs.float_value;
|
||||
case json::Type::Double:
|
||||
diff --git a/json.h b/json.h
|
||||
index e42ee96ac8697eaf17fd9d5298e877a45a4644a0..31c5ea39b67286df158a9d6e13ab5073498126b8 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
+#include <climits>
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
@@ -92,6 +93,7 @@ class json
|
||||
Null,
|
||||
Bool,
|
||||
Int,
|
||||
+ Uint,
|
||||
Float,
|
||||
Double,
|
||||
String,
|
||||
@@ -144,6 +146,7 @@ class json
|
||||
float float_value;
|
||||
double double_value;
|
||||
long long long_value;
|
||||
+ unsigned long long ulong_value;
|
||||
std::string string_value;
|
||||
array_t array_value;
|
||||
object_t object_value;
|
||||
@@ -155,8 +158,6 @@ class json
|
||||
|
||||
json(const json&);
|
||||
json(json&&);
|
||||
- json(unsigned long);
|
||||
- json(unsigned long long);
|
||||
json(const char*);
|
||||
json(const std::string&);
|
||||
json(std::string_view);
|
||||
@@ -186,10 +187,32 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
+ constexpr json(unsigned long value)
|
||||
+ {
|
||||
+ if (value <= LLONG_MAX) {
|
||||
+ type_ = Type::Int;
|
||||
+ long_value = value;
|
||||
+ } else {
|
||||
+ type_ = Type::Uint;
|
||||
+ ulong_value = value;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
constexpr json(long long value) : type_(Type::Int), long_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
+ constexpr json(unsigned long long value)
|
||||
+ {
|
||||
+ if (value <= LLONG_MAX) {
|
||||
+ type_ = Type::Int;
|
||||
+ long_value = value;
|
||||
+ } else {
|
||||
+ type_ = Type::Uint;
|
||||
+ ulong_value = value;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
constexpr json(double value) : type_(Type::Double), double_value(value)
|
||||
{
|
||||
}
|
||||
@@ -241,7 +264,7 @@ class json
|
||||
|
||||
constexpr bool is_number() const
|
||||
{
|
||||
- return is_float() || is_double() || is_int();
|
||||
+ return is_float() || is_double() || is_int() || is_uint();
|
||||
}
|
||||
|
||||
constexpr bool is_int() const
|
||||
@@ -249,6 +272,11 @@ class json
|
||||
return type_ == Type::Int;
|
||||
}
|
||||
|
||||
+ constexpr bool is_uint() const
|
||||
+ {
|
||||
+ return type_ == Type::Uint;
|
||||
+ }
|
||||
+
|
||||
constexpr bool is_float() const
|
||||
{
|
||||
return type_ == Type::Float;
|
||||
@@ -279,6 +307,7 @@ class json
|
||||
double get_double() const;
|
||||
double get_number() const;
|
||||
long long get_int() const;
|
||||
+ unsigned long long get_uint() const;
|
||||
std::string& get_string();
|
||||
const std::string& get_string() const;
|
||||
array_t& get_array();
|
||||
@@ -376,6 +405,7 @@ class json
|
||||
static void stringify_float(wpi::util::raw_ostream&, float);
|
||||
static void stringify_double(wpi::util::raw_ostream&, double);
|
||||
static void stringify_int(wpi::util::raw_ostream&, long long);
|
||||
+ static void stringify_uint(wpi::util::raw_ostream&, unsigned long long);
|
||||
static void stringify_array(wpi::util::raw_ostream&, const array_t&, bool pretty = false, int indent = 0);
|
||||
static void stringify_object(wpi::util::raw_ostream&, const object_t&, bool pretty = false, int indent = 0);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Johnson <johnson.peter@gmail.com>
|
||||
Date: Mon, 6 Apr 2026 17:49:08 -0700
|
||||
Subject: [PATCH 25/25] Make bool constructor safe
|
||||
|
||||
---
|
||||
json.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/json.h b/json.h
|
||||
index 31c5ea39b67286df158a9d6e13ab5073498126b8..2746badf92a5bb4de6c38007d8e6dcfbed5b47eb 100644
|
||||
--- a/json.h
|
||||
+++ b/json.h
|
||||
@@ -167,7 +167,7 @@ class json
|
||||
{
|
||||
}
|
||||
|
||||
- constexpr json(bool value) : type_(Type::Bool), bool_value(value)
|
||||
+ constexpr json(std::same_as<bool> auto value) : type_(Type::Bool), bool_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user