Allow Json parser understand TER strings where appropriate

This commit is contained in:
Edward Hennis
2017-04-05 17:12:12 -04:00
committed by Scott Schurr
parent 7e9ac16c22
commit 46004158a2
8 changed files with 293 additions and 6 deletions

View File

@@ -31,6 +31,7 @@
#include <ripple/protocol/STInteger.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/protocol/STPathSet.h>
#include <ripple/protocol/TER.h>
#include <ripple/protocol/TxFormats.h>
#include <ripple/protocol/types.h>
#include <ripple/protocol/impl/STVar.h>
@@ -189,31 +190,61 @@ static boost::optional<detail::STVar> parseLeaf (
case STI_UINT8:
try
{
constexpr auto minValue = std::numeric_limits<std::uint8_t>::min();
constexpr auto maxValue = std::numeric_limits<std::uint8_t>::max();
if (value.isString ())
{
// VFALCO TODO wtf?
std::string const strValue = value.asString();
if (!strValue.empty() &&
((strValue[0] < '0') || (strValue[0] > '9')))
{
if (field == sfTransactionResult)
{
auto ter = transCode(strValue);
if (!ter || *ter < minValue || *ter > maxValue)
{
error = out_of_range(json_name, fieldName);
return ret;
}
ret = detail::make_stvar<STUInt8>(field,
static_cast<std::uint8_t>(*ter));
}
else
{
error = bad_type(json_name, fieldName);
return ret;
}
}
else
{
ret = detail::make_stvar <STUInt8>(field,
beast::lexicalCastThrow <std::uint8_t>(strValue));
}
}
else if (value.isInt ())
{
if (value.asInt () < 0 || value.asInt () > 255)
if (value.asInt () < minValue || value.asInt () > maxValue)
{
error = out_of_range (json_name, fieldName);
return ret;
}
ret = detail::make_stvar <STUInt8> (field,
static_cast <unsigned char> (value.asInt ()));
static_cast <std::uint8_t> (value.asInt ()));
}
else if (value.isUInt ())
{
if (value.asUInt () > 255)
if (value.asUInt () > maxValue)
{
error = out_of_range (json_name, fieldName);
return ret;
}
ret = detail::make_stvar <STUInt8> (field,
static_cast <unsigned char> (value.asUInt ()));
static_cast <std::uint8_t> (value.asUInt ()));
}
else
{

View File

@@ -19,12 +19,19 @@
#include <BeastConfig.h>
#include <ripple/protocol/TER.h>
#include <boost/range/adaptor/transformed.hpp>
#include <unordered_map>
#include <type_traits>
namespace ripple {
bool transResultInfo (TER code, std::string& token, std::string& text)
namespace detail {
static
std::unordered_map<
std::underlying_type_t<TER>,
std::pair<char const* const, char const* const>> const&
transResults()
{
static
std::unordered_map<
@@ -141,6 +148,14 @@ bool transResultInfo (TER code, std::string& token, std::string& text)
{ tesSUCCESS, { "tesSUCCESS", "The transaction was applied. Only final in a validated ledger." } },
};
return results;
}
}
bool transResultInfo (TER code, std::string& token, std::string& text)
{
auto& results = detail::transResults();
auto const r = results.find (
static_cast<std::underlying_type_t<TER>> (code));
@@ -169,4 +184,35 @@ std::string transHuman (TER code)
return transResultInfo (code, token, text) ? text : "-";
}
boost::optional<TER>
transCode(std::string const& token)
{
static
auto const results = []
{
auto& byTer = detail::transResults();
auto range = boost::make_iterator_range(byTer.begin(),
byTer.end());
auto tRange = boost::adaptors::transform(
range,
[](auto const& r)
{
return std::make_pair(r.second.first, r.first);
}
);
std::unordered_map<
std::string,
std::underlying_type_t<TER>> const
byToken(tRange.begin(), tRange.end());
return byToken;
}();
auto const r = results.find(token);
if (r == results.end())
return boost::none;
return static_cast<TER>(r->second);
}
} // ripple