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