mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #13579 from ethereum/refactor-json
[libsolutil] Add new JSON helper functions.
This commit is contained in:
commit
0c168b154c
@ -67,4 +67,66 @@ std::string jsonPrint(Json::Value const& _input, JsonFormat const& _format);
|
||||
/// \return \c true if the document was successfully parsed, \c false if an error occurred.
|
||||
bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* _errs = nullptr);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct helper;
|
||||
|
||||
template<typename T, bool(Json::Value::*checkMember)() const, T(Json::Value::*convertMember)() const>
|
||||
struct helper_impl
|
||||
{
|
||||
static bool isOfType(Json::Value const& _input)
|
||||
{
|
||||
return (_input.*checkMember)();
|
||||
}
|
||||
static T get(Json::Value const& _input)
|
||||
{
|
||||
return (_input.*convertMember)();
|
||||
}
|
||||
static T getOrDefault(Json::Value const& _input, T _default = {})
|
||||
{
|
||||
T result = _default;
|
||||
if (isOfType(_input))
|
||||
result = (_input.*convertMember)();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct helper<float>: helper_impl<float, &Json::Value::isDouble, &Json::Value::asFloat> {};
|
||||
template<> struct helper<double>: helper_impl<double, &Json::Value::isDouble, &Json::Value::asDouble> {};
|
||||
template<> struct helper<std::string>: helper_impl<std::string, &Json::Value::isString, &Json::Value::asString> {};
|
||||
template<> struct helper<Json::Int>: helper_impl<Json::Int, &Json::Value::isInt, &Json::Value::asInt> {};
|
||||
template<> struct helper<Json::Int64>: helper_impl<Json::Int64, &Json::Value::isInt64, &Json::Value::asInt64> {};
|
||||
template<> struct helper<Json::UInt>: helper_impl<Json::UInt, &Json::Value::isUInt, &Json::Value::asUInt> {};
|
||||
template<> struct helper<Json::UInt64>: helper_impl<Json::UInt64, &Json::Value::isUInt64, &Json::Value::asUInt64> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
bool isOfType(Json::Value const& _input)
|
||||
{
|
||||
return detail::helper<T>::isOfType(_input);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool isOfTypeIfExists(Json::Value const& _input, std::string const& _name)
|
||||
{
|
||||
if (_input.isMember(_name))
|
||||
return isOfType<T>(_input[_name]);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get(Json::Value const& _input)
|
||||
{
|
||||
return detail::helper<T>::get(_input);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getOrDefault(Json::Value const& _input, T _default = {})
|
||||
{
|
||||
return detail::helper<T>::getOrDefault(_input, _default);
|
||||
}
|
||||
|
||||
} // namespace solidity::util
|
||||
|
@ -184,6 +184,131 @@ BOOST_AUTO_TEST_CASE(parse_json_strict)
|
||||
BOOST_CHECK(json[0] == "😊");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_isOfType)
|
||||
{
|
||||
Json::Value json;
|
||||
|
||||
json["float"] = 3.1f;
|
||||
json["double"] = 3.1;
|
||||
json["int"] = 2;
|
||||
json["int64"] = Json::Int64{0x4000000000000000};
|
||||
json["string"] = "Hello World!";
|
||||
|
||||
BOOST_CHECK(isOfType<float>(json["float"]));
|
||||
BOOST_CHECK(isOfType<double>(json["double"]));
|
||||
BOOST_CHECK(isOfType<int>(json["int"]));
|
||||
BOOST_CHECK(isOfType<Json::Int>(json["int"]));
|
||||
BOOST_CHECK(isOfType<Json::UInt>(json["int"]));
|
||||
BOOST_CHECK(isOfType<Json::Int64>(json["int"]));
|
||||
BOOST_CHECK(isOfType<Json::Int64>(json["int64"]));
|
||||
BOOST_CHECK(isOfType<Json::UInt64>(json["int64"]));
|
||||
BOOST_CHECK(isOfType<std::string>(json["string"]));
|
||||
BOOST_CHECK(!isOfType<Json::Int>(json["int64"]));
|
||||
BOOST_CHECK(!isOfType<int>(json["double"]));
|
||||
BOOST_CHECK(!isOfType<float>(json["string"]));
|
||||
BOOST_CHECK(!isOfType<double>(json["string"]));
|
||||
BOOST_CHECK(!isOfType<Json::Int>(json["string"]));
|
||||
BOOST_CHECK(!isOfType<Json::Int64>(json["string"]));
|
||||
BOOST_CHECK(!isOfType<Json::UInt>(json["string"]));
|
||||
BOOST_CHECK(!isOfType<Json::UInt64>(json["string"]));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_isisOfTypeIfExists)
|
||||
{
|
||||
Json::Value json;
|
||||
|
||||
json["float"] = 3.1f;
|
||||
json["double"] = 3.1;
|
||||
json["int"] = 2;
|
||||
json["int64"] = Json::Int64{0x4000000000000000};
|
||||
json["string"] = "Hello World!";
|
||||
|
||||
BOOST_CHECK(isOfTypeIfExists<float>(json, "float"));
|
||||
BOOST_CHECK(isOfTypeIfExists<double>(json, "double"));
|
||||
BOOST_CHECK(isOfTypeIfExists<int>(json, "int"));
|
||||
BOOST_CHECK(isOfTypeIfExists<Json::Int>(json, "int"));
|
||||
BOOST_CHECK(isOfTypeIfExists<Json::UInt>(json, "int"));
|
||||
BOOST_CHECK(isOfTypeIfExists<Json::Int64>(json, "int"));
|
||||
BOOST_CHECK(isOfTypeIfExists<Json::Int64>(json, "int64"));
|
||||
BOOST_CHECK(isOfTypeIfExists<Json::UInt64>(json, "int64"));
|
||||
BOOST_CHECK(isOfTypeIfExists<std::string>(json, "string"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<Json::Int>(json, "int64"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<int>(json, "double"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<float>(json, "string"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<double>(json, "string"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<Json::Int>(json, "string"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<Json::Int64>(json, "string"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<Json::UInt>(json, "string"));
|
||||
BOOST_CHECK(!isOfTypeIfExists<Json::UInt64>(json, "string"));
|
||||
BOOST_CHECK(isOfTypeIfExists<Json::UInt64>(json, "NOT_EXISTING"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_getOrDefault)
|
||||
{
|
||||
Json::Value json;
|
||||
|
||||
json["float"] = 3.1f;
|
||||
json["double"] = 3.1;
|
||||
json["int"] = 2;
|
||||
json["int64"] = Json::Int64{0x4000000000000000};
|
||||
json["uint64"] = Json::UInt64{0x5000000000000000};
|
||||
json["string"] = "Hello World!";
|
||||
|
||||
BOOST_CHECK(getOrDefault<float>(json["float"]) == 3.1f);
|
||||
BOOST_CHECK(getOrDefault<float>(json["float"], -1.1f) == 3.1f);
|
||||
BOOST_CHECK(getOrDefault<float>(json["no_float"], -1.1f) == -1.1f);
|
||||
BOOST_CHECK(getOrDefault<double>(json["double"]) == 3.1);
|
||||
BOOST_CHECK(getOrDefault<double>(json["double"], -1) == 3.1);
|
||||
BOOST_CHECK(getOrDefault<double>(json["no_double"], -1.1) == -1.1);
|
||||
BOOST_CHECK(getOrDefault<int>(json["int"]) == 2);
|
||||
BOOST_CHECK(getOrDefault<int>(json["int"], -1) == 2);
|
||||
BOOST_CHECK(getOrDefault<int>(json["no_int"], -1) == -1);
|
||||
BOOST_CHECK(getOrDefault<Json::Int>(json["int"]) == 2);
|
||||
BOOST_CHECK(getOrDefault<Json::Int>(json["int"], -1) == 2);
|
||||
BOOST_CHECK(getOrDefault<Json::Int>(json["no_int"], -1) == -1);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt>(json["int"]) == 2);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt>(json["int"], 1) == 2);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt>(json["no_int"], 1) == 1);
|
||||
BOOST_CHECK(getOrDefault<Json::Int64>(json["int"]) == 2);
|
||||
BOOST_CHECK(getOrDefault<Json::Int64>(json["int"], -1) == 2);
|
||||
BOOST_CHECK(getOrDefault<Json::Int64>(json["no_int"], -1) == -1);
|
||||
BOOST_CHECK(getOrDefault<Json::Int64>(json["int64"]) == 0x4000000000000000);
|
||||
BOOST_CHECK(getOrDefault<Json::Int64>(json["int64"], -1) == 0x4000000000000000);
|
||||
BOOST_CHECK(getOrDefault<Json::Int64>(json["no_int64"], -1) == -1);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt64>(json["int64"]) == 0x4000000000000000);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt64>(json["int64"], 1) == 0x4000000000000000);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt64>(json["no_int64"], 1) == 1);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt64>(json["uint64"]) == 0x5000000000000000);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt64>(json["uint64"], 1) == 0x5000000000000000);
|
||||
BOOST_CHECK(getOrDefault<Json::UInt64>(json["no_uint64"], 1) == 1);
|
||||
BOOST_CHECK(getOrDefault<std::string>(json["string"], "ERROR") == "Hello World!");
|
||||
BOOST_CHECK(getOrDefault<std::string>(json["no_string"]).empty());
|
||||
BOOST_CHECK(getOrDefault<std::string>(json["no_string"], "ERROR") == "ERROR");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_get)
|
||||
{
|
||||
Json::Value json;
|
||||
|
||||
json["float"] = 3.1f;
|
||||
json["double"] = 3.1;
|
||||
json["int"] = 2;
|
||||
json["int64"] = Json::Int64{0x4000000000000000};
|
||||
json["uint64"] = Json::UInt64{0x5000000000000000};
|
||||
json["string"] = "Hello World!";
|
||||
|
||||
BOOST_CHECK(get<float>(json["float"]) == 3.1f);
|
||||
BOOST_CHECK(get<double>(json["double"]) == 3.1);
|
||||
BOOST_CHECK(get<int>(json["int"]) == 2);
|
||||
BOOST_CHECK(get<Json::Int>(json["int"]) == 2);
|
||||
BOOST_CHECK(get<Json::UInt>(json["int"]) == 2);
|
||||
BOOST_CHECK(get<Json::Int64>(json["int"]) == 2);
|
||||
BOOST_CHECK(get<Json::Int64>(json["int64"]) == 0x4000000000000000);
|
||||
BOOST_CHECK(get<Json::UInt64>(json["int64"]) == 0x4000000000000000);
|
||||
BOOST_CHECK(get<Json::UInt64>(json["uint64"]) == 0x5000000000000000);
|
||||
BOOST_CHECK(get<std::string>(json["string"]) == "Hello World!");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user