123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- // 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;
- }
|