home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------------
- *
- * (c) Westmount Technology 1991
- *
- * File: @(#)HashTbl.hxx 1.2 (1.7) (1.1)
- * Author: sipi (original by K.E. Gorlen)
- * Description: implementation of hash tables
- * A hash table is an unordered collection of objects in which
- * no object is duplicated. Duplicate objects are defined by
- * the function Hashable::isEqual.
- * The capacity() function returns 1/2 the capacity of the
- * hash table and the size() function returns the number of
- * objects currently in the hash table.
- * For efficiency, the capacity is always a power of two and
- * is doubled whenever the table becomes half full.
- *
- *---------------------------------------------------------------------------
- SccsId = @(#)HashTbl.hxx 1.2 (1.7) (1.1)\t11 Nov 1993 Copyright 1992 Westmount Technology */
-
- #ifndef HASHTBL_HXX
- #define HASHTBL_HXX
-
- #ifndef TEMPLCONF_HXX
- #include "TemplConf.hxx"
- #endif
-
- #if HAS_TEMPLATES
-
- #ifndef FLEXARRAY_HXX
- #include <FlexArray.hxx>
- #endif
-
- class Hashable {
- public:
- Hashable() {}
- virtual ~Hashable();
-
- // Calculate a hash value for this object
- //
- virtual unsigned hash() const = 0;
-
- // Compare the given key with the key from this Hashable
- // If both are equal then return 1 else return 0
- //
- virtual int isEqual(const Hashable& key) const = 0;
- };
-
- class hash_iter;
- typedef Hashable *hashptr;
-
- typedef FlexArray<hashptr> hashList;
-
- class HashTbl {
- friend class hash_iter;
- private:
- unsigned count; // number of objects in set
- unsigned nbits; // log base 2 of contents.capacity()
- unsigned mask; // contents.capacity()-1
- hashList contents; // array of pointers to Hashables
- int current; // current in array for first/next
-
- private:
- // Compute set allocation size.
- // Round size up to the next highest power of two, if necessary
- //
- unsigned setCapacity(unsigned);
-
- // Convert hash key into contents index
- //
- int getIndex(unsigned long) const;
-
- // Search this set for the specified Hashable
- // and return index of object if found or nil slot if not found
- //
- int findIndexOf(const Hashable&) const;
-
- // Change the capacity of this HashTbl to new size
- //
- void reSize(unsigned new_size);
-
- public:
- static unsigned DEFAULT_SIZE; // HashTbl size
- static unsigned EXPANSION_FACTOR; // HashTbl grow factor
-
- public:
- HashTbl(unsigned size = HashTbl::DEFAULT_SIZE);
- HashTbl(const HashTbl&);
- ~HashTbl();
- HashTbl& operator=(const HashTbl&);
-
- // Add an object to this HashTbl,
- // making the HashTbl larger if it becomes half full.
- // Return pointer to given object if it does not yet exist
- // else return pointer to existing object in HashTbl.
- //
- Hashable *add(Hashable&);
-
- // Add all objects from given HashTbl to this HashTbl
- //
- void addAll(const HashTbl&);
-
- // Remove object from HashTbl
- // Return pointer to given object of it is removed
- // else return 0 if it does not exist in this HashTbl.
- //
- Hashable *remove(const Hashable&);
-
- // Remove all objects from HashTbl
- //
- void removeAll();
-
- // Remove all objects present in given HashTbl from HashTbl
- //
- void removeAll(const HashTbl&);
-
- // Remove all objects from HashTbl and destruct each individual object
- //
- void destructAll();
-
- // Find object in HashTbl using given key
- // Returns 0 if not found else pointer to object
- //
- Hashable *find(const Hashable& key) const
- {return contents.at(findIndexOf(key));}
- Hashable *operator[](const Hashable& key) const
- {return contents.at(findIndexOf(key));}
-
- // Return 1 if the specified HashTbl equals this HashTbl
- // Else return 0
- //
- int operator==(const HashTbl&) const;
-
- // Return 1 if the specified HashTbl does not equal this HashTbl
- // Else return 0
- //
- int operator!=(const HashTbl& tbl) const {return !(*this==tbl);}
-
- // Walk through HashTbl using index
- // Either 0 or a pointer to a Hashable is returned
- //
- Hashable *at(int index) const {return contents[index];}
-
- // Walk through HashTbl using first/next (no order is defined)
- // Returns 0 if the HashTbl is empty or no next element.
- //
- Hashable *first();
- Hashable *next();
-
- // The capacity() function returns 1/2 the capacity of the
- // hash table and the size() function returns the number of
- // objects currently in the hash table.
- //
- unsigned capacity() const {return contents.capacity()>>1;}
- unsigned size() const {return count;}
- };
-
- class hash_iter {
- const HashTbl& tbl;
- int curr_idx;
- public:
- hash_iter(const HashTbl& tbl);
- ~hash_iter();
-
- // Start iterating again
- //
- void rewind(void);
-
- // Go to next element if there is one
- // Sets the iterator in the end-of-iteration state if positioned
- // at the last element
- //
- void advance(void);
-
- // get current entry if there is one
- // Effect is undefined if iterator is in end-of-iteration state
- //
- Hashable* get(void) const { return tbl.at(curr_idx); }
-
- // testing: return non-0 if advanced over the last element
- //
- int end_of_iteration(void) const { return curr_idx == -1; }
-
- // Shorthands:
- operator const void* (void) const
- { return end_of_iteration()? 0: this; }
- int operator ! (void) const { return !end_of_iteration(); }
- void operator++ (void) { advance(); }
- Hashable* operator() (void) const { return get(); }
- };
-
- template<class Key, class Value> class hashTbl;
-
- template<class Key, class Value>
- class hashIter : private hash_iter {
- public:
- hash_iter::rewind;
- hash_iter::advance;
- hash_iter::end_of_iteration;
- hash_iter::operator !;
- hash_iter::operator++;
-
- hashIter(const hashTbl<Key,Value>& x): hash_iter(x) {}
- Value* operator()() { return (Value*) hash_iter::operator()();}
- Value* get() { return (Value*) hash_iter::get();}
- operator const void* () const
- { return hash_iter::operator const void*(); }
- };
-
- template<class Key, class Value>
- class hashTbl : private HashTbl {
- friend class hashIter<Key, Value>;
- public:
- hashTbl<Key,Value>& operator=(const hashTbl<Key,Value>& tbl)
- {return (hashTbl<Key,Value> &) HashTbl::operator=(tbl);}
- hashTbl(unsigned size = HashTbl::DEFAULT_SIZE)
- : HashTbl(size) {}
- hashTbl(const hashTbl<Key,Value> & tbl)
- : HashTbl(tbl) {}
- Value *add(Key & x)
- {return (Value*)HashTbl::add(x);}
- void addAll(const hashTbl<Key,Value> & tbl)
- {HashTbl::addAll(tbl);}
- Value *remove(const Key & x )
- {return (Value*) HashTbl::remove(x);}
- Value *find(const Key & x) const
- {return (Value*) HashTbl::find(x);}
- Value *operator[](const Key & x) const
- {return (Value*) HashTbl::operator[](x);}
- int operator==(const hashTbl<Key,Value> & tbl) const
- {return HashTbl::operator==(tbl);}
- int operator!=(const hashTbl<Key,Value> & tbl) const
- {return HashTbl::operator!=(tbl);}
- Value *at(int index) const
- {return (Value*) HashTbl::at(index);}
- Value *first()
- {return (Value*) HashTbl::first();}
- Value *next()
- {return (Value*) HashTbl::next();}
- void removeAll()
- {HashTbl::removeAll();}
- void removeAll(const hashTbl<Key,Value> & tbl)
- {HashTbl::removeAll(tbl);}
- void destructAll()
- {HashTbl::destructAll();}
- unsigned capacity() const
- {return HashTbl::capacity();}
- unsigned size() const
- {return HashTbl::size();}
- };
-
- #else
-
- #ifndef GENERICH
- #include <generic.h>
- #endif
-
- #ifndef FLEXARRAY_HXX
- #include <FlexArray.hxx>
- #endif
-
- class Hashable {
- public:
- Hashable() {}
- virtual ~Hashable();
-
- // Calculate a hash value for this object
- //
- virtual unsigned hash() const = 0;
-
- // Compare the given key with the key from this Hashable
- // If both are equal then return 1 else return 0
- //
- virtual int isEqual(const Hashable& key) const = 0;
- };
-
- class hash_iter;
- typedef Hashable *hashptr;
- declare(FlexArray,hashptr);
- typedef hashptr_FlexArray hashList;
-
- class HashTbl {
- friend class hash_iter;
- private:
- unsigned count; // number of objects in set
- unsigned nbits; // log base 2 of contents.capacity()
- unsigned mask; // contents.capacity()-1
- hashList contents; // array of pointers to Hashables
- int current; // current in array for first/next
-
- private:
- // Compute set allocation size.
- // Round size up to the next highest power of two, if necessary
- //
- unsigned setCapacity(unsigned);
-
- // Convert hash key into contents index
- //
- int getIndex(unsigned long) const;
-
- // Search this set for the specified Hashable
- // and return index of object if found or nil slot if not found
- //
- int findIndexOf(const Hashable&) const;
-
- // Change the capacity of this HashTbl to new size
- //
- void reSize(unsigned new_size);
-
- public:
- static unsigned DEFAULT_SIZE; // HashTbl size
- static unsigned EXPANSION_FACTOR; // HashTbl grow factor
-
- public:
- HashTbl(unsigned size = HashTbl::DEFAULT_SIZE);
- HashTbl(const HashTbl&);
- ~HashTbl();
- HashTbl& operator=(const HashTbl&);
-
- // Add an object to this HashTbl,
- // making the HashTbl larger if it becomes half full.
- // Return pointer to given object if it does not yet exist
- // else return pointer to existing object in HashTbl.
- //
- Hashable *add(Hashable&);
-
- // Add all objects from given HashTbl to this HashTbl
- //
- void addAll(const HashTbl&);
-
- // Remove object from HashTbl
- // Return pointer to given object of it is removed
- // else return 0 if it does not exist in this HashTbl.
- //
- Hashable *remove(const Hashable&);
-
- // Remove all objects from HashTbl
- //
- void removeAll();
-
- // Remove all objects present in given HashTbl from HashTbl
- //
- void removeAll(const HashTbl&);
-
- // Remove all objects from HashTbl and destruct each individual object
- //
- void destructAll();
-
- // Find object in HashTbl using given key
- // Returns 0 if not found else pointer to object
- //
- Hashable *find(const Hashable& key) const
- {return contents.at(findIndexOf(key));}
- Hashable *operator[](const Hashable& key) const
- {return contents.at(findIndexOf(key));}
-
- // Return 1 if the specified HashTbl equals this HashTbl
- // Else return 0
- //
- int operator==(const HashTbl&) const;
-
- // Return 1 if the specified HashTbl does not equal this HashTbl
- // Else return 0
- //
- int operator!=(const HashTbl& tbl) const {return !(*this==tbl);}
-
- // Walk through HashTbl using index
- // Either 0 or a pointer to a Hashable is returned
- //
- Hashable *at(int index) const {return contents[index];}
-
- // Walk through HashTbl using first/next (no order is defined)
- // Returns 0 if the HashTbl is empty or no next element.
- //
- Hashable *first();
- Hashable *next();
-
- // The capacity() function returns 1/2 the capacity of the
- // hash table and the size() function returns the number of
- // objects currently in the hash table.
- //
- unsigned capacity() const {return contents.capacity()>>1;}
- unsigned size() const {return count;}
- };
-
- class hash_iter {
- const HashTbl& tbl;
- int curr_idx;
- public:
- hash_iter(const HashTbl& tbl);
- ~hash_iter();
-
- // Start iterating again
- //
- void rewind(void);
-
- // Go to next element if there is one
- // Sets the iterator in the end-of-iteration state if positioned
- // at the last element
- //
- void advance(void);
-
- // get current entry if there is one
- // Effect is undefined if iterator is in end-of-iteration state
- //
- Hashable* get(void) const { return tbl.at(curr_idx); }
-
- // testing: return non-0 if advanced over the last element
- //
- int end_of_iteration(void) const { return curr_idx == -1; }
-
- // Shorthands:
- operator const void* (void) const
- { return end_of_iteration()? 0: this; }
- int operator ! (void) const { return !end_of_iteration(); }
- void operator++ (void) { advance(); }
- Hashable* operator() (void) const { return get(); }
- };
-
- #define hashTbl(key,keyval) name3(key,keyval,_HashTbl)
- #define hashIter(key,keyval) name3(key,keyval,_hash_iter)
-
- #define hashIterdeclare2(key,keyval) \
- class hashIter(key,keyval) : private hash_iter { \
- public: \
- hash_iter::rewind; \
- hash_iter::advance; \
- hash_iter::end_of_iteration; \
- hash_iter::operator !; \
- hash_iter::operator++; \
- \
- hashIter(key,keyval)(const hashTbl(key,keyval)& x): hash_iter(x){}\
- keyval* operator()() { return (keyval*) hash_iter::operator()();}\
- keyval* get() { return (keyval*) hash_iter::get();} \
- operator const void* () const \
- { return hash_iter::operator const void*(); } \
- }
-
- #define HashTbldeclare2(key,keyval) \
- class hashTbl(key,keyval) : private HashTbl { \
- friend class hashIter(key,keyval); \
- public: \
- hashTbl(key,keyval) & operator=(const hashTbl(key,keyval) & tbl)\
- {return (hashTbl(key,keyval) &) HashTbl::operator=(tbl);} \
- hashTbl(key,keyval) (unsigned size = HashTbl::DEFAULT_SIZE) \
- : HashTbl(size) {} \
- hashTbl(key,keyval) (const hashTbl(key,keyval) & tbl) \
- : HashTbl(tbl) {} \
- keyval *add(key & x) \
- {return (keyval*)HashTbl::add(x);} \
- void addAll(const hashTbl(key,keyval) & tbl) \
- {HashTbl::addAll(tbl);} \
- keyval *remove(const key & x ) \
- {return (keyval*) HashTbl::remove(x);} \
- keyval *find(const key & x) const \
- {return (keyval*) HashTbl::find(x);} \
- keyval *operator[](const key & x) const \
- {return (keyval*) HashTbl::operator[](x);} \
- int operator==(const hashTbl(key,keyval) & tbl) const\
- {return HashTbl::operator==(tbl);} \
- int operator!=(const hashTbl(key,keyval) & tbl) const\
- {return HashTbl::operator!=(tbl);} \
- keyval *at(int index) const \
- {return (keyval*) HashTbl::at(index);} \
- keyval *first() \
- {return (keyval*) HashTbl::first();} \
- keyval *next() \
- {return (keyval*) HashTbl::next();} \
- void removeAll() \
- {HashTbl::removeAll();} \
- void removeAll(const hashTbl(key,keyval) & tbl) \
- {HashTbl::removeAll(tbl);} \
- void destructAll() \
- {HashTbl::destructAll();} \
- unsigned capacity() const \
- {return HashTbl::capacity();} \
- unsigned size() const \
- {return HashTbl::size();} \
- }; \
- hashIterdeclare2(key,keyval)
-
- #endif /* HAS_TEMPLATES */
-
- #endif /* HASHTBL_HXX */
-