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