mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 19:25:51 +00:00
Cleanups to Json Object code.
* Replace Json::JsonException with std::logic_error. * Move two functions definitions to Object.cpp. * Fix include guards.
This commit is contained in:
@@ -20,6 +20,9 @@
|
||||
#ifndef RIPPLE_BASICS_TOSTRING_H_INCLUDED
|
||||
#define RIPPLE_BASICS_TOSTRING_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** to_string() generalizes std::to_string to handle bools, chars, and strings.
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_RPC_JSONOBJECT_H_INCLUDED
|
||||
#define RIPPLE_RPC_JSONOBJECT_H_INCLUDED
|
||||
#ifndef RIPPLE_JSON_OBJECT_H_INCLUDED
|
||||
#define RIPPLE_JSON_OBJECT_H_INCLUDED
|
||||
|
||||
#include <ripple/json/Writer.h>
|
||||
#include <beast/cxx14/memory.h>
|
||||
@@ -39,14 +39,14 @@ namespace Json {
|
||||
|
||||
1. Only one collection can be open for change at any one time.
|
||||
|
||||
This condition is enforced automatically and a JsonException thrown if it
|
||||
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 JsonException is thrown when the tag is added for a second time.
|
||||
a std::logic_error is thrown when the tag is added for a second time.
|
||||
|
||||
Code samples:
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Json {
|
||||
// Outputs {"hands":{"left":false,"right":true}}
|
||||
|
||||
|
||||
Typical ways to make mistakes and get a JsonException:
|
||||
Typical ways to make mistakes and get a std::logic_error:
|
||||
|
||||
Writer writer;
|
||||
Object::Root root (writer);
|
||||
@@ -360,6 +360,14 @@ public:
|
||||
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.
|
||||
}
|
||||
};
|
||||
|
||||
@@ -373,36 +381,6 @@ void Array::append (Scalar const& value)
|
||||
writer_->append (value);
|
||||
}
|
||||
|
||||
inline 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;
|
||||
}
|
||||
}
|
||||
assert (false); // Can't get here.
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void Object::set (std::string const& key, Scalar const& value)
|
||||
{
|
||||
@@ -411,36 +389,6 @@ void Object::set (std::string const& key, Scalar const& value)
|
||||
writer_->set (key, value);
|
||||
}
|
||||
|
||||
inline 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;
|
||||
}
|
||||
}
|
||||
assert (false); // Can't get here.
|
||||
}
|
||||
|
||||
inline
|
||||
Json::Value& setArray (Json::Value& json, Json::StaticString const& key)
|
||||
{
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
#define RIPPLE_JSON_OUTPUT_H_INCLUDED
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace Json {
|
||||
|
||||
class Value;
|
||||
|
||||
using Output = std::function <void (boost::string_ref const&)>;
|
||||
|
||||
inline
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_RPC_JSONWRITER_H_INCLUDED
|
||||
#define RIPPLE_RPC_JSONWRITER_H_INCLUDED
|
||||
#ifndef RIPPLE_JSON_WRITER_H_INCLUDED
|
||||
#define RIPPLE_JSON_WRITER_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/ToString.h>
|
||||
#include <ripple/json/Output.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Json {
|
||||
@@ -200,17 +199,23 @@ public:
|
||||
/*** Output a Json::Value. */
|
||||
void output (Json::Value const&);
|
||||
|
||||
/** Output a null. */
|
||||
void output (std::nullptr_t);
|
||||
|
||||
/** Output a float. */
|
||||
void output (float);
|
||||
|
||||
/** Output a double. */
|
||||
void output (double);
|
||||
|
||||
/** Output a bool. */
|
||||
void output (bool);
|
||||
|
||||
/** Output numbers or booleans. */
|
||||
template <typename Type>
|
||||
void output (Type t)
|
||||
{
|
||||
implOutput (ripple::to_string (t));
|
||||
}
|
||||
|
||||
/** Output an error code. */
|
||||
void output (ripple::error_code_i t)
|
||||
{
|
||||
output (int(t));
|
||||
implOutput (std::to_string (t));
|
||||
}
|
||||
|
||||
void output (Json::StaticString const& t)
|
||||
@@ -225,23 +230,10 @@ private:
|
||||
void implOutput (std::string const&);
|
||||
};
|
||||
|
||||
class JsonException : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit JsonException (std::string const& name) : name_(name) {}
|
||||
const char* what() const throw() override
|
||||
{
|
||||
return name_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string const name_;
|
||||
};
|
||||
|
||||
inline void check (bool condition, std::string const& message)
|
||||
{
|
||||
if (!condition)
|
||||
throw JsonException (message);
|
||||
throw std::logic_error (message);
|
||||
}
|
||||
|
||||
} // Json
|
||||
|
||||
@@ -62,9 +62,9 @@ Collection::Collection (Collection&& that) noexcept
|
||||
void Collection::checkWritable (std::string const& label)
|
||||
{
|
||||
if (!enabled_)
|
||||
throw JsonException (label + ": not enabled");
|
||||
throw std::logic_error (label + ": not enabled");
|
||||
if (!writer_)
|
||||
throw JsonException (label + ": not writable");
|
||||
throw std::logic_error (label + ": not writable");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -125,6 +125,70 @@ 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;
|
||||
}
|
||||
}
|
||||
assert (false); // Can't get here.
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
assert (false); // Can't get here.
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
template <class Object>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <ripple/json/Output.h>
|
||||
#include <ripple/json/Writer.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <stack>
|
||||
|
||||
namespace Json {
|
||||
|
||||
@@ -146,7 +147,7 @@ public:
|
||||
|
||||
void writeObjectTag (std::string const& tag)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifndef NDEBUG
|
||||
// Make sure we haven't already seen this tag.
|
||||
auto& tags = stack_.top ().tags;
|
||||
check (tags.find (tag) == tags.end (), "Already seen tag " + tag);
|
||||
@@ -194,7 +195,7 @@ private:
|
||||
* If false, we have to emit a , before we write the next entry. */
|
||||
bool isFirst = true;
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef NDEBUG
|
||||
/** What tags have we already seen in this collection? */
|
||||
std::set <std::string> tags;
|
||||
#endif
|
||||
@@ -246,26 +247,28 @@ void Writer::output (Json::Value const& value)
|
||||
outputJson (value, impl_->getOutput());
|
||||
}
|
||||
|
||||
template <>
|
||||
void Writer::output (float f)
|
||||
{
|
||||
auto s = ripple::to_string (f);
|
||||
impl_->output ({s.data (), lengthWithoutTrailingZeros (s)});
|
||||
}
|
||||
|
||||
template <>
|
||||
void Writer::output (double f)
|
||||
{
|
||||
auto s = ripple::to_string (f);
|
||||
impl_->output ({s.data (), lengthWithoutTrailingZeros (s)});
|
||||
}
|
||||
|
||||
template <>
|
||||
void Writer::output (std::nullptr_t)
|
||||
{
|
||||
impl_->output ("null");
|
||||
}
|
||||
|
||||
void Writer::output (bool b)
|
||||
{
|
||||
impl_->output (b ? "true" : "false");
|
||||
}
|
||||
|
||||
void Writer::implOutput (std::string const& s)
|
||||
{
|
||||
impl_->output (s);
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||
* but may be useful to support feature such as RPC where bandwith is limited.
|
||||
* \sa Reader, Value
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/json/Output.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
#include <ripple/json/json_writer.h>
|
||||
#include <ripple/rpc/tests/TestOutputSuite.test.h>
|
||||
|
||||
namespace Json {
|
||||
|
||||
@@ -250,7 +250,7 @@ void executeRPC (
|
||||
{
|
||||
// Can't ever get here.
|
||||
assert (false);
|
||||
throw Json::JsonException ("RPC handler with no method");
|
||||
throw std::logic_error ("RPC handler with no method");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ std::string getHTTPHeaderTimestamp ()
|
||||
return std::string (buffer);
|
||||
}
|
||||
|
||||
void HTTPReply (int nStatus, std::string const& content, Json::Output output)
|
||||
void HTTPReply (
|
||||
int nStatus, std::string const& content, Json::Output const& output)
|
||||
{
|
||||
if (ShouldLog (lsTRACE, RPC))
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
void HTTPReply (int nStatus, std::string const& strMsg, Json::Output);
|
||||
void HTTPReply (int nStatus, std::string const& strMsg, Json::Output const&);
|
||||
|
||||
} // ripple
|
||||
|
||||
|
||||
Reference in New Issue
Block a user