mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[libsolutil] JSON: Add ofType, ofTypeIfExists & getOrDefault.
This commit is contained in:
parent
5c9c88ccc9
commit
555d774f64
@ -34,7 +34,7 @@
|
||||
#include <liblangutil/CharStream.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
#include <json/json.h>
|
||||
#include <libsolutil/JSON.h>
|
||||
|
||||
#include <range/v3/algorithm/any_of.hpp>
|
||||
#include <range/v3/view/enumerate.hpp>
|
||||
@ -98,14 +98,23 @@ void Assembly::addAssemblyItemsFromJSON(Json::Value const& _code)
|
||||
|
||||
AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json)
|
||||
{
|
||||
std::string name = _json["name"].isString() ? _json["name"].asString() : "";
|
||||
int begin = _json["begin"].isInt() ? _json["begin"].asInt() : -1;
|
||||
int end = _json["end"].isInt() ? _json["end"].asInt() : -1;
|
||||
int srcIndex = _json["source"].isInt() ? _json["source"].asInt() : -1;
|
||||
size_t modifierDepth = _json["modifierDepth"].isInt() ? static_cast<size_t>(_json["modifierDepth"].asInt()) : 0;
|
||||
std::string value = _json["value"].isString() ? _json["value"].asString() : "";
|
||||
std::string jumpType = _json["jumpType"].isString() ? _json["jumpType"].asString() : "";
|
||||
solAssert(!name.empty(), "");
|
||||
solAssert(ofType<std::string>(_json, "name"));
|
||||
solAssert(ofType<int>(_json, "begin"));
|
||||
solAssert(ofType<int>(_json, "end"));
|
||||
solAssert(ofType<int>(_json, "source"));
|
||||
solAssert(ofTypeIfExists<std::string>(_json, "value"));
|
||||
solAssert(ofTypeIfExists<int>(_json, "modifierDepth"));
|
||||
solAssert(ofTypeIfExists<std::string>(_json, "jumpType"));
|
||||
|
||||
std::string name = getOrDefault<std::string>(_json, "name", "");
|
||||
solAssert(!name.empty());
|
||||
|
||||
int begin = getOrDefault<int>(_json, "begin", -1);
|
||||
int end = getOrDefault<int>(_json, "end", -1);
|
||||
int srcIndex = getOrDefault<int>(_json, "source", -1);
|
||||
size_t modifierDepth = static_cast<size_t>(getOrDefault<int>(_json, "modifierDepth", 0));
|
||||
std::string value = getOrDefault<std::string>(_json, "value", "");
|
||||
std::string jumpType = getOrDefault<std::string>(_json, "jumpType", "");
|
||||
|
||||
SourceLocation location;
|
||||
location.start = begin;
|
||||
|
@ -67,4 +67,57 @@ 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;
|
||||
|
||||
#define DEFINE_HELPER(TYPE, CHECK_TYPE, CONVERT_TYPE) \
|
||||
template<> \
|
||||
struct helper<TYPE> \
|
||||
{ \
|
||||
static bool ofType(Json::Value const& _input, std::string const& _name) \
|
||||
{ \
|
||||
return _input[_name].CHECK_TYPE(); \
|
||||
} \
|
||||
static TYPE getOrDefault(Json::Value const& _input, std::string const& _name, TYPE _default = {}) \
|
||||
{ \
|
||||
TYPE result = _default; \
|
||||
if (helper::ofType(_input, _name)) \
|
||||
result = _input[_name].CONVERT_TYPE(); \
|
||||
return result; \
|
||||
} \
|
||||
};
|
||||
|
||||
DEFINE_HELPER(float, isDouble, asFloat)
|
||||
DEFINE_HELPER(double, isDouble, asDouble)
|
||||
DEFINE_HELPER(std::string, isString, asString)
|
||||
DEFINE_HELPER(Json::Int, isInt, asInt)
|
||||
DEFINE_HELPER(Json::Int64, isInt64, asInt64)
|
||||
DEFINE_HELPER(Json::UInt, isUInt, asUInt)
|
||||
DEFINE_HELPER(Json::UInt64, isUInt64, asUInt64)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
bool ofType(Json::Value const& _input, std::string const& _name)
|
||||
{
|
||||
return detail::helper<T>::ofType(_input, _name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ofTypeIfExists(Json::Value const& _input, std::string const& _name)
|
||||
{
|
||||
if (_input.isMember(_name))
|
||||
return ofType<T>(_input, _name);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getOrDefault(Json::Value const& _input, std::string const& _name, T _default = {})
|
||||
{
|
||||
return detail::helper<T>::getOrDefault(_input, _name, _default);
|
||||
}
|
||||
|
||||
} // namespace solidity::util
|
||||
|
@ -184,6 +184,108 @@ BOOST_AUTO_TEST_CASE(parse_json_strict)
|
||||
BOOST_CHECK(json[0] == "😊");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_ofType)
|
||||
{
|
||||
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(ofType<float>(json, "float"));
|
||||
BOOST_CHECK(ofType<double>(json, "double"));
|
||||
BOOST_CHECK(ofType<int>(json, "int"));
|
||||
BOOST_CHECK(ofType<Json::Int>(json, "int"));
|
||||
BOOST_CHECK(ofType<Json::UInt>(json, "int"));
|
||||
BOOST_CHECK(ofType<Json::Int64>(json, "int"));
|
||||
BOOST_CHECK(ofType<Json::Int64>(json, "int64"));
|
||||
BOOST_CHECK(ofType<Json::UInt64>(json, "int64"));
|
||||
BOOST_CHECK(ofType<std::string>(json, "string"));
|
||||
BOOST_CHECK(!ofType<Json::Int>(json, "int64"));
|
||||
BOOST_CHECK(!ofType<int>(json, "double"));
|
||||
BOOST_CHECK(!ofType<float>(json, "string"));
|
||||
BOOST_CHECK(!ofType<double>(json, "string"));
|
||||
BOOST_CHECK(!ofType<Json::Int>(json, "string"));
|
||||
BOOST_CHECK(!ofType<Json::Int64>(json, "string"));
|
||||
BOOST_CHECK(!ofType<Json::UInt>(json, "string"));
|
||||
BOOST_CHECK(!ofType<Json::UInt64>(json, "string"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_ofTypeIfExists)
|
||||
{
|
||||
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(ofTypeIfExists<float>(json, "float"));
|
||||
BOOST_CHECK(ofTypeIfExists<double>(json, "double"));
|
||||
BOOST_CHECK(ofTypeIfExists<int>(json, "int"));
|
||||
BOOST_CHECK(ofTypeIfExists<Json::Int>(json, "int"));
|
||||
BOOST_CHECK(ofTypeIfExists<Json::UInt>(json, "int"));
|
||||
BOOST_CHECK(ofTypeIfExists<Json::Int64>(json, "int"));
|
||||
BOOST_CHECK(ofTypeIfExists<Json::Int64>(json, "int64"));
|
||||
BOOST_CHECK(ofTypeIfExists<Json::UInt64>(json, "int64"));
|
||||
BOOST_CHECK(ofTypeIfExists<std::string>(json, "string"));
|
||||
BOOST_CHECK(!ofTypeIfExists<Json::Int>(json, "int64"));
|
||||
BOOST_CHECK(!ofTypeIfExists<int>(json, "double"));
|
||||
BOOST_CHECK(!ofTypeIfExists<float>(json, "string"));
|
||||
BOOST_CHECK(!ofTypeIfExists<double>(json, "string"));
|
||||
BOOST_CHECK(!ofTypeIfExists<Json::Int>(json, "string"));
|
||||
BOOST_CHECK(!ofTypeIfExists<Json::Int64>(json, "string"));
|
||||
BOOST_CHECK(!ofTypeIfExists<Json::UInt>(json, "string"));
|
||||
BOOST_CHECK(!ofTypeIfExists<Json::UInt64>(json, "string"));
|
||||
BOOST_CHECK(ofTypeIfExists<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_SUITE_END()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user