26 if (!
items_[index].isItemAvailable()) {
27 if (!
items_[index].isMemberNameStatic())
36 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
41 virtual ValueInternalMap* newMapCopy(
const ValueInternalMap& other) {
42 return new ValueInternalMap(other);
45 virtual void destructMap(ValueInternalMap* map) {
delete map; }
47 virtual ValueInternalLink* allocateMapBuckets(
unsigned int size) {
48 return new ValueInternalLink[size];
51 virtual void releaseMapBuckets(ValueInternalLink* links) {
delete[] links; }
53 virtual ValueInternalLink* allocateMapLink() {
54 return new ValueInternalLink();
57 virtual void releaseMapLink(ValueInternalLink* link) {
delete link; }
60 class DefaultValueMapAllocator :
public ValueMapAllocator {
63 virtual ValueInternalMap* newMap() {
64 ValueInternalMap* map = mapsAllocator_.allocate();
65 new (map) ValueInternalMap();
69 virtual ValueInternalMap* newMapCopy(
const ValueInternalMap& other) {
70 ValueInternalMap* map = mapsAllocator_.allocate();
71 new (map) ValueInternalMap(other);
75 virtual void destructMap(ValueInternalMap* map) {
77 map->~ValueInternalMap();
78 mapsAllocator_.release(map);
82 virtual ValueInternalLink* allocateMapBuckets(
unsigned int size) {
83 return new ValueInternalLink[size];
86 virtual void releaseMapBuckets(ValueInternalLink* links) {
delete[] links; }
88 virtual ValueInternalLink* allocateMapLink() {
89 ValueInternalLink* link = linksAllocator_.allocate();
90 memset(link, 0,
sizeof(ValueInternalLink));
94 virtual void releaseMapLink(ValueInternalLink* link) {
95 link->~ValueInternalLink();
96 linksAllocator_.release(link);
100 BatchAllocator<ValueInternalMap, 1> mapsAllocator_;
101 BatchAllocator<ValueInternalLink, 1> linksAllocator_;
106 static DefaultValueMapAllocator defaultAllocator;
111 static struct DummyMapAllocatorInitializer {
112 DummyMapAllocatorInitializer() {
128 : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {}
131 : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {
135 other.makeBeginIterator(it);
136 other.makeEndIterator(itEnd);
137 for (; !equals(it, itEnd); increment(it)) {
139 const char* memberName = key(it, isStatic);
140 const Value& aValue = value(it);
152 for (
BucketIndex bucketIndex = 0; bucketIndex < bucketsSize_;
167 buckets_ = other.buckets_;
168 other.buckets_ = tempBuckets;
170 tailLink_ = other.tailLink_;
171 other.tailLink_ = tempTailLink;
173 bucketsSize_ = other.bucketsSize_;
174 other.bucketsSize_ = tempBucketsSize;
176 itemCount_ = other.itemCount_;
177 other.itemCount_ = tempItemCount;
190 return reserve(itemCount_ + growth);
194 if (!buckets_ && newItemCount > 0) {
197 tailLink_ = &buckets_[0];
208 BucketIndex bucketIndex = hashedKey % bucketsSize_;
210 current = current->
next_) {
213 if (current->items_[index].isItemAvailable())
215 if (strcmp(key, current->keys_[index]) == 0)
216 return ¤t->items_[index];
224 return const_cast<Value*
>(constThis->
find(key));
230 BucketIndex bucketIndex = hashedKey % bucketsSize_;
234 previous = ¤t->
next_, current = current->
next_) {
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];
245 return unsafeAdd(key, isStatic, hashedKey);
252 BucketIndex bucketIndex = hashedKey % bucketsSize_;
254 link = link->
next_) {
257 if (link->items_[index].isItemAvailable())
259 if (strcmp(key, link->keys_[index]) == 0) {
279 if (lastLink->
items_[lastItemIndex].isItemAvailable())
285 Value* valueToPreserve = &lastLink->
items_[lastUsedIndex];
286 if (valueToDelete != valueToPreserve)
287 valueToDelete->
swap(*valueToPreserve);
288 if (lastUsedIndex == 0)
291 if (linkPreviousToLast != 0)
294 linkPreviousToLast->
next_ = 0;
295 lastLink = linkPreviousToLast;
299 valueToPreserve->
swap(dummy);
300 valueToPreserve->setItemUsed(
false);
307 if (bucketIndex == bucketsSize_ - 1)
311 previous = &buckets_[bucketIndex];
319 char* duplicatedKey = makeMemberName(key);
321 link->
keys_[index] = duplicatedKey;
322 link->
items_[index].setItemUsed();
323 link->
items_[index].setMemberNameIsStatic(isStatic);
324 return link->
items_[index];
330 "ValueInternalMap::unsafeAdd(): internal logic error.");
331 BucketIndex bucketIndex = hashedKey % bucketsSize_;
336 if (link->
items_[index].isItemAvailable())
339 if (index == ValueInternalLink::itemPerLink)
343 link->
next_ = newLink;
344 previousLink = newLink;
347 return setNewItem(key, isStatic, link, index);
358 int sizeDiff(itemCount_ - other.itemCount_);
365 makeBeginIterator(it);
366 makeEndIterator(itEnd);
367 for (; !equals(it, itEnd); increment(it)) {
368 if (!other.
find(key(it)))
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);
383 void ValueInternalMap::makeBeginIterator(IteratorState& it)
const {
390 void ValueInternalMap::makeEndIterator(IteratorState& it)
const {
392 it.bucketIndex_ = bucketsSize_;
397 bool 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_;
403 void ValueInternalMap::incrementBucket(IteratorState& iterator) {
404 ++iterator.bucketIndex_;
406 iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
407 "ValueInternalMap::increment(): attempting to iterate beyond end.");
408 if (iterator.bucketIndex_ == iterator.map_->bucketsSize_)
411 iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
412 iterator.itemIndex_ = 0;
415 void ValueInternalMap::increment(IteratorState& iterator) {
417 "Attempting to iterator using invalid iterator.");
418 ++iterator.itemIndex_;
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);
431 void ValueInternalMap::decrement(IteratorState& iterator) {
432 if (iterator.itemIndex_ == 0) {
434 "Attempting to iterate using invalid iterator.");
435 if (iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_]) {
437 "Attempting to iterate beyond beginning.");
438 --(iterator.bucketIndex_);
440 iterator.link_ = iterator.link_->previous_;
445 const char* ValueInternalMap::key(
const IteratorState& iterator) {
447 "Attempting to iterate using invalid iterator.");
448 return iterator.link_->keys_[iterator.itemIndex_];
451 const char* ValueInternalMap::key(
const IteratorState& iterator,
454 "Attempting to iterate using invalid iterator.");
455 isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
456 return iterator.link_->keys_[iterator.itemIndex_];
459 Value& ValueInternalMap::value(
const IteratorState& iterator) {
461 "Attempting to iterate using invalid iterator.");
462 return iterator.link_->items_[iterator.itemIndex_];
465 int ValueInternalMap::distance(
const IteratorState& x,
const IteratorState& y) {
467 IteratorState it = x;
468 while (!equals(it, y))
bool reserveDelta(BucketIndex growth)
#define JSON_ASSERT_MESSAGE(condition, message)
int compare(const Value &other) const
void remove(const char *key)
ValueInternalLink * previous_
Value & unsafeAdd(const char *key, bool isStatic, HashKey hashedKey)
void swap(ValueInternalMap &other)
char * keys_[itemPerLink]
virtual void releaseMapLink(ValueInternalLink *link)=0
virtual ~ValueMapAllocator()
int compare(const ValueInternalMap &other) const
virtual void releaseMapBuckets(ValueInternalLink *links)=0
ValueInternalMap hash-map bucket chain link (for internal use only).
void doActualRemove(ValueInternalLink *link, BucketIndex index, BucketIndex bucketIndex)
bool reserve(BucketIndex newItemCount)
Allocator to customize Value internal map.
Value & setNewItem(const char *key, bool isStatic, ValueInternalLink *link, BucketIndex index)
static struct Json::DummyMapAllocatorInitializer dummyMapAllocatorInitializer
ValueInternalLink *& getLastLinkInBucket(BucketIndex bucketIndex)
const Value * find(const char *key) const
void swap(Value &other)
Swap values.
Value & resolveReference(const char *key, bool isStatic)
static ValueMapAllocator *& mapAllocator()
ValueInternalLink * next_
ValueInternalMap & operator=(ValueInternalMap other)
A linked page based hash-table implementation used internally by Value.
virtual ValueInternalLink * allocateMapLink()=0
Value items_[itemPerLink]
HashKey hash(const char *key) const
virtual ValueInternalLink * allocateMapBuckets(unsigned int size)=0