Mercurial > hg > gpsynth
comparison third_party/json/json_internalarray.inl @ 0:add35537fdbb tip
Initial import
author | irh <ian.r.hobson@gmail.com> |
---|---|
date | Thu, 25 Aug 2011 11:05:55 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:add35537fdbb |
---|---|
1 // Copyright 2007-2010 Baptiste Lepilleur | |
2 // Distributed under MIT license, or public domain if desired and | |
3 // recognized in your jurisdiction. | |
4 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
5 | |
6 // included by json_value.cpp | |
7 | |
8 namespace Json { | |
9 | |
10 // ////////////////////////////////////////////////////////////////// | |
11 // ////////////////////////////////////////////////////////////////// | |
12 // ////////////////////////////////////////////////////////////////// | |
13 // class ValueInternalArray | |
14 // ////////////////////////////////////////////////////////////////// | |
15 // ////////////////////////////////////////////////////////////////// | |
16 // ////////////////////////////////////////////////////////////////// | |
17 | |
18 ValueArrayAllocator::~ValueArrayAllocator() | |
19 { | |
20 } | |
21 | |
22 // ////////////////////////////////////////////////////////////////// | |
23 // class DefaultValueArrayAllocator | |
24 // ////////////////////////////////////////////////////////////////// | |
25 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
26 class DefaultValueArrayAllocator : public ValueArrayAllocator | |
27 { | |
28 public: // overridden from ValueArrayAllocator | |
29 virtual ~DefaultValueArrayAllocator() | |
30 { | |
31 } | |
32 | |
33 virtual ValueInternalArray *newArray() | |
34 { | |
35 return new ValueInternalArray(); | |
36 } | |
37 | |
38 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) | |
39 { | |
40 return new ValueInternalArray( other ); | |
41 } | |
42 | |
43 virtual void destructArray( ValueInternalArray *array ) | |
44 { | |
45 delete array; | |
46 } | |
47 | |
48 virtual void reallocateArrayPageIndex( Value **&indexes, | |
49 ValueInternalArray::PageIndex &indexCount, | |
50 ValueInternalArray::PageIndex minNewIndexCount ) | |
51 { | |
52 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; | |
53 if ( minNewIndexCount > newIndexCount ) | |
54 newIndexCount = minNewIndexCount; | |
55 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); | |
56 JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc."); | |
57 indexCount = newIndexCount; | |
58 indexes = static_cast<Value **>( newIndexes ); | |
59 } | |
60 virtual void releaseArrayPageIndex( Value **indexes, | |
61 ValueInternalArray::PageIndex indexCount ) | |
62 { | |
63 if ( indexes ) | |
64 free( indexes ); | |
65 } | |
66 | |
67 virtual Value *allocateArrayPage() | |
68 { | |
69 return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); | |
70 } | |
71 | |
72 virtual void releaseArrayPage( Value *value ) | |
73 { | |
74 if ( value ) | |
75 free( value ); | |
76 } | |
77 }; | |
78 | |
79 #else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
80 /// @todo make this thread-safe (lock when accessign batch allocator) | |
81 class DefaultValueArrayAllocator : public ValueArrayAllocator | |
82 { | |
83 public: // overridden from ValueArrayAllocator | |
84 virtual ~DefaultValueArrayAllocator() | |
85 { | |
86 } | |
87 | |
88 virtual ValueInternalArray *newArray() | |
89 { | |
90 ValueInternalArray *array = arraysAllocator_.allocate(); | |
91 new (array) ValueInternalArray(); // placement new | |
92 return array; | |
93 } | |
94 | |
95 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) | |
96 { | |
97 ValueInternalArray *array = arraysAllocator_.allocate(); | |
98 new (array) ValueInternalArray( other ); // placement new | |
99 return array; | |
100 } | |
101 | |
102 virtual void destructArray( ValueInternalArray *array ) | |
103 { | |
104 if ( array ) | |
105 { | |
106 array->~ValueInternalArray(); | |
107 arraysAllocator_.release( array ); | |
108 } | |
109 } | |
110 | |
111 virtual void reallocateArrayPageIndex( Value **&indexes, | |
112 ValueInternalArray::PageIndex &indexCount, | |
113 ValueInternalArray::PageIndex minNewIndexCount ) | |
114 { | |
115 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; | |
116 if ( minNewIndexCount > newIndexCount ) | |
117 newIndexCount = minNewIndexCount; | |
118 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); | |
119 JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc."); | |
120 indexCount = newIndexCount; | |
121 indexes = static_cast<Value **>( newIndexes ); | |
122 } | |
123 virtual void releaseArrayPageIndex( Value **indexes, | |
124 ValueInternalArray::PageIndex indexCount ) | |
125 { | |
126 if ( indexes ) | |
127 free( indexes ); | |
128 } | |
129 | |
130 virtual Value *allocateArrayPage() | |
131 { | |
132 return static_cast<Value *>( pagesAllocator_.allocate() ); | |
133 } | |
134 | |
135 virtual void releaseArrayPage( Value *value ) | |
136 { | |
137 if ( value ) | |
138 pagesAllocator_.release( value ); | |
139 } | |
140 private: | |
141 BatchAllocator<ValueInternalArray,1> arraysAllocator_; | |
142 BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_; | |
143 }; | |
144 #endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR | |
145 | |
146 static ValueArrayAllocator *&arrayAllocator() | |
147 { | |
148 static DefaultValueArrayAllocator defaultAllocator; | |
149 static ValueArrayAllocator *arrayAllocator = &defaultAllocator; | |
150 return arrayAllocator; | |
151 } | |
152 | |
153 static struct DummyArrayAllocatorInitializer { | |
154 DummyArrayAllocatorInitializer() | |
155 { | |
156 arrayAllocator(); // ensure arrayAllocator() statics are initialized before main(). | |
157 } | |
158 } dummyArrayAllocatorInitializer; | |
159 | |
160 // ////////////////////////////////////////////////////////////////// | |
161 // class ValueInternalArray | |
162 // ////////////////////////////////////////////////////////////////// | |
163 bool | |
164 ValueInternalArray::equals( const IteratorState &x, | |
165 const IteratorState &other ) | |
166 { | |
167 return x.array_ == other.array_ | |
168 && x.currentItemIndex_ == other.currentItemIndex_ | |
169 && x.currentPageIndex_ == other.currentPageIndex_; | |
170 } | |
171 | |
172 | |
173 void | |
174 ValueInternalArray::increment( IteratorState &it ) | |
175 { | |
176 JSON_ASSERT_MESSAGE( it.array_ && | |
177 (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_ | |
178 != it.array_->size_, | |
179 "ValueInternalArray::increment(): moving iterator beyond end" ); | |
180 ++(it.currentItemIndex_); | |
181 if ( it.currentItemIndex_ == itemsPerPage ) | |
182 { | |
183 it.currentItemIndex_ = 0; | |
184 ++(it.currentPageIndex_); | |
185 } | |
186 } | |
187 | |
188 | |
189 void | |
190 ValueInternalArray::decrement( IteratorState &it ) | |
191 { | |
192 JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_ | |
193 && it.currentItemIndex_ == 0, | |
194 "ValueInternalArray::decrement(): moving iterator beyond end" ); | |
195 if ( it.currentItemIndex_ == 0 ) | |
196 { | |
197 it.currentItemIndex_ = itemsPerPage-1; | |
198 --(it.currentPageIndex_); | |
199 } | |
200 else | |
201 { | |
202 --(it.currentItemIndex_); | |
203 } | |
204 } | |
205 | |
206 | |
207 Value & | |
208 ValueInternalArray::unsafeDereference( const IteratorState &it ) | |
209 { | |
210 return (*(it.currentPageIndex_))[it.currentItemIndex_]; | |
211 } | |
212 | |
213 | |
214 Value & | |
215 ValueInternalArray::dereference( const IteratorState &it ) | |
216 { | |
217 JSON_ASSERT_MESSAGE( it.array_ && | |
218 (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_ | |
219 < it.array_->size_, | |
220 "ValueInternalArray::dereference(): dereferencing invalid iterator" ); | |
221 return unsafeDereference( it ); | |
222 } | |
223 | |
224 void | |
225 ValueInternalArray::makeBeginIterator( IteratorState &it ) const | |
226 { | |
227 it.array_ = const_cast<ValueInternalArray *>( this ); | |
228 it.currentItemIndex_ = 0; | |
229 it.currentPageIndex_ = pages_; | |
230 } | |
231 | |
232 | |
233 void | |
234 ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const | |
235 { | |
236 it.array_ = const_cast<ValueInternalArray *>( this ); | |
237 it.currentItemIndex_ = index % itemsPerPage; | |
238 it.currentPageIndex_ = pages_ + index / itemsPerPage; | |
239 } | |
240 | |
241 | |
242 void | |
243 ValueInternalArray::makeEndIterator( IteratorState &it ) const | |
244 { | |
245 makeIterator( it, size_ ); | |
246 } | |
247 | |
248 | |
249 ValueInternalArray::ValueInternalArray() | |
250 : pages_( 0 ) | |
251 , size_( 0 ) | |
252 , pageCount_( 0 ) | |
253 { | |
254 } | |
255 | |
256 | |
257 ValueInternalArray::ValueInternalArray( const ValueInternalArray &other ) | |
258 : pages_( 0 ) | |
259 , size_( other.size_ ) | |
260 , pageCount_( 0 ) | |
261 { | |
262 PageIndex minNewPages = other.size_ / itemsPerPage; | |
263 arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages ); | |
264 JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, | |
265 "ValueInternalArray::reserve(): bad reallocation" ); | |
266 IteratorState itOther; | |
267 other.makeBeginIterator( itOther ); | |
268 Value *value; | |
269 for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) ) | |
270 { | |
271 if ( index % itemsPerPage == 0 ) | |
272 { | |
273 PageIndex pageIndex = index / itemsPerPage; | |
274 value = arrayAllocator()->allocateArrayPage(); | |
275 pages_[pageIndex] = value; | |
276 } | |
277 new (value) Value( dereference( itOther ) ); | |
278 } | |
279 } | |
280 | |
281 | |
282 ValueInternalArray & | |
283 ValueInternalArray::operator =( const ValueInternalArray &other ) | |
284 { | |
285 ValueInternalArray temp( other ); | |
286 swap( temp ); | |
287 return *this; | |
288 } | |
289 | |
290 | |
291 ValueInternalArray::~ValueInternalArray() | |
292 { | |
293 // destroy all constructed items | |
294 IteratorState it; | |
295 IteratorState itEnd; | |
296 makeBeginIterator( it); | |
297 makeEndIterator( itEnd ); | |
298 for ( ; !equals(it,itEnd); increment(it) ) | |
299 { | |
300 Value *value = &dereference(it); | |
301 value->~Value(); | |
302 } | |
303 // release all pages | |
304 PageIndex lastPageIndex = size_ / itemsPerPage; | |
305 for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex ) | |
306 arrayAllocator()->releaseArrayPage( pages_[pageIndex] ); | |
307 // release pages index | |
308 arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ ); | |
309 } | |
310 | |
311 | |
312 void | |
313 ValueInternalArray::swap( ValueInternalArray &other ) | |
314 { | |
315 Value **tempPages = pages_; | |
316 pages_ = other.pages_; | |
317 other.pages_ = tempPages; | |
318 ArrayIndex tempSize = size_; | |
319 size_ = other.size_; | |
320 other.size_ = tempSize; | |
321 PageIndex tempPageCount = pageCount_; | |
322 pageCount_ = other.pageCount_; | |
323 other.pageCount_ = tempPageCount; | |
324 } | |
325 | |
326 void | |
327 ValueInternalArray::clear() | |
328 { | |
329 ValueInternalArray dummy; | |
330 swap( dummy ); | |
331 } | |
332 | |
333 | |
334 void | |
335 ValueInternalArray::resize( ArrayIndex newSize ) | |
336 { | |
337 if ( newSize == 0 ) | |
338 clear(); | |
339 else if ( newSize < size_ ) | |
340 { | |
341 IteratorState it; | |
342 IteratorState itEnd; | |
343 makeIterator( it, newSize ); | |
344 makeIterator( itEnd, size_ ); | |
345 for ( ; !equals(it,itEnd); increment(it) ) | |
346 { | |
347 Value *value = &dereference(it); | |
348 value->~Value(); | |
349 } | |
350 PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage; | |
351 PageIndex lastPageIndex = size_ / itemsPerPage; | |
352 for ( ; pageIndex < lastPageIndex; ++pageIndex ) | |
353 arrayAllocator()->releaseArrayPage( pages_[pageIndex] ); | |
354 size_ = newSize; | |
355 } | |
356 else if ( newSize > size_ ) | |
357 resolveReference( newSize ); | |
358 } | |
359 | |
360 | |
361 void | |
362 ValueInternalArray::makeIndexValid( ArrayIndex index ) | |
363 { | |
364 // Need to enlarge page index ? | |
365 if ( index >= pageCount_ * itemsPerPage ) | |
366 { | |
367 PageIndex minNewPages = (index + 1) / itemsPerPage; | |
368 arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages ); | |
369 JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" ); | |
370 } | |
371 | |
372 // Need to allocate new pages ? | |
373 ArrayIndex nextPageIndex = | |
374 (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage | |
375 : size_; | |
376 if ( nextPageIndex <= index ) | |
377 { | |
378 PageIndex pageIndex = nextPageIndex / itemsPerPage; | |
379 PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1; | |
380 for ( ; pageToAllocate-- > 0; ++pageIndex ) | |
381 pages_[pageIndex] = arrayAllocator()->allocateArrayPage(); | |
382 } | |
383 | |
384 // Initialize all new entries | |
385 IteratorState it; | |
386 IteratorState itEnd; | |
387 makeIterator( it, size_ ); | |
388 size_ = index + 1; | |
389 makeIterator( itEnd, size_ ); | |
390 for ( ; !equals(it,itEnd); increment(it) ) | |
391 { | |
392 Value *value = &dereference(it); | |
393 new (value) Value(); // Construct a default value using placement new | |
394 } | |
395 } | |
396 | |
397 Value & | |
398 ValueInternalArray::resolveReference( ArrayIndex index ) | |
399 { | |
400 if ( index >= size_ ) | |
401 makeIndexValid( index ); | |
402 return pages_[index/itemsPerPage][index%itemsPerPage]; | |
403 } | |
404 | |
405 Value * | |
406 ValueInternalArray::find( ArrayIndex index ) const | |
407 { | |
408 if ( index >= size_ ) | |
409 return 0; | |
410 return &(pages_[index/itemsPerPage][index%itemsPerPage]); | |
411 } | |
412 | |
413 ValueInternalArray::ArrayIndex | |
414 ValueInternalArray::size() const | |
415 { | |
416 return size_; | |
417 } | |
418 | |
419 int | |
420 ValueInternalArray::distance( const IteratorState &x, const IteratorState &y ) | |
421 { | |
422 return indexOf(y) - indexOf(x); | |
423 } | |
424 | |
425 | |
426 ValueInternalArray::ArrayIndex | |
427 ValueInternalArray::indexOf( const IteratorState &iterator ) | |
428 { | |
429 if ( !iterator.array_ ) | |
430 return ArrayIndex(-1); | |
431 return ArrayIndex( | |
432 (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage | |
433 + iterator.currentItemIndex_ ); | |
434 } | |
435 | |
436 | |
437 int | |
438 ValueInternalArray::compare( const ValueInternalArray &other ) const | |
439 { | |
440 int sizeDiff( size_ - other.size_ ); | |
441 if ( sizeDiff != 0 ) | |
442 return sizeDiff; | |
443 | |
444 for ( ArrayIndex index =0; index < size_; ++index ) | |
445 { | |
446 int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( | |
447 other.pages_[index/itemsPerPage][index%itemsPerPage] ); | |
448 if ( diff != 0 ) | |
449 return diff; | |
450 } | |
451 return 0; | |
452 } | |
453 | |
454 } // namespace Json |