-- $Date: 2004/01/27 11:58:57 $
-- $Revision: 1.13 $
-- $Author: jcrocholl $

with Limited_Hash_Tables;

generic

   -- Generic type of keys to access items.
   type Key_Type is private;

   -- Generic type of the items to be stored.
   type Item_Type is private;

   with function Hash
     (Key : in Key_Type;
      Max : in Positive)
     return Positive
     is <>;

   with function Equal
     (Left, Right : in Key_Type)
     return Boolean
     is <>;

-- Versatile implementation of hash tables.
-- - Generic to allow all kinds of content.
-- - Variable size (always prime).
package Hash_Tables is

   -- Import inner implementation of hash tables.
   package Inner_Tables is new Limited_Hash_Tables(Key_Type, Item_Type);
   subtype Hash_Table is Inner_Tables.Hash_Table;
   subtype Hash_Table_Access is Inner_Tables.Hash_Table_Access;

   ---------------
   -- Construction
   ---------------

   -- Create a new hash table with the given table size.
   function Create
     (Size : in Positive := Inner_Tables.Default_Start_Size) -- Initial size.
     return Hash_Table_Access                                -- The new table.
     renames Inner_Tables.Create;

   ------------------------------
   -- Storing and retrieving data
   ------------------------------

   -- Check for available space in the table, grow if necessary, then
   -- insert the key item pair into the table.
   -- Raises Key_Exists if the key is already in use.
   procedure Put
     (This : in out Hash_Table_Access-- Add pair to this hash table.
      Key  : in Key_Type;              -- Create this key.
      Item : in Item_Type);            -- Associate this item.

   -- Retrieve an item from the table.
   -- Raises Key_Not_Found if the key is not in the table.
   function Get
     (This : access Hash_Table-- Get value from this hash table.
      Key  : in Key_Type)       -- Look up this key.
     return Item_Type;          -- The item that was found.

   -----------------
   -- Indexed access
   -----------------

   -- Get the index of a given key.
   function Get_Index
     (This : access Hash_Table-- Get key from this hash table.
      Key  : in Key_Type)       -- Iteration pointer to the current field.
     return Positive            -- The index of the requested key.
     renames Inner_Tables.Get_Index;

   -- Get the key at a given index position.
   function Get_Key
     (This  : access Hash_Table-- Get key from this hash table.
      Index : in Positive)       -- Iteration pointer to the current field.
     return Key_Type             -- The requested key.
     renames Inner_Tables.Get_Key;

   -- Get the item at a given index position.
   function Get_Item
     (This  : access Hash_Table-- Get item from this hash table.
      Index : in Positive)       -- Iteration pointer to the current field.
     return Item_Type            -- The requested item.
     renames Inner_Tables.Get_Item;

   ------------
   -- Iterating
   ------------

   -- Iterate over the items in the table. You should start with an
   -- Index of 0 and stop iterating as soon as Index is 0 again.
   procedure Next
     (This  : access Hash_Table-- Iterate through this hash table.
      Index : in out Natural)    -- Iteration pointer to the current field.
     renames Inner_Tables.Next;

   -- Iterate over the items in the table. You should start with an
   -- Index of 0 and stop iterating as soon as Index is 0 again.
   procedure Get_Next
     (This  : access Hash_Table-- Get pair from this hash table.
      Index : in out Natural;    -- Iteration pointer to the current field.
      Key   : out Key_Type;      -- The key at the updated index position.
      Item  : out Item_Type);    -- The item at the updated index position.

   ------------------------
   -- Performance debugging
   ------------------------

   -- Print a visual representation of the hash table's usage. Empty
   -- fields are represented by a '-' character, used fields by '#'.
   procedure Print_Usage
     (This : access Hash_Table-- Print usage of this hash table.
     renames Inner_Tables.Print_Usage;

end Hash_Tables;