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:
Nik Bougalis
2014-09-29 12:45:42 -07:00
committed by Tom Ritchford
parent 6d91d02c62
commit 558c6b621b
21 changed files with 100 additions and 3167 deletions

View File

@@ -2012,12 +2012,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\json\impl\json_assert.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\impl\json_batchallocator.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\impl\json_internalarray.inl">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\impl\json_internalmap.inl">
</ClInclude>
<ClCompile Include="..\..\src\ripple\json\impl\json_reader.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
@@ -2034,10 +2028,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\json\JsonPropertyStream.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_config.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_features.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_forwards.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_reader.h">

View File

@@ -2952,15 +2952,6 @@
<ClInclude Include="..\..\src\ripple\json\impl\json_assert.h">
<Filter>ripple\json\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\impl\json_batchallocator.h">
<Filter>ripple\json\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\impl\json_internalarray.inl">
<Filter>ripple\json\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\impl\json_internalmap.inl">
<Filter>ripple\json\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\json\impl\json_reader.cpp">
<Filter>ripple\json\impl</Filter>
</ClCompile>
@@ -2979,12 +2970,6 @@
<ClInclude Include="..\..\src\ripple\json\JsonPropertyStream.h">
<Filter>ripple\json</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_config.h">
<Filter>ripple\json</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_features.h">
<Filter>ripple\json</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\json\json_forwards.h">
<Filter>ripple\json</Filter>
</ClInclude>

View File

