Skip to content

Commit 0ae37c8

Browse files
committed
[libsolutil] JSON: Add ofType, ofTypeIfExists & getOrDefault.
1 parent be6a359 commit 0ae37c8

File tree

3 files changed

+173
-9
lines changed

3 files changed

+173
-9
lines changed

libevmasm/Assembly.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include <liblangutil/CharStream.h>
3535
#include <liblangutil/Exceptions.h>
3636

37-
#include <json/json.h>
37+
#include <libsolutil/JSON.h>
3838

3939
#include <range/v3/algorithm/any_of.hpp>
4040
#include <range/v3/view/enumerate.hpp>
@@ -98,14 +98,23 @@ void Assembly::addAssemblyItemsFromJSON(Json::Value const& _code)
9898

9999
AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json)
100100
{
101-
std::string name = _json["name"].isString() ? _json["name"].asString() : "";
102-
int begin = _json["begin"].isInt() ? _json["begin"].asInt() : -1;
103-
int end = _json["end"].isInt() ? _json["end"].asInt() : -1;
104-
int srcIndex = _json["source"].isInt() ? _json["source"].asInt() : -1;
105-
size_t modifierDepth = _json["modifierDepth"].isInt() ? static_cast<size_t>(_json["modifierDepth"].asInt()) : 0;
106-
std::string value = _json["value"].isString() ? _json["value"].asString() : "";
107-
std::string jumpType = _json["jumpType"].isString() ? _json["jumpType"].asString() : "";
108-
solAssert(!name.empty(), "");
101+
solAssert(ofType<std::string>(_json, "name"));
102+
solAssert(ofType<int>(_json, "begin"));
103+
solAssert(ofType<int>(_json, "end"));
104+
solAssert(ofType<int>(_json, "source"));
105+
solAssert(ofTypeIfExists<std::string>(_json, "value"));
106+
solAssert(ofTypeIfExists<int>(_json, "modifierDepth"));
107+
solAssert(ofTypeIfExists<std::string>(_json, "jumpType"));
108+
109+
std::string name = getOrDefault<std::string>(_json, "name", "");
110+
solAssert(!name.empty());
111+
112+
int begin = getOrDefault<int>(_json, "begin", -1);
113+
int end = getOrDefault<int>(_json, "end", -1);
114+
int srcIndex = getOrDefault<int>(_json, "source", -1);
115+
size_t modifierDepth = static_cast<size_t>(getOrDefault<int>(_json, "modifierDepth", 0));
116+
std::string value = getOrDefault<std::string>(_json, "value", "");
117+
std::string jumpType = getOrDefault<std::string>(_json, "jumpType", "");
109118

110119
SourceLocation location;
111120
location.start = begin;

libsolutil/JSON.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,57 @@ std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format);
6767
/// \return \c true if the document was successfully parsed, \c false if an error occurred.
6868
bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* _errs = nullptr);
6969

70+
namespace detail
71+
{
72+
73+
template<typename T>
74+
struct helper;
75+
76+
#define DEFINE_HELPER(TYPE, CHECK_TYPE, CONVERT_TYPE) \
77+
template<> \
78+
struct helper<TYPE> \
79+
{ \
80+
static bool ofType(Json::Value const& _input, std::string const& _name) \
81+
{ \
82+
return _input[_name].CHECK_TYPE(); \
83+
} \
84+
static TYPE getOrDefault(Json::Value const& _input, std::string const& _name, TYPE _default = {}) \
85+
{ \
86+
TYPE result = _default; \
87+
if (helper::ofType(_input, _name)) \
88+
result = _input[_name].CONVERT_TYPE(); \
89+
return result; \
90+
} \
91+
};
92+
93+
DEFINE_HELPER(float, isDouble, asFloat)
94+
DEFINE_HELPER(double, isDouble, asDouble)
95+
DEFINE_HELPER(std::string, isString, asString)
96+
DEFINE_HELPER(Json::Int, isInt, asInt)
97+
DEFINE_HELPER(Json::Int64, isInt64, asInt64)
98+
DEFINE_HELPER(Json::UInt, isUInt, asUInt)
99+
DEFINE_HELPER(Json::UInt64, isUInt64, asUInt64)
100+
101+
} // namespace detail
102+
103+
template<typename T>
104+
bool ofType(Json::Value const& _input, std::string const& _name)
105+
{
106+
return detail::helper<T>::ofType(_input, _name);
70107
}
108+
109+
template<typename T>
110+
bool ofTypeIfExists(Json::Value const& _input, std::string const& _name)
111+
{
112+
if (_input.isMember(_name))
113+
return ofType<T>(_input, _name);
114+
return true;
115+
}
116+
117+
template<typename T>
118+
T getOrDefault(Json::Value const& _input, std::string const& _name, T _default = {})
119+
{
120+
return detail::helper<T>::getOrDefault(_input, _name, _default);
121+
}
122+
123+
} // namespace solidity::util

