1
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
* JSON Library, originally from http://jsoncpp.sourceforge.net/
5
* Copyright (C) 2011 Stewart Smith
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions are
12
* * Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
15
* * Redistributions in binary form must reproduce the above
16
* copyright notice, this list of conditions and the following disclaimer
17
* in the documentation and/or other materials provided with the
20
* * The names of its contributors may not be used to endorse or
21
* promote products derived from this software without specific prior
24
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
// included by json_value.cpp
40
// everything is within Json namespace
42
// //////////////////////////////////////////////////////////////////
43
// //////////////////////////////////////////////////////////////////
44
// //////////////////////////////////////////////////////////////////
45
// class ValueInternalArray
46
// //////////////////////////////////////////////////////////////////
47
// //////////////////////////////////////////////////////////////////
48
// //////////////////////////////////////////////////////////////////
50
ValueArrayAllocator::~ValueArrayAllocator()
54
// //////////////////////////////////////////////////////////////////
55
// class DefaultValueArrayAllocator
56
// //////////////////////////////////////////////////////////////////
57
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
58
class DefaultValueArrayAllocator : public ValueArrayAllocator
60
public: // overridden from ValueArrayAllocator
61
virtual ~DefaultValueArrayAllocator()
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 )
100
virtual Value *allocateArrayPage()
102
return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
105
virtual void releaseArrayPage( Value *value )
112
#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
113
/// @todo make this thread-safe (lock when accessign batch allocator)
114
class DefaultValueArrayAllocator : public ValueArrayAllocator
116
public: // overridden from ValueArrayAllocator
117
virtual ~DefaultValueArrayAllocator()
121
virtual ValueInternalArray *newArray()
123
ValueInternalArray *array = arraysAllocator_.allocate();
124
new (array) ValueInternalArray(); // placement new
128
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
130
ValueInternalArray *array = arraysAllocator_.allocate();
131
new (array) ValueInternalArray( other ); // placement new
135
virtual void destructArray( ValueInternalArray *array )
139
array->~ValueInternalArray();
140
arraysAllocator_.release( array );
144
virtual void reallocateArrayPageIndex( Value **&indexes,
145
ValueInternalArray::PageIndex &indexCount,
146
ValueInternalArray::PageIndex minNewIndexCount )
148
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
149
if ( minNewIndexCount > newIndexCount )
150
newIndexCount = minNewIndexCount;
151
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
153
throw std::bad_alloc();
154
indexCount = newIndexCount;
155
indexes = static_cast<Value **>( newIndexes );
157
virtual void releaseArrayPageIndex( Value **indexes,
158
ValueInternalArray::PageIndex indexCount )
164
virtual Value *allocateArrayPage()
166
return static_cast<Value *>( pagesAllocator_.allocate() );
169
virtual void releaseArrayPage( Value *value )
172
pagesAllocator_.release( value );
175
BatchAllocator<ValueInternalArray,1> arraysAllocator_;
176
BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
178
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
180
static ValueArrayAllocator *&arrayAllocator()
182
static DefaultValueArrayAllocator defaultAllocator;
183
static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
184
return arrayAllocator;
187
static struct DummyArrayAllocatorInitializer {
188
DummyArrayAllocatorInitializer()
190
arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
192
} dummyArrayAllocatorInitializer;
194
// //////////////////////////////////////////////////////////////////
195
// class ValueInternalArray
196
// //////////////////////////////////////////////////////////////////
198
ValueInternalArray::equals( const IteratorState &x,
199
const IteratorState &other )
201
return x.array_ == other.array_
202
&& x.currentItemIndex_ == other.currentItemIndex_
203
&& x.currentPageIndex_ == other.currentPageIndex_;
208
ValueInternalArray::increment( IteratorState &it )
210
JSON_ASSERT_MESSAGE( it.array_ &&
211
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
213
"ValueInternalArray::increment(): moving iterator beyond end" );
214
++(it.currentItemIndex_);
215
if ( it.currentItemIndex_ == itemsPerPage )
217
it.currentItemIndex_ = 0;
218
++(it.currentPageIndex_);
224
ValueInternalArray::decrement( IteratorState &it )
226
JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
227
&& it.currentItemIndex_ == 0,
228
"ValueInternalArray::decrement(): moving iterator beyond end" );
229
if ( it.currentItemIndex_ == 0 )
231
it.currentItemIndex_ = itemsPerPage-1;
232
--(it.currentPageIndex_);
236
--(it.currentItemIndex_);
242
ValueInternalArray::unsafeDereference( const IteratorState &it )
244
return (*(it.currentPageIndex_))[it.currentItemIndex_];
249
ValueInternalArray::dereference( const IteratorState &it )
251
JSON_ASSERT_MESSAGE( it.array_ &&
252
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
254
"ValueInternalArray::dereference(): dereferencing invalid iterator" );
255
return unsafeDereference( it );
259
ValueInternalArray::makeBeginIterator( IteratorState &it ) const
261
it.array_ = const_cast<ValueInternalArray *>( this );
262
it.currentItemIndex_ = 0;
263
it.currentPageIndex_ = pages_;
268
ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
270
it.array_ = const_cast<ValueInternalArray *>( this );
271
it.currentItemIndex_ = index % itemsPerPage;
272
it.currentPageIndex_ = pages_ + index / itemsPerPage;
277
ValueInternalArray::makeEndIterator( IteratorState &it ) const
279
makeIterator( it, size_ );
283
ValueInternalArray::ValueInternalArray()
291
ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
294
, size_( other.size_ )
296
PageIndex minNewPages = other.size_ / itemsPerPage;
297
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
298
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
299
"ValueInternalArray::reserve(): bad reallocation" );
300
IteratorState itOther;
301
other.makeBeginIterator( itOther );
303
for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
305
if ( index % itemsPerPage == 0 )
307
PageIndex pageIndex = index / itemsPerPage;
308
value = arrayAllocator()->allocateArrayPage();
309
pages_[pageIndex] = value;
311
new (value) Value( dereference( itOther ) );
317
ValueInternalArray::operator =( const ValueInternalArray &other )
319
ValueInternalArray temp( other );
325
ValueInternalArray::~ValueInternalArray()
327
// destroy all constructed items
330
makeBeginIterator( it);
331
makeEndIterator( itEnd );
332
for ( ; !equals(it,itEnd); increment(it) )
334
Value *value = &dereference(it);
338
PageIndex lastPageIndex = size_ / itemsPerPage;
339
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
340
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
341
// release pages index
342
arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
347
ValueInternalArray::swap( ValueInternalArray &other )
349
Value **tempPages = pages_;
350
pages_ = other.pages_;
351
other.pages_ = tempPages;
352
ArrayIndex tempSize = size_;
354
other.size_ = tempSize;
355
PageIndex tempPageCount = pageCount_;
356
pageCount_ = other.pageCount_;
357
other.pageCount_ = tempPageCount;
361
ValueInternalArray::clear()
363
ValueInternalArray dummy;
369
ValueInternalArray::resize( ArrayIndex newSize )
373
else if ( newSize < size_ )
377
makeIterator( it, newSize );
378
makeIterator( itEnd, size_ );
379
for ( ; !equals(it,itEnd); increment(it) )
381
Value *value = &dereference(it);
384
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
385
PageIndex lastPageIndex = size_ / itemsPerPage;
386
for ( ; pageIndex < lastPageIndex; ++pageIndex )
387
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
390
else if ( newSize > size_ )
391
resolveReference( newSize );
396
ValueInternalArray::makeIndexValid( ArrayIndex index )
398
// Need to enlarge page index ?
399
if ( index >= pageCount_ * itemsPerPage )
401
PageIndex minNewPages = (index + 1) / itemsPerPage;
402
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
403
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
406
// Need to allocate new pages ?
407
ArrayIndex nextPageIndex =
408
(size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
410
if ( nextPageIndex <= index )
412
PageIndex pageIndex = nextPageIndex / itemsPerPage;
413
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
414
for ( ; pageToAllocate-- > 0; ++pageIndex )
415
pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
418
// Initialize all new entries
421
makeIterator( it, size_ );
423
makeIterator( itEnd, size_ );
424
for ( ; !equals(it,itEnd); increment(it) )
426
Value *value = &dereference(it);
427
new (value) Value(); // Construct a default value using placement new
432
ValueInternalArray::resolveReference( ArrayIndex index )
434
if ( index >= size_ )
435
makeIndexValid( index );
436
return pages_[index/itemsPerPage][index%itemsPerPage];
440
ValueInternalArray::find( ArrayIndex index ) const
442
if ( index >= size_ )
444
return &(pages_[index/itemsPerPage][index%itemsPerPage]);
447
ValueInternalArray::ArrayIndex
448
ValueInternalArray::size() const
454
ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
456
return indexOf(y) - indexOf(x);
460
ValueInternalArray::ArrayIndex
461
ValueInternalArray::indexOf( const IteratorState &iterator )
463
if ( !iterator.array_ )
464
return ArrayIndex(-1);
466
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
467
+ iterator.currentItemIndex_ );
472
ValueInternalArray::compare( const ValueInternalArray &other ) const
474
int sizeDiff( size_ - other.size_ );
478
for ( ArrayIndex index =0; index < size_; ++index )
480
int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
481
other.pages_[index/itemsPerPage][index%itemsPerPage] );