00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #pragma once
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 ValueArrayAllocator::~ValueArrayAllocator()
00051 {
00052 }
00053
00054
00055
00056
00057 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00058 class DefaultValueArrayAllocator : public ValueArrayAllocator
00059 {
00060 public:
00061 virtual ~DefaultValueArrayAllocator()
00062 {
00063 }
00064
00065 virtual ValueInternalArray *newArray()
00066 {
00067 return new ValueInternalArray();
00068 }
00069
00070 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
00071 {
00072 return new ValueInternalArray( other );
00073 }
00074
00075 virtual void destructArray( ValueInternalArray *array )
00076 {
00077 delete array;
00078 }
00079
00080 virtual void reallocateArrayPageIndex( Value **&indexes,
00081 ValueInternalArray::PageIndex &indexCount,
00082 ValueInternalArray::PageIndex minNewIndexCount )
00083 {
00084 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
00085 if ( minNewIndexCount > newIndexCount )
00086 newIndexCount = minNewIndexCount;
00087 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
00088 if ( !newIndexes )
00089 throw std::bad_alloc();
00090 indexCount = newIndexCount;
00091 indexes = static_cast<Value **>( newIndexes );
00092 }
00093 virtual void releaseArrayPageIndex( Value **indexes,
00094 ValueInternalArray::PageIndex indexCount )
00095 {
00096 free( indexes );
00097 }
00098
00099 virtual Value *allocateArrayPage()
00100 {
00101 return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
00102 }
00103
00104 virtual void releaseArrayPage( Value *value )
00105 {
00106 free( value );
00107 }
00108 };
00109
00110 #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00111
00112 class DefaultValueArrayAllocator : public ValueArrayAllocator
00113 {
00114 public:
00115 virtual ~DefaultValueArrayAllocator()
00116 {
00117 }
00118
00119 virtual ValueInternalArray *newArray()
00120 {
00121 ValueInternalArray *array = arraysAllocator_.allocate();
00122 new (array) ValueInternalArray();
00123 return array;
00124 }
00125
00126 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
00127 {
00128 ValueInternalArray *array = arraysAllocator_.allocate();
00129 new (array) ValueInternalArray( other );
00130 return array;
00131 }
00132
00133 virtual void destructArray( ValueInternalArray *array )
00134 {
00135 if ( array )
00136 {
00137 array->~ValueInternalArray();
00138 arraysAllocator_.release( array );
00139 }
00140 }
00141
00142 virtual void reallocateArrayPageIndex( Value **&indexes,
00143 ValueInternalArray::PageIndex &indexCount,
00144 ValueInternalArray::PageIndex minNewIndexCount )
00145 {
00146 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
00147 if ( minNewIndexCount > newIndexCount )
00148 newIndexCount = minNewIndexCount;
00149 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
00150 if ( !newIndexes )
00151 throw std::bad_alloc();
00152 indexCount = newIndexCount;
00153 indexes = static_cast<Value **>( newIndexes );
00154 }
00155 virtual void releaseArrayPageIndex( Value **indexes,
00156 ValueInternalArray::PageIndex indexCount )
00157 {
00158 free( indexes );
00159 }
00160
00161 virtual Value *allocateArrayPage()
00162 {
00163 return static_cast<Value *>( pagesAllocator_.allocate() );
00164 }
00165
00166 virtual void releaseArrayPage( Value *value )
00167 {
00168 if ( value )
00169 pagesAllocator_.release( value );
00170 }
00171 private:
00172 BatchAllocator<ValueInternalArray,1> arraysAllocator_;
00173 BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
00174 };
00175 #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00176
00177 static ValueArrayAllocator *&arrayAllocator()
00178 {
00179 static DefaultValueArrayAllocator defaultAllocator;
00180 static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
00181 return arrayAllocator;
00182 }
00183
00184 static struct DummyArrayAllocatorInitializer {
00185 DummyArrayAllocatorInitializer()
00186 {
00187 arrayAllocator();
00188 }
00189 } dummyArrayAllocatorInitializer;
00190
00191
00192
00193
00194 bool
00195 ValueInternalArray::equals( const IteratorState &x,
00196 const IteratorState &other )
00197 {
00198 return x.array_ == other.array_
00199 && x.currentItemIndex_ == other.currentItemIndex_
00200 && x.currentPageIndex_ == other.currentPageIndex_;
00201 }
00202
00203
00204 void
00205 ValueInternalArray::increment( IteratorState &it )
00206 {
00207 JSON_ASSERT_MESSAGE( it.array_ &&
00208 (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
00209 != it.array_->size_,
00210 "ValueInternalArray::increment(): moving iterator beyond end" );
00211 ++(it.currentItemIndex_);
00212 if ( it.currentItemIndex_ == itemsPerPage )
00213 {
00214 it.currentItemIndex_ = 0;
00215 ++(it.currentPageIndex_);
00216 }
00217 }
00218
00219
00220 void
00221 ValueInternalArray::decrement( IteratorState &it )
00222 {
00223 JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
00224 && it.currentItemIndex_ == 0,
00225 "ValueInternalArray::decrement(): moving iterator beyond end" );
00226 if ( it.currentItemIndex_ == 0 )
00227 {
00228 it.currentItemIndex_ = itemsPerPage-1;
00229 --(it.currentPageIndex_);
00230 }
00231 else
00232 {
00233 --(it.currentItemIndex_);
00234 }
00235 }
00236
00237
00238 Value &
00239 ValueInternalArray::unsafeDereference( const IteratorState &it )
00240 {
00241 return (*(it.currentPageIndex_))[it.currentItemIndex_];
00242 }
00243
00244
00245 Value &
00246 ValueInternalArray::dereference( const IteratorState &it )
00247 {
00248 JSON_ASSERT_MESSAGE( it.array_ &&
00249 (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
00250 < it.array_->size_,
00251 "ValueInternalArray::dereference(): dereferencing invalid iterator" );
00252 return unsafeDereference( it );
00253 }
00254
00255 void
00256 ValueInternalArray::makeBeginIterator( IteratorState &it ) const
00257 {
00258 it.array_ = const_cast<ValueInternalArray *>( this );
00259 it.currentItemIndex_ = 0;
00260 it.currentPageIndex_ = pages_;
00261 }
00262
00263
00264 void
00265 ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
00266 {
00267 it.array_ = const_cast<ValueInternalArray *>( this );
00268 it.currentItemIndex_ = index % itemsPerPage;
00269 it.currentPageIndex_ = pages_ + index / itemsPerPage;
00270 }
00271
00272
00273 void
00274 ValueInternalArray::makeEndIterator( IteratorState &it ) const
00275 {
00276 makeIterator( it, size_ );
00277 }
00278
00279
00280 ValueInternalArray::ValueInternalArray()
00281 : pages_( 0 )
00282 , size_( 0 )
00283 , pageCount_( 0 )
00284 {
00285 }
00286
00287
00288 ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
00289 : pages_( 0 )
00290 , pageCount_( 0 )
00291 , size_( other.size_ )
00292 {
00293 PageIndex minNewPages = other.size_ / itemsPerPage;
00294 arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
00295 JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
00296 "ValueInternalArray::reserve(): bad reallocation" );
00297 IteratorState itOther;
00298 other.makeBeginIterator( itOther );
00299 Value *value;
00300 for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
00301 {
00302 if ( index % itemsPerPage == 0 )
00303 {
00304 PageIndex pageIndex = index / itemsPerPage;
00305 value = arrayAllocator()->allocateArrayPage();
00306 pages_[pageIndex] = value;
00307 }
00308 new (value) Value( dereference( itOther ) );
00309 }
00310 }
00311
00312
00313 ValueInternalArray &
00314 ValueInternalArray::operator =( const ValueInternalArray &other )
00315 {
00316 ValueInternalArray temp( other );
00317 swap( temp );
00318 return *this;
00319 }
00320
00321
00322 ValueInternalArray::~ValueInternalArray()
00323 {
00324
00325 IteratorState it;
00326 IteratorState itEnd;
00327 makeBeginIterator( it);
00328 makeEndIterator( itEnd );
00329 for ( ; !equals(it,itEnd); increment(it) )
00330 {
00331 Value *value = &dereference(it);
00332 value->~Value();
00333 }
00334
00335 PageIndex lastPageIndex = size_ / itemsPerPage;
00336 for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
00337 arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
00338
00339 arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
00340 }
00341
00342
00343 void
00344 ValueInternalArray::swap( ValueInternalArray &other )
00345 {
00346 Value **tempPages = pages_;
00347 pages_ = other.pages_;
00348 other.pages_ = tempPages;
00349 ArrayIndex tempSize = size_;
00350 size_ = other.size_;
00351 other.size_ = tempSize;
00352 PageIndex tempPageCount = pageCount_;
00353 pageCount_ = other.pageCount_;
00354 other.pageCount_ = tempPageCount;
00355 }
00356
00357 void
00358 ValueInternalArray::clear()
00359 {
00360 ValueInternalArray dummy;
00361 swap( dummy );
00362 }
00363
00364
00365 void
00366 ValueInternalArray::resize( ArrayIndex newSize )
00367 {
00368 if ( newSize == 0 )
00369 clear();
00370 else if ( newSize < size_ )
00371 {
00372 IteratorState it;
00373 IteratorState itEnd;
00374 makeIterator( it, newSize );
00375 makeIterator( itEnd, size_ );
00376 for ( ; !equals(it,itEnd); increment(it) )
00377 {
00378 Value *value = &dereference(it);
00379 value->~Value();
00380 }
00381 PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
00382 PageIndex lastPageIndex = size_ / itemsPerPage;
00383 for ( ; pageIndex < lastPageIndex; ++pageIndex )
00384 arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
00385 size_ = newSize;
00386 }
00387 else if ( newSize > size_ )
00388 resolveReference( newSize );
00389 }
00390
00391
00392 void
00393 ValueInternalArray::makeIndexValid( ArrayIndex index )
00394 {
00395
00396 if ( index >= pageCount_ * itemsPerPage )
00397 {
00398 PageIndex minNewPages = (index + 1) / itemsPerPage;
00399 arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
00400 JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
00401 }
00402
00403
00404 ArrayIndex nextPageIndex =
00405 (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
00406 : size_;
00407 if ( nextPageIndex <= index )
00408 {
00409 PageIndex pageIndex = nextPageIndex / itemsPerPage;
00410 PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
00411 for ( ; pageToAllocate-- > 0; ++pageIndex )
00412 pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
00413 }
00414
00415
00416 IteratorState it;
00417 IteratorState itEnd;
00418 makeIterator( it, size_ );
00419 size_ = index + 1;
00420 makeIterator( itEnd, size_ );
00421 for ( ; !equals(it,itEnd); increment(it) )
00422 {
00423 Value *value = &dereference(it);
00424 new (value) Value();
00425 }
00426 }
00427
00428 Value &
00429 ValueInternalArray::resolveReference( ArrayIndex index )
00430 {
00431 if ( index >= size_ )
00432 makeIndexValid( index );
00433 return pages_[index/itemsPerPage][index%itemsPerPage];
00434 }
00435
00436 Value *
00437 ValueInternalArray::find( ArrayIndex index ) const
00438 {
00439 if ( index >= size_ )
00440 return 0;
00441 return &(pages_[index/itemsPerPage][index%itemsPerPage]);
00442 }
00443
00444 ValueInternalArray::ArrayIndex
00445 ValueInternalArray::size() const
00446 {
00447 return size_;
00448 }
00449
00450 int
00451 ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
00452 {
00453 return indexOf(y) - indexOf(x);
00454 }
00455
00456
00457 ValueInternalArray::ArrayIndex
00458 ValueInternalArray::indexOf( const IteratorState &iterator )
00459 {
00460 if ( !iterator.array_ )
00461 return ArrayIndex(-1);
00462 return ArrayIndex(
00463 (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
00464 + iterator.currentItemIndex_ );
00465 }
00466
00467
00468 int
00469 ValueInternalArray::compare( const ValueInternalArray &other ) const
00470 {
00471 int sizeDiff( size_ - other.size_ );
00472 if ( sizeDiff != 0 )
00473 return sizeDiff;
00474
00475 for ( ArrayIndex index =0; index < size_; ++index )
00476 {
00477 int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
00478 other.pages_[index/itemsPerPage][index%itemsPerPage] );
00479 if ( diff != 0 )
00480 return diff;
00481 }
00482 return 0;
00483 }