Repository: bitcoin/bitcoin
File: src/rpc/client.cpp (C++)

Code before:

class RPCConvertTable
{
public:
    RPCConvertTable() = default;

    const CRPCConvertParam* FromPosition(std::string_view method, int pos) const
    {
        auto it = std::ranges::find_if(vRPCConvertParams, [&](const auto& p) {
            return p.methodName == method && p.paramIdx == pos;
        });

        return it == std::end(vRPCConvertParams) ? nullptr : &*it;
    }

    const CRPCConvertParam* FromName(std::string_view method, std::string_view name) const
    {
        auto it = std::ranges::find_if(vRPCConvertParams, [&](const auto& p) {
            return p.methodName == method && p.paramName == name;
        });

        return it == std::end(vRPCConvertParams) ? nullptr : &*it;
    }
};

static const RPCConvertTable g_rpc_convert_table;

static const CRPCConvertParam* ParamFromPosition(std::string_view method_name, size_t position)
{
    return g_rpc_convert_table.FromPosition(method_name, static_cast<int>(position));
}

static const CRPCConvertParam* ParamFromName(std::string_view method_name, std::string_view param_name)
{
    return g_rpc_convert_table.FromName(method_name, param_name);
}

/** Parse string to UniValue or throw runtime_error if string contains invalid JSON */
static UniValue Parse(std::string_view raw)
{
    UniValue parsed;
    if (!parsed.read(raw)) throw std::runtime_error(tfm::format("Error parsing JSON: %s", raw));
    return parsed;
}

static UniValue ParseParam(const CRPCConvertParam* param, std::string_view raw)
{
    // Only parse parameters which have the JSON format; otherwise, treat them as strings.
    return (param && param->format == ParamFormat::JSON) ? Parse(raw) : UniValue(std::string(raw));
}


Review comment (suggestion):
In commit "rpc: Handle -named argument parsing where '=' character is used" (fbeacfabe802c24b427bee2cd82da1f12ef9899d)

Could consider dropping the RPCConvertTable class and g_rpc_convert_table global variable. The RPCConvertTable class has no state and only has two standalone methods which could be plain functions.

Code after:
    { "signmessage", 1, "message", ParamFormat::STRING },
    { "signmessagewithprivkey", 1, "message", ParamFormat::STRING },
    { "walletpassphrasechange", 0, "oldpassphrase", ParamFormat::STRING },
    { "walletpassphrasechange", 1, "newpassphrase", ParamFormat::STRING },
};
// clang-format on

/** Parse string to UniValue or throw runtime_error if string contains invalid JSON */
static UniValue Parse(std::string_view raw, ParamFormat format = ParamFormat::JSON)
{
    UniValue parsed;
    if (!parsed.read(raw)) {
        if (format != ParamFormat::JSON_OR_STRING) throw std::runtime_error(tfm::format("Error parsing JSON: %s", raw));
        return UniValue(std::string(raw));
    }
    return parsed;
}

namespace rpc_convert
{
const CRPCConvertParam* FromPosition(std::string_view method, size_t pos)
{
    auto it = std::ranges::find_if(vRPCConvertParams, [&](const auto& p) {
        return p.methodName == method && p.paramIdx == static_cast<int>(pos);
    });

    return it == std::end(vRPCConvertParams) ? nullptr : &*it;
}

const CRPCConvertParam* FromName(std::string_view method, std::string_view name)
{
    auto it = std::ranges::find_if(vRPCConvertParams, [&](const auto& p) {
        return p.methodName == method && p.paramName == name;
    });

    return it == std::end(vRPCConvertParams) ? nullptr : &*it;
}
} // namespace rpc_convert

static UniValue ParseParam(const CRPCConvertParam* param, std::string_view raw)
{
    // Only parse parameters which have the JSON or JSON_OR_STRING format; otherwise, treat them as strings.
    return (param && (param->format == ParamFormat::JSON || param->format == ParamFormat::JSON_OR_STRING)) ? Parse(raw, param->format) : UniValue(std::string(raw));
}

/**
 * Convert command lines arguments to params object when -named is disabled.
 */
UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
{
    UniValue params(UniValue::VARR);