31 if ( !
items_[index].isItemAvailable() )
33 if ( !
items_[index].isMemberNameStatic() )
47 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
56 virtual ValueInternalMap *newMapCopy(
const ValueInternalMap &other )
58 return new ValueInternalMap( other );
61 virtual void destructMap( ValueInternalMap *map )
66 virtual ValueInternalLink *allocateMapBuckets(
unsigned int size )
68 return new ValueInternalLink[size];
71 virtual void releaseMapBuckets( ValueInternalLink *links )
76 virtual ValueInternalLink *allocateMapLink()
78 return new ValueInternalLink();
81 virtual void releaseMapLink( ValueInternalLink *link )
87 class DefaultValueMapAllocator :
public ValueMapAllocator
91 virtual ValueInternalMap *newMap()
93 ValueInternalMap *map = mapsAllocator_.allocate();
94 new (map) ValueInternalMap();
98 virtual ValueInternalMap *newMapCopy(
const ValueInternalMap &other )
100 ValueInternalMap *map = mapsAllocator_.allocate();
101 new (map) ValueInternalMap( other );
105 virtual void destructMap( ValueInternalMap *map )
109 map->~ValueInternalMap();
110 mapsAllocator_.release( map );
114 virtual ValueInternalLink *allocateMapBuckets(
unsigned int size )
116 return new ValueInternalLink[size];
119 virtual void releaseMapBuckets( ValueInternalLink *links )
124 virtual ValueInternalLink *allocateMapLink()
126 ValueInternalLink *link = linksAllocator_.allocate();
127 memset( link, 0,
sizeof(ValueInternalLink) );
131 virtual void releaseMapLink( ValueInternalLink *link )
133 link->~ValueInternalLink();
134 linksAllocator_.release( link );
137 BatchAllocator<ValueInternalMap,1> mapsAllocator_;
138 BatchAllocator<ValueInternalLink,1> linksAllocator_;
144 static DefaultValueMapAllocator defaultAllocator;
149 static struct DummyMapAllocatorInitializer {
150 DummyMapAllocatorInitializer()
186 other.makeBeginIterator( it );
187 other.makeEndIterator( itEnd );
188 for ( ; !equals(it,itEnd); increment(it) )
191 const char *memberName = key( it, isStatic );
192 const Value &aValue = value( it );
211 for (
BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
230 buckets_ = other.buckets_;
231 other.buckets_ = tempBuckets;
233 tailLink_ = other.tailLink_;
234 other.tailLink_ = tempTailLink;
236 bucketsSize_ = other.bucketsSize_;
237 other.bucketsSize_ = tempBucketsSize;
239 itemCount_ = other.itemCount_;
240 other.itemCount_ = tempItemCount;
261 return reserve( itemCount_ + growth );
267 if ( !buckets_ && newItemCount > 0 )
271 tailLink_ = &buckets_[0];
284 BucketIndex bucketIndex = hashedKey % bucketsSize_;
287 current = current->
next_ )
291 if ( current->items_[index].isItemAvailable() )
293 if ( strcmp( key, current->keys_[index] ) == 0 )
294 return ¤t->items_[index];
305 return const_cast<Value *
>( constThis->
find( key ) );
316 BucketIndex bucketIndex = hashedKey % bucketsSize_;
321 previous = ¤t->
next_, current = current->
next_ )
325 if ( current->items_[index].isItemAvailable() )
326 return setNewItem( key, isStatic, current, index );
327 if ( strcmp( key, current->keys_[index] ) == 0 )
328 return current->items_[index];
334 return unsafeAdd( key, isStatic, hashedKey );
344 BucketIndex bucketIndex = hashedKey % bucketsSize_;
352 if ( link->items_[index].isItemAvailable() )
354 if ( strcmp( key, link->keys_[index] ) == 0 )
377 if ( lastLink->
items_[lastItemIndex].isItemAvailable() )
383 Value *valueToPreserve = &lastLink->
items_[lastUsedIndex];
384 if ( valueToDelete != valueToPreserve )
385 valueToDelete->
swap( *valueToPreserve );
386 if ( lastUsedIndex == 0 )
389 if ( linkPreviousToLast != 0 )
392 linkPreviousToLast->
next_ = 0;
393 lastLink = linkPreviousToLast;
399 valueToPreserve->
swap( dummy );
400 valueToPreserve->setItemUsed(
false );
409 if ( bucketIndex == bucketsSize_ - 1 )
413 previous = &buckets_[bucketIndex];
424 char *duplicatedKey = makeMemberName( key );
426 link->
keys_[index] = duplicatedKey;
427 link->
items_[index].setItemUsed();
428 link->
items_[index].setMemberNameIsStatic( isStatic );
429 return link->
items_[index];
438 JSON_ASSERT_MESSAGE( bucketsSize_ > 0,
"ValueInternalMap::unsafeAdd(): internal logic error." );
439 BucketIndex bucketIndex = hashedKey % bucketsSize_;
445 if ( link->
items_[index].isItemAvailable() )
448 if ( index == ValueInternalLink::itemPerLink )
452 link->
next_ = newLink;
453 previousLink = newLink;
456 return setNewItem( key, isStatic, link, index );
473 int sizeDiff( itemCount_ - other.itemCount_ );
479 makeBeginIterator( it );
480 makeEndIterator( itEnd );
481 for ( ; !equals(it,itEnd); increment(it) )
483 if ( !other.
find( key( it ) ) )
488 makeBeginIterator( it );
489 for ( ; !equals(it,itEnd); increment(it) )
491 const Value *otherValue = other.
find( key( it ) );
492 int valueDiff = value(it).
compare( *otherValue );
493 if ( valueDiff != 0 )
501 ValueInternalMap::makeBeginIterator( IteratorState &it )
const
511 ValueInternalMap::makeEndIterator( IteratorState &it )
const
514 it.bucketIndex_ = bucketsSize_;
521 ValueInternalMap::equals(
const IteratorState &x,
const IteratorState &other )
523 return x.map_ == other.map_
524 && x.bucketIndex_ == other.bucketIndex_
525 && x.link_ == other.link_
526 && x.itemIndex_ == other.itemIndex_;
531 ValueInternalMap::incrementBucket( IteratorState &iterator )
533 ++iterator.bucketIndex_;
535 "ValueInternalMap::increment(): attempting to iterate beyond end." );
536 if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
539 iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
540 iterator.itemIndex_ = 0;
545 ValueInternalMap::increment( IteratorState &iterator )
548 ++iterator.itemIndex_;
552 "ValueInternalMap::increment(): attempting to iterate beyond end." );
553 iterator.link_ = iterator.link_->next_;
554 if ( iterator.link_ == 0 )
555 incrementBucket( iterator );
557 else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
559 incrementBucket( iterator );
565 ValueInternalMap::decrement( IteratorState &iterator )
567 if ( iterator.itemIndex_ == 0 )
570 if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
572 JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0,
"Attempting to iterate beyond beginning." );
573 --(iterator.bucketIndex_);
575 iterator.link_ = iterator.link_->previous_;
582 ValueInternalMap::key(
const IteratorState &iterator )
585 return iterator.link_->keys_[iterator.itemIndex_];
589 ValueInternalMap::key(
const IteratorState &iterator,
bool &isStatic )
592 isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
593 return iterator.link_->keys_[iterator.itemIndex_];
598 ValueInternalMap::value(
const IteratorState &iterator )
601 return iterator.link_->items_[iterator.itemIndex_];
606 ValueInternalMap::distance(
const IteratorState &x,
const IteratorState &y )
609 IteratorState it = x;
610 while ( !equals( it, y ) )
bool reserveDelta(BucketIndex growth)
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
#define JSON_ASSERT_MESSAGE(condition, message)
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)
JSON (JavaScript Object Notation).
static struct Json::DummyMapAllocatorInitializer dummyMapAllocatorInitializer
ValueInternalLink *& getLastLinkInBucket(BucketIndex bucketIndex)
const Value * find(const char *key) const
void swap(Value &other)
Swap values.
ValueInternalMap & operator=(const ValueInternalMap &other)
Value & resolveReference(const char *key, bool isStatic)
static ValueMapAllocator *& mapAllocator()
ValueInternalLink * next_
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