test/libsolutil/JSON.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,108 @@ BOOST_AUTO_TEST_CASE(parse_json_strict)
184184
BOOST_CHECK(json[0] == "😊");
185185
}
186186

187+
BOOST_AUTO_TEST_CASE(json_ofType)
188+
{
189+
Json::Value json;
190+
191+
json["float"] = 3.1f;
192+
json["double"] = 3.1;
193+
json["int"] = 2;
194+
json["int64"] = Json::Int64{0x4000000000000000};
195+
json["string"] = "Hello World!";
196+
197+
BOOST_CHECK(ofType<float>(json, "float"));
198+
BOOST_CHECK(ofType<double>(json, "double"));
199+
BOOST_CHECK(ofType<int>(json, "int"));
200+
BOOST_CHECK(ofType<Json::Int>(json, "int"));
201+
BOOST_CHECK(ofType<Json::UInt>(json, "int"));
202+
BOOST_CHECK(ofType<Json::Int64>(json, "int"));
203+
BOOST_CHECK(ofType<Json::Int64>(json, "int64"));
204+
BOOST_CHECK(ofType<Json::UInt64>(json, "int64"));
205+
BOOST_CHECK(ofType<std::string>(json, "string"));
206+
BOOST_CHECK(!ofType<Json::Int>(json, "int64"));
207+
BOOST_CHECK(!ofType<int>(json, "double"));
208+
BOOST_CHECK(!ofType<float>(json, "string"));
209+
BOOST_CHECK(!ofType<double>(json, "string"));
210+
BOOST_CHECK(!ofType<Json::Int>(json, "string"));
211+
BOOST_CHECK(!ofType<Json::Int64>(json, "string"));
212+
BOOST_CHECK(!ofType<Json::UInt>(json, "string"));
213+
BOOST_CHECK(!ofType<Json::UInt64>(json, "string"));
214+
}
215+
216+
BOOST_AUTO_TEST_CASE(json_ofTypeIfExists)
217+
{
218+
Json::Value json;
219+
220+
json["float"] = 3.1f;
221+
json["double"] = 3.1;
222+
json["int"] = 2;
223+
json["int64"] = Json::Int64{0x4000000000000000};
224+
json["string"] = "Hello World!";
225+
226+
BOOST_CHECK(ofTypeIfExists<float>(json, "float"));
227+
BOOST_CHECK(ofTypeIfExists<double>(json, "double"));
228+
BOOST_CHECK(ofTypeIfExists<int>(json, "int"));
229+
BOOST_CHECK(ofTypeIfExists<Json::Int>(json, "int"));
230+
BOOST_CHECK(ofTypeIfExists<Json::UInt>(json, "int"));
231+
BOOST_CHECK(ofTypeIfExists<Json::Int64>(json, "int"));
232+
BOOST_CHECK(ofTypeIfExists<Json::Int64>(json, "int64"));
233+
BOOST_CHECK(ofTypeIfExists<Json::UInt64>(json, "int64"));
234+
BOOST_CHECK(ofTypeIfExists<std::string>(json, "string"));
235+
BOOST_CHECK(!ofTypeIfExists<Json::Int>(json, "int64"));
236+
BOOST_CHECK(!ofTypeIfExists<int>(json, "double"));
237+
BOOST_CHECK(!ofTypeIfExists<float>(json, "string"));
238+
BOOST_CHECK(!ofTypeIfExists<double>(json, "string"));
239+
BOOST_CHECK(!ofTypeIfExists<Json::Int>(json, "string"));
240+
BOOST_CHECK(!ofTypeIfExists<Json::Int64>(json, "string"));
241+
BOOST_CHECK(!ofTypeIfExists<Json::UInt>(json, "string"));
242+
BOOST_CHECK(!ofTypeIfExists<Json::UInt64>(json, "string"));
243+
BOOST_CHECK(ofTypeIfExists<Json::UInt64>(json, "NOT_EXISTING"));
244+
}
245+
246+
BOOST_AUTO_TEST_CASE(json_getOrDefault)
247+
{
248+
Json::Value json;
249+
250+
json["float"] = 3.1f;
251+
json["double"] = 3.1;
252+
json["int"] = 2;
253+
json["int64"] = Json::Int64{0x4000000000000000};
254+
json["uint64"] = Json::UInt64{0x5000000000000000};
255+
json["string"] = "Hello World!";
256+
257+
BOOST_CHECK(getOrDefault<float>(json, "float") == 3.1f);
258+
BOOST_CHECK(getOrDefault<float>(json, "float", -1.1f) == 3.1f);
259+
BOOST_CHECK(getOrDefault<float>(json, "no_float", -1.1f) == -1.1f);
260+
BOOST_CHECK(getOrDefault<double>(json, "double") == 3.1);
261+
BOOST_CHECK(getOrDefault<double>(json, "double", -1) == 3.1);
262+
BOOST_CHECK(getOrDefault<double>(json, "no_double", -1.1) == -1.1);
263+
BOOST_CHECK(getOrDefault<int>(json, "int") == 2);
264+
BOOST_CHECK(getOrDefault<int>(json, "int", -1) == 2);
265+
BOOST_CHECK(getOrDefault<int>(json, "no_int", -1) == -1);
266+
BOOST_CHECK(getOrDefault<Json::Int>(json, "int") == 2);
267+
BOOST_CHECK(getOrDefault<Json::Int>(json, "int", -1) == 2);
268+
BOOST_CHECK(getOrDefault<Json::Int>(json, "no_int", -1) == -1);
269+
BOOST_CHECK(getOrDefault<Json::UInt>(json, "int") == 2);
270+
BOOST_CHECK(getOrDefault<Json::UInt>(json, "int", 1) == 2);
271+
BOOST_CHECK(getOrDefault<Json::UInt>(json, "no_int", 1) == 1);
272+
BOOST_CHECK(getOrDefault<Json::Int64>(json, "int") == 2);
273+
BOOST_CHECK(getOrDefault<Json::Int64>(json, "int", -1) == 2);
274+
BOOST_CHECK(getOrDefault<Json::Int64>(json, "no_int", -1) == -1);
275+
BOOST_CHECK(getOrDefault<Json::Int64>(json, "int64") == 0x4000000000000000);
276+
BOOST_CHECK(getOrDefault<Json::Int64>(json, "int64", -1) == 0x4000000000000000);
277+
BOOST_CHECK(getOrDefault<Json::Int64>(json, "no_int64", -1) == -1);
278+
BOOST_CHECK(getOrDefault<Json::UInt64>(json, "int64") == 0x4000000000000000);
279+
BOOST_CHECK(getOrDefault<Json::UInt64>(json, "int64", 1) == 0x4000000000000000);
280+
BOOST_CHECK(getOrDefault<Json::UInt64>(json, "no_int64", 1) == 1);
281+
BOOST_CHECK(getOrDefault<Json::UInt64>(json, "uint64") == 0x5000000000000000);
282+
BOOST_CHECK(getOrDefault<Json::UInt64>(json, "uint64", 1) == 0x5000000000000000);
283+
BOOST_CHECK(getOrDefault<Json::UInt64>(json, "no_uint64", 1) == 1);
284+
BOOST_CHECK(getOrDefault<std::string>(json, "string", "ERROR") == "Hello World!");
285+
BOOST_CHECK(getOrDefault<std::string>(json, "no_string").empty());
286+
BOOST_CHECK(getOrDefault<std::string>(json, "no_string", "ERROR") == "ERROR");
287+
}
288+
187289
BOOST_AUTO_TEST_SUITE_END()
188290

189291
}

0 commit comments

Comments
 (0)