src/Dictionary.cpp
author Jens Alfke <jens@mooseyard.com>
Sun Sep 20 15:14:12 2009 -0700 (2009-09-20)
changeset 0 31a43d94cc26
child 2 851de24ecb61
permissions -rw-r--r--
First official checkin.
     1 /*
     2  *  Dictionary.cpp
     3  *  Ottoman
     4  *
     5  *  Created by Jens Alfke on 8/23/09.
     6  *  Copyright 2009 Jens Alfke. All rights reserved.
     7  *  BSD-Licensed: See the file "LICENSE.txt" for details.
     8  */
     9 
    10 #include "Dictionary.h"
    11 #include "Hash.h"
    12 #include <assert.h>
    13 #include <algorithm>
    14 #include <math.h>
    15 
    16 namespace Mooseyard {
    17     
    18     Dictionary::Dictionary() {
    19     }
    20     
    21     Dictionary::~Dictionary() {
    22     }
    23     
    24     Dictionary::Iterator::~Iterator() {
    25     }
    26     
    27     
    28     const int Dictionary::kMinSize = 8;
    29     const float Dictionary::kMinLoadFactor = 0.25;
    30     const float Dictionary::kMaxLoadFactor = 0.75;
    31         
    32     // Choose the smallest power of two that's large enough to hold the given capacity
    33     // of entries with no greater than the given load (fraction full).
    34     int Dictionary::choosePowerOfTwoSize (int capacity, float load) {
    35         int idealSize = capacity / load;
    36         int size;
    37         for (size=kMinSize; size<idealSize; size *= 2)
    38             ;
    39         return size;
    40     }
    41     
    42     int Dictionary::chooseAnyOldSize (int capacity, float load) {
    43         return std::max((int)::ceil(capacity / load), 2);
    44     }
    45     
    46     
    47     //-----------------------------------------------------------------------------
    48     // MurmurHashNeutral2, by Austin Appleby
    49     // http://murmurhash.googlepages.com/MurmurHashNeutral2.cpp
    50     
    51     // Same as MurmurHash2, but endian- and alignment-neutral.
    52     // Half the speed though, alas.
    53     
    54     static uint32_t MurmurHashNeutral2 ( const void * key, int32_t len, uint32_t seed )
    55     {
    56         static const uint32_t m = 0x5bd1e995;
    57         static const int32_t r = 24;
    58         
    59         uint32_t h = seed ^ len;
    60         
    61         const unsigned char * data = (const unsigned char *)key;
    62         
    63         while(len >= 4)
    64         {
    65             uint32_t k;
    66             
    67             k  = data[0];
    68             k |= data[1] << 8;
    69             k |= data[2] << 16;
    70             k |= data[3] << 24;
    71             
    72             k *= m; 
    73             k ^= k >> r; 
    74             k *= m;
    75             
    76             h *= m;
    77             h ^= k;
    78             
    79             data += 4;
    80             len -= 4;
    81         }
    82         
    83         switch(len)
    84         {
    85             case 3: h ^= data[2] << 16;
    86             case 2: h ^= data[1] << 8;
    87             case 1: h ^= data[0];
    88                 h *= m;
    89         };
    90         
    91         h ^= h >> 13;
    92         h *= m;
    93         h ^= h >> 15;
    94         
    95         return h;
    96     } 
    97     
    98     HashCode Key::computeHash (Blob key) {
    99         return MurmurHashNeutral2(key.bytes, key.length, 0);
   100     }
   101     
   102     
   103     
   104     void MutableDictionary::add (Dictionary* dict) {
   105         Iterator *it = dict->iterate();
   106         for (; *it; it->next())
   107             put(it->key(), it->value());
   108         delete it;
   109     }
   110     
   111     
   112         
   113     const Dictionary& Dictionary::kEmpty = * new HashDictionary();
   114     
   115 
   116 #pragma mark -
   117 #pragma mark KEY AND VALUE
   118     
   119     class KeyAndValue {
   120     public:
   121         static KeyAndValue* create (Blob key, Blob value) {
   122             size_t size = 2*sizeof(uint32_t) + key.length;
   123             size = (size + 0x3) & ~0x3; // 32-bit align start of value
   124             if (value!=kDeletedValue)
   125                 size += value.length;
   126             KeyAndValue *kv = (KeyAndValue*) ::operator new(size);
   127             kv->_keyLength = key.length;
   128             memcpy(&kv->_keyLength + 1, key.bytes, key.length);
   129             uint32_t *valueLengthPtr = const_cast<uint32_t*>(kv->valueLengthPtr());
   130             *valueLengthPtr = value.length;
   131             if (value!=kDeletedValue)
   132                 memcpy(valueLengthPtr + 1, value.bytes, value.length);
   133             return kv;
   134         }
   135         Blob key() const {
   136             return Blob(&_keyLength+1, _keyLength);
   137         }
   138         
   139         Blob value() const{
   140             const uint32_t *v = this->valueLengthPtr();
   141             if (*v != kDeletedValue.length)
   142                 return Blob(v+1, *v);
   143             else
   144                 return kDeletedValue;
   145         }
   146 
   147         /** Magic value OverlayDictionary stores in me to represent a deleted value. */
   148         static const Blob kDeletedValue;
   149     private:
   150         const uint32_t* valueLengthPtr() const {
   151             size_t ptr = (size_t)(&_keyLength + 1) + _keyLength;
   152             ptr = (ptr + 0x3) & ~0x3;       // 32-bit align
   153             return (uint32_t*)ptr;
   154         }
   155         
   156         uint32_t _keyLength;
   157         //...there follows the key, valueLength and value...
   158     };
   159 
   160     const Blob KeyAndValue::kDeletedValue(NULL, (size_t)-1);
   161 
   162     
   163 
   164     
   165 #pragma mark -
   166 #pragma mark HASH DICTIONARY:
   167     
   168     HashDictionary::~HashDictionary() {
   169         removeAll();
   170     }
   171     
   172     Blob HashDictionary::_convertValue (void *value) {
   173         return value ?((KeyAndValue*)value)->value() :Blob();
   174     }
   175     
   176     bool HashDictionary::contains (Key key) const {
   177         Blob value = get(key);
   178         return value.bytes || value.length;
   179     }
   180 
   181     
   182     void HashDictionary::put (Key key, Blob value) {
   183         // Allocate a block to store both the Blob struct and the data
   184         KeyAndValue *kv = KeyAndValue::create(key,value);
   185         _hash.put(Key(kv->key(),key.hash), kv);
   186     }
   187     
   188     bool HashDictionary::remove (Key key) {
   189         KeyAndValue *kv = (KeyAndValue*) _hash.get(key);
   190         if (kv) {
   191             free(kv);
   192             return true;
   193         } else
   194             return false;
   195     }
   196     
   197     void HashDictionary::removeAll() {
   198         for (Hash::Iterator it(&_hash); it; ++it)
   199             free(it.value());
   200         _hash.removeAll();
   201     }
   202         
   203     
   204     
   205     
   206 #pragma mark -
   207 #pragma mark OVERLAY DICTIONARY:
   208     
   209     
   210     OverlayDictionary::OverlayDictionary (const Dictionary *base)
   211     :_base(base),
   212      _overlay(new HashDictionary()),
   213      _count(base->count()),
   214      _allRemoved(false)
   215     { }
   216     
   217     OverlayDictionary::~OverlayDictionary() {
   218         delete _overlay;
   219     }
   220     
   221     int OverlayDictionary::count() const {
   222         return _count;
   223     }
   224     
   225     bool OverlayDictionary::isChanged() const {
   226         return _overlay->count() > 0;
   227     }
   228     
   229     Blob OverlayDictionary::get (Key key) const {
   230         Blob result = _overlay->get(key);
   231         if (!result) {
   232             if (result==KeyAndValue::kDeletedValue)
   233                 result = Blob();                // It's been marked as deleted
   234             else if (!_allRemoved)
   235                 result = _base->get(key);
   236         }
   237         return result;
   238     }
   239     
   240     bool OverlayDictionary::contains (Key key) const {
   241         Blob result = _overlay->get(key);
   242         if (result)
   243             return true;
   244         else if (result==KeyAndValue::kDeletedValue)
   245             return false;
   246         else if (!_allRemoved)
   247             return _base->get(key);
   248         else 
   249             return false;
   250     }
   251     
   252     void OverlayDictionary::put (Key key, Blob value) {
   253         assert(value.bytes || value.length==0);    // make sure it doesn't look like magic kDeletedValue
   254         _overlay->put(key,value);
   255         if (_allRemoved || !_base->contains(key))
   256             _count++;
   257     }
   258     
   259     bool OverlayDictionary::remove (Key key) {
   260         if (!_allRemoved && _base->contains(key)) {
   261             _overlay->put(key,KeyAndValue::kDeletedValue);
   262             _count--;
   263             return true;
   264         } else if (_overlay->remove(key)) {
   265             _count--;
   266             return true;
   267         } else
   268             return false;
   269     }
   270     
   271     void OverlayDictionary::removeAll() {
   272         _allRemoved = true;
   273         _count = 0;
   274     }
   275     
   276     
   277     void OverlayDictionary::revert() {
   278         _overlay->removeAll();
   279         _count = _base->count();
   280         _allRemoved = false;
   281     }
   282     
   283     void OverlayDictionary::revertTo (const Dictionary* newBase) {
   284         _base = newBase;
   285         revert();
   286     }
   287     
   288     void OverlayDictionary::rebase (const Dictionary* newBase) {
   289         _base = newBase;
   290     }
   291 
   292     OverlayDictionary::Iterator::Iterator (const OverlayDictionary &dict)
   293         :_iter(dict.base()->iterate()),
   294          _overlay(dict._overlay)
   295     {
   296         if (skipCurrentState())
   297             next();
   298     }
   299     
   300     Key OverlayDictionary::Iterator::key() const        {return _iter ?_iter->key() :Key();}
   301     Blob OverlayDictionary::Iterator::value() const     {return _iter ?_iter->value() :Blob();}
   302     
   303     bool OverlayDictionary::Iterator::next() {
   304         if (_iter) {
   305             do {
   306                 _iter->next();
   307             } while (skipCurrentState());
   308         }
   309         return _iter && *_iter;
   310     }
   311     
   312     bool OverlayDictionary::Iterator::skipCurrentState() {
   313         if (_iter) {
   314             if (*_iter) {
   315                 if (_overlay) {
   316                     if (_overlay->contains(_iter->key()))
   317                         return true;        // Skip overridden value in base dict
   318                 } else {
   319                     if (_iter->value() == KeyAndValue::kDeletedValue)
   320                         return true;        // Skip marked-deleted value in overlay dict
   321                 }
   322             } else {
   323                 delete _iter;
   324                 if (_overlay) {
   325                     // end of base iterator; switch to overlay
   326                     _iter = _overlay->iterate();
   327                     _overlay = NULL;
   328                     return skipCurrentState();
   329                 } else {
   330                     _iter = NULL;
   331                 }
   332             }
   333         }
   334         return false;
   335     }
   336     
   337     
   338 #pragma mark -
   339 #pragma mark CHANGE ITERATOR:
   340     
   341     
   342     Dictionary::ChangeIterator::ChangeIterator (const Dictionary *dict1, const Dictionary *dict2) {
   343         _init(dict1, dict2);
   344     }
   345     
   346     Dictionary::ChangeIterator::ChangeIterator (const OverlayDictionary *overlay) {
   347         _init(overlay->_overlay, overlay->base());
   348     }
   349     
   350     void Dictionary::ChangeIterator::_init(const Dictionary *dict1, const Dictionary *dict2) {
   351         _dict2 = dict2;
   352         _iter = dict1->iterate();
   353         if (*_iter)
   354             _skipMatching();
   355     }
   356     
   357     Dictionary::ChangeIterator::~ChangeIterator() {
   358         delete _iter;
   359     }
   360     
   361     bool Dictionary::ChangeIterator::next() {
   362         return _iter->next() && this->_skipMatching();
   363     }
   364     
   365     bool Dictionary::ChangeIterator::_skipMatching() {
   366         do{
   367             _otherValue = _dict2->get(_iter->key());
   368             if (!_otherValue.equals(_iter->value()))
   369                 return true;
   370         }while (_iter->next());
   371         return false;
   372     }
   373     
   374     
   375 
   376 }