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