------------------------------------------------------------------------------
--                                                                          --
--                      CHARLES CONTAINER LIBRARY                           --
--                                                                          --
--              Copyright (C) 2001-2003 Matthew J Heaney                    --
--                                                                          --
-- The Charles Container Library ("Charles") is free software; you can      --
-- redistribute it and/or modify it under terms of the GNU General Public   --
-- License as published by the Free Software Foundation; either version 2,  --
-- or (at your option) any later version.  Charles is distributed in the    --
-- hope that it will be useful, but WITHOUT ANY WARRANTY; without even the  --
-- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
-- See the GNU General Public License for more details.  You should have    --
-- received a copy of the GNU General Public License distributed with       --
-- Charles;  see file COPYING.TXT.  If not, write to the Free Software      --
-- Foundation,  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.    --
--                                                                          --
-- As a special exception, if other files instantiate generics from this    --
-- unit, or you link this unit with other files to produce an executable,   --
-- this unit does not by itself cause the resulting executable to be        --
-- covered by the GNU General Public License.  This exception does not      --
-- however invalidate any other reasons why the executable file might be    --
-- covered by the GNU Public License.                                       --
--                                                                          --
-- Charles is maintained by Matthew J Heaney.                               --
--                                                                          --
-- http://home.earthlink.net/~matthewjheaney/index.html                     --
-- mailto:matthewjheaney@earthlink.net                                      --
--                                                                          --
------------------------------------------------------------------------------

generic

   type Node_Access is private;

   Null_Node : in Node_Access;

   with function Hash
     (Key : Node_Access) return Hash_Type is <>;

   with function Next
     (Node : Node_Access) return Node_Access is <>;

   with procedure Set_Next
     (Node : Node_Access;
      Next : Node_Access) is <>;

   with procedure Free
     (X : in out Node_Access) is <>;

package Charles.Hash_Tables is
   pragma Preelaborate (Hash_Tables);

   type Buckets_Type is array (Hash_Type range <>) of Node_Access;
   type Buckets_Access is access all Buckets_Type;

   type Hash_Table_Type is
      record
         Buckets : Buckets_Access;
         Length  : Natural;
      end record;

   pragma Volatile (Hash_Table_Type);

   function "=" (L, R : Hash_Table_Type) return Boolean is abstract;

   generic
      with function New_Node (Node : Node_Access) return Node_Access is <>;
   procedure Generic_Adjust (Hash_Table : in out Hash_Table_Type);

   procedure Finalize (Hash_Table : in out Hash_Table_Type);

   generic
      with function New_Node (Node : Node_Access) return Node_Access is <>;
   procedure Generic_Assign
     (Target : in out Hash_Table_Type;
      Source : in     Hash_Table_Type);

   generic
      with function Is_Equal
        (L, R : Node_Access) return Boolean is <>;
   function Generic_Equal
     (L, R : Hash_Table_Type) return Boolean;

   function Index
     (Hash_Table : Hash_Table_Type;
      Node       : Node_Access) return Hash_Type;
   pragma Inline (Index);

   procedure Clear (Hash_Table : in out Hash_Table_Type);

   procedure Swap (Left, Right : in out Hash_Table_Type);

   procedure Delete
     (Hash_Table : in out Hash_Table_Type;
      Node       : in out Node_Access);

--     procedure Delete
--       (Hash_Table : in out Hash_Table_Type;
--        First      : in out Node_Access;
--        Back       : in     Node_Access);

   function Size (Hash_Table : Hash_Table_Type) return Natural;

   procedure Resize
     (Hash_Table : in out Hash_Table_Type;
      Length     : in     Natural);

   generic
      with procedure Process (Node : in Node_Access) is <>;
   procedure Generic_Iteration (Hash_Table : in Hash_Table_Type);


   function First (Hash_Table : Hash_Table_Type)
     return Node_Access;

   function Succ
     (Hash_Table : Hash_Table_Type;
      Node       : Node_Access) return Node_Access;


   generic

      type Key_Type (<>) is limited private;

      with function Hash
        (Key : Key_Type) return Hash_Type is <>;

      with function Is_Equal_Key
        (Node : Node_Access;
         Key  : Key_Type) return Boolean is <>;

   package Generic_Keys is

      function Index
        (Hash_Table : Hash_Table_Type;
         Key        : Key_Type) return Hash_Type;

      generic
         with function New_Node
           (Next : Node_Access) return Node_Access is <>;
      procedure Generic_Conditional_Insert
        (Hash_Table : in out Hash_Table_Type;
         Key        : in     Key_Type;
         Node       :    out Node_Access;
         Success    :    out Boolean);

      generic
         with function New_Node
           (Next : Node_Access) return Node_Access is <>;
      procedure Generic_Unconditional_Insert
        (Hash_Table : in out Hash_Table_Type;
         Key        : in     Key_Type;
         Node       :    out Node_Access);

      procedure Delete
        (Hash_Table : in out Hash_Table_Type;
         Key        : in     Key_Type);

      function Find
        (Hash_Table : Hash_Table_Type;
         Key        : Key_Type) return Node_Access;

      procedure Equal_Range
        (Hash_Table  : in     Hash_Table_Type;
         Key         : in     Key_Type;
         First, Back :    out Node_Access);

      generic
         with procedure Process (Node : Node_Access) is <>;
      procedure Generic_Equal_Range
        (Hash_Table : in Hash_Table_Type;
         Key        : in Key_Type);

   end Generic_Keys;


end Charles.Hash_Tables;

