Drizzled Public API Documentation

json_internalmap.inl
00001 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  * 
00003  *  JSON Library, originally from http://jsoncpp.sourceforge.net/
00004  *
00005  *  Copyright (C) 2011 Stewart Smith
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions are
00010  *  met:
00011  *
00012  *      * Redistributions of source code must retain the above copyright
00013  *  notice, this list of conditions and the following disclaimer.
00014  *
00015  *      * Redistributions in binary form must reproduce the above
00016  *  copyright notice, this list of conditions and the following disclaimer
00017  *  in the documentation and/or other materials provided with the
00018  *  distribution.
00019  *
00020  *      * The names of its contributors may not be used to endorse or
00021  *  promote products derived from this software without specific prior
00022  *  written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 #pragma once
00039 // included by json_value.cpp
00040 // everything is within Json namespace
00041 
00042 // //////////////////////////////////////////////////////////////////
00043 // //////////////////////////////////////////////////////////////////
00044 // //////////////////////////////////////////////////////////////////
00045 // class ValueInternalMap
00046 // //////////////////////////////////////////////////////////////////
00047 // //////////////////////////////////////////////////////////////////
00048 // //////////////////////////////////////////////////////////////////
00049 
00053 ValueInternalLink::ValueInternalLink()
00054    : previous_( 0 )
00055    , next_( 0 )
00056 {
00057 }
00058 
00059 ValueInternalLink::~ValueInternalLink()
00060 { 
00061    for ( int index =0; index < itemPerLink; ++index )
00062    {
00063       if ( !items_[index].isItemAvailable() )
00064       {
00065          if ( !items_[index].isMemberNameStatic() )
00066             free( keys_[index] );
00067       }
00068       else
00069          break;
00070    }
00071 }
00072 
00073 
00074 
00075 ValueMapAllocator::~ValueMapAllocator()
00076 {
00077 }
00078 
00079 #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00080 class DefaultValueMapAllocator : public ValueMapAllocator
00081 {
00082 public: // overridden from ValueMapAllocator
00083    virtual ValueInternalMap *newMap()
00084    {
00085       return new ValueInternalMap();
00086    }
00087 
00088    virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
00089    {
00090       return new ValueInternalMap( other );
00091    }
00092 
00093    virtual void destructMap( ValueInternalMap *map )
00094    {
00095       delete map;
00096    }
00097 
00098    virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
00099    {
00100       return new ValueInternalLink[size];
00101    }
00102 
00103    virtual void releaseMapBuckets( ValueInternalLink *links )
00104    {
00105       delete[] links;
00106    }
00107 
00108    virtual ValueInternalLink *allocateMapLink()
00109    {
00110       return new ValueInternalLink();
00111    }
00112 
00113    virtual void releaseMapLink( ValueInternalLink *link )
00114    {
00115       delete link;
00116    }
00117 };
00118 #else
00119 
00120 class DefaultValueMapAllocator : public ValueMapAllocator
00121 {
00122 public: // overridden from ValueMapAllocator
00123    virtual ValueInternalMap *newMap()
00124    {
00125       ValueInternalMap *map = mapsAllocator_.allocate();
00126       new (map) ValueInternalMap(); // placement new
00127       return map;
00128    }
00129 
00130    virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
00131    {
00132       ValueInternalMap *map = mapsAllocator_.allocate();
00133       new (map) ValueInternalMap( other ); // placement new
00134       return map;
00135    }
00136 
00137    virtual void destructMap( ValueInternalMap *map )
00138    {
00139       if ( map )
00140       {
00141          map->~ValueInternalMap();
00142          mapsAllocator_.release( map );
00143       }
00144    }
00145 
00146    virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
00147    {
00148       return new ValueInternalLink[size];
00149    }
00150 
00151    virtual void releaseMapBuckets( ValueInternalLink *links )
00152    {
00153       delete[] links;
00154    }
00155 
00156    virtual ValueInternalLink *allocateMapLink()
00157    {
00158       ValueInternalLink *link = linksAllocator_.allocate();
00159       memset( link, 0, sizeof(ValueInternalLink) );
00160       return link;
00161    }
00162 
00163    virtual void releaseMapLink( ValueInternalLink *link )
00164    {
00165       link->~ValueInternalLink();
00166       linksAllocator_.release( link );
00167    }
00168 private:
00169    BatchAllocator<ValueInternalMap,1> mapsAllocator_;
00170    BatchAllocator<ValueInternalLink,1> linksAllocator_;
00171 };
00172 #endif
00173 
00174 static ValueMapAllocator *&mapAllocator()
00175 {
00176    static DefaultValueMapAllocator defaultAllocator;
00177    static ValueMapAllocator *mapAllocator = &defaultAllocator;
00178    return mapAllocator;
00179 }
00180 
00181 static struct DummyMapAllocatorInitializer {
00182    DummyMapAllocatorInitializer() 
00183    {
00184       mapAllocator();      // ensure mapAllocator() statics are initialized before main().
00185    }
00186 } dummyMapAllocatorInitializer;
00187 
00188 
00189 
00190 // h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
00191 
00192 /*
00193 use linked list hash map. 
00194 buckets array is a container.
00195 linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
00196 value have extra state: valid, available, deleted
00197 */
00198 
00199 
00200 ValueInternalMap::ValueInternalMap()
00201    : buckets_( 0 )
00202    , tailLink_( 0 )
00203    , bucketsSize_( 0 )
00204    , itemCount_( 0 )
00205 {
00206 }
00207 
00208 
00209 ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
00210    : buckets_( 0 )
00211    , tailLink_( 0 )
00212    , bucketsSize_( 0 )
00213    , itemCount_( 0 )
00214 {
00215    reserve( other.itemCount_ );
00216    IteratorState it;
00217    IteratorState itEnd;
00218    other.makeBeginIterator( it );
00219    other.makeEndIterator( itEnd );
00220    for ( ; !equals(it,itEnd); increment(it) )
00221    {
00222       bool isStatic;
00223       const char *memberName = key( it, isStatic );
00224       const Value &aValue = value( it );
00225       resolveReference(memberName, isStatic) = aValue;
00226    }
00227 }
00228 
00229 
00230 ValueInternalMap &
00231 ValueInternalMap::operator =( const ValueInternalMap &other )
00232 {
00233    ValueInternalMap dummy( other );
00234    swap( dummy );
00235    return *this;
00236 }
00237 
00238 
00239 ValueInternalMap::~ValueInternalMap()
00240 {
00241    if ( buckets_ )
00242    {
00243       for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
00244       {
00245          ValueInternalLink *link = buckets_[bucketIndex].next_;
00246          while ( link )
00247          {
00248             ValueInternalLink *linkToRelease = link;
00249             link = link->next_;
00250             mapAllocator()->releaseMapLink( linkToRelease );
00251          }
00252       }
00253       mapAllocator()->releaseMapBuckets( buckets_ );
00254    }
00255 }
00256 
00257 
00258 void 
00259 ValueInternalMap::swap( ValueInternalMap &other )
00260 {
00261    ValueInternalLink *tempBuckets = buckets_;
00262    buckets_ = other.buckets_;
00263    other.buckets_ = tempBuckets;
00264    ValueInternalLink *tempTailLink = tailLink_;
00265    tailLink_ = other.tailLink_;
00266    other.tailLink_ = tempTailLink;
00267    BucketIndex tempBucketsSize = bucketsSize_;
00268    bucketsSize_ = other.bucketsSize_;
00269    other.bucketsSize_ = tempBucketsSize;
00270    BucketIndex tempItemCount = itemCount_;
00271    itemCount_ = other.itemCount_;
00272    other.itemCount_ = tempItemCount;
00273 }
00274 
00275 
00276 void 
00277 ValueInternalMap::clear()
00278 {
00279    ValueInternalMap dummy;
00280    swap( dummy );
00281 }
00282 
00283 
00284 ValueInternalMap::BucketIndex 
00285 ValueInternalMap::size() const
00286 {
00287    return itemCount_;
00288 }
00289 
00290 bool 
00291 ValueInternalMap::reserveDelta( BucketIndex growth )
00292 {
00293    return reserve( itemCount_ + growth );
00294 }
00295 
00296 bool 
00297 ValueInternalMap::reserve( BucketIndex newItemCount )
00298 {
00299    if ( !buckets_  &&  newItemCount > 0 )
00300    {
00301       buckets_ = mapAllocator()->allocateMapBuckets( 1 );
00302       bucketsSize_ = 1;
00303       tailLink_ = &buckets_[0];
00304    }
00305 //   BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
00306    return true;
00307 }
00308 
00309 
00310 const Value *
00311 ValueInternalMap::find( const char *key ) const
00312 {
00313    if ( !bucketsSize_ )
00314       return 0;
00315    HashKey hashedKey = hash( key );
00316    BucketIndex bucketIndex = hashedKey % bucketsSize_;
00317    for ( const ValueInternalLink *current = &buckets_[bucketIndex]; 
00318          current != 0; 
00319          current = current->next_ )
00320    {
00321       for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
00322       {
00323          if ( current->items_[index].isItemAvailable() )
00324             return 0;
00325          if ( strcmp( key, current->keys_[index] ) == 0 )
00326             return &current->items_[index];
00327       }
00328    }
00329    return 0;
00330 }
00331 
00332 
00333 Value *
00334 ValueInternalMap::find( const char *key )
00335 {
00336    const ValueInternalMap *constThis = this;
00337    return const_cast<Value *>( constThis->find( key ) );
00338 }
00339 
00340 
00341 Value &
00342 ValueInternalMap::resolveReference( const char *key,
00343                                     bool isStatic )
00344 {
00345    HashKey hashedKey = hash( key );
00346    if ( bucketsSize_ )
00347    {
00348       BucketIndex bucketIndex = hashedKey % bucketsSize_;
00349       ValueInternalLink **previous = 0;
00350       BucketIndex index;
00351       for ( ValueInternalLink *current = &buckets_[bucketIndex]; 
00352             current != 0; 
00353             previous = &current->next_, current = current->next_ )
00354       {
00355          for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
00356          {
00357             if ( current->items_[index].isItemAvailable() )
00358                return setNewItem( key, isStatic, current, index );
00359             if ( strcmp( key, current->keys_[index] ) == 0 )
00360                return current->items_[index];
00361          }
00362       }
00363    }
00364 
00365    reserveDelta( 1 );
00366    return unsafeAdd( key, isStatic, hashedKey );
00367 }
00368 
00369 
00370 void 
00371 ValueInternalMap::remove( const char *key )
00372 {
00373    HashKey hashedKey = hash( key );
00374    if ( !bucketsSize_ )
00375       return;
00376    BucketIndex bucketIndex = hashedKey % bucketsSize_;
00377    for ( ValueInternalLink *link = &buckets_[bucketIndex]; 
00378          link != 0; 
00379          link = link->next_ )
00380    {
00381       BucketIndex index;
00382       for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
00383       {
00384          if ( link->items_[index].isItemAvailable() )
00385             return;
00386          if ( strcmp( key, link->keys_[index] ) == 0 )
00387          {
00388             doActualRemove( link, index, bucketIndex );
00389             return;
00390          }
00391       }
00392    }
00393 }
00394 
00395 void 
00396 ValueInternalMap::doActualRemove( ValueInternalLink *link, 
00397                                   BucketIndex index,
00398                                   BucketIndex bucketIndex )
00399 {
00400    // find last item of the bucket and swap it with the 'removed' one.
00401    // set removed items flags to 'available'.
00402    // if last page only contains 'available' items, then desallocate it (it's empty)
00403    ValueInternalLink *&lastLink = getLastLinkInBucket( index );
00404    BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
00405    for ( ;   
00406          lastItemIndex < ValueInternalLink::itemPerLink; 
00407          ++lastItemIndex ) // may be optimized with dicotomic search
00408    {
00409       if ( lastLink->items_[lastItemIndex].isItemAvailable() )
00410          break;
00411    }
00412    
00413    BucketIndex lastUsedIndex = lastItemIndex - 1;
00414    Value *valueToDelete = &link->items_[index];
00415    Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
00416    if ( valueToDelete != valueToPreserve )
00417       valueToDelete->swap( *valueToPreserve );
00418    if ( lastUsedIndex == 0 )  // page is now empty
00419    {  // remove it from bucket linked list and delete it.
00420       ValueInternalLink *linkPreviousToLast = lastLink->previous_;
00421       if ( linkPreviousToLast != 0 )   // can not deleted bucket link.
00422       {
00423          mapAllocator()->releaseMapLink( lastLink );
00424          linkPreviousToLast->next_ = 0;
00425          lastLink = linkPreviousToLast;
00426       }
00427    }
00428    else
00429    {
00430       Value dummy;
00431       valueToPreserve->swap( dummy ); // restore deleted to default Value.
00432       valueToPreserve->setItemUsed( false );
00433    }
00434    --itemCount_;
00435 }
00436 
00437 
00438 ValueInternalLink *&
00439 ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
00440 {
00441    if ( bucketIndex == bucketsSize_ - 1 )
00442       return tailLink_;
00443    ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
00444    if ( !previous )
00445       previous = &buckets_[bucketIndex];
00446    return previous;
00447 }
00448 
00449 
00450 Value &
00451 ValueInternalMap::setNewItem( const char *key, 
00452                               bool isStatic,
00453                               ValueInternalLink *link, 
00454                               BucketIndex index )
00455 {
00456    char *duplicatedKey = valueAllocator()->makeMemberName( key );
00457    ++itemCount_;
00458    link->keys_[index] = duplicatedKey;
00459    link->items_[index].setItemUsed();
00460    link->items_[index].setMemberNameIsStatic( isStatic );
00461    return link->items_[index]; // items already default constructed.
00462 }
00463 
00464 
00465 Value &
00466 ValueInternalMap::unsafeAdd( const char *key, 
00467                              bool isStatic, 
00468                              HashKey hashedKey )
00469 {
00470    JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
00471    BucketIndex bucketIndex = hashedKey % bucketsSize_;
00472    ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
00473    ValueInternalLink *link = previousLink;
00474    BucketIndex index;
00475    for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
00476    {
00477       if ( link->items_[index].isItemAvailable() )
00478          break;
00479    }
00480    if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
00481    {
00482       ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
00483       index = 0;
00484       link->next_ = newLink;
00485       previousLink = newLink;
00486       link = newLink;
00487    }
00488    return setNewItem( key, isStatic, link, index );
00489 }
00490 
00491 
00492 ValueInternalMap::HashKey 
00493 ValueInternalMap::hash( const char *key ) const
00494 {
00495    HashKey hash = 0;
00496    while ( *key )
00497       hash += *key++ * 37;
00498    return hash;
00499 }
00500 
00501 
00502 int 
00503 ValueInternalMap::compare( const ValueInternalMap &other ) const
00504 {
00505    int sizeDiff( itemCount_ - other.itemCount_ );
00506    if ( sizeDiff != 0 )
00507       return sizeDiff;
00508    // Strict order guaranty is required. Compare all keys FIRST, then compare values.
00509    IteratorState it;
00510    IteratorState itEnd;
00511    makeBeginIterator( it );
00512    makeEndIterator( itEnd );
00513    for ( ; !equals(it,itEnd); increment(it) )
00514    {
00515       if ( !other.find( key( it ) ) )
00516          return 1;
00517    }
00518 
00519    // All keys are equals, let's compare values
00520    makeBeginIterator( it );
00521    for ( ; !equals(it,itEnd); increment(it) )
00522    {
00523       const Value *otherValue = other.find( key( it ) );
00524       int valueDiff = value(it).compare( *otherValue );
00525       if ( valueDiff != 0 )
00526          return valueDiff;
00527    }
00528    return 0;
00529 }
00530 
00531 
00532 void 
00533 ValueInternalMap::makeBeginIterator( IteratorState &it ) const
00534 {
00535    it.map_ = const_cast<ValueInternalMap *>( this );
00536    it.bucketIndex_ = 0;
00537    it.itemIndex_ = 0;
00538    it.link_ = buckets_;
00539 }
00540 
00541 
00542 void 
00543 ValueInternalMap::makeEndIterator( IteratorState &it ) const
00544 {
00545    it.map_ = const_cast<ValueInternalMap *>( this );
00546    it.bucketIndex_ = bucketsSize_;
00547    it.itemIndex_ = 0;
00548    it.link_ = 0;
00549 }
00550 
00551 
00552 bool 
00553 ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
00554 {
00555    return x.map_ == other.map_  
00556           &&  x.bucketIndex_ == other.bucketIndex_  
00557           &&  x.link_ == other.link_
00558           &&  x.itemIndex_ == other.itemIndex_;
00559 }
00560 
00561 
00562 void 
00563 ValueInternalMap::incrementBucket( IteratorState &iterator )
00564 {
00565    ++iterator.bucketIndex_;
00566    JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
00567       "ValueInternalMap::increment(): attempting to iterate beyond end." );
00568    if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
00569       iterator.link_ = 0;
00570    else
00571       iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
00572    iterator.itemIndex_ = 0;
00573 }
00574 
00575 
00576 void 
00577 ValueInternalMap::increment( IteratorState &iterator )
00578 {
00579    JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
00580    ++iterator.itemIndex_;
00581    if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
00582    {
00583       JSON_ASSERT_MESSAGE( iterator.link_ != 0,
00584          "ValueInternalMap::increment(): attempting to iterate beyond end." );
00585       iterator.link_ = iterator.link_->next_;
00586       if ( iterator.link_ == 0 )
00587          incrementBucket( iterator );
00588    }
00589    else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
00590    {
00591       incrementBucket( iterator );
00592    }
00593 }
00594 
00595 
00596 void 
00597 ValueInternalMap::decrement( IteratorState &iterator )
00598 {
00599    if ( iterator.itemIndex_ == 0 )
00600    {
00601       JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
00602       if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
00603       {
00604          JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
00605          --(iterator.bucketIndex_);
00606       }
00607       iterator.link_ = iterator.link_->previous_;
00608       iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
00609    }
00610 }
00611 
00612 
00613 const char *
00614 ValueInternalMap::key( const IteratorState &iterator )
00615 {
00616    JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
00617    return iterator.link_->keys_[iterator.itemIndex_];
00618 }
00619 
00620 const char *
00621 ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
00622 {
00623    JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
00624    isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
00625    return iterator.link_->keys_[iterator.itemIndex_];
00626 }
00627 
00628 
00629 Value &
00630 ValueInternalMap::value( const IteratorState &iterator )
00631 {
00632    JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
00633    return iterator.link_->items_[iterator.itemIndex_];
00634 }
00635 
00636 
00637 int 
00638 ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
00639 {
00640    int offset = 0;
00641    IteratorState it = x;
00642    while ( !equals( it, y ) )
00643       increment( it );
00644    return offset;
00645 }