mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Clean up JSON code:
* Remove obsolete files * Remove obsolete preprocessor configuration tags and decorations * Remove arcane functionality (YAML compatibility, comment support) * Enforce strict mode (single root) * Improve parsing of numerical types * Misc. cleanups
This commit is contained in:
committed by
Tom Ritchford
parent
6d91d02c62
commit
558c6b621b
@@ -20,65 +20,16 @@
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
namespace Json
|
||||
{
|
||||
|
||||
// Implementation of class Features
|
||||
// ////////////////////////////////
|
||||
|
||||
Features::Features ()
|
||||
: allowComments_ ( true )
|
||||
, strictRoot_ ( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Features
|
||||
Features::all ()
|
||||
{
|
||||
return Features ();
|
||||
}
|
||||
|
||||
|
||||
Features
|
||||
Features::strictMode ()
|
||||
{
|
||||
Features features;
|
||||
features.allowComments_ = false;
|
||||
features.strictRoot_ = true;
|
||||
return features;
|
||||
}
|
||||
|
||||
// Implementation of class Reader
|
||||
// ////////////////////////////////
|
||||
|
||||
|
||||
static inline bool
|
||||
in ( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
|
||||
{
|
||||
return c == c1 || c == c2 || c == c3 || c == c4;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
in ( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
|
||||
{
|
||||
return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
containsNewLine ( Reader::Location begin,
|
||||
Reader::Location end )
|
||||
{
|
||||
for ( ; begin < end; ++begin )
|
||||
if ( *begin == '\n' || *begin == '\r' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string codePointToUTF8 (unsigned int cp)
|
||||
static
|
||||
std::string
|
||||
codePointToUTF8 (unsigned int cp)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
@@ -119,33 +70,24 @@ static std::string codePointToUTF8 (unsigned int cp)
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
Reader::Reader ()
|
||||
: features_ ( Features::all () )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reader::Reader ( const Features& features )
|
||||
: features_ ( features )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Reader::parse ( std::string const& document,
|
||||
Value& root,
|
||||
bool collectComments )
|
||||
Value& root)
|
||||
{
|
||||
document_ = document;
|
||||
const char* begin = document_.c_str ();
|
||||
const char* end = begin + document_.length ();
|
||||
return parse ( begin, end, root, collectComments );
|
||||
return parse ( begin, end, root );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Reader::parse ( std::istream& sin,
|
||||
Value& root,
|
||||
bool collectComments )
|
||||
Value& root)
|
||||
{
|
||||
//std::istream_iterator<char> begin(sin);
|
||||
//std::istream_iterator<char> end;
|
||||
@@ -156,26 +98,18 @@ Reader::parse ( std::istream& sin,
|
||||
// create an extra copy.
|
||||
std::string doc;
|
||||
std::getline (sin, doc, (char)EOF);
|
||||
return parse ( doc, root, collectComments );
|
||||
return parse ( doc, root );
|
||||
}
|
||||
|
||||
bool
|
||||
Reader::parse ( const char* beginDoc, const char* endDoc,
|
||||
Value& root,
|
||||
bool collectComments )
|
||||
Value& root)
|
||||
{
|
||||
if ( !features_.allowComments_ )
|
||||
{
|
||||
collectComments = false;
|
||||
}
|
||||
|
||||
begin_ = beginDoc;
|
||||
end_ = endDoc;
|
||||
collectComments_ = collectComments;
|
||||
current_ = begin_;
|
||||
lastValueEnd_ = 0;
|
||||
lastValue_ = 0;
|
||||
commentsBefore_ = "";
|
||||
errors_.clear ();
|
||||
|
||||
while ( !nodes_.empty () )
|
||||
@@ -187,27 +121,20 @@ Reader::parse ( const char* beginDoc, const char* endDoc,
|
||||
Token token;
|
||||
skipCommentTokens ( token );
|
||||
|
||||
if ( collectComments_ && !commentsBefore_.empty () )
|
||||
root.setComment ( commentsBefore_, commentAfter );
|
||||
|
||||
if ( features_.strictRoot_ )
|
||||
if ( !root.isArray () && !root.isObject () )
|
||||
{
|
||||
if ( !root.isArray () && !root.isObject () )
|
||||
{
|
||||
// Set error location to start of doc, ideally should be first token found in doc
|
||||
token.type_ = tokenError;
|
||||
token.start_ = beginDoc;
|
||||
token.end_ = endDoc;
|
||||
addError ( "A valid JSON document must be either an array or an object value.",
|
||||
token );
|
||||
return false;
|
||||
}
|
||||
// Set error location to start of doc, ideally should be first token found in doc
|
||||
token.type_ = tokenError;
|
||||
token.start_ = beginDoc;
|
||||
token.end_ = endDoc;
|
||||
addError ( "A valid JSON document must be either an array or an object value.",
|
||||
token );
|
||||
return false;
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Reader::readValue ()
|
||||
{
|
||||
@@ -215,13 +142,6 @@ Reader::readValue ()
|
||||
skipCommentTokens ( token );
|
||||
bool successful = true;
|
||||
|
||||
if ( collectComments_ && !commentsBefore_.empty () )
|
||||
{
|
||||
currentValue ().setComment ( commentsBefore_, commentBefore );
|
||||
commentsBefore_ = "";
|
||||
}
|
||||
|
||||
|
||||
switch ( token.type_ )
|
||||
{
|
||||
case tokenObjectBegin:
|
||||
@@ -232,10 +152,14 @@ Reader::readValue ()
|
||||
successful = readArray ( token );
|
||||
break;
|
||||
|
||||
case tokenNumber:
|
||||
case tokenInteger:
|
||||
successful = decodeNumber ( token );
|
||||
break;
|
||||
|
||||
case tokenDouble:
|
||||
successful = decodeDouble ( token );
|
||||
break;
|
||||
|
||||
case tokenString:
|
||||
successful = decodeString ( token );
|
||||
break;
|
||||
@@ -256,12 +180,6 @@ Reader::readValue ()
|
||||
return addError ( "Syntax error: value, object or array expected.", token );
|
||||
}
|
||||
|
||||
if ( collectComments_ )
|
||||
{
|
||||
lastValueEnd_ = current_;
|
||||
lastValue_ = ¤tValue ();
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
@@ -269,18 +187,11 @@ Reader::readValue ()
|
||||
void
|
||||
Reader::skipCommentTokens ( Token& token )
|
||||
{
|
||||
if ( features_.allowComments_ )
|
||||
{
|
||||
do
|
||||
{
|
||||
readToken ( token );
|
||||
}
|
||||
while ( token.type_ == tokenComment );
|
||||
}
|
||||
else
|
||||
do
|
||||
{
|
||||
readToken ( token );
|
||||
}
|
||||
while ( token.type_ == tokenComment );
|
||||
}
|
||||
|
||||
|
||||
@@ -343,8 +254,7 @@ Reader::readToken ( Token& token )
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
token.type_ = tokenNumber;
|
||||
readNumber ();
|
||||
token.type_ = readNumber ();
|
||||
break;
|
||||
|
||||
case 't':
|
||||
@@ -423,57 +333,17 @@ Reader::match ( Location pattern,
|
||||
bool
|
||||
Reader::readComment ()
|
||||
{
|
||||
Location commentBegin = current_ - 1;
|
||||
Char c = getNextChar ();
|
||||
bool successful = false;
|
||||
|
||||
if ( c == '*' )
|
||||
successful = readCStyleComment ();
|
||||
else if ( c == '/' )
|
||||
successful = readCppStyleComment ();
|
||||
return readCStyleComment ();
|
||||
|
||||
if ( !successful )
|
||||
return false;
|
||||
if ( c == '/' )
|
||||
return readCppStyleComment ();
|
||||
|
||||
if ( collectComments_ )
|
||||
{
|
||||
CommentPlacement placement = commentBefore;
|
||||
|
||||
if ( lastValueEnd_ && !containsNewLine ( lastValueEnd_, commentBegin ) )
|
||||
{
|
||||
if ( c != '*' || !containsNewLine ( commentBegin, current_ ) )
|
||||
placement = commentAfterOnSameLine;
|
||||
}
|
||||
|
||||
addComment ( commentBegin, current_, placement );
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Reader::addComment ( Location begin,
|
||||
Location end,
|
||||
CommentPlacement placement )
|
||||
{
|
||||
assert ( collectComments_ );
|
||||
|
||||
if ( placement == commentAfterOnSameLine )
|
||||
{
|
||||
assert ( lastValue_ != 0 );
|
||||
lastValue_->setComment ( std::string ( begin, end ), placement );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !commentsBefore_.empty () )
|
||||
commentsBefore_ += "\n";
|
||||
|
||||
commentsBefore_ += std::string ( begin, end );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Reader::readCStyleComment ()
|
||||
{
|
||||
@@ -503,18 +373,36 @@ Reader::readCppStyleComment ()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Reader::TokenType
|
||||
Reader::readNumber ()
|
||||
{
|
||||
while ( current_ != end_ )
|
||||
{
|
||||
if ( ! (*current_ >= '0' && *current_ <= '9') &&
|
||||
!in ( *current_, '.', 'e', 'E', '+', '-' ) )
|
||||
break;
|
||||
static char const extended_tokens[] = { '.', 'e', 'E', '+', '-' };
|
||||
|
||||
++current_;
|
||||
TokenType type = tokenInteger;
|
||||
|
||||
if ( current_ != end_ )
|
||||
{
|
||||
if (*current_ == '-')
|
||||
++current_;
|
||||
|
||||
while ( current_ != end_ )
|
||||
{
|
||||
if (!std::isdigit (*current_))
|
||||
{
|
||||
auto ret = std::find (std::begin (extended_tokens),
|
||||
std::end (extended_tokens), *current_);
|
||||
|
||||
if (ret == std::end (extended_tokens))
|
||||
break;
|
||||
|
||||
type = tokenDouble;
|
||||
}
|
||||
|
||||
++current_;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -664,28 +552,29 @@ Reader::readArray ( Token& tokenStart )
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
in ( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
|
||||
{
|
||||
return c == c1 || c == c2 || c == c3 || c == c4;
|
||||
}
|
||||
|
||||
bool
|
||||
Reader::decodeNumber ( Token& token )
|
||||
{
|
||||
bool isDouble = false;
|
||||
|
||||
for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
|
||||
{
|
||||
isDouble = isDouble
|
||||
|| in ( *inspect, '.', 'e', 'E', '+' )
|
||||
|| ( *inspect == '-' && inspect != token.start_ );
|
||||
}
|
||||
|
||||
if ( isDouble )
|
||||
return decodeDouble ( token );
|
||||
|
||||
Location current = token.start_;
|
||||
bool isNegative = *current == '-';
|
||||
|
||||
if ( isNegative )
|
||||
++current;
|
||||
|
||||
if (current == token.end_)
|
||||
{
|
||||
return addError ( "'" + std::string ( token.start_, token.end_ ) +
|
||||
"' is not a valid number.", token );
|
||||
}
|
||||
|
||||
// The existing Json integers are 32-bit so using a 64-bit value here avoids
|
||||
// overflows in the conversion code below.
|
||||
std::int64_t value = 0;
|
||||
|
||||
static_assert(sizeof(value) > sizeof(Value::maxUInt),
|
||||
@@ -1063,7 +952,7 @@ Reader::getFormatedErrorMessages () const
|
||||
std::istream& operator>> ( std::istream& sin, Value& root )
|
||||
{
|
||||
Json::Reader reader;
|
||||
bool ok = reader.parse (sin, root, true);
|
||||
bool ok = reader.parse (sin, root);
|
||||
|
||||
//JSON_ASSERT( ok );
|
||||
if (!ok) throw std::runtime_error (reader.getFormatedErrorMessages ());
|
||||
|
||||
Reference in New Issue
Block a user