Ran clang-format again, this time hitting .inl files too.

clang-format -i $(find . -name '*.h' -or -name '*.cpp' -or -name '*.inl')
This commit is contained in:
Aaron Jacobs 2014-09-18 08:55:18 +10:00 committed by Christopher Dunn
parent 57dde78308
commit ba330893d7
4 changed files with 760 additions and 1051 deletions

View File

@ -2,13 +2,15 @@
// and "version.h.in" files. // and "version.h.in" files.
// Run CMake configure step to update it. // Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED #ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED #define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "0.7.0" #define JSONCPP_VERSION_STRING "0.7.0"
# define JSONCPP_VERSION_MAJOR 0 #define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 7 #define JSONCPP_VERSION_MINOR 7
# define JSONCPP_VERSION_PATCH 0 #define JSONCPP_VERSION_PATCH 0
# define JSONCPP_VERSION_QUALIFIER #define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) #define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
#endif // JSON_VERSION_H_INCLUDED #endif // JSON_VERSION_H_INCLUDED

View File

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

View File

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

View File

@ -17,201 +17,165 @@ namespace Json {
ValueIteratorBase::ValueIteratorBase() ValueIteratorBase::ValueIteratorBase()
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
: current_() : current_(), isNull_(true) {
, isNull_( true )
{
} }
#else #else
: isArray_( true ) : isArray_(true), isNull_(true) {
, isNull_( true ) iterator_.array_ = ValueInternalArray::IteratorState();
{
iterator_.array_ = ValueInternalArray::IteratorState();
} }
#endif #endif
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current ) ValueIteratorBase::ValueIteratorBase(
: current_( current ) const Value::ObjectValues::iterator& current)
, isNull_( false ) : current_(current), isNull_(false) {}
{
}
#else #else
ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) ValueIteratorBase::ValueIteratorBase(
: isArray_( true ) const ValueInternalArray::IteratorState& state)
{ : isArray_(true) {
iterator_.array_ = state; iterator_.array_ = state;
} }
ValueIteratorBase::ValueIteratorBase(
ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) const ValueInternalMap::IteratorState& state)
: isArray_( false ) : isArray_(false) {
{ iterator_.map_ = state;
iterator_.map_ = state;
} }
#endif #endif
Value & Value& ValueIteratorBase::deref() const {
ValueIteratorBase::deref() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
return current_->second; return current_->second;
#else #else
if ( isArray_ ) if (isArray_)
return ValueInternalArray::dereference( iterator_.array_ ); return ValueInternalArray::dereference(iterator_.array_);
return ValueInternalMap::value( iterator_.map_ ); return ValueInternalMap::value(iterator_.map_);
#endif #endif
} }
void ValueIteratorBase::increment() {
void
ValueIteratorBase::increment()
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
++current_; ++current_;
#else #else
if ( isArray_ ) if (isArray_)
ValueInternalArray::increment( iterator_.array_ ); ValueInternalArray::increment(iterator_.array_);
ValueInternalMap::increment( iterator_.map_ ); ValueInternalMap::increment(iterator_.map_);
#endif #endif
} }
void ValueIteratorBase::decrement() {
void
ValueIteratorBase::decrement()
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
--current_; --current_;
#else #else
if ( isArray_ ) if (isArray_)
ValueInternalArray::decrement( iterator_.array_ ); ValueInternalArray::decrement(iterator_.array_);
ValueInternalMap::decrement( iterator_.map_ ); ValueInternalMap::decrement(iterator_.map_);
#endif #endif
} }
ValueIteratorBase::difference_type ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance( const SelfType &other ) const ValueIteratorBase::computeDistance(const SelfType& other) const {
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
# ifdef JSON_USE_CPPTL_SMALLMAP #ifdef JSON_USE_CPPTL_SMALLMAP
return current_ - other.current_; 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
// of the default std::map::iterator, they can not be compared.
// To allow this, we handle this comparison specifically.
if ( isNull_ && other.isNull_ )
{
return 0;
}
// Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
// which is the one used by default).
// Using a portable hand-made version for non random iterator instead:
// return difference_type( std::distance( current_, other.current_ ) );
difference_type myDistance = 0;
for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
{
++myDistance;
}
return myDistance;
# endif
#else #else
if ( isArray_ ) // Iterator for null value are initialized using the default
return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); // constructor, which initialize current_ to the default
return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); // std::map::iterator. As begin() and end() are two instance
// of the default std::map::iterator, they can not be compared.
// To allow this, we handle this comparison specifically.
if (isNull_ && other.isNull_) {
return 0;
}
// Usage of std::distance is not portable (does not compile with Sun Studio 12
// RogueWave STL,
// which is the one used by default).
// Using a portable hand-made version for non random iterator instead:
// return difference_type( std::distance( current_, other.current_ ) );
difference_type myDistance = 0;
for (Value::ObjectValues::iterator it = current_; it != other.current_;
++it) {
++myDistance;
}
return myDistance;
#endif
#else
if (isArray_)
return ValueInternalArray::distance(iterator_.array_,
other.iterator_.array_);
return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_);
#endif #endif
} }
bool ValueIteratorBase::isEqual(const SelfType& other) const {
bool
ValueIteratorBase::isEqual( const SelfType &other ) const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
if ( isNull_ ) if (isNull_) {
{ return other.isNull_;
return other.isNull_; }
} return current_ == other.current_;
return current_ == other.current_;
#else #else
if ( isArray_ ) if (isArray_)
return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_);
return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_);
#endif #endif
} }
void ValueIteratorBase::copy(const SelfType& other) {
void
ValueIteratorBase::copy( const SelfType &other )
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
current_ = other.current_; current_ = other.current_;
isNull_ = other.isNull_; isNull_ = other.isNull_;
#else #else
if ( isArray_ ) if (isArray_)
iterator_.array_ = other.iterator_.array_; iterator_.array_ = other.iterator_.array_;
iterator_.map_ = other.iterator_.map_; iterator_.map_ = other.iterator_.map_;
#endif #endif
} }
Value ValueIteratorBase::key() const {
Value
ValueIteratorBase::key() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first; const Value::CZString czstring = (*current_).first;
if ( czstring.c_str() ) if (czstring.c_str()) {
{ if (czstring.isStaticString())
if ( czstring.isStaticString() ) return Value(StaticString(czstring.c_str()));
return Value( StaticString( czstring.c_str() ) ); return Value(czstring.c_str());
return Value( czstring.c_str() ); }
} return Value(czstring.index());
return Value( czstring.index() );
#else #else
if ( isArray_ ) if (isArray_)
return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); return Value(ValueInternalArray::indexOf(iterator_.array_));
bool isStatic; bool isStatic;
const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic ); const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic);
if ( isStatic ) if (isStatic)
return Value( StaticString( memberName ) ); return Value(StaticString(memberName));
return Value( memberName ); return Value(memberName);
#endif #endif
} }
UInt ValueIteratorBase::index() const {
UInt
ValueIteratorBase::index() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first; const Value::CZString czstring = (*current_).first;
if ( !czstring.c_str() ) if (!czstring.c_str())
return czstring.index(); return czstring.index();
return Value::UInt( -1 ); return Value::UInt(-1);
#else #else
if ( isArray_ ) if (isArray_)
return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); return Value::UInt(ValueInternalArray::indexOf(iterator_.array_));
return Value::UInt( -1 ); return Value::UInt(-1);
#endif #endif
} }
const char* ValueIteratorBase::memberName() const {
const char *
ValueIteratorBase::memberName() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
const char *name = (*current_).first.c_str(); const char* name = (*current_).first.c_str();
return name ? name : ""; return name ? name : "";
#else #else
if ( !isArray_ ) if (!isArray_)
return ValueInternalMap::key( iterator_.map_ ); return ValueInternalMap::key(iterator_.map_);
return ""; return "";
#endif #endif
} }
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
@ -220,36 +184,28 @@ ValueIteratorBase::memberName() const
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
ValueConstIterator::ValueConstIterator() ValueConstIterator::ValueConstIterator() {}
{
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current ) ValueConstIterator::ValueConstIterator(
: ValueIteratorBase( current ) const Value::ObjectValues::iterator& current)
{ : ValueIteratorBase(current) {}
}
#else #else
ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) ValueConstIterator::ValueConstIterator(
: ValueIteratorBase( state ) const ValueInternalArray::IteratorState& state)
{ : ValueIteratorBase(state) {}
}
ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) ValueConstIterator::ValueConstIterator(
: ValueIteratorBase( state ) const ValueInternalMap::IteratorState& state)
{ : ValueIteratorBase(state) {}
}
#endif #endif
ValueConstIterator & ValueConstIterator& ValueConstIterator::
ValueConstIterator::operator =( const ValueIteratorBase &other ) operator=(const ValueIteratorBase& other) {
{ copy(other);
copy( other ); return *this;
return *this;
} }
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
@ -258,43 +214,28 @@ ValueConstIterator::operator =( const ValueIteratorBase &other )
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
ValueIterator::ValueIterator() ValueIterator::ValueIterator() {}
{
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current ) ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
: ValueIteratorBase( current ) : ValueIteratorBase(current) {}
{
}
#else #else
ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state)
: ValueIteratorBase( state ) : ValueIteratorBase(state) {}
{
}
ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state)
: ValueIteratorBase( state ) : ValueIteratorBase(state) {}
{
}
#endif #endif
ValueIterator::ValueIterator( const ValueConstIterator &other ) ValueIterator::ValueIterator(const ValueConstIterator& other)
: ValueIteratorBase( other ) : ValueIteratorBase(other) {}
{
}
ValueIterator::ValueIterator( const ValueIterator &other ) ValueIterator::ValueIterator(const ValueIterator& other)
: ValueIteratorBase( other ) : ValueIteratorBase(other) {}
{
}
ValueIterator & ValueIterator& ValueIterator::operator=(const SelfType& other) {
ValueIterator::operator =( const SelfType &other ) copy(other);
{ return *this;
copy( other );
return *this;
} }
} // namespace Json } // namespace Json