@@ -1074,7 +1074,7 @@ bool ApplicationImp::loadOldLedger (
{
Json::Reader reader;
Json::Value jLedger;
if (!reader.parse (ledgerFile, jLedger, false))
if (!reader.parse (ledgerFile, jLedger))
m_journal.fatal << "Unable to parse ledger JSON";
else
{

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_JSON_JSONPROPERTYSTREAM_H_INCLUDED
#define RIPPLE_JSON_JSONPROPERTYSTREAM_H_INCLUDED
#include <ripple/json/json_config.h>
#include <beast/utility/PropertyStream.h>
namespace ripple {

View File

@@ -1,41 +0,0 @@
//------------------------------------------------------------------------------
/*
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 RIPPLE_JSON_JSON_AUTOLINK_H_INCLUDED
#define RIPPLE_JSON_JSON_AUTOLINK_H_INCLUDED
// VFALCO TODO remove this file
#error This file is deprecated!
# include "config.h"
# ifdef JSON_IN_CPPTL
# include <cpptl/cpptl_autolink.h>
# endif
# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
# define CPPTL_AUTOLINK_NAME "json"
# undef CPPTL_AUTOLINK_DLL
# ifdef JSON_DLL
# define CPPTL_AUTOLINK_DLL
# endif
# include "autolink.h"
# endif
#endif // JSON_AUTOLINK_H_INCLUDED

View File

@@ -20,8 +20,6 @@
#ifndef RIPPLE_JSON_JSON_BATCHALLOCATOR_H_INCLUDED
#define RIPPLE_JSON_JSON_BATCHALLOCATOR_H_INCLUDED
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
namespace Json
{
@@ -139,7 +137,5 @@ private:
} // namespace Json
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED

View File

@@ -1,497 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// included by json_value.cpp
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueInternalArray
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueArrayAllocator::~ValueArrayAllocator ()
{
}
// //////////////////////////////////////////////////////////////////
// class DefaultValueArrayAllocator
// //////////////////////////////////////////////////////////////////
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
class DefaultValueArrayAllocator : public ValueArrayAllocator
{
public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator ()
{
}
virtual ValueInternalArray* newArray ()
{
return new ValueInternalArray ();
}
virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other )
{
return new ValueInternalArray ( other );
}
virtual void destructArray ( ValueInternalArray* array )
{
delete array;
}
virtual void reallocateArrayPageIndex ( Value**& indexes,
ValueInternalArray::PageIndex& indexCount,
ValueInternalArray::PageIndex minNewIndexCount )
{
ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void* newIndexes = realloc ( indexes, sizeof (Value*) * newIndexCount );
if ( !newIndexes )
throw std::bad_alloc ();
indexCount = newIndexCount;
indexes = static_cast<Value**> ( newIndexes );
}
virtual void releaseArrayPageIndex ( Value** indexes,
ValueInternalArray::PageIndex indexCount )
{
if ( indexes )
free ( indexes );
}
virtual Value* allocateArrayPage ()
{
return static_cast<Value*> ( malloc ( sizeof (Value) * ValueInternalArray::itemsPerPage ) );
}
virtual void releaseArrayPage ( Value* value )
{
if ( value )
free ( value );
}
};
#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
/// @todo make this thread-safe (lock when accessign batch allocator)
class DefaultValueArrayAllocator : public ValueArrayAllocator
{
public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator ()
{
}
virtual ValueInternalArray* newArray ()
{
ValueInternalArray* array = arraysAllocator_.allocate ();
new (array) ValueInternalArray (); // placement new
return array;
}
virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other )
{
ValueInternalArray* array = arraysAllocator_.allocate ();
new (array) ValueInternalArray ( other ); // placement new
return array;
}
virtual void destructArray ( ValueInternalArray* array )
{
if ( array )
{
array->~ValueInternalArray ();
arraysAllocator_.release ( array );
}
}
virtual void reallocateArrayPageIndex ( Value**& indexes,
ValueInternalArray::PageIndex& indexCount,
ValueInternalArray::PageIndex minNewIndexCount )
{
ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void* newIndexes = realloc ( indexes, sizeof (Value*) * newIndexCount );
if ( !newIndexes )
throw std::bad_alloc ();
indexCount = newIndexCount;
indexes = static_cast<Value**> ( newIndexes );
}
virtual void releaseArrayPageIndex ( Value** indexes,
ValueInternalArray::PageIndex indexCount )
{
if ( indexes )
free ( indexes );
}
virtual Value* allocateArrayPage ()
{
return static_cast<Value*> ( pagesAllocator_.allocate () );
}
virtual void releaseArrayPage ( Value* value )
{
if ( value )
pagesAllocator_.release ( value );
}
private:
BatchAllocator<ValueInternalArray, 1> arraysAllocator_;
BatchAllocator<Value, ValueInternalArray::itemsPerPage> pagesAllocator_;
};
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
static ValueArrayAllocator*& arrayAllocator ()
{
static DefaultValueArrayAllocator defaultAllocator;
static ValueArrayAllocator* arrayAllocator = &defaultAllocator;
return arrayAllocator;
}
static struct DummyArrayAllocatorInitializer
{
DummyArrayAllocatorInitializer ()
{
arrayAllocator (); // ensure arrayAllocator() statics are initialized before main().
}
} dummyArrayAllocatorInitializer;
// //////////////////////////////////////////////////////////////////
// class ValueInternalArray
// //////////////////////////////////////////////////////////////////
bool
ValueInternalArray::equals ( const IteratorState& x,
const IteratorState& other )
{
return x.array_ == other.array_
&& x.currentItemIndex_ == other.currentItemIndex_
&& x.currentPageIndex_ == other.currentPageIndex_;
}
void
ValueInternalArray::increment ( IteratorState& it )
{
JSON_ASSERT_MESSAGE ( it.array_ &&
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
!= it.array_->size_,
"ValueInternalArray::increment(): moving iterator beyond end" );
++ (it.currentItemIndex_);
if ( it.currentItemIndex_ == itemsPerPage )
{
it.currentItemIndex_ = 0;
++ (it.currentPageIndex_);
}
}
void
ValueInternalArray::decrement ( IteratorState& it )
{
JSON_ASSERT_MESSAGE ( it.array_ && it.currentPageIndex_ == it.array_->pages_
&& it.currentItemIndex_ == 0,
"ValueInternalArray::decrement(): moving iterator beyond end" );
if ( it.currentItemIndex_ == 0 )
{
it.currentItemIndex_ = itemsPerPage - 1;
-- (it.currentPageIndex_);
}
else
{
-- (it.currentItemIndex_);
}
}
Value&
ValueInternalArray::unsafeDereference ( const IteratorState& it )
{
return (* (it.currentPageIndex_))[it.currentItemIndex_];
}
Value&
ValueInternalArray::dereference ( const IteratorState& it )
{
JSON_ASSERT_MESSAGE ( it.array_ &&
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
< it.array_->size_,
"ValueInternalArray::dereference(): dereferencing invalid iterator" );
return unsafeDereference ( it );
}
void
ValueInternalArray::makeBeginIterator ( IteratorState& it ) const
{
it.array_ = const_cast<ValueInternalArray*> ( this );
it.currentItemIndex_ = 0;
it.currentPageIndex_ = pages_;
}
void
ValueInternalArray::makeIterator ( IteratorState& it, ArrayIndex index ) const
{
it.array_ = const_cast<ValueInternalArray*> ( this );
it.currentItemIndex_ = index % itemsPerPage;
it.currentPageIndex_ = pages_ + index / itemsPerPage;
}
void
ValueInternalArray::makeEndIterator ( IteratorState& it ) const
{
makeIterator ( it, size_ );
}
ValueInternalArray::ValueInternalArray ()
: pages_ ( 0 )
, size_ ( 0 )
, pageCount_ ( 0 )
{
}
ValueInternalArray::ValueInternalArray ( const ValueInternalArray& other )
: pages_ ( 0 )
, pageCount_ ( 0 )
, size_ ( other.size_ )
{
PageIndex minNewPages = other.size_ / itemsPerPage;
arrayAllocator ()->reallocateArrayPageIndex ( pages_, pageCount_, minNewPages );
JSON_ASSERT_MESSAGE ( pageCount_ >= minNewPages,
"ValueInternalArray::reserve(): bad reallocation" );
IteratorState itOther;
other.makeBeginIterator ( itOther );
Value* value;
for ( ArrayIndex index = 0; index < size_; ++index, increment (itOther) )
{
if ( index % itemsPerPage == 0 )
{
PageIndex pageIndex = index / itemsPerPage;
value = arrayAllocator ()->allocateArrayPage ();
pages_[pageIndex] = value;
}
new (value) Value ( dereference ( itOther ) );
}
}
ValueInternalArray&
ValueInternalArray::operator = ( const ValueInternalArray& other )
{
ValueInternalArray temp ( other );
swap ( temp );
return *this;
}
ValueInternalArray::~ValueInternalArray ()
{
// destroy all constructed items
IteratorState it;
IteratorState itEnd;
makeBeginIterator ( it);
makeEndIterator ( itEnd );
for ( ; !equals (it, itEnd); increment (it) )
{
Value* value = &dereference (it);
value->~Value ();
}
// release all pages
PageIndex lastPageIndex = size_ / itemsPerPage;
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
arrayAllocator ()->releaseArrayPage ( pages_[pageIndex] );
// release pages index
arrayAllocator ()->releaseArrayPageIndex ( pages_, pageCount_ );
}
void
ValueInternalArray::swap ( ValueInternalArray& other )
{
Value** tempPages = pages_;
pages_ = other.pages_;
other.pages_ = tempPages;
ArrayIndex tempSize = size_;
size_ = other.size_;
other.size_ = tempSize;
PageIndex tempPageCount = pageCount_;
pageCount_ = other.pageCount_;
other.pageCount_ = tempPageCount;
}
void
ValueInternalArray::clear ()
{
ValueInternalArray dummy;
swap ( dummy );
}
void
ValueInternalArray::resize ( ArrayIndex newSize )
{
if ( newSize == 0 )
clear ();
else if ( newSize < size_ )
{
IteratorState it;
IteratorState itEnd;
makeIterator ( it, newSize );
makeIterator ( itEnd, size_ );
for ( ; !equals (it, itEnd); increment (it) )
{
Value* value = &dereference (it);
value->~Value ();
}
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
PageIndex lastPageIndex = size_ / itemsPerPage;
for ( ; pageIndex < lastPageIndex; ++pageIndex )
arrayAllocator ()->releaseArrayPage ( pages_[pageIndex] );
size_ = newSize;
}
else if ( newSize > size_ )
resolveReference ( newSize );
}
void
ValueInternalArray::makeIndexValid ( ArrayIndex index )
{
// Need to enlarge page index ?
if ( index >= pageCount_ * itemsPerPage )
{
PageIndex minNewPages = (index + 1) / itemsPerPage;
arrayAllocator ()->reallocateArrayPageIndex ( pages_, pageCount_, minNewPages );
JSON_ASSERT_MESSAGE ( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
}
// Need to allocate new pages ?
ArrayIndex nextPageIndex =
(size_ % itemsPerPage) != 0 ? size_ - (size_ % itemsPerPage) + itemsPerPage
: size_;
if ( nextPageIndex <= index )
{
PageIndex pageIndex = nextPageIndex / itemsPerPage;
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
for ( ; pageToAllocate-- > 0; ++pageIndex )
pages_[pageIndex] = arrayAllocator ()->allocateArrayPage ();
}
// Initialize all new entries
IteratorState it;
IteratorState itEnd;
makeIterator ( it, size_ );
size_ = index + 1;
makeIterator ( itEnd, size_ );
for ( ; !equals (it, itEnd); increment (it) )
{
Value* value = &dereference (it);
new (value) Value (); // Construct a default value using placement new
}
}
Value&
ValueInternalArray::resolveReference ( ArrayIndex index )
{
if ( index >= size_ )
makeIndexValid ( index );
return pages_[index / itemsPerPage][index % itemsPerPage];
}
Value*
ValueInternalArray::find ( ArrayIndex index ) const
{
if ( index >= size_ )
return 0;
return & (pages_[index / itemsPerPage][index % itemsPerPage]);
}
ValueInternalArray::ArrayIndex
ValueInternalArray::size () const
{
return size_;
}
int
ValueInternalArray::distance ( const IteratorState& x, const IteratorState& y )
{
return indexOf (y) - indexOf (x);
}
ValueInternalArray::ArrayIndex
ValueInternalArray::indexOf ( const IteratorState& iterator )
{
if ( !iterator.array_ )
return ArrayIndex (-1);
return ArrayIndex (
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
+ iterator.currentItemIndex_ );
}
int
ValueInternalArray::compare ( const ValueInternalArray& other ) const
{
int sizeDiff ( size_ - other.size_ );
if ( sizeDiff != 0 )
return sizeDiff;
for ( ArrayIndex index = 0; index < size_; ++index )
{
int diff = pages_[index / itemsPerPage][index % itemsPerPage].compare (
other.pages_[index / itemsPerPage][index % itemsPerPage] );
if ( diff != 0 )
return diff;
}
return 0;
}

View File

@@ -1,671 +0,0 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// included by json_value.cpp
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueInternalMap
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
* This optimization is used by the fast allocator.
*/
ValueInternalLink::ValueInternalLink ()
: previous_ ( 0 )
, next_ ( 0 )
{
}
ValueInternalLink::~ValueInternalLink ()
{
for ( int index = 0; index < itemPerLink; ++index )
{
if ( !items_[index].isItemAvailable () )
{
if ( !items_[index].isMemberNameStatic () )
free ( keys_[index] );
}
else
break;
}
}
ValueMapAllocator::~ValueMapAllocator ()
{
}
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
class DefaultValueMapAllocator : public ValueMapAllocator
{
public: // overridden from ValueMapAllocator
virtual ValueInternalMap* newMap ()
{
return new ValueInternalMap ();
}
virtual ValueInternalMap* newMapCopy ( const ValueInternalMap& other )
{
return new ValueInternalMap ( other );
}
virtual void destructMap ( ValueInternalMap* map )
{
delete map;
}
virtual ValueInternalLink* allocateMapBuckets ( unsigned int size )
{
return new ValueInternalLink[size];
}
virtual void releaseMapBuckets ( ValueInternalLink* links )
{
delete [] links;
}
virtual ValueInternalLink* allocateMapLink ()
{
return new ValueInternalLink ();
}
virtual void releaseMapLink ( ValueInternalLink* link )
{
delete link;
}
};
#else
/// @todo make this thread-safe (lock when accessign batch allocator)
class DefaultValueMapAllocator : public ValueMapAllocator
{
public: // overridden from ValueMapAllocator
virtual ValueInternalMap* newMap ()
{
ValueInternalMap* map = mapsAllocator_.allocate ();
new (map) ValueInternalMap (); // placement new
return map;
}
virtual ValueInternalMap* newMapCopy ( const ValueInternalMap& other )
{
ValueInternalMap* map = mapsAllocator_.allocate ();
new (map) ValueInternalMap ( other ); // placement new
return map;
}
virtual void destructMap ( ValueInternalMap* map )
{
if ( map )
{
map->~ValueInternalMap ();
mapsAllocator_.release ( map );
}
}
virtual ValueInternalLink* allocateMapBuckets ( unsigned int size )
{
return new ValueInternalLink[size];
}
virtual void releaseMapBuckets ( ValueInternalLink* links )
{
delete [] links;
}
virtual ValueInternalLink* allocateMapLink ()
{
ValueInternalLink* link = linksAllocator_.allocate ();
memset ( link, 0, sizeof (ValueInternalLink) );
return link;
}
virtual void releaseMapLink ( ValueInternalLink* link )
{
link->~ValueInternalLink ();
linksAllocator_.release ( link );
}
private:
BatchAllocator<ValueInternalMap, 1> mapsAllocator_;
BatchAllocator<ValueInternalLink, 1> linksAllocator_;
};
#endif
static ValueMapAllocator*& mapAllocator ()
{
static DefaultValueMapAllocator defaultAllocator;
static ValueMapAllocator* mapAllocator = &defaultAllocator;
return mapAllocator;
}
static struct DummyMapAllocatorInitializer
{
DummyMapAllocatorInitializer ()
{
mapAllocator (); // ensure mapAllocator() statics are initialized before main().
}
} dummyMapAllocatorInitializer;
// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
/*
use linked list hash map.
buckets array is a container.
linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
value have extra state: valid, available, deleted
*/
ValueInternalMap::ValueInternalMap ()
: buckets_ ( 0 )
, tailLink_ ( 0 )
, bucketsSize_ ( 0 )
, itemCount_ ( 0 )
{
}
ValueInternalMap::ValueInternalMap ( const ValueInternalMap& other )
: buckets_ ( 0 )
, tailLink_ ( 0 )
, bucketsSize_ ( 0 )
, itemCount_ ( 0 )
{
reserve ( other.itemCount_ );
IteratorState it;
IteratorState itEnd;
other.makeBeginIterator ( it );
other.makeEndIterator ( itEnd );
for ( ; !equals (it, itEnd); increment (it) )
{
bool isStatic;
const char* memberName = key ( it, isStatic );
const Value& aValue = value ( it );
resolveReference (memberName, isStatic) = aValue;
}
}
ValueInternalMap&
ValueInternalMap::operator = ( const ValueInternalMap& other )
{
ValueInternalMap dummy ( other );
swap ( dummy );
return *this;
}
ValueInternalMap::~ValueInternalMap ()
{
if ( buckets_ )
{
for ( BucketIndex bucketIndex = 0; bucketIndex < bucketsSize_; ++bucketIndex )
{
ValueInternalLink* link = buckets_[bucketIndex].next_;
while ( link )
{
ValueInternalLink* linkToRelease = link;
link = link->next_;
mapAllocator ()->releaseMapLink ( linkToRelease );
}
}
mapAllocator ()->releaseMapBuckets ( buckets_ );
}
}
void
ValueInternalMap::swap ( ValueInternalMap& other ) noexcept
{
ValueInternalLink* tempBuckets = buckets_;
buckets_ = other.buckets_;
other.buckets_ = tempBuckets;
ValueInternalLink* tempTailLink = tailLink_;
tailLink_ = other.tailLink_;
other.tailLink_ = tempTailLink;
BucketIndex tempBucketsSize = bucketsSize_;
bucketsSize_ = other.bucketsSize_;
other.bucketsSize_ = tempBucketsSize;
BucketIndex tempItemCount = itemCount_;
itemCount_ = other.itemCount_;
other.itemCount_ = tempItemCount;
}
void
ValueInternalMap::clear ()
{
ValueInternalMap dummy;
swap ( dummy );
}
ValueInternalMap::BucketIndex
ValueInternalMap::size () const
{
return itemCount_;
}
bool
ValueInternalMap::reserveDelta ( BucketIndex growth )
{
return reserve ( itemCount_ + growth );
}
bool
ValueInternalMap::reserve ( BucketIndex newItemCount )
{
if ( !buckets_ && newItemCount > 0 )
{
buckets_ = mapAllocator ()->allocateMapBuckets ( 1 );
bucketsSize_ = 1;
tailLink_ = &buckets_[0];
}
// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
return true;
}
const Value*
ValueInternalMap::find ( const char* key ) const
{
if ( !bucketsSize_ )
return 0;
HashKey hashedKey = hash ( key );
BucketIndex bucketIndex = hashedKey % bucketsSize_;
for ( const ValueInternalLink* current = &buckets_[bucketIndex];
current != 0;
current = current->next_ )
{
for ( BucketIndex index = 0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( current->items_[index].isItemAvailable () )
return 0;
if ( strcmp ( key, current->keys_[index] ) == 0 )
return &current->items_[index];
}
}
return 0;
}
Value*
ValueInternalMap::find ( const char* key )
{
const ValueInternalMap* constThis = this;
return const_cast<Value*> ( constThis->find ( key ) );
}
Value&
ValueInternalMap::resolveReference ( const char* key,
bool isStatic )
{
HashKey hashedKey = hash ( key );
if ( bucketsSize_ )
{
BucketIndex bucketIndex = hashedKey % bucketsSize_;
ValueInternalLink** previous = 0;
BucketIndex index;
for ( ValueInternalLink* current = &buckets_[bucketIndex];
current != 0;
previous = &current->next_, current = current->next_ )
{
for ( index = 0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( current->items_[index].isItemAvailable () )
return setNewItem ( key, isStatic, current, index );
if ( strcmp ( key, current->keys_[index] ) == 0 )
return current->items_[index];
}
}
}
reserveDelta ( 1 );
return unsafeAdd ( key, isStatic, hashedKey );
}
void
ValueInternalMap::remove ( const char* key )
{
HashKey hashedKey = hash ( key );
if ( !bucketsSize_ )
return;
BucketIndex bucketIndex = hashedKey % bucketsSize_;
for ( ValueInternalLink* link = &buckets_[bucketIndex];
link != 0;
link = link->next_ )
{
BucketIndex index;
for ( index = 0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( link->items_[index].isItemAvailable () )
return;
if ( strcmp ( key, link->keys_[index] ) == 0 )
{
doActualRemove ( link, index, bucketIndex );
return;
}
}
}
}
void
ValueInternalMap::doActualRemove ( ValueInternalLink* link,
BucketIndex index,
BucketIndex bucketIndex )
{
// find last item of the bucket and swap it with the 'removed' one.
// set removed items flags to 'available'.
// if last page only contains 'available' items, then desallocate it (it's empty)
ValueInternalLink*& lastLink = getLastLinkInBucket ( index );
BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
for ( ;
lastItemIndex < ValueInternalLink::itemPerLink;
++lastItemIndex ) // may be optimized with dicotomic search
{
if ( lastLink->items_[lastItemIndex].isItemAvailable () )
break;
}
BucketIndex lastUsedIndex = lastItemIndex - 1;
Value* valueToDelete = &link->items_[index];
Value* valueToPreserve = &lastLink->items_[lastUsedIndex];
if ( valueToDelete != valueToPreserve )
valueToDelete->swap ( *valueToPreserve );
if ( lastUsedIndex == 0 ) // page is now empty
{
// remove it from bucket linked list and delete it.
ValueInternalLink* linkPreviousToLast = lastLink->previous_;
if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
{
mapAllocator ()->releaseMapLink ( lastLink );
linkPreviousToLast->next_ = 0;
lastLink = linkPreviousToLast;
}
}
else
{
Value dummy;
valueToPreserve->swap ( dummy ); // restore deleted to default Value.
valueToPreserve->setItemUsed ( false );
}
--itemCount_;
}
ValueInternalLink*&
ValueInternalMap::getLastLinkInBucket ( BucketIndex bucketIndex )
{
if ( bucketIndex == bucketsSize_ - 1 )
return tailLink_;
ValueInternalLink*& previous = buckets_[bucketIndex + 1].previous_;
if ( !previous )
previous = &buckets_[bucketIndex];
return previous;
}
Value&
ValueInternalMap::setNewItem ( const char* key,
bool isStatic,
ValueInternalLink* link,
BucketIndex index )
{
char* duplicatedKey = valueAllocator ()->makeMemberName ( key );
++itemCount_;
link->keys_[index] = duplicatedKey;
link->items_[index].setItemUsed ();
link->items_[index].setMemberNameIsStatic ( isStatic );
return link->items_[index]; // items already default constructed.
}
Value&
ValueInternalMap::unsafeAdd ( const char* key,
bool isStatic,
HashKey hashedKey )
{
JSON_ASSERT_MESSAGE ( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
BucketIndex bucketIndex = hashedKey % bucketsSize_;
ValueInternalLink*& previousLink = getLastLinkInBucket ( bucketIndex );
ValueInternalLink* link = previousLink;
BucketIndex index;
for ( index = 0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( link->items_[index].isItemAvailable () )
break;
}
if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
{
ValueInternalLink* newLink = mapAllocator ()->allocateMapLink ();
index = 0;
link->next_ = newLink;
previousLink = newLink;
link = newLink;
}
return setNewItem ( key, isStatic, link, index );
}
ValueInternalMap::HashKey
ValueInternalMap::hash ( const char* key ) const
{
HashKey hash = 0;
while ( *key )
hash += *key++ * 37;
return hash;
}
int
ValueInternalMap::compare ( const ValueInternalMap& other ) const
{
int sizeDiff ( itemCount_ - other.itemCount_ );
if ( sizeDiff != 0 )
return sizeDiff;
// Strict order guaranty is required. Compare all keys FIRST, then compare values.
IteratorState it;
IteratorState itEnd;
makeBeginIterator ( it );
makeEndIterator ( itEnd );
for ( ; !equals (it, itEnd); increment (it) )
{
if ( !other.find ( key ( it ) ) )
return 1;
}
// All keys are equals, let's compare values
makeBeginIterator ( it );
for ( ; !equals (it, itEnd); increment (it) )
{
const Value* otherValue = other.find ( key ( it ) );
int valueDiff = value (it).compare ( *otherValue );
if ( valueDiff != 0 )
return valueDiff;
}
return 0;
}
void
ValueInternalMap::makeBeginIterator ( IteratorState& it ) const
{
it.map_ = const_cast<ValueInternalMap*> ( this );
it.bucketIndex_ = 0;
it.itemIndex_ = 0;
it.link_ = buckets_;
}
void
ValueInternalMap::makeEndIterator ( IteratorState& it ) const
{
it.map_ = const_cast<ValueInternalMap*> ( this );
it.bucketIndex_ = bucketsSize_;
it.itemIndex_ = 0;
it.link_ = 0;
}
bool
ValueInternalMap::equals ( const IteratorState& x, const IteratorState& other )
{
return x.map_ == other.map_
&& x.bucketIndex_ == other.bucketIndex_
&& x.link_ == other.link_
&& x.itemIndex_ == other.itemIndex_;
}
void
ValueInternalMap::incrementBucket ( IteratorState& iterator )
{
++iterator.bucketIndex_;
JSON_ASSERT_MESSAGE ( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
"ValueInternalMap::increment(): attempting to iterate beyond end." );
if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
iterator.link_ = 0;
else
iterator.link_ = & (iterator.map_->buckets_[iterator.bucketIndex_]);
iterator.itemIndex_ = 0;
}
void
ValueInternalMap::increment ( IteratorState& iterator )
{
JSON_ASSERT_MESSAGE ( iterator.map_, "Attempting to iterator using invalid iterator." );
++iterator.itemIndex_;
if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
{
JSON_ASSERT_MESSAGE ( iterator.link_ != 0,
"ValueInternalMap::increment(): attempting to iterate beyond end." );
iterator.link_ = iterator.link_->next_;
if ( iterator.link_ == 0 )
incrementBucket ( iterator );
}
else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable () )
{
incrementBucket ( iterator );
}
}
void
ValueInternalMap::decrement ( IteratorState& iterator )
{
if ( iterator.itemIndex_ == 0 )
{
JSON_ASSERT_MESSAGE ( iterator.map_, "Attempting to iterate using invalid iterator." );
if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
{
JSON_ASSERT_MESSAGE ( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
-- (iterator.bucketIndex_);
}
iterator.link_ = iterator.link_->previous_;
iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
}
}
const char*
ValueInternalMap::key ( const IteratorState& iterator )
{
JSON_ASSERT_MESSAGE ( iterator.link_, "Attempting to iterate using invalid iterator." );
return iterator.link_->keys_[iterator.itemIndex_];
}
const char*
ValueInternalMap::key ( const IteratorState& iterator, bool& isStatic )
{
JSON_ASSERT_MESSAGE ( iterator.link_, "Attempting to iterate using invalid iterator." );
isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic ();
return iterator.link_->keys_[iterator.itemIndex_];
}
Value&
ValueInternalMap::value ( const IteratorState& iterator )
{
JSON_ASSERT_MESSAGE ( iterator.link_, "Attempting to iterate using invalid iterator." );
return iterator.link_->items_[iterator.itemIndex_];
}
int
ValueInternalMap::distance ( const IteratorState& x, const IteratorState& y )
{
int offset = 0;
IteratorState it = x;
while ( !equals ( it, y ) )
increment ( it );
return offset;
}

View File

@@ -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,11 +121,6 @@ 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 () )
{
// Set error location to start of doc, ideally should be first token found in doc
@@ -202,12 +131,10 @@ Reader::parse ( const char* beginDoc, const char* endDoc,
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_ = &currentValue ();
}
return successful;
}
@@ -269,18 +187,11 @@ Reader::readValue ()
void
Reader::skipCommentTokens ( Token& token )
{
if ( features_.allowComments_ )
{
do
{
readToken ( token );
}
while ( token.type_ == tokenComment );
}
else
{
readToken ( token );
}
}
@@ -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 ( c == '/' )
return 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 ()
{
@@ -503,18 +373,36 @@ Reader::readCppStyleComment ()
return true;
}
void
Reader::TokenType
Reader::readNumber ()
{
static char const extended_tokens[] = { '.', 'e', 'E', '+', '-' };
TokenType type = tokenInteger;
if ( current_ != end_ )
{
if (*current_ == '-')
++current_;
while ( current_ != end_ )
{
if ( ! (*current_ >= '0' && *current_ <= '9') &&
!in ( *current_, '.', 'e', 'E', '+', '-' ) )
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 ());

File diff suppressed because it is too large Load Diff

View File

@@ -30,95 +30,41 @@
// //////////////////////////////////////////////////////////////////
ValueIteratorBase::ValueIteratorBase ()
#ifndef JSON_VALUE_USE_INTERNAL_MAP
: current_ ()
, isNull_ ( true )
{
}
#else
:
isArray_ ( true )
, isNull_ ( true )
{
iterator_.array_ = ValueInternalArray::IteratorState ();
}
#endif
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIteratorBase::ValueIteratorBase ( const Value::ObjectValues::iterator& current )
: current_ ( current )
, isNull_ ( false )
{
}
#else
ValueIteratorBase::ValueIteratorBase ( const ValueInternalArray::IteratorState& state )
: isArray_ ( true )
{
iterator_.array_ = state;
}
ValueIteratorBase::ValueIteratorBase ( const ValueInternalMap::IteratorState& state )
: isArray_ ( false )
{
iterator_.map_ = state;
}
#endif
Value&
ValueIteratorBase::deref () const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
return current_->second;
#else
if ( isArray_ )
return ValueInternalArray::dereference ( iterator_.array_ );
return ValueInternalMap::value ( iterator_.map_ );
#endif
}
void
ValueIteratorBase::increment ()
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
++current_;
#else
if ( isArray_ )
ValueInternalArray::increment ( iterator_.array_ );
ValueInternalMap::increment ( iterator_.map_ );
#endif
}
void
ValueIteratorBase::decrement ()
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
--current_;
#else
if ( isArray_ )
ValueInternalArray::decrement ( iterator_.array_ );
ValueInternalMap::decrement ( iterator_.map_ );
#endif
}
ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance ( const SelfType& other ) const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
# ifdef JSON_USE_CPPTL_SMALLMAP
return current_ - other.current_;
# else
// Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default
// std::map::iterator. As begin() and end() are two instance
@@ -142,57 +88,31 @@ ValueIteratorBase::computeDistance ( const SelfType& other ) const
}
return myDistance;
# endif
#else
if ( isArray_ )
return ValueInternalArray::distance ( iterator_.array_, other.iterator_.array_ );
return ValueInternalMap::distance ( iterator_.map_, other.iterator_.map_ );
#endif
}
bool
ValueIteratorBase::isEqual ( const SelfType& other ) const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
if ( isNull_ )
{
return other.isNull_;
}
return current_ == other.current_;
#else
if ( isArray_ )
return ValueInternalArray::equals ( iterator_.array_, other.iterator_.array_ );
return ValueInternalMap::equals ( iterator_.map_, other.iterator_.map_ );
#endif
}
void
ValueIteratorBase::copy ( const SelfType& other )
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
current_ = other.current_;
#else
if ( isArray_ )
iterator_.array_ = other.iterator_.array_;
iterator_.map_ = other.iterator_.map_;
#endif
}
Value
ValueIteratorBase::key () const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first;
if ( czstring.c_str () )
@@ -204,55 +124,26 @@ ValueIteratorBase::key () const
}
return Value ( czstring.index () );
#else
if ( isArray_ )
return Value ( ValueInternalArray::indexOf ( iterator_.array_ ) );
bool isStatic;
const char* memberName = ValueInternalMap::key ( iterator_.map_, isStatic );
if ( isStatic )
return Value ( StaticString ( memberName ) );
return Value ( memberName );
#endif
}
UInt
ValueIteratorBase::index () const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first;
if ( !czstring.c_str () )
return czstring.index ();
return Value::UInt ( -1 );
#else
if ( isArray_ )
return Value::UInt ( ValueInternalArray::indexOf ( iterator_.array_ ) );
return Value::UInt ( -1 );
#endif
}
const char*
ValueIteratorBase::memberName () const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
const char* name = (*current_).first.c_str ();
return name ? name : "";
#else
if ( !isArray_ )
return ValueInternalMap::key ( iterator_.map_ );
return "";
#endif
}
@@ -268,23 +159,10 @@ ValueConstIterator::ValueConstIterator ()
{
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueConstIterator::ValueConstIterator ( const Value::ObjectValues::iterator& current )
: ValueIteratorBase ( current )
{
}
#else
ValueConstIterator::ValueConstIterator ( const ValueInternalArray::IteratorState& state )
: ValueIteratorBase ( state )
{
}
ValueConstIterator::ValueConstIterator ( const ValueInternalMap::IteratorState& state )
: ValueIteratorBase ( state )
{
}
#endif
ValueConstIterator&
ValueConstIterator::operator = ( const ValueIteratorBase& other )
@@ -307,22 +185,10 @@ ValueIterator::ValueIterator ()
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIterator::ValueIterator ( const Value::ObjectValues::iterator& current )
: ValueIteratorBase ( current )
{
}
#else
ValueIterator::ValueIterator ( const ValueInternalArray::IteratorState& state )
: ValueIteratorBase ( state )
{
}
ValueIterator::ValueIterator ( const ValueInternalMap::IteratorState& state )
: ValueIteratorBase ( state )
{
}
#endif
ValueIterator::ValueIterator ( const ValueConstIterator& other )
: ValueIteratorBase ( other )

View File

@@ -189,18 +189,9 @@ Writer::~Writer ()
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter ()
: yamlCompatiblityEnabled_ ( false )
{
}
void
FastWriter::enableYAMLCompatibility ()
{
yamlCompatiblityEnabled_ = true;
}
std::string
FastWriter::write ( const Value& root )
{
@@ -272,8 +263,7 @@ FastWriter::writeValue ( const Value& value )
document_ += ",";
document_ += valueToQuotedString ( name.c_str () );
document_ += yamlCompatiblityEnabled_ ? ": "
: ":";
document_ += ":";
writeValue ( value[name] );
}
@@ -300,9 +290,7 @@ StyledWriter::write ( const Value& root )
document_ = "";
addChildValues_ = false;
indentString_ = "";
writeCommentBeforeValue ( root );
writeValue ( root );
writeCommentAfterValueOnSameLine ( root );
document_ += "\n";
return document_;
}
@@ -357,19 +345,14 @@ StyledWriter::writeValue ( const Value& value )
{
std::string const& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue ( childValue );
writeWithIndent ( valueToQuotedString ( name.c_str () ) );
document_ += " : ";
writeValue ( childValue );
if ( ++it == members.end () )
{
writeCommentAfterValueOnSameLine ( childValue );
break;
}
document_ += ",";
writeCommentAfterValueOnSameLine ( childValue );
}
unindent ();
@@ -402,7 +385,6 @@ StyledWriter::writeArrayValue ( const Value& value )
while ( true )
{
const Value& childValue = value[index];
writeCommentBeforeValue ( childValue );
if ( hasChildValue )
writeWithIndent ( childValues_[index] );
@@ -413,13 +395,9 @@ StyledWriter::writeArrayValue ( const Value& value )
}
if ( ++index == size )
{
writeCommentAfterValueOnSameLine ( childValue );
break;
}
document_ += ",";
writeCommentAfterValueOnSameLine ( childValue );
}
unindent ();
@@ -465,11 +443,10 @@ StyledWriter::isMultineArray ( const Value& value )
addChildValues_ = true;
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for ( int index = 0; index < size && !isMultiLine; ++index )
for ( int index = 0; index < size; ++index )
{
writeValue ( value[index] );
lineLength += int ( childValues_[index].length () );
isMultiLine = isMultiLine && hasCommentForValue ( value[index] );
}
addChildValues_ = false;
@@ -530,70 +507,6 @@ StyledWriter::unindent ()
indentString_.resize ( indentString_.size () - indentSize_ );
}
void
StyledWriter::writeCommentBeforeValue ( const Value& root )
{
if ( !root.hasComment ( commentBefore ) )
return;
document_ += normalizeEOL ( root.getComment ( commentBefore ) );
document_ += "\n";
}
void
StyledWriter::writeCommentAfterValueOnSameLine ( const Value& root )
{
if ( root.hasComment ( commentAfterOnSameLine ) )
document_ += " " + normalizeEOL ( root.getComment ( commentAfterOnSameLine ) );
if ( root.hasComment ( commentAfter ) )
{
document_ += "\n";
document_ += normalizeEOL ( root.getComment ( commentAfter ) );
document_ += "\n";
}
}
bool
StyledWriter::hasCommentForValue ( const Value& value )
{
return value.hasComment ( commentBefore )
|| value.hasComment ( commentAfterOnSameLine )
|| value.hasComment ( commentAfter );
}
std::string
StyledWriter::normalizeEOL ( std::string const& text )
{
std::string normalized;
normalized.reserve ( text.length () );
const char* begin = text.c_str ();
const char* end = begin + text.length ();
const char* current = begin;
while ( current != end )
{
char c = *current++;
if ( c == '\r' ) // mac or dos EOL
{
if ( *current == '\n' ) // convert dos EOL
++current;
normalized += '\n';
}
else // handle unix EOL & other char
normalized += c;
}
return normalized;
}
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
@@ -611,9 +524,7 @@ StyledStreamWriter::write ( std::ostream& out, const Value& root )
document_ = &out;
addChildValues_ = false;
indentString_ = "";
writeCommentBeforeValue ( root );
writeValue ( root );
writeCommentAfterValueOnSameLine ( root );
*document_ << "\n";
document_ = nullptr; // Forget the stream, for safety.
}
@@ -668,19 +579,14 @@ StyledStreamWriter::writeValue ( const Value& value )
{
std::string const& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue ( childValue );
writeWithIndent ( valueToQuotedString ( name.c_str () ) );
*document_ << " : ";
writeValue ( childValue );
if ( ++it == members.end () )
{
writeCommentAfterValueOnSameLine ( childValue );
break;
}
*document_ << ",";
writeCommentAfterValueOnSameLine ( childValue );
}
unindent ();
@@ -713,7 +619,6 @@ StyledStreamWriter::writeArrayValue ( const Value& value )
while ( true )
{
const Value& childValue = value[index];
writeCommentBeforeValue ( childValue );
if ( hasChildValue )
writeWithIndent ( childValues_[index] );
@@ -724,13 +629,9 @@ StyledStreamWriter::writeArrayValue ( const Value& value )
}
if ( ++index == size )
{
writeCommentAfterValueOnSameLine ( childValue );
break;
}
*document_ << ",";
writeCommentAfterValueOnSameLine ( childValue );
}
unindent ();
@@ -776,11 +677,10 @@ StyledStreamWriter::isMultineArray ( const Value& value )
addChildValues_ = true;
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for ( int index = 0; index < size && !isMultiLine; ++index )
for ( int index = 0; index < size; ++index )
{
writeValue ( value[index] );
lineLength += int ( childValues_[index].length () );
isMultiLine = isMultiLine && hasCommentForValue ( value[index] );
}
addChildValues_ = false;
@@ -843,69 +743,6 @@ StyledStreamWriter::unindent ()
}
void
StyledStreamWriter::writeCommentBeforeValue ( const Value& root )
{
if ( !root.hasComment ( commentBefore ) )
return;
*document_ << normalizeEOL ( root.getComment ( commentBefore ) );
*document_ << "\n";
}
void
StyledStreamWriter::writeCommentAfterValueOnSameLine ( const Value& root )
{
if ( root.hasComment ( commentAfterOnSameLine ) )
*document_ << " " + normalizeEOL ( root.getComment ( commentAfterOnSameLine ) );
if ( root.hasComment ( commentAfter ) )
{
*document_ << "\n";
*document_ << normalizeEOL ( root.getComment ( commentAfter ) );
*document_ << "\n";
}
}
bool
StyledStreamWriter::hasCommentForValue ( const Value& value )
{
return value.hasComment ( commentBefore )
|| value.hasComment ( commentAfterOnSameLine )
|| value.hasComment ( commentAfter );
}
std::string
StyledStreamWriter::normalizeEOL ( std::string const& text )
{
std::string normalized;
normalized.reserve ( text.length () );
const char* begin = text.c_str ();
const char* end = begin + text.length ();
const char* current = begin;
while ( current != end )
{
char c = *current++;
if ( c == '\r' ) // mac or dos EOL
{
if ( *current == '\n' ) // convert dos EOL
++current;
normalized += '\n';
}
else // handle unix EOL & other char
normalized += c;
}
return normalized;
}
std::ostream& operator<< ( std::ostream& sout, const Value& root )
{
Json::StyledStreamWriter writer;

View File

@@ -1,62 +0,0 @@
//------------------------------------------------------------------------------
/*
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 RIPPLE_JSON_JSON_CONFIG_H_INCLUDED
#define RIPPLE_JSON_JSON_CONFIG_H_INCLUDED
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
/// If defined, indicates that Json specific container should be used
/// (hash table & simple deque container with customizable allocator).
/// THIS FEATURE IS STILL EXPERIMENTAL!
//# define JSON_VALUE_USE_INTERNAL_MAP 1
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
/// as if it was a POD) that may cause some validation tool to report errors.
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
/// If defined, indicates that Json use exception to report invalid type manipulation
/// instead of C assert macro.
# define JSON_USE_EXCEPTION 1
# ifdef JSON_IN_CPPTL
# include <cpptl/config.h>
# ifndef JSON_USE_CPPTL
# define JSON_USE_CPPTL 1
# endif
# endif
# ifdef JSON_IN_CPPTL
# define JSON_API CPPTL_API
# elif defined(JSON_DLL_BUILD)
# define JSON_API __declspec(dllexport)
# elif defined(JSON_DLL)
# define JSON_API __declspec(dllimport)
# else
# define JSON_API
# endif
#endif // JSON_CONFIG_H_INCLUDED

View File

@@ -1,62 +0,0 @@
//------------------------------------------------------------------------------
/*
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 RIPPLE_JSON_JSON_FEATURES_H_INCLUDED
#define RIPPLE_JSON_JSON_FEATURES_H_INCLUDED
#include <ripple/json/json_config.h>
namespace Json
{
/** \brief Configuration passed to reader and writer.
* This configuration object can be used to force the Reader or Writer
* to behave in a standard conforming way.
*/
class JSON_API Features
{
public:
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
* - C & C++ comments are allowed
* - Root object can be any JSON value
* - Assumes Value strings are encoded in UTF-8
*/
static Features all ();
/** \brief A configuration that is strictly compatible with the JSON specification.
* - Comments are forbidden.
* - Root object must be either an array or an object value.
* - Assumes Value strings are encoded in UTF-8
*/
static Features strictMode ();
/** \brief Initialize the configuration like JsonConfig::allFeatures;
*/
Features ();
/// \c true if comments are allowed. Default: \c true.
bool allowComments_;
/// \c true if root must be either an array or an object value. Default: \c false.
bool strictRoot_;
};
} // namespace Json
#endif // CPPTL_JSON_FEATURES_H_INCLUDED

