blob: ef3f3302dc9ee756a376ddd6de4d139b8ff51476 [file] [log] [blame]
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001// 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
8namespace Json {
9
10// //////////////////////////////////////////////////////////////////
11// //////////////////////////////////////////////////////////////////
12// //////////////////////////////////////////////////////////////////
13// class ValueInternalMap
14// //////////////////////////////////////////////////////////////////
15// //////////////////////////////////////////////////////////////////
16// //////////////////////////////////////////////////////////////////
17
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050018/** \internal MUST be safely initialized using memset( this, 0,
19 * sizeof(ValueInternalLink) );
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040020 * This optimization is used by the fast allocator.
21 */
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050022ValueInternalLink::ValueInternalLink() : previous_(0), next_(0) {}
23
24ValueInternalLink::~ValueInternalLink() {
25 for (int index = 0; index < itemPerLink; ++index) {
26 if (!items_[index].isItemAvailable()) {
27 if (!items_[index].isMemberNameStatic())
28 free(keys_[index]);
29 } else
30 break;
31 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040032}
33
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050034ValueMapAllocator::~ValueMapAllocator() {}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040035
36#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050037class DefaultValueMapAllocator : public ValueMapAllocator {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040038public: // overridden from ValueMapAllocator
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050039 virtual ValueInternalMap* newMap() { return new ValueInternalMap(); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040040
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050041 virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
42 return new ValueInternalMap(other);
43 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040044
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050045 virtual void destructMap(ValueInternalMap* map) { delete map; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040046
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050047 virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
48 return new ValueInternalLink[size];
49 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040050
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050051 virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040052
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050053 virtual ValueInternalLink* allocateMapLink() {
54 return new ValueInternalLink();
55 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040056
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050057 virtual void releaseMapLink(ValueInternalLink* link) { delete link; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040058};
59#else
60/// @todo make this thread-safe (lock when accessign batch allocator)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050061class DefaultValueMapAllocator : public ValueMapAllocator {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040062public: // overridden from ValueMapAllocator
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050063 virtual ValueInternalMap* newMap() {
64 ValueInternalMap* map = mapsAllocator_.allocate();
65 new (map) ValueInternalMap(); // placement new
66 return map;
67 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040068
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050069 virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
70 ValueInternalMap* map = mapsAllocator_.allocate();
71 new (map) ValueInternalMap(other); // placement new
72 return map;
73 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040074
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050075 virtual void destructMap(ValueInternalMap* map) {
76 if (map) {
77 map->~ValueInternalMap();
78 mapsAllocator_.release(map);
79 }
80 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040081
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050082 virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
83 return new ValueInternalLink[size];
84 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040085
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050086 virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040087
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050088 virtual ValueInternalLink* allocateMapLink() {
89 ValueInternalLink* link = linksAllocator_.allocate();
90 memset(link, 0, sizeof(ValueInternalLink));
91 return link;
92 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040093
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050094 virtual void releaseMapLink(ValueInternalLink* link) {
95 link->~ValueInternalLink();
96 linksAllocator_.release(link);
97 }
98
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040099private:
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500100 BatchAllocator<ValueInternalMap, 1> mapsAllocator_;
101 BatchAllocator<ValueInternalLink, 1> linksAllocator_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400102};
103#endif
104
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500105static ValueMapAllocator*& mapAllocator() {
106 static DefaultValueMapAllocator defaultAllocator;
107 static ValueMapAllocator* mapAllocator = &defaultAllocator;
108 return mapAllocator;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400109}
110
111static struct DummyMapAllocatorInitializer {
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500112 DummyMapAllocatorInitializer() {
113 mapAllocator(); // ensure mapAllocator() statics are initialized before
114 // main().
115 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400116} dummyMapAllocatorInitializer;
117
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400118// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
119
120/*
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500121use linked list hash map.
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400122buckets array is a container.
123linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
124value have extra state: valid, available, deleted
125*/
126
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400127ValueInternalMap::ValueInternalMap()
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500128 : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {}
129
130ValueInternalMap::ValueInternalMap(const ValueInternalMap& other)
131 : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {
132 reserve(other.itemCount_);
133 IteratorState it;
134 IteratorState itEnd;
135 other.makeBeginIterator(it);
136 other.makeEndIterator(itEnd);
137 for (; !equals(it, itEnd); increment(it)) {
138 bool isStatic;
139 const char* memberName = key(it, isStatic);
140 const Value& aValue = value(it);
141 resolveReference(memberName, isStatic) = aValue;
142 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400143}
144
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500145ValueInternalMap& ValueInternalMap::operator=(ValueInternalMap other) {
146 swap(other);
147 return *this;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400148}
149
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500150ValueInternalMap::~ValueInternalMap() {
151 if (buckets_) {
152 for (BucketIndex bucketIndex = 0; bucketIndex < bucketsSize_;
153 ++bucketIndex) {
154 ValueInternalLink* link = buckets_[bucketIndex].next_;
155 while (link) {
156 ValueInternalLink* linkToRelease = link;
157 link = link->next_;
158 mapAllocator()->releaseMapLink(linkToRelease);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400159 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500160 }
161 mapAllocator()->releaseMapBuckets(buckets_);
162 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400163}
164
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500165void ValueInternalMap::swap(ValueInternalMap& other) {
166 ValueInternalLink* tempBuckets = buckets_;
167 buckets_ = other.buckets_;
168 other.buckets_ = tempBuckets;
169 ValueInternalLink* tempTailLink = tailLink_;
170 tailLink_ = other.tailLink_;
171 other.tailLink_ = tempTailLink;
172 BucketIndex tempBucketsSize = bucketsSize_;
173 bucketsSize_ = other.bucketsSize_;
174 other.bucketsSize_ = tempBucketsSize;
175 BucketIndex tempItemCount = itemCount_;
176 itemCount_ = other.itemCount_;
177 other.itemCount_ = tempItemCount;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400178}
179
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500180void ValueInternalMap::clear() {
181 ValueInternalMap dummy;
182 swap(dummy);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400183}
184
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500185ValueInternalMap::BucketIndex ValueInternalMap::size() const {
186 return itemCount_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400187}
188
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500189bool ValueInternalMap::reserveDelta(BucketIndex growth) {
190 return reserve(itemCount_ + growth);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400191}
192
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500193bool ValueInternalMap::reserve(BucketIndex newItemCount) {
194 if (!buckets_ && newItemCount > 0) {
195 buckets_ = mapAllocator()->allocateMapBuckets(1);
196 bucketsSize_ = 1;
197 tailLink_ = &buckets_[0];
198 }
199 // BucketIndex idealBucketCount = (newItemCount +
200 // ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
201 return true;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400202}
203
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500204const Value* ValueInternalMap::find(const char* key) const {
205 if (!bucketsSize_)
206 return 0;
207 HashKey hashedKey = hash(key);
208 BucketIndex bucketIndex = hashedKey % bucketsSize_;
209 for (const ValueInternalLink* current = &buckets_[bucketIndex]; current != 0;
210 current = current->next_) {
211 for (BucketIndex index = 0; index < ValueInternalLink::itemPerLink;
212 ++index) {
213 if (current->items_[index].isItemAvailable())
214 return 0;
215 if (strcmp(key, current->keys_[index]) == 0)
216 return &current->items_[index];
217 }
218 }
219 return 0;
220}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400221
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500222Value* ValueInternalMap::find(const char* key) {
223 const ValueInternalMap* constThis = this;
224 return const_cast<Value*>(constThis->find(key));
225}
226
227Value& ValueInternalMap::resolveReference(const char* key, bool isStatic) {
228 HashKey hashedKey = hash(key);
229 if (bucketsSize_) {
230 BucketIndex bucketIndex = hashedKey % bucketsSize_;
231 ValueInternalLink** previous = 0;
232 BucketIndex index;
233 for (ValueInternalLink* current = &buckets_[bucketIndex]; current != 0;
234 previous = &current->next_, current = current->next_) {
235 for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
236 if (current->items_[index].isItemAvailable())
237 return setNewItem(key, isStatic, current, index);
238 if (strcmp(key, current->keys_[index]) == 0)
239 return current->items_[index];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400240 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500241 }
242 }
243
244 reserveDelta(1);
245 return unsafeAdd(key, isStatic, hashedKey);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400246}
247
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500248void ValueInternalMap::remove(const char* key) {
249 HashKey hashedKey = hash(key);
250 if (!bucketsSize_)
251 return;
252 BucketIndex bucketIndex = hashedKey % bucketsSize_;
253 for (ValueInternalLink* link = &buckets_[bucketIndex]; link != 0;
254 link = link->next_) {
255 BucketIndex index;
256 for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
257 if (link->items_[index].isItemAvailable())
258 return;
259 if (strcmp(key, link->keys_[index]) == 0) {
260 doActualRemove(link, index, bucketIndex);
261 return;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400262 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500263 }
264 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400265}
266
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500267void ValueInternalMap::doActualRemove(ValueInternalLink* link,
268 BucketIndex index,
269 BucketIndex bucketIndex) {
270 // find last item of the bucket and swap it with the 'removed' one.
271 // set removed items flags to 'available'.
272 // if last page only contains 'available' items, then desallocate it (it's
273 // empty)
274 ValueInternalLink*& lastLink = getLastLinkInBucket(index);
275 BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
276 for (; lastItemIndex < ValueInternalLink::itemPerLink;
277 ++lastItemIndex) // may be optimized with dicotomic search
278 {
279 if (lastLink->items_[lastItemIndex].isItemAvailable())
280 break;
281 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400282
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500283 BucketIndex lastUsedIndex = lastItemIndex - 1;
284 Value* valueToDelete = &link->items_[index];
285 Value* valueToPreserve = &lastLink->items_[lastUsedIndex];
286 if (valueToDelete != valueToPreserve)
287 valueToDelete->swap(*valueToPreserve);
288 if (lastUsedIndex == 0) // page is now empty
289 { // remove it from bucket linked list and delete it.
290 ValueInternalLink* linkPreviousToLast = lastLink->previous_;
291 if (linkPreviousToLast != 0) // can not deleted bucket link.
292 {
293 mapAllocator()->releaseMapLink(lastLink);
294 linkPreviousToLast->next_ = 0;
295 lastLink = linkPreviousToLast;
296 }
297 } else {
298 Value dummy;
299 valueToPreserve->swap(dummy); // restore deleted to default Value.
300 valueToPreserve->setItemUsed(false);
301 }
302 --itemCount_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400303}
304
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500305ValueInternalLink*&
306ValueInternalMap::getLastLinkInBucket(BucketIndex bucketIndex) {
307 if (bucketIndex == bucketsSize_ - 1)
308 return tailLink_;
309 ValueInternalLink*& previous = buckets_[bucketIndex + 1].previous_;
310 if (!previous)
311 previous = &buckets_[bucketIndex];
312 return previous;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400313}
314
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500315Value& ValueInternalMap::setNewItem(const char* key,
316 bool isStatic,
317 ValueInternalLink* link,
318 BucketIndex index) {
319 char* duplicatedKey = makeMemberName(key);
320 ++itemCount_;
321 link->keys_[index] = duplicatedKey;
322 link->items_[index].setItemUsed();
323 link->items_[index].setMemberNameIsStatic(isStatic);
324 return link->items_[index]; // items already default constructed.
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400325}
326
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500327Value&
328ValueInternalMap::unsafeAdd(const char* key, bool isStatic, HashKey hashedKey) {
329 JSON_ASSERT_MESSAGE(bucketsSize_ > 0,
330 "ValueInternalMap::unsafeAdd(): internal logic error.");
331 BucketIndex bucketIndex = hashedKey % bucketsSize_;
332 ValueInternalLink*& previousLink = getLastLinkInBucket(bucketIndex);
333 ValueInternalLink* link = previousLink;
334 BucketIndex index;
335 for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
336 if (link->items_[index].isItemAvailable())
337 break;
338 }
339 if (index == ValueInternalLink::itemPerLink) // need to add a new page
340 {
341 ValueInternalLink* newLink = mapAllocator()->allocateMapLink();
342 index = 0;
343 link->next_ = newLink;
344 previousLink = newLink;
345 link = newLink;
346 }
347 return setNewItem(key, isStatic, link, index);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400348}
349
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500350ValueInternalMap::HashKey ValueInternalMap::hash(const char* key) const {
351 HashKey hash = 0;
352 while (*key)
353 hash += *key++ * 37;
354 return hash;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400355}
356
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500357int ValueInternalMap::compare(const ValueInternalMap& other) const {
358 int sizeDiff(itemCount_ - other.itemCount_);
359 if (sizeDiff != 0)
360 return sizeDiff;
361 // Strict order guaranty is required. Compare all keys FIRST, then compare
362 // values.
363 IteratorState it;
364 IteratorState itEnd;
365 makeBeginIterator(it);
366 makeEndIterator(itEnd);
367 for (; !equals(it, itEnd); increment(it)) {
368 if (!other.find(key(it)))
369 return 1;
370 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400371
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500372 // All keys are equals, let's compare values
373 makeBeginIterator(it);
374 for (; !equals(it, itEnd); increment(it)) {
375 const Value* otherValue = other.find(key(it));
376 int valueDiff = value(it).compare(*otherValue);
377 if (valueDiff != 0)
378 return valueDiff;
379 }
380 return 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400381}
382
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500383void ValueInternalMap::makeBeginIterator(IteratorState& it) const {
384 it.map_ = const_cast<ValueInternalMap*>(this);
385 it.bucketIndex_ = 0;
386 it.itemIndex_ = 0;
387 it.link_ = buckets_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400388}
389
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500390void ValueInternalMap::makeEndIterator(IteratorState& it) const {
391 it.map_ = const_cast<ValueInternalMap*>(this);
392 it.bucketIndex_ = bucketsSize_;
393 it.itemIndex_ = 0;
394 it.link_ = 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400395}
396
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500397bool ValueInternalMap::equals(const IteratorState& x,
398 const IteratorState& other) {
399 return x.map_ == other.map_ && x.bucketIndex_ == other.bucketIndex_ &&
400 x.link_ == other.link_ && x.itemIndex_ == other.itemIndex_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400401}
402
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500403void ValueInternalMap::incrementBucket(IteratorState& iterator) {
404 ++iterator.bucketIndex_;
405 JSON_ASSERT_MESSAGE(
406 iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
407 "ValueInternalMap::increment(): attempting to iterate beyond end.");
408 if (iterator.bucketIndex_ == iterator.map_->bucketsSize_)
409 iterator.link_ = 0;
410 else
411 iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
412 iterator.itemIndex_ = 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400413}
414
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500415void ValueInternalMap::increment(IteratorState& iterator) {
416 JSON_ASSERT_MESSAGE(iterator.map_,
417 "Attempting to iterator using invalid iterator.");
418 ++iterator.itemIndex_;
419 if (iterator.itemIndex_ == ValueInternalLink::itemPerLink) {
420 JSON_ASSERT_MESSAGE(
421 iterator.link_ != 0,
422 "ValueInternalMap::increment(): attempting to iterate beyond end.");
423 iterator.link_ = iterator.link_->next_;
424 if (iterator.link_ == 0)
425 incrementBucket(iterator);
426 } else if (iterator.link_->items_[iterator.itemIndex_].isItemAvailable()) {
427 incrementBucket(iterator);
428 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400429}
430
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500431void ValueInternalMap::decrement(IteratorState& iterator) {
432 if (iterator.itemIndex_ == 0) {
433 JSON_ASSERT_MESSAGE(iterator.map_,
434 "Attempting to iterate using invalid iterator.");
435 if (iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_]) {
436 JSON_ASSERT_MESSAGE(iterator.bucketIndex_ > 0,
437 "Attempting to iterate beyond beginning.");
438 --(iterator.bucketIndex_);
439 }
440 iterator.link_ = iterator.link_->previous_;
441 iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
442 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400443}
444
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500445const char* ValueInternalMap::key(const IteratorState& iterator) {
446 JSON_ASSERT_MESSAGE(iterator.link_,
447 "Attempting to iterate using invalid iterator.");
448 return iterator.link_->keys_[iterator.itemIndex_];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400449}
450
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500451const char* ValueInternalMap::key(const IteratorState& iterator,
452 bool& isStatic) {
453 JSON_ASSERT_MESSAGE(iterator.link_,
454 "Attempting to iterate using invalid iterator.");
455 isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
456 return iterator.link_->keys_[iterator.itemIndex_];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400457}
458
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500459Value& ValueInternalMap::value(const IteratorState& iterator) {
460 JSON_ASSERT_MESSAGE(iterator.link_,
461 "Attempting to iterate using invalid iterator.");
462 return iterator.link_->items_[iterator.itemIndex_];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400463}
464
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500465int ValueInternalMap::distance(const IteratorState& x, const IteratorState& y) {
466 int offset = 0;
467 IteratorState it = x;
468 while (!equals(it, y))
469 increment(it);
470 return offset;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400471}
472
473} // namespace Json