Skip to content

Commit 6f6048a

Browse files
authored
Decimal numbers support for the json lib (#5283)
Signed-off-by: stan-leetasi <[email protected]>
1 parent 5a243dc commit 6f6048a

File tree

5 files changed

+73
-38
lines changed

5 files changed

+73
-38
lines changed

backends/bmv2/common/extern.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ void ExternConverter::addToFieldList(ConversionContext *ctxt, const IR::Expressi
169169
auto val = jo->getAs<Util::JsonValue>("value");
170170
j = jo = new Util::JsonObject();
171171
jo->emplace("type", "hexstr");
172-
jo->emplace("value", stringRepr(val->getValue()));
172+
jo->emplace("value", stringRepr(val->getIntValue()));
173173
}
174174
}
175175
}

backends/bmv2/common/helpers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void ConversionContext::addToFieldList(const IR::Expression *expr, Util::JsonArr
118118
auto val = jo->getAs<Util::JsonValue>("value");
119119
j = jo = new Util::JsonObject();
120120
jo->emplace("type", "hexstr");
121-
jo->emplace("value", stringRepr(val->getValue()));
121+
jo->emplace("value", stringRepr(val->getIntValue()));
122122
}
123123
}
124124
}

lib/json.cpp

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,20 @@ void IJson::dump() const { std::cout << toString(); }
3535

3636
JsonValue *JsonValue::null = new JsonValue();
3737

38-
JsonValue::JsonValue(long long v) : tag(Kind::Number), value(v) {}
38+
JsonValue::JsonValue(long long v) : tag(Kind::Integer), intValue(v) {}
3939

40-
JsonValue::JsonValue(unsigned long long v) : tag(Kind::Number), value(v) {}
40+
JsonValue::JsonValue(unsigned long long v) : tag(Kind::Integer), intValue(v) {}
4141

