json_internalarray.inl 12 KB

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