50 ValueArrayAllocator::~ValueArrayAllocator()
57 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
65 virtual ValueInternalArray *newArray()
67 return new ValueInternalArray();
70 virtual ValueInternalArray *newArrayCopy(
const ValueInternalArray &other )
72 return new ValueInternalArray( other );
75 virtual void destructArray( ValueInternalArray *array )
80 virtual void reallocateArrayPageIndex( Value **&indexes,
81 ValueInternalArray::PageIndex &indexCount,
82 ValueInternalArray::PageIndex minNewIndexCount )
84 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
85 if ( minNewIndexCount > newIndexCount )
86 newIndexCount = minNewIndexCount;
87 void *newIndexes = realloc( indexes,
sizeof(Value*) * newIndexCount );
89 throw std::bad_alloc();
90 indexCount = newIndexCount;
91 indexes =
static_cast<Value **
>( newIndexes );
93 virtual void releaseArrayPageIndex( Value **indexes,
94 ValueInternalArray::PageIndex indexCount )
99 virtual Value *allocateArrayPage()
101 return static_cast<Value *
>( malloc(
sizeof(Value) * ValueInternalArray::itemsPerPage ) );
104 virtual void releaseArrayPage( Value *value )
110 #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
119 virtual ValueInternalArray *newArray()
121 ValueInternalArray *array = arraysAllocator_.allocate();
122 new (array) ValueInternalArray();
126 virtual ValueInternalArray *newArrayCopy(
const ValueInternalArray &other )
128 ValueInternalArray *array = arraysAllocator_.allocate();
129 new (array) ValueInternalArray( other );
133 virtual void destructArray( ValueInternalArray *array )
137 array->~ValueInternalArray();
138 arraysAllocator_.release( array );
142 virtual void reallocateArrayPageIndex( Value **&indexes,
143 ValueInternalArray::PageIndex &indexCount,
144 ValueInternalArray::PageIndex minNewIndexCount )
146 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
147 if ( minNewIndexCount > newIndexCount )
148 newIndexCount = minNewIndexCount;
149 void *newIndexes = realloc( indexes,
sizeof(Value*) * newIndexCount );
151 throw std::bad_alloc();
152 indexCount = newIndexCount;
153 indexes =
static_cast<Value **
>( newIndexes );
155 virtual void releaseArrayPageIndex( Value **indexes,
156 ValueInternalArray::PageIndex indexCount )
161 virtual Value *allocateArrayPage()
163 return static_cast<Value *
>( pagesAllocator_.allocate() );
166 virtual void releaseArrayPage( Value *value )
169 pagesAllocator_.release( value );
172 BatchAllocator<ValueInternalArray,1> arraysAllocator_;
173 BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
175 #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
177 static ValueArrayAllocator *&arrayAllocator()
180 static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
181 return arrayAllocator;
189 } dummyArrayAllocatorInitializer;
195 ValueInternalArray::equals(
const IteratorState &x,
196 const IteratorState &other )
198 return x.array_ == other.array_
199 && x.currentItemIndex_ == other.currentItemIndex_
200 && x.currentPageIndex_ == other.currentPageIndex_;
205 ValueInternalArray::increment( IteratorState &it )
207 JSON_ASSERT_MESSAGE( it.array_ &&
208 (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
210 "ValueInternalArray::increment(): moving iterator beyond end" );
211 ++(it.currentItemIndex_);
212 if ( it.currentItemIndex_ == itemsPerPage )
214 it.currentItemIndex_ = 0;
215 ++(it.currentPageIndex_);
221 ValueInternalArray::decrement( IteratorState &it )
223 JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
224 && it.currentItemIndex_ == 0,
225 "ValueInternalArray::decrement(): moving iterator beyond end" );
226 if ( it.currentItemIndex_ == 0 )
228 it.currentItemIndex_ = itemsPerPage-1;
229 --(it.currentPageIndex_);
233 --(it.currentItemIndex_);
239 ValueInternalArray::unsafeDereference(
const IteratorState &it )
241 return (*(it.currentPageIndex_))[it.currentItemIndex_];
246 ValueInternalArray::dereference(
const IteratorState &it )
248 JSON_ASSERT_MESSAGE( it.array_ &&
249 (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
251 "ValueInternalArray::dereference(): dereferencing invalid iterator" );
252 return unsafeDereference( it );
256 ValueInternalArray::makeBeginIterator( IteratorState &it )
const
258 it.array_ =
const_cast<ValueInternalArray *
>( this );
259 it.currentItemIndex_ = 0;
260 it.currentPageIndex_ = pages_;
265 ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index )
const
267 it.array_ =
const_cast<ValueInternalArray *
>( this );
268 it.currentItemIndex_ = index % itemsPerPage;
269 it.currentPageIndex_ = pages_ + index / itemsPerPage;
274 ValueInternalArray::makeEndIterator( IteratorState &it )
const
276 makeIterator( it, size_ );
280 ValueInternalArray::ValueInternalArray()
288 ValueInternalArray::ValueInternalArray(
const ValueInternalArray &other )
291 , size_( other.size_ )
293 PageIndex minNewPages = other.size_ / itemsPerPage;
294 arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
295 JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
296 "ValueInternalArray::reserve(): bad reallocation" );
297 IteratorState itOther;
298 other.makeBeginIterator( itOther );
300 for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
302 if ( index % itemsPerPage == 0 )
304 PageIndex pageIndex = index / itemsPerPage;
305 value = arrayAllocator()->allocateArrayPage();
306 pages_[pageIndex] = value;
308 new (value) Value( dereference( itOther ) );
314 ValueInternalArray::operator =(
const ValueInternalArray &other )
316 ValueInternalArray temp( other );
322 ValueInternalArray::~ValueInternalArray()
327 makeBeginIterator( it);
328 makeEndIterator( itEnd );
329 for ( ; !equals(it,itEnd); increment(it) )
331 Value *value = &dereference(it);
335 PageIndex lastPageIndex = size_ / itemsPerPage;
336 for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
337 arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
339 arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
344 ValueInternalArray::swap( ValueInternalArray &other )
346 Value **tempPages = pages_;
347 pages_ = other.pages_;
348 other.pages_ = tempPages;
349 ArrayIndex tempSize = size_;
351 other.size_ = tempSize;
352 PageIndex tempPageCount = pageCount_;
353 pageCount_ = other.pageCount_;
354 other.pageCount_ = tempPageCount;
358 ValueInternalArray::clear()
360 ValueInternalArray dummy;
366 ValueInternalArray::resize( ArrayIndex newSize )
370 else if ( newSize < size_ )
374 makeIterator( it, newSize );
375 makeIterator( itEnd, size_ );
376 for ( ; !equals(it,itEnd); increment(it) )
378 Value *value = &dereference(it);
381 PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
382 PageIndex lastPageIndex = size_ / itemsPerPage;
383 for ( ; pageIndex < lastPageIndex; ++pageIndex )
384 arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
387 else if ( newSize > size_ )
388 resolveReference( newSize );
393 ValueInternalArray::makeIndexValid( ArrayIndex index )
396 if ( index >= pageCount_ * itemsPerPage )
398 PageIndex minNewPages = (index + 1) / itemsPerPage;
399 arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
400 JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
"ValueInternalArray::reserve(): bad reallocation" );
404 ArrayIndex nextPageIndex =
405 (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
407 if ( nextPageIndex <= index )
409 PageIndex pageIndex = nextPageIndex / itemsPerPage;
410 PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
411 for ( ; pageToAllocate-- > 0; ++pageIndex )
412 pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
418 makeIterator( it, size_ );
420 makeIterator( itEnd, size_ );
421 for ( ; !equals(it,itEnd); increment(it) )
423 Value *value = &dereference(it);
429 ValueInternalArray::resolveReference( ArrayIndex index )
431 if ( index >= size_ )
432 makeIndexValid( index );
433 return pages_[index/itemsPerPage][index%itemsPerPage];
437 ValueInternalArray::find( ArrayIndex index )
const
439 if ( index >= size_ )
441 return &(pages_[index/itemsPerPage][index%itemsPerPage]);
444 ValueInternalArray::ArrayIndex
445 ValueInternalArray::size()
const
451 ValueInternalArray::distance(
const IteratorState &x,
const IteratorState &y )
453 return indexOf(y) - indexOf(x);
457 ValueInternalArray::ArrayIndex
458 ValueInternalArray::indexOf(
const IteratorState &iterator )
460 if ( !iterator.array_ )
461 return ArrayIndex(-1);
463 (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
464 + iterator.currentItemIndex_ );
469 ValueInternalArray::compare(
const ValueInternalArray &other )
const
471 int sizeDiff( size_ - other.size_ );
475 for ( ArrayIndex index =0; index < size_; ++index )
477 int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
478 other.pages_[index/itemsPerPage][index%itemsPerPage] );