Home | History | Annotate | Download | only in lib_json
      1 // 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 
      8 namespace Json {
      9 
     10 // //////////////////////////////////////////////////////////////////
     11 // //////////////////////////////////////////////////////////////////
     12 // //////////////////////////////////////////////////////////////////
     13 // class ValueInternalMap
     14 // //////////////////////////////////////////////////////////////////
     15 // //////////////////////////////////////////////////////////////////
     16 // //////////////////////////////////////////////////////////////////
     17 
     18 /** \internal MUST be safely initialized using memset( this, 0,
     19  * sizeof(ValueInternalLink) );
     20    * This optimization is used by the fast allocator.
     21    */
     22 ValueInternalLink::ValueInternalLink() : previous_(0), next_(0) {}
     23 
     24 ValueInternalLink::~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   }
     32 }
     33 
     34 ValueMapAllocator::~ValueMapAllocator() {}
     35 
     36 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
     37 class DefaultValueMapAllocator : public ValueMapAllocator {
     38 public: // overridden from ValueMapAllocator
     39   virtual ValueInternalMap* newMap() { return new ValueInternalMap(); }
     40 
     41   virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
     42     return new ValueInternalMap(other);
     43   }
     44 
     45   virtual void destructMap(ValueInternalMap* map) { delete map; }
     46 
     47   virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
     48     return new ValueInternalLink[size];
     49   }
     50 
     51   virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
     52 
     53   virtual ValueInternalLink* allocateMapLink() {
     54     return new ValueInternalLink();
     55   }
     56 
     57   virtual void releaseMapLink(ValueInternalLink* link) { delete link; }
     58 };
     59 #else
     60 /// @todo make this thread-safe (lock when accessign batch allocator)
     61 class DefaultValueMapAllocator : public ValueMapAllocator {
     62 public: // overridden from ValueMapAllocator
     63   virtual ValueInternalMap* newMap() {
     64     ValueInternalMap* map = mapsAllocator_.allocate();
     65     new (map) ValueInternalMap(); // placement new
     66     return map;
     67   }
     68 
     69   virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
     70     ValueInternalMap* map = mapsAllocator_.allocate();
     71     new (map) ValueInternalMap(other); // placement new
     72     return map;
     73   }
     74 
     75   virtual void destructMap(ValueInternalMap* map) {
     76     if (map) {
     77       map->~ValueInternalMap();
     78       mapsAllocator_.release(map);
     79     }
     80   }
     81 
     82   virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
     83     return new ValueInternalLink[size];
     84   }
     85 
     86   virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
     87 
     88   virtual ValueInternalLink* allocateMapLink() {
     89     ValueInternalLink* link = linksAllocator_.allocate();
     90     memset(link, 0, sizeof(ValueInternalLink));
     91     return link;
     92   }
     93 
     94   virtual void releaseMapLink(ValueInternalLink* link) {
     95     link->~ValueInternalLink();
     96     linksAllocator_.release(link);
     97   }
     98 
     99 private:
    100   BatchAllocator<ValueInternalMap, 1> mapsAllocator_;
    101   BatchAllocator<ValueInternalLink, 1> linksAllocator_;
    102 };
    103 #endif
    104 
    105 static ValueMapAllocator*& mapAllocator() {
    106   static DefaultValueMapAllocator defaultAllocator;
    107   static ValueMapAllocator* mapAllocator = &defaultAllocator;
    108   return mapAllocator;
    109 }
    110 
    111 static struct DummyMapAllocatorInitializer {
    112   DummyMapAllocatorInitializer() {
    113     mapAllocator(); // ensure mapAllocator() statics are initialized before
    114                     // main().
    115   }
    116 } dummyMapAllocatorInitializer;
    117 
    118 // h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
    119 
    120 /*
    121 use linked list hash map.
    122 buckets array is a container.
    123 linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
    124 value have extra state: valid, available, deleted
    125 */
    126 
    127 ValueInternalMap::ValueInternalMap()
    128     : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {}
    129 
    130 ValueInternalMap::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   }
    143 }
    144 
    145 ValueInternalMap& ValueInternalMap::operator=(ValueInternalMap other) {
    146   swap(other);
    147   return *this;
    148 }
    149 
    150 ValueInternalMap::~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);
    159       }
    160     }
    161     mapAllocator()->releaseMapBuckets(buckets_);
    162   }
    163 }
    164 
    165 void 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;
    178 }
    179 
    180 void ValueInternalMap::clear() {
    181   ValueInternalMap dummy;
    182   swap(dummy);
    183 }
    184 
    185 ValueInternalMap::BucketIndex ValueInternalMap::size() const {
    186   return itemCount_;
    187 }
    188 
    189 bool ValueInternalMap::reserveDelta(BucketIndex growth) {
    190   return reserve(itemCount_ + growth);
    191 }
    192 
    193 bool 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;
    202 }
    203 
    204 const 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 }
    221 
    222 Value* ValueInternalMap::find(const char* key) {
    223   const ValueInternalMap* constThis = this;
    224   return const_cast<Value*>(constThis->find(key));
    225 }
    226 
    227 Value& 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];
    240       }
    241     }
    242   }
    243 
    244   reserveDelta(1);
    245   return unsafeAdd(key, isStatic, hashedKey);
    246 }
    247 
    248 void 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;
    262       }
    263     }
    264   }
    265 }
    266 
    267 void 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   }
    282 
    283   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_;
    303 }
    304 
    305 ValueInternalLink*&
    306 ValueInternalMap::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;
    313 }
    314 
    315 Value& 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.
    325 }
    326 
    327 Value&
    328 ValueInternalMap::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);
    348 }
    349 
    350 ValueInternalMap::HashKey ValueInternalMap::hash(const char* key) const {
    351   HashKey hash = 0;
    352   while (*key)
    353     hash += *key++ * 37;
    354   return hash;
    355 }
    356 
    357 int 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   }
    371 
    372   // 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;
    381 }
    382 
    383 void ValueInternalMap::makeBeginIterator(IteratorState& it) const {
    384   it.map_ = const_cast<ValueInternalMap*>(this);
    385   it.bucketIndex_ = 0;
    386   it.itemIndex_ = 0;
    387   it.link_ = buckets_;
    388 }
    389 
    390 void ValueInternalMap::makeEndIterator(IteratorState& it) const {
    391   it.map_ = const_cast<ValueInternalMap*>(this);
    392   it.bucketIndex_ = bucketsSize_;
    393   it.itemIndex_ = 0;
    394   it.link_ = 0;
    395 }
    396 
    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_;
    401 }
    402 
    403 void 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;
    413 }
    414 
    415 void 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   }
    429 }
    430 
    431 void 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   }
    443 }
    444 
    445 const 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_];
    449 }
    450 
    451 const 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_];
    457 }
    458 
    459 Value& 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_];
    463 }
    464 
    465 int 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;
    471 }
    472 
    473 } // namespace Json
    474