LCOV - code coverage report
Current view: top level - src - Dict.h (source / functions) Hit Total Coverage
Test: app.info Lines: 22 26 84.6 %
Date: 2010-12-13 Functions: 19 22 86.4 %
Branches: 2 4 50.0 %

           Branch data     Line data    Source code
       1                 :            : // $Id: Dict.h 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #ifndef dict_h
       6                 :            : #define dict_h
       7                 :            : 
       8                 :            : #include "List.h"
       9                 :            : #include "Hash.h"
      10                 :            : 
      11                 :            : class Dictionary;
      12                 :            : class DictEntry;
      13                 :            : class IterCookie;
      14                 :            : 
      15                 :     529340 : declare(PList,DictEntry);
      16                 :      49134 : declare(PList,IterCookie);
      17                 :            : 
      18                 :            : // Default number of hash buckets in dictionary.  The dictionary will
      19                 :            : // increase the size of the hash table as needed.
      20                 :            : #define DEFAULT_DICT_SIZE 16
      21                 :            : 
      22                 :            : // Type indicating whether the dictionary should keep track of the order
      23                 :            : // of insertions.
      24                 :            : typedef enum { ORDERED, UNORDERED } dict_order;
      25                 :            : 
      26                 :            : // Type for function to be called when deleting elements.
      27                 :            : typedef void (*dict_delete_func)(void*);
      28                 :            : 
      29                 :            : // A dict_delete_func that just calls delete.
      30                 :            : extern void generic_delete_func(void*);
      31                 :            : 
      32                 :            : class Dictionary {
      33                 :            : public:
      34                 :            :         Dictionary(dict_order ordering = UNORDERED,
      35                 :            :                         int initial_size = DEFAULT_DICT_SIZE);
      36                 :            :         virtual ~Dictionary();
      37                 :            : 
      38                 :            :         // Member functions for looking up a key, inserting/changing its
      39                 :            :         // contents, and deleting it.  These come in two flavors: one
      40                 :            :         // which takes a HashKey, and the other which takes a raw key,
      41                 :            :         // its size, and its (unmodulated) hash.
      42                 :     191810 :         void* Lookup(const HashKey* key) const
      43                 :     191810 :                 { return Lookup(key->Key(), key->Size(), key->Hash()); }
      44                 :            :         void* Lookup(const void* key, int key_size, hash_t hash) const;
      45                 :            : 
      46                 :            :         // Returns previous value, or 0 if none.
      47                 :      45428 :         void* Insert(HashKey* key, void* val)
      48                 :            :                 {
      49                 :      45428 :                 return Insert(key->TakeKey(), key->Size(), key->Hash(), val, 0);
      50                 :            :                 }
      51                 :            :         // If copy_key is true, then the key is copied, otherwise it's assumed
      52                 :            :         // that it's a heap pointer that now belongs to the Dictionary to
      53                 :            :         // manage as needed.
      54                 :            :         void* Insert(void* key, int key_size, hash_t hash, void* val,
      55                 :            :                         int copy_key);
      56                 :            : 
      57                 :            :         // Removes the given element.  Returns a pointer to the element in
      58                 :            :         // case it needs to be deleted.  Returns 0 if no such element exists.
      59                 :            :         // If dontdelete is true, the key's bytes will not be deleted.
      60                 :        938 :         void* Remove(const HashKey* key)
      61                 :        938 :                 { return Remove(key->Key(), key->Size(), key->Hash()); }
      62                 :            :         void* Remove(const void* key, int key_size, hash_t hash,
      63                 :            :                                 bool dont_delete = false);
      64                 :            : 
      65                 :            :         // Number of entries.
      66                 :      98332 :         int Length() const
      67         [ +  + ]:      98332 :                 { return tbl2 ? num_entries + num_entries2 : num_entries; }
      68                 :            : 
      69                 :            :         // Largest it's ever been.
      70                 :          0 :         int MaxLength() const
      71                 :            :                 {
      72                 :            :                 return tbl2 ?
      73         [ #  # ]:          0 :                         max_num_entries + max_num_entries2 : max_num_entries;
      74                 :            :                 }
      75                 :            : 
      76                 :            :         // True if the dictionary is ordered, false otherwise.
      77                 :            :         int IsOrdered() const           { return order != 0; }
      78                 :            : 
      79                 :            :         // If the dictionary is ordered then returns the n'th entry's value;
      80                 :            :         // the second method also returns the key.  The first entry inserted
      81                 :            :         // corresponds to n=0.
      82                 :            :         //
      83                 :            :         // Returns nil if the dictionary is not ordered or if "n" is out
      84                 :            :         // of range.
      85                 :          0 :         void* NthEntry(int n) const
      86                 :            :                 {
      87                 :            :                 const void* key;
      88                 :            :                 int key_len;
      89                 :          0 :                 return NthEntry(n, key, key_len);
      90                 :            :                 }
      91                 :            :         void* NthEntry(int n, const void*& key, int& key_len) const;
      92                 :            : 
      93                 :            :         // To iterate through the dictionary, first call InitForIteration()
      94                 :            :         // to get an "iteration cookie".  The cookie can then be handed
      95                 :            :         // to NextEntry() to get the next entry in the iteration and update
      96                 :            :         // the cookie.  If NextEntry() indicates no more entries, it will
      97                 :            :         // also delete the cookie, or the cookie can be manually deleted
      98                 :            :         // prior to this if no longer needed.
      99                 :            :         //
     100                 :            :         // Unexpected results will occur if the elements of
     101                 :            :         // the dictionary are changed between calls to NextEntry() without
     102                 :            :         // first calling InitForIteration().
     103                 :            :         //
     104                 :            :         // If return_hash is true, a HashKey for the entry is returned in h,
     105                 :            :         // which should be delete'd when no longer needed.
     106                 :            :         IterCookie* InitForIteration() const;
     107                 :            :         void* NextEntry(HashKey*& h, IterCookie*& cookie, int return_hash) const;
     108                 :            :         void* NextEntry(const void*& key, int& key_len, IterCookie*& cookie)
     109                 :            :                 const;
     110                 :            :         void StopIteration(IterCookie* cookie) const;
     111                 :            : 
     112                 :      14752 :         void SetDeleteFunc(dict_delete_func f)          { delete_func = f; }
     113                 :            : 
     114                 :            :         // With a robust cookie, it is safe to change the dictionary while
     115                 :            :         // iterating. This means that (i) we will eventually visit all
     116                 :            :         // unmodified entries as well as all entries added during iteration,
     117                 :            :         // and (ii) we won't visit any still-unseen entries which are getting
     118                 :            :         // removed. (We don't get this for free, so only use it if
     119                 :            :         // necessary.)
     120                 :       7834 :         void MakeRobustCookie(IterCookie* cookie)
     121                 :       7834 :                 { cookies.append(cookie); }
     122                 :            : 
     123                 :            :         unsigned int MemoryAllocation() const;
     124                 :            : 
     125                 :            : private:
     126                 :            :         void Init(int size);
     127                 :            :         void Init2(int size);   // initialize second table for resizing
     128                 :            : 
     129                 :            :         // Internal version of Insert().
     130                 :            :         void* Insert(DictEntry* entry, int copy_key);
     131                 :            : 
     132                 :            :         void* DoRemove(DictEntry* entry, hash_t h,
     133                 :            :                         PList(DictEntry)* chain, int chain_offset);
     134                 :            : 
     135                 :            :         int NextPrime(int n) const;
     136                 :            :         int IsPrime(int n) const;
     137                 :            :         void StartChangeSize(int new_size);
     138                 :            :         void FinishChangeSize(void);
     139                 :            :         void MoveChains(void);
     140                 :            : 
     141                 :            :         // The following get and set the "density" threshold - if the
     142                 :            :         // average hash chain length exceeds this threshold, the
     143                 :            :         // table will be resized.  The default value is 3.0.
     144                 :         55 :         double DensityThresh() const    { return den_thresh; }
     145                 :            : 
     146                 :      17252 :         void SetDensityThresh(double thresh)
     147                 :            :                 {
     148                 :      17252 :                 den_thresh = thresh;
     149                 :      17252 :                 thresh_entries = int(thresh * double(num_buckets));
     150                 :      17252 :                 }
     151                 :            : 
     152                 :            :         // Same for the second table, when resizing.
     153                 :         55 :         void SetDensityThresh2(double thresh)
     154                 :            :                 {
     155                 :         55 :                 den_thresh2 = thresh;
     156                 :         55 :                 thresh_entries2 = int(thresh * double(num_buckets2));
     157                 :         55 :                 }
     158                 :            : 
     159                 :            :         // Normally we only have tbl.
     160                 :            :         // When we're resizing, we'll have tbl (old) and tbl2 (new)
     161                 :            :         // tbl_next_ind keeps track of how much we've moved to tbl2
     162                 :            :         // (it's the next index we're going to move).
     163                 :            :         PList(DictEntry)** tbl;
     164                 :            :         int num_buckets;
     165                 :            :         int num_entries;
     166                 :            :         int max_num_entries;
     167                 :            :         double den_thresh;
     168                 :            :         int thresh_entries;
     169                 :            : 
     170                 :            :         // Resizing table (replicates tbl above).
     171                 :            :         PList(DictEntry)** tbl2;
     172                 :            :         int num_buckets2;
     173                 :            :         int num_entries2;
     174                 :            :         int max_num_entries2;
     175                 :            :         double den_thresh2;
     176                 :            :         int thresh_entries2;
     177                 :            : 
     178                 :            :         hash_t tbl_next_ind;
     179                 :            : 
     180                 :            :         PList(DictEntry)* order;
     181                 :            :         dict_delete_func delete_func;
     182                 :            : 
     183                 :            :         PList(IterCookie) cookies;
     184                 :            : };
     185                 :            : 
     186                 :            : 
     187                 :            : #define PDict(type) type ## PDict
     188                 :            : #define PDictdeclare(type)      \
     189                 :            : class PDict(type) : public Dictionary { \
     190                 :            : public: \
     191                 :            :         PDict(type)(dict_order ordering = UNORDERED,    \
     192                 :            :                         int initial_size = DEFAULT_DICT_SIZE) : \
     193                 :            :                 Dictionary(ordering, initial_size) {}   \
     194                 :            :         type* Lookup(const char* key) const     \
     195                 :            :                 {       \
     196                 :            :                 HashKey h(key); \
     197                 :            :                 return (type*) Dictionary::Lookup(&h);      \
     198                 :            :                 }       \
     199                 :            :         type* Lookup(const HashKey* key) const  \
     200                 :            :                 { return (type*) Dictionary::Lookup(key); }     \
     201                 :            :         type* Insert(const char* key, type* val)        \
     202                 :            :                 {       \
     203                 :            :                 HashKey h(key); \
     204                 :            :                 return (type*) Dictionary::Insert(&h, (void*) val); \
     205                 :            :                 }       \
     206                 :            :         type* Insert(HashKey* key, type* val)   \
     207                 :            :                 { return (type*) Dictionary::Insert(key, (void*) val); }\
     208                 :            :         type* NthEntry(int n) const     \
     209                 :            :                 { return (type*) Dictionary::NthEntry(n); }     \
     210                 :            :         type* NthEntry(int n, const char*& key) const       \
     211                 :            :                 {       \
     212                 :            :                 int key_len;    \
     213                 :            :                 return (type*) Dictionary::NthEntry(n, (const void*&) key,\
     214                 :            :                                                         key_len);       \
     215                 :            :                 }       \
     216                 :            :         type* NextEntry(IterCookie*& cookie) const  \
     217                 :            :                 {       \
     218                 :            :                 HashKey* h; \
     219                 :            :                 return (type*) Dictionary::NextEntry(h, cookie, 0);     \
     220                 :            :                 } \
     221                 :            :         type* NextEntry(HashKey*& h, IterCookie*& cookie) const \
     222                 :            :                 { return (type*) Dictionary::NextEntry(h, cookie, 1); } \
     223                 :            :         type* RemoveEntry(const HashKey* key)   \
     224                 :            :                 { return (type*) Remove(key->Key(), key->Size(),  \
     225                 :            :                                         key->Hash()); } \
     226                 :            : }
     227                 :            : 
     228                 :            : #endif

Generated by: LCOV version 1.8