First official checkin.
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.
10 #include "Dictionary.h"
18 Dictionary::Dictionary() {
21 Dictionary::~Dictionary() {
24 Dictionary::Iterator::~Iterator() {
28 const int Dictionary::kMinSize = 8;
29 const float Dictionary::kMinLoadFactor = 0.25;
30 const float Dictionary::kMaxLoadFactor = 0.75;
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;
37 for (size=kMinSize; size<idealSize; size *= 2)
42 int Dictionary::chooseAnyOldSize (int capacity, float load) {
43 return std::max((int)::ceil(capacity / load), 2);
47 //-----------------------------------------------------------------------------
48 // MurmurHashNeutral2, by Austin Appleby
49 // http://murmurhash.googlepages.com/MurmurHashNeutral2.cpp
51 // Same as MurmurHash2, but endian- and alignment-neutral.
52 // Half the speed though, alas.
54 static uint32_t MurmurHashNeutral2 ( const void * key, int32_t len, uint32_t seed )
56 static const uint32_t m = 0x5bd1e995;
57 static const int32_t r = 24;
59 uint32_t h = seed ^ len;
61 const unsigned char * data = (const unsigned char *)key;
85 case 3: h ^= data[2] << 16;
86 case 2: h ^= data[1] << 8;
98 HashCode Key::computeHash (Blob key) {
99 return MurmurHashNeutral2(key.bytes, key.length, 0);
104 void MutableDictionary::add (Dictionary* dict) {
105 Iterator *it = dict->iterate();
106 for (; *it; it->next())
107 put(it->key(), it->value());
113 const Dictionary& Dictionary::kEmpty = * new HashDictionary();
117 #pragma mark KEY AND VALUE
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);
136 return Blob(&_keyLength+1, _keyLength);
140 const uint32_t *v = this->valueLengthPtr();
141 if (*v != kDeletedValue.length)
142 return Blob(v+1, *v);
144 return kDeletedValue;
147 /** Magic value OverlayDictionary stores in me to represent a deleted value. */
148 static const Blob kDeletedValue;
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;
157 //...there follows the key, valueLength and value...
160 const Blob KeyAndValue::kDeletedValue(NULL, (size_t)-1);
166 #pragma mark HASH DICTIONARY:
168 HashDictionary::~HashDictionary() {
172 Blob HashDictionary::_convertValue (void *value) {
173 return value ?((KeyAndValue*)value)->value() :Blob();
176 bool HashDictionary::contains (Key key) const {
177 Blob value = get(key);
178 return value.bytes || value.length;
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);
188 bool HashDictionary::remove (Key key) {
189 KeyAndValue *kv = (KeyAndValue*) _hash.get(key);
197 void HashDictionary::removeAll() {
198 for (Hash::Iterator it(&_hash); it; ++it)
207 #pragma mark OVERLAY DICTIONARY:
210 OverlayDictionary::OverlayDictionary (const Dictionary *base)
212 _overlay(new HashDictionary()),
213 _count(base->count()),
217 OverlayDictionary::~OverlayDictionary() {
221 int OverlayDictionary::count() const {
225 bool OverlayDictionary::isChanged() const {
226 return _overlay->count() > 0;
229 Blob OverlayDictionary::get (Key key) const {
230 Blob result = _overlay->get(key);
232 if (result==KeyAndValue::kDeletedValue)
233 result = Blob(); // It's been marked as deleted
234 else if (!_allRemoved)
235 result = _base->get(key);
240 bool OverlayDictionary::contains (Key key) const {
241 Blob result = _overlay->get(key);
244 else if (result==KeyAndValue::kDeletedValue)
246 else if (!_allRemoved)
247 return _base->get(key);
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))
259 bool OverlayDictionary::remove (Key key) {
260 if (!_allRemoved && _base->contains(key)) {
261 _overlay->put(key,KeyAndValue::kDeletedValue);
264 } else if (_overlay->remove(key)) {
271 void OverlayDictionary::removeAll() {
277 void OverlayDictionary::revert() {
278 _overlay->removeAll();
279 _count = _base->count();
283 void OverlayDictionary::revertTo (const Dictionary* newBase) {
288 void OverlayDictionary::rebase (const Dictionary* newBase) {
292 OverlayDictionary::Iterator::Iterator (const OverlayDictionary &dict)
293 :_iter(dict.base()->iterate()),
294 _overlay(dict._overlay)
296 if (skipCurrentState())
300 Key OverlayDictionary::Iterator::key() const {return _iter ?_iter->key() :Key();}
301 Blob OverlayDictionary::Iterator::value() const {return _iter ?_iter->value() :Blob();}
303 bool OverlayDictionary::Iterator::next() {
307 } while (skipCurrentState());
309 return _iter && *_iter;
312 bool OverlayDictionary::Iterator::skipCurrentState() {
316 if (_overlay->contains(_iter->key()))
317 return true; // Skip overridden value in base dict
319 if (_iter->value() == KeyAndValue::kDeletedValue)
320 return true; // Skip marked-deleted value in overlay dict
325 // end of base iterator; switch to overlay
326 _iter = _overlay->iterate();
328 return skipCurrentState();
339 #pragma mark CHANGE ITERATOR:
342 Dictionary::ChangeIterator::ChangeIterator (const Dictionary *dict1, const Dictionary *dict2) {
346 Dictionary::ChangeIterator::ChangeIterator (const OverlayDictionary *overlay) {
347 _init(overlay->_overlay, overlay->base());
350 void Dictionary::ChangeIterator::_init(const Dictionary *dict1, const Dictionary *dict2) {
352 _iter = dict1->iterate();
357 Dictionary::ChangeIterator::~ChangeIterator() {
361 bool Dictionary::ChangeIterator::next() {
362 return _iter->next() && this->_skipMatching();
365 bool Dictionary::ChangeIterator::_skipMatching() {
367 _otherValue = _dict2->get(_iter->key());
368 if (!_otherValue.equals(_iter->value()))
370 }while (_iter->next());