4242
void JsonValue::serialize(std::ostream &out) const {
4343
switch (tag) {
4444
case Kind::String:
4545
out << "\"" << str << "\"";
4646
break;
47-
case Kind::Number:
48-
out << value;
47+
case Kind::Integer:
48+
out << intValue;
49+
break;
50+
case Kind::Float:
51+
out << floatValue;
4952
break;
5053
case Kind::True:
5154
out << "true";
@@ -60,14 +63,14 @@ void JsonValue::serialize(std::ostream &out) const {
6063
}
6164

6265
bool JsonValue::operator==(const big_int &v) const {
63-
return tag == Kind::Number ? v == value : false;
66+
return tag == Kind::Integer ? v == intValue : false;
6467
}
6568
bool JsonValue::operator==(const double &v) const {
66-
return tag == Kind::Number ? big_int(v) == value : false;
67-
}
68-
bool JsonValue::operator==(const float &v) const {
69-
return tag == Kind::Number ? big_int(v) == value : false;
69+
return tag == Kind::Float ? floatValue == v
70+
: tag == Kind::Integer ? static_cast<double>(intValue) == v
71+
: false;
7072
}
73+
bool JsonValue::operator==(const float &v) const { return *this == static_cast<double>(v); }
7174
bool JsonValue::operator==(const cstring &s) const {
7275
return tag == Kind::String ? s == str : false;
7376
}
@@ -89,8 +92,10 @@ bool JsonValue::operator==(const JsonValue &other) const {
8992
switch (tag) {
9093
case Kind::String:
9194
return str == other.str;
92-
case Kind::Number:
93-
return value == other.value;
95+
case Kind::Integer:
96+
return intValue == other.intValue;
97+
case Kind::Float:
98+
return floatValue == other.floatValue;
9499
case Kind::True:
95100
case Kind::False:
96101
case Kind::Null:
@@ -134,15 +139,20 @@ cstring JsonValue::getString() const {
134139
return str;
135140
}
136141

137-
big_int JsonValue::getValue() const {
138-
if (!isNumber()) throw std::logic_error("Incorrect json value kind");
139-
return value;
142+
big_int JsonValue::getIntValue() const {
143+
if (!isInteger()) throw std::logic_error("Not an integer");
144+
return intValue;
145+
}
146+
147+
double JsonValue::getFloatValue() const {
148+
if (!isFloat()) throw std::logic_error("Not a float");
149+
return floatValue;
140150
}
141151

142152
int JsonValue::getInt() const {
143-
big_int val = getValue();
144-
if (val < INT_MIN || val > INT_MAX) throw std::logic_error("Value too large for an int");
145-
return int(val);
153+
auto val = getIntValue();
154+
if (val < INT_MIN || val > INT_MAX) throw std::logic_error("Value too large for int");
155+
return static_cast<int>(val);
146156
}
147157

148158
JsonArray *JsonArray::append(IJson *value) {

lib/json.h

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,30 +54,38 @@ class JsonValue final : public IJson {
5454
#endif
5555

5656
public:
57-
enum Kind { String, Number, True, False, Null };
57+
enum Kind { String, Integer, Float, True, False, Null };
5858
JsonValue() : tag(Kind::Null) {}
59-
JsonValue(bool b) : tag(b ? Kind::True : Kind::False) {} // NOLINT
60-
JsonValue(big_int v) : tag(Kind::Number), value(v) {} // NOLINT
61-
JsonValue(int v) : tag(Kind::Number), value(v) {} // NOLINT
62-
JsonValue(long v) : tag(Kind::Number), value(v) {} // NOLINT
63-
JsonValue(long long v); // NOLINT
64-
JsonValue(unsigned v) : tag(Kind::Number), value(v) {} // NOLINT
65-
JsonValue(unsigned long v) : tag(Kind::Number), value(v) {} // NOLINT
66-
JsonValue(unsigned long long v); // NOLINT
67-
JsonValue(double v) : tag(Kind::Number), value(v) {} // NOLINT
68-
JsonValue(float v) : tag(Kind::Number), value(v) {} // NOLINT
69-
JsonValue(cstring s) : tag(Kind::String), str(s) {} // NOLINT
59+
JsonValue(bool b) : tag(b ? Kind::True : Kind::False) {} // NOLINT
60+
JsonValue(big_int v) : tag(Kind::Integer), intValue(v) {} // NOLINT
61+
JsonValue(int v) : tag(Kind::Integer), intValue(v) {} // NOLINT
62+
JsonValue(long v) : tag(Kind::Integer), intValue(v) {} // NOLINT
63+
JsonValue(long long v); // NOLINT
64+
JsonValue(unsigned v) : tag(Kind::Integer), intValue(v) {} // NOLINT
65+
JsonValue(unsigned long v) : tag(Kind::Integer), intValue(v) {} // NOLINT
66+
JsonValue(unsigned long long v); // NOLINT
67+
JsonValue(double v) : tag(Kind::Float), floatValue(v) {} // NOLINT
68+
JsonValue(float v) : tag(Kind::Float), floatValue(v) {} // NOLINT
69+
JsonValue(cstring s) : tag(Kind::String), str(s) {} // NOLINT
7070
// FIXME: replace these two ctors with std::string view, cannot do now as
7171
// std::string is implicitly convertible to cstring
7272
JsonValue(const char *s) : tag(Kind::String), str(s) {} // NOLINT
7373
JsonValue(const std::string &s) : tag(Kind::String), str(s) {} // NOLINT
7474
void serialize(std::ostream &out) const override;
7575

7676
bool operator==(const big_int &v) const;
77-
// is_integral is true for bool
77+
// Integer types
7878
template <typename T, typename std::enable_if_t<std::is_integral_v<T>, int> = 0>
7979
bool operator==(const T &v) const {
80-
return (tag == Kind::Number) && (v == value);
80+
if (tag == Kind::Integer) return intValue == v;
81+
return false;
82+
}
83+
84+
template <typename T, typename std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
85+
bool operator==(const T &v) const {
86+
if (tag == Kind::Integer) return static_cast<double>(intValue) == static_cast<double>(v);
87+
if (tag == Kind::Float) return floatValue == static_cast<double>(v);
88+
return false;
8189
}
8290
bool operator==(const double &v) const;
8391
bool operator==(const float &v) const;
@@ -88,26 +96,30 @@ class JsonValue final : public IJson {
8896
bool operator==(const std::string &s) const;
8997
bool operator==(const JsonValue &other) const;
9098

91-
bool isNumber() const { return tag == Kind::Number; }
99+
bool isNumber() const { return tag == Kind::Integer || tag == Kind::Float; }
92100
bool isBool() const { return tag == Kind::True || tag == Kind::False; }
93101
bool isString() const { return tag == Kind::String; }
94102
bool isNull() const { return tag == Kind::Null; }
103+
bool isInteger() const { return tag == Kind::Integer; }
104+
bool isFloat() const { return tag == Kind::Float; }
95105

96106
bool getBool() const;
97107
cstring getString() const;
98-
big_int getValue() const;
108+
big_int getIntValue() const;
109+
double getFloatValue() const;
99110
int getInt() const;
100111

101112
static JsonValue *null;
102113

103114
private:
104-
JsonValue(Kind kind) : tag(kind) { // NOLINT
105-
if (kind == Kind::String || kind == Kind::Number)
115+
JsonValue(Kind kind) : tag(kind) {
116+
if (kind == Kind::String || kind == Kind::Integer || kind == Kind::Float)
106117
throw std::logic_error("Incorrect constructor called");
107118
}
108119

109120
const Kind tag;
110-
const big_int value = 0;
121+
const big_int intValue = 0;
122+
const double floatValue = 0.0;
111123
const cstring str = cstring::empty;
112124

113125
DECLARE_TYPEINFO(JsonValue, IJson);

test/gtest/json_test.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ TEST(Util, Json) {
5050
auto smallestLongLong = static_cast<long long>(1LL << 63);
5151
value = new JsonValue(smallestLongLong);
5252
EXPECT_EQ(getNumStringRepr(smallestLongLong), value->toString());
53+
value = new JsonValue(0.0f);
54+
EXPECT_EQ("0", value->toString());
55+
value = new JsonValue(3.14f);
56+
EXPECT_EQ("3.14", value->toString());
57+
value = new JsonValue(2.718);
58+
EXPECT_EQ("2.718", value->toString());
59+
value = new JsonValue(-0.00123);
60+
EXPECT_EQ("-0.00123", value->toString());
61+
value = new JsonValue(1.23456e-10);
62+
EXPECT_EQ("1.23456e-10", value->toString());
63+
value = new JsonValue(static_cast<float>(1.0 / 3.0));
64+
std::string floatStr = value->toString().string();
65+
EXPECT_EQ(floatStr.find("0.333"), 0);
5366

5467
auto arr = new JsonArray();
5568
arr->append(5);

0 commit comments

Comments
 (0)