Files
allwpilib/upstream_utils/json_patches/0024-Add-support-for-unsigned-long-long-values.patch

327 lines
10 KiB
Diff
Raw Normal View History

2026-03-29 15:37:32 -07:00
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);