mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 06:25:51 +00:00
Better interoperation between Json::Value and JsonObject.
* Generic functions to add entries to both object models. * Add Json::Value into JsonObjects. * Write Json::Value to string incrementally. * Get rid of ripple::RPC::New namespace
This commit is contained in:
committed by
Vinnie Falco
parent
7cfac1a91a
commit
8053598069
@@ -2812,6 +2812,8 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<None Include="..\..\src\ripple\resource\README.md">
|
<None Include="..\..\src\ripple\resource\README.md">
|
||||||
</None>
|
</None>
|
||||||
|
<ClInclude Include="..\..\src\ripple\rpc\Coroutine.h">
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\ErrorCodes.h">
|
<ClInclude Include="..\..\src\ripple\rpc\ErrorCodes.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\handlers\AccountCurrencies.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\handlers\AccountCurrencies.cpp">
|
||||||
@@ -3008,6 +3010,12 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\Context.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\Context.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Coroutine.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Coroutine.test.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\DoPrint.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\DoPrint.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\ErrorCodes.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\ErrorCodes.cpp">
|
||||||
@@ -3028,7 +3036,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonObject.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonObject.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonObject_test.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonObject.test.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter.cpp">
|
||||||
@@ -3036,7 +3044,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonWriter.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonWriter.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter_test.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter.test.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\LegacyPathFind.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\LegacyPathFind.cpp">
|
||||||
@@ -3063,7 +3071,7 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Status_test.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.test.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\TestOutputSuite.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\TestOutputSuite.h">
|
||||||
@@ -3075,10 +3083,15 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Yield.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\WriteJson.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Yield_test.cpp">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\WriteJson.h">
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\WriteJson.test.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Yield.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\InternalHandler.h">
|
<ClInclude Include="..\..\src\ripple\rpc\InternalHandler.h">
|
||||||
|
|||||||
@@ -3906,6 +3906,9 @@
|
|||||||
<None Include="..\..\src\ripple\resource\README.md">
|
<None Include="..\..\src\ripple\resource\README.md">
|
||||||
<Filter>ripple\resource</Filter>
|
<Filter>ripple\resource</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<ClInclude Include="..\..\src\ripple\rpc\Coroutine.h">
|
||||||
|
<Filter>ripple\rpc</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\ErrorCodes.h">
|
<ClInclude Include="..\..\src\ripple\rpc\ErrorCodes.h">
|
||||||
<Filter>ripple\rpc</Filter>
|
<Filter>ripple\rpc</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -4107,6 +4110,12 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\Context.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\Context.h">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Coroutine.cpp">
|
||||||
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Coroutine.test.cpp">
|
||||||
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\DoPrint.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\DoPrint.h">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -4131,7 +4140,7 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonObject.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonObject.h">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonObject_test.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonObject.test.cpp">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter.cpp">
|
||||||
@@ -4140,7 +4149,7 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonWriter.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\JsonWriter.h">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter_test.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\JsonWriter.test.cpp">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\LegacyPathFind.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\LegacyPathFind.cpp">
|
||||||
@@ -4170,7 +4179,7 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.cpp">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Status_test.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.test.cpp">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\TestOutputSuite.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\TestOutputSuite.h">
|
||||||
@@ -4185,10 +4194,16 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Yield.cpp">
|
<ClCompile Include="..\..\src\ripple\rpc\impl\WriteJson.cpp">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\rpc\impl\Yield_test.cpp">
|
<ClInclude Include="..\..\src\ripple\rpc\impl\WriteJson.h">
|
||||||
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\WriteJson.test.cpp">
|
||||||
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\rpc\impl\Yield.cpp">
|
||||||
<Filter>ripple\rpc\impl</Filter>
|
<Filter>ripple\rpc\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\rpc\InternalHandler.h">
|
<ClInclude Include="..\..\src\ripple\rpc\InternalHandler.h">
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
/** Status represents the results of an operation that might fail.
|
/** Status represents the results of an operation that might fail.
|
||||||
|
|
||||||
@@ -114,7 +113,6 @@ private:
|
|||||||
Strings messages_;
|
Strings messages_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace New
|
|
||||||
} // namespace RPC
|
} // namespace RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,9 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <ripple/rpc/impl/JsonObject.h>
|
#include <ripple/rpc/impl/JsonObject.h>
|
||||||
#include <ripple/rpc/impl/JsonWriter.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
Collection::Collection (Collection* parent, Writer* writer)
|
Collection::Collection (Collection* parent, Writer* writer)
|
||||||
: parent_ (parent), writer_ (writer), enabled_ (true)
|
: parent_ (parent), writer_ (writer), enabled_ (true)
|
||||||
@@ -71,31 +69,9 @@ void Collection::checkWritable (std::string const& label)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename Scalar>
|
|
||||||
Array& Array::append (Scalar value)
|
|
||||||
{
|
|
||||||
checkWritable ("append");
|
|
||||||
if (writer_)
|
|
||||||
writer_->append (value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Object::Root::Root (Writer& w) : Object (nullptr, &w)
|
Object::Root::Root (Writer& w) : Object (nullptr, &w)
|
||||||
{
|
{
|
||||||
writer_->startRoot (Writer::object); // writer_ can't be null.
|
writer_->startRoot (Writer::object);
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template <typename Scalar>
|
|
||||||
Object& Object::set (std::string const& key, Scalar value)
|
|
||||||
{
|
|
||||||
checkWritable ("set");
|
|
||||||
if (writer_)
|
|
||||||
writer_->set (key, value);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object Object::makeObject (std::string const& key)
|
Object Object::makeObject (std::string const& key)
|
||||||
@@ -113,6 +89,8 @@ Array Object::makeArray (std::string const& key) {
|
|||||||
return Array (this, writer_);
|
return Array (this, writer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
Object Array::makeObject ()
|
Object Array::makeObject ()
|
||||||
{
|
{
|
||||||
checkWritable ("Array::makeObject");
|
checkWritable ("Array::makeObject");
|
||||||
@@ -139,9 +117,44 @@ Object::Proxy::Proxy (Object& object, std::string const& key)
|
|||||||
|
|
||||||
Object::Proxy Object::operator[] (std::string const& key)
|
Object::Proxy Object::operator[] (std::string const& key)
|
||||||
{
|
{
|
||||||
return {*this, key};
|
return Proxy (*this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Proxy Object::operator[] (Json::StaticString const& key)
|
||||||
|
{
|
||||||
|
return Proxy (*this, std::string (key));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Object>
|
||||||
|
void doCopyFrom (Object& to, Json::Value const& from)
|
||||||
|
{
|
||||||
|
auto members = from.getMemberNames();
|
||||||
|
for (auto& m: members)
|
||||||
|
to[m] = from[m];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFrom (Json::Value& to, Json::Value const& from)
|
||||||
|
{
|
||||||
|
if (to.empty()) // 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // New
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#ifndef RIPPLED_RIPPLE_RPC_IMPL_JSONCOLLECTIONS_H
|
#ifndef RIPPLED_RIPPLE_RPC_IMPL_JSONCOLLECTIONS_H
|
||||||
#define RIPPLED_RIPPLE_RPC_IMPL_JSONCOLLECTIONS_H
|
#define RIPPLED_RIPPLE_RPC_IMPL_JSONCOLLECTIONS_H
|
||||||
|
|
||||||
|
#include <ripple/rpc/impl/JsonWriter.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
class Writer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Collection is a base class for Array and Object, classes which provide the
|
Collection is a base class for Array and Object, classes which provide the
|
||||||
@@ -32,8 +31,8 @@ class Writer;
|
|||||||
heap memory and only a very small amount of stack.
|
heap memory and only a very small amount of stack.
|
||||||
|
|
||||||
From http://json.org, JSON has two types of collection: array, and object.
|
From http://json.org, JSON has two types of collection: array, and object.
|
||||||
Everything else is a *scalar* - a number, a string, a boolean or the special
|
Everything else is a *scalar* - a number, a string, a boolean, the special
|
||||||
value null.
|
value null, or a legacy Json::Value.
|
||||||
|
|
||||||
Collections must write JSON "as-it-goes" in order to get the strong
|
Collections must write JSON "as-it-goes" in order to get the strong
|
||||||
performance guarantees. This puts restrictions upon API users:
|
performance guarantees. This puts restrictions upon API users:
|
||||||
@@ -182,7 +181,8 @@ public:
|
|||||||
|
|
||||||
/** Set a scalar value in the Object for a key.
|
/** Set a scalar value in the Object for a key.
|
||||||
|
|
||||||
A JSON scalar is a single value - a number, string, boolean or null.
|
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
|
`set()` throws an exception if this object is disabled (which means that
|
||||||
one of its children is enabled).
|
one of its children is enabled).
|
||||||
@@ -193,11 +193,13 @@ public:
|
|||||||
An operator[] is provided to allow writing `object["key"] = scalar;`.
|
An operator[] is provided to allow writing `object["key"] = scalar;`.
|
||||||
*/
|
*/
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
Object& set (std::string const& key, Scalar);
|
Object& set (std::string const& key, Scalar const&);
|
||||||
|
|
||||||
// Detail class and method used to implement operator[].
|
// Detail class and method used to implement operator[].
|
||||||
class Proxy;
|
class Proxy;
|
||||||
|
|
||||||
Proxy operator[] (std::string const& key);
|
Proxy operator[] (std::string const& key);
|
||||||
|
Proxy operator[] (Json::StaticString const& key);
|
||||||
|
|
||||||
/** Make a new Object at a key and return it.
|
/** Make a new Object at a key and return it.
|
||||||
|
|
||||||
@@ -218,8 +220,6 @@ protected:
|
|||||||
Object (Collection* parent, Writer* w) : Collection (parent, w) {}
|
Object (Collection* parent, Writer* w) : Collection (parent, w) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class Object::Root : public Object
|
class Object::Root : public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -239,7 +239,7 @@ public:
|
|||||||
its sub-collections is enabled).
|
its sub-collections is enabled).
|
||||||
*/
|
*/
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
Array& append (Scalar);
|
Array& append (const Scalar&);
|
||||||
|
|
||||||
/** Append a new Object and return it.
|
/** Append a new Object and return it.
|
||||||
|
|
||||||
@@ -262,12 +262,71 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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& addArray (Json::Value&, Json::StaticString const& key);
|
||||||
|
|
||||||
|
/** Add a new subarray at a named key in a Json object. */
|
||||||
|
Array addArray (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);
|
||||||
|
|
||||||
|
/** 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<Writer> (output)),
|
||||||
|
object_ (std::make_unique<Object::Root> (*writer_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
WriterObject (WriterObject&& other)
|
||||||
|
: writer_ (std::move (other.writer_)),
|
||||||
|
object_ (std::move (other.object_))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Object* operator->()
|
||||||
|
{
|
||||||
|
return object_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Object& operator*()
|
||||||
|
{
|
||||||
|
return *object_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr <Writer> writer_;
|
||||||
|
std::unique_ptr<Object::Root> object_;
|
||||||
|
};
|
||||||
|
|
||||||
|
WriterObject stringWriterObject (std::string&);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Implementation details.
|
||||||
|
|
||||||
// Detail class for Object::operator[].
|
// Detail class for Object::operator[].
|
||||||
class Object::Proxy
|
class Object::Proxy
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Object& object_;
|
Object& object_;
|
||||||
std::string const& key_;
|
std::string const key_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Proxy (Object& object, std::string const& key);
|
Proxy (Object& object, std::string const& key);
|
||||||
@@ -280,7 +339,50 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // New
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <typename Scalar>
|
||||||
|
Array& Array::append (Scalar const& value)
|
||||||
|
{
|
||||||
|
checkWritable ("append");
|
||||||
|
if (writer_)
|
||||||
|
writer_->append (value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Scalar>
|
||||||
|
Object& Object::set (std::string const& key, Scalar const& value)
|
||||||
|
{
|
||||||
|
checkWritable ("set");
|
||||||
|
if (writer_)
|
||||||
|
writer_->set (key, value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
Json::Value& addArray (Json::Value& json, Json::StaticString const& key)
|
||||||
|
{
|
||||||
|
return (json[key] = Json::arrayValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
Array addArray (Object& json, Json::StaticString const& key)
|
||||||
|
{
|
||||||
|
return json.makeArray (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.makeObject (std::string (key));
|
||||||
|
}
|
||||||
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|
||||||
|
|||||||
@@ -23,17 +23,37 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
class JsonObject_test : public TestOutputSuite
|
class JsonObject_test : public TestOutputSuite
|
||||||
{
|
{
|
||||||
|
void setup (std::string const& testName)
|
||||||
|
{
|
||||||
|
testcase (testName);
|
||||||
|
output_.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<WriterObject> writerObject_;
|
||||||
|
|
||||||
|
Object& makeRoot()
|
||||||
|
{
|
||||||
|
writerObject_ = std::make_unique<WriterObject> (
|
||||||
|
stringWriterObject (output_));
|
||||||
|
return **writerObject_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectResult (std::string const& expected)
|
||||||
|
{
|
||||||
|
writerObject_.reset();
|
||||||
|
TestOutputSuite::expectResult (expected);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void testTrivial ()
|
void testTrivial ()
|
||||||
{
|
{
|
||||||
setup ("trivial");
|
setup ("trivial");
|
||||||
|
|
||||||
{
|
{
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
(void) root;
|
(void) root;
|
||||||
}
|
}
|
||||||
expectResult ("{}");
|
expectResult ("{}");
|
||||||
@@ -43,7 +63,7 @@ public:
|
|||||||
{
|
{
|
||||||
setup ("simple");
|
setup ("simple");
|
||||||
{
|
{
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
root["hello"] = "world";
|
root["hello"] = "world";
|
||||||
root["skidoo"] = 23;
|
root["skidoo"] = 23;
|
||||||
root["awake"] = false;
|
root["awake"] = false;
|
||||||
@@ -60,7 +80,7 @@ public:
|
|||||||
void testSimpleShort ()
|
void testSimpleShort ()
|
||||||
{
|
{
|
||||||
setup ("simpleShort");
|
setup ("simpleShort");
|
||||||
Object::Root (*writer_)
|
makeRoot()
|
||||||
.set ("hello", "world")
|
.set ("hello", "world")
|
||||||
.set ("skidoo", 23)
|
.set ("skidoo", 23)
|
||||||
.set ("awake", false)
|
.set ("awake", false)
|
||||||
@@ -77,7 +97,7 @@ public:
|
|||||||
{
|
{
|
||||||
setup ("oneSub");
|
setup ("oneSub");
|
||||||
{
|
{
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
root.makeArray ("ar");
|
root.makeArray ("ar");
|
||||||
}
|
}
|
||||||
expectResult ("{\"ar\":[]}");
|
expectResult ("{\"ar\":[]}");
|
||||||
@@ -87,7 +107,7 @@ public:
|
|||||||
{
|
{
|
||||||
setup ("subs");
|
setup ("subs");
|
||||||
{
|
{
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
|
|
||||||
{
|
{
|
||||||
// Add an array with three entries.
|
// Add an array with three entries.
|
||||||
@@ -122,7 +142,7 @@ public:
|
|||||||
setup ("subsShort");
|
setup ("subsShort");
|
||||||
|
|
||||||
{
|
{
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
|
|
||||||
// Add an array with three entries.
|
// Add an array with three entries.
|
||||||
root.makeArray ("ar")
|
root.makeArray ("ar")
|
||||||
@@ -163,19 +183,19 @@ public:
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
setup ("object failure assign");
|
setup ("object failure assign");
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
auto obj = root.makeObject ("o1");
|
auto obj = root.makeObject ("o1");
|
||||||
expectException ([&]() { root["fail"] = "complete"; });
|
expectException ([&]() { root["fail"] = "complete"; });
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
setup ("object failure object");
|
setup ("object failure object");
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
auto obj = root.makeObject ("o1");
|
auto obj = root.makeObject ("o1");
|
||||||
expectException ([&] () { root.makeObject ("o2"); });
|
expectException ([&] () { root.makeObject ("o2"); });
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
setup ("object failure Array");
|
setup ("object failure Array");
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
auto obj = root.makeArray ("o1");
|
auto obj = root.makeArray ("o1");
|
||||||
expectException ([&] () { root.makeArray ("o2"); });
|
expectException ([&] () { root.makeArray ("o2"); });
|
||||||
}
|
}
|
||||||
@@ -185,7 +205,7 @@ public:
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
setup ("array failure append");
|
setup ("array failure append");
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
auto array = root.makeArray ("array");
|
auto array = root.makeArray ("array");
|
||||||
auto subarray = array.makeArray ();
|
auto subarray = array.makeArray ();
|
||||||
auto fail = [&]() { array.append ("fail"); };
|
auto fail = [&]() { array.append ("fail"); };
|
||||||
@@ -193,7 +213,7 @@ public:
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
setup ("array failure makeArray");
|
setup ("array failure makeArray");
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
auto array = root.makeArray ("array");
|
auto array = root.makeArray ("array");
|
||||||
auto subarray = array.makeArray ();
|
auto subarray = array.makeArray ();
|
||||||
auto fail = [&]() { array.makeArray (); };
|
auto fail = [&]() { array.makeArray (); };
|
||||||
@@ -201,7 +221,7 @@ public:
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
setup ("array failure makeObject");
|
setup ("array failure makeObject");
|
||||||
Object::Root root (*writer_);
|
auto& root = makeRoot();
|
||||||
auto array = root.makeArray ("array");
|
auto array = root.makeArray ("array");
|
||||||
auto subarray = array.makeArray ();
|
auto subarray = array.makeArray ();
|
||||||
auto fail = [&]() { array.makeObject (); };
|
auto fail = [&]() { array.makeObject (); };
|
||||||
@@ -213,7 +233,7 @@ public:
|
|||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
setup ("repeating keys");
|
setup ("repeating keys");
|
||||||
Object::Root root(*writer_);
|
auto& root = makeRoot();
|
||||||
root.set ("foo", "bar")
|
root.set ("foo", "bar")
|
||||||
.set ("baz", 0);
|
.set ("baz", 0);
|
||||||
auto fail = [&]() { root.set ("foo", "bar"); };
|
auto fail = [&]() { root.set ("foo", "bar"); };
|
||||||
@@ -223,6 +243,7 @@ public:
|
|||||||
|
|
||||||
void run () override
|
void run () override
|
||||||
{
|
{
|
||||||
|
testTrivial ();
|
||||||
testSimple ();
|
testSimple ();
|
||||||
testSimpleShort ();
|
testSimpleShort ();
|
||||||
|
|
||||||
@@ -238,6 +259,5 @@ public:
|
|||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(JsonObject, ripple_basics, ripple);
|
BEAST_DEFINE_TESTSUITE(JsonObject, ripple_basics, ripple);
|
||||||
|
|
||||||
} // New
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <ripple/rpc/impl/JsonWriter.h>
|
#include <ripple/rpc/impl/JsonWriter.h>
|
||||||
|
#include <ripple/rpc/impl/WriteJson.h>
|
||||||
#include <beast/unit_test/suite.h>
|
#include <beast/unit_test/suite.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ std::map <char, const char*> jsonSpecialCharacterEscape = {
|
|||||||
{'\t', "\\t"}
|
{'\t', "\\t"}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int const jsonEscapeLength = 2;
|
static size_t const jsonEscapeLength = 2;
|
||||||
|
|
||||||
// All other JSON punctuation.
|
// All other JSON punctuation.
|
||||||
const char closeBrace = '}';
|
const char closeBrace = '}';
|
||||||
@@ -50,12 +50,24 @@ const char quote = '"';
|
|||||||
|
|
||||||
const std::string none;
|
const std::string none;
|
||||||
|
|
||||||
|
static auto const integralFloatsBecomeInts = false;
|
||||||
|
|
||||||
size_t lengthWithoutTrailingZeros (std::string const& s)
|
size_t lengthWithoutTrailingZeros (std::string const& s)
|
||||||
{
|
{
|
||||||
if (s.find ('.') == std::string::npos)
|
auto dotPos = s.find ('.');
|
||||||
|
if (dotPos == std::string::npos)
|
||||||
return s.size();
|
return s.size();
|
||||||
|
|
||||||
return s.find_last_not_of ('0') + 1;
|
auto lastNonZero = s.find_last_not_of ('0');
|
||||||
|
auto hasDecimals = dotPos != lastNonZero;
|
||||||
|
|
||||||
|
if (hasDecimals)
|
||||||
|
return lastNonZero + 1;
|
||||||
|
|
||||||
|
if (integralFloatsBecomeInts || lastNonZero + 2 > s.size())
|
||||||
|
return lastNonZero;
|
||||||
|
|
||||||
|
return lastNonZero + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -63,7 +75,8 @@ size_t lengthWithoutTrailingZeros (std::string const& s)
|
|||||||
class Writer::Impl
|
class Writer::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Impl (Output output) : output_(output) {}
|
Impl (Output const& output) : output_(output) {}
|
||||||
|
~Impl() = default;
|
||||||
|
|
||||||
Impl(Impl&&) = delete;
|
Impl(Impl&&) = delete;
|
||||||
Impl& operator=(Impl&&) = delete;
|
Impl& operator=(Impl&&) = delete;
|
||||||
@@ -168,6 +181,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Output const& getOutput() const { return output_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// JSON collections are either arrrays, or objects.
|
// JSON collections are either arrrays, or objects.
|
||||||
struct Collection
|
struct Collection
|
||||||
@@ -193,12 +208,14 @@ private:
|
|||||||
bool isStarted_ = false;
|
bool isStarted_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Writer::Writer (Output output) : impl_(std::make_unique <Impl> (output))
|
Writer::Writer (Output const &output)
|
||||||
|
: impl_(std::make_unique <Impl> (output))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Writer::~Writer()
|
Writer::~Writer()
|
||||||
{
|
{
|
||||||
|
if (impl_)
|
||||||
impl_->finishAll ();
|
impl_->finishAll ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +240,12 @@ void Writer::output (std::string const& s)
|
|||||||
impl_->stringOutput (s);
|
impl_->stringOutput (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Writer::output (Json::Value const& value)
|
||||||
|
{
|
||||||
|
impl_->markStarted();
|
||||||
|
writeJson (value, impl_->getOutput());
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void Writer::output (float f)
|
void Writer::output (float f)
|
||||||
{
|
{
|
||||||
@@ -243,37 +266,32 @@ void Writer::output (std::nullptr_t)
|
|||||||
impl_->output ("null");
|
impl_->output ("null");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
void Writer::implOutput (std::string const& s)
|
||||||
void Writer::output (Type t)
|
|
||||||
{
|
{
|
||||||
impl_->output (to_string (t));
|
impl_->output (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::finishAll ()
|
void Writer::finishAll ()
|
||||||
{
|
{
|
||||||
|
if (impl_)
|
||||||
impl_->finishAll ();
|
impl_->finishAll ();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
void Writer::rawAppend()
|
||||||
void Writer::append (Type t)
|
|
||||||
{
|
{
|
||||||
impl_->nextCollectionEntry (array, "append");
|
impl_->nextCollectionEntry (array, "append");
|
||||||
output (t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
void Writer::rawSet (std::string const& tag)
|
||||||
void Writer::set (std::string const& tag, Type t)
|
|
||||||
{
|
{
|
||||||
check (!tag.empty(), "Tag can't be empty");
|
check (!tag.empty(), "Tag can't be empty");
|
||||||
|
|
||||||
impl_->nextCollectionEntry (object, "set");
|
impl_->nextCollectionEntry (object, "set");
|
||||||
impl_->writeObjectTag (tag);
|
impl_->writeObjectTag (tag);
|
||||||
output (t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Writer::startRoot (CollectionType type)
|
void Writer::startRoot (CollectionType type)
|
||||||
{
|
{
|
||||||
check (impl_->empty(), "stack_ not empty() in start");
|
|
||||||
impl_->start (type);
|
impl_->start (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,9 +310,9 @@ void Writer::startSet (CollectionType type, std::string const& key)
|
|||||||
|
|
||||||
void Writer::finish ()
|
void Writer::finish ()
|
||||||
{
|
{
|
||||||
|
if (impl_)
|
||||||
impl_->finish ();
|
impl_->finish ();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // New
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
#include <ripple/basics/ToString.h>
|
#include <ripple/basics/ToString.h>
|
||||||
#include <ripple/rpc/Output.h>
|
#include <ripple/rpc/Output.h>
|
||||||
|
#include <ripple/rpc/ErrorCodes.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writer implements an O(1)-space, O(1)-granular output JSON writer.
|
* Writer implements an O(1)-space, O(1)-granular output JSON writer.
|
||||||
@@ -127,13 +127,13 @@ class Writer
|
|||||||
public:
|
public:
|
||||||
enum CollectionType {array, object};
|
enum CollectionType {array, object};
|
||||||
|
|
||||||
explicit Writer (Output output);
|
explicit Writer (Output const& output);
|
||||||
Writer(Writer&&);
|
Writer(Writer&&);
|
||||||
Writer& operator=(Writer&&);
|
Writer& operator=(Writer&&);
|
||||||
|
|
||||||
~Writer();
|
~Writer();
|
||||||
|
|
||||||
/** Start a new collection at the root level. May only be called once. */
|
/** Start a new collection at the root level. */
|
||||||
void startRoot (CollectionType);
|
void startRoot (CollectionType);
|
||||||
|
|
||||||
/** Start a new collection inside an array. */
|
/** Start a new collection inside an array. */
|
||||||
@@ -152,10 +152,18 @@ public:
|
|||||||
/** Append a value to an array.
|
/** Append a value to an array.
|
||||||
*
|
*
|
||||||
* Scalar must be a scalar - that is, a number, boolean, string, string
|
* Scalar must be a scalar - that is, a number, boolean, string, string
|
||||||
* literal, or nullptr.
|
* literal, nullptr or Json::Value
|
||||||
*/
|
*/
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
void append (Scalar);
|
void append (Scalar t)
|
||||||
|
{
|
||||||
|
rawAppend();
|
||||||
|
output (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a comma before this next item if not the first item in an array.
|
||||||
|
Useful if you are writing the actual array yourself. */
|
||||||
|
void rawAppend();
|
||||||
|
|
||||||
/** Add a key, value assignment to an object.
|
/** Add a key, value assignment to an object.
|
||||||
*
|
*
|
||||||
@@ -168,8 +176,16 @@ public:
|
|||||||
* If CHECK_JSON_WRITER is defined, this function throws an exception if if
|
* If CHECK_JSON_WRITER is defined, this function throws an exception if if
|
||||||
* the tag you use has already been used in this object.
|
* the tag you use has already been used in this object.
|
||||||
*/
|
*/
|
||||||
template <typename Scalar>
|
template <typename Type>
|
||||||
void set (std::string const& key, Scalar value);
|
void set (std::string const& tag, Type t)
|
||||||
|
{
|
||||||
|
rawSet (tag);
|
||||||
|
output (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emit just "tag": as part of an object. Useful if you are writing the
|
||||||
|
actual value data yourself. */
|
||||||
|
void rawSet (std::string const& key);
|
||||||
|
|
||||||
// You won't need to call anything below here until you are writing single
|
// You won't need to call anything below here until you are writing single
|
||||||
// items (numbers, strings, bools, null) to a JSON stream.
|
// items (numbers, strings, bools, null) to a JSON stream.
|
||||||
@@ -180,13 +196,32 @@ public:
|
|||||||
/*** Output a literal constant or C string. */
|
/*** Output a literal constant or C string. */
|
||||||
void output (char const*);
|
void output (char const*);
|
||||||
|
|
||||||
|
/*** Output a literal constant or C string. */
|
||||||
|
void output (Json::Value const&);
|
||||||
|
|
||||||
/** Output numbers, booleans, or nullptr. */
|
/** Output numbers, booleans, or nullptr. */
|
||||||
template <typename Scalar>
|
template <typename Type>
|
||||||
void output (Scalar t);
|
void output (Type t)
|
||||||
|
{
|
||||||
|
implOutput (to_string (t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Output an error code. */
|
||||||
|
void output (error_code_i t)
|
||||||
|
{
|
||||||
|
output (int(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void output (Json::StaticString const& t)
|
||||||
|
{
|
||||||
|
output (t.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Impl;
|
||||||
std::unique_ptr <Impl> impl_;
|
std::unique_ptr <Impl> impl_;
|
||||||
|
|
||||||
|
void implOutput (std::string const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonException : public std::exception
|
class JsonException : public std::exception
|
||||||
@@ -208,7 +243,6 @@ inline void check (bool condition, std::string const& message)
|
|||||||
throw JsonException (message);
|
throw JsonException (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // New
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/json/json_writer.h>
|
||||||
|
|
||||||
#include <ripple/rpc/impl/JsonWriter.h>
|
#include <ripple/rpc/impl/JsonWriter.h>
|
||||||
#include <ripple/rpc/impl/TestOutputSuite.h>
|
#include <ripple/rpc/impl/TestOutputSuite.h>
|
||||||
#include <beast/unit_test/suite.h>
|
#include <beast/unit_test/suite.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
class JsonWriter_test : public TestOutputSuite
|
class JsonWriter_test : public TestOutputSuite
|
||||||
{
|
{
|
||||||
@@ -32,6 +33,13 @@ public:
|
|||||||
{
|
{
|
||||||
setup ("trivial");
|
setup ("trivial");
|
||||||
expect (output_.empty ());
|
expect (output_.empty ());
|
||||||
|
expectResult("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testNearTrivial ()
|
||||||
|
{
|
||||||
|
setup ("near trivial");
|
||||||
|
expect (output_.empty ());
|
||||||
writer_->output (0);
|
writer_->output (0);
|
||||||
expectResult("0");
|
expectResult("0");
|
||||||
}
|
}
|
||||||
@@ -50,6 +58,10 @@ public:
|
|||||||
writer_->output (23);
|
writer_->output (23);
|
||||||
expectResult ("23");
|
expectResult ("23");
|
||||||
|
|
||||||
|
setup ("23.0");
|
||||||
|
writer_->output (23.0);
|
||||||
|
expectResult ("23.0");
|
||||||
|
|
||||||
setup ("23.5");
|
setup ("23.5");
|
||||||
writer_->output (23.5);
|
writer_->output (23.5);
|
||||||
expectResult ("23.5");
|
expectResult ("23.5");
|
||||||
@@ -161,9 +173,22 @@ public:
|
|||||||
"\"subarray\":[23.5]}]]}");
|
"\"subarray\":[23.5]}]]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testJson ()
|
||||||
|
{
|
||||||
|
setup ("object");
|
||||||
|
Json::Value value (Json::objectValue);
|
||||||
|
value["foo"] = 23;
|
||||||
|
writer_->startRoot (Writer::object);
|
||||||
|
writer_->set ("hello", value);
|
||||||
|
writer_->finish ();
|
||||||
|
|
||||||
|
expectResult ("{\"hello\":{\"foo\":23}}");
|
||||||
|
}
|
||||||
|
|
||||||
void run () override
|
void run () override
|
||||||
{
|
{
|
||||||
testTrivial ();
|
testTrivial ();
|
||||||
|
testNearTrivial ();
|
||||||
testPrimitives ();
|
testPrimitives ();
|
||||||
testEmpty ();
|
testEmpty ();
|
||||||
testEscaping ();
|
testEscaping ();
|
||||||
@@ -172,11 +197,11 @@ public:
|
|||||||
testEmbeddedArraySimple ();
|
testEmbeddedArraySimple ();
|
||||||
testObject ();
|
testObject ();
|
||||||
testComplexObject ();
|
testComplexObject ();
|
||||||
|
testJson();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(JsonWriter, ripple_basics, ripple);
|
BEAST_DEFINE_TESTSUITE(JsonWriter, ripple_basics, ripple);
|
||||||
|
|
||||||
} // New
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
std::string Status::codeString () const
|
std::string Status::codeString () const
|
||||||
{
|
{
|
||||||
@@ -72,6 +71,5 @@ void Status::fillJson (Json::Value& value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace New
|
|
||||||
} // namespace RPC
|
} // namespace RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
class codeString_test : public beast::unit_test::suite
|
class codeString_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
@@ -209,6 +208,5 @@ public:
|
|||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE (fillJson, Status, RPC);
|
BEAST_DEFINE_TESTSUITE (fillJson, Status, RPC);
|
||||||
|
|
||||||
} // namespace New
|
|
||||||
} // namespace RPC
|
} // namespace RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
@@ -26,13 +26,11 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace RPC {
|
namespace RPC {
|
||||||
namespace New {
|
|
||||||
|
|
||||||
class TestOutputSuite : public beast::unit_test::suite
|
class TestOutputSuite : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::string output_;
|
std::string output_;
|
||||||
|
|
||||||
std::unique_ptr <Writer> writer_;
|
std::unique_ptr <Writer> writer_;
|
||||||
|
|
||||||
void setup (std::string const& testName)
|
void setup (std::string const& testName)
|
||||||
@@ -46,6 +44,7 @@ protected:
|
|||||||
void expectResult (std::string const& expected)
|
void expectResult (std::string const& expected)
|
||||||
{
|
{
|
||||||
writer_.reset ();
|
writer_.reset ();
|
||||||
|
|
||||||
expectEquals (output_, expected);
|
expectEquals (output_, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +57,6 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // New
|
|
||||||
} // RPC
|
} // RPC
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|
||||||
|
|||||||
112
src/ripple/rpc/impl/WriteJson.cpp
Normal file
112
src/ripple/rpc/impl/WriteJson.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/rpc/impl/WriteJson.h>
|
||||||
|
#include <ripple/rpc/impl/JsonWriter.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace RPC {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void writeJson (Json::Value const& value, Writer& writer)
|
||||||
|
{
|
||||||
|
switch (value.type())
|
||||||
|
{
|
||||||
|
case Json::nullValue:
|
||||||
|
{
|
||||||
|
writer.output (nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::intValue:
|
||||||
|
{
|
||||||
|
writer.output (value.asInt());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::uintValue:
|
||||||
|
{
|
||||||
|
writer.output (value.asUInt());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::realValue:
|
||||||
|
{
|
||||||
|
writer.output (value.asDouble());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::stringValue:
|
||||||
|
{
|
||||||
|
writer.output (value.asString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::booleanValue:
|
||||||
|
{
|
||||||
|
writer.output (value.asBool());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::arrayValue:
|
||||||
|
{
|
||||||
|
writer.startRoot (Writer::array);
|
||||||
|
for (auto const& i: value)
|
||||||
|
{
|
||||||
|
writer.rawAppend();
|
||||||
|
writeJson (i, writer);
|
||||||
|
}
|
||||||
|
writer.finish();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Json::objectValue:
|
||||||
|
{
|
||||||
|
writer.startRoot (Writer::object);
|
||||||
|
auto members = value.getMemberNames ();
|
||||||
|
for (auto const& tag: members)
|
||||||
|
{
|
||||||
|
writer.rawSet (tag);
|
||||||
|
writeJson (value[tag], writer);
|
||||||
|
}
|
||||||
|
writer.finish();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void writeJson (Json::Value const& value, Output const& out)
|
||||||
|
{
|
||||||
|
Writer writer (out);
|
||||||
|
writeJson (value, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string jsonAsString (Json::Value const& value)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
Writer writer (stringOutput (s));
|
||||||
|
writeJson (value, writer);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // RPC
|
||||||
|
} // ripple
|
||||||
43
src/ripple/rpc/impl/WriteJson.h
Normal file
43
src/ripple/rpc/impl/WriteJson.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLED_RIPPLE_RPC_IMPL_WRITELEGACYJSON_H
|
||||||
|
#define RIPPLED_RIPPLE_RPC_IMPL_WRITELEGACYJSON_H
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace RPC {
|
||||||
|
|
||||||
|
/** Writes a minimal representation of a Json value to an Output in O(n) time.
|
||||||
|
|
||||||
|
Data is streamed right to the output, so only a marginal amount of memory is
|
||||||
|
used. This can be very important for a very large Json::Value.
|
||||||
|
*/
|
||||||
|
void writeJson (Json::Value const&, Output const&);
|
||||||
|
|
||||||
|
/** Return the minimal string representation of a Json::Value in O(n) time.
|
||||||
|
|
||||||
|
This requires a memory allocation for the full size of the output.
|
||||||
|
If possible, use write().
|
||||||
|
*/
|
||||||
|
std::string jsonAsString (Json::Value const&);
|
||||||
|
|
||||||
|
} // RPC
|
||||||
|
} // ripple
|
||||||
|
|
||||||
|
#endif
|
||||||
73
src/ripple/rpc/impl/WriteJson.test.cpp
Normal file
73
src/ripple/rpc/impl/WriteJson.test.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/rpc/impl/WriteJson.h>
|
||||||
|
#include <ripple/rpc/impl/TestOutputSuite.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace RPC {
|
||||||
|
|
||||||
|
struct WriteJson_test : TestOutputSuite
|
||||||
|
{
|
||||||
|
void runTest (std::string const& name, std::string const& valueDesc)
|
||||||
|
{
|
||||||
|
setup (name);
|
||||||
|
Json::Value value;
|
||||||
|
expect (Json::Reader().parse (valueDesc, value));
|
||||||
|
auto out = stringOutput (output_);
|
||||||
|
writeJson (value, out);
|
||||||
|
|
||||||
|
// Compare with the original version.
|
||||||
|
auto expected = Json::FastWriter().write (value);
|
||||||
|
expected.resize (expected.size() - 1);
|
||||||
|
// For some reason, the FastWriter puts a carriage return on the end of
|
||||||
|
// every piece of Json it outputs.
|
||||||
|
|
||||||
|
expectResult (expected);
|
||||||
|
expectResult (valueDesc);
|
||||||
|
expectResult (jsonAsString (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void runTest (std::string const& name)
|
||||||
|
{
|
||||||
|
runTest (name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run () override
|
||||||
|
{
|
||||||
|
runTest ("null");
|
||||||
|
runTest ("true");
|
||||||
|
runTest ("0");
|
||||||
|
runTest ("23.5");
|
||||||
|
runTest ("string", "\"a string\"");
|
||||||
|
runTest ("empty dict", "{}");
|
||||||
|
runTest ("empty array", "[]");
|
||||||
|
runTest ("array", "[23,4.25,true,null,\"string\"]");
|
||||||
|
runTest ("dict", "{\"hello\":\"world\"}");
|
||||||
|
runTest ("array dict", "[{}]");
|
||||||
|
runTest ("array array", "[[]]");
|
||||||
|
runTest ("more complex",
|
||||||
|
"{\"array\":[{\"12\":23},{},null,false,0.5]}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(WriteJson, ripple_basics, ripple);
|
||||||
|
|
||||||
|
} // RPC
|
||||||
|
} // ripple
|
||||||
@@ -30,14 +30,15 @@
|
|||||||
#include <ripple/overlay/Overlay.h>
|
#include <ripple/overlay/Overlay.h>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
#include <ripple/rpc/impl/Coroutine.cpp>
|
||||||
#include <ripple/rpc/impl/ErrorCodes.cpp>
|
#include <ripple/rpc/impl/ErrorCodes.cpp>
|
||||||
#include <ripple/rpc/impl/JsonObject.cpp>
|
#include <ripple/rpc/impl/JsonObject.cpp>
|
||||||
#include <ripple/rpc/impl/JsonWriter.cpp>
|
#include <ripple/rpc/impl/JsonWriter.cpp>
|
||||||
|
#include <ripple/rpc/impl/WriteJson.cpp>
|
||||||
#include <ripple/rpc/impl/Manager.cpp>
|
#include <ripple/rpc/impl/Manager.cpp>
|
||||||
#include <ripple/rpc/impl/RPCHandler.cpp>
|
#include <ripple/rpc/impl/RPCHandler.cpp>
|
||||||
#include <ripple/rpc/impl/Status.cpp>
|
#include <ripple/rpc/impl/Status.cpp>
|
||||||
#include <ripple/rpc/impl/Yield.cpp>
|
#include <ripple/rpc/impl/Yield.cpp>
|
||||||
#include <ripple/rpc/impl/Status_test.cpp>
|
|
||||||
|
|
||||||
#include <ripple/rpc/handlers/Handlers.h>
|
#include <ripple/rpc/handlers/Handlers.h>
|
||||||
#include <ripple/rpc/handlers/AccountCurrencies.cpp>
|
#include <ripple/rpc/handlers/AccountCurrencies.cpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user