Update to use the new opensource jsoncpp and remove jsoncpp mods.
Review URL: http://webrtc-codereview.appspot.com/145001 git-svn-id: http://webrtc.googlecode.com/svn/trunk@596 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
19eefdc9f0
commit
b27f3f16b6
6
DEPS
6
DEPS
@ -61,7 +61,7 @@ deps = {
|
|||||||
Var("chromium_trunk") + "/deps/third_party/yasm/binaries@74228",
|
Var("chromium_trunk") + "/deps/third_party/yasm/binaries@74228",
|
||||||
|
|
||||||
"trunk/third_party/jsoncpp/":
|
"trunk/third_party/jsoncpp/":
|
||||||
"https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/jsoncpp@139",
|
"https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/jsoncpp@246",
|
||||||
}
|
}
|
||||||
|
|
||||||
deps_os = {
|
deps_os = {
|
||||||
@ -72,10 +72,6 @@ deps_os = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hooks = [
|
hooks = [
|
||||||
{
|
|
||||||
"pattern": ".",
|
|
||||||
"action": ["svn", "export", Var("webrtc_trunk") + "/third_party_mods/jsoncpp", "trunk/third_party/jsoncpp", "--force"],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
# Create a supplement.gypi file under trunk/. This file will be picked up
|
# Create a supplement.gypi file under trunk/. This file will be picked up
|
||||||
# by gyp and we use it to set Chromium related variables (inside_chromium_build)
|
# by gyp and we use it to set Chromium related variables (inside_chromium_build)
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
|
||||||
# found in the LICENSE file.
|
|
||||||
|
|
||||||
{
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'jsoncpp',
|
|
||||||
'type': '<(library)',
|
|
||||||
'sources': [
|
|
||||||
'include/json/autolink.h',
|
|
||||||
'include/json/config.h',
|
|
||||||
'include/json/forwards.h',
|
|
||||||
'include/json/json.h',
|
|
||||||
'include/json/reader.h',
|
|
||||||
'include/json/value.h',
|
|
||||||
'include/json/writer.h',
|
|
||||||
'src/lib_json/json_batchallocator.h',
|
|
||||||
'src/lib_json/json_internalarray.inl',
|
|
||||||
'src/lib_json/json_internalmap.inl',
|
|
||||||
'src/lib_json/json_reader.cpp',
|
|
||||||
'src/lib_json/json_value.cpp',
|
|
||||||
'src/lib_json/json_valueiterator.inl',
|
|
||||||
'src/lib_json/json_writer.cpp',
|
|
||||||
],
|
|
||||||
'include_dirs': [
|
|
||||||
'include/',
|
|
||||||
],
|
|
||||||
'direct_dependent_settings': {
|
|
||||||
'include_dirs': [
|
|
||||||
'include/',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:2
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=2 shiftwidth=2:
|
|
@ -1,885 +0,0 @@
|
|||||||
#include <json/reader.h>
|
|
||||||
#include <json/value.h>
|
|
||||||
#include <utility>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1400 // VC++ 8.0
|
|
||||||
#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
|
||||||
|
|
||||||
if (cp <= 0x7f)
|
|
||||||
{
|
|
||||||
result.resize(1);
|
|
||||||
result[0] = static_cast<char>(cp);
|
|
||||||
}
|
|
||||||
else if (cp <= 0x7FF)
|
|
||||||
{
|
|
||||||
result.resize(2);
|
|
||||||
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
|
||||||
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
|
||||||
}
|
|
||||||
else if (cp <= 0xFFFF)
|
|
||||||
{
|
|
||||||
result.resize(3);
|
|
||||||
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
|
||||||
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
|
|
||||||
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
|
|
||||||
}
|
|
||||||
else if (cp <= 0x10FFFF)
|
|
||||||
{
|
|
||||||
result.resize(4);
|
|
||||||
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
|
||||||
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
|
||||||
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
|
||||||
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Class Reader
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Reader::Reader()
|
|
||||||
: features_( Features::all() )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Reader::Reader( const Features &features )
|
|
||||||
: features_( features )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::parse( const std::string &document,
|
|
||||||
Value &root,
|
|
||||||
bool collectComments )
|
|
||||||
{
|
|
||||||
document_ = document;
|
|
||||||
const char *begin = document_.c_str();
|
|
||||||
const char *end = begin + document_.length();
|
|
||||||
return parse( begin, end, root, collectComments );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::parse( std::istream& sin,
|
|
||||||
Value &root,
|
|
||||||
bool collectComments )
|
|
||||||
{
|
|
||||||
//std::istream_iterator<char> begin(sin);
|
|
||||||
//std::istream_iterator<char> end;
|
|
||||||
// Those would allow streamed input from a file, if parse() were a
|
|
||||||
// template function.
|
|
||||||
|
|
||||||
// Since std::string is reference-counted, this at least does not
|
|
||||||
// create an extra copy.
|
|
||||||
std::string doc;
|
|
||||||
std::getline(sin, doc, (char)EOF);
|
|
||||||
return parse( doc, root, collectComments );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::parse( const char *beginDoc, const char *endDoc,
|
|
||||||
Value &root,
|
|
||||||
bool collectComments )
|
|
||||||
{
|
|
||||||
if ( !features_.allowComments_ )
|
|
||||||
{
|
|
||||||
collectComments = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
begin_ = beginDoc;
|
|
||||||
end_ = endDoc;
|
|
||||||
collectComments_ = collectComments;
|
|
||||||
current_ = begin_;
|
|
||||||
lastValueEnd_ = 0;
|
|
||||||
lastValue_ = 0;
|
|
||||||
commentsBefore_ = "";
|
|
||||||
errors_.clear();
|
|
||||||
while ( !nodes_.empty() )
|
|
||||||
nodes_.pop();
|
|
||||||
nodes_.push( &root );
|
|
||||||
|
|
||||||
bool successful = readValue();
|
|
||||||
Token token;
|
|
||||||
skipCommentTokens( token );
|
|
||||||
if ( collectComments_ && !commentsBefore_.empty() )
|
|
||||||
root.setComment( commentsBefore_, commentAfter );
|
|
||||||
if ( features_.strictRoot_ )
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return successful;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readValue()
|
|
||||||
{
|
|
||||||
Token token;
|
|
||||||
skipCommentTokens( token );
|
|
||||||
bool successful = true;
|
|
||||||
|
|
||||||
if ( collectComments_ && !commentsBefore_.empty() )
|
|
||||||
{
|
|
||||||
currentValue().setComment( commentsBefore_, commentBefore );
|
|
||||||
commentsBefore_ = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch ( token.type_ )
|
|
||||||
{
|
|
||||||
case tokenObjectBegin:
|
|
||||||
successful = readObject( token );
|
|
||||||
break;
|
|
||||||
case tokenArrayBegin:
|
|
||||||
successful = readArray( token );
|
|
||||||
break;
|
|
||||||
case tokenNumber:
|
|
||||||
successful = decodeNumber( token );
|
|
||||||
break;
|
|
||||||
case tokenString:
|
|
||||||
successful = decodeString( token );
|
|
||||||
break;
|
|
||||||
case tokenTrue:
|
|
||||||
currentValue() = true;
|
|
||||||
break;
|
|
||||||
case tokenFalse:
|
|
||||||
currentValue() = false;
|
|
||||||
break;
|
|
||||||
case tokenNull:
|
|
||||||
currentValue() = Value();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return addError( "Syntax error: value, object or array expected.", token );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( collectComments_ )
|
|
||||||
{
|
|
||||||
lastValueEnd_ = current_;
|
|
||||||
lastValue_ = ¤tValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return successful;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Reader::skipCommentTokens( Token &token )
|
|
||||||
{
|
|
||||||
if ( features_.allowComments_ )
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
readToken( token );
|
|
||||||
}
|
|
||||||
while ( token.type_ == tokenComment );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
readToken( token );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::expectToken( TokenType type, Token &token, const char *message )
|
|
||||||
{
|
|
||||||
readToken( token );
|
|
||||||
if ( token.type_ != type )
|
|
||||||
return addError( message, token );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readToken( Token &token )
|
|
||||||
{
|
|
||||||
skipSpaces();
|
|
||||||
token.start_ = current_;
|
|
||||||
Char c = getNextChar();
|
|
||||||
bool ok = true;
|
|
||||||
switch ( c )
|
|
||||||
{
|
|
||||||
case '{':
|
|
||||||
token.type_ = tokenObjectBegin;
|
|
||||||
break;
|
|
||||||
case '}':
|
|
||||||
token.type_ = tokenObjectEnd;
|
|
||||||
break;
|
|
||||||
case '[':
|
|
||||||
token.type_ = tokenArrayBegin;
|
|
||||||
break;
|
|
||||||
case ']':
|
|
||||||
token.type_ = tokenArrayEnd;
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
token.type_ = tokenString;
|
|
||||||
ok = readString();
|
|
||||||
break;
|
|
||||||
case '/':
|
|
||||||
token.type_ = tokenComment;
|
|
||||||
ok = readComment();
|
|
||||||
break;
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
case '-':
|
|
||||||
token.type_ = tokenNumber;
|
|
||||||
readNumber();
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
token.type_ = tokenTrue;
|
|
||||||
ok = match( "rue", 3 );
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
token.type_ = tokenFalse;
|
|
||||||
ok = match( "alse", 4 );
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
token.type_ = tokenNull;
|
|
||||||
ok = match( "ull", 3 );
|
|
||||||
break;
|
|
||||||
case ',':
|
|
||||||
token.type_ = tokenArraySeparator;
|
|
||||||
break;
|
|
||||||
case ':':
|
|
||||||
token.type_ = tokenMemberSeparator;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
token.type_ = tokenEndOfStream;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( !ok )
|
|
||||||
token.type_ = tokenError;
|
|
||||||
token.end_ = current_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Reader::skipSpaces()
|
|
||||||
{
|
|
||||||
while ( current_ != end_ )
|
|
||||||
{
|
|
||||||
Char c = *current_;
|
|
||||||
if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
|
|
||||||
++current_;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::match( Location pattern,
|
|
||||||
int patternLength )
|
|
||||||
{
|
|
||||||
if ( end_ - current_ < patternLength )
|
|
||||||
return false;
|
|
||||||
int index = patternLength;
|
|
||||||
while ( index-- )
|
|
||||||
if ( current_[index] != pattern[index] )
|
|
||||||
return false;
|
|
||||||
current_ += patternLength;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readComment()
|
|
||||||
{
|
|
||||||
Location commentBegin = current_ - 1;
|
|
||||||
Char c = getNextChar();
|
|
||||||
bool successful = false;
|
|
||||||
if ( c == '*' )
|
|
||||||
successful = readCStyleComment();
|
|
||||||
else if ( c == '/' )
|
|
||||||
successful = readCppStyleComment();
|
|
||||||
if ( !successful )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ( collectComments_ )
|
|
||||||
{
|
|
||||||
CommentPlacement placement = commentBefore;
|
|
||||||
if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
|
|
||||||
{
|
|
||||||
if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
|
|
||||||
placement = commentAfterOnSameLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
addComment( commentBegin, current_, placement );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
while ( current_ != end_ )
|
|
||||||
{
|
|
||||||
Char c = getNextChar();
|
|
||||||
if ( c == '*' && *current_ == '/' )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return getNextChar() == '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readCppStyleComment()
|
|
||||||
{
|
|
||||||
while ( current_ != end_ )
|
|
||||||
{
|
|
||||||
Char c = getNextChar();
|
|
||||||
if ( c == '\r' || c == '\n' )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Reader::readNumber()
|
|
||||||
{
|
|
||||||
while ( current_ != end_ )
|
|
||||||
{
|
|
||||||
if ( !(*current_ >= '0' && *current_ <= '9') &&
|
|
||||||
!in( *current_, '.', 'e', 'E', '+', '-' ) )
|
|
||||||
break;
|
|
||||||
++current_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readString()
|
|
||||||
{
|
|
||||||
Char c = 0;
|
|
||||||
while ( current_ != end_ )
|
|
||||||
{
|
|
||||||
c = getNextChar();
|
|
||||||
if ( c == '\\' )
|
|
||||||
getNextChar();
|
|
||||||
else if ( c == '"' )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return c == '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readObject( Token &tokenStart )
|
|
||||||
{
|
|
||||||
Token tokenName;
|
|
||||||
std::string name;
|
|
||||||
currentValue() = Value( objectValue );
|
|
||||||
while ( readToken( tokenName ) )
|
|
||||||
{
|
|
||||||
bool initialTokenOk = true;
|
|
||||||
while ( tokenName.type_ == tokenComment && initialTokenOk )
|
|
||||||
initialTokenOk = readToken( tokenName );
|
|
||||||
if ( !initialTokenOk )
|
|
||||||
break;
|
|
||||||
if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
|
|
||||||
return true;
|
|
||||||
if ( tokenName.type_ != tokenString )
|
|
||||||
break;
|
|
||||||
|
|
||||||
name = "";
|
|
||||||
if ( !decodeString( tokenName, name ) )
|
|
||||||
return recoverFromError( tokenObjectEnd );
|
|
||||||
|
|
||||||
Token colon;
|
|
||||||
if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
|
|
||||||
{
|
|
||||||
return addErrorAndRecover( "Missing ':' after object member name",
|
|
||||||
colon,
|
|
||||||
tokenObjectEnd );
|
|
||||||
}
|
|
||||||
Value &value = currentValue()[ name ];
|
|
||||||
nodes_.push( &value );
|
|
||||||
bool ok = readValue();
|
|
||||||
nodes_.pop();
|
|
||||||
if ( !ok ) // error already set
|
|
||||||
return recoverFromError( tokenObjectEnd );
|
|
||||||
|
|
||||||
Token comma;
|
|
||||||
if ( !readToken( comma )
|
|
||||||
|| ( comma.type_ != tokenObjectEnd &&
|
|
||||||
comma.type_ != tokenArraySeparator &&
|
|
||||||
comma.type_ != tokenComment ) )
|
|
||||||
{
|
|
||||||
return addErrorAndRecover( "Missing ',' or '}' in object declaration",
|
|
||||||
comma,
|
|
||||||
tokenObjectEnd );
|
|
||||||
}
|
|
||||||
bool finalizeTokenOk = true;
|
|
||||||
while ( comma.type_ == tokenComment &&
|
|
||||||
finalizeTokenOk )
|
|
||||||
finalizeTokenOk = readToken( comma );
|
|
||||||
if ( comma.type_ == tokenObjectEnd )
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return addErrorAndRecover( "Missing '}' or object member name",
|
|
||||||
tokenName,
|
|
||||||
tokenObjectEnd );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::readArray( Token &tokenStart )
|
|
||||||
{
|
|
||||||
currentValue() = Value( arrayValue );
|
|
||||||
skipSpaces();
|
|
||||||
if ( *current_ == ']' ) // empty array
|
|
||||||
{
|
|
||||||
Token endArray;
|
|
||||||
readToken( endArray );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int index = 0;
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
Value &value = currentValue()[ index++ ];
|
|
||||||
nodes_.push( &value );
|
|
||||||
bool ok = readValue();
|
|
||||||
nodes_.pop();
|
|
||||||
if ( !ok ) // error already set
|
|
||||||
return recoverFromError( tokenArrayEnd );
|
|
||||||
|
|
||||||
Token token;
|
|
||||||
// Accept Comment after last item in the array.
|
|
||||||
ok = readToken( token );
|
|
||||||
while ( token.type_ == tokenComment && ok )
|
|
||||||
{
|
|
||||||
ok = readToken( token );
|
|
||||||
}
|
|
||||||
bool badTokenType = ( token.type_ == tokenArraySeparator &&
|
|
||||||
token.type_ == tokenArrayEnd );
|
|
||||||
if ( !ok || badTokenType )
|
|
||||||
{
|
|
||||||
return addErrorAndRecover( "Missing ',' or ']' in array declaration",
|
|
||||||
token,
|
|
||||||
tokenArrayEnd );
|
|
||||||
}
|
|
||||||
if ( token.type_ == tokenArrayEnd )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt)
|
|
||||||
: Value::maxUInt) / 10;
|
|
||||||
Value::UInt value = 0;
|
|
||||||
while ( current < token.end_ )
|
|
||||||
{
|
|
||||||
Char c = *current++;
|
|
||||||
if ( c < '0' || c > '9' )
|
|
||||||
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
|
|
||||||
if ( value >= threshold )
|
|
||||||
return decodeDouble( token );
|
|
||||||
value = value * 10 + Value::UInt(c - '0');
|
|
||||||
}
|
|
||||||
if ( isNegative )
|
|
||||||
currentValue() = -Value::Int( value );
|
|
||||||
else if ( value <= Value::UInt(Value::maxInt) )
|
|
||||||
currentValue() = Value::Int( value );
|
|
||||||
else
|
|
||||||
currentValue() = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::decodeDouble( Token &token )
|
|
||||||
{
|
|
||||||
double value = 0;
|
|
||||||
const int bufferSize = 32;
|
|
||||||
int count;
|
|
||||||
int length = int(token.end_ - token.start_);
|
|
||||||
if ( length <= bufferSize )
|
|
||||||
{
|
|
||||||
Char buffer[bufferSize];
|
|
||||||
memcpy( buffer, token.start_, length );
|
|
||||||
buffer[length] = 0;
|
|
||||||
count = sscanf( buffer, "%lf", &value );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string buffer( token.start_, token.end_ );
|
|
||||||
count = sscanf( buffer.c_str(), "%lf", &value );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( count != 1 )
|
|
||||||
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
|
|
||||||
currentValue() = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::decodeString( Token &token )
|
|
||||||
{
|
|
||||||
std::string decoded;
|
|
||||||
if ( !decodeString( token, decoded ) )
|
|
||||||
return false;
|
|
||||||
currentValue() = decoded;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::decodeString( Token &token, std::string &decoded )
|
|
||||||
{
|
|
||||||
decoded.reserve( token.end_ - token.start_ - 2 );
|
|
||||||
Location current = token.start_ + 1; // skip '"'
|
|
||||||
Location end = token.end_ - 1; // do not include '"'
|
|
||||||
while ( current != end )
|
|
||||||
{
|
|
||||||
Char c = *current++;
|
|
||||||
if ( c == '"' )
|
|
||||||
break;
|
|
||||||
else if ( c == '\\' )
|
|
||||||
{
|
|
||||||
if ( current == end )
|
|
||||||
return addError( "Empty escape sequence in string", token, current );
|
|
||||||
Char escape = *current++;
|
|
||||||
switch ( escape )
|
|
||||||
{
|
|
||||||
case '"': decoded += '"'; break;
|
|
||||||
case '/': decoded += '/'; break;
|
|
||||||
case '\\': decoded += '\\'; break;
|
|
||||||
case 'b': decoded += '\b'; break;
|
|
||||||
case 'f': decoded += '\f'; break;
|
|
||||||
case 'n': decoded += '\n'; break;
|
|
||||||
case 'r': decoded += '\r'; break;
|
|
||||||
case 't': decoded += '\t'; break;
|
|
||||||
case 'u':
|
|
||||||
{
|
|
||||||
unsigned int unicode;
|
|
||||||
if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
|
|
||||||
return false;
|
|
||||||
decoded += codePointToUTF8(unicode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return addError( "Bad escape sequence in string", token, current );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
decoded += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::decodeUnicodeCodePoint( Token &token,
|
|
||||||
Location ¤t,
|
|
||||||
Location end,
|
|
||||||
unsigned int &unicode )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
|
|
||||||
return false;
|
|
||||||
if (unicode >= 0xD800 && unicode <= 0xDBFF)
|
|
||||||
{
|
|
||||||
// surrogate pairs
|
|
||||||
if (end - current < 6)
|
|
||||||
return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
|
|
||||||
unsigned int surrogatePair;
|
|
||||||
if (*(current++) == '\\' && *(current++)== 'u')
|
|
||||||
{
|
|
||||||
if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
|
|
||||||
{
|
|
||||||
unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::decodeUnicodeEscapeSequence( Token &token,
|
|
||||||
Location ¤t,
|
|
||||||
Location end,
|
|
||||||
unsigned int &unicode )
|
|
||||||
{
|
|
||||||
if ( end - current < 4 )
|
|
||||||
return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
|
|
||||||
unicode = 0;
|
|
||||||
for ( int index =0; index < 4; ++index )
|
|
||||||
{
|
|
||||||
Char c = *current++;
|
|
||||||
unicode *= 16;
|
|
||||||
if ( c >= '0' && c <= '9' )
|
|
||||||
unicode += c - '0';
|
|
||||||
else if ( c >= 'a' && c <= 'f' )
|
|
||||||
unicode += c - 'a' + 10;
|
|
||||||
else if ( c >= 'A' && c <= 'F' )
|
|
||||||
unicode += c - 'A' + 10;
|
|
||||||
else
|
|
||||||
return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::addError( const std::string &message,
|
|
||||||
Token &token,
|
|
||||||
Location extra )
|
|
||||||
{
|
|
||||||
ErrorInfo info;
|
|
||||||
info.token_ = token;
|
|
||||||
info.message_ = message;
|
|
||||||
info.extra_ = extra;
|
|
||||||
errors_.push_back( info );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::recoverFromError( TokenType skipUntilToken )
|
|
||||||
{
|
|
||||||
int errorCount = int(errors_.size());
|
|
||||||
Token skip;
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
if ( !readToken(skip) )
|
|
||||||
errors_.resize( errorCount ); // discard errors caused by recovery
|
|
||||||
if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
errors_.resize( errorCount );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Reader::addErrorAndRecover( const std::string &message,
|
|
||||||
Token &token,
|
|
||||||
TokenType skipUntilToken )
|
|
||||||
{
|
|
||||||
addError( message, token );
|
|
||||||
return recoverFromError( skipUntilToken );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Value &
|
|
||||||
Reader::currentValue()
|
|
||||||
{
|
|
||||||
return *(nodes_.top());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Reader::Char
|
|
||||||
Reader::getNextChar()
|
|
||||||
{
|
|
||||||
if ( current_ == end_ )
|
|
||||||
return 0;
|
|
||||||
return *current_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Reader::getLocationLineAndColumn( Location location,
|
|
||||||
int &line,
|
|
||||||
int &column ) const
|
|
||||||
{
|
|
||||||
Location current = begin_;
|
|
||||||
Location lastLineStart = current;
|
|
||||||
line = 0;
|
|
||||||
while ( current < location && current != end_ )
|
|
||||||
{
|
|
||||||
Char c = *current++;
|
|
||||||
if ( c == '\r' )
|
|
||||||
{
|
|
||||||
if ( *current == '\n' )
|
|
||||||
++current;
|
|
||||||
lastLineStart = current;
|
|
||||||
++line;
|
|
||||||
}
|
|
||||||
else if ( c == '\n' )
|
|
||||||
{
|
|
||||||
lastLineStart = current;
|
|
||||||
++line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// column & line start at 1
|
|
||||||
column = int(location - lastLineStart) + 1;
|
|
||||||
++line;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string
|
|
||||||
Reader::getLocationLineAndColumn( Location location ) const
|
|
||||||
{
|
|
||||||
int line, column;
|
|
||||||
getLocationLineAndColumn( location, line, column );
|
|
||||||
char buffer[18+16+16+1];
|
|
||||||
sprintf( buffer, "Line %d, Column %d", line, column );
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string
|
|
||||||
Reader::getFormatedErrorMessages() const
|
|
||||||
{
|
|
||||||
std::string formattedMessage;
|
|
||||||
for ( Errors::const_iterator itError = errors_.begin();
|
|
||||||
itError != errors_.end();
|
|
||||||
++itError )
|
|
||||||
{
|
|
||||||
const ErrorInfo &error = *itError;
|
|
||||||
formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
|
|
||||||
formattedMessage += " " + error.message_ + "\n";
|
|
||||||
if ( error.extra_ )
|
|
||||||
formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
|
|
||||||
}
|
|
||||||
return formattedMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::istream& operator>>( std::istream &sin, Value &root )
|
|
||||||
{
|
|
||||||
Json::Reader reader;
|
|
||||||
bool ok = reader.parse(sin, root, true);
|
|
||||||
//JSON_ASSERT( ok );
|
|
||||||
//if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
|
|
||||||
return sin;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Json
|
|
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
|||||||
'overrides': '<(libjingle_orig)/source',
|
'overrides': '<(libjingle_orig)/source',
|
||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
|
'jsoncpp': '../../third_party/jsoncpp',
|
||||||
},
|
},
|
||||||
'target_defaults': {
|
'target_defaults': {
|
||||||
'defines': [
|
'defines': [
|
||||||
@ -162,6 +163,41 @@
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
'targets': [
|
'targets': [
|
||||||
|
#TODO(ronghuawu): move jsoncpp target to its own gyp
|
||||||
|
{
|
||||||
|
'target_name': 'jsoncpp',
|
||||||
|
'type': '<(library)',
|
||||||
|
'defines': [
|
||||||
|
'JSON_USE_EXCEPTION=0',
|
||||||
|
],
|
||||||
|
'sources': [
|
||||||
|
'<(jsoncpp)/include/json/assertions.h',
|
||||||
|
'<(jsoncpp)/include/json/autolink.h',
|
||||||
|
'<(jsoncpp)/include/json/config.h',
|
||||||
|
'<(jsoncpp)/include/json/features.h',
|
||||||
|
'<(jsoncpp)/include/json/forwards.h',
|
||||||
|
'<(jsoncpp)/include/json/json.h',
|
||||||
|
'<(jsoncpp)/include/json/reader.h',
|
||||||
|
'<(jsoncpp)/include/json/value.h',
|
||||||
|
'<(jsoncpp)/include/json/writer.h',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_batchallocator.h',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_internalarray.inl',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_internalmap.inl',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_reader.cpp',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_tool.h',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_value.cpp',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_valueiterator.inl',
|
||||||
|
'<(jsoncpp)/src/lib_json/json_writer.cpp',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'<(jsoncpp)/include/',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': [
|
||||||
|
'<(jsoncpp)/include/',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'target_name': 'libjingle',
|
'target_name': 'libjingle',
|
||||||
'type': 'static_library',
|
'type': 'static_library',
|
||||||
@ -385,7 +421,7 @@
|
|||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'../../third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
'jsoncpp',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
# This has to be is a separate project due to a bug in MSVS:
|
# This has to be is a separate project due to a bug in MSVS:
|
||||||
@ -573,7 +609,7 @@
|
|||||||
'<(libjingle_mods)/source/talk/app/webrtc/webrtc_json.h',
|
'<(libjingle_mods)/source/talk/app/webrtc/webrtc_json.h',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'../../third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
'jsoncpp',
|
||||||
],
|
],
|
||||||
'conditions': [
|
'conditions': [
|
||||||
['inside_chromium_build==1', {
|
['inside_chromium_build==1', {
|
||||||
|
@ -451,7 +451,7 @@ bool ParseICECandidates(const Json::Value& value,
|
|||||||
std::vector<Json::Value> ReadValues(
|
std::vector<Json::Value> ReadValues(
|
||||||
const Json::Value& value, const std::string& key) {
|
const Json::Value& value, const std::string& key) {
|
||||||
std::vector<Json::Value> objects;
|
std::vector<Json::Value> objects;
|
||||||
for (size_t i = 0; i < value[key].size(); ++i) {
|
for (Json::ArrayIndex i = 0; i < value[key].size(); ++i) {
|
||||||
objects.push_back(value[key][i]);
|
objects.push_back(value[key][i]);
|
||||||
}
|
}
|
||||||
return objects;
|
return objects;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user