diff --git a/include/xrpl/json/Object.h b/include/xrpl/json/Object.h deleted file mode 100644 index 754d0dcb08..0000000000 --- a/include/xrpl/json/Object.h +++ /dev/null @@ -1,445 +0,0 @@ -#ifndef XRPL_JSON_OBJECT_H_INCLUDED -#define XRPL_JSON_OBJECT_H_INCLUDED - -#include - -#include - -namespace Json { - -/** - Collection is a base class for Array and Object, classes which provide the - facade of JSON collections for the O(1) JSON writer, while still using no - heap memory and only a very small amount of stack. - - From http://json.org, JSON has two types of collection: array, and object. - Everything else is a *scalar* - a number, a string, a boolean, the special - value null, or a legacy Json::Value. - - Collections must write JSON "as-it-goes" in order to get the strong - performance guarantees. This puts restrictions upon API users: - - 1. Only one collection can be open for change at any one time. - - This condition is enforced automatically and a std::logic_error thrown if - it is violated. - - 2. A tag may only be used once in an Object. - - Some objects have many tags, so this condition might be a little - expensive. Enforcement of this condition is turned on in debug builds and - a std::logic_error is thrown when the tag is added for a second time. - - Code samples: - - Writer writer; - - // An empty object. - { - Object::Root (writer); - } - // Outputs {} - - // An object with one scalar value. - { - Object::Root root (writer); - write["hello"] = "world"; - } - // Outputs {"hello":"world"} - - // Same, using chaining. - { - Object::Root (writer)["hello"] = "world"; - } - // Output is the same. - - // Add several scalars, with chaining. - { - Object::Root (writer) - .set ("hello", "world") - .set ("flag", false) - .set ("x", 42); - } - // Outputs {"hello":"world","flag":false,"x":42} - - // Add an array. - { - Object::Root root (writer); - { - auto array = root.setArray ("hands"); - array.append ("left"); - array.append ("right"); - } - } - // Outputs {"hands":["left", "right"]} - - // Same, using chaining. - { - Object::Root (writer) - .setArray ("hands") - .append ("left") - .append ("right"); - } - // Output is the same. - - // Add an object. - { - Object::Root root (writer); - { - auto object = root.setObject ("hands"); - object["left"] = false; - object["right"] = true; - } - } - // Outputs {"hands":{"left":false,"right":true}} - - // Same, using chaining. - { - Object::Root (writer) - .setObject ("hands") - .set ("left", false) - .set ("right", true); - } - } - // Outputs {"hands":{"left":false,"right":true}} - - - Typical ways to make mistakes and get a std::logic_error: - - Writer writer; - Object::Root root (writer); - - // Repeat a tag. - { - root ["hello"] = "world"; - root ["hello"] = "there"; // THROWS! in a debug build. - } - - // Open a subcollection, then set something else. - { - auto object = root.setObject ("foo"); - root ["hello"] = "world"; // THROWS! - } - - // Open two subcollections at a time. - { - auto object = root.setObject ("foo"); - auto array = root.setArray ("bar"); // THROWS!! - } - - For more examples, check the unit tests. - */ - -class Collection -{ -public: - Collection(Collection&& c) noexcept; - Collection& - operator=(Collection&& c) noexcept; - Collection() = delete; - - ~Collection(); - -protected: - // A null parent means "no parent at all". - // Writers cannot be null. - Collection(Collection* parent, Writer*); - void - checkWritable(std::string const& label); - - Collection* parent_; - Writer* writer_; - bool enabled_; -}; - -class Array; - -//------------------------------------------------------------------------------ - -/** Represents a JSON object being written to a Writer. */ -class Object : protected Collection -{ -public: - /** Object::Root is the only Collection that has a public constructor. */ - class Root; - - /** Set a scalar value in the Object for a key. - - A JSON scalar is a single value - a number, string, boolean, nullptr or - a Json::Value. - - `set()` throws an exception if this object is disabled (which means that - one of its children is enabled). - - In a debug build, `set()` also throws an exception if the key has - already been set() before. - - An operator[] is provided to allow writing `object["key"] = scalar;`. - */ - template - void - set(std::string const& key, Scalar const&); - - void - set(std::string const& key, Json::Value const&); - - // Detail class and method used to implement operator[]. - class Proxy; - - Proxy - operator[](std::string const& key); - Proxy - operator[](Json::StaticString const& key); - - /** Make a new Object at a key and return it. - - This Object is disabled until that sub-object is destroyed. - Throws an exception if this Object was already disabled. - */ - Object - setObject(std::string const& key); - - /** Make a new Array at a key and return it. - - This Object is disabled until that sub-array is destroyed. - Throws an exception if this Object was already disabled. - */ - Array - setArray(std::string const& key); - -protected: - friend class Array; - Object(Collection* parent, Writer* w) : Collection(parent, w) - { - } -}; - -class Object::Root : public Object -{ -public: - /** Each Object::Root must be constructed with its own unique Writer. */ - Root(Writer&); -}; - -//------------------------------------------------------------------------------ - -/** Represents a JSON array being written to a Writer. */ -class Array : private Collection -{ -public: - /** Append a scalar to the Arrary. - - Throws an exception if this array is disabled (which means that one of - its sub-collections is enabled). - */ - template - void - append(Scalar const&); - - /** - Appends a Json::Value to an array. - Throws an exception if this Array was disabled. - */ - void - append(Json::Value const&); - - /** Append a new Object and return it. - - This Array is disabled until that sub-object is destroyed. - Throws an exception if this Array was disabled. - */ - Object - appendObject(); - - /** Append a new Array and return it. - - This Array is disabled until that sub-array is destroyed. - Throws an exception if this Array was already disabled. - */ - Array - appendArray(); - -protected: - friend class Object; - Array(Collection* parent, Writer* w) : Collection(parent, w) - { - } -}; - -//------------------------------------------------------------------------------ - -// Generic accessor functions to allow Json::Value and Collection to -// interoperate. - -/** Add a new subarray at a named key in a Json object. */ -Json::Value& -setArray(Json::Value&, Json::StaticString const& key); - -/** Add a new subarray at a named key in a Json object. */ -Array -setArray(Object&, Json::StaticString const& key); - -/** Add a new subobject at a named key in a Json object. */ -Json::Value& -addObject(Json::Value&, Json::StaticString const& key); - -/** Add a new subobject at a named key in a Json object. */ -Object -addObject(Object&, Json::StaticString const& key); - -/** Append a new subarray to a Json array. */ -Json::Value& -appendArray(Json::Value&); - -/** Append a new subarray to a Json array. */ -Array -appendArray(Array&); - -/** Append a new subobject to a Json object. */ -Json::Value& -appendObject(Json::Value&); - -/** Append a new subobject to a Json object. */ -Object -appendObject(Array&); - -/** Copy all the keys and values from one object into another. */ -void -copyFrom(Json::Value& to, Json::Value const& from); - -/** Copy all the keys and values from one object into another. */ -void -copyFrom(Object& to, Json::Value const& from); - -/** An Object that contains its own Writer. */ -class WriterObject -{ -public: - WriterObject(Output const& output) - : writer_(std::make_unique(output)) - , object_(std::make_unique(*writer_)) - { - } - - WriterObject(WriterObject&& other) = default; - - Object* - operator->() - { - return object_.get(); - } - - Object& - operator*() - { - return *object_; - } - -private: - std::unique_ptr writer_; - std::unique_ptr object_; -}; - -WriterObject -stringWriterObject(std::string&); - -//------------------------------------------------------------------------------ -// Implementation details. - -// Detail class for Object::operator[]. -class Object::Proxy -{ -private: - Object& object_; - std::string const key_; - -public: - Proxy(Object& object, std::string const& key); - - template - void - operator=(T const& t) - { - object_.set(key_, t); - // Note: This function shouldn't return *this, because it's a trap. - // - // In Json::Value, foo[jss::key] returns a reference to a - // mutable Json::Value contained _inside_ foo. But in the case of - // Json::Object, where we write once only, there isn't any such - // reference that can be returned. Returning *this would return an - // object "a level higher" than in Json::Value, leading to obscure bugs, - // particularly in generic code. - } -}; - -//------------------------------------------------------------------------------ - -template -void -Array::append(Scalar const& value) -{ - checkWritable("append"); - if (writer_) - writer_->append(value); -} - -template -void -Object::set(std::string const& key, Scalar const& value) -{ - checkWritable("set"); - if (writer_) - writer_->set(key, value); -} - -inline Json::Value& -setArray(Json::Value& json, Json::StaticString const& key) -{ - return (json[key] = Json::arrayValue); -} - -inline Array -setArray(Object& json, Json::StaticString const& key) -{ - return json.setArray(std::string(key)); -} - -inline Json::Value& -addObject(Json::Value& json, Json::StaticString const& key) -{ - return (json[key] = Json::objectValue); -} - -inline Object -addObject(Object& object, Json::StaticString const& key) -{ - return object.setObject(std::string(key)); -} - -inline Json::Value& -appendArray(Json::Value& json) -{ - return json.append(Json::arrayValue); -} - -inline Array -appendArray(Array& json) -{ - return json.appendArray(); -} - -inline Json::Value& -appendObject(Json::Value& json) -{ - return json.append(Json::objectValue); -} - -inline Object -appendObject(Array& json) -{ - return json.appendObject(); -} - -} // namespace Json - -#endif diff --git a/include/xrpl/protocol/ApiVersion.h b/include/xrpl/protocol/ApiVersion.h index b2ee64621e..d1a84e76b0 100644 --- a/include/xrpl/protocol/ApiVersion.h +++ b/include/xrpl/protocol/ApiVersion.h @@ -58,14 +58,14 @@ static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion); static_assert(apiBetaVersion >= apiMaximumSupportedVersion); static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion); -template -void -setVersion(JsonObject& parent, unsigned int apiVersion, bool betaEnabled) +inline void +setVersion(Json::Value& parent, unsigned int apiVersion, bool betaEnabled) { XRPL_ASSERT( apiVersion != apiInvalidVersion, "xrpl::RPC::setVersion : input is valid"); - auto& retObj = addObject(parent, jss::version); + + auto& retObj = parent[jss::version] = Json::objectValue; if (apiVersion == apiVersionIfUnspecified) { diff --git a/include/xrpl/protocol/ErrorCodes.h b/include/xrpl/protocol/ErrorCodes.h index 8d5d871aa1..3a2645347a 100644 --- a/include/xrpl/protocol/ErrorCodes.h +++ b/include/xrpl/protocol/ErrorCodes.h @@ -209,33 +209,11 @@ get_error_info(error_code_i code); /** Add or update the json update to reflect the error code. */ /** @{ */ -template void -inject_error(error_code_i code, JsonValue& json) -{ - ErrorInfo const& info(get_error_info(code)); - json[jss::error] = info.token; - json[jss::error_code] = info.code; - json[jss::error_message] = info.message; -} +inject_error(error_code_i code, Json::Value& json); -template void -inject_error(int code, JsonValue& json) -{ - inject_error(error_code_i(code), json); -} - -template -void -inject_error(error_code_i code, std::string const& message, JsonValue& json) -{ - ErrorInfo const& info(get_error_info(code)); - json[jss::error] = info.token; - json[jss::error_code] = info.code; - json[jss::error_message] = message; -} - +inject_error(error_code_i code, std::string const& message, Json::Value& json); /** @} */ /** Returns a new json object that reflects the error code. */ diff --git a/include/xrpl/protocol/RPCErr.h b/include/xrpl/protocol/RPCErr.h index 90df1562e7..fcca15747e 100644 --- a/include/xrpl/protocol/RPCErr.h +++ b/include/xrpl/protocol/RPCErr.h @@ -9,7 +9,7 @@ namespace xrpl { bool isRpcError(Json::Value jvResult); Json::Value -rpcError(int iError); +rpcError(error_code_i iError); } // namespace xrpl diff --git a/src/libxrpl/json/Object.cpp b/src/libxrpl/json/Object.cpp deleted file mode 100644 index ea5e5a32d8..0000000000 --- a/src/libxrpl/json/Object.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace Json { - -Collection::Collection(Collection* parent, Writer* writer) - : parent_(parent), writer_(writer), enabled_(true) -{ - checkWritable("Collection::Collection()"); - if (parent_) - { - check(parent_->enabled_, "Parent not enabled in constructor"); - parent_->enabled_ = false; - } -} - -Collection::~Collection() -{ - if (writer_) - writer_->finish(); - if (parent_) - parent_->enabled_ = true; -} - -Collection& -Collection::operator=(Collection&& that) noexcept -{ - parent_ = that.parent_; - writer_ = that.writer_; - enabled_ = that.enabled_; - - that.parent_ = nullptr; - that.writer_ = nullptr; - that.enabled_ = false; - - return *this; -} - -Collection::Collection(Collection&& that) noexcept -{ - *this = std::move(that); -} - -void -Collection::checkWritable(std::string const& label) -{ - if (!enabled_) - xrpl::Throw(label + ": not enabled"); - if (!writer_) - xrpl::Throw(label + ": not writable"); -} - -//------------------------------------------------------------------------------ - -Object::Root::Root(Writer& w) : Object(nullptr, &w) -{ - writer_->startRoot(Writer::object); -} - -Object -Object::setObject(std::string const& key) -{ - checkWritable("Object::setObject"); - if (writer_) - writer_->startSet(Writer::object, key); - return Object(this, writer_); -} - -Array -Object::setArray(std::string const& key) -{ - checkWritable("Object::setArray"); - if (writer_) - writer_->startSet(Writer::array, key); - return Array(this, writer_); -} - -//------------------------------------------------------------------------------ - -Object -Array::appendObject() -{ - checkWritable("Array::appendObject"); - if (writer_) - writer_->startAppend(Writer::object); - return Object(this, writer_); -} - -Array -Array::appendArray() -{ - checkWritable("Array::makeArray"); - if (writer_) - writer_->startAppend(Writer::array); - return Array(this, writer_); -} - -//------------------------------------------------------------------------------ - -Object::Proxy::Proxy(Object& object, std::string const& key) - : object_(object), key_(key) -{ -} - -Object::Proxy -Object::operator[](std::string const& key) -{ - return Proxy(*this, key); -} - -Object::Proxy -Object::operator[](Json::StaticString const& key) -{ - return Proxy(*this, std::string(key)); -} - -//------------------------------------------------------------------------------ - -void -Array::append(Json::Value const& v) -{ - auto t = v.type(); - switch (t) - { - case Json::nullValue: - return append(nullptr); - case Json::intValue: - return append(v.asInt()); - case Json::uintValue: - return append(v.asUInt()); - case Json::realValue: - return append(v.asDouble()); - case Json::stringValue: - return append(v.asString()); - case Json::booleanValue: - return append(v.asBool()); - - case Json::objectValue: { - auto object = appendObject(); - copyFrom(object, v); - return; - } - - case Json::arrayValue: { - auto array = appendArray(); - for (auto& item : v) - array.append(item); - return; - } - } - UNREACHABLE("Json::Array::append : invalid type"); // LCOV_EXCL_LINE -} - -void -Object::set(std::string const& k, Json::Value const& v) -{ - auto t = v.type(); - switch (t) - { - case Json::nullValue: - return set(k, nullptr); - case Json::intValue: - return set(k, v.asInt()); - case Json::uintValue: - return set(k, v.asUInt()); - case Json::realValue: - return set(k, v.asDouble()); - case Json::stringValue: - return set(k, v.asString()); - case Json::booleanValue: - return set(k, v.asBool()); - - case Json::objectValue: { - auto object = setObject(k); - copyFrom(object, v); - return; - } - - case Json::arrayValue: { - auto array = setArray(k); - for (auto& item : v) - array.append(item); - return; - } - } - UNREACHABLE("Json::Object::set : invalid type"); // LCOV_EXCL_LINE -} - -//------------------------------------------------------------------------------ - -namespace { - -template -void -doCopyFrom(Object& to, Json::Value const& from) -{ - XRPL_ASSERT(from.isObjectOrNull(), "Json::doCopyFrom : valid input type"); - auto members = from.getMemberNames(); - for (auto& m : members) - to[m] = from[m]; -} - -} // namespace - -void -copyFrom(Json::Value& to, Json::Value const& from) -{ - if (!to) // Short circuit this very common case. - to = from; - else - doCopyFrom(to, from); -} - -void -copyFrom(Object& to, Json::Value const& from) -{ - doCopyFrom(to, from); -} - -WriterObject -stringWriterObject(std::string& s) -{ - return WriterObject(stringOutput(s)); -} - -} // namespace Json diff --git a/src/libxrpl/protocol/ErrorCodes.cpp b/src/libxrpl/protocol/ErrorCodes.cpp index f37ba0c8e4..d78ff594e1 100644 --- a/src/libxrpl/protocol/ErrorCodes.cpp +++ b/src/libxrpl/protocol/ErrorCodes.cpp @@ -160,6 +160,24 @@ constexpr ErrorInfo unknownError; //------------------------------------------------------------------------------ +void +inject_error(error_code_i code, Json::Value& json) +{ + ErrorInfo const& info(get_error_info(code)); + json[jss::error] = info.token; + json[jss::error_code] = info.code; + json[jss::error_message] = info.message; +} + +void +inject_error(error_code_i code, std::string const& message, Json::Value& json) +{ + ErrorInfo const& info(get_error_info(code)); + json[jss::error] = info.token; + json[jss::error_code] = info.code; + json[jss::error_message] = message; +} + ErrorInfo const& get_error_info(error_code_i code) { diff --git a/src/libxrpl/protocol/RPCErr.cpp b/src/libxrpl/protocol/RPCErr.cpp index 658dd06b3d..e25b5e574b 100644 --- a/src/libxrpl/protocol/RPCErr.cpp +++ b/src/libxrpl/protocol/RPCErr.cpp @@ -9,7 +9,7 @@ struct RPCErr; // VFALCO NOTE Deprecated function Json::Value -rpcError(int iError) +rpcError(error_code_i iError) { Json::Value jvResult(Json::objectValue); RPC::inject_error(iError, jvResult); diff --git a/src/test/json/Object_test.cpp b/src/test/json/Object_test.cpp deleted file mode 100644 index b74754db33..0000000000 --- a/src/test/json/Object_test.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include - -#include -#include - -namespace Json { - -class JsonObject_test : public xrpl::test::TestOutputSuite -{ - void - setup(std::string const& testName) - { - testcase(testName); - output_.clear(); - } - - std::unique_ptr writerObject_; - - Object& - makeRoot() - { - writerObject_ = - std::make_unique(stringWriterObject(output_)); - return **writerObject_; - } - - void - expectResult(std::string const& expected) - { - writerObject_.reset(); - TestOutputSuite::expectResult(expected); - } - -public: - void - testTrivial() - { - setup("trivial"); - - { - auto& root = makeRoot(); - (void)root; - } - expectResult("{}"); - } - - void - testSimple() - { - setup("simple"); - { - auto& root = makeRoot(); - root["hello"] = "world"; - root["skidoo"] = 23; - root["awake"] = false; - root["temperature"] = 98.6; - } - - expectResult( - "{\"hello\":\"world\"," - "\"skidoo\":23," - "\"awake\":false," - "\"temperature\":98.6}"); - } - - void - testOneSub() - { - setup("oneSub"); - { - auto& root = makeRoot(); - root.setArray("ar"); - } - expectResult("{\"ar\":[]}"); - } - - void - testSubs() - { - setup("subs"); - { - auto& root = makeRoot(); - - { - // Add an array with three entries. - auto array = root.setArray("ar"); - array.append(23); - array.append(false); - array.append(23.5); - } - - { - // Add an object with one entry. - auto obj = root.setObject("obj"); - obj["hello"] = "world"; - } - - { - // Add another object with two entries. - Json::Value value; - value["h"] = "w"; - value["f"] = false; - root["obj2"] = value; - } - } - - // Json::Value has an unstable order... - auto case1 = - "{\"ar\":[23,false,23.5]," - "\"obj\":{\"hello\":\"world\"}," - "\"obj2\":{\"h\":\"w\",\"f\":false}}"; - auto case2 = - "{\"ar\":[23,false,23.5]," - "\"obj\":{\"hello\":\"world\"}," - "\"obj2\":{\"f\":false,\"h\":\"w\"}}"; - writerObject_.reset(); - BEAST_EXPECT(output_ == case1 || output_ == case2); - } - - void - testSubsShort() - { - setup("subsShort"); - - { - auto& root = makeRoot(); - - { - // Add an array with three entries. - auto array = root.setArray("ar"); - array.append(23); - array.append(false); - array.append(23.5); - } - - // Add an object with one entry. - root.setObject("obj")["hello"] = "world"; - - { - // Add another object with two entries. - auto object = root.setObject("obj2"); - object.set("h", "w"); - object.set("f", false); - } - } - expectResult( - "{\"ar\":[23,false,23.5]," - "\"obj\":{\"hello\":\"world\"}," - "\"obj2\":{\"h\":\"w\",\"f\":false}}"); - } - - void - testFailureObject() - { - { - setup("object failure assign"); - auto& root = makeRoot(); - auto obj = root.setObject("o1"); - expectException([&]() { root["fail"] = "complete"; }); - } - { - setup("object failure object"); - auto& root = makeRoot(); - auto obj = root.setObject("o1"); - expectException([&]() { root.setObject("o2"); }); - } - { - setup("object failure Array"); - auto& root = makeRoot(); - auto obj = root.setArray("o1"); - expectException([&]() { root.setArray("o2"); }); - } - } - - void - testFailureArray() - { - { - setup("array failure append"); - auto& root = makeRoot(); - auto array = root.setArray("array"); - auto subarray = array.appendArray(); - auto fail = [&]() { array.append("fail"); }; - expectException(fail); - } - { - setup("array failure appendArray"); - auto& root = makeRoot(); - auto array = root.setArray("array"); - auto subarray = array.appendArray(); - auto fail = [&]() { array.appendArray(); }; - expectException(fail); - } - { - setup("array failure appendObject"); - auto& root = makeRoot(); - auto array = root.setArray("array"); - auto subarray = array.appendArray(); - auto fail = [&]() { array.appendObject(); }; - expectException(fail); - } - } - - void - testKeyFailure() - { - setup("repeating keys"); - auto& root = makeRoot(); - root.set("foo", "bar"); - root.set("baz", 0); - // setting key again throws in !NDEBUG builds - auto set_again = [&]() { root.set("foo", "bar"); }; -#ifdef NDEBUG - set_again(); - pass(); -#else - expectException(set_again); -#endif - } - - void - run() override - { - testTrivial(); - testSimple(); - - testOneSub(); - testSubs(); - testSubsShort(); - - testFailureObject(); - testFailureArray(); - testKeyFailure(); - } -}; - -BEAST_DEFINE_TESTSUITE(JsonObject, json, xrpl); - -} // namespace Json diff --git a/src/test/jtx/impl/utility.cpp b/src/test/jtx/impl/utility.cpp index 81bce576ce..920e715c16 100644 --- a/src/test/jtx/impl/utility.cpp +++ b/src/test/jtx/impl/utility.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -83,7 +82,7 @@ cmdToJSONRPC( // If paramsObj is not empty, put it in a [params] array. if (paramsObj.begin() != paramsObj.end()) { - auto& paramsArray = Json::setArray(jv, jss::params); + auto& paramsArray = jv[jss::params] = Json::arrayValue; paramsArray.append(paramsObj); } if (paramsObj.isMember(jss::jsonrpc)) diff --git a/src/xrpld/app/ledger/LedgerToJson.h b/src/xrpld/app/ledger/LedgerToJson.h index 7ebbfc655e..7b7e267d81 100644 --- a/src/xrpld/app/ledger/LedgerToJson.h +++ b/src/xrpld/app/ledger/LedgerToJson.h @@ -7,7 +7,6 @@ #include #include -#include #include namespace xrpl { @@ -42,10 +41,9 @@ struct LedgerFill std::optional closeTime; }; -/** Given a Ledger and options, fill a Json::Object or Json::Value with a +/** Given a Ledger and options, fill a Json::Value with a description of the ledger. */ - void addJson(Json::Value&, LedgerFill const&); @@ -53,6 +51,10 @@ addJson(Json::Value&, LedgerFill const&); Json::Value getJson(LedgerFill const&); +/** Copy all the keys and values from one object into another. */ +void +copyFrom(Json::Value& to, Json::Value const& from); + } // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/LedgerToJson.cpp b/src/xrpld/app/ledger/detail/LedgerToJson.cpp index 8c9e21acde..b1f6d6b297 100644 --- a/src/xrpld/app/ledger/detail/LedgerToJson.cpp +++ b/src/xrpld/app/ledger/detail/LedgerToJson.cpp @@ -32,10 +32,9 @@ isBinary(LedgerFill const& fill) return fill.options & LedgerFill::binary; } -template void fillJson( - Object& json, + Json::Value& json, bool closed, LedgerHeader const& info, bool bFull, @@ -78,9 +77,8 @@ fillJson( } } -template void -fillJsonBinary(Object& json, bool closed, LedgerHeader const& info) +fillJsonBinary(Json::Value& json, bool closed, LedgerHeader const& info) { if (!closed) json[jss::closed] = false; @@ -207,11 +205,10 @@ fillJsonTx( return txJson; } -template void -fillJsonTx(Object& json, LedgerFill const& fill) +fillJsonTx(Json::Value& json, LedgerFill const& fill) { - auto&& txns = setArray(json, jss::transactions); + auto& txns = json[jss::transactions] = Json::arrayValue; auto bBinary = isBinary(fill); auto bExpanded = isExpanded(fill); @@ -238,12 +235,11 @@ fillJsonTx(Object& json, LedgerFill const& fill) } } -template void -fillJsonState(Object& json, LedgerFill const& fill) +fillJsonState(Json::Value& json, LedgerFill const& fill) { auto& ledger = fill.ledger; - auto&& array = Json::setArray(json, jss::accountState); + auto& array = json[jss::accountState] = Json::arrayValue; auto expanded = isExpanded(fill); auto binary = isBinary(fill); @@ -251,7 +247,7 @@ fillJsonState(Object& json, LedgerFill const& fill) { if (binary) { - auto&& obj = appendObject(array); + auto& obj = array.append(Json::objectValue); obj[jss::hash] = to_string(sle->key()); obj[jss::tx_blob] = serializeHex(*sle); } @@ -262,17 +258,16 @@ fillJsonState(Object& json, LedgerFill const& fill) } } -template void -fillJsonQueue(Object& json, LedgerFill const& fill) +fillJsonQueue(Json::Value& json, LedgerFill const& fill) { - auto&& queueData = Json::setArray(json, jss::queue_data); + auto& queueData = json[jss::queue_data] = Json::arrayValue; auto bBinary = isBinary(fill); auto bExpanded = isExpanded(fill); for (auto const& tx : fill.txQueue) { - auto&& txJson = appendObject(queueData); + auto& txJson = queueData.append(Json::objectValue); txJson[jss::fee_level] = to_string(tx.feeLevel); if (tx.lastValid) txJson[jss::LastLedgerSequence] = *tx.lastValid; @@ -297,9 +292,8 @@ fillJsonQueue(Object& json, LedgerFill const& fill) } } -template void -fillJson(Object& json, LedgerFill const& fill) +fillJson(Json::Value& json, LedgerFill const& fill) { // TODO: what happens if bBinary and bExtracted are both set? // Is there a way to report this back? @@ -327,7 +321,7 @@ fillJson(Object& json, LedgerFill const& fill) void addJson(Json::Value& json, LedgerFill const& fill) { - auto&& object = Json::addObject(json, jss::ledger); + auto& object = json[jss::ledger] = Json::objectValue; fillJson(object, fill); if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty()) @@ -342,4 +336,20 @@ getJson(LedgerFill const& fill) return json; } +void +copyFrom(Json::Value& to, Json::Value const& from) +{ + if (!to) // Short circuit this very common case. + to = from; + else + { + // TODO: figure out if there is a way to remove this clause + // or check that it does/needs to do a deep copy + XRPL_ASSERT(from.isObjectOrNull(), "copyFrom : invalid input type"); + auto const members = from.getMemberNames(); + for (auto const& m : members) + to[m] = from[m]; + } +} + } // namespace xrpl diff --git a/src/xrpld/rpc/Status.h b/src/xrpld/rpc/Status.h index f4ffcae9b2..5d6175336e 100644 --- a/src/xrpld/rpc/Status.h +++ b/src/xrpld/rpc/Status.h @@ -94,9 +94,8 @@ public: /** Apply the Status to a JsonObject */ - template void - inject(Object& object) const + inject(Json::Value& object) const { if (auto ec = toErrorCode()) { diff --git a/src/xrpld/rpc/handlers/GetCounts.h b/src/xrpld/rpc/handlers/GetCounts.h index 0d544a4f11..de2c4f2f96 100644 --- a/src/xrpld/rpc/handlers/GetCounts.h +++ b/src/xrpld/rpc/handlers/GetCounts.h @@ -3,8 +3,6 @@ #include -#include - namespace xrpl { Json::Value diff --git a/src/xrpld/rpc/handlers/LedgerHandler.cpp b/src/xrpld/rpc/handlers/LedgerHandler.cpp index 2929776549..f8e8111aad 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerHandler.cpp @@ -75,6 +75,43 @@ LedgerHandler::check() return Status::OK; } +void +LedgerHandler::writeResult(Json::Value& value) +{ + if (ledger_) + { + copyFrom(value, result_); + addJson(value, {*ledger_, &context_, options_, queueTxs_}); + } + else + { + auto& master = context_.app.getLedgerMaster(); + { + auto& closed = value[jss::closed] = Json::objectValue; + addJson(closed, {*master.getClosedLedger(), &context_, 0}); + } + { + auto& open = value[jss::open] = Json::objectValue; + addJson(open, {*master.getCurrentLedger(), &context_, 0}); + } + } + + Json::Value warnings{Json::arrayValue}; + if (context_.params.isMember(jss::type)) + { + Json::Value& w = warnings.append(Json::objectValue); + w[jss::id] = warnRPC_FIELDS_DEPRECATED; + w[jss::message] = + "Some fields from your request are deprecated. Please check the " + "documentation at " + "https://xrpl.org/docs/references/http-websocket-apis/ " + "and update your request. Field `type` is deprecated."; + } + + if (warnings.size()) + value[jss::warnings] = std::move(warnings); +} + } // namespace RPC std::pair diff --git a/src/xrpld/rpc/handlers/LedgerHandler.h b/src/xrpld/rpc/handlers/LedgerHandler.h index fbf60fb22e..3285118d11 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.h +++ b/src/xrpld/rpc/handlers/LedgerHandler.h @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -37,9 +36,8 @@ public: Status check(); - template void - writeResult(Object&); + writeResult(Json::Value&); static constexpr char name[] = "ledger"; @@ -59,49 +57,6 @@ private: int options_ = 0; }; -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// -// Implementation. - -template -void -LedgerHandler::writeResult(Object& value) -{ - if (ledger_) - { - Json::copyFrom(value, result_); - addJson(value, {*ledger_, &context_, options_, queueTxs_}); - } - else - { - auto& master = context_.app.getLedgerMaster(); - { - auto&& closed = Json::addObject(value, jss::closed); - addJson(closed, {*master.getClosedLedger(), &context_, 0}); - } - { - auto&& open = Json::addObject(value, jss::open); - addJson(open, {*master.getCurrentLedger(), &context_, 0}); - } - } - - Json::Value warnings{Json::arrayValue}; - if (context_.params.isMember(jss::type)) - { - Json::Value& w = warnings.append(Json::objectValue); - w[jss::id] = warnRPC_FIELDS_DEPRECATED; - w[jss::message] = - "Some fields from your request are deprecated. Please check the " - "documentation at " - "https://xrpl.org/docs/references/http-websocket-apis/ " - "and update your request. Field `type` is deprecated."; - } - - if (warnings.size()) - value[jss::warnings] = std::move(warnings); -} - } // namespace RPC } // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Version.h b/src/xrpld/rpc/handlers/Version.h index 8af2fd20bc..b8f9512ef3 100644 --- a/src/xrpld/rpc/handlers/Version.h +++ b/src/xrpld/rpc/handlers/Version.h @@ -20,9 +20,8 @@ public: return Status::OK; } - template void - writeResult(Object& obj) + writeResult(Json::Value& obj) { setVersion(obj, apiVersion_, betaEnabled_); }