------------------------------------------------------------------------------
--                                                                          --
--                         GNAT LIBRARY COMPONENTS                          --
--                                                                          --
--               ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_KEYS                --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--             Copyright (C) 2004 Free Software Foundation, Inc.            --
--                                                                          --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
-- apply solely to the  contents of the part following the private keyword. --
--                                                                          --
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT 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 GNAT;  see file COPYING.  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.                                      --
--                                                                          --
-- This unit was originally developed by Matthew J Heaney.                  --
------------------------------------------------------------------------------

package body Ada.Containers.Red_Black_Trees.Generic_Keys is

   package Ops renames Tree_Operations;

   -------------
   -- Ceiling --
   -------------

   --  AKA Lower_Bound

   function Ceiling (Tree : Tree_Type; Key  : Key_Type) return Node_Access is
      Y : Node_Access;
      X : Node_Access := Tree.Root;

   begin
      while X /= Ops.Null_Node loop
         if Is_Greater_Key_Node (Key, X) then
            X := Ops.Right (X);
         else
            Y := X;
            X := Ops.Left (X);
         end if;
      end loop;

      return Y;
   end Ceiling;

   ----------
   -- Find --
   ----------

   function Find (Tree : Tree_Type; Key  : Key_Type) return Node_Access is
      Y : Node_Access;
      X : Node_Access := Tree.Root;

   begin
      while X /= Ops.Null_Node loop
         if Is_Greater_Key_Node (Key, X) then
            X := Ops.Right (X);
         else
            Y := X;
            X := Ops.Left (X);
         end if;
      end loop;

      if Y = Ops.Null_Node then
         return Ops.Null_Node;
      end if;

      if Is_Less_Key_Node (Key, Y) then
         return Ops.Null_Node;
      end if;

      return Y;
   end Find;

   -----------
   -- Floor --
   -----------

   function Floor (Tree : Tree_Type; Key  : Key_Type) return Node_Access is
      Y : Node_Access;
      X : Node_Access := Tree.Root;

   begin
      while X /= Ops.Null_Node loop
         if Is_Less_Key_Node (Key, X) then
            X := Ops.Left (X);
         else
            Y := X;
            X := Ops.Right (X);
         end if;
      end loop;

      return Y;
   end Floor;

   --------------------------------
   -- Generic_Conditional_Insert --
   --------------------------------

   procedure Generic_Conditional_Insert
     (Tree    : in out Tree_Type;
      Key     : Key_Type;
      Node    : out Node_Access;
      Success : out Boolean)
   is
      Y : Node_Access := Ops.Null_Node;
      X : Node_Access := Tree.Root;

   begin
      Success := True;
      while X /= Ops.Null_Node loop
         Y := X;
         Success := Is_Less_Key_Node (Key, X);

         if Success then
            X := Ops.Left (X);
         else
            X := Ops.Right (X);
         end if;
      end loop;

      Node := Y;

      if Success then
         if Node = Tree.First then
            Insert_Post (Tree, X, Y, Key, Node);
            return;
         end if;

         Node := Ops.Previous (Node);
      end if;

      if Is_Greater_Key_Node (Key, Node) then
         Insert_Post (Tree, X, Y, Key, Node);
         Success := True;
         return;
      end if;

      Success := False;
   end Generic_Conditional_Insert;

   ------------------------------------------
   -- Generic_Conditional_Insert_With_Hint --
   ------------------------------------------

   procedure Generic_Conditional_Insert_With_Hint
     (Tree     : in out Tree_Type;
      Position : Node_Access;
      Key      : Key_Type;
      Node     : out Node_Access;
      Success  : out Boolean)
   is
   begin
      if Position = Ops.Null_Node then  -- largest
         if Tree.Length > 0
           and then Is_Greater_Key_Node (Key, Tree.Last)
         then
            Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
            Success := True;
         else
            Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
         end if;

         return;
      end if;

      pragma Assert (Tree.Length > 0);

      if Is_Less_Key_Node (Key, Position) then
         if Position = Tree.First then
            Insert_Post (Tree, Position, Position, Key, Node);
            Success := True;
            return;
         end if;

         declare
            Before : constant Node_Access := Ops.Previous (Position);

         begin
            if Is_Greater_Key_Node (Key, Before) then
               if Ops.Right (Before) = Ops.Null_Node then
                  Insert_Post (Tree, Ops.Null_Node, Before, Key, Node);
               else
                  Insert_Post (Tree, Position, Position, Key, Node);
               end if;

               Success := True;

            else
               Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
            end if;
         end;

         return;
      end if;

      if Is_Greater_Key_Node (Key, Position) then
         if Position = Tree.Last then
            Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
            Success := True;
            return;
         end if;

         declare
            After : constant Node_Access := Ops.Next (Position);

         begin
            if Is_Less_Key_Node (Key, After) then
               if Ops.Right (Position) = Ops.Null_Node then
                  Insert_Post (Tree, Ops.Null_Node, Position, Key, Node);
               else
                  Insert_Post (Tree, After, After, Key, Node);
               end if;

               Success := True;

            else
               Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
            end if;
         end;

         return;
      end if;

      Node := Position;
      Success := False;
   end Generic_Conditional_Insert_With_Hint;

   -------------------------
   -- Generic_Insert_Post --
   -------------------------

   procedure Generic_Insert_Post
     (Tree : in out Tree_Type;
      X, Y : Node_Access;
      Key  : Key_Type;
      Z    : out Node_Access)
   is
      subtype Length_Subtype is Count_Type range 0 .. Count_Type'Last - 1;

      New_Length : constant Count_Type := Length_Subtype'(Tree.Length) + 1;

   begin
      if Y = Ops.Null_Node
        or else X /= Ops.Null_Node
        or else Is_Less_Key_Node (Key, Y)
      then
         pragma Assert (Y = Ops.Null_Node
                          or else Ops.Left (Y) = Ops.Null_Node);

         --  Delay allocation as long as we can, in order to defend
         --  against exceptions propagated by relational operators.

         Z := New_Node;

         pragma Assert (Z /= Ops.Null_Node);
         pragma Assert (Ops.Color (Z) = Red);

         if Y = Ops.Null_Node then
            pragma Assert (Tree.Length = 0);
            pragma Assert (Tree.Root = Ops.Null_Node);
            pragma Assert (Tree.First = Ops.Null_Node);
            pragma Assert (Tree.Last = Ops.Null_Node);

            Tree.Root := Z;
            Tree.First := Z;
            Tree.Last := Z;

         else
            Ops.Set_Left (Y, Z);

            if Y = Tree.First then
               Tree.First := Z;
            end if;
         end if;

      else
         pragma Assert (Ops.Right (Y) = Ops.Null_Node);

         --  Delay allocation as long as we can, in order to defend
         --  against exceptions propagated by relational operators.

         Z := New_Node;

         pragma Assert (Z /= Ops.Null_Node);
         pragma Assert (Ops.Color (Z) = Red);

         Ops.Set_Right (Y, Z);

         if Y = Tree.Last then
            Tree.Last := Z;
         end if;
      end if;

      Ops.Set_Parent (Z, Y);
      Ops.Rebalance_For_Insert (Tree, Z);
      Tree.Length := New_Length;
   end Generic_Insert_Post;

   -----------------------
   -- Generic_Iteration --
   -----------------------

   procedure Generic_Iteration
     (Tree : Tree_Type;
      Key  : Key_Type)
   is
      procedure Iterate (Node : Node_Access);

      -------------
      -- Iterate --
      -------------

      procedure Iterate (Node : Node_Access) is
         N : Node_Access := Node;
      begin
         while N /= Ops.Null_Node loop
            if Is_Less_Key_Node (Key, N) then
               N := Ops.Left (N);
            elsif Is_Greater_Key_Node (Key, N) then
               N := Ops.Right (N);
            else
               Iterate (Ops.Left (N));
               Process (N);
               N := Ops.Right (N);
            end if;
         end loop;
      end Iterate;

   --  Start of processing for Generic_Iteration

   begin
      Iterate (Tree.Root);
   end Generic_Iteration;

   -------------------------------
   -- Generic_Reverse_Iteration --
   -------------------------------

   procedure Generic_Reverse_Iteration
     (Tree : Tree_Type;
      Key  : Key_Type)
   is
      procedure Iterate (Node : Node_Access);

      -------------
      -- Iterate --
      -------------

      procedure Iterate (Node : Node_Access) is
         N : Node_Access := Node;
      begin
         while N /= Ops.Null_Node loop
            if Is_Less_Key_Node (Key, N) then
               N := Ops.Left (N);
            elsif Is_Greater_Key_Node (Key, N) then
               N := Ops.Right (N);
            else
               Iterate (Ops.Right (N));
               Process (N);
               N := Ops.Left (N);
            end if;
         end loop;
      end Iterate;

   --  Start of processing for Generic_Reverse_Iteration

   begin
      Iterate (Tree.Root);
   end Generic_Reverse_Iteration;

   ----------------------------------
   -- Generic_Unconditional_Insert --
   ----------------------------------

   procedure Generic_Unconditional_Insert
     (Tree : in out Tree_Type;
      Key  : Key_Type;
      Node : out Node_Access)
   is
      Y : Node_Access := Ops.Null_Node;
      X : Node_Access := Tree.Root;

   begin
      while X /= Ops.Null_Node loop
         Y := X;

         if Is_Less_Key_Node (Key, X) then
            X := Ops.Left (X);
         else
            X := Ops.Right (X);
         end if;
      end loop;

      Insert_Post (Tree, X, Y, Key, Node);
   end Generic_Unconditional_Insert;

   --------------------------------------------
   -- Generic_Unconditional_Insert_With_Hint --
   --------------------------------------------

   procedure Generic_Unconditional_Insert_With_Hint
     (Tree : in out Tree_Type;
      Hint : Node_Access;
      Key  : Key_Type;
      Node : out Node_Access)
   is
      --  TODO: verify this algorithm.  It was (quickly) adapted it from the
      --  same algorithm for conditional_with_hint. It may be that the test
      --  Key > Hint should be something like a Key >= Hint, to handle the
      --  case when Hint is The Last Item of A (Contiguous) sequence of
      --  Equivalent Items.  (The Key < Hint Test is probably OK. It is not
      --  clear that you can use Key <= Hint, since new items are always
      --  inserted last in the sequence of equivalent items.) ???

   begin
      if Hint = Ops.Null_Node then  -- largest
         if Tree.Length > 0
           and then Is_Greater_Key_Node (Key, Tree.Last)
         then
            Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
         else
            Unconditional_Insert_Sans_Hint (Tree, Key, Node);
         end if;

         return;
      end if;

      pragma Assert (Tree.Length > 0);

      if Is_Less_Key_Node (Key, Hint) then
         if Hint = Tree.First then
            Insert_Post (Tree, Hint, Hint, Key, Node);
            return;
         end if;

         declare
            Before : constant Node_Access := Ops.Previous (Hint);
         begin
            if Is_Greater_Key_Node (Key, Before) then
               if Ops.Right (Before) = Ops.Null_Node then
                  Insert_Post (Tree, Ops.Null_Node, Before, Key, Node);
               else
                  Insert_Post (Tree, Hint, Hint, Key, Node);
               end if;
            else
               Unconditional_Insert_Sans_Hint (Tree, Key, Node);
            end if;
         end;

         return;
      end if;

      if Is_Greater_Key_Node (Key, Hint) then
         if Hint = Tree.Last then
            Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
            return;
         end if;

         declare
            After : constant Node_Access := Ops.Next (Hint);
         begin
            if Is_Less_Key_Node (Key, After) then
               if Ops.Right (Hint) = Ops.Null_Node then
                  Insert_Post (Tree, Ops.Null_Node, Hint, Key, Node);
               else
                  Insert_Post (Tree, After, After, Key, Node);
               end if;
            else
               Unconditional_Insert_Sans_Hint (Tree, Key, Node);
            end if;
         end;

         return;
      end if;

      Unconditional_Insert_Sans_Hint (Tree, Key, Node);
   end Generic_Unconditional_Insert_With_Hint;

   -----------------
   -- Upper_Bound --
   -----------------

   function Upper_Bound
     (Tree : Tree_Type;
      Key  : Key_Type) return Node_Access
   is
      Y : Node_Access;
      X : Node_Access := Tree.Root;

   begin
      while X /= Ops.Null_Node loop
         if Is_Less_Key_Node (Key, X) then
            Y := X;
            X := Ops.Left (X);
         else
            X := Ops.Right (X);
         end if;
      end loop;

      return Y;
   end Upper_Bound;

end Ada.Containers.Red_Black_Trees.Generic_Keys;


