include/Dictionary.h
author Jens Alfke <jens@mooseyard.com>
Sun Sep 20 15:14:12 2009 -0700 (2009-09-20)
changeset 0 31a43d94cc26
child 3 8e3ae153e2c9
permissions -rw-r--r--
First official checkin.
jens@0
     1
/*
jens@0
     2
 *  Dictionary.h
jens@0
     3
 *  Ottoman
jens@0
     4
 *
jens@0
     5
 *  Created by Jens Alfke on 8/23/09.
jens@0
     6
 *  Copyright 2009 Jens Alfke. All rights reserved.
jens@0
     7
 *  BSD-Licensed: See the file "LICENSE.txt" for details.
jens@0
     8
 */
jens@0
     9
jens@0
    10
#ifndef _MOOSEYARD_DICTIONARY_
jens@0
    11
#define _MOOSEYARD_DICTIONARY_
jens@0
    12
#include "Base.h"
jens@0
    13
jens@0
    14
namespace Mooseyard {
jens@0
    15
jens@0
    16
    typedef uint32_t HashCode;
jens@0
    17
    
jens@0
    18
    /** A Key is a data blob treated as a dictionary key.
jens@0
    19
        It carries its hash-code around with it, to avoid redundant computation. */
jens@0
    20
    struct Key :public Blob {
jens@0
    21
        HashCode hash;
jens@0
    22
        
jens@0
    23
        Key ()                                          :Blob(), hash(0) { }
jens@0
    24
        explicit Key (const Blob &b)                    :Blob(b), hash(computeHash(b)) { }
jens@0
    25
        Key (const Blob &b, HashCode h)                 :Blob(b), hash(h) { }
jens@0
    26
        Key (const char *str)                           :Blob(str), hash(computeHash(*this)) { }
jens@0
    27
        Key (const void *b, uint32_t len, HashCode h)   :Blob(b,len), hash(h) { }
jens@0
    28
jens@0
    29
        static HashCode computeHash (Blob);
jens@0
    30
    };
jens@0
    31
    
jens@0
    32
    
jens@0
    33
    /** An abstract interface for key/value dictionaries.
jens@0
    34
        Dictionary itself is read-only; its subclass MutableDictionary allows changes. */
jens@0
    35
    class Dictionary {
jens@0
    36
    public:
jens@0
    37
        class Iterator;
jens@0
    38
        class ChangeIterator;
jens@0
    39
jens@0
    40
        virtual ~Dictionary();
jens@0
    41
        
jens@0
    42
        /** The number of items in the dictionary. */
jens@0
    43
        virtual int count() const =0;
jens@0
    44
        
jens@0
    45
        /** Returns the value associated with the given key.
jens@0
    46
            Keys are compared by exact binary data equality.
jens@0
    47
            The data pointed to by the value returned is valid at least until the next call to
jens@0
    48
            this Dictionary; some subclasses may guarantee a longer lifetime.
jens@0
    49
            If there is no value for the given key, a Blob of {NULL, 0} will be returned. */
jens@0
    50
        virtual Blob get (Key) const =0;
jens@0
    51
        
jens@0
    52
        /** Returns true iff there is a value associated with the given key. */
jens@0
    53
        virtual bool contains (Key key) const      {return get(key).bytes != NULL;}
jens@0
    54
        
jens@0
    55
        /** Returns a pointer to a new Iterator object that can be used to iterate this Dictionary.
jens@0
    56
            The iterator must be deleted when you're done with it. */
jens@0
    57
        virtual Iterator* iterate() const =0;
jens@0
    58
        
jens@0
    59
        /** A singleton empty Dictionary. */
jens@0
    60
        static const Dictionary& kEmpty;
jens@0
    61
        
jens@0
    62
        // utilities
jens@0
    63
        /** Returns a suggested size for a hash table that can hold 'capacity' items without
jens@0
    64
            being more than the 'load' fraction full; result is always a power of two. */
jens@0
    65
        static int choosePowerOfTwoSize (int capacity, float load = kMaxLoadFactor);
jens@0
    66
jens@0
    67
        static int chooseAnyOldSize (int capacity, float load = kMaxLoadFactor);
jens@0
    68
jens@0
    69
        static const int   kMinSize;
jens@0
    70
        static const float kMinLoadFactor;
jens@0
    71
        static const float kMaxLoadFactor;
jens@0
    72
        
jens@0
    73
    protected:
jens@0
    74
        Dictionary();
jens@0
    75
    };
jens@0
    76
    
jens@0
    77
    
jens@0
    78
    /** An abstract interface for mutable key/value dictionaries; extends Dictionary. */
jens@0
    79
    class MutableDictionary : public Dictionary {
jens@0
    80
    public:
jens@0
    81
        /** Stores the given value for the given key, replacing any prior value.
jens@0
    82
            The memory for the key and value is copied, so you don't need to preserve it after
jens@0
    83
            the call returns. */
jens@0
    84
        virtual void put (Key, Blob value) =0;
jens@0
    85
        
jens@0
    86
        /** Adds the contents of the given Dictionary to this one.
jens@0
    87
            Effectively calls this->put() with every key/value pair in the source Dictionary. */
jens@0
    88
        virtual void add (Dictionary*);
jens@0
    89
        
jens@0
    90
        /** Removes the value for the given key, if any.
jens@0
    91
            Returns true if the value was removed, false if there was no value. */
jens@0
    92
        virtual bool remove (Key) =0;
jens@0
    93
        
jens@0
    94
        /** Removes all keys and values, returning the dictionary to an empty state. */
jens@0
    95
        virtual void removeAll() = 0;
jens@0
    96
    };
jens@0
    97
    
jens@0
    98
    
jens@0
    99
    /** Abstract iterator interface. Each Dictionary subclass defines its own.
jens@0
   100
        The order in which items are returned is undefined, and in effect quite random, due to
jens@0
   101
        the properties of hash tables. */
jens@0
   102
    class Dictionary::Iterator {
jens@0
   103
    public:
jens@0
   104
        virtual ~Iterator();
jens@0
   105
        
jens@0
   106
        /** The current key the iterator is pointing to. */
jens@0
   107
        virtual Key key() const =0;
jens@0
   108
        /** The current value the iterator is pointing to. */
jens@0
   109
        virtual Blob value() const =0;
jens@0
   110
        /** Returns true if the iterator has a current item, or false if it's reached the end. */
jens@0
   111
        virtual bool hasValue() const           {return key().bytes != 0;}
jens@0
   112
        /** Advances the Iterator to the next item. Returns false if it's reached the end.
jens@0
   113
            (Note that the order of items is undefined and in practice quite random.) */
jens@0
   114
        virtual bool next() =0;
jens@0
   115
        
jens@0
   116
        operator bool() const                   {return hasValue();}
jens@0
   117
        Iterator& operator++()                  {next(); return *this;}
jens@0
   118
    };
jens@0
   119
    
jens@0
   120
    class OverlayDictionary;
jens@0
   121
    
jens@0
   122
    
jens@0
   123
    /** An iterator that walks through the differences between two Dictionaries. */
jens@0
   124
    class Dictionary::ChangeIterator :public Dictionary::Iterator {
jens@0
   125
    public:
jens@0
   126
        ChangeIterator (const Dictionary *dict1, const Dictionary *dict2);
jens@0
   127
        explicit ChangeIterator (const OverlayDictionary*);
jens@0
   128
        virtual ~ChangeIterator();
jens@0
   129
        
jens@0
   130
        /** Returns the current key, whose values in the two dictionaries differ. */
jens@0
   131
        virtual Key key() const                 {return _iter->key();}
jens@0
   132
        /** Returns the corresponding value from dict1.
jens@0
   133
            May be empty (NULL,0) if the key does not appear in dict1 (i.e. inserted into dict2.) */
jens@0
   134
        virtual Blob value() const              {return _iter->value();}
jens@0
   135
        /** Returns the corresponding value from dict2.
jens@0
   136
            May be empty (NULL,0) if the key does not appear in dict2 (i.e. deleted from dict2.) */
jens@0
   137
        virtual Blob otherValue() const         {return _otherValue;}
jens@0
   138
        virtual bool hasValue() const           {return _iter->hasValue();}
jens@0
   139
        virtual bool next();
jens@0
   140
        
jens@0
   141
    private:
jens@0
   142
        void _init (const Dictionary *dict1, const Dictionary *dict2);
jens@0
   143
        bool _skipMatching();
jens@0
   144
        const Dictionary *_dict2;
jens@0
   145
        Iterator *_iter;
jens@0
   146
        Blob _otherValue;
jens@0
   147
    };
jens@0
   148
    
jens@0
   149
    
jens@0
   150
    /** Adapter class that allows a Dictionary to appear to be mutable, by using a separate
jens@0
   151
        mutable dictionary to remember the changes. */
jens@0
   152
    class OverlayDictionary :public MutableDictionary {
jens@0
   153
    public:
jens@0
   154
        /** Creates a mutable dictionary that overlays base. Initially its contents will appear
jens@0
   155
            identical to base. It can be changed, but the changes will not affect the base. */
jens@0
   156
        explicit OverlayDictionary (const Dictionary *base);
jens@0
   157
        virtual ~OverlayDictionary();
jens@0
   158
        
jens@0
   159
        /** The base dictionary this is overlaying. */
jens@0
   160
        const Dictionary* base() const              {return _base;}
jens@0
   161
        /** The dictionary that contains the changes made to the base.
jens@0
   162
            Only keys/values that have been changed appear here. */
jens@0
   163
        const Dictionary* overlay() const           {return _overlay;}
jens@0
   164
        /** Returns true if changes have been made. */
jens@0
   165
        bool isChanged() const;
jens@0
   166
        /** Returns true if the base has been completely replaced by calling removeAll. */
jens@0
   167
        bool baseReplaced() const                   {return _allRemoved;}
jens@0
   168
        
jens@0
   169
        /** Removes all changes, restoring the overlay to look identical to the base. */
jens@0
   170
        void revert();
jens@0
   171
        /** Changes the overlay to a new base, clearing all changes. */
jens@0
   172
        void revertTo (const Dictionary* newBase);
jens@0
   173
        
jens@0
   174
        /** Changes the base without clearing changes. */
jens@0
   175
        void rebase (const Dictionary* newBase);
jens@0
   176
        
jens@0
   177
        virtual int count() const;
jens@0
   178
        virtual Blob get (Key) const;
jens@0
   179
        virtual bool contains (Key) const;
jens@0
   180
        virtual void put (Key, Blob value);
jens@0
   181
        virtual bool remove (Key);
jens@0
   182
        virtual void removeAll();
jens@0
   183
        virtual Iterator* iterate() const           {return new Iterator(*this);}
jens@0
   184
        
jens@0
   185
        class Iterator :public Dictionary::Iterator {
jens@0
   186
        public:
jens@0
   187
            explicit Iterator (const OverlayDictionary&);
jens@0
   188
            virtual Key key() const;
jens@0
   189
            virtual Blob value() const;
jens@0
   190
            virtual bool next();
jens@0
   191
        private:
jens@0
   192
            bool skipCurrentState();
jens@0
   193
            Dictionary::Iterator *_iter;
jens@0
   194
            const MutableDictionary *_overlay;
jens@0
   195
        };
jens@0
   196
        
jens@0
   197
    private:
jens@0
   198
        const Dictionary *_base;
jens@0
   199
        MutableDictionary *_overlay;
jens@0
   200
        int _count;
jens@0
   201
        bool _allRemoved;
jens@0
   202
        friend class ChangeIterator;
jens@0
   203
    };
jens@0
   204
    
jens@0
   205
    
jens@0
   206
}
jens@0
   207
jens@0
   208
#endif _MOOSEYARD_DICTIONARY_