View File

@@ -20,38 +20,17 @@
#ifndef RIPPLE_JSON_JSON_FORWARDS_H_INCLUDED
#define RIPPLE_JSON_JSON_FORWARDS_H_INCLUDED
#include <ripple/json/json_config.h>
namespace Json
{
// writer.h
class FastWriter;
class StyledWriter;
// reader.h
class Reader;
// features.h
class Features;
// value.h
typedef int Int;
typedef unsigned int UInt;
class StaticString;
class Path;
class PathArgument;
class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
#ifdef JSON_VALUE_USE_INTERNAL_MAP
class ValueAllocator;
class ValueMapAllocator;
class ValueInternalLink;
class ValueInternalArray;
class ValueInternalMap;
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
} // namespace Json

View File

@@ -22,8 +22,6 @@
# define CPPTL_JSON_READER_H_INCLUDED
#include <ripple/json/json_config.h>
#include <ripple/json/json_features.h>
#include <ripple/json/json_forwards.h>
#include <ripple/json/json_value.h>
@@ -35,7 +33,7 @@ namespace Json
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
*
*/
class JSON_API Reader
class Reader
{
public:
typedef char Char;
@@ -46,44 +44,25 @@ public:
*/
Reader ();
/** \brief Constructs a Reader allowing the specified feature set
* for parsing.
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
* \param document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \return \c true if the document was successfully parsed, \c false if an error occurred.
*/
Reader ( const Features& features );
bool parse ( std::string const& document, Value& root);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
* \param document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during
* serialization, \c false to discard comments.
* This parameter is ignored if Features::allowComments_
* is \c false.
* \return \c true if the document was successfully parsed, \c false if an error occurred.
*/
bool parse ( std::string const& document,
Value& root,
bool collectComments = true );
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
* \param document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during
* serialization, \c false to discard comments.
* This parameter is ignored if Features::allowComments_
* is \c false.
* \return \c true if the document was successfully parsed, \c false if an error occurred.
*/
bool parse ( const char* beginDoc, const char* endDoc,
Value& root,
bool collectComments = true );
bool parse ( const char* beginDoc, const char* endDoc, Value& root);
/// \brief Parse from input stream.
/// \see Json::operator>>(std::istream&, Json::Value&).
bool parse ( std::istream& is,
Value& root,
bool collectComments = true );
bool parse ( std::istream& is, Value& root);
/** \brief Returns a user friendly string that list errors in the parsed document.
* \return Formatted error message with the list of errors with their location in
@@ -101,7 +80,8 @@ private:
tokenArrayBegin,
tokenArrayEnd,
tokenString,
tokenNumber,
tokenInteger,
tokenDouble,
tokenTrue,
tokenFalse,
tokenNull,
@@ -138,7 +118,7 @@ private:
bool readCStyleComment ();
bool readCppStyleComment ();
bool readString ();
void readNumber ();
Reader::TokenType readNumber ();
bool readValue ();
bool readObject ( Token& token );
bool readArray ( Token& token );
@@ -168,9 +148,6 @@ private:
int& line,
int& column ) const;
std::string getLocationLineAndColumn ( Location location ) const;
void addComment ( Location begin,
Location end,
CommentPlacement placement );
void skipCommentTokens ( Token& token );
typedef std::stack<Value*> Nodes;
@@ -182,9 +159,6 @@ private:
Location current_;
Location lastValueEnd_;
Value* lastValue_;
std::string commentsBefore_;
Features features_;
bool collectComments_;
};
/** \brief Read from 'sin' into 'root'.

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_JSON_JSON_VALUE_H_INCLUDED
#define RIPPLE_JSON_JSON_VALUE_H_INCLUDED
#include <ripple/json/json_config.h>
#include <ripple/json/json_forwards.h>
#include <beast/strings/String.h>
#include <functional>
@@ -54,11 +53,6 @@ enum CommentPlacement
numberOfCommentPlacement
};
//# ifdef JSON_USE_CPPTL
// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
//# endif
/** \brief Lightweight wrapper to tag static string.
*
* Value constructor and objectValue member assignement takes advantage of the
@@ -73,7 +67,7 @@ enum CommentPlacement
* object[code] = 1234;
* \endcode
*/
class JSON_API StaticString
class StaticString
{
public:
explicit StaticString ( const char* czstring )
@@ -122,13 +116,10 @@ private:
* It is possible to iterate over the list of a #objectValue values using
* the getMemberNames() method.
*/
class JSON_API Value
class Value
{
friend class ValueIteratorBase;
# ifdef JSON_VALUE_USE_INTERNAL_MAP
friend class ValueInternalLink;
friend class ValueInternalMap;
# endif
public:
typedef std::vector<std::string> Members;
typedef ValueIterator iterator;
@@ -143,8 +134,6 @@ public:
static const UInt maxUInt;
private:
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
# ifndef JSON_VALUE_USE_INTERNAL_MAP
class CZString
{
public:
@@ -171,13 +160,7 @@ private:
};
public:
# ifndef JSON_USE_CPPTL_SMALLMAP
typedef std::map<CZString, Value> ObjectValues;
# else
typedef CppTL::SmallMap<CZString, Value> ObjectValues;
# endif // ifndef JSON_USE_CPPTL_SMALLMAP
# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
public:
/** \brief Create a default Value of the given type.
@@ -215,9 +198,6 @@ public:
Value ( std::string const& value );
// VFALCO DEPRECATED Avoid this conversion
Value (beast::String const& beastString);
# ifdef JSON_USE_CPPTL
Value ( const CppTL::ConstString& value );
# endif
Value ( bool value );
Value ( const Value& other );
~Value ();
@@ -246,9 +226,6 @@ public:
const char* asCString () const;
std::string asString () const;
# ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString () const;
# endif
Int asInt () const;
UInt asUInt () const;
double asDouble () const;
@@ -330,23 +307,14 @@ public:
* \endcode
*/
Value& operator[] ( const StaticString& key );
# ifdef JSON_USE_CPPTL
/// Access an object value by name, create a null member if it does not exist.
Value& operator[] ( const CppTL::ConstString& key );
/// Access an object value by name, returns null if there is no member with that name.
const Value& operator[] ( const CppTL::ConstString& key ) const;
# endif
/// Return the member named key if it exist, defaultValue otherwise.
Value get ( const char* key,
const Value& defaultValue ) const;
/// Return the member named key if it exist, defaultValue otherwise.
Value get ( std::string const& key,
const Value& defaultValue ) const;
# ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise.
Value get ( const CppTL::ConstString& key,
const Value& defaultValue ) const;
# endif
/// \brief Remove and return the named member.
///
/// Do nothing if it did not exist.
@@ -361,10 +329,6 @@ public:
bool isMember ( const char* key ) const;
/// Return true if the object has a member named key.
bool isMember ( std::string const& key ) const;
# ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key.
bool isMember ( const CppTL::ConstString& key ) const;
# endif
/// \brief Return a list of the member names.
///
@@ -373,17 +337,6 @@ public:
/// \post if type() was nullValue, it remains nullValue
Members getMemberNames () const;
//# ifdef JSON_USE_CPPTL
// EnumMemberNames enumMemberNames() const;
// EnumValues enumValues() const;
//# endif
/// Comments must be //... or /* ... */
void setComment ( const char* comment,
CommentPlacement placement );
/// Comments must be //... or /* ... */
void setComment ( std::string const& comment,
CommentPlacement placement );
bool hasComment ( CommentPlacement placement ) const;
/// Include delimiters and embedded newlines.
std::string getComment ( CommentPlacement placement ) const;
@@ -400,48 +353,7 @@ private:
Value& resolveReference ( const char* key,
bool isStatic );
# ifdef JSON_VALUE_USE_INTERNAL_MAP
inline bool isItemAvailable () const
{
return itemIsUsed_ == 0;
}
inline void setItemUsed ( bool isUsed = true )
{
itemIsUsed_ = isUsed ? 1 : 0;
}
inline bool isMemberNameStatic () const
{
return memberNameIsStatic_ == 0;
}
inline void setMemberNameIsStatic ( bool isStatic )
{
memberNameIsStatic_ = isStatic ? 1 : 0;
}
# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
private:
struct CommentInfo
{
CommentInfo ();
~CommentInfo ();
void setComment ( const char* text );
char* comment_;
};
//struct MemberNamesTransform
//{
// typedef const char *result_type;
// const char *operator()( const CZString &name ) const
// {
// return name.c_str();
// }
//};
union ValueHolder
{
Int int_;
@@ -449,88 +361,10 @@ private:
double real_;
bool bool_;
char* string_;
# ifdef JSON_VALUE_USE_INTERNAL_MAP
ValueInternalArray* array_;
ValueInternalMap* map_;
#else
ObjectValues* map_;
# endif
} value_;
ValueType type_ : 8;
int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
# ifdef JSON_VALUE_USE_INTERNAL_MAP
unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container.
int memberNameIsStatic_ : 1; // used by the ValueInternalMap container.
# endif
CommentInfo* comments_;
};
/** \brief Experimental and untested: represents an element of the "path" to access a node.
*/
class PathArgument
{
public:
friend class Path;
PathArgument ();
PathArgument ( UInt index );
PathArgument ( const char* key );
PathArgument ( std::string const& key );
private:
enum Kind
{
kindNone = 0,
kindIndex,
kindKey
};
std::string key_;
UInt index_;
Kind kind_;
};
/** \brief Experimental and untested: represents a "path" to access a node.
*
* Syntax:
* - "." => root node
* - ".[n]" => elements at index 'n' of root node (an array value)
* - ".name" => member named 'name' of root node (an object value)
* - ".name1.name2.name3"
* - ".[0][1][2].name1[3]"
* - ".%" => member name is provided as parameter
* - ".[%]" => index is provied as parameter
*/
class Path
{
public:
Path ( std::string const& path,
const PathArgument& a1 = PathArgument (),
const PathArgument& a2 = PathArgument (),
const PathArgument& a3 = PathArgument (),
const PathArgument& a4 = PathArgument (),
const PathArgument& a5 = PathArgument () );
const Value& resolve ( const Value& root ) const;
Value resolve ( const Value& root,
const Value& defaultValue ) const;
/// Creates the "path" to access the specified node and returns a reference on the node.
Value& make ( Value& root ) const;
private:
typedef std::vector<const PathArgument*> InArgs;
typedef std::vector<PathArgument> Args;
void makePath ( std::string const& path,
const InArgs& in );
void addPathInArg ( std::string const& path,
const InArgs& in,
InArgs::const_iterator& itInArg,
PathArgument::Kind kind );
void invalidPath ( std::string const& path,
int location );
Args args_;
};
/** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
@@ -554,346 +388,6 @@ public:
virtual void releaseStringValue ( char* value ) = 0;
};
#ifdef JSON_VALUE_USE_INTERNAL_MAP
/** \brief Allocator to customize Value internal map.
* Below is an example of a simple implementation (default implementation actually
* use memory pool for speed).
* \code
class DefaultValueMapAllocator : public ValueMapAllocator
{
public: // overridden from ValueMapAllocator
virtual ValueInternalMap *newMap()
{
return new ValueInternalMap();
}
virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
{
return new ValueInternalMap( other );
}
virtual void destructMap( ValueInternalMap *map )
{
delete map;
}
virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
{
return new ValueInternalLink[size];
}
virtual void releaseMapBuckets( ValueInternalLink *links )
{
delete [] links;
}
virtual ValueInternalLink *allocateMapLink()
{
return new ValueInternalLink();
}
virtual void releaseMapLink( ValueInternalLink *link )
{
delete link;
}
};
* \endcode
*/
class JSON_API ValueMapAllocator
{
public:
virtual ~ValueMapAllocator ();
virtual ValueInternalMap* newMap () = 0;
virtual ValueInternalMap* newMapCopy ( const ValueInternalMap& other ) = 0;
virtual void destructMap ( ValueInternalMap* map ) = 0;
virtual ValueInternalLink* allocateMapBuckets ( unsigned int size ) = 0;
virtual void releaseMapBuckets ( ValueInternalLink* links ) = 0;
virtual ValueInternalLink* allocateMapLink () = 0;
virtual void releaseMapLink ( ValueInternalLink* link ) = 0;
};
/** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
* \internal previous_ & next_ allows for bidirectional traversal.
*/
class JSON_API ValueInternalLink
{
public:
enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
enum InternalFlags
{
flagAvailable = 0,
flagUsed = 1
};
ValueInternalLink ();
~ValueInternalLink ();
Value items_[itemPerLink];
char* keys_[itemPerLink];
ValueInternalLink* previous_;
ValueInternalLink* next_;
};
/** \brief A linked page based hash-table implementation used internally by Value.
* \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
* list in each bucket to handle collision. There is an addional twist in that
* each node of the collision linked list is a page containing a fixed amount of
* value. This provides a better compromise between memory usage and speed.
*
* Each bucket is made up of a chained list of ValueInternalLink. The last
* link of a given bucket can be found in the 'previous_' field of the following bucket.
* The last link of the last bucket is stored in tailLink_ as it has no following bucket.
* Only the last link of a bucket may contains 'available' item. The last link always
* contains at least one element unless is it the bucket one very first link.
*/
class JSON_API ValueInternalMap
{
friend class ValueIteratorBase;
friend class Value;
public:
typedef unsigned int HashKey;
typedef unsigned int BucketIndex;
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
struct IteratorState
{
IteratorState ()
: map_ (0)
, link_ (0)
, itemIndex_ (0)
, bucketIndex_ (0)
{
}
ValueInternalMap* map_;
ValueInternalLink* link_;
BucketIndex itemIndex_;
BucketIndex bucketIndex_;
};
# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
ValueInternalMap ();
ValueInternalMap ( const ValueInternalMap& other );
ValueInternalMap& operator = ( const ValueInternalMap& other );
~ValueInternalMap ();
void swap ( ValueInternalMap& other ) noexcept;
BucketIndex size () const;
void clear ();
bool reserveDelta ( BucketIndex growth );
bool reserve ( BucketIndex newItemCount );
const Value* find ( const char* key ) const;
Value* find ( const char* key );
Value& resolveReference ( const char* key,
bool isStatic );
void remove ( const char* key );
void doActualRemove ( ValueInternalLink* link,
BucketIndex index,
BucketIndex bucketIndex );
ValueInternalLink*& getLastLinkInBucket ( BucketIndex bucketIndex );
Value& setNewItem ( const char* key,
bool isStatic,
ValueInternalLink* link,
BucketIndex index );
Value& unsafeAdd ( const char* key,
bool isStatic,
HashKey hashedKey );
HashKey hash ( const char* key ) const;
int compare ( const ValueInternalMap& other ) const;
private:
void makeBeginIterator ( IteratorState& it ) const;
void makeEndIterator ( IteratorState& it ) const;
static bool equals ( const IteratorState& x, const IteratorState& other );
static void increment ( IteratorState& iterator );
static void incrementBucket ( IteratorState& iterator );
static void decrement ( IteratorState& iterator );
static const char* key ( const IteratorState& iterator );
static const char* key ( const IteratorState& iterator, bool& isStatic );
static Value& value ( const IteratorState& iterator );
static int distance ( const IteratorState& x, const IteratorState& y );
private:
ValueInternalLink* buckets_;
ValueInternalLink* tailLink_;
BucketIndex bucketsSize_;
BucketIndex itemCount_;
};
/** \brief A simplified deque implementation used internally by Value.
* \internal
* It is based on a list of fixed "page", each page contains a fixed number of items.
* Instead of using a linked-list, a array of pointer is used for fast item look-up.
* Look-up for an element is as follow:
* - compute page index: pageIndex = itemIndex / itemsPerPage
* - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
*
* Insertion is amortized constant time (only the array containing the index of pointers
* need to be reallocated when items are appended).
*/
class JSON_API ValueInternalArray
{
friend class Value;
friend class ValueIteratorBase;
public:
enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo.
typedef Value::ArrayIndex ArrayIndex;
typedef unsigned int PageIndex;
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
struct IteratorState // Must be a POD
{
IteratorState ()
: array_ (0)
, currentPageIndex_ (0)
, currentItemIndex_ (0)
{
}
ValueInternalArray* array_;
Value** currentPageIndex_;
unsigned int currentItemIndex_;
};
# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
ValueInternalArray ();
ValueInternalArray ( const ValueInternalArray& other );
ValueInternalArray& operator = ( const ValueInternalArray& other );
~ValueInternalArray ();
void swap ( ValueInternalArray& other ) noexcept;
void clear ();
void resize ( ArrayIndex newSize );
Value& resolveReference ( ArrayIndex index );
Value* find ( ArrayIndex index ) const;
ArrayIndex size () const;
int compare ( const ValueInternalArray& other ) const;
private:
static bool equals ( const IteratorState& x, const IteratorState& other );
static void increment ( IteratorState& iterator );
static void decrement ( IteratorState& iterator );
static Value& dereference ( const IteratorState& iterator );
static Value& unsafeDereference ( const IteratorState& iterator );
static int distance ( const IteratorState& x, const IteratorState& y );
static ArrayIndex indexOf ( const IteratorState& iterator );
void makeBeginIterator ( IteratorState& it ) const;
void makeEndIterator ( IteratorState& it ) const;
void makeIterator ( IteratorState& it, ArrayIndex index ) const;
void makeIndexValid ( ArrayIndex index );
Value** pages_;
ArrayIndex size_;
PageIndex pageCount_;
};
/** \brief Experimental: do not use. Allocator to customize Value internal array.
* Below is an example of a simple implementation (actual implementation use
* memory pool).
\code
class DefaultValueArrayAllocator : public ValueArrayAllocator
{
public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator()
{
}
virtual ValueInternalArray *newArray()
{
return new ValueInternalArray();
}
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
{
return new ValueInternalArray( other );
}
virtual void destruct( ValueInternalArray *array )
{
delete array;
}
virtual void reallocateArrayPageIndex( Value **&indexes,
ValueInternalArray::PageIndex &indexCount,
ValueInternalArray::PageIndex minNewIndexCount )
{
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
if ( !newIndexes )
throw std::bad_alloc();
indexCount = newIndexCount;
indexes = static_cast<Value **>( newIndexes );
}
virtual void releaseArrayPageIndex( Value **indexes,
ValueInternalArray::PageIndex indexCount )
{
if ( indexes )
free( indexes );
}
virtual Value *allocateArrayPage()
{
return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
}
virtual void releaseArrayPage( Value *value )
{
if ( value )
free( value );
}
};
\endcode
*/
class JSON_API ValueArrayAllocator
{
public:
virtual ~ValueArrayAllocator ();
virtual ValueInternalArray* newArray () = 0;
virtual ValueInternalArray* newArrayCopy ( const ValueInternalArray& other ) = 0;
virtual void destructArray ( ValueInternalArray* array ) = 0;
/** \brief Reallocate array page index.
* Reallocates an array of pointer on each page.
* \param indexes [input] pointer on the current index. May be \c NULL.
* [output] pointer on the new index of at least
* \a minNewIndexCount pages.
* \param indexCount [input] current number of pages in the index.
* [output] number of page the reallocated index can handle.
* \b MUST be >= \a minNewIndexCount.
* \param minNewIndexCount Minimum number of page the new index must be able to
* handle.
*/
virtual void reallocateArrayPageIndex ( Value**& indexes,
ValueInternalArray::PageIndex& indexCount,
ValueInternalArray::PageIndex minNewIndexCount ) = 0;
virtual void releaseArrayPageIndex ( Value** indexes,
ValueInternalArray::PageIndex indexCount ) = 0;
virtual Value* allocateArrayPage () = 0;
virtual void releaseArrayPage ( Value* value ) = 0;
};
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
/** \brief base class for Value iterators.
*
*/
@@ -905,12 +399,8 @@ public:
typedef ValueIteratorBase SelfType;
ValueIteratorBase ();
#ifndef JSON_VALUE_USE_INTERNAL_MAP
explicit ValueIteratorBase ( const Value::ObjectValues::iterator& current );
#else
ValueIteratorBase ( const ValueInternalArray::IteratorState& state );
ValueIteratorBase ( const ValueInternalMap::IteratorState& state );
#endif
bool operator == ( const SelfType& other ) const
{
@@ -950,18 +440,9 @@ protected:
void copy ( const SelfType& other );
private:
#ifndef JSON_VALUE_USE_INTERNAL_MAP
Value::ObjectValues::iterator current_;
// Indicates that iterator is for a null value.
bool isNull_;
#else
union
{
ValueInternalArray::IteratorState array_;
ValueInternalMap::IteratorState map_;
} iterator_;
bool isArray_;
#endif
};
/** \brief const iterator for object and array value.
@@ -981,12 +462,7 @@ public:
private:
/*! \internal Use by Value to create an iterator.
*/
#ifndef JSON_VALUE_USE_INTERNAL_MAP
explicit ValueConstIterator ( const Value::ObjectValues::iterator& current );
#else
ValueConstIterator ( const ValueInternalArray::IteratorState& state );
ValueConstIterator ( const ValueInternalMap::IteratorState& state );
#endif
public:
SelfType& operator = ( const ValueIteratorBase& other );
@@ -1041,12 +517,7 @@ public:
private:
/*! \internal Use by Value to create an iterator.
*/
#ifndef JSON_VALUE_USE_INTERNAL_MAP
explicit ValueIterator ( const Value::ObjectValues::iterator& current );
#else
ValueIterator ( const ValueInternalArray::IteratorState& state );
ValueIterator ( const ValueInternalMap::IteratorState& state );
#endif
public:
SelfType& operator = ( const SelfType& other );

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_JSON_JSON_WRITER_H_INCLUDED
#define RIPPLE_JSON_JSON_WRITER_H_INCLUDED
#include <ripple/json/json_config.h>
#include <ripple/json/json_forwards.h>
#include <ripple/json/json_value.h>
#include <vector>
@@ -32,7 +31,7 @@ class Value;
/** \brief Abstract class for writers.
*/
class JSON_API Writer
class Writer
{
public:
virtual ~Writer ();
@@ -46,14 +45,12 @@ public:
* but may be usefull to support feature such as RPC where bandwith is limited.
* \sa Reader, Value
*/
class JSON_API FastWriter : public Writer
class FastWriter : public Writer
{
public:
FastWriter ();
virtual ~FastWriter () {}
void enableYAMLCompatibility ();
public: // overridden from Writer
virtual std::string write ( const Value& root );
@@ -61,7 +58,6 @@ private:
void writeValue ( const Value& value );
std::string document_;
bool yamlCompatiblityEnabled_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
@@ -82,7 +78,7 @@ private:
*
* \sa Reader, Value, Value::setComment()
*/
class JSON_API StyledWriter: public Writer
class StyledWriter: public Writer
{
public:
StyledWriter ();
@@ -104,10 +100,6 @@ private:
void writeWithIndent ( std::string const& value );
void indent ();
void unindent ();
void writeCommentBeforeValue ( const Value& root );
void writeCommentAfterValueOnSameLine ( const Value& root );
bool hasCommentForValue ( const Value& value );
static std::string normalizeEOL ( std::string const& text );
typedef std::vector<std::string> ChildValues;
@@ -139,7 +131,7 @@ private:
* \param indentation Each level will be indented by this amount extra.
* \sa Reader, Value, Value::setComment()
*/
class JSON_API StyledStreamWriter
class StyledStreamWriter
{
public:
StyledStreamWriter ( std::string indentation = "\t" );
@@ -162,10 +154,6 @@ private:
void writeWithIndent ( std::string const& value );
void indent ();
void unindent ();
void writeCommentBeforeValue ( const Value& root );
void writeCommentAfterValueOnSameLine ( const Value& root );
bool hasCommentForValue ( const Value& value );
static std::string normalizeEOL ( std::string const& text );
typedef std::vector<std::string> ChildValues;
@@ -177,11 +165,11 @@ private:
bool addChildValues_;
};
std::string JSON_API valueToString ( Int value );
std::string JSON_API valueToString ( UInt value );
std::string JSON_API valueToString ( double value );
std::string JSON_API valueToString ( bool value );
std::string JSON_API valueToQuotedString ( const char* value );
std::string valueToString ( Int value );
std::string valueToString ( UInt value );
std::string valueToString ( double value );
std::string valueToString ( bool value );
std::string valueToQuotedString ( const char* value );
/// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>()

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_JSON_TO_STRING_H_INCLUDED
#define RIPPLE_JSON_TO_STRING_H_INCLUDED
#include <ripple/json/json_config.h>
#include <string>
#include <ostream>

View File

@@ -52,11 +52,6 @@ struct WriteJson_test : TestOutputSuite
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\"]");

View File

@@ -27,12 +27,6 @@
// For json/
//
#ifdef JSON_USE_CPPTL
#include <cpptl/conststring.h>
#endif
#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
#include <ripple/json/impl/json_batchallocator.h>
#endif
#define JSON_ASSERT_UNREACHABLE assert( false )
#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw