20#include <xrpl/basics/StringUtilities.h> 
   21#include <xrpl/basics/base_uint.h> 
   22#include <xrpl/basics/contract.h> 
   23#include <xrpl/basics/safe_cast.h> 
   24#include <xrpl/beast/core/LexicalCast.h> 
   25#include <xrpl/json/json_forwards.h> 
   26#include <xrpl/json/json_value.h> 
   27#include <xrpl/protocol/AccountID.h> 
   28#include <xrpl/protocol/ErrorCodes.h> 
   29#include <xrpl/protocol/LedgerFormats.h> 
   30#include <xrpl/protocol/Permissions.h> 
   31#include <xrpl/protocol/SField.h> 
   32#include <xrpl/protocol/STAccount.h> 
   33#include <xrpl/protocol/STAmount.h> 
   34#include <xrpl/protocol/STArray.h> 
   35#include <xrpl/protocol/STBitString.h> 
   36#include <xrpl/protocol/STBlob.h> 
   37#include <xrpl/protocol/STCurrency.h> 
   38#include <xrpl/protocol/STInteger.h> 
   39#include <xrpl/protocol/STIssue.h> 
   40#include <xrpl/protocol/STNumber.h> 
   41#include <xrpl/protocol/STParsedJSON.h> 
   42#include <xrpl/protocol/STPathSet.h> 
   43#include <xrpl/protocol/STVector256.h> 
   44#include <xrpl/protocol/STXChainBridge.h> 
   45#include <xrpl/protocol/TER.h> 
   46#include <xrpl/protocol/TxFormats.h> 
   47#include <xrpl/protocol/UintTypes.h> 
   48#include <xrpl/protocol/detail/STVar.h> 
   65namespace STParsedJSONDetail {
 
   66template <
typename U, 
typename S>
 
   72        Throw<std::runtime_error>(
"Value out of range");
 
   73    return static_cast<U
>(value);
 
 
   76template <
typename U1, 
typename U2>
 
   82        Throw<std::runtime_error>(
"Value out of range");
 
   83    return static_cast<U1
>(value);
 
 
   93    return object + 
"." + field;
 
 
  101        "Field '" + 
make_name(
object, field) + 
"' is not a JSON object.");
 
 
  122        "Field '" + 
make_name(
object, field) + 
"' is unknown.");
 
 
  130        "Field '" + 
make_name(
object, field) + 
"' is out of range.");
 
 
  138        "Field '" + 
make_name(
object, field) + 
"' has bad type.");
 
 
  146        "Field '" + 
make_name(
object, field) + 
"' has invalid data.");
 
 
  160        "Field '" + 
make_name(
object, field) + 
"' must be a JSON array.");
 
 
  168        "Field '" + 
make_name(
object, field) + 
"' must be a string.");
 
 
  176        "Field '" + 
object + 
"' exceeds nesting depth limit.");
 
 
  185            "]' must be an object with a single key/object value.");
 
 
  193        "Object '" + sField.
getName() +
 
  194            "' contents did not meet requirements for that type.");
 
 
  203            " is not an object.  Arrays may only contain objects.");
 
 
  207template <
class STResult, 
class Integer>
 
  223            ret = detail::make_stvar<STResult>(
 
  225                safe_cast<typename STResult::value_type>(
 
  226                    beast::lexicalCastThrow<Integer>(value.
asString())));
 
  228        else if (value.
isInt())
 
  230            ret = detail::make_stvar<STResult>(
 
  232                to_unsigned<typename STResult::value_type>(value.
asInt()));
 
  236            ret = detail::make_stvar<STResult>(
 
  238                to_unsigned<typename STResult::value_type>(value.
asUInt()));
 
  242            error = 
bad_type(json_name, fieldName);
 
 
  255template <
class STResult, 
class Integer = std::u
int16_t>
 
  273            if (!strValue.
empty() &&
 
  274                ((strValue[0] < 
'0') || (strValue[0] > 
'9')))
 
  276                if (field == sfTransactionType)
 
  278                    ret = detail::make_stvar<STResult>(
 
  280                        safe_cast<typename STResult::value_type>(
 
  281                            static_cast<Integer
>(
 
  286                        name = &sfTransaction;
 
  288                else if (field == sfLedgerEntryType)
 
  290                    ret = detail::make_stvar<STResult>(
 
  292                        safe_cast<typename STResult::value_type>(
 
  293                            static_cast<Integer
>(
 
  298                        name = &sfLedgerEntry;
 
  308            return parseUnsigned<STResult, Integer>(
 
  309                field, json_name, fieldName, name, value, error);
 
 
  320template <
class STResult, 
class Integer = std::u
int32_t>
 
  336            if (field == sfPermissionValue)
 
  339                auto const granularPermission =
 
  341                if (granularPermission)
 
  343                    ret = detail::make_stvar<STResult>(
 
  344                        field, *granularPermission);
 
  350                    ret = detail::make_stvar<STResult>(
 
  357                ret = detail::make_stvar<STResult>(
 
  359                    safe_cast<typename STResult::value_type>(
 
  360                        beast::lexicalCastThrow<Integer>(value.
asString())));
 
  364            return parseUnsigned<STResult, Integer>(
 
  365                field, json_name, fieldName, name, value, error);
 
 
  399    switch (field.fieldType)
 
  404                constexpr auto minValue =
 
  406                constexpr auto maxValue =
 
  412                    if (!strValue.
empty() &&
 
  413                        ((strValue[0] < 
'0') || (strValue[0] > 
'9')))
 
  415                        if (field == sfTransactionResult)
 
  419                            if (!ter || 
TERtoInt(*ter) < minValue ||
 
  426                            ret = detail::make_stvar<STUInt8>(
 
  432                            error = 
bad_type(json_name, fieldName);
 
  438                        ret = detail::make_stvar<STUInt8>(
 
  440                            beast::lexicalCastThrow<std::uint8_t>(strValue));
 
  443                else if (value.
isInt())
 
  445                    if (value.
asInt() < minValue || value.
asInt() > maxValue)
 
  451                    ret = detail::make_stvar<STUInt8>(
 
  456                    if (value.
asUInt() > maxValue)
 
  462                    ret = detail::make_stvar<STUInt8>(
 
  467                    error = 
bad_type(json_name, fieldName);
 
  479            ret = parseUint16<STUInt16>(
 
  480                field, json_name, fieldName, name, value, error);
 
  487            ret = parseUint32<STUInt32>(
 
  488                field, json_name, fieldName, name, value, error);
 
  503                    bool const useBase10 =
 
  509                        str.data() + str.size(),
 
  511                        useBase10 ? 10 : 16);
 
  513                    if (ec != 
std::errc() || (p != str.data() + str.size()))
 
  514                        Throw<std::invalid_argument>(
"invalid data");
 
  516                    ret = detail::make_stvar<STUInt64>(field, val);
 
  518                else if (value.
isInt())
 
  520                    ret = detail::make_stvar<STUInt64>(
 
  521                        field, to_unsigned<std::uint64_t>(value.
asInt()));
 
  525                    ret = detail::make_stvar<STUInt64>(
 
  526                        field, safe_cast<std::uint64_t>(value.
asUInt()));
 
  530                    error = 
bad_type(json_name, fieldName);
 
  545                error = 
bad_type(json_name, fieldName);
 
  562            ret = detail::make_stvar<STUInt128>(field, num);
 
  569                error = 
bad_type(json_name, fieldName);
 
  586            ret = detail::make_stvar<STUInt160>(field, num);
 
  593                error = 
bad_type(json_name, fieldName);
 
  610            ret = detail::make_stvar<STUInt192>(field, num);
 
  617                error = 
bad_type(json_name, fieldName);
 
  634            ret = detail::make_stvar<STUInt256>(field, num);
 
  643                    ret = detail::make_stvar<STInt32>(
 
  645                        beast::lexicalCastThrow<std::int32_t>(
 
  648                else if (value.
isInt())
 
  655                    ret = detail::make_stvar<STInt32>(field, value.
asInt());
 
  659                    auto const uintValue = value.
asUInt();
 
  667                    ret = detail::make_stvar<STInt32>(
 
  672                    error = 
bad_type(json_name, fieldName);
 
  687                error = 
bad_type(json_name, fieldName);
 
  695                    ret = detail::make_stvar<STBlob>(
 
  696                        field, vBlob->data(), vBlob->size());
 
  700                    Throw<std::invalid_argument>(
"invalid data");
 
  753                        Throw<std::invalid_argument>(
"invalid data");
 
  756                ret = detail::make_stvar<STVector256>(std::move(tail));
 
  781                    if (!value[i].isArrayOrNull())
 
  784                        ss << fieldName << 
"[" << i << 
"]";
 
  792                        ss << fieldName << 
"[" << i << 
"][" << j << 
"]";
 
  794                            json_name + 
"." + ss.
str());
 
  810                        bool hasCurrency = 
false;
 
  814                        if (!account && !currency && !issuer)
 
  823                            if (!account.isString())
 
  832                            if (!uAccount.
parseHex(account.asString()))
 
  835                                    parseBase58<AccountID>(account.asString());
 
  882                                    parseBase58<AccountID>(issuer.
asString());
 
  894                            uAccount, uCurrency, uIssuer, hasCurrency);
 
  899                ret = detail::make_stvar<STPathSet>(std::move(tail));
 
  912                error = 
bad_type(json_name, fieldName);
 
  920                if (
AccountID account; account.parseHex(strValue))
 
  921                    return detail::make_stvar<STAccount>(field, account);
 
  923                if (
auto result = parseBase58<AccountID>(strValue))
 
  924                    return detail::make_stvar<STAccount>(field, *result);
 
  940                ret = detail::make_stvar<STIssue>(
issueFromJson(field, value));
 
  949        case STI_XCHAIN_BRIDGE:
 
  952                ret = detail::make_stvar<STXChainBridge>(
 
  965                ret = detail::make_stvar<STCurrency>(
 
  976            error = 
bad_type(json_name, fieldName);
 
 
 1030            switch (field.fieldType)
 
 1034                case STI_TRANSACTION:
 
 1035                case STI_LEDGERENTRY:
 
 1036                case STI_VALIDATION:
 
 1046                            json_name + 
"." + fieldName,
 
 1053                        data.emplace_back(std::move(*ret));
 
 1068                            json_name + 
"." + fieldName,
 
 1073                        if (!array.has_value())
 
 1075                        data.emplace_back(std::move(*array));
 
 1088                        parseLeaf(json_name, fieldName, &inName, value, error);
 
 1093                    data.emplace_back(std::move(*leaf));
 
 1101        data.applyTemplateFromSField(inName);  
 
 
 1143            bool const isObjectOrNull(json[i].isObjectOrNull());
 
 1144            bool const singleKey(isObjectOrNull ? json[i].size() == 1 : 
true);
 
 1146            if (!isObjectOrNull || !singleKey)
 
 1156            std::string const objectName(json[i].getMemberNames()[0]);
 
 1166            Json::Value const objectFields(json[i][objectName]);
 
 1169            ss << json_name << 
"." << 
"[" << i << 
"]." << objectName;
 
 1172                ss.
str(), objectFields, nameField, depth + 1, error);
 
 1175                std::string errMsg = error[
"error_message"].asString();
 
 1176                error[
"error_message"] =
 
 1177                    "Error at '" + ss.
str() + 
"'. " + errMsg;
 
 1181            if (ret->getFName().fieldType != STI_OBJECT)
 
 1183                ss << 
"Field type: " << ret->getFName().fieldType << 
" ";
 
 1191        return detail::make_stvar<STArray>(std::move(tail));
 
 
 
 1208    using namespace STParsedJSONDetail;
 
 
bool isObjectOrNull() const
 
Members getMemberNames() const
Return a list of the member names.
 
bool isValidIndex(UInt index) const
Return true if index < size().
 
std::string asString() const
Returns the unquoted string value.
 
bool isArrayOrNull() const
 
std::optional< std::uint32_t > getGranularValue(std::string const &name) const
 
static Permission const & getInstance()
 
std::string const & getName() const
 
static SField const & getField(int fieldCode)
 
void push_back(STObject const &object)
 
Json::Value error
On failure, an appropriate set of error values.
 
STParsedJSONObject()=delete
 
void push_back(STPath const &e)
 
void emplace_back(Args &&... args)
 
void push_back(uint256 const &v)
 
Integers of any length that is a multiple of 32-bits.
 
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
 
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
 
static std::optional< detail::STVar > parseUint16(SField const &field, std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
 
static std::optional< detail::STVar > parseLeaf(std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
 
static Json::Value not_an_object(std::string const &object, std::string const &field)
 
static std::optional< detail::STVar > parseUnsigned(SField const &field, std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
 
static Json::Value bad_type(std::string const &object, std::string const &field)
 
constexpr std::enable_if_t< std::is_unsigned< U >::value &&std::is_signed< S >::value, U > to_unsigned(S value)
 
static std::optional< detail::STVar > parseArray(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
 
static Json::Value array_expected(std::string const &object, std::string const &field)
 
static Json::Value singleton_expected(std::string const &object, unsigned int index)
 
static Json::Value not_an_array(std::string const &object)
 
static std::optional< detail::STVar > parseUint32(SField const &field, std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
 
static Json::Value invalid_data(std::string const &object, std::string const &field)
 
static Json::Value non_object_in_array(std::string const &item, Json::UInt index)
 
static std::optional< STObject > parseObject(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
 
static Json::Value too_deep(std::string const &object)
 
static Json::Value unknown_field(std::string const &object, std::string const &field)
 
static Json::Value template_mismatch(SField const &sField)
 
static Json::Value out_of_range(std::string const &object, std::string const &field)
 
static Json::Value string_expected(std::string const &object, std::string const &field)
 
static int const maxDepth
 
static std::string make_name(std::string const &object, std::string const &field)
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
 
STCurrency currencyFromJson(SField const &name, Json::Value const &v)
 
STAmount amountFromJson(SField const &name, Json::Value const &v)
 
Issue issueFromJson(Json::Value const &v)
 
constexpr TERUnderlyingType TERtoInt(TELcodes v)
 
STNumber numberFromJson(SField const &field, Json::Value const &value)
 
std::optional< TER > transCode(std::string const &token)
 
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.