// Copyright 1995 Barbara Liskov

#ifndef _BHASH_H
#define _BHASH_H

/*
    The remainder provides definitions for classes
    that are used to construct the Map classes. A key piece is the
    "bhash" class, a hash table implementation that is
    independent of the implementation of the individual buckets.
*/

#define BH_TEMPLATE template <class KEY, class VALUE, class PAIRSET>

BH_TEMPLATE class bhash {
/*
    A "bhash" is a hash table that implements a map from a KEY type to
    a VALUE type. The keys and values in the hash table may be any C++
    type. The hash table is implemented as a parameterized class.
    
    The specifications of the methods are as described above.
    
    The constraints on the types KEY, VALUE, and PAIRSET are
    described below.
*/
    friend class bhash_generator<KEY, VALUE, PAIRSET>;
public:
    bhash(int size_hint);
      /*
         Create a new hash table whose number of elements is expected to
         be around "size_hint".
      */

    int size() const;
    void add(KEY, VALUE);
    bool find(KEY, VALUE &v) const;
    VALUE operator[](KEY k) const;
    bool contains(KEY k) const;
    bool store(KEY, VALUE);
    bool remove(KEY k, VALUE &v);
    hash_generator<KEY, VALUE> *mappings();
    generator<KEY> *keys() const;
    void predict(int size);
    void allowAutoResize();
    float estimateEfficiency() const;
    float estimateClumping() const;
/* operations for stack-allocated and inlined hash tables */
    ~bhash();
    bhash(bhash<KEY, VALUE, PAIRSET> const &);
    bhash<KEY, VALUE, PAIRSET> const &operator=(bhash<KEY, VALUE, PAIRSET> const &);
protected:
    int numItems;         // number of elements in the hash table
    int numSlots;         // size of the bucket array.
    int slotBits;         // lg size of the bucket array
    PAIRSET *pairsets;     // the array of top-level slots

    int do_hash(KEY key) const; // compute the hash value modulo "numSlots"
    void sizeup(int size);      // set slotBits, numSlots appropriately
    void copy_items(bhash<KEY, VALUE, PAIRSET> const &);

#ifdef __GNUC__
    static bhash<KEY, VALUE, PAIRSET> *dummy; // force g++ expansion
    // this previous line actually makes cxx screw up for some reason
#endif

    /* Abstraction function: the hash map contains all mappings that are
           found in all its non-empty pairsets.
       Rep Invariant: The total number of non-empty slots is equal to
           "numItems".  No two pairsets contain the same key, and every
           element is found in a pair set whose index in "pairsets"
           is what the key hashes to, modulo the number of
           slots, which must be a power of two. Also,
	   "numSlots == 1<<slotBits".
    */
};

/*
The class PAIRSET must conform to the following declaration:
*/

#if 0
class PAIRSET {
    // A "PAIRSET" represents a set of (key, value) pairs.
    // Typically, these sets will be very small, so insertion and
    // deletion should be optimized on this basis.
    // A "PAIRSET" is used as a inlined abstraction.
    PAIRSET();
        // Results: an empty PAIRSET.
    ~PAIRSET();
        // Results: destroys this PAIRSET.
    PAIRSET(PAIRSET const &);
	// create a copy
    void operator=(PAIRSET const &);
        // overwrite with a copy
    bool full();
        // Results: whether the set is non-empty.
    bool fetch(KEY key, VALUE &value);
        // Place the value corresponding to this key into "value",
        //    and return TRUE. Return FALSE if no such mapping exists.
    VALUE fetch_fast(KEY key);
        // Checks: there is a mapping for "k".
        // Results: the value corresponding to "k".
    add(KEY k, VALUE v);
        // Checks: (k,v) is not already in the set.
        // Adds the pair (k, v) to the set.
    bool store(KEY k, VALUE v);
        // Adds the pair (k, v) to the set if there is no mapping for
        // "k", or overwrites the existing mapping for "k" with "v".
	// Returns TRUE if there was an existing mapping for "k".
    bool remove(KEY k, VALUE &v);
        // Results: the mapping for "k" is removed if it exists, and
	//    TRUE is returned. Otherwise, FALSE is returned.
    hash_generator<KEY, VALUE> *mappings();
        //  Return a generator that yields every key in the set.
};
#endif /* documentation */

#define BK_TEMPLATE template <class KEY, class VALUE>

BK_TEMPLATE struct buckets_rep;

BK_TEMPLATE class buckets {
public:
    friend class buckets_generator<KEY, VALUE>;
/*
    A "buckets" is a standard implementation of a PAIRSET (see above)
    using a linked list of buckets. It is suitable for use with a "bhash",
    e.g.

    "bhash<int, int, buckets<int, int>, buckets<int, int>::generator>"

    is a well-defined type, since "int" satisfies both the KEY and VALUE
    constraints.
*/
    buckets();
    ~buckets();
    buckets(buckets<KEY, VALUE> const &);
    void operator=(buckets<KEY, VALUE> const &);
    bool full() const;
    bool find(KEY, VALUE &) const;
    VALUE fetch(KEY) const;
    void add(KEY, VALUE);
    bool store(KEY, VALUE);
    bool remove(KEY, VALUE &);
    hash_generator<KEY, VALUE> *mappings();
private:
    buckets_rep<KEY, VALUE> *pairs;
#ifdef __GNUC__
    //static buckets_generator<KEY, VALUE> *dummy; // force g++ expansion
    
    // this previous line actually makes cxx screw up for some reason
#endif
};

#ifdef __GNUC__
#include "template/bhash.t"
#include "template/buckets.t"
#endif

#undef BH_TEMPLATE

#endif /* _BHASH_H */
