a-swunha.ads, [...]: Removed.
authorMatthew Heaney <heaney@adacore.com>
Thu, 16 Jun 2005 08:56:24 +0000 (10:56 +0200)
committerArnaud Charlet <charlet@gcc.gnu.org>
Thu, 16 Jun 2005 08:56:24 +0000 (10:56 +0200)
2005-06-14  Matthew Heaney  <heaney@adacore.com>

* a-swunha.ads, a-swunha.adb: Removed. Replaced by a-swuwha.ad[sb]
* a-swuwha.ads, a-swuwha.adb: New files

* a-szunha.ads, a-szunha.adb: Removed, replaced by a-szuzha.ad[sb]
* a-szuzha.ads, a-szuzha.adb: New files.

* a-rbtgso.adb, a-crbtgo.ads, a-crbtgo.adb, a-crbtgk.ads,
a-crbtgk.adb, a-crbltr.ads, a-coorse.ads, a-coorse.adb, a-convec.ads,
a-convec.adb, a-coinve.ads, a-coinve.adb, a-cohata.ads, a-cohama.ads,
a-cohama.adb, a-ciorse.ads, a-ciorse.adb, a-cihama.ads, a-cihama.adb,
a-cidlli.ads, a-cidlli.adb, a-chtgop.ads, a-chtgop.adb, a-cdlili.ads,
a-cdlili.adb, a-coormu.adb, a-ciormu.adb, a-cihase.adb, a-cohase.adb,
a-cohase.ads, a-ciorma.ads, a-coorma.ads, a-ciormu.ads, a-coormu.ads,
a-swunha.adb, a-stunha.adb, a-ciorma.adb, a-coorma.adb, a-shcain.ads,
a-shcain.adb, a-chtgke.ads, a-chtgke.adb, a-stwiha.ads, a-stwiha.adb,
a-strhas.adb, a-stzhas.adb: synchronized to the latest version of the
Ada 2005 RM.

From-SVN: r101069

53 files changed:
gcc/ada/a-cdlili.adb
gcc/ada/a-cdlili.ads
gcc/ada/a-chtgke.adb
gcc/ada/a-chtgke.ads
gcc/ada/a-chtgop.adb
gcc/ada/a-chtgop.ads
gcc/ada/a-cidlli.adb
gcc/ada/a-cidlli.ads
gcc/ada/a-cihama.adb
gcc/ada/a-cihama.ads
gcc/ada/a-cihase.adb
gcc/ada/a-ciorma.adb
gcc/ada/a-ciorma.ads
gcc/ada/a-ciormu.adb
gcc/ada/a-ciormu.ads
gcc/ada/a-ciorse.adb
gcc/ada/a-ciorse.ads
gcc/ada/a-cohama.adb
gcc/ada/a-cohama.ads
gcc/ada/a-cohase.adb
gcc/ada/a-cohase.ads
gcc/ada/a-cohata.ads
gcc/ada/a-coinve.adb
gcc/ada/a-coinve.ads
gcc/ada/a-convec.adb
gcc/ada/a-convec.ads
gcc/ada/a-coorma.adb
gcc/ada/a-coorma.ads
gcc/ada/a-coormu.adb
gcc/ada/a-coormu.ads
gcc/ada/a-coorse.adb
gcc/ada/a-coorse.ads
gcc/ada/a-crbltr.ads
gcc/ada/a-crbtgk.adb
gcc/ada/a-crbtgk.ads
gcc/ada/a-crbtgo.adb
gcc/ada/a-crbtgo.ads
gcc/ada/a-rbtgso.adb
gcc/ada/a-shcain.adb
gcc/ada/a-shcain.ads
gcc/ada/a-strhas.adb
gcc/ada/a-stunha.adb
gcc/ada/a-stwiha.adb
gcc/ada/a-stwiha.ads
gcc/ada/a-stzhas.adb
gcc/ada/a-swunha.adb [deleted file]
gcc/ada/a-swunha.ads [deleted file]
gcc/ada/a-swuwha.adb [new file with mode: 0644]
gcc/ada/a-swuwha.ads [new file with mode: 0644]
gcc/ada/a-szunha.adb [deleted file]
gcc/ada/a-szunha.ads [deleted file]
gcc/ada/a-szuzha.adb [new file with mode: 0644]
gcc/ada/a-szuzha.ads [new file with mode: 0644]

index 435679d313deaa01386c3aca79bea4f7ab1315dc..a9801e22c3c07423b560e1443f57aad5a10032a2 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                    ADA.CONTAINERS.DOUBLY_LINKED_LISTS                    --
+--   A D A . C O N T A I N E R S . D O U B L Y _ L I N K E D _ L I S T S    --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -45,10 +45,6 @@ package body Ada.Containers.Doubly_Linked_Lists is
    -- Local Subprograms --
    -----------------------
 
-   procedure Delete_Node
-     (Container : in out List;
-      Node      : in out Node_Access);
-
    procedure Insert_Internal
      (Container : in out List;
       Before    : Node_Access;
@@ -88,38 +84,42 @@ package body Ada.Containers.Doubly_Linked_Lists is
    ------------
 
    procedure Adjust (Container : in out List) is
-      Src    : Node_Access := Container.First;
-      Length : constant Count_Type := Container.Length;
+      Src : Node_Access := Container.First;
 
    begin
       if Src = null then
          pragma Assert (Container.Last = null);
-         pragma Assert (Length = 0);
+         pragma Assert (Container.Length = 0);
+         pragma Assert (Container.Busy = 0);
+         pragma Assert (Container.Lock = 0);
          return;
       end if;
 
       pragma Assert (Container.First.Prev = null);
       pragma Assert (Container.Last.Next = null);
-      pragma Assert (Length > 0);
+      pragma Assert (Container.Length > 0);
 
       Container.First := null;
       Container.Last := null;
       Container.Length := 0;
+      Container.Busy := 0;
+      Container.Lock := 0;
 
       Container.First := new Node_Type'(Src.Element, null, null);
-
       Container.Last := Container.First;
-      loop
-         Container.Length := Container.Length + 1;
-         Src := Src.Next;
-         exit when Src = null;
+      Container.Length := 1;
+
+      Src := Src.Next;
+
+      while Src /= null loop
          Container.Last.Next := new Node_Type'(Element => Src.Element,
                                                Prev    => Container.Last,
                                                Next    => null);
          Container.Last := Container.Last.Next;
-      end loop;
+         Container.Length := Container.Length + 1;
 
-      pragma Assert (Container.Length = Length);
+         Src := Src.Next;
+      end loop;
    end Adjust;
 
    ------------
@@ -129,8 +129,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
    procedure Append
      (Container : in out List;
       New_Item  : Element_Type;
-      Count     : Count_Type := 1)
-   is
+      Count     : Count_Type := 1) is
    begin
       Insert (Container, No_Element, New_Item, Count);
    end Append;
@@ -140,8 +139,45 @@ package body Ada.Containers.Doubly_Linked_Lists is
    -----------
 
    procedure Clear (Container : in out List) is
+      X : Node_Access;
+
    begin
-      Delete_Last (Container, Count => Container.Length);
+      if Container.Length = 0 then
+         pragma Assert (Container.First = null);
+         pragma Assert (Container.Last = null);
+         pragma Assert (Container.Busy = 0);
+         pragma Assert (Container.Lock = 0);
+         return;
+      end if;
+
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      while Container.Length > 1 loop
+         X := Container.First;
+         pragma Assert (X.Next.Prev = Container.First);
+
+         Container.First := X.Next;
+         X.Next := null;  --  prevent mischief
+
+         Container.First.Prev := null;
+         Container.Length := Container.Length - 1;
+
+         Free (X);
+      end loop;
+
+      X := Container.First;
+      pragma Assert (X = Container.Last);
+
+      Container.First := null;
+      Container.Last := null;
+      Container.Length := 0;
+
+      Free (X);
    end Clear;
 
    --------------
@@ -150,8 +186,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
 
    function Contains
      (Container : List;
-      Item      : Element_Type) return Boolean
-   is
+      Item      : Element_Type) return Boolean is
    begin
       return Find (Container, Item) /= No_Element;
    end Contains;
@@ -165,22 +200,68 @@ package body Ada.Containers.Doubly_Linked_Lists is
       Position  : in out Cursor;
       Count     : Count_Type := 1)
    is
+      X : Node_Access;
+
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         raise Constraint_Error;
       end if;
 
       if Position.Container /= List_Access'(Container'Unchecked_Access) then
          raise Program_Error;
       end if;
 
+      pragma Assert (Container.Length > 0);
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Container.Last);
+
+      if Position.Node = Container.First then
+         Delete_First (Container, Count);
+         Position := First (Container);
+         return;
+      end if;
+
+      if Count = 0 then
+         return;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       for Index in 1 .. Count loop
-         Delete_Node (Container, Position.Node);
+         X := Position.Node;
+         Container.Length := Container.Length - 1;
 
-         if Position.Node = null then
-            Position.Container := null;
+         if X = Container.Last then
+            Position := No_Element;
+
+            Container.Last := X.Prev;
+            Container.Last.Next := null;
+
+            X.Prev := null;  --  prevent mischief
+            Free (X);
             return;
          end if;
+
+         Position.Node := X.Next;
+
+         X.Next.Prev := X.Prev;
+         X.Prev.Next := X.Next;
+
+         X.Next := null;
+         X.Prev := null;
+         Free (X);
       end loop;
    end Delete;
 
@@ -192,10 +273,33 @@ package body Ada.Containers.Doubly_Linked_Lists is
      (Container : in out List;
       Count     : Count_Type := 1)
    is
-      Node : Node_Access := Container.First;
+      X : Node_Access;
+
    begin
-      for J in 1 .. Count_Type'Min (Count, Container.Length) loop
-         Delete_Node (Container, Node);
+      if Count >= Container.Length then
+         Clear (Container);
+         return;
+      end if;
+
+      if Count = 0 then
+         return;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      for I in 1 .. Count loop
+         X := Container.First;
+         pragma Assert (X.Next.Prev = Container.First);
+
+         Container.First := X.Next;
+         Container.First.Prev := null;
+
+         Container.Length := Container.Length - 1;
+
+         X.Next := null;  --  prevent mischief
+         Free (X);
       end loop;
    end Delete_First;
 
@@ -207,55 +311,35 @@ package body Ada.Containers.Doubly_Linked_Lists is
      (Container : in out List;
       Count     : Count_Type := 1)
    is
-      Node : Node_Access;
-   begin
-      for J in 1 .. Count_Type'Min (Count, Container.Length) loop
-         Node := Container.Last;
-         Delete_Node (Container, Node);
-      end loop;
-   end Delete_Last;
-
-   -----------------
-   -- Delete_Node --
-   -----------------
-
-   procedure Delete_Node
-     (Container : in out List;
-      Node      : in out Node_Access)
-   is
-      X : Node_Access := Node;
+      X : Node_Access;
 
    begin
-      Node := X.Next;
-      Container.Length := Container.Length - 1;
+      if Count >= Container.Length then
+         Clear (Container);
+         return;
+      end if;
 
-      if X = Container.First then
-         Container.First := X.Next;
+      if Count = 0 then
+         return;
+      end if;
 
-         if X = Container.Last then
-            pragma Assert (Container.First = null);
-            pragma Assert (Container.Length = 0);
-            Container.Last := null;
-         else
-            pragma Assert (Container.Length > 0);
-            Container.First.Prev := null;
-         end if;
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
 
-      elsif X = Container.Last then
-         pragma Assert (Container.Length > 0);
+      for I in 1 .. Count loop
+         X := Container.Last;
+         pragma Assert (X.Prev.Next = Container.Last);
 
          Container.Last := X.Prev;
          Container.Last.Next := null;
 
-      else
-         pragma Assert (Container.Length > 0);
+         Container.Length := Container.Length - 1;
 
-         X.Next.Prev := X.Prev;
-         X.Prev.Next := X.Next;
-      end if;
-
-      Free (X);
-   end Delete_Node;
+         X.Prev := null;  --  prevent mischief
+         Free (X);
+      end loop;
+   end Delete_Last;
 
    -------------
    -- Element --
@@ -263,6 +347,21 @@ package body Ada.Containers.Doubly_Linked_Lists is
 
    function Element (Position : Cursor) return Element_Type is
    begin
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       return Position.Node.Element;
    end Element;
 
@@ -280,8 +379,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
    begin
       if Node = null then
          Node := Container.First;
-      elsif Position.Container /= List_Access'(Container'Unchecked_Access) then
-         raise Program_Error;
+      else
+         if Position.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Position.Node.Prev = null
+                          or else Position.Node.Prev.Next = Position.Node);
+         pragma Assert (Position.Node.Next = null
+                          or else Position.Node.Next.Prev = Position.Node);
+         pragma Assert (Position.Node.Prev /= null
+                          or else Position.Node = Container.First);
+         pragma Assert (Position.Node.Next /= null
+                          or else Position.Node = Container.Last);
       end if;
 
       while Node /= null loop
@@ -317,131 +431,173 @@ package body Ada.Containers.Doubly_Linked_Lists is
       return Container.First.Element;
    end First_Element;
 
-   -------------------
-   -- Generic_Merge --
-   -------------------
+   ---------------------
+   -- Generic_Sorting --
+   ---------------------
 
-   procedure Generic_Merge
-     (Target : in out List;
-      Source : in out List)
-   is
-      LI : Cursor := First (Target);
-      RI : Cursor := First (Source);
+   package body Generic_Sorting is
 
-   begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
+      ---------------
+      -- Is_Sorted --
+      ---------------
 
-      while RI.Node /= null loop
-         if LI.Node = null then
-            Splice (Target, No_Element, Source);
+      function Is_Sorted (Container : List) return Boolean is
+         Node : Node_Access := Container.First;
+
+      begin
+         for I in 2 .. Container.Length loop
+            if Node.Next.Element < Node.Element then
+               return False;
+            end if;
+
+            Node := Node.Next;
+         end loop;
+
+         return True;
+      end Is_Sorted;
+
+      -----------
+      -- Merge --
+      -----------
+
+      procedure Merge
+        (Target : in out List;
+         Source : in out List)
+      is
+         LI : Cursor := First (Target);
+         RI : Cursor := First (Source);
+
+      begin
+         if Target'Address = Source'Address then
             return;
          end if;
 
-         if RI.Node.Element < LI.Node.Element then
-            declare
-               RJ : constant Cursor := RI;
-            begin
-               RI.Node := RI.Node.Next;
-               Splice (Target, LI, Source, RJ);
-            end;
-
-         else
-            LI.Node := LI.Node.Next;
+         if Target.Busy > 0
+           or else Source.Busy > 0
+         then
+            raise Program_Error;
          end if;
-      end loop;
-   end Generic_Merge;
 
-   ------------------
-   -- Generic_Sort --
-   ------------------
+         while RI.Node /= null loop
+            if LI.Node = null then
+               Splice (Target, No_Element, Source);
+               return;
+            end if;
+
+            if RI.Node.Element < LI.Node.Element then
+               declare
+                  RJ : Cursor := RI;
+               begin
+                  RI.Node := RI.Node.Next;
+                  Splice (Target, LI, Source, RJ);
+               end;
+
+            else
+               LI.Node := LI.Node.Next;
+            end if;
+         end loop;
+      end Merge;
 
-   procedure Generic_Sort (Container : in out List) is
+      ----------
+      -- Sort --
+      ----------
 
-      procedure Partition
-        (Pivot : in Node_Access;
-         Back  : in Node_Access);
+      procedure Sort (Container : in out List) is
 
-      procedure Sort (Front, Back : Node_Access);
+         procedure Partition
+           (Pivot : in Node_Access;
+            Back  : in Node_Access);
 
-      ---------------
-      -- Partition --
-      ---------------
+         procedure Sort (Front, Back : Node_Access);
 
-      procedure Partition
-        (Pivot : Node_Access;
-         Back  : Node_Access)
-      is
-         Node : Node_Access := Pivot.Next;
+         ---------------
+         -- Partition --
+         ---------------
 
-      begin
-         while Node /= Back loop
-            if Node.Element < Pivot.Element then
-               declare
-                  Prev : constant Node_Access := Node.Prev;
-                  Next : constant Node_Access := Node.Next;
+         procedure Partition
+           (Pivot : Node_Access;
+            Back  : Node_Access)
+         is
+            Node : Node_Access := Pivot.Next;
 
-               begin
-                  Prev.Next := Next;
+         begin
+            while Node /= Back loop
+               if Node.Element < Pivot.Element then
+                  declare
+                     Prev : constant Node_Access := Node.Prev;
+                     Next : constant Node_Access := Node.Next;
 
-                  if Next = null then
-                     Container.Last := Prev;
-                  else
-                     Next.Prev := Prev;
-                  end if;
+                  begin
+                     Prev.Next := Next;
 
-                  Node.Next := Pivot;
-                  Node.Prev := Pivot.Prev;
+                     if Next = null then
+                        Container.Last := Prev;
+                     else
+                        Next.Prev := Prev;
+                     end if;
 
-                  Pivot.Prev := Node;
+                     Node.Next := Pivot;
+                     Node.Prev := Pivot.Prev;
 
-                  if Node.Prev = null then
-                     Container.First := Node;
-                  else
-                     Node.Prev.Next := Node;
-                  end if;
+                     Pivot.Prev := Node;
 
-                  Node := Next;
-               end;
+                     if Node.Prev = null then
+                        Container.First := Node;
+                     else
+                        Node.Prev.Next := Node;
+                     end if;
+
+                     Node := Next;
+                  end;
 
+               else
+                  Node := Node.Next;
+               end if;
+            end loop;
+         end Partition;
+
+         ----------
+         -- Sort --
+         ----------
+
+         procedure Sort (Front, Back : Node_Access) is
+            Pivot : Node_Access;
+
+         begin
+            if Front = null then
+               Pivot := Container.First;
             else
-               Node := Node.Next;
+               Pivot := Front.Next;
             end if;
-         end loop;
-      end Partition;
 
-      ----------
-      -- Sort --
-      ----------
+            if Pivot /= Back then
+               Partition (Pivot, Back);
+               Sort (Front, Pivot);
+               Sort (Pivot, Back);
+            end if;
+         end Sort;
 
-      procedure Sort (Front, Back : Node_Access) is
-         Pivot : Node_Access;
+      --  Start of processing for Sort
 
       begin
-         if Front = null then
-            Pivot := Container.First;
-         else
-            Pivot := Front.Next;
+         if Container.Length <= 1 then
+            return;
          end if;
 
-         if Pivot /= Back then
-            Partition (Pivot, Back);
-            Sort (Front, Pivot);
-            Sort (Pivot, Back);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         if Container.Busy > 0 then
+            raise Program_Error;
          end if;
-      end Sort;
 
-   --  Start of processing for Generic_Sort
+         Sort (Front => null, Back => null);
 
-   begin
-      Sort (Front => null, Back => null);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+      end Sort;
 
-      pragma Assert (Container.Length = 0
-                       or else
-                         (Container.First.Prev = null
-                            and then Container.Last.Next = null));
-   end Generic_Sort;
+   end Generic_Sorting;
 
    -----------------
    -- Has_Element --
@@ -449,7 +605,26 @@ package body Ada.Containers.Doubly_Linked_Lists is
 
    function Has_Element (Position : Cursor) return Boolean is
    begin
-      return Position.Container /= null and then Position.Node /= null;
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return False;
+      end if;
+
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      return True;
    end Has_Element;
 
    ------------
@@ -466,10 +641,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
       New_Node : Node_Access;
 
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Container.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Container.Last);
       end if;
 
       if Count = 0 then
@@ -477,10 +665,18 @@ package body Ada.Containers.Doubly_Linked_Lists is
          return;
       end if;
 
+      if Container.Length > Count_Type'Last - Count then
+         raise Constraint_Error;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       New_Node := new Node_Type'(New_Item, null, null);
       Insert_Internal (Container, Before.Node, New_Node);
 
-      Position := Cursor'(Before.Container, New_Node);
+      Position := Cursor'(Container'Unchecked_Access, New_Node);
 
       for J in Count_Type'(2) .. Count loop
          New_Node := new Node_Type'(New_Item, null, null);
@@ -508,10 +704,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
       New_Node : Node_Access;
 
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Container.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Container.Last);
       end if;
 
       if Count = 0 then
@@ -519,10 +728,18 @@ package body Ada.Containers.Doubly_Linked_Lists is
          return;
       end if;
 
+      if Container.Length > Count_Type'Last - Count then
+         raise Constraint_Error;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       New_Node := new Node_Type;
       Insert_Internal (Container, Before.Node, New_Node);
 
-      Position := Cursor'(Before.Container, New_Node);
+      Position := Cursor'(Container'Unchecked_Access, New_Node);
 
       for J in Count_Type'(2) .. Count loop
          New_Node := new Node_Type;
@@ -595,12 +812,26 @@ package body Ada.Containers.Doubly_Linked_Lists is
      (Container : List;
       Process   : not null access procedure (Position : Cursor))
    is
+      C : List renames Container'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+
       Node : Node_Access := Container.First;
+
    begin
-      while Node /= null loop
-         Process (Cursor'(Container'Unchecked_Access, Node));
-         Node := Node.Next;
-      end loop;
+      B := B + 1;
+
+      begin
+         while Node /= null loop
+            Process (Cursor'(Container'Unchecked_Access, Node));
+            Node := Node.Next;
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ----------
@@ -647,10 +878,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
          return;
       end if;
 
-      if Target.Length > 0 then
-         raise Constraint_Error;
+      if Source.Busy > 0 then
+         raise Program_Error;
       end if;
 
+      Clear (Target);
+
       Target.First := Source.First;
       Source.First := null;
 
@@ -668,9 +901,24 @@ package body Ada.Containers.Doubly_Linked_Lists is
    procedure Next (Position : in out Cursor) is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       Position.Node := Position.Node.Next;
 
       if Position.Node = null then
@@ -681,9 +929,24 @@ package body Ada.Containers.Doubly_Linked_Lists is
    function Next (Position : Cursor) return Cursor is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return No_Element;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       declare
          Next_Node : constant Node_Access := Position.Node.Next;
       begin
@@ -715,9 +978,24 @@ package body Ada.Containers.Doubly_Linked_Lists is
    procedure Previous (Position : in out Cursor) is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       Position.Node := Position.Node.Prev;
 
       if Position.Node = null then
@@ -728,9 +1006,24 @@ package body Ada.Containers.Doubly_Linked_Lists is
    function Previous (Position : Cursor) return Cursor is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return No_Element;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       declare
          Prev_Node : constant Node_Access := Position.Node.Prev;
       begin
@@ -750,8 +1043,42 @@ package body Ada.Containers.Doubly_Linked_Lists is
      (Position : Cursor;
       Process  : not null access procedure (Element : in Element_Type))
    is
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      E : Element_Type renames Position.Node.Element;
+
+      C : List renames Position.Container.all'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+      L : Natural renames C.Lock;
+
    begin
-      Process (Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -766,7 +1093,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
       X : Node_Access;
 
    begin
-      Clear (Item);  --  ???
+      Clear (Item);
       Count_Type'Base'Read (Stream, N);
 
       if N = 0 then
@@ -814,8 +1141,29 @@ package body Ada.Containers.Doubly_Linked_Lists is
      (Position : Cursor;
       By       : Element_Type)
    is
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      E : Element_Type renames Position.Node.Element;
+
    begin
-      Position.Node.Element := By;
+      if Position.Container.Lock > 0 then
+         raise Program_Error;
+      end if;
+
+      E := By;
    end Replace_Element;
 
    ------------------
@@ -832,8 +1180,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
    begin
       if Node = null then
          Node := Container.Last;
-      elsif Position.Container /= List_Access'(Container'Unchecked_Access) then
-         raise Program_Error;
+      else
+         if Position.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Position.Node.Prev = null
+                          or else Position.Node.Prev.Next = Position.Node);
+         pragma Assert (Position.Node.Next = null
+                          or else Position.Node.Next.Prev = Position.Node);
+         pragma Assert (Position.Node.Prev /= null
+                          or else Position.Node = Container.First);
+         pragma Assert (Position.Node.Next /= null
+                          or else Position.Node = Container.Last);
       end if;
 
       while Node /= null loop
@@ -855,12 +1218,26 @@ package body Ada.Containers.Doubly_Linked_Lists is
      (Container : List;
       Process   : not null access procedure (Position : Cursor))
    is
+      C : List renames Container'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+
       Node : Node_Access := Container.Last;
+
    begin
-      while Node /= null loop
-         Process (Cursor'(Container'Unchecked_Access, Node));
-         Node := Node.Prev;
-      end loop;
+      B := B + 1;
+
+      begin
+         while Node /= null loop
+            Process (Cursor'(Container'Unchecked_Access, Node));
+            Node := Node.Prev;
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    ------------------
@@ -918,6 +1295,13 @@ package body Ada.Containers.Doubly_Linked_Lists is
          return;
       end if;
 
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       Container.First := J;
       Container.Last := I;
       loop
@@ -952,10 +1336,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
       Source : in out List)
    is
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Target'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Target'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Target.Length >= 1);
+         pragma Assert (Target.First.Prev = null);
+         pragma Assert (Target.Last.Next = null);
+
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Target.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Target.Last);
       end if;
 
       if Target'Address = Source'Address
@@ -964,7 +1361,22 @@ package body Ada.Containers.Doubly_Linked_Lists is
          return;
       end if;
 
+      pragma Assert (Source.First.Prev = null);
+      pragma Assert (Source.Last.Next = null);
+
+      if Target.Length > Count_Type'Last - Source.Length then
+         raise Constraint_Error;
+      end if;
+
+      if Target.Busy > 0
+        or else Source.Busy > 0
+      then
+         raise Program_Error;
+      end if;
+
       if Target.Length = 0 then
+         pragma Assert (Target.First = null);
+         pragma Assert (Target.Last = null);
          pragma Assert (Before = No_Element);
 
          Target.First := Source.First;
@@ -987,6 +1399,8 @@ package body Ada.Containers.Doubly_Linked_Lists is
          Target.First := Source.First;
 
       else
+         pragma Assert (Target.Length >= 2);
+
          Before.Node.Prev.Next := Source.First;
          Source.First.Prev := Before.Node.Prev;
 
@@ -1006,189 +1420,309 @@ package body Ada.Containers.Doubly_Linked_Lists is
       Before   : Cursor;
       Position : Cursor)
    is
-      X : Node_Access := Position.Node;
-
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Target'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Target'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Target.Length >= 1);
+         pragma Assert (Target.First.Prev = null);
+         pragma Assert (Target.Last.Next = null);
+
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Target.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Target.Last);
       end if;
 
-      if Position.Container /= null
-        and then Position.Container /= List_Access'(Target'Unchecked_Access)
-      then
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
+
+      if Position.Container /= List_Access'(Target'Unchecked_Access) then
          raise Program_Error;
       end if;
 
-      if X = null
-        or else X = Before.Node
-        or else X.Next = Before.Node
+      pragma Assert (Target.Length >= 1);
+      pragma Assert (Target.First.Prev = null);
+      pragma Assert (Target.Last.Next = null);
+
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Target.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Target.Last);
+
+      if Position.Node = Before.Node
+        or else Position.Node.Next = Before.Node
       then
          return;
       end if;
 
-      pragma Assert (Target.Length > 0);
+      pragma Assert (Target.Length >= 2);
+
+      if Target.Busy > 0 then
+         raise Program_Error;
+      end if;
 
       if Before.Node = null then
-         pragma Assert (X /= Target.Last);
+         pragma Assert (Position.Node /= Target.Last);
 
-         if X = Target.First then
-            Target.First := X.Next;
+         if Position.Node = Target.First then
+            Target.First := Position.Node.Next;
             Target.First.Prev := null;
          else
-            X.Prev.Next := X.Next;
-            X.Next.Prev := X.Prev;
+            Position.Node.Prev.Next := Position.Node.Next;
+            Position.Node.Next.Prev := Position.Node.Prev;
          end if;
 
-         Target.Last.Next := X;
-         X.Prev := Target.Last;
+         Target.Last.Next := Position.Node;
+         Position.Node.Prev := Target.Last;
 
-         Target.Last := X;
+         Target.Last := Position.Node;
          Target.Last.Next := null;
 
          return;
       end if;
 
       if Before.Node = Target.First then
-         pragma Assert (X /= Target.First);
+         pragma Assert (Position.Node /= Target.First);
 
-         if X = Target.Last then
-            Target.Last := X.Prev;
+         if Position.Node = Target.Last then
+            Target.Last := Position.Node.Prev;
             Target.Last.Next := null;
          else
-            X.Prev.Next := X.Next;
-            X.Next.Prev := X.Prev;
+            Position.Node.Prev.Next := Position.Node.Next;
+            Position.Node.Next.Prev := Position.Node.Prev;
          end if;
 
-         Target.First.Prev := X;
-         X.Next := Target.First;
+         Target.First.Prev := Position.Node;
+         Position.Node.Next := Target.First;
 
-         Target.First := X;
+         Target.First := Position.Node;
          Target.First.Prev := null;
 
          return;
       end if;
 
-      if X = Target.First then
-         Target.First := X.Next;
+      if Position.Node = Target.First then
+         Target.First := Position.Node.Next;
          Target.First.Prev := null;
 
-      elsif X = Target.Last then
-         Target.Last := X.Prev;
+      elsif Position.Node = Target.Last then
+         Target.Last := Position.Node.Prev;
          Target.Last.Next := null;
 
       else
-         X.Prev.Next := X.Next;
-         X.Next.Prev := X.Prev;
+         Position.Node.Prev.Next := Position.Node.Next;
+         Position.Node.Next.Prev := Position.Node.Prev;
       end if;
 
-      Before.Node.Prev.Next := X;
-      X.Prev := Before.Node.Prev;
+      Before.Node.Prev.Next := Position.Node;
+      Position.Node.Prev := Before.Node.Prev;
+
+      Before.Node.Prev := Position.Node;
+      Position.Node.Next := Before.Node;
 
-      Before.Node.Prev := X;
-      X.Next := Before.Node;
+      pragma Assert (Target.First.Prev = null);
+      pragma Assert (Target.Last.Next = null);
    end Splice;
 
    procedure Splice
      (Target   : in out List;
       Before   : Cursor;
       Source   : in out List;
-      Position : Cursor)
+      Position : in out Cursor)
    is
-      X : Node_Access := Position.Node;
-
    begin
       if Target'Address = Source'Address then
          Splice (Target, Before, Position);
          return;
       end if;
 
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Target'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Target'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Target.Length >= 1);
+         pragma Assert (Target.First.Prev = null);
+         pragma Assert (Target.Last.Next = null);
+
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Target.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Target.Last);
       end if;
 
-      if Position.Container /= null
-        and then Position.Container /= List_Access'(Source'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if X = null then
-         return;
+      if Position.Container /= List_Access'(Source'Unchecked_Access) then
+         raise Program_Error;
       end if;
 
-      pragma Assert (Source.Length > 0);
+      pragma Assert (Source.Length >= 1);
       pragma Assert (Source.First.Prev = null);
       pragma Assert (Source.Last.Next = null);
 
-      if X = Source.First then
-         Source.First := X.Next;
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Source.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Source.Last);
+
+      if Target.Length = Count_Type'Last then
+         raise Constraint_Error;
+      end if;
+
+      if Target.Busy > 0
+        or else Source.Busy > 0
+      then
+         raise Program_Error;
+      end if;
+
+      if Position.Node = Source.First then
+         Source.First := Position.Node.Next;
          Source.First.Prev := null;
 
-         if X = Source.Last then
+         if Position.Node = Source.Last then
             pragma Assert (Source.First = null);
             pragma Assert (Source.Length = 1);
             Source.Last := null;
          end if;
 
-      elsif X = Source.Last then
-         Source.Last := X.Prev;
+      elsif Position.Node = Source.Last then
+         pragma Assert (Source.Length >= 2);
+         Source.Last := Position.Node.Prev;
          Source.Last.Next := null;
 
       else
-         X.Prev.Next := X.Next;
-         X.Next.Prev := X.Prev;
+         pragma Assert (Source.Length >= 3);
+         Position.Node.Prev.Next := Position.Node.Next;
+         Position.Node.Next.Prev := Position.Node.Prev;
       end if;
 
       if Target.Length = 0 then
-         pragma Assert (Before = No_Element);
          pragma Assert (Target.First = null);
          pragma Assert (Target.Last = null);
+         pragma Assert (Before = No_Element);
 
-         Target.First := X;
-         Target.Last := X;
+         Target.First := Position.Node;
+         Target.Last := Position.Node;
+
+         Target.First.Prev := null;
+         Target.Last.Next := null;
 
       elsif Before.Node = null then
-         Target.Last.Next := X;
-         X.Next := Target.Last;
+         pragma Assert (Target.Last.Next = null);
+         Target.Last.Next := Position.Node;
+         Position.Node.Prev := Target.Last;
 
-         Target.Last := X;
+         Target.Last := Position.Node;
          Target.Last.Next := null;
 
       elsif Before.Node = Target.First then
-         Target.First.Prev := X;
-         X.Next := Target.First;
+         pragma Assert (Target.First.Prev = null);
+         Target.First.Prev := Position.Node;
+         Position.Node.Next := Target.First;
 
-         Target.First := X;
+         Target.First := Position.Node;
          Target.First.Prev := null;
 
       else
-         Before.Node.Prev.Next := X;
-         X.Prev := Before.Node.Prev;
+         pragma Assert (Target.Length >= 2);
+         Before.Node.Prev.Next := Position.Node;
+         Position.Node.Prev := Before.Node.Prev;
 
-         Before.Node.Prev := X;
-         X.Next := Before.Node;
+         Before.Node.Prev := Position.Node;
+         Position.Node.Next := Before.Node;
       end if;
 
       Target.Length := Target.Length + 1;
       Source.Length := Source.Length - 1;
+
+      Position.Container := Target'Unchecked_Access;
    end Splice;
 
    ----------
    -- Swap --
    ----------
 
-   --  Is this defined when I and J designate elements in different containers,
-   --  or should it raise an exception (Program_Error)???
-
-   procedure Swap (I, J : in Cursor) is
-      EI : constant Element_Type := I.Node.Element;
+   procedure Swap (I, J : Cursor) is
    begin
-      I.Node.Element := J.Node.Element;
-      J.Node.Element := EI;
+      if I.Container = null
+        or else J.Container = null
+      then
+         raise Constraint_Error;
+      end if;
+
+      if I.Container /= J.Container then
+         raise Program_Error;
+      end if;
+
+      declare
+         C : List renames I.Container.all;
+      begin
+         pragma Assert (C.Length >= 1);
+         pragma Assert (C.First.Prev = null);
+         pragma Assert (C.Last.Next = null);
+
+         pragma Assert (I.Node /= null);
+         pragma Assert (I.Node.Prev = null
+                          or else I.Node.Prev.Next = I.Node);
+         pragma Assert (I.Node.Next = null
+                          or else I.Node.Next.Prev = I.Node);
+         pragma Assert (I.Node.Prev /= null
+                          or else I.Node = C.First);
+         pragma Assert (I.Node.Next /= null
+                          or else I.Node = C.Last);
+
+         if I.Node = J.Node then
+            return;
+         end if;
+
+         pragma Assert (C.Length >= 2);
+         pragma Assert (J.Node /= null);
+         pragma Assert (J.Node.Prev = null
+                          or else J.Node.Prev.Next = J.Node);
+         pragma Assert (J.Node.Next = null
+                          or else J.Node.Next.Prev = J.Node);
+         pragma Assert (J.Node.Prev /= null
+                          or else J.Node = C.First);
+         pragma Assert (J.Node.Next /= null
+                          or else J.Node = C.Last);
+
+         if C.Lock > 0 then
+            raise Program_Error;
+         end if;
+
+         declare
+            EI : Element_Type renames I.Node.Element;
+            EJ : Element_Type renames J.Node.Element;
+
+            EI_Copy : constant Element_Type := EI;
+         begin
+            EI := EJ;
+            EJ := EI_Copy;
+         end;
+      end;
    end Swap;
 
    ----------------
@@ -1197,11 +1731,10 @@ package body Ada.Containers.Doubly_Linked_Lists is
 
    procedure Swap_Links
      (Container : in out List;
-      I, J      : Cursor)
-   is
+      I, J      : Cursor) is
    begin
-      if I = No_Element
-        or else J = No_Element
+      if I.Container = null
+        or else J.Container = null
       then
          raise Constraint_Error;
       end if;
@@ -1215,6 +1748,18 @@ package body Ada.Containers.Doubly_Linked_Lists is
       end if;
 
       pragma Assert (Container.Length >= 1);
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      pragma Assert (I.Node /= null);
+      pragma Assert (I.Node.Prev = null
+                       or else I.Node.Prev.Next = I.Node);
+      pragma Assert (I.Node.Next = null
+                       or else I.Node.Next.Prev = I.Node);
+      pragma Assert (I.Node.Prev /= null
+                       or else I.Node = Container.First);
+      pragma Assert (I.Node.Next /= null
+                       or else I.Node = Container.Last);
 
       if I.Node = J.Node then
          return;
@@ -1222,6 +1767,20 @@ package body Ada.Containers.Doubly_Linked_Lists is
 
       pragma Assert (Container.Length >= 2);
 
+      pragma Assert (J.Node /= null);
+      pragma Assert (J.Node.Prev = null
+                       or else J.Node.Prev.Next = J.Node);
+      pragma Assert (J.Node.Next = null
+                       or else J.Node.Next.Prev = J.Node);
+      pragma Assert (J.Node.Prev /= null
+                       or else J.Node = Container.First);
+      pragma Assert (J.Node.Next /= null
+                       or else J.Node = Container.Last);
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       declare
          I_Next : constant Cursor := Next (I);
 
@@ -1255,8 +1814,43 @@ package body Ada.Containers.Doubly_Linked_Lists is
    procedure Update_Element
      (Position : Cursor;
       Process  : not null access procedure (Element : in out Element_Type)) is
+
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length >= 1);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      E : Element_Type renames Position.Node.Element;
+
+      C : List renames Position.Container.all'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+      L : Natural renames C.Lock;
+
    begin
-      Process (Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
    -----------
@@ -1279,4 +1873,3 @@ package body Ada.Containers.Doubly_Linked_Lists is
    end Write;
 
 end Ada.Containers.Doubly_Linked_Lists;
-
index f87479cabe649c109937fa5aefe5aeaeea1f2a8d..32f8d7749e7686b465ebe3dff27aa55f5372c504 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                    ADA.CONTAINERS.DOUBLY_LINKED_LISTS                    --
+--   A D A . C O N T A I N E R S . D O U B L Y _ L I N K E D _ L I S T S    --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -122,18 +122,20 @@ package Ada.Containers.Doubly_Linked_Lists is
       Count     : Count_Type := 1);
 
    generic
-      with function "<" (Left, Right : Element_Type)
-         return Boolean is <>;
-   procedure Generic_Sort (Container : in out List);
+      with function "<" (Left, Right : Element_Type) return Boolean is <>;
+   package Generic_Sorting is
 
-   generic
-      with function "<" (Left, Right : Element_Type)
-         return Boolean is <>;
-   procedure Generic_Merge (Target : in out List; Source : in out List);
+      function Is_Sorted (Container : List) return Boolean;
+
+      procedure Sort (Container : in out List);
+
+      procedure Merge (Target, Source : in out List);
+
+   end Generic_Sorting;
 
    procedure Reverse_List (Container : in out List);
 
-   procedure Swap (I, J : in Cursor);
+   procedure Swap (I, J : Cursor);
 
    procedure Swap_Links
      (Container : in out List;
@@ -153,7 +155,7 @@ package Ada.Containers.Doubly_Linked_Lists is
      (Target   : in out List;
       Before   : Cursor;
       Source   : in out List;
-      Position : Cursor);
+      Position : in out Cursor);
 
    function First (Container : List) return Cursor;
 
@@ -200,14 +202,12 @@ private
    type Node_Access is access Node_Type;
 
    type Node_Type is
-      record
+      limited record
          Element : Element_Type;
          Next    : Node_Access;
          Prev    : Node_Access;
       end record;
 
-   function "=" (L, R : Node_Type) return Boolean is abstract;
-
    use Ada.Finalization;
 
    type List is
@@ -215,6 +215,8 @@ private
         First  : Node_Access;
         Last   : Node_Access;
         Length : Count_Type := 0;
+        Busy   : Natural := 0;
+        Lock   : Natural := 0;
      end record;
 
    procedure Adjust (Container : in out List);
@@ -235,7 +237,7 @@ private
 
    for List'Write use Write;
 
-   Empty_List : constant List := List'(Controlled with null, null, 0);
+   Empty_List : constant List := (Controlled with null, null, 0, 0, 0);
 
    type List_Access is access constant List;
    for List_Access'Storage_Size use 0;
@@ -249,4 +251,3 @@ private
    No_Element : constant Cursor := Cursor'(null, null);
 
 end Ada.Containers.Doubly_Linked_Lists;
-
index 9a21ad0c9eb73fad209081d6e731a19fb818cd85..010d557de82d989f53b3816b8f21b2930b7e0c27 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                 ADA.CONTAINERS.HASH_TABLES.GENERIC_KEYS                  --
+--                      A D A . C O N T A I N E R S .                       --
+--             H A S H _ T A B L E S . G E N E R I C _ K E Y S              --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -40,7 +41,7 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
    --------------------------
 
    procedure Delete_Key_Sans_Free
-     (HT   : in out HT_Type;
+     (HT   : in out Hash_Table_Type;
       Key  : Key_Type;
       X    : out Node_Access)
    is
@@ -49,18 +50,21 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
 
    begin
       if HT.Length = 0 then
-         X := Null_Node;
+         X := null;
          return;
       end if;
 
       Indx := Index (HT, Key);
       X := HT.Buckets (Indx);
 
-      if X = Null_Node then
+      if X = null then
          return;
       end if;
 
       if Equivalent_Keys (Key, X) then
+         if HT.Busy > 0 then
+            raise Program_Error;
+         end if;
          HT.Buckets (Indx) := Next (X);
          HT.Length := HT.Length - 1;
          return;
@@ -70,11 +74,14 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
          Prev := X;
          X := Next (Prev);
 
-         if X = Null_Node then
+         if X = null then
             return;
          end if;
 
          if Equivalent_Keys (Key, X) then
+            if HT.Busy > 0 then
+               raise Program_Error;
+            end if;
             Set_Next (Node => Prev, Next => Next (X));
             HT.Length := HT.Length - 1;
             return;
@@ -87,7 +94,7 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
    ----------
 
    function Find
-     (HT  : HT_Type;
+     (HT  : Hash_Table_Type;
       Key : Key_Type) return Node_Access is
 
       Indx : Hash_Type;
@@ -95,20 +102,20 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
 
    begin
       if HT.Length = 0 then
-         return Null_Node;
+         return null;
       end if;
 
       Indx := Index (HT, Key);
 
       Node := HT.Buckets (Indx);
-      while Node /= Null_Node loop
+      while Node /= null loop
          if Equivalent_Keys (Key, Node) then
             return Node;
          end if;
          Node := Next (Node);
       end loop;
 
-      return Null_Node;
+      return null;
    end Find;
 
    --------------------------------
@@ -116,10 +123,10 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
    --------------------------------
 
    procedure Generic_Conditional_Insert
-     (HT      : in out HT_Type;
-      Key     : Key_Type;
-      Node    : out Node_Access;
-      Success : out Boolean)
+     (HT       : in out Hash_Table_Type;
+      Key      : Key_Type;
+      Node     : out Node_Access;
+      Inserted : out Boolean)
    is
       Indx : constant Hash_Type := Index (HT, Key);
       B    : Node_Access renames HT.Buckets (Indx);
@@ -127,12 +134,16 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
       subtype Length_Subtype is Count_Type range 0 .. Count_Type'Last - 1;
 
    begin
-      if B = Null_Node then
+      if B = null then
+         if HT.Busy > 0 then
+            raise Program_Error;
+         end if;
+
          declare
             Length : constant Length_Subtype := HT.Length;
          begin
-            Node := New_Node (Next => Null_Node);
-            Success := True;
+            Node := New_Node (Next => null);
+            Inserted := True;
 
             B := Node;
             HT.Length := Length + 1;
@@ -144,20 +155,24 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
       Node := B;
       loop
          if Equivalent_Keys (Key, Node) then
-            Success := False;
+            Inserted := False;
             return;
          end if;
 
          Node := Next (Node);
 
-         exit when Node = Null_Node;
+         exit when Node = null;
       end loop;
 
+      if HT.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       declare
          Length : constant Length_Subtype := HT.Length;
       begin
          Node := New_Node (Next => B);
-         Success := True;
+         Inserted := True;
 
          B := Node;
          HT.Length := Length + 1;
@@ -169,7 +184,7 @@ package body Ada.Containers.Hash_Tables.Generic_Keys is
    -----------
 
    function Index
-     (HT  : HT_Type;
+     (HT  : Hash_Table_Type;
       Key : Key_Type) return Hash_Type is
    begin
       return Hash (Key) mod HT.Buckets'Length;
index 704c653f730bc6244cf03c93def20ba460e8142c..a0812ba612ba6072a97f4bb350b12cd86f06277a 100644 (file)
@@ -2,27 +2,44 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                 ADA.CONTAINERS.HASH_TABLES.GENERIC_KEYS                  --
+--                      A D A . C O N T A I N E R S .                       --
+--             H A S H _ T A B L E S . G E N E R I C _ K E Y S              --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
--- This specification is adapted from the Ada Reference Manual for use with --
--- GNAT.  In accordance with the copyright of that document, you can freely --
--- copy and modify this specification,  provided that if you redistribute a --
--- modified version,  any changes that you have made are clearly indicated. --
+--          Copyright (C) 2004-2005 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.                  --
 ------------------------------------------------------------------------------
 
 generic
    with package HT_Types is
      new Generic_Hash_Table_Types (<>);
 
-   type HT_Type is new HT_Types.Hash_Table_Type with private;
-
    use HT_Types;
 
-   Null_Node : Node_Access;
-
    with function Next (Node : Node_Access) return Node_Access;
 
    with procedure Set_Next
@@ -41,24 +58,24 @@ package Ada.Containers.Hash_Tables.Generic_Keys is
    pragma Preelaborate;
 
    function Index
-     (HT  : HT_Type;
+     (HT  : Hash_Table_Type;
       Key : Key_Type) return Hash_Type;
    pragma Inline (Index);
 
    procedure Delete_Key_Sans_Free
-     (HT   : in out HT_Type;
+     (HT   : in out Hash_Table_Type;
       Key  : Key_Type;
       X    : out Node_Access);
 
-   function Find (HT  : HT_Type; Key : Key_Type) return Node_Access;
+   function Find (HT  : Hash_Table_Type; Key : Key_Type) return Node_Access;
 
    generic
       with function New_Node
         (Next : Node_Access) return Node_Access;
    procedure Generic_Conditional_Insert
-     (HT      : in out HT_Type;
-      Key     : Key_Type;
-      Node    : out Node_Access;
-      Success : out Boolean);
+     (HT       : in out Hash_Table_Type;
+      Key      : Key_Type;
+      Node     : out Node_Access;
+      Inserted : out Boolean);
 
 end Ada.Containers.Hash_Tables.Generic_Keys;
index aa27f427c2e85e590dbf2d16c7dea3dd7a0731c3..39879b64aa8037b82fc391400c7faf14277dd170 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---              ADA.CONTAINERS.HASH_TABLES.GENERIC_OPERATIONS               --
+--                       A D A . C O N T A I N E R S .                      --
+--       H A S H _ T A B L E S . G E N E R I C _ O P E R A T I O N S        --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 Free Software Foundation, Inc.          --
 --                                                                          --
 -- 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- --
@@ -68,7 +69,9 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       end if;
 
       HT.Buckets := new Buckets_Type (Src_Buckets'Range);
+      --  TODO: allocate minimum size req'd.  (See note below.)
 
+      --  NOTE: see note below about these comments.
       --  Probably we have to duplicate the Size (Src), too, in order
       --  to guarantee that
 
@@ -80,11 +83,30 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       --  If we relax the requirement that the hash value must be the
       --  same, then of course we can't guarantee that following
       --  assignment that Dst = Src is true ???
+      --
+      --  NOTE: 17 Apr 2005
+      --  What I said above is no longer true.  The semantics of (map) equality
+      --  changed, such that we use key in the left map to look up the
+      --  equivalent key in the right map, and then compare the elements (using
+      --  normal equality) of the equivalent keys.  So it doesn't matter that
+      --  the maps have different capacities (i.e. the hash tables have
+      --  different lengths), since we just look up the key, irrespective of
+      --  its map's hash table length.  All the RM says we're required to do
+      --  it arrange for the target map to "=" the source map following an
+      --  assignment (that is, following an Adjust), so it doesn't matter
+      --  what the capacity of the target map is.  What I'll probably do is
+      --  allocate a new hash table that has the minimum size necessary,
+      --  instead of allocating a new hash table whose size exactly matches
+      --  that of the source.  (See the assignment that immediately precedes
+      --  these comments.)  What we really need is a special Assign operation
+      --  (not unlike what we have already for Vector) that allows the user to
+      --  choose the capacity of the target.
+      --  END NOTE.
 
       for Src_Index in Src_Buckets'Range loop
          Src_Node := Src_Buckets (Src_Index);
 
-         if Src_Node /= Null_Node then
+         if Src_Node /= null then
             declare
                Dst_Node : constant Node_Access := Copy_Node (Src_Node);
 
@@ -100,7 +122,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
             end;
 
             Src_Node := Next (Src_Node);
-            while Src_Node /= Null_Node loop
+            while Src_Node /= null loop
                declare
                   Dst_Node : constant Node_Access := Copy_Node (Src_Node);
 
@@ -145,8 +167,12 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       Node  : Node_Access;
 
    begin
+      if HT.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       while HT.Length > 0 loop
-         while HT.Buckets (Index) = Null_Node loop
+         while HT.Buckets (Index) = null loop
             Index := Index + 1;
          end loop;
 
@@ -158,7 +184,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
                Bucket := Next (Bucket);
                HT.Length := HT.Length - 1;
                Free (Node);
-               exit when Bucket = Null_Node;
+               exit when Bucket = null;
             end loop;
          end;
       end loop;
@@ -172,7 +198,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
      (HT : in out Hash_Table_Type;
       X  : Node_Access)
    is
-      pragma Assert (X /= Null_Node);
+      pragma Assert (X /= null);
 
       Indx : Hash_Type;
       Prev : Node_Access;
@@ -186,7 +212,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       Indx := Index (HT, X);
       Prev := HT.Buckets (Indx);
 
-      if Prev = Null_Node then
+      if Prev = null then
          raise Program_Error;
       end if;
 
@@ -203,7 +229,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       loop
          Curr := Next (Prev);
 
-         if Curr = Null_Node then
+         if Curr = null then
             raise Program_Error;
          end if;
 
@@ -217,75 +243,6 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       end loop;
    end Delete_Node_Sans_Free;
 
-   ---------------------
-   -- Ensure_Capacity --
-   ---------------------
-
-   procedure Ensure_Capacity
-     (HT : in out Hash_Table_Type;
-      N  : Count_Type)
-   is
-      NN : Hash_Type;
-
-   begin
-      if N = 0 then
-         if HT.Length = 0 then
-            Free (HT.Buckets);
-
-         elsif HT.Length < HT.Buckets'Length then
-            NN := Prime_Numbers.To_Prime (HT.Length);
-
-            --  ASSERT: NN >= HT.Length
-
-            if NN < HT.Buckets'Length then
-               Rehash (HT, Size => NN);
-            end if;
-         end if;
-
-         return;
-      end if;
-
-      if HT.Buckets = null then
-         NN := Prime_Numbers.To_Prime (N);
-
-         --  ASSERT: NN >= N
-
-         Rehash (HT, Size => NN);
-         return;
-      end if;
-
-      if N <= HT.Length then
-         if HT.Length >= HT.Buckets'Length then
-            return;
-         end if;
-
-         NN := Prime_Numbers.To_Prime (HT.Length);
-
-         --  ASSERT: NN >= HT.Length
-
-         if NN < HT.Buckets'Length then
-            Rehash (HT, Size => NN);
-         end if;
-
-         return;
-      end if;
-
-      --  ASSERT: N > HT.Length
-
-      if N = HT.Buckets'Length then
-         return;
-      end if;
-
-      NN := Prime_Numbers.To_Prime (N);
-
-      --  ASSERT: NN >= N
-      --  ASSERT: NN > HT.Length
-
-      if NN /= HT.Buckets'Length then
-         Rehash (HT, Size => NN);
-      end if;
-   end Ensure_Capacity;
-
    --------------
    -- Finalize --
    --------------
@@ -305,12 +262,12 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
 
    begin
       if HT.Length = 0 then
-         return Null_Node;
+         return null;
       end if;
 
       Indx := HT.Buckets'First;
       loop
-         if HT.Buckets (Indx) /= Null_Node then
+         if HT.Buckets (Indx) /= null then
             return HT.Buckets (Indx);
          end if;
 
@@ -331,7 +288,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       end if;
 
       for J in Buckets'Range loop
-         while Buckets (J) /= Null_Node loop
+         while Buckets (J) /= null loop
             Node := Buckets (J);
             Buckets (J) := Next (Node);
             Free (Node);
@@ -370,7 +327,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
 
       loop
          L_Node := L.Buckets (L_Index);
-         exit when L_Node /= Null_Node;
+         exit when L_Node /= null;
          L_Index := L_Index + 1;
       end loop;
 
@@ -385,7 +342,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
 
          L_Node := Next (L_Node);
 
-         if L_Node = Null_Node then
+         if L_Node = null then
             if N = 0 then
                return True;
             end if;
@@ -393,7 +350,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
             loop
                L_Index := L_Index + 1;
                L_Node := L.Buckets (L_Index);
-               exit when L_Node /= Null_Node;
+               exit when L_Node /= null;
             end loop;
          end if;
       end loop;
@@ -404,22 +361,32 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
    -----------------------
 
    procedure Generic_Iteration (HT : Hash_Table_Type) is
-      Node : Node_Access;
+      Busy : Natural renames HT'Unrestricted_Access.all.Busy;
 
    begin
-      if HT.Buckets = null
-        or else HT.Length = 0
-      then
+      if HT.Length = 0 then
          return;
       end if;
 
-      for Indx in HT.Buckets'Range loop
-         Node := HT.Buckets (Indx);
-         while Node /= Null_Node loop
-            Process (Node);
-            Node := Next (Node);
+      Busy := Busy + 1;
+
+      declare
+         Node : Node_Access;
+      begin
+         for Indx in HT.Buckets'Range loop
+            Node := HT.Buckets (Indx);
+            while Node /= null loop
+               Process (Node);
+               Node := Next (Node);
+            end loop;
          end loop;
-      end loop;
+      exception
+         when others =>
+            Busy := Busy - 1;
+            raise;
+      end;
+
+      Busy := Busy - 1;
    end Generic_Iteration;
 
    ------------------
@@ -436,10 +403,6 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       N, M    : Count_Type'Base;
 
    begin
-      --  As with the sorted set, it's not clear whether read is allowed to
-      --  have side effect if it fails. For now, we assume side effects are
-      --  allowed since it simplifies the algorithm ???
-      --
       Clear (HT);
 
       declare
@@ -452,6 +415,10 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
 
       Hash_Type'Read (Stream, Last);
 
+      --  TODO: don't immediately deallocate the buckets array we
+      --  already have. Instead, allocate a new buckets array only
+      --  if it needs to expanded because of the value of Last.
+
       if Last /= 0 then
          HT.Buckets := new Buckets_Type (0 .. Last);
       end if;
@@ -461,15 +428,15 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       while N > 0 loop
          Hash_Type'Read (Stream, I);
          pragma Assert (I in HT.Buckets'Range);
-         pragma Assert (HT.Buckets (I) = Null_Node);
+         pragma Assert (HT.Buckets (I) = null);
 
          Count_Type'Base'Read (Stream, M);
          pragma Assert (M >= 1);
          pragma Assert (M <= N);
 
          HT.Buckets (I) := New_Node (Stream);
-         pragma Assert (HT.Buckets (I) /= Null_Node);
-         pragma Assert (Next (HT.Buckets (I)) = Null_Node);
+         pragma Assert (HT.Buckets (I) /= null);
+         pragma Assert (Next (HT.Buckets (I)) = null);
 
          Y := HT.Buckets (I);
 
@@ -477,8 +444,8 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
 
          for J in Count_Type range 2 .. M loop
             X := New_Node (Stream);
-            pragma Assert (X /= Null_Node);
-            pragma Assert (Next (X) = Null_Node);
+            pragma Assert (X /= null);
+            pragma Assert (Next (X) = null);
 
             Set_Next (Node => Y, Next => X);
             Y := X;
@@ -517,11 +484,11 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       for Indx in HT.Buckets'Range loop
          X := HT.Buckets (Indx);
 
-         if X /= Null_Node then
+         if X /= null then
             M := 1;
             loop
                X := Next (X);
-               exit when X = Null_Node;
+               exit when X = null;
                M := M + 1;
             end loop;
 
@@ -534,7 +501,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
                X := Next (X);
             end loop;
 
-            pragma Assert (X = Null_Node);
+            pragma Assert (X = null);
          end if;
       end loop;
    end Generic_Write;
@@ -567,14 +534,18 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
          return;
       end if;
 
-      if Target.Length > 0 then
-         raise Constraint_Error;
+      if Source.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      Free (Target.Buckets);
+      Clear (Target);
 
-      Target.Buckets := Source.Buckets;
-      Source.Buckets := null;
+      declare
+         Buckets : constant Buckets_Access := Target.Buckets;
+      begin
+         Target.Buckets := Source.Buckets;
+         Source.Buckets := Buckets;
+      end;
 
       Target.Length := Source.Length;
       Source.Length := 0;
@@ -591,19 +562,19 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       Result : Node_Access := Next (Node);
 
    begin
-      if Result /= Null_Node then
+      if Result /= null then
          return Result;
       end if;
 
       for Indx in Index (HT, Node) + 1 .. HT.Buckets'Last loop
          Result := HT.Buckets (Indx);
 
-         if Result /= Null_Node then
+         if Result /= null then
             return Result;
          end if;
       end loop;
 
-      return Null_Node;
+      return null;
    end Next;
 
    ------------
@@ -642,7 +613,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
          declare
             Src_Bucket : Node_Access renames Src_Buckets (Src_Index);
          begin
-            while Src_Bucket /= Null_Node loop
+            while Src_Bucket /= null loop
                declare
                   Src_Node   : constant Node_Access := Src_Bucket;
                   Dst_Index  : constant Hash_Type :=
@@ -662,6 +633,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
          exception
             when others =>
 
+               --  NOTE: see todo below.
                --  Not clear that we can deallocate the nodes,
                --  because they may be designated by outstanding
                --  iterators.  Which means they're now lost... ???
@@ -671,7 +643,7 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
                --                       Dst : Node_Access renames NB (J);
                --                       X   : Node_Access;
                --                    begin
-               --                       while Dst /= Null_Node loop
+               --                       while Dst /= null loop
                --                          X := Dst;
                --                          Dst := Succ (Dst);
                --                          Free (X);
@@ -679,9 +651,15 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
                --                    end;
                --                 end loop;
 
+               --  TODO: 17 Apr 2005
+               --  What I should do instead is go ahead and deallocate the
+               --  nodes, since when assertions are enabled, we vet the
+               --  cursors, and we modify the state of a node enough when
+               --  it is deallocated in order to detect mischief.
+               --  END TODO.
 
                Free (Dst_Buckets);
-               raise;
+               raise;  --  TODO: raise Program_Error instead
          end;
 
          --  exit when L = 0;
@@ -697,5 +675,85 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
       Free (Src_Buckets);
    end Rehash;
 
-end Ada.Containers.Hash_Tables.Generic_Operations;
+   ----------------------
+   -- Reserve_Capacity --
+   ----------------------
+
+   procedure Reserve_Capacity
+     (HT : in out Hash_Table_Type;
+      N  : Count_Type)
+   is
+      NN : Hash_Type;
+
+   begin
+      if N = 0 then
+         if HT.Length = 0 then
+            Free (HT.Buckets);
+
+         elsif HT.Length < HT.Buckets'Length then
+            NN := Prime_Numbers.To_Prime (HT.Length);
+
+            --  ASSERT: NN >= HT.Length
+
+            if NN < HT.Buckets'Length then
+               if HT.Busy > 0 then
+                  raise Program_Error;
+               end if;
+
+               Rehash (HT, Size => NN);
+            end if;
+         end if;
+
+         return;
+      end if;
+
+      if HT.Buckets = null then
+         NN := Prime_Numbers.To_Prime (N);
+
+         --  ASSERT: NN >= N
+
+         Rehash (HT, Size => NN);
+         return;
+      end if;
+
+      if N <= HT.Length then
+         if HT.Length >= HT.Buckets'Length then
+            return;
+         end if;
+
+         NN := Prime_Numbers.To_Prime (HT.Length);
+
+         --  ASSERT: NN >= HT.Length
+
+         if NN < HT.Buckets'Length then
+            if HT.Busy > 0 then
+               raise Program_Error;
+            end if;
+
+            Rehash (HT, Size => NN);
+         end if;
+
+         return;
+      end if;
 
+      --  ASSERT: N > HT.Length
+
+      if N = HT.Buckets'Length then
+         return;
+      end if;
+
+      NN := Prime_Numbers.To_Prime (N);
+
+      --  ASSERT: NN >= N
+      --  ASSERT: NN > HT.Length
+
+      if NN /= HT.Buckets'Length then
+         if HT.Busy > 0 then
+            raise Program_Error;
+         end if;
+
+         Rehash (HT, Size => NN);
+      end if;
+   end Reserve_Capacity;
+
+end Ada.Containers.Hash_Tables.Generic_Operations;
index 232c719b04c69157b90685636dd592e09d2ad0aa..7d6e545e27196e46d88f73fc0391b887bcb89cd1 100644 (file)
@@ -2,12 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---              ADA.CONTAINERS.HASH_TABLES.GENERIC_OPERATIONS               --
+--                       A D A . C O N T A I N E R S .                      --
+--       H A S H _ T A B L E S . G E N E R I C _ O P E R A T I O N S        --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
---                                                                          --
 -- This specification is adapted from the Ada Reference Manual for use with --
 -- GNAT.  In accordance with the copyright of that document, you can freely --
 -- copy and modify this specification,  provided that if you redistribute a --
@@ -22,12 +21,8 @@ generic
    with package HT_Types is
      new Generic_Hash_Table_Types (<>);
 
-   type Hash_Table_Type is new HT_Types.Hash_Table_Type with private;
-
    use HT_Types;
 
-   Null_Node : in Node_Access;
-
    with function Hash_Node (Node : Node_Access) return Hash_Type;
 
    with function Next (Node : Node_Access) return Node_Access;
@@ -72,7 +67,7 @@ package Ada.Containers.Hash_Tables.Generic_Operations is
 
    function Capacity (HT : Hash_Table_Type) return Count_Type;
 
-   procedure Ensure_Capacity
+   procedure Reserve_Capacity
      (HT : in out Hash_Table_Type;
       N  : Count_Type);
 
@@ -108,4 +103,3 @@ package Ada.Containers.Hash_Tables.Generic_Operations is
       HT     : out Hash_Table_Type);
 
 end Ada.Containers.Hash_Tables.Generic_Operations;
-
index 252b64f2a34d64353655d24cfab61e33ca80b821..6fb6d9e0f820b337c869c802f1928c4df610feef 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---              ADA.CONTAINERS.INDEFINITE_DOUBLY_LINKED_LISTS               --
+--                      A D A . C O N T A I N E R S .                       --
+--        I N D E F I N I T E _ D O U B L Y _ L I N K E D _ L I S T S       --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -48,10 +49,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    -- Local Subprograms --
    -----------------------
 
-   procedure Delete_Node
-     (Container : in out List;
-      Node      : in out Node_Access);
-
    procedure Insert_Internal
      (Container : in out List;
       Before    : Node_Access;
@@ -77,15 +74,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       L := Left.First;
       R := Right.First;
       for J in 1 .. Left.Length loop
-         if L.Element = null then
-            if R.Element /= null then
-               return False;
-            end if;
-
-         elsif R.Element = null then
-            return False;
-
-         elsif L.Element.all /= R.Element.all then
+         if L.Element.all /= R.Element.all then
             return False;
          end if;
 
@@ -108,6 +97,8 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       if Src = null then
          pragma Assert (Container.Last = null);
          pragma Assert (Container.Length = 0);
+         pragma Assert (Container.Busy = 0);
+         pragma Assert (Container.Lock = 0);
          return;
       end if;
 
@@ -118,41 +109,40 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       Container.First := null;
       Container.Last := null;
       Container.Length := 0;
+      Container.Busy := 0;
+      Container.Lock := 0;
 
-      Dst := new Node_Type'(null, null, null);
+      declare
+         Element : Element_Access := new Element_Type'(Src.Element.all);
+      begin
+         Dst := new Node_Type'(Element, null, null);
+      exception
+         when others =>
+            Free (Element);
+            raise;
+      end;
 
-      if Src.Element /= null then
+      Container.First := Dst;
+      Container.Last := Dst;
+      Container.Length := 1;
+
+      Src := Src.Next;
+      while Src /= null loop
+         declare
+            Element : Element_Access := new Element_Type'(Src.Element.all);
          begin
-            Dst.Element := new Element_Type'(Src.Element.all);
+            Dst := new Node_Type'(Element, null, Prev => Container.Last);
          exception
             when others =>
-               Free (Dst);
+               Free (Element);
                raise;
          end;
-      end if;
-
-      Container.First := Dst;
-
-      Container.Last := Dst;
-      loop
-         Container.Length := Container.Length + 1;
-         Src := Src.Next;
-         exit when Src = null;
-
-         Dst := new Node_Type'(null, Prev => Container.Last, Next => null);
-
-         if Src.Element /= null then
-            begin
-               Dst.Element := new Element_Type'(Src.Element.all);
-            exception
-               when others =>
-                  Free (Dst);
-                  raise;
-            end;
-         end if;
 
          Container.Last.Next := Dst;
          Container.Last := Dst;
+         Container.Length := Container.Length + 1;
+
+         Src := Src.Next;
       end loop;
    end Adjust;
 
@@ -174,8 +164,63 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    -----------
 
    procedure Clear (Container : in out List) is
+      X : Node_Access;
+
    begin
-      Delete_Last (Container, Count => Container.Length);
+      if Container.Length = 0 then
+         pragma Assert (Container.First = null);
+         pragma Assert (Container.Last = null);
+         pragma Assert (Container.Busy = 0);
+         pragma Assert (Container.Lock = 0);
+         return;
+      end if;
+
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      while Container.Length > 1 loop
+         X := Container.First;
+         pragma Assert (X.Next.Prev = Container.First);
+
+         Container.First := X.Next;
+         Container.First.Prev := null;
+         Container.Length := Container.Length - 1;
+
+         X.Next := null;  --  prevent mischief
+
+         begin
+            Free (X.Element);
+         exception
+            when others =>
+               X.Element := null;
+               Free (X);
+               raise;
+         end;
+
+         Free (X);
+      end loop;
+
+      X := Container.First;
+      pragma Assert (X = Container.Last);
+
+      Container.First := null;
+      Container.Last := null;
+      Container.Length := 0;
+
+      begin
+         Free (X.Element);
+      exception
+         when others =>
+            X.Element := null;
+            Free (X);
+            raise;
+      end;
+
+      Free (X);
    end Clear;
 
    --------------
@@ -198,22 +243,88 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       Position  : in out Cursor;
       Count     : Count_Type := 1)
    is
+      X : Node_Access;
+
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
       if Position.Container /= List_Access'(Container'Unchecked_Access) then
          raise Program_Error;
       end if;
 
+      pragma Assert (Container.Length > 0);
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Container.Last);
+
+      if Position.Node = Container.First then
+         Delete_First (Container, Count);
+         Position := First (Container);
+         return;
+      end if;
+
+      if Count = 0 then
+         return;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       for Index in 1 .. Count loop
-         Delete_Node (Container, Position.Node);
+         X := Position.Node;
+         Container.Length := Container.Length - 1;
+
+         if X = Container.Last then
+            Position := No_Element;
 
-         if Position.Node = null then
-            Position.Container := null;
+            Container.Last := X.Prev;
+            Container.Last.Next := null;
+
+            X.Prev := null;  --  prevent mischief
+
+            begin
+               Free (X.Element);
+            exception
+               when others =>
+                  X.Element := null;
+                  Free (X);
+                  raise;
+            end;
+
+            Free (X);
             return;
          end if;
+
+         Position.Node := X.Next;
+
+         X.Next.Prev := X.Prev;
+         X.Prev.Next := X.Next;
+
+         X.Prev := null;
+         X.Next := null;
+
+         begin
+            Free (X.Element);
+         exception
+            when others =>
+               X.Element := null;
+               Free (X);
+               raise;
+         end;
+
+         Free (X);
       end loop;
    end Delete;
 
@@ -225,10 +336,43 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Container : in out List;
       Count     : Count_Type := 1)
    is
-      Node : Node_Access := Container.First;
+      X : Node_Access;
+
    begin
-      for J in 1 .. Count_Type'Min (Count, Container.Length) loop
-         Delete_Node (Container, Node);
+      if Count >= Container.Length then
+         Clear (Container);
+         return;
+      end if;
+
+      if Count = 0 then
+         return;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      for I in 1 .. Count loop
+         X := Container.First;
+         pragma Assert (X.Next.Prev = Container.First);
+
+         Container.First := X.Next;
+         Container.First.Prev := null;
+
+         Container.Length := Container.Length - 1;
+
+         X.Next := null;  --  prevent mischief
+
+         begin
+            Free (X.Element);
+         exception
+            when others =>
+               X.Element := null;
+               Free (X);
+               raise;
+         end;
+
+         Free (X);
       end loop;
    end Delete_First;
 
@@ -240,57 +384,45 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Container : in out List;
       Count     : Count_Type := 1)
    is
-      Node : Node_Access;
-   begin
-      for J in 1 .. Count_Type'Min (Count, Container.Length) loop
-         Node := Container.Last;
-         Delete_Node (Container, Node);
-      end loop;
-   end Delete_Last;
-
-   -----------------
-   -- Delete_Node --
-   -----------------
-
-   procedure Delete_Node
-     (Container : in out List;
-      Node      : in out Node_Access)
-   is
-      X : Node_Access := Node;
+      X : Node_Access;
 
    begin
-      Node := X.Next;
-      Container.Length := Container.Length - 1;
+      if Count >= Container.Length then
+         Clear (Container);
+         return;
+      end if;
 
-      if X = Container.First then
-         Container.First := X.Next;
+      if Count = 0 then
+         return;
+      end if;
 
-         if X = Container.Last then
-            pragma Assert (Container.First = null);
-            pragma Assert (Container.Length = 0);
-            Container.Last := null;
-         else
-            pragma Assert (Container.Length > 0);
-            Container.First.Prev := null;
-         end if;
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
 
-      elsif X = Container.Last then
-         pragma Assert (Container.Length > 0);
+      for I in 1 .. Count loop
+         X := Container.Last;
+         pragma Assert (X.Prev.Next = Container.Last);
 
          Container.Last := X.Prev;
          Container.Last.Next := null;
 
-      else
-         pragma Assert (Container.Length > 0);
+         Container.Length := Container.Length - 1;
 
-         X.Next.Prev := X.Prev;
-         X.Prev.Next := X.Next;
+         X.Prev := null;  --  prevent mischief
 
-      end if;
+         begin
+            Free (X.Element);
+         exception
+            when others =>
+               X.Element := null;
+               Free (X);
+               raise;
+         end;
 
-      Free (X.Element);
-      Free (X);
-   end Delete_Node;
+         Free (X);
+      end loop;
+   end Delete_Last;
 
    -------------
    -- Element --
@@ -298,6 +430,22 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
 
    function Element (Position : Cursor) return Element_Type is
    begin
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       return Position.Node.Element.all;
    end Element;
 
@@ -315,14 +463,29 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    begin
       if Node = null then
          Node := Container.First;
-      elsif Position.Container /= List_Access'(Container'Unchecked_Access) then
-         raise Program_Error;
+
+      else
+         if Position.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Position.Node.Element /= null);
+         pragma Assert (Position.Node.Prev = null
+                          or else Position.Node.Prev.Next = Position.Node);
+         pragma Assert (Position.Node.Next = null
+                          or else Position.Node.Next.Prev = Position.Node);
+         pragma Assert (Position.Node.Prev /= null
+                          or else Position.Node = Container.First);
+         pragma Assert (Position.Node.Next /= null
+                          or else Position.Node = Container.Last);
       end if;
 
       while Node /= null loop
-         if Node.Element /= null
-           and then Node.Element.all = Item
-         then
+         if Node.Element.all = Item then
             return Cursor'(Container'Unchecked_Access, Node);
          end if;
 
@@ -354,135 +517,168 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       return Container.First.Element.all;
    end First_Element;
 
-   -------------------
-   -- Generic_Merge --
-   -------------------
+   ---------------------
+   -- Generic_Sorting --
+   ---------------------
 
-   procedure Generic_Merge
-     (Target : in out List;
-      Source : in out List)
-   is
-      LI : Cursor;
-      RI : Cursor;
+   package body Generic_Sorting is
 
-   begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
+      ---------------
+      -- Is_Sorted --
+      ---------------
+
+      function Is_Sorted (Container : List) return Boolean is
+         Node : Node_Access := Container.First;
+
+      begin
+         for I in 2 .. Container.Length loop
+            if Node.Next.Element.all < Node.Element.all then
+               return False;
+            end if;
+
+            Node := Node.Next;
+         end loop;
+
+         return True;
+      end Is_Sorted;
+
+      -----------
+      -- Merge --
+      -----------
 
-      LI := First (Target);
-      RI := First (Source);
-      while RI.Node /= null loop
-         if LI.Node = null then
-            Splice (Target, No_Element, Source);
+      procedure Merge
+        (Target : in out List;
+         Source : in out List)
+      is
+         LI : Cursor;
+         RI : Cursor;
+
+      begin
+         if Target'Address = Source'Address then
             return;
          end if;
 
-         if LI.Node.Element = null then
-            LI.Node := LI.Node.Next;
-
-         elsif RI.Node.Element = null
-           or else RI.Node.Element.all < LI.Node.Element.all
+         if Target.Busy > 0
+           or else Source.Busy > 0
          then
-            declare
-               RJ : constant Cursor := RI;
-            begin
-               RI.Node := RI.Node.Next;
-               Splice (Target, LI, Source, RJ);
-            end;
-
-         else
-            LI.Node := LI.Node.Next;
+            raise Program_Error;
          end if;
-      end loop;
-   end Generic_Merge;
 
-   ------------------
-   -- Generic_Sort --
-   ------------------
+         LI := First (Target);
+         RI := First (Source);
+         while RI.Node /= null loop
+            if LI.Node = null then
+               Splice (Target, No_Element, Source);
+               return;
+            end if;
 
-   procedure Generic_Sort (Container : in out List) is
-      procedure Partition (Pivot : Node_Access; Back  : Node_Access);
+            if RI.Node.Element.all < LI.Node.Element.all then
+               declare
+                  RJ : Cursor := RI;
+               begin
+                  RI.Node := RI.Node.Next;
+                  Splice (Target, LI, Source, RJ);
+               end;
 
-      procedure Sort (Front, Back : Node_Access);
+            else
+               LI.Node := LI.Node.Next;
+            end if;
+         end loop;
+      end Merge;
 
-      ---------------
-      -- Partition --
-      ---------------
+      ----------
+      -- Sort --
+      ----------
 
-      procedure Partition (Pivot : Node_Access; Back  : Node_Access) is
-         Node : Node_Access := Pivot.Next;
+      procedure Sort (Container : in out List) is
+         procedure Partition (Pivot : Node_Access; Back  : Node_Access);
 
-      begin
-         while Node /= Back loop
-            if Pivot.Element = null then
-               Node := Node.Next;
+         procedure Sort (Front, Back : Node_Access);
 
-            elsif Node.Element = null
-              or else Node.Element.all < Pivot.Element.all
-            then
-               declare
-                  Prev : constant Node_Access := Node.Prev;
-                  Next : constant Node_Access := Node.Next;
-               begin
-                  Prev.Next := Next;
+         ---------------
+         -- Partition --
+         ---------------
 
-                  if Next = null then
-                     Container.Last := Prev;
-                  else
-                     Next.Prev := Prev;
-                  end if;
+         procedure Partition (Pivot : Node_Access; Back : Node_Access) is
+            Node : Node_Access := Pivot.Next;
 
-                  Node.Next := Pivot;
-                  Node.Prev := Pivot.Prev;
+         begin
+            while Node /= Back loop
+               if Node.Element.all < Pivot.Element.all then
+                  declare
+                     Prev : constant Node_Access := Node.Prev;
+                     Next : constant Node_Access := Node.Next;
+                  begin
+                     Prev.Next := Next;
+
+                     if Next = null then
+                        Container.Last := Prev;
+                     else
+                        Next.Prev := Prev;
+                     end if;
+
+                     Node.Next := Pivot;
+                     Node.Prev := Pivot.Prev;
+
+                     Pivot.Prev := Node;
+
+                     if Node.Prev = null then
+                        Container.First := Node;
+                     else
+                        Node.Prev.Next := Node;
+                     end if;
+
+                     Node := Next;
+                  end;
 
-                  Pivot.Prev := Node;
+               else
+                  Node := Node.Next;
+               end if;
+            end loop;
+         end Partition;
 
-                  if Node.Prev = null then
-                     Container.First := Node;
-                  else
-                     Node.Prev.Next := Node;
-                  end if;
+         ----------
+         -- Sort --
+         ----------
 
-                  Node := Next;
-               end;
+         procedure Sort (Front, Back : Node_Access) is
+            Pivot : Node_Access;
 
+         begin
+            if Front = null then
+               Pivot := Container.First;
             else
-               Node := Node.Next;
+               Pivot := Front.Next;
             end if;
-         end loop;
-      end Partition;
 
-      ----------
-      -- Sort --
-      ----------
+            if Pivot /= Back then
+               Partition (Pivot, Back);
+               Sort (Front, Pivot);
+               Sort (Pivot, Back);
+            end if;
+         end Sort;
 
-      procedure Sort (Front, Back : Node_Access) is
-         Pivot : Node_Access;
+      --  Start of processing for Sort
 
       begin
-         if Front = null then
-            Pivot := Container.First;
-         else
-            Pivot := Front.Next;
+         if Container.Length <= 1 then
+            return;
          end if;
 
-         if Pivot /= Back then
-            Partition (Pivot, Back);
-            Sort (Front, Pivot);
-            Sort (Pivot, Back);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         if Container.Busy > 0 then
+            raise Program_Error;
          end if;
-      end Sort;
 
-   --  Start of processing for Generic_Sort
+         Sort (Front => null, Back => null);
 
-   begin
-      Sort (Front => null, Back => null);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+      end Sort;
 
-      pragma Assert (Container.Length = 0
-                       or else (Container.First.Prev = null
-                                  and Container.Last.Next = null));
-   end Generic_Sort;
+   end Generic_Sorting;
 
    -----------------
    -- Has_Element --
@@ -490,7 +686,27 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
 
    function Has_Element (Position : Cursor) return Boolean is
    begin
-      return Position.Container /= null and then Position.Node /= null;
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return False;
+      end if;
+
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      return True;
    end Has_Element;
 
    ------------
@@ -507,10 +723,24 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       New_Node : Node_Access;
 
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Before.Node.Element /= null);
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Container.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Container.Last);
       end if;
 
       if Count = 0 then
@@ -518,6 +748,14 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          return;
       end if;
 
+      if Container.Length > Count_Type'Last - Count then
+         raise Constraint_Error;
+      end if;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       declare
          Element : Element_Access := new Element_Type'(New_Item);
       begin
@@ -529,7 +767,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       end;
 
       Insert_Internal (Container, Before.Node, New_Node);
-      Position := Cursor'(Before.Container, New_Node);
+      Position := Cursor'(Container'Unchecked_Access, New_Node);
 
       for J in Count_Type'(2) .. Count loop
 
@@ -623,12 +861,26 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Container : List;
       Process   : not null access procedure (Position : in Cursor))
    is
+      C : List renames Container'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+
       Node : Node_Access := Container.First;
+
    begin
-      while Node /= null loop
-         Process (Cursor'(Container'Unchecked_Access, Node));
-         Node := Node.Next;
-      end loop;
+      B := B + 1;
+
+      begin
+         while Node /= null loop
+            Process (Cursor'(Container'Unchecked_Access, Node));
+            Node := Node.Next;
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ----------
@@ -641,10 +893,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          return;
       end if;
 
-      if Target.Length > 0 then
-         raise Constraint_Error;
+      if Source.Busy > 0 then
+         raise Program_Error;
       end if;
 
+      Clear (Target);
+
       Target.First := Source.First;
       Source.First := null;
 
@@ -693,9 +947,25 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    procedure Next (Position : in out Cursor) is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       Position.Node := Position.Node.Next;
 
       if Position.Node = null then
@@ -706,9 +976,25 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    function Next (Position : Cursor) return Cursor is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return No_Element;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       declare
          Next_Node : constant Node_Access := Position.Node.Next;
       begin
@@ -740,9 +1026,25 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    procedure Previous (Position : in out Cursor) is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       Position.Node := Position.Node.Prev;
 
       if Position.Node = null then
@@ -753,9 +1055,25 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    function Previous (Position : Cursor) return Cursor is
    begin
       if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return No_Element;
       end if;
 
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       declare
          Prev_Node : constant Node_Access := Position.Node.Prev;
       begin
@@ -775,8 +1093,43 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Position : Cursor;
       Process  : not null access procedure (Element : in Element_Type))
    is
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      E : Element_Type renames Position.Node.Element.all;
+
+      C : List renames Position.Container.all'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+      L : Natural renames C.Lock;
+
    begin
-      Process (Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -787,11 +1140,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Stream : access Root_Stream_Type'Class;
       Item   : out List)
    is
-      N : Count_Type'Base;
-      X : Node_Access;
+      N   : Count_Type'Base;
+      Dst : Node_Access;
 
    begin
-      Clear (Item);  --  ???
+      Clear (Item);
 
       Count_Type'Base'Read (Stream, N);
 
@@ -799,36 +1152,36 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          return;
       end if;
 
-      X := new Node_Type;
-
+      declare
+         Element : Element_Access :=
+                     new Element_Type'(Element_Type'Input (Stream));
       begin
-         X.Element := new Element_Type'(Element_Type'Input (Stream));
+         Dst := new Node_Type'(Element, null, null);
       exception
          when others =>
-            Free (X);
+            Free (Element);
             raise;
       end;
 
-      Item.First := X;
-
-      Item.Last := X;
-      loop
-         Item.Length := Item.Length + 1;
-         exit when Item.Length = N;
-
-         X := new Node_Type;
+      Item.First := Dst;
+      Item.Last := Dst;
+      Item.Length := 1;
 
+      while Item.Length < N loop
+         declare
+            Element : Element_Access :=
+                        new Element_Type'(Element_Type'Input (Stream));
          begin
-            X.Element := new Element_Type'(Element_Type'Input (Stream));
+            Dst := new Node_Type'(Element, Next => null, Prev => Item.Last);
          exception
             when others =>
-               Free (X);
+               Free (Element);
                raise;
          end;
 
-         X.Prev := Item.Last;
-         Item.Last.Next := X;
-         Item.Last := X;
+         Item.Last.Next := Dst;
+         Item.Last := Dst;
+         Item.Length := Item.Length + 1;
       end loop;
    end Read;
 
@@ -840,8 +1193,29 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Position : Cursor;
       By       : Element_Type)
    is
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
       X : Element_Access := Position.Node.Element;
+
    begin
+      if Position.Container.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       Position.Node.Element := new Element_Type'(By);
       Free (X);
    end Replace_Element;
@@ -860,14 +1234,29 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    begin
       if Node = null then
          Node := Container.Last;
-      elsif Position.Container /= List_Access'(Container'Unchecked_Access) then
-         raise Program_Error;
+
+      else
+         if Position.Container /= List_Access'(Container'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Container.Length > 0);
+         pragma Assert (Container.First.Prev = null);
+         pragma Assert (Container.Last.Next = null);
+
+         pragma Assert (Position.Node.Element /= null);
+         pragma Assert (Position.Node.Prev = null
+                          or else Position.Node.Prev.Next = Position.Node);
+         pragma Assert (Position.Node.Next = null
+                          or else Position.Node.Next.Prev = Position.Node);
+         pragma Assert (Position.Node.Prev /= null
+                          or else Position.Node = Container.First);
+         pragma Assert (Position.Node.Next /= null
+                          or else Position.Node = Container.Last);
       end if;
 
       while Node /= null loop
-         if Node.Element /= null
-           and then Node.Element.all = Item
-         then
+         if Node.Element.all = Item then
             return Cursor'(Container'Unchecked_Access, Node);
          end if;
 
@@ -885,13 +1274,26 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Container : List;
       Process   : not null access procedure (Position : in Cursor))
    is
+      C : List renames Container'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+
       Node : Node_Access := Container.Last;
 
    begin
-      while Node /= null loop
-         Process (Cursor'(Container'Unchecked_Access, Node));
-         Node := Node.Prev;
-      end loop;
+      B := B + 1;
+
+      begin
+         while Node /= null loop
+            Process (Cursor'(Container'Unchecked_Access, Node));
+            Node := Node.Prev;
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    ------------------
@@ -949,6 +1351,13 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          return;
       end if;
 
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       Container.First := J;
       Container.Last := I;
       loop
@@ -983,10 +1392,24 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       Source : in out List)
    is
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Target'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Target'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Target.Length >= 1);
+         pragma Assert (Target.First.Prev = null);
+         pragma Assert (Target.Last.Next = null);
+
+         pragma Assert (Before.Node.Element /= null);
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Target.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Target.Last);
       end if;
 
       if Target'Address = Source'Address
@@ -995,8 +1418,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          return;
       end if;
 
+      pragma Assert (Source.First.Prev = null);
+      pragma Assert (Source.Last.Next = null);
+
+      if Target.Length > Count_Type'Last - Source.Length then
+         raise Constraint_Error;
+      end if;
+
+      if Target.Busy > 0
+        or else Source.Busy > 0
+      then
+         raise Program_Error;
+      end if;
+
       if Target.Length = 0 then
          pragma Assert (Before = No_Element);
+         pragma Assert (Target.First = null);
+         pragma Assert (Target.Last = null);
 
          Target.First := Source.First;
          Target.Last := Source.Last;
@@ -1018,6 +1456,7 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          Target.First := Source.First;
 
       else
+         pragma Assert (Target.Length >= 2);
          Before.Node.Prev.Next := Source.First;
          Source.First.Prev := Before.Node.Prev;
 
@@ -1037,141 +1476,207 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       Before   : Cursor;
       Position : Cursor)
    is
-      X : Node_Access := Position.Node;
-
    begin
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Target'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Target'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Target.Length >= 1);
+         pragma Assert (Target.First.Prev = null);
+         pragma Assert (Target.Last.Next = null);
+
+         pragma Assert (Before.Node.Element /= null);
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Target.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Target.Last);
       end if;
 
-      if Position.Container /= null
-        and then Position.Container /= List_Access'(Target'Unchecked_Access)
-      then
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
+
+      if Position.Container /= List_Access'(Target'Unchecked_Access) then
          raise Program_Error;
       end if;
 
-      if X = null
-        or else X = Before.Node
-        or else X.Next = Before.Node
+      pragma Assert (Target.Length >= 1);
+      pragma Assert (Target.First.Prev = null);
+      pragma Assert (Target.Last.Next = null);
+
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Target.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Target.Last);
+
+      if Position.Node = Before.Node
+        or else Position.Node.Next = Before.Node
       then
          return;
       end if;
 
-      pragma Assert (Target.Length > 0);
+      pragma Assert (Target.Length >= 2);
+
+      if Target.Busy > 0 then
+         raise Program_Error;
+      end if;
 
       if Before.Node = null then
-         pragma Assert (X /= Target.Last);
+         pragma Assert (Position.Node /= Target.Last);
 
-         if X = Target.First then
-            Target.First := X.Next;
+         if Position.Node = Target.First then
+            Target.First := Position.Node.Next;
             Target.First.Prev := null;
          else
-            X.Prev.Next := X.Next;
-            X.Next.Prev := X.Prev;
+            Position.Node.Prev.Next := Position.Node.Next;
+            Position.Node.Next.Prev := Position.Node.Prev;
          end if;
 
-         Target.Last.Next := X;
-         X.Prev := Target.Last;
+         Target.Last.Next := Position.Node;
+         Position.Node.Prev := Target.Last;
 
-         Target.Last := X;
+         Target.Last := Position.Node;
          Target.Last.Next := null;
 
          return;
       end if;
 
       if Before.Node = Target.First then
-         pragma Assert (X /= Target.First);
+         pragma Assert (Position.Node /= Target.First);
 
-         if X = Target.Last then
-            Target.Last := X.Prev;
+         if Position.Node = Target.Last then
+            Target.Last := Position.Node.Prev;
             Target.Last.Next := null;
          else
-            X.Prev.Next := X.Next;
-            X.Next.Prev := X.Prev;
+            Position.Node.Prev.Next := Position.Node.Next;
+            Position.Node.Next.Prev := Position.Node.Prev;
          end if;
 
-         Target.First.Prev := X;
-         X.Next := Target.First;
+         Target.First.Prev := Position.Node;
+         Position.Node.Next := Target.First;
 
-         Target.First := X;
+         Target.First := Position.Node;
          Target.First.Prev := null;
 
          return;
       end if;
 
-      if X = Target.First then
-         Target.First := X.Next;
+      if Position.Node = Target.First then
+         Target.First := Position.Node.Next;
          Target.First.Prev := null;
 
-      elsif X = Target.Last then
-         Target.Last := X.Prev;
+      elsif Position.Node = Target.Last then
+         Target.Last := Position.Node.Prev;
          Target.Last.Next := null;
 
       else
-         X.Prev.Next := X.Next;
-         X.Next.Prev := X.Prev;
+         Position.Node.Prev.Next := Position.Node.Next;
+         Position.Node.Next.Prev := Position.Node.Prev;
       end if;
 
-      Before.Node.Prev.Next := X;
-      X.Prev := Before.Node.Prev;
+      Before.Node.Prev.Next := Position.Node;
+      Position.Node.Prev := Before.Node.Prev;
+
+      Before.Node.Prev := Position.Node;
+      Position.Node.Next := Before.Node;
 
-      Before.Node.Prev := X;
-      X.Next := Before.Node;
+      pragma Assert (Target.First.Prev = null);
+      pragma Assert (Target.Last.Next = null);
    end Splice;
 
    procedure Splice
      (Target   : in out List;
       Before   : Cursor;
       Source   : in out List;
-      Position : Cursor)
+      Position : in out Cursor)
    is
-      X : Node_Access := Position.Node;
-
    begin
       if Target'Address = Source'Address then
          Splice (Target, Before, Position);
          return;
       end if;
 
-      if Before.Container /= null
-        and then Before.Container /= List_Access'(Target'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Before.Node /= null then
+         if Before.Container /= List_Access'(Target'Unchecked_Access) then
+            raise Program_Error;
+         end if;
+
+         pragma Assert (Target.Length >= 1);
+         pragma Assert (Target.First.Prev = null);
+         pragma Assert (Target.Last.Next = null);
+
+         pragma Assert (Before.Node.Element /= null);
+         pragma Assert (Before.Node.Prev = null
+                          or else Before.Node.Prev.Next = Before.Node);
+         pragma Assert (Before.Node.Next = null
+                          or else Before.Node.Next.Prev = Before.Node);
+         pragma Assert (Before.Node.Prev /= null
+                          or else Before.Node = Target.First);
+         pragma Assert (Before.Node.Next /= null
+                          or else Before.Node = Target.Last);
       end if;
 
-      if Position.Container /= null
-        and then Position.Container /= List_Access'(Source'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if X = null then
-         return;
+      if Position.Container /= List_Access'(Source'Unchecked_Access) then
+         raise Program_Error;
       end if;
 
-      pragma Assert (Source.Length > 0);
+      pragma Assert (Source.Length >= 1);
       pragma Assert (Source.First.Prev = null);
       pragma Assert (Source.Last.Next = null);
 
-      if X = Source.First then
-         Source.First := X.Next;
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Source.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Source.Last);
+
+      if Target.Length = Count_Type'Last then
+         raise Constraint_Error;
+      end if;
+
+      if Target.Busy > 0
+        or else Source.Busy > 0
+      then
+         raise Program_Error;
+      end if;
+
+      if Position.Node = Source.First then
+         Source.First := Position.Node.Next;
          Source.First.Prev := null;
 
-         if X = Source.Last then
+         if Position.Node = Source.Last then
             pragma Assert (Source.First = null);
             pragma Assert (Source.Length = 1);
             Source.Last := null;
          end if;
 
-      elsif X = Source.Last then
-         Source.Last := X.Prev;
+      elsif Position.Node = Source.Last then
+         pragma Assert (Source.Length >= 2);
+         Source.Last := Position.Node.Prev;
          Source.Last.Next := null;
 
       else
-         X.Prev.Next := X.Next;
-         X.Next.Prev := X.Prev;
+         pragma Assert (Source.Length >= 3);
+         Position.Node.Prev.Next := Position.Node.Next;
+         Position.Node.Next.Prev := Position.Node.Prev;
       end if;
 
       if Target.Length = 0 then
@@ -1179,33 +1684,41 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
          pragma Assert (Target.First = null);
          pragma Assert (Target.Last = null);
 
-         Target.First := X;
-         Target.Last := X;
+         Target.First := Position.Node;
+         Target.Last := Position.Node;
+
+         Target.First.Prev := null;
+         Target.Last.Next := null;
 
       elsif Before.Node = null then
-         Target.Last.Next := X;
-         X.Next := Target.Last;
+         pragma Assert (Target.Last.Next = null);
+         Target.Last.Next := Position.Node;
+         Position.Node.Prev := Target.Last;
 
-         Target.Last := X;
+         Target.Last := Position.Node;
          Target.Last.Next := null;
 
       elsif Before.Node = Target.First then
-         Target.First.Prev := X;
-         X.Next := Target.First;
+         pragma Assert (Target.First.Prev = null);
+         Target.First.Prev := Position.Node;
+         Position.Node.Next := Target.First;
 
-         Target.First := X;
+         Target.First := Position.Node;
          Target.First.Prev := null;
 
       else
-         Before.Node.Prev.Next := X;
-         X.Prev := Before.Node.Prev;
+         pragma Assert (Target.Length >= 2);
+         Before.Node.Prev.Next := Position.Node;
+         Position.Node.Prev := Before.Node.Prev;
 
-         Before.Node.Prev := X;
-         X.Next := Before.Node;
+         Before.Node.Prev := Position.Node;
+         Position.Node.Next := Before.Node;
       end if;
 
       Target.Length := Target.Length + 1;
       Source.Length := Source.Length - 1;
+
+      Position.Container := Target'Unchecked_Access;
    end Splice;
 
    ----------
@@ -1213,15 +1726,62 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    ----------
 
    procedure Swap (I, J : Cursor) is
+   begin
+      if I.Container = null
+        or else J.Container = null
+      then
+         raise Constraint_Error;
+      end if;
 
-      --  Is this op legal when I and J designate elements in different
-      --  containers, or should it raise an exception (e.g. Program_Error).
+      if I.Container /= J.Container then
+         raise Program_Error;
+      end if;
 
-      EI : constant Element_Access := I.Node.Element;
+      declare
+         C : List renames I.Container.all;
+      begin
+         pragma Assert (C.Length > 0);
+         pragma Assert (C.First.Prev = null);
+         pragma Assert (C.Last.Next = null);
+
+         pragma Assert (I.Node /= null);
+         pragma Assert (I.Node.Element /= null);
+         pragma Assert (I.Node.Prev = null
+                          or else I.Node.Prev.Next = I.Node);
+         pragma Assert (I.Node.Next = null
+                          or else I.Node.Next.Prev = I.Node);
+         pragma Assert (I.Node.Prev /= null
+                          or else I.Node = C.First);
+         pragma Assert (I.Node.Next /= null
+                          or else I.Node = C.Last);
+
+         if I.Node = J.Node then
+            return;
+         end if;
 
-   begin
-      I.Node.Element := J.Node.Element;
-      J.Node.Element := EI;
+         pragma Assert (C.Length > 1);
+         pragma Assert (J.Node /= null);
+         pragma Assert (J.Node.Element /= null);
+         pragma Assert (J.Node.Prev = null
+                          or else J.Node.Prev.Next = J.Node);
+         pragma Assert (J.Node.Next = null
+                          or else J.Node.Next.Prev = J.Node);
+         pragma Assert (J.Node.Prev /= null
+                          or else J.Node = C.First);
+         pragma Assert (J.Node.Next /= null
+                          or else J.Node = C.Last);
+
+         if C.Lock > 0 then
+            raise Program_Error;
+         end if;
+
+         declare
+            EI_Copy : constant Element_Access := I.Node.Element;
+         begin
+            I.Node.Element := J.Node.Element;
+            J.Node.Element := EI_Copy;
+         end;
+      end;
    end Swap;
 
    ----------------
@@ -1233,8 +1793,8 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       I, J      : Cursor)
    is
    begin
-      if I = No_Element
-        or else J = No_Element
+      if I.Container = null
+        or else J.Container = null
       then
          raise Constraint_Error;
       end if;
@@ -1248,12 +1808,39 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
       end if;
 
       pragma Assert (Container.Length >= 1);
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
+
+      pragma Assert (I.Node /= null);
+      pragma Assert (I.Node.Element /= null);
+      pragma Assert (I.Node.Prev = null
+                       or else I.Node.Prev.Next = I.Node);
+      pragma Assert (I.Node.Next = null
+                       or else I.Node.Next.Prev = I.Node);
+      pragma Assert (I.Node.Prev /= null
+                       or else I.Node = Container.First);
+      pragma Assert (I.Node.Next /= null
+                       or else I.Node = Container.Last);
 
       if I.Node = J.Node then
          return;
       end if;
 
       pragma Assert (Container.Length >= 2);
+      pragma Assert (J.Node /= null);
+      pragma Assert (J.Node.Element /= null);
+      pragma Assert (J.Node.Prev = null
+                       or else J.Node.Prev.Next = J.Node);
+      pragma Assert (J.Node.Next = null
+                       or else J.Node.Next.Prev = J.Node);
+      pragma Assert (J.Node.Prev /= null
+                       or else J.Node = Container.First);
+      pragma Assert (J.Node.Next /= null
+                       or else J.Node = Container.Last);
+
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
 
       declare
          I_Next : constant Cursor := Next (I);
@@ -1278,6 +1865,9 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
             end;
          end if;
       end;
+
+      pragma Assert (Container.First.Prev = null);
+      pragma Assert (Container.Last.Next = null);
    end Swap_Links;
 
    --------------------
@@ -1288,8 +1878,43 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Position : Cursor;
       Process  : not null access procedure (Element : in out Element_Type))
    is
+      pragma Assert (Position.Container /= null);
+      pragma Assert (Position.Container.Length > 0);
+      pragma Assert (Position.Container.First.Prev = null);
+      pragma Assert (Position.Container.Last.Next = null);
+
+      pragma Assert (Position.Node /= null);
+      pragma Assert (Position.Node.Element /= null);
+      pragma Assert (Position.Node.Prev = null
+                       or else Position.Node.Prev.Next = Position.Node);
+      pragma Assert (Position.Node.Next = null
+                       or else Position.Node.Next.Prev = Position.Node);
+      pragma Assert (Position.Node.Prev /= null
+                       or else Position.Node = Position.Container.First);
+      pragma Assert (Position.Node.Next /= null
+                       or else Position.Node = Position.Container.Last);
+
+      E : Element_Type renames Position.Node.Element.all;
+
+      C : List renames Position.Container.all'Unrestricted_Access.all;
+      B : Natural renames C.Busy;
+      L : Natural renames C.Lock;
+
    begin
-      Process (Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
    -----------
@@ -1310,5 +1935,3 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
    end Write;
 
 end Ada.Containers.Indefinite_Doubly_Linked_Lists;
-
-
index 2f4ebcb69f0f2d58ce77c25f0c81fa5c151992cb..07341a835564d920bdbbc4345b17fae012f6065e 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---              ADA.CONTAINERS.INDEFINITE_DOUBLY_LINKED_LISTS               --
+--                      A D A . C O N T A I N E R S .                       --
+--        I N D E F I N I T E _ D O U B L Y _ L I N K E D _ L I S T S       --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -118,16 +119,16 @@ package Ada.Containers.Indefinite_Doubly_Linked_Lists is
       Count     : Count_Type := 1);
 
    generic
-      with function "<" (Left, Right : Element_Type)
-         return Boolean is <>;
-   procedure Generic_Sort (Container : in out List);
+      with function "<" (Left, Right : Element_Type) return Boolean is <>;
+   package Generic_Sorting is
 
-   generic
-      with function "<" (Left, Right : Element_Type)
-         return Boolean is <>;
-   procedure Generic_Merge
-     (Target : in out List;
-      Source : in out List);
+      function Is_Sorted (Container : List) return Boolean;
+
+      procedure Sort (Container : in out List);
+
+      procedure Merge (Target, Source : in out List);
+
+   end Generic_Sorting;
 
    procedure Reverse_List (Container : in out List);
 
@@ -149,7 +150,7 @@ package Ada.Containers.Indefinite_Doubly_Linked_Lists is
      (Target   : in out List;
       Before   : Cursor;
       Source   : in out List;
-      Position : Cursor);
+      Position : in out Cursor);
 
    function First (Container : List) return Cursor;
 
@@ -198,14 +199,12 @@ private
    type Element_Access is access Element_Type;
 
    type Node_Type is
-      record
+      limited record
          Element : Element_Access;
          Next    : Node_Access;
          Prev    : Node_Access;
       end record;
 
-   function "=" (L, R : Node_Type) return Boolean is abstract;
-
    use Ada.Finalization;
 
    type List is
@@ -213,6 +212,8 @@ private
         First  : Node_Access;
         Last   : Node_Access;
         Length : Count_Type := 0;
+        Busy   : Natural := 0;
+        Lock   : Natural := 0;
      end record;
 
    procedure Adjust (Container : in out List);
@@ -233,7 +234,7 @@ private
 
    for List'Write use Write;
 
-   Empty_List : constant List := List'(Controlled with null, null, 0);
+   Empty_List : constant List := List'(Controlled with null, null, 0, 0, 0);
 
    type List_Access is access constant List;
    for List_Access'Storage_Size use 0;
@@ -247,5 +248,3 @@ private
    No_Element : constant Cursor := Cursor'(null, null);
 
 end Ada.Containers.Indefinite_Doubly_Linked_Lists;
-
-
index c0bfaed874a551dfab0478483943ddad50e6a99a..8467800584e65f098f0a3bdb8e6f1c5f8a2d6d63 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_HASHED_MAPS                   --
+--                      A D A . C O N T A I N E R S .                       --
+--               I N D E F I N I T E _ H A S H E D _ M A P S                --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -43,15 +44,6 @@ with Ada.Unchecked_Deallocation;
 
 package body Ada.Containers.Indefinite_Hashed_Maps is
 
-   type Key_Access is access Key_Type;
-   type Element_Access is access Element_Type;
-
-   type Node_Type is limited record
-      Key     : Key_Access;
-      Element : Element_Access;
-      Next    : Node_Access;
-   end record;
-
    procedure Free_Key is
       new Ada.Unchecked_Deallocation (Key_Type, Key_Access);
 
@@ -65,17 +57,17 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    function Copy_Node (Node : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Equivalent_Keys
+   function Equivalent_Key_Node
      (Key  : Key_Type;
       Node : Node_Access) return Boolean;
-   pragma Inline (Equivalent_Keys);
+   pragma Inline (Equivalent_Key_Node);
 
    function Find_Equal_Key
-     (R_Map  : Map;
+     (R_HT   : Hash_Table_Type;
       L_Node : Node_Access) return Boolean;
 
    procedure Free (X : in out Node_Access);
-   pragma Inline (Free);
+   --  pragma Inline (Free);
 
    function Hash_Node (Node : Node_Access) return Hash_Type;
    pragma Inline (Hash_Node);
@@ -89,6 +81,8 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    procedure Set_Next (Node : Node_Access; Next : Node_Access);
    pragma Inline (Set_Next);
 
+   function Vet (Position : Cursor) return Boolean;
+
    procedure Write_Node
      (Stream : access Root_Stream_Type'Class;
       Node   : Node_Access);
@@ -100,8 +94,6 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    package HT_Ops is
       new Ada.Containers.Hash_Tables.Generic_Operations
         (HT_Types          => HT_Types,
-         Hash_Table_Type   => Map,
-         Null_Node         => null,
          Hash_Node         => Hash_Node,
          Next              => Next,
          Set_Next          => Set_Next,
@@ -111,13 +103,11 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    package Key_Ops is
       new Hash_Tables.Generic_Keys
        (HT_Types  => HT_Types,
-        HT_Type   => Map,
-        Null_Node => null,
         Next      => Next,
         Set_Next  => Set_Next,
         Key_Type  => Key_Type,
         Hash      => Hash,
-        Equivalent_Keys => Equivalent_Keys);
+        Equivalent_Keys => Equivalent_Key_Node);
 
    ---------
    -- "=" --
@@ -125,26 +115,37 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Is_Equal is new HT_Ops.Generic_Equal (Find_Equal_Key);
 
-   function "=" (Left, Right : Map) return Boolean renames Is_Equal;
+   function "=" (Left, Right : Map) return Boolean is
+   begin
+      return Is_Equal (Left.HT, Right.HT);
+   end "=";
 
    ------------
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Map) renames HT_Ops.Adjust;
+   procedure Adjust (Container : in out Map) is
+   begin
+      HT_Ops.Adjust (Container.HT);
+   end Adjust;
 
    --------------
    -- Capacity --
    --------------
 
-   function Capacity (Container : Map)
-     return Count_Type renames HT_Ops.Capacity;
+   function Capacity (Container : Map) return Count_Type is
+   begin
+      return HT_Ops.Capacity (Container.HT);
+   end Capacity;
 
    -----------
    -- Clear --
    -----------
 
-   procedure Clear (Container : in out Map) renames HT_Ops.Clear;
+   procedure Clear (Container : in out Map) is
+   begin
+      HT_Ops.Clear (Container.HT);
+   end Clear;
 
    --------------
    -- Contains --
@@ -182,7 +183,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
       X : Node_Access;
 
    begin
-      Key_Ops.Delete_Key_Sans_Free (Container, Key, X);
+      Key_Ops.Delete_Key_Sans_Free (Container.HT, Key, X);
 
       if X = null then
          raise Constraint_Error;
@@ -193,7 +194,8 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Delete (Container : in out Map; Position : in out Cursor) is
    begin
-      if Position = No_Element then
+      if Position.Node = null then
+         raise Constraint_Error;
          return;
       end if;
 
@@ -201,9 +203,17 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
          raise Program_Error;
       end if;
 
-      HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
-      Free (Position.Node);
+      pragma Assert (Position.Node.Next /= Position.Node);
+      pragma Assert (Position.Node.Key /= null);
+      pragma Assert (Position.Node.Element /= null);
+
+      if Container.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node);
 
+      Free (Position.Node);
       Position.Container := null;
    end Delete;
 
@@ -219,23 +229,30 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Element (Position : Cursor) return Element_Type is
    begin
+      pragma Assert (Vet (Position));
       return Position.Node.Element.all;
    end Element;
 
-   ---------------------
-   -- Equivalent_Keys --
-   ---------------------
+   -------------------------
+   -- Equivalent_Key_Node --
+   -------------------------
 
-   function Equivalent_Keys
+   function Equivalent_Key_Node
      (Key  : Key_Type;
       Node : Node_Access) return Boolean
    is
    begin
       return Equivalent_Keys (Key, Node.Key.all);
-   end Equivalent_Keys;
+   end Equivalent_Key_Node;
+
+   ---------------------
+   -- Equivalent_Keys --
+   ---------------------
 
    function Equivalent_Keys (Left, Right : Cursor) return Boolean is
    begin
+      pragma Assert (Vet (Left));
+      pragma Assert (Vet (Right));
       return Equivalent_Keys (Left.Node.Key.all, Right.Node.Key.all);
    end Equivalent_Keys;
 
@@ -244,6 +261,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
       Right : Key_Type) return Boolean
    is
    begin
+      pragma Assert (Vet (Left));
       return Equivalent_Keys (Left.Node.Key.all, Right);
    end Equivalent_Keys;
 
@@ -252,6 +270,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
       Right : Cursor) return Boolean
    is
    begin
+      pragma Assert (Vet (Right));
       return Equivalent_Keys (Left, Right.Node.Key.all);
    end Equivalent_Keys;
 
@@ -262,7 +281,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    procedure Exclude (Container : in out Map; Key : Key_Type) is
       X : Node_Access;
    begin
-      Key_Ops.Delete_Key_Sans_Free (Container, Key, X);
+      Key_Ops.Delete_Key_Sans_Free (Container.HT, Key, X);
       Free (X);
    end Exclude;
 
@@ -270,14 +289,17 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    -- Finalize --
    --------------
 
-   procedure Finalize (Container : in out Map) renames HT_Ops.Finalize;
+   procedure Finalize (Container : in out Map) is
+   begin
+      HT_Ops.Finalize (Container.HT);
+   end Finalize;
 
    ----------
    -- Find --
    ----------
 
    function Find (Container : Map; Key : Key_Type) return Cursor is
-      Node : constant Node_Access := Key_Ops.Find (Container, Key);
+      Node : constant Node_Access := Key_Ops.Find (Container.HT, Key);
 
    begin
       if Node = null then
@@ -292,11 +314,11 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    --------------------
 
    function Find_Equal_Key
-     (R_Map  : Map;
+     (R_HT   : Hash_Table_Type;
       L_Node : Node_Access) return Boolean
    is
-      R_Index : constant Hash_Type := Key_Ops.Index (R_Map, L_Node.Key.all);
-      R_Node  : Node_Access := R_Map.Buckets (R_Index);
+      R_Index : constant Hash_Type := Key_Ops.Index (R_HT, L_Node.Key.all);
+      R_Node  : Node_Access := R_HT.Buckets (R_Index);
 
    begin
       while R_Node /= null loop
@@ -315,7 +337,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    -----------
 
    function First (Container : Map) return Cursor is
-      Node : constant Node_Access := HT_Ops.First (Container);
+      Node : constant Node_Access := HT_Ops.First (Container.HT);
    begin
       if Node = null then
          return No_Element;
@@ -332,11 +354,40 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
       procedure Deallocate is
          new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
    begin
-      if X /= null then
+      if X = null then
+         return;
+      end if;
+
+      X.Next := X;  --  detect mischief (in Vet)
+
+      begin
          Free_Key (X.Key);
+      exception
+         when others =>
+            X.Key := null;
+
+            begin
+               Free_Element (X.Element);
+            exception
+               when others =>
+                  X.Element := null;
+            end;
+
+            Deallocate (X);
+            raise;
+      end;
+
+      begin
          Free_Element (X.Element);
-         Deallocate (X);
-      end if;
+      exception
+         when others =>
+            X.Element := null;
+
+            Deallocate (X);
+            raise;
+      end;
+
+      Deallocate (X);
    end Free;
 
    -----------------
@@ -345,7 +396,13 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Has_Element (Position : Cursor) return Boolean is
    begin
-      return Position /= No_Element;
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return False;
+      end if;
+
+      pragma Assert (Vet (Position));
+      return True;
    end Has_Element;
 
    ---------------
@@ -376,11 +433,22 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
       Insert (Container, Key, New_Item, Position, Inserted);
 
       if not Inserted then
+         if Container.HT.Lock > 0 then
+            raise Program_Error;
+         end if;
+
          K := Position.Node.Key;
          E := Position.Node.Element;
 
          Position.Node.Key := new Key_Type'(Key);
-         Position.Node.Element := new Element_Type'(New_Item);
+
+         begin
+            Position.Node.Element := new Element_Type'(New_Item);
+         exception
+            when others =>
+               Free_Key (K);
+               raise;
+         end;
 
          Free_Key (K);
          Free_Element (E);
@@ -420,11 +488,17 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
             raise;
       end New_Node;
 
+      HT : Hash_Table_Type renames Container.HT;
+
    --  Start of processing for Insert
 
    begin
-      HT_Ops.Ensure_Capacity (Container, Container.Length + 1);
-      Insert (Container, Key, Position.Node, Inserted);
+      if HT.Length >= HT_Ops.Capacity (HT) then
+         --  TODO: see note in a-cohama.adb.
+         HT_Ops.Reserve_Capacity (HT, HT.Length + 1);
+      end if;
+
+      Insert (HT, Key, Position.Node, Inserted);
       Position.Container := Container'Unchecked_Access;
    end Insert;
 
@@ -450,7 +524,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Is_Empty (Container : Map) return Boolean is
    begin
-      return Container.Length = 0;
+      return Container.HT.Length = 0;
    end Is_Empty;
 
    -------------
@@ -479,7 +553,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    --  Start of processing Iterate
 
    begin
-      Iterate (Container);
+      Iterate (Container.HT);
    end Iterate;
 
    ---------
@@ -488,6 +562,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Key (Position : Cursor) return Key_Type is
    begin
+      pragma Assert (Vet (Position));
       return Position.Node.Key.all;
    end Key;
 
@@ -497,7 +572,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Length (Container : Map) return Count_Type is
    begin
-      return Container.Length;
+      return Container.HT.Length;
    end Length;
 
    ----------
@@ -506,7 +581,11 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Move
      (Target : in out Map;
-      Source : in out Map) renames HT_Ops.Move;
+      Source : in out Map)
+   is
+   begin
+      HT_Ops.Move (Target => Target.HT, Source => Source.HT);
+   end Move;
 
    ----------
    -- Next --
@@ -524,13 +603,15 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    function Next (Position : Cursor) return Cursor is
    begin
-      if Position = No_Element then
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return No_Element;
       end if;
 
       declare
-         M    : Map renames Position.Container.all;
-         Node : constant Node_Access := HT_Ops.Next (M, Position.Node);
+         pragma Assert (Vet (Position));
+         HT   : Hash_Table_Type renames Position.Container.HT;
+         Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
 
       begin
          if Node = null then
@@ -547,10 +628,35 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Query_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : Element_Type))
    is
+      pragma Assert (Vet (Position));
+
+      K : Key_Type renames Position.Node.Key.all;
+      E : Element_Type renames Position.Node.Element.all;
+
+      M  : Map renames Position.Container.all;
+      HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
+
+      B : Natural renames HT.Busy;
+      L : Natural renames HT.Lock;
+
    begin
-      Process (Position.Node.Key.all, Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -561,7 +667,11 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Read
      (Stream    : access Root_Stream_Type'Class;
-      Container : out Map) renames Read_Nodes;
+      Container : out Map)
+   is
+   begin
+      Read_Nodes (Stream, Container.HT);
+   end Read;
 
    ---------------
    -- Read_Node --
@@ -602,7 +712,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
       Key       : Key_Type;
       New_Item  : Element_Type)
    is
-      Node : constant Node_Access := Key_Ops.Find (Container, Key);
+      Node : constant Node_Access := Key_Ops.Find (Container.HT, Key);
 
       K : Key_Access;
       E : Element_Access;
@@ -612,11 +722,22 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
          raise Constraint_Error;
       end if;
 
+      if Container.HT.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       K := Node.Key;
       E := Node.Element;
 
       Node.Key := new Key_Type'(Key);
-      Node.Element := new Element_Type'(New_Item);
+
+      begin
+         Node.Element := new Element_Type'(New_Item);
+      exception
+         when others =>
+            Free_Key (K);
+            raise;
+      end;
 
       Free_Key (K);
       Free_Element (E);
@@ -627,8 +748,13 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    ---------------------
 
    procedure Replace_Element (Position : Cursor; By : Element_Type) is
+      pragma Assert (Vet (Position));
       X : Element_Access := Position.Node.Element;
    begin
+      if Position.Container.HT.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       Position.Node.Element := new Element_Type'(By);
       Free_Element (X);
    end Replace_Element;
@@ -639,7 +765,11 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Reserve_Capacity
      (Container : in out Map;
-      Capacity  : Count_Type) renames HT_Ops.Ensure_Capacity;
+      Capacity  : Count_Type)
+   is
+   begin
+      HT_Ops.Reserve_Capacity (Container.HT, Capacity);
+   end Reserve_Capacity;
 
    --------------
    -- Set_Next --
@@ -656,12 +786,93 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Update_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : in out Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : in out Element_Type))
    is
+      pragma Assert (Vet (Position));
+
+      K : Key_Type renames Position.Node.Key.all;
+      E : Element_Type renames Position.Node.Element.all;
+
+      M  : Map renames Position.Container.all;
+      HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
+
+      B : Natural renames HT.Busy;
+      L : Natural renames HT.Lock;
+
    begin
-      Process (Position.Node.Key.all, Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
+   ---------
+   -- Vet --
+   ---------
+
+   function Vet (Position : Cursor) return Boolean is
+   begin
+      if Position.Node = null then
+         return False;
+      end if;
+
+      if Position.Node.Next = Position.Node then
+         return False;
+      end if;
+
+      if Position.Node.Key = null then
+         return False;
+      end if;
+
+      if Position.Node.Element = null then
+         return False;
+      end if;
+
+      declare
+         HT : Hash_Table_Type renames Position.Container.HT;
+         X  : Node_Access;
+      begin
+         if HT.Length = 0 then
+            return False;
+         end if;
+
+         if HT.Buckets = null then
+            return False;
+         end if;
+
+         X := HT.Buckets (Key_Ops.Index (HT, Position.Node.Key.all));
+
+         for J in 1 .. HT.Length loop
+            if X = Position.Node then
+               return True;
+            end if;
+
+            if X = null then
+               return False;
+            end if;
+
+            if X = X.Next then -- weird
+               return False;
+            end if;
+
+            X := X.Next;
+         end loop;
+
+         return False;
+      end;
+   end Vet;
+
    -----------
    -- Write --
    -----------
@@ -670,7 +881,11 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Write
      (Stream    : access Root_Stream_Type'Class;
-      Container : Map) renames Write_Nodes;
+      Container : Map)
+   is
+   begin
+      Write_Nodes (Stream, Container.HT);
+   end Write;
 
    ----------------
    -- Write_Node --
@@ -686,4 +901,3 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
    end Write_Node;
 
 end Ada.Containers.Indefinite_Hashed_Maps;
-
index 7769cbb1a83c9009bd710c014184e01421c4c4fc..1f15c585db67815e3efa83e0561b1c4299d11328 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_HASHED_MAPS                   --
+--                      A D A . C O N T A I N E R S .                       --
+--               I N D E F I N I T E _ H A S H E D _ M A P S                --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -35,6 +36,7 @@
 
 with Ada.Containers.Hash_Tables;
 with Ada.Streams;
+with Ada.Finalization;
 
 generic
    type Key_Type (<>) is private;
@@ -61,6 +63,8 @@ package Ada.Containers.Indefinite_Hashed_Maps is
 
    procedure Clear (Container : in out Map);
 
+   function Key (Position : Cursor) return Key_Type;
+
    function Element (Position : Cursor) return Element_Type;
 
    procedure Query_Element
@@ -105,14 +109,14 @@ package Ada.Containers.Indefinite_Hashed_Maps is
      (Container : in out Map;
       Key       : Key_Type);
 
-   procedure Exclude
-     (Container : in out Map;
-      Key       : Key_Type);
-
    procedure Delete
      (Container : in out Map;
       Position  : in out Cursor);
 
+   procedure Exclude
+     (Container : in out Map;
+      Key       : Key_Type);
+
    function Contains
      (Container : Map;
       Key       : Key_Type) return Boolean;
@@ -125,12 +129,6 @@ package Ada.Containers.Indefinite_Hashed_Maps is
      (Container : Map;
       Key       : Key_Type) return Element_Type;
 
-   function Capacity (Container : Map) return Count_Type;
-
-   procedure Reserve_Capacity
-     (Container : in out Map;
-      Capacity  : Count_Type);
-
    function First (Container : Map) return Cursor;
 
    function Next (Position : Cursor) return Cursor;
@@ -139,8 +137,6 @@ package Ada.Containers.Indefinite_Hashed_Maps is
 
    function Has_Element (Position : Cursor) return Boolean;
 
-   function Key (Position : Cursor) return Key_Type;
-
    function Equivalent_Keys (Left, Right : Cursor)
      return Boolean;
 
@@ -156,16 +152,48 @@ package Ada.Containers.Indefinite_Hashed_Maps is
      (Container : Map;
       Process   : not null access procedure (Position : Cursor));
 
+   function Capacity (Container : Map) return Count_Type;
+
+   procedure Reserve_Capacity
+     (Container : in out Map;
+      Capacity  : Count_Type);
+
 private
+   pragma Inline ("=");
+   pragma Inline (Length);
+   pragma Inline (Is_Empty);
+   pragma Inline (Clear);
+   pragma Inline (Key);
+   pragma Inline (Element);
+   pragma Inline (Move);
+   pragma Inline (Contains);
+   pragma Inline (Capacity);
+   pragma Inline (Reserve_Capacity);
+   pragma Inline (Has_Element);
+   pragma Inline (Equivalent_Keys);
+
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package HT_Types is
-      new Hash_Tables.Generic_Hash_Table_Types (Node_Access);
+   type Key_Access is access Key_Type;
+   type Element_Access is access Element_Type;
 
-   use HT_Types;
+   type Node_Type is limited record
+      Key     : Key_Access;
+      Element : Element_Access;
+      Next    : Node_Access;
+   end record;
+
+   package HT_Types is new Hash_Tables.Generic_Hash_Table_Types
+     (Node_Type,
+      Node_Access);
+
+   type Map is new Ada.Finalization.Controlled with record
+      HT : HT_Types.Hash_Table_Type;
+   end record;
 
-   type Map is new Hash_Table_Type with null record;
+   use HT_Types;
+   use Ada.Finalization;
 
    procedure Adjust (Container : in out Map);
 
@@ -198,9 +226,6 @@ private
 
    for Map'Read use Read;
 
-   Empty_Map : constant Map := (Hash_Table_Type with null record);
+   Empty_Map : constant Map := (Controlled with HT => (null, 0, 0, 0));
 
 end Ada.Containers.Indefinite_Hashed_Maps;
-
-
-
index cc5589f0c1cfc5479b2fbca044c7a0d558ce8cc7..f47d9a6c157d7de1b4243c56c2d89dad4503fcf9 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_HASHED_SETS                   --
+--                      A D A . C O N T A I N E R S .                       --
+--               I N D E F I N I T E _ H A S H E D _ S E T S                --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -45,849 +46,1184 @@ with System;  use type System.Address;
 
 with Ada.Containers.Prime_Numbers;
 
-with Ada.Finalization;  use Ada.Finalization;
-
 package body Ada.Containers.Indefinite_Hashed_Sets is
 
-   type Element_Access is access Element_Type;
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
 
-   type Node_Type is
-      limited record
-         Element : Element_Access;
-         Next    : Node_Access;
-      end record;
+   function Copy_Node (Source : Node_Access) return Node_Access;
+   pragma Inline (Copy_Node);
 
-   function Hash_Node
-     (Node : Node_Access) return Hash_Type;
-   pragma Inline (Hash_Node);
+   function Equivalent_Keys
+     (Key  : Element_Type;
+      Node : Node_Access) return Boolean;
+   pragma Inline (Equivalent_Keys);
 
-   function Hash_Node
-     (Node : Node_Access) return Hash_Type is
-   begin
-      return Hash (Node.Element.all);
-   end Hash_Node;
+   function Find_Equal_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean;
 
-   function Next
-     (Node : Node_Access) return Node_Access;
-   pragma Inline (Next);
+   function Find_Equivalent_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean;
 
-   function Next
-     (Node : Node_Access) return Node_Access is
-   begin
-      return Node.Next;
-   end Next;
+   procedure Free (X : in out Node_Access);
 
-   procedure Set_Next
-     (Node : Node_Access;
-      Next : Node_Access);
-   pragma Inline (Set_Next);
+   function Hash_Node (Node : Node_Access) return Hash_Type;
+   pragma Inline (Hash_Node);
 
-   procedure Set_Next
-     (Node : Node_Access;
-      Next : Node_Access) is
-   begin
-      Node.Next := Next;
-   end Set_Next;
+   function Is_In (HT  : Hash_Table_Type; Key : Node_Access) return Boolean;
+   pragma Inline (Is_In);
 
-   function Equivalent_Keys
-     (Key  : Element_Type;
-      Node : Node_Access) return Boolean;
-   pragma Inline (Equivalent_Keys);
+   function Next (Node : Node_Access) return Node_Access;
+   pragma Inline (Next);
 
-   function Equivalent_Keys
-     (Key  : Element_Type;
-      Node : Node_Access) return Boolean is
-   begin
-      return Equivalent_Keys (Key, Node.Element.all);
-   end Equivalent_Keys;
+   function Read_Node (Stream : access Root_Stream_Type'Class)
+     return Node_Access;
+   pragma Inline (Read_Node);
 
-   function Copy_Node
-     (Source : Node_Access) return Node_Access;
-   pragma Inline (Copy_Node);
+   procedure Replace_Element
+     (HT      : in out Hash_Table_Type;
+      Node    : Node_Access;
+      Element : Element_Type);
 
-   function Copy_Node
-     (Source : Node_Access) return Node_Access is
+   procedure Set_Next (Node : Node_Access; Next : Node_Access);
+   pragma Inline (Set_Next);
 
-      Target : constant Node_Access :=
-        new Node_Type'(Element => Source.Element,
-                       Next    => null);
-   begin
-      return Target;
-   end Copy_Node;
+   procedure Write_Node
+     (Stream : access Root_Stream_Type'Class;
+      Node   : Node_Access);
+   pragma Inline (Write_Node);
 
+   --------------------------
+   -- Local Instantiations --
+   --------------------------
 
    procedure Free_Element is
       new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
 
-   procedure Free (X : in out Node_Access);
-
-   procedure Free (X : in out Node_Access) is
-      procedure Deallocate is
-         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
-   begin
-      if X /= null then
-         Free_Element (X.Element);
-         Deallocate (X);
-      end if;
-   end Free;
-
    package HT_Ops is
       new Hash_Tables.Generic_Operations
-       (HT_Types          => HT_Types,
-        Hash_Table_Type   => Set,
-        Null_Node         => null,
-        Hash_Node         => Hash_Node,
-        Next              => Next,
-        Set_Next          => Set_Next,
-        Copy_Node         => Copy_Node,
-        Free              => Free);
+       (HT_Types  => HT_Types,
+        Hash_Node => Hash_Node,
+        Next      => Next,
+        Set_Next  => Set_Next,
+        Copy_Node => Copy_Node,
+        Free      => Free);
 
    package Element_Keys is
       new Hash_Tables.Generic_Keys
        (HT_Types  => HT_Types,
-        HT_Type   => Set,
-        Null_Node => null,
         Next      => Next,
         Set_Next  => Set_Next,
         Key_Type  => Element_Type,
         Hash      => Hash,
         Equivalent_Keys => Equivalent_Keys);
 
+   function Is_Equal is
+      new HT_Ops.Generic_Equal (Find_Equal_Key);
 
-   procedure Adjust (Container : in out Set) renames HT_Ops.Adjust;
-
-   procedure Finalize (Container : in out Set) renames HT_Ops.Finalize;
-
-
-   function Find_Equal_Key
-     (R_Set  : Set;
-      L_Node : Node_Access) return Boolean;
+   function Is_Equivalent is
+      new HT_Ops.Generic_Equal (Find_Equivalent_Key);
 
-   function Find_Equal_Key
-     (R_Set  : Set;
-      L_Node : Node_Access) return Boolean is
+   procedure Read_Nodes is
+      new HT_Ops.Generic_Read (Read_Node);
 
-      R_Index : constant Hash_Type :=
-        Element_Keys.Index (R_Set, L_Node.Element.all);
+   procedure Write_Nodes is
+     new HT_Ops.Generic_Write (Write_Node);
 
-      R_Node  : Node_Access := R_Set.Buckets (R_Index);
+   ---------
+   -- "=" --
+   ---------
 
+   function "=" (Left, Right : Set) return Boolean is
    begin
+      return Is_Equal (Left.HT, Right.HT);
+   end "=";
 
-      loop
-
-         if R_Node = null then
-            return False;
-         end if;
-
-         if L_Node.Element.all = R_Node.Element.all then
-            return True;
-         end if;
-
-         R_Node := Next (R_Node);
-
-      end loop;
-
-   end Find_Equal_Key;
-
-   function Is_Equal is
-      new HT_Ops.Generic_Equal (Find_Equal_Key);
+   ------------
+   -- Adjust --
+   ------------
 
-   function "=" (Left, Right : Set) return Boolean renames Is_Equal;
+   procedure Adjust (Container : in out Set) is
+   begin
+      HT_Ops.Adjust (Container.HT);
+   end Adjust;
 
+   --------------
+   -- Capacity --
+   --------------
 
-   function Length (Container : Set) return Count_Type is
+   function Capacity (Container : Set) return Count_Type is
    begin
-      return Container.Length;
-   end Length;
+      return HT_Ops.Capacity (Container.HT);
+   end Capacity;
 
+   -----------
+   -- Clear --
+   -----------
 
-   function Is_Empty (Container : Set) return Boolean is
+   procedure Clear (Container : in out Set) is
    begin
-      return Container.Length = 0;
-   end Is_Empty;
+      HT_Ops.Clear (Container.HT);
+   end Clear;
 
+   --------------
+   -- Contains --
+   --------------
 
-   procedure Clear (Container : in out Set) renames HT_Ops.Clear;
+   function Contains (Container : Set; Item : Element_Type) return Boolean is
+   begin
+      return Find (Container, Item) /= No_Element;
+   end Contains;
 
+   ---------------
+   -- Copy_Node --
+   ---------------
 
-   function Element (Position : Cursor) return Element_Type is
+   function Copy_Node (Source : Node_Access) return Node_Access is
+      E : Element_Access := new Element_Type'(Source.Element.all);
    begin
-      return Position.Node.Element.all;
-   end Element;
+      return new Node_Type'(Element => E, Next => null);
+   exception
+      when others =>
+         Free_Element (E);
+         raise;
+   end Copy_Node;
 
+   ------------
+   -- Delete --
+   ------------
 
-   procedure Query_Element
-     (Position : in Cursor;
-      Process  : not null access procedure (Element : in Element_Type)) is
-   begin
-      Process (Position.Node.Element.all);
-   end Query_Element;
+   procedure Delete
+     (Container : in out Set;
+      Item      : Element_Type)
+   is
+      X : Node_Access;
 
+   begin
+      Element_Keys.Delete_Key_Sans_Free (Container.HT, Item, X);
 
---  TODO:
---     procedure Replace_Element (Container : in out Set;
---                                Position  : in     Node_Access;
---                                By        : in     Element_Type);
+      if X = null then
+         raise Constraint_Error;
+      end if;
 
---     procedure Replace_Element (Container : in out Set;
---                                Position  : in     Node_Access;
---                                By        : in     Element_Type) is
+      Free (X);
+   end Delete;
 
---        Node : Node_Access := Position;
+   procedure Delete
+     (Container : in out Set;
+      Position  : in out Cursor)
+   is
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
 
---     begin
+      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
+         raise Program_Error;
+      end if;
 
---        if Equivalent_Keys (Node.Element.all, By) then
+      if Container.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
---           declare
---              X : Element_Access := Node.Element;
---           begin
---              Node.Element := new Element_Type'(By);
---              --
---              --  NOTE: If there's an exception here, then just
---              --  let it propagate.  We haven't modified the
---              --  state of the container, so there's nothing else
---              --  we need to do.
+      HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node);
 
---              Free_Element (X);
---           end;
+      Free (Position.Node);
 
---           return;
+      Position.Container := null;
+   end Delete;
 
---        end if;
+   ----------------
+   -- Difference --
+   ----------------
 
---        HT_Ops.Delete_Node_Sans_Free (Container, Node);
+   procedure Difference
+     (Target : in out Set;
+      Source : Set)
+   is
+      Tgt_Node : Node_Access;
 
---        begin
---           Free_Element (Node.Element);
---        exception
---           when others =>
---              Node.Element := null;  --  don't attempt to dealloc X.E again
---              Free (Node);
---              raise;
---        end;
+   begin
+      if Target'Address = Source'Address then
+         Clear (Target);
+         return;
+      end if;
 
---        begin
---           Node.Element := new Element_Type'(By);
---        exception
---           when others =>
---              Free (Node);
---              raise;
---        end;
+      if Source.Length = 0 then
+         return;
+      end if;
 
---        declare
---           function New_Node (Next : Node_Access) return Node_Access;
---           pragma Inline (New_Node);
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
---           function New_Node (Next : Node_Access) return Node_Access is
---           begin
---              Node.Next := Next;
---              return Node;
---           end New_Node;
+      --  TODO: This can be written in terms of a loop instead as
+      --  active-iterator style, sort of like a passive iterator.
 
---           procedure Insert is
---              new Element_Keys.Generic_Conditional_Insert (New_Node);
+      Tgt_Node := HT_Ops.First (Target.HT);
+      while Tgt_Node /= null loop
+         if Is_In (Source.HT, Tgt_Node) then
+            declare
+               X : Node_Access := Tgt_Node;
+            begin
+               Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
+               HT_Ops.Delete_Node_Sans_Free (Target.HT, X);
+               Free (X);
+            end;
 
---           Result  : Node_Access;
---           Success : Boolean;
---        begin
---           Insert
---             (HT      => Container,
---              Key     => Node.Element.all,
---              Node    => Result,
---              Success => Success);
+         else
+            Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
+         end if;
+      end loop;
+   end Difference;
 
---           if not Success then
---              Free (Node);
---              raise Program_Error;
---           end if;
+   function Difference (Left, Right : Set) return Set is
+      Buckets : HT_Types.Buckets_Access;
+      Length  : Count_Type;
 
---           pragma Assert (Result = Node);
---        end;
+   begin
+      if Left'Address = Right'Address then
+         return Empty_Set;
+      end if;
 
---     end Replace_Element;
+      if Left.Length = 0 then
+         return Empty_Set;
+      end if;
 
+      if Right.Length = 0 then
+         return Left;
+      end if;
 
---     procedure Replace_Element (Container : in out Set;
---                                Position  : in     Cursor;
---                                By        : in     Element_Type) is
---     begin
+      declare
+         Size : constant Hash_Type := Prime_Numbers.To_Prime (Left.Length);
+      begin
+         Buckets := new Buckets_Type (0 .. Size - 1);
+      end;
 
---        if Position.Container = null then
---           raise Constraint_Error;
---        end if;
+      Length := 0;
 
---        if Position.Container /= Set_Access'(Container'Unchecked_Access) then
---           raise Program_Error;
---        end if;
+      Iterate_Left : declare
+         procedure Process (L_Node : Node_Access);
 
---        Replace_Element (Container, Position.Node, By);
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
 
---     end Replace_Element;
+         -------------
+         -- Process --
+         -------------
 
+         procedure Process (L_Node : Node_Access) is
+         begin
+            if not Is_In (Right.HT, L_Node) then
+               declare
+                  Indx : constant Hash_Type :=
+                           Hash (L_Node.Element.all) mod Buckets'Length;
 
-   procedure Move (Target : in out Set;
-                   Source : in out Set) renames HT_Ops.Move;
+                  Bucket : Node_Access renames Buckets (Indx);
 
+               begin
+                  Bucket := new Node_Type'(L_Node.Element, Bucket);
+               end;
 
-   procedure Insert (Container : in out Set;
-                     New_Item  : in     Element_Type;
-                     Position  :    out Cursor;
-                     Inserted  :    out Boolean) is
+               Length := Length + 1;
+            end if;
+         end Process;
 
-      function New_Node (Next : Node_Access) return Node_Access;
-      pragma Inline (New_Node);
+      --  Start of processing for Iterate_Left
 
-      function New_Node (Next : Node_Access) return Node_Access is
-         Element : Element_Access := new Element_Type'(New_Item);
       begin
-         return new Node_Type'(Element, Next);
+         Iterate (Left.HT);
       exception
          when others =>
-            Free_Element (Element);
+            HT_Ops.Free_Hash_Table (Buckets);
             raise;
-      end New_Node;
+      end Iterate_Left;
 
-      procedure Insert is
-        new Element_Keys.Generic_Conditional_Insert (New_Node);
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Difference;
+
+   -------------
+   -- Element --
+   -------------
 
+   function Element (Position : Cursor) return Element_Type is
    begin
+      return Position.Node.Element.all;
+   end Element;
 
-      HT_Ops.Ensure_Capacity (Container, Container.Length + 1);
-      Insert (Container, New_Item, Position.Node, Inserted);
-      Position.Container := Container'Unchecked_Access;
+   ---------------------
+   -- Equivalent_Sets --
+   ---------------------
 
-   end Insert;
+   function Equivalent_Sets (Left, Right : Set) return Boolean is
+   begin
+      return Is_Equivalent (Left.HT, Right.HT);
+   end Equivalent_Sets;
 
+   -------------------------
+   -- Equivalent_Elements --
+   -------------------------
 
-   procedure Insert (Container : in out Set;
-                     New_Item  : in     Element_Type) is
+   function Equivalent_Elements (Left, Right : Cursor)
+     return Boolean is
+   begin
+      return Equivalent_Elements
+               (Left.Node.Element.all,
+                Right.Node.Element.all);
+   end Equivalent_Elements;
 
-      Position : Cursor;
-      Inserted : Boolean;
+   function Equivalent_Elements (Left : Cursor; Right : Element_Type)
+     return Boolean is
+   begin
+      return Equivalent_Elements (Left.Node.Element.all, Right);
+   end Equivalent_Elements;
 
+   function Equivalent_Elements (Left : Element_Type; Right : Cursor)
+     return Boolean is
    begin
+      return Equivalent_Elements (Left, Right.Node.Element.all);
+   end Equivalent_Elements;
 
-      Insert (Container, New_Item, Position, Inserted);
+   ---------------------
+   -- Equivalent_Keys --
+   ---------------------
 
-      if not Inserted then
-         raise Constraint_Error;
-      end if;
+   function Equivalent_Keys (Key : Element_Type; Node : Node_Access)
+     return Boolean is
+   begin
+      return Equivalent_Elements (Key, Node.Element.all);
+   end Equivalent_Keys;
 
-   end Insert;
+   -------------
+   -- Exclude --
+   -------------
 
+   procedure Exclude
+     (Container : in out Set;
+      Item      : Element_Type)
+   is
+      X : Node_Access;
+   begin
+      Element_Keys.Delete_Key_Sans_Free (Container.HT, Item, X);
+      Free (X);
+   end Exclude;
 
-   procedure Replace (Container : in out Set;
-                      New_Item  : in     Element_Type) is
+   --------------
+   -- Finalize --
+   --------------
 
-      Node : constant Node_Access :=
-        Element_Keys.Find (Container, New_Item);
+   procedure Finalize (Container : in out Set) is
+   begin
+      HT_Ops.Finalize (Container.HT);
+   end Finalize;
 
-      X : Element_Access;
+   ----------
+   -- Find --
+   ----------
 
-   begin
+   function Find
+     (Container : Set;
+      Item      : Element_Type) return Cursor
+   is
+      Node : constant Node_Access := Element_Keys.Find (Container.HT, Item);
 
+   begin
       if Node = null then
-         raise Constraint_Error;
+         return No_Element;
       end if;
 
-      X := Node.Element;
+      return Cursor'(Container'Unrestricted_Access, Node);
+   end Find;
 
-      Node.Element := new Element_Type'(New_Item);
+   --------------------
+   -- Find_Equal_Key --
+   --------------------
 
-      Free_Element (X);
+   function Find_Equal_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean
+   is
+      R_Index : constant Hash_Type :=
+                  Element_Keys.Index (R_HT, L_Node.Element.all);
 
-   end Replace;
+      R_Node  : Node_Access := R_HT.Buckets (R_Index);
 
+   begin
+      loop
+         if R_Node = null then
+            return False;
+         end if;
 
-   procedure Include (Container : in out Set;
-                      New_Item  : in     Element_Type) is
+         if L_Node.Element.all = R_Node.Element.all then
+            return True;
+         end if;
 
-      Position : Cursor;
-      Inserted : Boolean;
+         R_Node := Next (R_Node);
+      end loop;
+   end Find_Equal_Key;
 
-      X : Element_Access;
+   -------------------------
+   -- Find_Equivalent_Key --
+   -------------------------
+
+   function Find_Equivalent_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean
+   is
+      R_Index : constant Hash_Type :=
+                  Element_Keys.Index (R_HT, L_Node.Element.all);
+
+      R_Node  : Node_Access := R_HT.Buckets (R_Index);
 
    begin
+      loop
+         if R_Node = null then
+            return False;
+         end if;
 
-      Insert (Container, New_Item, Position, Inserted);
+         if Equivalent_Elements (L_Node.Element.all, R_Node.Element.all) then
+            return True;
+         end if;
 
-      if not Inserted then
+         R_Node := Next (R_Node);
+      end loop;
+   end Find_Equivalent_Key;
 
-         X := Position.Node.Element;
+   -----------
+   -- First --
+   -----------
 
-         Position.Node.Element := new Element_Type'(New_Item);
-
-         Free_Element (X);
+   function First (Container : Set) return Cursor is
+      Node : constant Node_Access := HT_Ops.First (Container.HT);
 
+   begin
+      if Node = null then
+         return No_Element;
       end if;
 
-   end Include;
-
+      return Cursor'(Container'Unrestricted_Access, Node);
+   end First;
 
-   procedure Delete (Container : in out Set;
-                     Item      : in     Element_Type) is
+   ----------
+   -- Free --
+   ----------
 
-      X : Node_Access;
+   procedure Free (X : in out Node_Access) is
+      procedure Deallocate is
+         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
 
    begin
-
-      Element_Keys.Delete_Key_Sans_Free (Container, Item, X);
-
       if X = null then
-         raise Constraint_Error;
+         return;
       end if;
 
-      Free (X);
+      begin
+         Free_Element (X.Element);
+      exception
+         when others =>
+            X.Element := null;
+            Deallocate (X);
+            raise;
+      end;
 
-   end Delete;
+      Deallocate (X);
+   end Free;
 
+   -----------------
+   -- Has_Element --
+   -----------------
 
-   procedure Exclude (Container : in out Set;
-                      Item      : in     Element_Type) is
+   function Has_Element (Position : Cursor) return Boolean is
+   begin
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return False;
+      end if;
 
-      X : Node_Access;
+      return True;
+   end Has_Element;
 
+   ---------------
+   -- Hash_Node --
+   ---------------
+
+   function Hash_Node (Node : Node_Access) return Hash_Type is
    begin
+      return Hash (Node.Element.all);
+   end Hash_Node;
 
-      Element_Keys.Delete_Key_Sans_Free (Container, Item, X);
-      Free (X);
+   -------------
+   -- Include --
+   -------------
 
-   end Exclude;
+   procedure Include
+     (Container : in out Set;
+      New_Item  : Element_Type)
+   is
+      Position : Cursor;
+      Inserted : Boolean;
 
+      X : Element_Access;
 
-   procedure Delete (Container : in out Set;
-                     Position  : in out Cursor) is
    begin
+      Insert (Container, New_Item, Position, Inserted);
 
-      if Position = No_Element then
-         return;
-      end if;
+      if not Inserted then
+         if Container.HT.Lock > 0 then
+            raise Program_Error;
+         end if;
 
-      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
-         raise Program_Error;
-      end if;
+         X := Position.Node.Element;
 
-      HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
-      Free (Position.Node);
+         Position.Node.Element := new Element_Type'(New_Item);
 
-      Position.Container := null;
+         Free_Element (X);
+      end if;
+   end Include;
 
-   end Delete;
+   ------------
+   -- Insert --
+   ------------
 
+   procedure Insert
+     (Container : in out Set;
+      New_Item  : Element_Type;
+      Position  : out Cursor;
+      Inserted  : out Boolean)
+   is
+      function New_Node (Next : Node_Access) return Node_Access;
+      pragma Inline (New_Node);
 
+      procedure Insert is
+         new Element_Keys.Generic_Conditional_Insert (New_Node);
 
-   procedure Union (Target : in out Set;
-                    Source : in     Set) is
+      --------------
+      -- New_Node --
+      --------------
 
-      procedure Process (Src_Node : in Node_Access);
+      function New_Node (Next : Node_Access) return Node_Access is
+         Element : Element_Access := new Element_Type'(New_Item);
 
-      procedure Process (Src_Node : in Node_Access) is
+      begin
+         return new Node_Type'(Element, Next);
+      exception
+         when others =>
+            Free_Element (Element);
+            raise;
+      end New_Node;
 
-         Src : Element_Type renames Src_Node.Element.all;
+      HT : Hash_Table_Type renames Container.HT;
 
-         function New_Node (Next : Node_Access) return Node_Access;
-         pragma Inline (New_Node);
+   --  Start of processing for Insert
 
-         function New_Node (Next : Node_Access) return Node_Access is
-            Tgt : Element_Access := new Element_Type'(Src);
-         begin
-            return new Node_Type'(Tgt, Next);
-         exception
-            when others =>
-               Free_Element (Tgt);
-               raise;
-         end New_Node;
+   begin
+      if HT.Length >= HT_Ops.Capacity (HT) then
+         --  TODO: optimize this (see a-cohase.adb)
+         HT_Ops.Reserve_Capacity (HT, HT.Length + 1);
+      end if;
 
-         procedure Insert is
-            new Element_Keys.Generic_Conditional_Insert (New_Node);
+      Insert (HT, New_Item, Position.Node, Inserted);
+      Position.Container := Container'Unchecked_Access;
+   end Insert;
 
-         Tgt_Node : Node_Access;
-         Success  : Boolean;
+   procedure Insert
+     (Container : in out Set;
+      New_Item  : Element_Type)
+   is
+      Position : Cursor;
+      Inserted : Boolean;
 
-      begin
+   begin
+      Insert (Container, New_Item, Position, Inserted);
 
-         Insert (Target, Src, Tgt_Node, Success);
+      if not Inserted then
+         raise Constraint_Error;
+      end if;
+   end Insert;
 
-      end Process;
+   ------------------
+   -- Intersection --
+   ------------------
 
-      procedure Iterate is
-         new HT_Ops.Generic_Iteration (Process);
+   procedure Intersection
+     (Target : in out Set;
+      Source : Set)
+   is
+      Tgt_Node : Node_Access;
 
    begin
-
       if Target'Address = Source'Address then
          return;
       end if;
 
-      HT_Ops.Ensure_Capacity (Target, Target.Length + Source.Length);
-
-      Iterate (Source);
+      if Source.Length = 0 then
+         Clear (Target);
+         return;
+      end if;
 
-   end Union;
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
+      --  TODO: optimize this to use an explicit
+      --  loop instead of an active iterator
+      --  (similar to how a passive iterator is
+      --  implemented).
+      --
+      --  Another possibility is to test which
+      --  set is smaller, and iterate over the
+      --  smaller set.
 
+      Tgt_Node := HT_Ops.First (Target.HT);
+      while Tgt_Node /= null loop
+         if Is_In (Source.HT, Tgt_Node) then
+            Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
 
-   function Union (Left, Right : Set) return Set is
+         else
+            declare
+               X : Node_Access := Tgt_Node;
+            begin
+               Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
+               HT_Ops.Delete_Node_Sans_Free (Target.HT, X);
+               Free (X);
+            end;
+         end if;
+      end loop;
+   end Intersection;
 
+   function Intersection (Left, Right : Set) return Set is
       Buckets : HT_Types.Buckets_Access;
       Length  : Count_Type;
 
    begin
-
       if Left'Address = Right'Address then
          return Left;
       end if;
 
-      if Right.Length = 0 then
-         return Left;
-      end if;
+      Length := Count_Type'Min (Left.Length, Right.Length);
 
-      if Left.Length = 0 then
-         return Right;
+      if Length = 0 then
+         return Empty_Set;
       end if;
 
       declare
-         Size : constant Hash_Type :=
-           Prime_Numbers.To_Prime (Left.Length + Right.Length);
+         Size : constant Hash_Type := Prime_Numbers.To_Prime (Length);
       begin
          Buckets := new Buckets_Type (0 .. Size - 1);
       end;
 
-      declare
+      Length := 0;
+
+      Iterate_Left : declare
          procedure Process (L_Node : Node_Access);
 
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
+
+         -------------
+         -- Process --
+         -------------
+
          procedure Process (L_Node : Node_Access) is
-            I : constant Hash_Type :=
-              Hash (L_Node.Element.all) mod Buckets'Length;
          begin
-            Buckets (I) := new Node_Type'(L_Node.Element, Buckets (I));
+            if Is_In (Right.HT, L_Node) then
+               declare
+                  Indx : constant Hash_Type :=
+                           Hash (L_Node.Element.all) mod Buckets'Length;
+
+                  Bucket : Node_Access renames Buckets (Indx);
+
+               begin
+                  Bucket := new Node_Type'(L_Node.Element, Bucket);
+               end;
+
+               Length := Length + 1;
+            end if;
          end Process;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
+      --  Start of processing for Iterate_Left
+
       begin
-         Iterate (Left);
+         Iterate (Left.HT);
       exception
          when others =>
             HT_Ops.Free_Hash_Table (Buckets);
             raise;
-      end;
+      end Iterate_Left;
 
-      Length := Left.Length;
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Intersection;
 
-      declare
-         procedure Process (Src_Node : Node_Access);
+   --------------
+   -- Is_Empty --
+   --------------
 
-         procedure Process (Src_Node : Node_Access) is
+   function Is_Empty (Container : Set) return Boolean is
+   begin
+      return Container.Length = 0;
+   end Is_Empty;
 
-            Src : Element_Type renames Src_Node.Element.all;
+   -----------
+   -- Is_In --
+   -----------
 
-            I : constant Hash_Type :=
-              Hash (Src) mod Buckets'Length;
+   function Is_In (HT  : Hash_Table_Type; Key : Node_Access) return Boolean is
+   begin
+      return Element_Keys.Find (HT, Key.Element.all) /= null;
+   end Is_In;
 
-            Tgt_Node : Node_Access := Buckets (I);
+   ---------------
+   -- Is_Subset --
+   ---------------
 
-         begin
+   function Is_Subset
+     (Subset : Set;
+      Of_Set : Set) return Boolean
+   is
+      Subset_Node : Node_Access;
 
-            while Tgt_Node /= null loop
+   begin
+      if Subset'Address = Of_Set'Address then
+         return True;
+      end if;
 
-               if Equivalent_Keys (Src, Tgt_Node.Element.all) then
-                  return;
-               end if;
+      if Subset.Length > Of_Set.Length then
+         return False;
+      end if;
 
-               Tgt_Node := Next (Tgt_Node);
+      --  TODO: rewrite this to loop in the
+      --  style of a passive iterator.
 
-            end loop;
+      Subset_Node := HT_Ops.First (Subset.HT);
+      while Subset_Node /= null loop
+         if not Is_In (Of_Set.HT, Subset_Node) then
+            return False;
+         end if;
 
-            declare
-               Tgt : Element_Access := new Element_Type'(Src);
-            begin
-               Buckets (I) := new Node_Type'(Tgt, Buckets (I));
-            exception
-               when others =>
-                  Free_Element (Tgt);
-                  raise;
-            end;
+         Subset_Node := HT_Ops.Next (Subset.HT, Subset_Node);
+      end loop;
 
-            Length := Length + 1;
+      return True;
+   end Is_Subset;
 
-         end Process;
+   -------------
+   -- Iterate --
+   -------------
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
-      begin
-         Iterate (Right);
-      exception
-         when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
-            raise;
-      end;
+   procedure Iterate
+     (Container : Set;
+      Process   : not null access procedure (Position : Cursor))
+   is
+      procedure Process_Node (Node : Node_Access);
+      pragma Inline (Process_Node);
 
-      return (Controlled with Buckets, Length);
+      procedure Iterate is
+         new HT_Ops.Generic_Iteration (Process_Node);
 
-   end Union;
+      ------------------
+      -- Process_Node --
+      ------------------
 
+      procedure Process_Node (Node : Node_Access) is
+      begin
+         Process (Cursor'(Container'Unrestricted_Access, Node));
+      end Process_Node;
 
-   function Is_In
-     (HT  : Set;
-      Key : Node_Access) return Boolean;
-   pragma Inline (Is_In);
+      HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
+      B  : Natural renames HT.Busy;
+
+   --  Start of processing for Iterate
 
-   function Is_In
-     (HT  : Set;
-      Key : Node_Access) return Boolean is
    begin
-      return Element_Keys.Find (HT, Key.Element.all) /= null;
-   end Is_In;
+      B := B + 1;
 
+      begin
+         Iterate (HT);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
 
-   procedure Intersection (Target : in out Set;
-                           Source : in     Set) is
+      B := B - 1;
+   end Iterate;
 
-      Tgt_Node : Node_Access;
+   ------------
+   -- Length --
+   ------------
 
+   function Length (Container : Set) return Count_Type is
    begin
+      return Container.HT.Length;
+   end Length;
 
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
-      if Source.Length = 0 then
-         Clear (Target);
-         return;
-      end if;
-
-      --  TODO: optimize this to use an explicit
-      --  loop instead of an active iterator
-      --  (similar to how a passive iterator is
-      --  implemented).
-      --
-      --  Another possibility is to test which
-      --  set is smaller, and iterate over the
-      --  smaller set.
-
-      Tgt_Node := HT_Ops.First (Target);
+   ----------
+   -- Move --
+   ----------
 
-      while Tgt_Node /= null loop
+   procedure Move (Target : in out Set; Source : in out Set) is
+   begin
+      HT_Ops.Move (Target => Target.HT, Source => Source.HT);
+   end Move;
 
-         if Is_In (Source, Tgt_Node) then
+   ----------
+   -- Next --
+   ----------
 
-            Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
+   function Next (Node : Node_Access) return Node_Access is
+   begin
+      return Node.Next;
+   end Next;
 
-         else
+   function Next (Position : Cursor) return Cursor is
+   begin
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return No_Element;
+      end if;
 
-            declare
-               X : Node_Access := Tgt_Node;
-            begin
-               Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
-               HT_Ops.Delete_Node_Sans_Free (Target, X);
-               Free (X);
-            end;
+      declare
+         HT   : Hash_Table_Type renames Position.Container.HT;
+         Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
 
+      begin
+         if Node = null then
+            return No_Element;
          end if;
 
-      end loop;
-
-   end Intersection;
+         return Cursor'(Position.Container, Node);
+      end;
+   end Next;
 
+   procedure Next (Position : in out Cursor) is
+   begin
+      Position := Next (Position);
+   end Next;
 
-   function Intersection (Left, Right : Set) return Set is
+   -------------
+   -- Overlap --
+   -------------
 
-      Buckets : HT_Types.Buckets_Access;
-      Length  : Count_Type;
+   function Overlap (Left, Right : Set) return Boolean is
+      Left_Node : Node_Access;
 
    begin
+      if Right.Length = 0 then
+         return False;
+      end if;
 
       if Left'Address = Right'Address then
-         return Left;
+         return True;
       end if;
 
-      Length := Count_Type'Min (Left.Length, Right.Length);
-
-      if Length = 0 then
-         return Empty_Set;
-      end if;
+      Left_Node := HT_Ops.First (Left.HT);
+      while Left_Node /= null loop
+         if Is_In (Right.HT, Left_Node) then
+            return True;
+         end if;
 
-      declare
-         Size : constant Hash_Type := Prime_Numbers.To_Prime (Length);
-      begin
-         Buckets := new Buckets_Type (0 .. Size - 1);
-      end;
+         Left_Node := HT_Ops.Next (Left.HT, Left_Node);
+      end loop;
 
-      Length := 0;
+      return False;
+   end Overlap;
 
-      declare
-         procedure Process (L_Node : Node_Access);
+   -------------------
+   -- Query_Element --
+   -------------------
 
-         procedure Process (L_Node : Node_Access) is
-         begin
-            if Is_In (Right, L_Node) then
+   procedure Query_Element
+     (Position : Cursor;
+      Process  : not null access procedure (Element : Element_Type))
+   is
+      E : Element_Type renames Position.Node.Element.all;
 
-               declare
-                  I : constant Hash_Type :=
-                    Hash (L_Node.Element.all) mod Buckets'Length;
-               begin
-                  Buckets (I) := new Node_Type'(L_Node.Element, Buckets (I));
-               end;
+      HT : Hash_Table_Type renames
+             Position.Container'Unrestricted_Access.all.HT;
 
-               Length := Length + 1;
+      B : Natural renames HT.Busy;
+      L : Natural renames HT.Lock;
 
-            end if;
-         end Process;
+   begin
+      B := B + 1;
+      L := L + 1;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
       begin
-         Iterate (Left);
+         Process (E);
       exception
          when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
+            L := L - 1;
+            B := B - 1;
             raise;
       end;
 
-      return (Controlled with Buckets, Length);
-
-   end Intersection;
+      L := L - 1;
+      B := B - 1;
+   end Query_Element;
 
+   ----------
+   -- Read --
+   ----------
 
-   procedure Difference (Target : in out Set;
-                         Source : in     Set) is
+   procedure Read
+     (Stream    : access Root_Stream_Type'Class;
+      Container : out Set)
+   is
+   begin
+      Read_Nodes (Stream, Container.HT);
+   end Read;
 
+   ---------------
+   -- Read_Node --
+   ---------------
 
-      Tgt_Node : Node_Access;
+   function Read_Node
+     (Stream : access Root_Stream_Type'Class) return Node_Access
+   is
+      X : Element_Access := new Element_Type'(Element_Type'Input (Stream));
 
    begin
+      return new Node_Type'(X, null);
+   exception
+      when others =>
+         Free_Element (X);
+         raise;
+   end Read_Node;
 
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
+   -------------
+   -- Replace --
+   -------------
 
-      if Source.Length = 0 then
-         return;
-      end if;
+   procedure Replace
+     (Container : in out Set;
+      New_Item  : Element_Type)
+   is
+      Node : constant Node_Access :=
+               Element_Keys.Find (Container.HT, New_Item);
 
-      --  TODO: As I noted above, this can be
-      --  written in terms of a loop instead as
-      --  active-iterator style, sort of like a
-      --  passive iterator.
+      X : Element_Access;
 
-      Tgt_Node := HT_Ops.First (Target);
+   begin
+      if Node = null then
+         raise Constraint_Error;
+      end if;
 
-      while Tgt_Node /= null loop
+      if Container.HT.Lock > 0 then
+         raise Program_Error;
+      end if;
 
-         if Is_In (Source, Tgt_Node) then
+      X := Node.Element;
 
-            declare
-               X : Node_Access := Tgt_Node;
-            begin
-               Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
-               HT_Ops.Delete_Node_Sans_Free (Target, X);
-               Free (X);
-            end;
+      Node.Element := new Element_Type'(New_Item);
 
-         else
+      Free_Element (X);
+   end Replace;
 
-            Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
+   ---------------------
+   -- Replace_Element --
+   ---------------------
+
+   procedure Replace_Element
+     (HT      : in out Hash_Table_Type;
+      Node    : Node_Access;
+      Element : Element_Type)
+   is
+   begin
+      if Equivalent_Elements (Node.Element.all, Element) then
+         pragma Assert (Hash (Node.Element.all) = Hash (Element));
 
+         if HT.Lock > 0 then
+            raise Program_Error;
          end if;
 
-      end loop;
+         declare
+            X : Element_Access := Node.Element;
+         begin
+            Node.Element := new Element_Type'(Element);  --  OK if fails
+            Free_Element (X);
+         end;
 
-   end Difference;
+         return;
+      end if;
 
+      if HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
+      HT_Ops.Delete_Node_Sans_Free (HT, Node);
 
-   function Difference (Left, Right : Set) return Set is
+      Insert_New_Element : declare
+         function New_Node (Next : Node_Access) return Node_Access;
+         pragma Inline (New_Node);
 
-      Buckets : HT_Types.Buckets_Access;
-      Length  : Count_Type;
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (New_Node);
 
-   begin
+         ------------------------
+         -- Insert_New_Element --
+         ------------------------
 
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
+         function New_Node (Next : Node_Access) return Node_Access is
+         begin
+            Node.Element := new Element_Type'(Element);  -- OK if fails
+            Node.Next := Next;
+            return Node;
+         end New_Node;
 
-      if Left.Length = 0 then
-         return Empty_Set;
-      end if;
+         Result   : Node_Access;
+         Inserted : Boolean;
 
-      if Right.Length = 0 then
-         return Left;
-      end if;
+         X : Element_Access := Node.Element;
+
+      --  Start of processing for Insert_New_Element
 
-      declare
-         Size : constant Hash_Type := Prime_Numbers.To_Prime (Left.Length);
       begin
-         Buckets := new Buckets_Type (0 .. Size - 1);
-      end;
+         Attempt_Insert : begin
+            Insert
+              (HT       => HT,
+               Key      => Element,
+               Node     => Result,
+               Inserted => Inserted);
+         exception
+            when others =>
+               Inserted := False;  -- Assignment failed
+         end Attempt_Insert;
 
-      Length := 0;
+         if Inserted then
+            pragma Assert (Result = Node);
+            Free_Element (X);  -- Just propagate if fails
+            return;
+         end if;
+      end Insert_New_Element;
 
+      Reinsert_Old_Element :
       declare
-         procedure Process (L_Node : Node_Access);
+         function New_Node (Next : Node_Access) return Node_Access;
+         pragma Inline (New_Node);
 
-         procedure Process (L_Node : Node_Access) is
-         begin
-            if not Is_In (Right, L_Node) then
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (New_Node);
 
-               declare
-                  I : constant Hash_Type :=
-                    Hash (L_Node.Element.all) mod Buckets'Length;
-               begin
-                  Buckets (I) := new Node_Type'(L_Node.Element, Buckets (I));
-               end;
+         --------------
+         -- New_Node --
+         --------------
 
-               Length := Length + 1;
+         function New_Node (Next : Node_Access) return Node_Access is
+         begin
+            Node.Next := Next;
+            return Node;
+         end New_Node;
 
-            end if;
-         end Process;
+         Result   : Node_Access;
+         Inserted : Boolean;
+
+      --  Start of processing for Reinsert_Old_Element
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
       begin
-         Iterate (Left);
+         Insert
+           (HT       => HT,
+            Key      => Node.Element.all,
+            Node     => Result,
+            Inserted => Inserted);
       exception
          when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
-            raise;
-      end;
+            null;
+      end Reinsert_Old_Element;
 
-      return (Controlled with Buckets, Length);
+      raise Program_Error;
+   end Replace_Element;
 
-   end Difference;
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type)
+   is
+      HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
+
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
 
+      if Position.Container /= Set_Access'(Container'Unrestricted_Access) then
+         raise Program_Error;
+      end if;
+
+      Replace_Element (HT, Position.Node, By);
+   end Replace_Element;
+
+   ----------------------
+   -- Reserve_Capacity --
+   ----------------------
+
+   procedure Reserve_Capacity
+     (Container : in out Set;
+      Capacity  : Count_Type)
+   is
+   begin
+      HT_Ops.Reserve_Capacity (Container.HT, Capacity);
+   end Reserve_Capacity;
 
+   --------------
+   -- Set_Next --
+   --------------
 
-   procedure Symmetric_Difference (Target : in out Set;
-                                   Source : in     Set) is
+   procedure Set_Next (Node : Node_Access; Next : Node_Access) is
    begin
+      Node.Next := Next;
+   end Set_Next;
 
+   --------------------------
+   -- Symmetric_Difference --
+   --------------------------
+
+   procedure Symmetric_Difference
+     (Target : in out Set;
+      Source : Set)
+   is
+   begin
       if Target'Address = Source'Address then
          Clear (Target);
          return;
       end if;
 
-      HT_Ops.Ensure_Capacity (Target, Target.Length + Source.Length);
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
-      if Target.Length = 0 then
+      declare
+         N : constant Count_Type := Target.Length + Source.Length;
+      begin
+         if N > HT_Ops.Capacity (Target.HT) then
+            HT_Ops.Reserve_Capacity (Target.HT, N);
+         end if;
+      end;
 
-         declare
+      if Target.Length = 0 then
+         Iterate_Source_When_Empty_Target : declare
             procedure Process (Src_Node : Node_Access);
 
+            procedure Iterate is
+               new HT_Ops.Generic_Iteration (Process);
+
+            -------------
+            -- Process --
+            -------------
+
             procedure Process (Src_Node : Node_Access) is
                E : Element_Type renames Src_Node.Element.all;
-               B : Buckets_Type renames Target.Buckets.all;
-               I : constant Hash_Type := Hash (E) mod B'Length;
-               N : Count_Type renames Target.Length;
+               B : Buckets_Type renames Target.HT.Buckets.all;
+               J : constant Hash_Type := Hash (E) mod B'Length;
+               N : Count_Type renames Target.HT.Length;
+
             begin
                declare
                   X : Element_Access := new Element_Type'(E);
                begin
-                  B (I) := new Node_Type'(X, B (I));
+                  B (J) := new Node_Type'(X, B (J));
                exception
                   when others =>
                      Free_Element (X);
@@ -897,29 +1233,35 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
                N := N + 1;
             end Process;
 
-            procedure Iterate is
-               new HT_Ops.Generic_Iteration (Process);
+         --  Start of processing for Iterate_Source_When_Empty_Target
+
          begin
-            Iterate (Source);
-         end;
+            Iterate (Source.HT);
+         end Iterate_Source_When_Empty_Target;
 
       else
-
-         declare
+         Iterate_Source : declare
             procedure Process (Src_Node : Node_Access);
 
+            procedure Iterate is
+               new HT_Ops.Generic_Iteration (Process);
+
+            -------------
+            -- Process --
+            -------------
+
             procedure Process (Src_Node : Node_Access) is
                E : Element_Type renames Src_Node.Element.all;
-               B : Buckets_Type renames Target.Buckets.all;
-               I : constant Hash_Type := Hash (E) mod B'Length;
-               N : Count_Type renames Target.Length;
-            begin
-               if B (I) = null then
+               B : Buckets_Type renames Target.HT.Buckets.all;
+               J : constant Hash_Type := Hash (E) mod B'Length;
+               N : Count_Type renames Target.HT.Length;
 
+            begin
+               if B (J) = null then
                   declare
                      X : Element_Access := new Element_Type'(E);
                   begin
-                     B (I) := new Node_Type'(X, null);
+                     B (J) := new Node_Type'(X, null);
                   exception
                      when others =>
                         Free_Element (X);
@@ -928,24 +1270,23 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
 
                   N := N + 1;
 
-               elsif Equivalent_Keys (E, B (I).Element.all) then
-
+               elsif Equivalent_Elements (E, B (J).Element.all) then
                   declare
-                     X : Node_Access := B (I);
+                     X : Node_Access := B (J);
                   begin
-                     B (I) := B (I).Next;
+                     B (J) := B (J).Next;
                      N := N - 1;
                      Free (X);
                   end;
 
                else
-
                   declare
-                     Prev : Node_Access := B (I);
+                     Prev : Node_Access := B (J);
                      Curr : Node_Access := Prev.Next;
+
                   begin
                      while Curr /= null loop
-                        if Equivalent_Keys (E, Curr.Element.all) then
+                        if Equivalent_Elements (E, Curr.Element.all) then
                            Prev.Next := Curr.Next;
                            N := N - 1;
                            Free (Curr);
@@ -959,7 +1300,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
                      declare
                         X : Element_Access := new Element_Type'(E);
                      begin
-                        B (I) := new Node_Type'(X, B (I));
+                        B (J) := new Node_Type'(X, B (J));
                      exception
                         when others =>
                            Free_Element (X);
@@ -968,28 +1309,22 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
 
                      N := N + 1;
                   end;
-
                end if;
             end Process;
 
-            procedure Iterate is
-               new HT_Ops.Generic_Iteration (Process);
-         begin
-            Iterate (Source);
-         end;
+         --  Start of processing for Iterate_Source
 
+         begin
+            Iterate (Source.HT);
+         end Iterate_Source;
       end if;
-
    end Symmetric_Difference;
 
-
    function Symmetric_Difference (Left, Right : Set) return Set is
-
       Buckets : HT_Types.Buckets_Access;
       Length  : Count_Type;
 
    begin
-
       if Left'Address = Right'Address then
          return Empty_Set;
       end if;
@@ -1004,28 +1339,35 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
 
       declare
          Size : constant Hash_Type :=
-           Prime_Numbers.To_Prime (Left.Length + Right.Length);
+                  Prime_Numbers.To_Prime (Left.Length + Right.Length);
       begin
          Buckets := new Buckets_Type (0 .. Size - 1);
       end;
 
       Length := 0;
 
-      declare
+      Iterate_Left : declare
          procedure Process (L_Node : Node_Access);
 
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
+
+         -------------
+         -- Process --
+         -------------
+
          procedure Process (L_Node : Node_Access) is
          begin
-            if not Is_In (Right, L_Node) then
+            if not Is_In (Right.HT, L_Node) then
                declare
                   E : Element_Type renames L_Node.Element.all;
-                  I : constant Hash_Type := Hash (E) mod Buckets'Length;
-               begin
+                  J : constant Hash_Type := Hash (E) mod Buckets'Length;
 
+               begin
                   declare
                      X : Element_Access := new Element_Type'(E);
                   begin
-                     Buckets (I) := new Node_Type'(X, Buckets (I));
+                     Buckets (J) := new Node_Type'(X, Buckets (J));
                   exception
                      when others =>
                         Free_Element (X);
@@ -1037,31 +1379,38 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
             end if;
          end Process;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
+      --  Start of processing for Iterate_Left
+
       begin
-         Iterate (Left);
+         Iterate (Left.HT);
       exception
          when others =>
             HT_Ops.Free_Hash_Table (Buckets);
             raise;
-      end;
+      end Iterate_Left;
 
-      declare
+      Iterate_Right : declare
          procedure Process (R_Node : Node_Access);
 
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
+
+         -------------
+         -- Process --
+         -------------
+
          procedure Process (R_Node : Node_Access) is
          begin
-            if not Is_In (Left, R_Node) then
+            if not Is_In (Left.HT, R_Node) then
                declare
                   E : Element_Type renames R_Node.Element.all;
-                  I : constant Hash_Type := Hash (E) mod Buckets'Length;
-               begin
+                  J : constant Hash_Type := Hash (E) mod Buckets'Length;
 
+               begin
                   declare
                      X : Element_Access := new Element_Type'(E);
                   begin
-                     Buckets (I) := new Node_Type'(X, Buckets (I));
+                     Buckets (J) := new Node_Type'(X, Buckets (J));
                   exception
                      when others =>
                         Free_Element (X);
@@ -1069,406 +1418,396 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
                   end;
 
                   Length := Length + 1;
-
                end;
             end if;
          end Process;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
+      --  Start of processing for Iterate_Right
+
       begin
-         Iterate (Right);
+         Iterate (Right.HT);
       exception
          when others =>
             HT_Ops.Free_Hash_Table (Buckets);
             raise;
-      end;
-
-      return (Controlled with Buckets, Length);
+      end Iterate_Right;
 
+      return (Controlled with HT => (Buckets, Length, 0, 0));
    end Symmetric_Difference;
 
+   -----------
+   -- Union --
+   -----------
 
-   function Is_Subset (Subset : Set;
-                       Of_Set : Set) return Boolean is
-
-      Subset_Node : Node_Access;
-
-   begin
-
-      if Subset'Address = Of_Set'Address then
-         return True;
-      end if;
-
-      if Subset.Length > Of_Set.Length then
-         return False;
-      end if;
-
-      --  TODO: rewrite this to loop in the
-      --  style of a passive iterator.
-
-      Subset_Node := HT_Ops.First (Subset);
-
-      while Subset_Node /= null loop
-         if not Is_In (Of_Set, Subset_Node) then
-            return False;
-         end if;
-
-         Subset_Node := HT_Ops.Next (Subset, Subset_Node);
-      end loop;
-
-      return True;
-
-   end Is_Subset;
-
-
-   function Overlap (Left, Right : Set) return Boolean is
-
-      Left_Node : Node_Access;
-
-   begin
-
-      if Right.Length = 0 then
-         return False;
-      end if;
-
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
-      Left_Node := HT_Ops.First (Left);
-
-      while Left_Node /= null loop
-         if Is_In (Right, Left_Node) then
-            return True;
-         end if;
-
-         Left_Node := HT_Ops.Next (Left, Left_Node);
-      end loop;
-
-      return False;
-
-   end Overlap;
-
-
-   function Find (Container : Set;
-                  Item      : Element_Type) return Cursor is
-
-      Node : constant Node_Access := Element_Keys.Find (Container, Item);
-
-   begin
+   procedure Union
+     (Target : in out Set;
+      Source : Set)
+   is
+      procedure Process (Src_Node : Node_Access);
 
-      if Node = null then
-         return No_Element;
-      end if;
+      procedure Iterate is
+         new HT_Ops.Generic_Iteration (Process);
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      -------------
+      -- Process --
+      -------------
 
-   end Find;
+      procedure Process (Src_Node : Node_Access) is
+         Src : Element_Type renames Src_Node.Element.all;
 
+         function New_Node (Next : Node_Access) return Node_Access;
+         pragma Inline (New_Node);
 
-   function Contains (Container : Set;
-                      Item      : Element_Type) return Boolean is
-   begin
-      return Find (Container, Item) /= No_Element;
-   end Contains;
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (New_Node);
 
+         --------------
+         -- New_Node --
+         --------------
 
+         function New_Node (Next : Node_Access) return Node_Access is
+            Tgt : Element_Access := new Element_Type'(Src);
 
-   function First (Container : Set) return Cursor is
-      Node : constant Node_Access := HT_Ops.First (Container);
-   begin
-      if Node = null then
-         return No_Element;
-      end if;
+         begin
+            return new Node_Type'(Tgt, Next);
+         exception
+            when others =>
+               Free_Element (Tgt);
+               raise;
+         end New_Node;
 
-      return Cursor'(Container'Unchecked_Access, Node);
-   end First;
+         Tgt_Node : Node_Access;
+         Success  : Boolean;
 
+      --  Start of processing for Process
 
---     function First_Element (Container : Set) return Element_Type is
---        Node : constant Node_Access := HT_Ops.First (Container);
---     begin
---        return Node.Element;
---     end First_Element;
+      begin
+         Insert (Target.HT, Src, Tgt_Node, Success);
+      end Process;
 
+   --  Start of processing for Union
 
-   function Next (Position : Cursor) return Cursor is
    begin
-      if Position.Container = null
-        or else Position.Node = null
-      then
-         return No_Element;
+      if Target'Address = Source'Address then
+         return;
+      end if;
+
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
       end if;
 
       declare
-         S : Set renames Position.Container.all;
-         Node : constant Node_Access := HT_Ops.Next (S, Position.Node);
+         N : constant Count_Type := Target.Length + Source.Length;
       begin
-         if Node = null then
-            return No_Element;
+         if N > HT_Ops.Capacity (Target.HT) then
+            HT_Ops.Reserve_Capacity (Target.HT, N);
          end if;
-
-         return Cursor'(Position.Container, Node);
       end;
-   end Next;
-
 
-   procedure Next (Position : in out Cursor) is
-   begin
-      Position := Next (Position);
-   end Next;
+      Iterate (Source.HT);
+   end Union;
 
+   function Union (Left, Right : Set) return Set is
+      Buckets : HT_Types.Buckets_Access;
+      Length  : Count_Type;
 
-   function Has_Element (Position : Cursor) return Boolean is
    begin
-      if Position.Container = null then
-         return False;
+      if Left'Address = Right'Address then
+         return Left;
       end if;
 
-      if Position.Node = null then
-         return False;
+      if Right.Length = 0 then
+         return Left;
       end if;
 
-      return True;
-   end Has_Element;
-
+      if Left.Length = 0 then
+         return Right;
+      end if;
 
-   function Equivalent_Keys (Left, Right : Cursor)
-     return Boolean is
-   begin
-      return Equivalent_Keys (Left.Node.Element.all, Right.Node.Element.all);
-   end Equivalent_Keys;
+      declare
+         Size : constant Hash_Type :=
+                  Prime_Numbers.To_Prime (Left.Length + Right.Length);
+      begin
+         Buckets := new Buckets_Type (0 .. Size - 1);
+      end;
 
+      Iterate_Left : declare
+         procedure Process (L_Node : Node_Access);
 
-   function Equivalent_Keys (Left  : Cursor;
-                             Right : Element_Type)
-    return Boolean is
-   begin
-      return Equivalent_Keys (Left.Node.Element.all, Right);
-   end Equivalent_Keys;
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
 
+         -------------
+         -- Process --
+         -------------
 
-   function Equivalent_Keys (Left  : Element_Type;
-                             Right : Cursor)
-    return Boolean is
-   begin
-      return Equivalent_Keys (Left, Right.Node.Element.all);
-   end Equivalent_Keys;
+         procedure Process (L_Node : Node_Access) is
+            J : constant Hash_Type :=
+                  Hash (L_Node.Element.all) mod Buckets'Length;
 
+            Bucket : Node_Access renames Buckets (J);
 
-   procedure Iterate
-     (Container : in Set;
-      Process   : not null access procedure (Position : in Cursor)) is
+         begin
+            Bucket := new Node_Type'(L_Node.Element, Bucket);
+         end Process;
 
-      procedure Process_Node (Node : in Node_Access);
-      pragma Inline (Process_Node);
+      --  Start of processing for Process
 
-      procedure Process_Node (Node : in Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
-      end Process_Node;
-
-      procedure Iterate is
-         new HT_Ops.Generic_Iteration (Process_Node);
-   begin
-      Iterate (Container);
-   end Iterate;
+         Iterate (Left.HT);
+      exception
+         when others =>
+            HT_Ops.Free_Hash_Table (Buckets);
+            raise;
+      end Iterate_Left;
 
+      Length := Left.Length;
 
-   function Capacity (Container : Set) return Count_Type
-     renames HT_Ops.Capacity;
+      Iterate_Right : declare
+         procedure Process (Src_Node : Node_Access);
 
-   procedure Reserve_Capacity
-     (Container : in out Set;
-      Capacity  : in     Count_Type)
-     renames HT_Ops.Ensure_Capacity;
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
 
+         -------------
+         -- Process --
+         -------------
 
-   procedure Write_Node
-     (Stream : access Root_Stream_Type'Class;
-      Node   : in     Node_Access);
-   pragma Inline (Write_Node);
+         procedure Process (Src_Node : Node_Access) is
+            Src : Element_Type renames Src_Node.Element.all;
+            Idx : constant Hash_Type := Hash (Src) mod Buckets'Length;
 
-   procedure Write_Node
-     (Stream : access Root_Stream_Type'Class;
-      Node   : in     Node_Access) is
-   begin
-      Element_Type'Output (Stream, Node.Element.all);
-   end Write_Node;
+            Tgt_Node : Node_Access := Buckets (Idx);
 
-   procedure Write_Nodes is
-      new HT_Ops.Generic_Write (Write_Node);
+         begin
+            while Tgt_Node /= null loop
+               if Equivalent_Elements (Src, Tgt_Node.Element.all) then
+                  return;
+               end if;
+               Tgt_Node := Next (Tgt_Node);
+            end loop;
 
-   procedure Write
-     (Stream    : access Root_Stream_Type'Class;
-      Container : in     Set) renames Write_Nodes;
+            declare
+               Tgt : Element_Access := new Element_Type'(Src);
+            begin
+               Buckets (Idx) := new Node_Type'(Tgt, Buckets (Idx));
+            exception
+               when others =>
+                  Free_Element (Tgt);
+                  raise;
+            end;
 
+            Length := Length + 1;
+         end Process;
 
-   function Read_Node (Stream : access Root_Stream_Type'Class)
-     return Node_Access;
-   pragma Inline (Read_Node);
+      --  Start of processing for Iterate_Right
 
-   function Read_Node (Stream : access Root_Stream_Type'Class)
-     return Node_Access is
+      begin
+         Iterate (Right.HT);
+      exception
+         when others =>
+            HT_Ops.Free_Hash_Table (Buckets);
+            raise;
+      end Iterate_Right;
 
-      X : Element_Access := new Element_Type'(Element_Type'Input (Stream));
-   begin
-      return new Node_Type'(X, null);
-   exception
-      when others =>
-         Free_Element (X);
-         raise;
-   end Read_Node;
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Union;
 
-   procedure Read_Nodes is
-      new HT_Ops.Generic_Read (Read_Node);
+   -----------
+   -- Write --
+   -----------
 
-   procedure Read
+   procedure Write
      (Stream    : access Root_Stream_Type'Class;
-      Container :    out Set) renames Read_Nodes;
+      Container : Set)
+   is
+   begin
+      Write_Nodes (Stream, Container.HT);
+   end Write;
 
+   ----------------
+   -- Write_Node --
+   ----------------
 
-   package body Generic_Keys is
+   procedure Write_Node
+     (Stream : access Root_Stream_Type'Class;
+      Node   : Node_Access)
+   is
+   begin
+      Element_Type'Output (Stream, Node.Element.all);
+   end Write_Node;
 
-      function Equivalent_Keys (Left  : Cursor;
-                                Right : Key_Type)
-        return Boolean is
-      begin
-         return Equivalent_Keys (Right, Left.Node.Element.all);
-      end Equivalent_Keys;
+   package body Generic_Keys is
 
-      function Equivalent_Keys (Left  : Key_Type;
-                                Right : Cursor)
-        return Boolean is
-      begin
-         return Equivalent_Keys (Left, Right.Node.Element.all);
-      end Equivalent_Keys;
+      -----------------------
+      -- Local Subprograms --
+      -----------------------
 
-      function Equivalent_Keys
+      function Equivalent_Key_Node
         (Key  : Key_Type;
          Node : Node_Access) return Boolean;
-      pragma Inline (Equivalent_Keys);
+      pragma Inline (Equivalent_Key_Node);
 
-      function Equivalent_Keys
-        (Key  : Key_Type;
-         Node : Node_Access) return Boolean is
-      begin
-         return Equivalent_Keys (Key, Node.Element.all);
-      end Equivalent_Keys;
+      --------------------------
+      -- Local Instantiations --
+      --------------------------
 
       package Key_Keys is
          new Hash_Tables.Generic_Keys
           (HT_Types  => HT_Types,
-           HT_Type   => Set,
-           Null_Node => null,
            Next      => Next,
            Set_Next  => Set_Next,
            Key_Type  => Key_Type,
            Hash      => Hash,
-           Equivalent_Keys => Equivalent_Keys);
+           Equivalent_Keys => Equivalent_Key_Node);
 
+      --------------
+      -- Contains --
+      --------------
 
-      function Find (Container : Set;
-                     Key       : Key_Type)
-         return Cursor is
-
-         Node : constant Node_Access :=
-           Key_Keys.Find (Container, Key);
-
+      function Contains
+        (Container : Set;
+         Key       : Key_Type) return Boolean
+      is
       begin
+         return Find (Container, Key) /= No_Element;
+      end Contains;
 
-         if Node = null then
-            return No_Element;
-         end if;
-
-         return Cursor'(Container'Unchecked_Access, Node);
-
-      end Find;
+      ------------
+      -- Delete --
+      ------------
 
+      procedure Delete
+        (Container : in out Set;
+         Key       : Key_Type)
+      is
+         X : Node_Access;
 
-      function Contains (Container : Set;
-                         Key       : Key_Type) return Boolean is
       begin
-         return Find (Container, Key) /= No_Element;
-      end Contains;
+         Key_Keys.Delete_Key_Sans_Free (Container.HT, Key, X);
+
+         if X = null then
+            raise Constraint_Error;
+         end if;
 
+         Free (X);
+      end Delete;
 
-      function Element (Container : Set;
-                        Key       : Key_Type)
-        return Element_Type is
+      -------------
+      -- Element --
+      -------------
 
-         Node : constant Node_Access := Key_Keys.Find (Container, Key);
+      function Element
+        (Container : Set;
+         Key       : Key_Type) return Element_Type
+      is
+         Node : constant Node_Access := Key_Keys.Find (Container.HT, Key);
       begin
          return Node.Element.all;
       end Element;
 
+      -------------------------
+      -- Equivalent_Key_Node --
+      -------------------------
 
-      function Key (Position : Cursor) return Key_Type is
+      function Equivalent_Key_Node
+        (Key  : Key_Type;
+         Node : Node_Access) return Boolean is
       begin
-         return Key (Position.Node.Element.all);
-      end Key;
-
-
---  TODO:
---        procedure Replace (Container : in out Set;
---                           Key       : in     Key_Type;
---                           New_Item  : in     Element_Type) is
-
---           Node : constant Node_Access :=
---             Key_Keys.Find (Container, Key);
-
---        begin
-
---           if Node = null then
---              raise Constraint_Error;
---           end if;
+         return Equivalent_Keys (Key, Node.Element.all);
+      end Equivalent_Key_Node;
 
---           Replace_Element (Container, Node, New_Item);
+      ---------------------
+      -- Equivalent_Keys --
+      ---------------------
 
---        end Replace;
+      function Equivalent_Keys
+        (Left  : Cursor;
+         Right : Key_Type) return Boolean
+      is
+      begin
+         return Equivalent_Keys (Right, Left.Node.Element.all);
+      end Equivalent_Keys;
 
+      function Equivalent_Keys
+        (Left  : Key_Type;
+         Right : Cursor) return Boolean
+      is
+      begin
+         return Equivalent_Keys (Left, Right.Node.Element.all);
+      end Equivalent_Keys;
 
-      procedure Delete (Container : in out Set;
-                        Key       : in     Key_Type) is
+      -------------
+      -- Exclude --
+      -------------
 
+      procedure Exclude
+        (Container : in out Set;
+         Key       : Key_Type)
+      is
          X : Node_Access;
-
       begin
+         Key_Keys.Delete_Key_Sans_Free (Container.HT, Key, X);
+         Free (X);
+      end Exclude;
 
-         Key_Keys.Delete_Key_Sans_Free (Container, Key, X);
+      ----------
+      -- Find --
+      ----------
 
-         if X = null then
-            raise Constraint_Error;
+      function Find
+        (Container : Set;
+         Key       : Key_Type) return Cursor
+      is
+         Node : constant Node_Access := Key_Keys.Find (Container.HT, Key);
+
+      begin
+         if Node = null then
+            return No_Element;
          end if;
 
-         Free (X);
+         return Cursor'(Container'Unrestricted_Access, Node);
+      end Find;
 
-      end Delete;
+      ---------
+      -- Key --
+      ---------
 
+      function Key (Position : Cursor) return Key_Type is
+      begin
+         return Key (Position.Node.Element.all);
+      end Key;
 
-      procedure Exclude (Container : in out Set;
-                         Key       : in     Key_Type) is
+      -------------
+      -- Replace --
+      -------------
 
-         X : Node_Access;
+      procedure Replace
+        (Container : in out Set;
+         Key       : Key_Type;
+         New_Item  : Element_Type)
+      is
+         Node : constant Node_Access :=
+                  Key_Keys.Find (Container.HT, Key);
 
       begin
+         if Node = null then
+            raise Constraint_Error;
+         end if;
 
-         Key_Keys.Delete_Key_Sans_Free (Container, Key, X);
-         Free (X);
-
-      end Exclude;
-
+         Replace_Element (Container.HT, Node, New_Item);
+      end Replace;
 
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : in     Cursor;
          Process   : not null access
-           procedure (Element : in out Element_Type)) is
+           procedure (Element : in out Element_Type))
+      is
+         HT : Hash_Table_Type renames Container.HT;
 
       begin
-
-         if Position.Container = null then
+         if Position.Node = null then
             raise Constraint_Error;
          end if;
 
@@ -1477,55 +1816,44 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
          end if;
 
          declare
-            Old_Key : Key_Type renames Key (Position.Node.Element.all);
-         begin
-            Process (Position.Node.Element.all);
-
-            if Equivalent_Keys (Old_Key, Position.Node.Element.all) then
-               return;
-            end if;
-         end;
-
-         declare
-            function New_Node (Next : Node_Access) return Node_Access;
-            pragma Inline (New_Node);
-
-            function New_Node (Next : Node_Access) return Node_Access is
-            begin
-               Position.Node.Next := Next;
-               return Position.Node;
-            end New_Node;
+            E : Element_Type renames Position.Node.Element.all;
+            K : Key_Type renames Key (E);
 
-            procedure Insert is
-               new Key_Keys.Generic_Conditional_Insert (New_Node);
+            B : Natural renames HT.Busy;
+            L : Natural renames HT.Lock;
 
-            Result  : Node_Access;
-            Success : Boolean;
          begin
-            HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
+            B := B + 1;
+            L := L + 1;
 
-            Insert
-              (HT      => Container,
-               Key     => Key (Position.Node.Element.all),
-               Node    => Result,
-               Success => Success);
+            begin
+               Process (E);
+            exception
+               when others =>
+                  L := L - 1;
+                  B := B - 1;
+                  raise;
+            end;
 
-            if not Success then
-               declare
-                  X : Node_Access := Position.Node;
-               begin
-                  Free (X);
-               end;
+            L := L - 1;
+            B := B - 1;
 
-               raise Program_Error;
+            if Equivalent_Keys (K, E) then
+               pragma Assert (Hash (K) = Hash (E));
+               return;
             end if;
+         end;
 
-            pragma Assert (Result = Position.Node);
+         declare
+            X : Node_Access := Position.Node;
+         begin
+            HT_Ops.Delete_Node_Sans_Free (HT, X);
+            Free (X);
          end;
 
-      end Checked_Update_Element;
+         raise Program_Error;
+      end Update_Element_Preserving_Key;
 
    end Generic_Keys;
 
 end Ada.Containers.Indefinite_Hashed_Sets;
-
index 1886d3d7dec2f50bc168441c15855837288cf961..a145bd048a5c245e68e6d3dd2cba3b7247a6314f 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_ORDERED_MAPS                  --
+--                      A D A . C O N T A I N E R S .                       --
+--             I N D E F I N I T E _ O R D E R E D _ M A P S                --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -41,24 +42,8 @@ pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
 with Ada.Containers.Red_Black_Trees.Generic_Keys;
 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
 
-with System;  use type System.Address;
-
 package body Ada.Containers.Indefinite_Ordered_Maps is
 
-   use Red_Black_Trees;
-
-   type Key_Access is access Key_Type;
-   type Element_Access is access Element_Type;
-
-   type Node_Type is limited record
-      Parent  : Node_Access;
-      Left    : Node_Access;
-      Right   : Node_Access;
-      Color   : Red_Black_Trees.Color_Type := Red;
-      Key     : Key_Access;
-      Element : Element_Access;
-   end record;
-
    -----------------------------
    -- Node Access Subprograms --
    -----------------------------
@@ -97,10 +82,6 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    function Copy_Node (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access;
-
-   procedure Delete_Tree (X : in out Node_Access);
-
    procedure Free (X : in out Node_Access);
 
    function Is_Equal_Node_Node
@@ -122,9 +103,13 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    --------------------------
 
    package Tree_Operations is
-     new Red_Black_Trees.Generic_Operations
-       (Tree_Types => Tree_Types,
-        Null_Node  => Node_Access'(null));
+     new Red_Black_Trees.Generic_Operations (Tree_Types);
+
+   procedure Delete_Tree is
+      new Tree_Operations.Generic_Delete_Tree (Free);
+
+   function Copy_Tree is
+      new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
 
    use Tree_Operations;
 
@@ -169,10 +154,6 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
 
    function "=" (Left, Right : Map) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
       return Is_Equal (Left.Tree, Right.Tree);
    end "=";
 
@@ -199,24 +180,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Map) is
-      Tree : Tree_Type renames Container.Tree;
-
-      N : constant Count_Type := Tree.Length;
-      X : constant Node_Access := Tree.Root;
+   procedure Adjust is
+      new Tree_Operations.Generic_Adjust (Copy_Tree);
 
+   procedure Adjust (Container : in out Map) is
    begin
-      if N = 0 then
-         pragma Assert (X = null);
-         return;
-      end if;
-
-      Tree := (Length => 0, others => null);
-
-      Tree.Root := Copy_Tree (X);
-      Tree.First := Min (Tree.Root);
-      Tree.Last := Max (Tree.Root);
-      Tree.Length := N;
+      Adjust (Container.Tree);
    end Adjust;
 
    -------------
@@ -229,7 +198,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       if Node = null then
          return No_Element;
       else
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end if;
    end Ceiling;
 
@@ -237,12 +206,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    -- Clear --
    -----------
 
+   procedure Clear is
+      new Tree_Operations.Generic_Clear (Delete_Tree);
+
    procedure Clear (Container : in out Map) is
-      Tree : Tree_Type renames Container.Tree;
-      Root : Node_Access := Tree.Root;
    begin
-      Tree := (Length => 0, others => null);
-      Delete_Tree (Root);
+      Clear (Container.Tree);
    end Clear;
 
    -----------
@@ -268,59 +237,23 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    ---------------
 
    function Copy_Node (Source : Node_Access) return Node_Access is
-      Target : constant Node_Access :=
-         new Node_Type'(Parent  => null,
-                        Left    => null,
-                        Right   => null,
-                        Color   => Source.Color,
-                        Key     => Source.Key,
-                        Element => Source.Element);
-   begin
-      return Target;
-   end Copy_Node;
-
-   ---------------
-   -- Copy_Tree --
-   ---------------
-
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access is
-      Target_Root : Node_Access := Copy_Node (Source_Root);
-
-      P, X : Node_Access;
-
+      K : Key_Access := new Key_Type'(Source.Key.all);
+      E : Element_Access;
    begin
-      if Source_Root.Right /= null then
-         Target_Root.Right := Copy_Tree (Source_Root.Right);
-         Target_Root.Right.Parent := Target_Root;
-      end if;
-
-      P := Target_Root;
-      X := Source_Root.Left;
-      while X /= null loop
-         declare
-            Y : Node_Access := Copy_Node (X);
-
-         begin
-            P.Left := Y;
-            Y.Parent := P;
-
-            if X.Right /= null then
-               Y.Right := Copy_Tree (X.Right);
-               Y.Right.Parent := Y;
-            end if;
-
-            P := Y;
-            X := X.Left;
-         end;
-      end loop;
-
-      return Target_Root;
-
+      E := new Element_Type'(Source.Element.all);
+
+      return new Node_Type'(Parent  => null,
+                            Left    => null,
+                            Right   => null,
+                            Color   => Source.Color,
+                            Key     => K,
+                            Element => E);
    exception
       when others =>
-         Delete_Tree (Target_Root);
+         Free_Key (K);
+         Free_Element (E);
          raise;
-   end Copy_Tree;
+   end Copy_Node;
 
    ------------
    -- Delete --
@@ -331,11 +264,11 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       Position  : in out Cursor)
    is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container /= Map_Access'(Container'Unchecked_Access) then
+      if Position.Container /= Map_Access'(Container'Unrestricted_Access) then
          raise Program_Error;
       end if;
 
@@ -361,9 +294,12 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    ------------------
 
    procedure Delete_First (Container : in out Map) is
-      Position : Cursor := First (Container);
+      X : Node_Access := Container.Tree.First;
    begin
-      Delete (Container, Position);
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
+         Free (X);
+      end if;
    end Delete_First;
 
    -----------------
@@ -371,26 +307,13 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    -----------------
 
    procedure Delete_Last (Container : in out Map) is
-      Position : Cursor := Last (Container);
-   begin
-      Delete (Container, Position);
-   end Delete_Last;
-
-   -----------------
-   -- Delete_Tree --
-   -----------------
-
-   procedure Delete_Tree (X : in out Node_Access) is
-      Y : Node_Access;
+      X : Node_Access := Container.Tree.Last;
    begin
-      while X /= null loop
-         Y := X.Right;
-         Delete_Tree (Y);
-         Y := X.Left;
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
          Free (X);
-         X := Y;
-      end loop;
-   end Delete_Tree;
+      end if;
+   end Delete_Last;
 
    -------------
    -- Element --
@@ -431,7 +354,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       if Node = null then
          return No_Element;
       else
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end if;
    end Find;
 
@@ -444,7 +367,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       if Container.Tree.First = null then
          return No_Element;
       else
-         return Cursor'(Container'Unchecked_Access, Container.Tree.First);
+         return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
       end if;
    end First;
 
@@ -476,7 +399,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       if Node = null then
          return No_Element;
       else
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end if;
    end Floor;
 
@@ -488,11 +411,38 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       procedure Deallocate is
         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
    begin
-      if X /= null then
+      if X = null then
+         return;
+      end if;
+
+      begin
          Free_Key (X.Key);
+      exception
+         when others =>
+            X.Key := null;
+
+            begin
+               Free_Element (X.Element);
+            exception
+               when others =>
+                  X.Element := null;
+            end;
+
+            Deallocate (X);
+            raise;
+      end;
+
+      begin
          Free_Element (X.Element);
-         Deallocate (X);
-      end if;
+      exception
+         when others =>
+            X.Element := null;
+
+            Deallocate (X);
+            raise;
+      end;
+
+      Deallocate (X);
    end Free;
 
    -----------------
@@ -523,11 +473,22 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       Insert (Container, Key, New_Item, Position, Inserted);
 
       if not Inserted then
+         if Container.Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
+
          K := Position.Node.Key;
          E := Position.Node.Element;
 
          Position.Node.Key := new Key_Type'(Key);
-         Position.Node.Element := new Element_Type'(New_Item);
+
+         begin
+            Position.Node.Element := new Element_Type'(New_Item);
+         exception
+            when others =>
+               Free_Key (K);
+               raise;
+         end;
 
          Free_Key (K);
          Free_Element (E);
@@ -571,7 +532,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
 
             --  On exception, deallocate key and elem
 
-            Free (Node);
+            Free (Node);  --  Note that Free deallocates key and elem too
             raise;
       end New_Node;
 
@@ -584,7 +545,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
          Position.Node,
          Inserted);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    procedure Insert
@@ -620,7 +581,15 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    function Is_Equal_Node_Node
      (L, R : Node_Access) return Boolean is
    begin
-      return L.Element.all = R.Element.all;
+      if L.Key.all < R.Key.all then
+         return False;
+
+      elsif R.Key.all < L.Key.all then
+         return False;
+
+      else
+         return L.Element.all = R.Element.all;
+      end if;
    end Is_Equal_Node_Node;
 
    -------------------------
@@ -668,13 +637,25 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
+
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Iterate (Container.Tree);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ---------
@@ -695,7 +676,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
       if Container.Tree.Last = null then
          return No_Element;
       else
-         return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
+         return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
       end if;
    end Last;
 
@@ -739,12 +720,11 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    -- Move --
    ----------
 
+   procedure Move is
+      new Tree_Operations.Generic_Move (Clear);
+
    procedure Move (Target : in out Map; Source : in out Map) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Move (Target => Target.Tree, Source => Source.Tree);
    end Move;
 
@@ -816,10 +796,32 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
 
    procedure Query_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : Element_Type))
    is
+      K : Key_Type renames Position.Node.Key.all;
+      E : Element_Type renames Position.Node.Element.all;
+
+      T : Tree_Type renames Position.Container.Tree;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Key.all, Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -830,43 +832,35 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
      (Stream    : access Root_Stream_Type'Class;
       Container : out Map)
    is
-      N : Count_Type'Base;
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+      pragma Inline (Read_Node);
 
-      function New_Node return Node_Access;
-      pragma Inline (New_Node);
+      procedure Read is
+         new Tree_Operations.Generic_Read (Clear, Read_Node);
 
-      procedure Local_Read is new Tree_Operations.Generic_Read (New_Node);
+      ---------------
+      -- Read_Node --
+      ---------------
 
-      --------------
-      -- New_Node --
-      --------------
-
-      function New_Node return Node_Access is
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access
+      is
          Node : Node_Access := new Node_Type;
-
       begin
          Node.Key := new Key_Type'(Key_Type'Input (Stream));
          Node.Element := new Element_Type'(Element_Type'Input (Stream));
          return Node;
-
       exception
          when others =>
-
-            --  Deallocate key and elem too on exception
-
-            Free (Node);
+            Free (Node);  --  Note that Free deallocates key and elem too
             raise;
-      end New_Node;
+      end Read_Node;
 
    --  Start of processing for Read
 
    begin
-      Clear (Container);
-
-      Count_Type'Base'Read (Stream, N);
-      pragma Assert (N >= 0);
-
-      Local_Read (Container.Tree, N);
+      Read (Stream, Container.Tree);
    end Read;
 
    -------------
@@ -889,11 +883,22 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
          raise Constraint_Error;
       end if;
 
+      if Container.Tree.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       K := Node.Key;
       E := Node.Element;
 
       Node.Key := new Key_Type'(Key);
-      Node.Element := new Element_Type'(New_Item);
+
+      begin
+         Node.Element := new Element_Type'(New_Item);
+      exception
+         when others =>
+            Free_Key (K);
+            raise;
+      end;
 
       Free_Key (K);
       Free_Element (E);
@@ -906,6 +911,10 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
    procedure Replace_Element (Position : Cursor; By : Element_Type) is
       X : Element_Access := Position.Node.Element;
    begin
+      if Position.Container.Tree.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       Position.Node.Element := new Element_Type'(By);
       Free_Element (X);
    end Replace_Element;
@@ -930,13 +939,25 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (Container.Tree);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    -----------
@@ -990,10 +1011,32 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
 
    procedure Update_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : in out Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : in out Element_Type))
    is
+      K : Key_Type renames Position.Node.Key.all;
+      E : Element_Type renames Position.Node.Element.all;
+
+      T : Tree_Type renames Position.Container.Tree;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Key.all, Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
    -----------
@@ -1004,28 +1047,31 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
      (Stream    : access Root_Stream_Type'Class;
       Container : Map)
    is
-      procedure Process (Node : Node_Access);
-      pragma Inline (Process);
-
-      procedure Iterate is
-        new Tree_Operations.Generic_Iteration (Process);
-
-      -------------
-      -- Process --
-      -------------
-
-      procedure Process (Node : Node_Access) is
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+      pragma Inline (Write_Node);
+
+      procedure Write is
+         new Tree_Operations.Generic_Write (Write_Node);
+
+      ----------------
+      -- Write_Node --
+      ----------------
+
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access)
+      is
       begin
          Key_Type'Output (Stream, Node.Key.all);
          Element_Type'Output (Stream, Node.Element.all);
-      end Process;
+      end Write_Node;
 
    --  Start of processing for Write
 
    begin
-      Count_Type'Base'Write (Stream, Container.Tree.Length);
-      Iterate (Container.Tree);
+      Write (Stream, Container.Tree);
    end Write;
 
 end Ada.Containers.Indefinite_Ordered_Maps;
-
index 8bfe3270e2132778a96203766a78c9b6c0163285..f6ae76fa33441f2ea55342420be426c1d6fa48ea 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_ORDERED_MAPS                  --
+--                      A D A . C O N T A I N E R S .                       --
+--             I N D E F I N I T E _ O R D E R E D _ M A P S                --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -110,10 +111,6 @@ pragma Preelaborate (Indefinite_Ordered_Maps);
      (Container : in out Map;
       Key       : Key_Type);
 
-   procedure Exclude
-     (Container : in out Map;
-      Key       : Key_Type);
-
    procedure Delete
      (Container : in out Map;
       Position  : in out Cursor);
@@ -122,6 +119,10 @@ pragma Preelaborate (Indefinite_Ordered_Maps);
 
    procedure Delete_Last (Container : in out Map);
 
+   procedure Exclude
+     (Container : in out Map;
+      Key       : Key_Type);
+
    function Contains
      (Container : Map;
       Key       : Key_Type) return Boolean;
@@ -156,10 +157,10 @@ pragma Preelaborate (Indefinite_Ordered_Maps);
 
    function Next (Position : Cursor) return Cursor;
 
-   function Previous (Position : Cursor) return Cursor;
-
    procedure Next (Position : in out Cursor);
 
+   function Previous (Position : Cursor) return Cursor;
+
    procedure Previous (Position : in out Cursor);
 
    function Has_Element (Position : Cursor) return Boolean;
@@ -189,21 +190,35 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package Tree_Types is
-     new Red_Black_Trees.Generic_Tree_Types (Node_Access);
+   type Key_Access is access Key_Type;
+   type Element_Access is access Element_Type;
 
-   use Tree_Types;
-   use Ada.Finalization;
+   type Node_Type is limited record
+      Parent  : Node_Access;
+      Left    : Node_Access;
+      Right   : Node_Access;
+      Color   : Red_Black_Trees.Color_Type := Red_Black_Trees.Red;
+      Key     : Key_Access;
+      Element : Element_Access;
+   end record;
 
-   type Map is new Controlled with record
-      Tree : Tree_Type := (Length => 0, others => null);
+   package Tree_Types is new Red_Black_Trees.Generic_Tree_Types
+     (Node_Type,
+      Node_Access);
+
+   type Map is new Ada.Finalization.Controlled with record
+      Tree : Tree_Types.Tree_Type;
    end record;
 
    procedure Adjust (Container : in out Map);
 
    procedure Finalize (Container : in out Map) renames Clear;
 
-   type Map_Access is access constant Map;
+   use Red_Black_Trees;
+   use Tree_Types;
+   use Ada.Finalization;
+
+   type Map_Access is access Map;
    for Map_Access'Storage_Size use 0;
 
    type Cursor is record
@@ -228,7 +243,11 @@ private
    for Map'Read use Read;
 
    Empty_Map : constant Map :=
-     (Controlled with Tree => (Length => 0, others => null));
+                 (Controlled with Tree => (First  => null,
+                                           Last   => null,
+                                           Root   => null,
+                                           Length => 0,
+                                           Busy   => 0,
+                                           Lock   => 0));
 
 end Ada.Containers.Indefinite_Ordered_Maps;
-
index 1d608b0367215f532d49a18f5beef03072f0c191..c836913e9a55d32db9ad5e09a1e07649366e019c 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---               ADA.CONTAINERS.INDEFINITE_ORDERED_MULTISETS                --
+--                      A D A . C O N T A I N E R S .                       --
+--         I N D E F I N I T E _ O R D E R E D _ M U L T I S E T S          --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -44,22 +45,8 @@ pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
 
-with System;  use type System.Address;
-
 package body Ada.Containers.Indefinite_Ordered_Multisets is
 
-   use Red_Black_Trees;
-
-   type Element_Access is access Element_Type;
-
-   type Node_Type is limited record
-      Parent  : Node_Access;
-      Left    : Node_Access;
-      Right   : Node_Access;
-      Color   : Red_Black_Trees.Color_Type := Red;
-      Element : Element_Access;
-   end record;
-
    -----------------------------
    -- Node Access Subprograms --
    -----------------------------
@@ -98,10 +85,6 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
    function Copy_Node (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access;
-
-   procedure Delete_Tree (X : in out Node_Access);
-
    procedure Free (X : in out Node_Access);
 
    procedure Insert_With_Hint
@@ -126,14 +109,23 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
    function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
    pragma Inline (Is_Less_Node_Node);
 
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type);
+
    --------------------------
    -- Local Instantiations --
    --------------------------
 
    package Tree_Operations is
-     new Red_Black_Trees.Generic_Operations
-       (Tree_Types => Tree_Types,
-        Null_Node  => Node_Access'(null));
+     new Red_Black_Trees.Generic_Operations (Tree_Types);
+
+   procedure Delete_Tree is
+     new Tree_Operations.Generic_Delete_Tree (Free);
+
+   function Copy_Tree is
+     new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
 
    use Tree_Operations;
 
@@ -182,11 +174,8 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
    -- "=" --
    ---------
 
-   function "=" (Left, Right : Set) return Boolean is begin
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
+   function "=" (Left, Right : Set) return Boolean is
+   begin
       return Is_Equal (Left.Tree, Right.Tree);
    end "=";
 
@@ -215,24 +204,12 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-
-      N : constant Count_Type := Tree.Length;
-      X : constant Node_Access := Tree.Root;
+   procedure Adjust is
+      new Tree_Operations.Generic_Adjust (Copy_Tree);
 
+   procedure Adjust (Container : in out Set) is
    begin
-      if N = 0 then
-         pragma Assert (X = null);
-         return;
-      end if;
-
-      Tree := (Length => 0, others => null);
-
-      Tree.Root := Copy_Tree (X);
-      Tree.First := Min (Tree.Root);
-      Tree.Last := Max (Tree.Root);
-      Tree.Length := N;
+      Adjust (Container.Tree);
    end Adjust;
 
    -------------
@@ -248,19 +225,19 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Ceiling;
 
    -----------
    -- Clear --
    -----------
 
+   procedure Clear is
+      new Tree_Operations.Generic_Clear (Delete_Tree);
+
    procedure Clear (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-      Root : Node_Access := Tree.Root;
    begin
-      Tree := (Length => 0, others => null);
-      Delete_Tree (Root);
+      Clear (Container.Tree);
    end Clear;
 
    -----------
@@ -301,49 +278,6 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          raise;
    end Copy_Node;
 
-   ---------------
-   -- Copy_Tree --
-   ---------------
-
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access is
-      Target_Root : Node_Access := Copy_Node (Source_Root);
-
-      P, X : Node_Access;
-
-   begin
-      if Source_Root.Right /= null then
-         Target_Root.Right := Copy_Tree (Source_Root.Right);
-         Target_Root.Right.Parent := Target_Root;
-      end if;
-
-      P := Target_Root;
-      X := Source_Root.Left;
-      while X /= null loop
-         declare
-            Y : Node_Access := Copy_Node (X);
-
-         begin
-            P.Left := Y;
-            Y.Parent := P;
-
-            if X.Right /= null then
-               Y.Right := Copy_Tree (X.Right);
-               Y.Right.Parent := Y;
-            end if;
-
-            P := Y;
-            X := X.Left;
-         end;
-      end loop;
-
-      return Target_Root;
-
-   exception
-      when others =>
-         Delete_Tree (Target_Root);
-         raise;
-   end Copy_Tree;
-
    ------------
    -- Delete --
    ------------
@@ -371,15 +305,15 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
    procedure Delete (Container : in out Set; Position : in out Cursor) is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
+      if Position.Container /= Container'Unrestricted_Access then
          raise Program_Error;
       end if;
 
-      Delete_Node_Sans_Free (Container.Tree, Position.Node);
+      Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
       Free (Position.Node);
 
       Position.Container := null;
@@ -419,48 +353,20 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
       Free (X);
    end Delete_Last;
 
-   -----------------
-   -- Delete_Tree --
-   -----------------
-
-   procedure Delete_Tree (X : in out Node_Access) is
-      Y : Node_Access;
-   begin
-      while X /= null loop
-         Y := X.Right;
-         Delete_Tree (Y);
-         Y := X.Left;
-         Free (X);
-         X := Y;
-      end loop;
-   end Delete_Tree;
-
    ----------------
    -- Difference --
    ----------------
 
    procedure Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Difference (Target.Tree, Source.Tree);
    end Difference;
 
    function Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Difference;
 
    -------------
@@ -472,6 +378,39 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
       return Position.Node.Element.all;
    end Element;
 
+   ---------------------
+   -- Equivalent_Sets --
+   ---------------------
+
+   function Equivalent_Sets (Left, Right : Set) return Boolean is
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
+      pragma Inline (Is_Equivalent_Node_Node);
+
+      function Is_Equivalent is
+         new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
+
+      -----------------------------
+      -- Is_Equivalent_Node_Node --
+      -----------------------------
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
+      begin
+         if L.Element.all < R.Element.all then
+            return False;
+         elsif R.Element.all < L.Element.all then
+            return False;
+         else
+            return True;
+         end if;
+      end Is_Equivalent_Node_Node;
+
+   --  Start of processing for Equivalent_Sets
+
+   begin
+      return Is_Equivalent (Left.Tree, Right.Tree);
+   end Equivalent_Sets;
+
    -------------
    -- Exclude --
    -------------
@@ -503,7 +442,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Find;
 
    -----------
@@ -516,7 +455,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.First);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
    end First;
 
    -------------------
@@ -541,7 +480,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Floor;
 
    ----------
@@ -552,10 +491,20 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
       procedure Deallocate is
         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
    begin
-      if X /= null then
-         Free_Element (X.Element);
-         Deallocate (X);
+      if X = null then
+         return;
       end if;
+
+      begin
+         Free_Element (X.Element);
+      exception
+         when others =>
+            X.Element := null;
+            Deallocate (X);
+            raise;
+      end;
+
+      Deallocate (X);
    end Free;
 
    ------------------
@@ -630,77 +579,9 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Ceiling;
 
-      ----------------------------
-      -- Checked_Update_Element --
-      ----------------------------
-
-      procedure Checked_Update_Element
-        (Container : in out Set;
-         Position  : Cursor;
-         Process   : not null access procedure (Element : in out Element_Type))
-      is
-      begin
-         if Position.Container = null then
-            raise Constraint_Error;
-         end if;
-
-         if Position.Container /= Set_Access'(Container'Unchecked_Access) then
-            raise Program_Error;
-         end if;
-
-         declare
-            Old_Key : Key_Type renames Key (Position.Node.Element.all);
-
-         begin
-            Process (Position.Node.Element.all);
-
-            if Old_Key < Position.Node.Element.all
-              or else Old_Key > Position.Node.Element.all
-            then
-               null;
-            else
-               return;
-            end if;
-         end;
-
-         Delete_Node_Sans_Free (Container.Tree, Position.Node);
-
-         Do_Insert : declare
-            Result : Node_Access;
-
-            function New_Node return Node_Access;
-            pragma Inline (New_Node);
-
-            procedure Insert_Post is
-              new Key_Keys.Generic_Insert_Post (New_Node);
-
-            procedure Insert is
-              new Key_Keys.Generic_Unconditional_Insert (Insert_Post);
-
-            --------------
-            -- New_Node --
-            --------------
-
-            function New_Node return Node_Access is
-            begin
-               return Position.Node;
-            end New_Node;
-
-         --  Start of processing for Do_Insert
-
-         begin
-            Insert
-              (Tree    => Container.Tree,
-               Key     => Key (Position.Node.Element.all),
-               Node    => Result);
-
-            pragma Assert (Result = Position.Node);
-         end Do_Insert;
-      end Checked_Update_Element;
-
       --------------
       -- Contains --
       --------------
@@ -776,7 +657,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Find;
 
       -----------
@@ -791,7 +672,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Floor;
 
       -------------------------
@@ -837,13 +718,26 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
          procedure Process_Node (Node : Node_Access) is
          begin
-            Process (Cursor'(Container'Unchecked_Access, Node));
+            Process (Cursor'(Container'Unrestricted_Access, Node));
          end Process_Node;
 
+         T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+         B : Natural renames T.Busy;
+
       --  Start of processing for Iterate
 
       begin
-         Local_Iterate (Container.Tree, Key);
+         B := B + 1;
+
+         begin
+            Local_Iterate (T, Key);
+         exception
+            when others =>
+               B := B - 1;
+               raise;
+         end;
+
+         B := B - 1;
       end Iterate;
 
       ---------
@@ -855,27 +749,6 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          return Key (Position.Node.Element.all);
       end Key;
 
-      -------------
-      -- Replace --
-      -------------
-
-      --  In post-madision api: ???
-
---     procedure Replace
---       (Container : in out Set;
---        Key       : Key_Type;
---        New_Item  : Element_Type)
---     is
---           Node : Node_Access := Key_Keys.Find (Container.Tree, Key);
-
---        begin
---           if Node = null then
---              raise Constraint_Error;
---           end if;
-
---           Replace_Node (Container, Node, New_Item);
---        end Replace;
-
       ---------------------
       -- Reverse_Iterate --
       ---------------------
@@ -901,15 +774,90 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
          procedure Process_Node (Node : Node_Access) is
          begin
-            Process (Cursor'(Container'Unchecked_Access, Node));
+            Process (Cursor'(Container'Unrestricted_Access, Node));
          end Process_Node;
 
+         T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+         B : Natural renames T.Busy;
+
       --  Start of processing for Reverse_Iterate
 
       begin
-         Local_Reverse_Iterate (Container.Tree, Key);
+         B := B + 1;
+
+         begin
+            Local_Reverse_Iterate (T, Key);
+         exception
+            when others =>
+               B := B - 1;
+               raise;
+         end;
+
+         B := B - 1;
       end Reverse_Iterate;
 
+      -----------------------------------
+      -- Update_Element_Preserving_Key --
+      -----------------------------------
+
+      procedure Update_Element_Preserving_Key
+        (Container : in out Set;
+         Position  : Cursor;
+         Process   : not null access procedure (Element : in out Element_Type))
+      is
+         Tree : Tree_Type renames Container.Tree;
+
+      begin
+         if Position.Node = null then
+            raise Constraint_Error;
+         end if;
+
+         if Position.Container /= Container'Unrestricted_Access then
+            raise Program_Error;
+         end if;
+
+         declare
+            E : Element_Type renames Position.Node.Element.all;
+            K : Key_Type renames Key (E);
+
+            B : Natural renames Tree.Busy;
+            L : Natural renames Tree.Lock;
+
+         begin
+            B := B + 1;
+            L := L + 1;
+
+            begin
+               Process (E);
+            exception
+               when others =>
+                  L := L - 1;
+                  B := B - 1;
+                  raise;
+            end;
+
+            L := L - 1;
+            B := B - 1;
+
+            if K < E
+              or else K > E
+            then
+               null;
+            else
+               return;
+            end if;
+         end;
+
+         declare
+            X : Node_Access := Position.Node;
+         begin
+            Tree_Operations.Delete_Node_Sans_Free (Tree, X);
+            Free (X);
+         end;
+
+         raise Program_Error;
+      end Update_Element_Preserving_Key;
+
    end Generic_Keys;
 
    -----------------
@@ -973,7 +921,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          New_Item,
          Position.Node);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    ----------------------
@@ -1036,25 +984,14 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
    procedure Intersection (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Intersection (Target.Tree, Source.Tree);
    end Intersection;
 
    function Intersection (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Intersection (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Intersection (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Intersection;
 
    --------------
@@ -1116,10 +1053,6 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
    begin
-      if Subset'Address = Of_Set'Address then
-         return True;
-      end if;
-
       return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
    end Is_Subset;
 
@@ -1144,13 +1077,26 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container.Tree, Item);
+      B := B + 1;
+
+      begin
+         Local_Iterate (T, Item);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    procedure Iterate
@@ -1169,13 +1115,26 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ----------
@@ -1188,7 +1147,7 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
    end Last;
 
    ------------------
@@ -1222,12 +1181,11 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
    -- Move --
    ----------
 
+   procedure Move is
+      new Tree_Operations.Generic_Move (Clear);
+
    procedure Move (Target : in out Set; Source : in out Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Move (Target => Target.Tree, Source => Source.Tree);
    end Move;
 
@@ -1265,10 +1223,6 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
    function Overlap (Left, Right : Set) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return Left.Tree.Length /= 0;
-      end if;
-
       return Set_Ops.Overlap (Left.Tree, Right.Tree);
    end Overlap;
 
@@ -1317,8 +1271,29 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type))
    is
+      E : Element_Type renames Position.Node.Element.all;
+
+      S : Set renames Position.Container.all;
+      T : Tree_Type renames S.Tree'Unrestricted_Access.all;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -1329,150 +1304,122 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
      (Stream    : access Root_Stream_Type'Class;
       Container : out Set)
    is
-      N : Count_Type'Base;
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+      pragma Inline (Read_Node);
 
-      function New_Node return Node_Access;
-      pragma Inline (New_Node);
+      procedure Read is
+         new Tree_Operations.Generic_Read (Clear, Read_Node);
 
-      procedure Local_Read is new Tree_Operations.Generic_Read (New_Node);
+      ---------------
+      -- Read_Node --
+      ---------------
 
-      --------------
-      -- New_Node --
-      --------------
-
-      function New_Node return Node_Access is
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access
+      is
          Node : Node_Access := new Node_Type;
-
       begin
-         begin
-            Node.Element := new Element_Type'(Element_Type'Input (Stream));
-         exception
-            when others =>
-               Free (Node);
-               raise;
-         end;
-
+         Node.Element := new Element_Type'(Element_Type'Input (Stream));
          return Node;
-      end New_Node;
+      exception
+         when others =>
+            Free (Node);  --  Note that Free deallocates elem too
+            raise;
+      end Read_Node;
 
    --  Start of processing for Read
 
    begin
-      Clear (Container);
+      Read (Stream, Container.Tree);
+   end Read;
 
-      Count_Type'Base'Read (Stream, N);
-      pragma Assert (N >= 0);
+   ---------------------
+   -- Replace_Element --
+   ---------------------
 
-      Local_Read (Container.Tree, N);
-   end Read;
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type)
+   is
+   begin
+      if Item < Node.Element.all
+        or else Node.Element.all < Item
+      then
+         null;
+      else
+         if Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
 
-   -------------
-   -- Replace --
-   -------------
+         declare
+            X : Element_Access := Node.Element;
+         begin
+            Node.Element := new Element_Type'(Item);
+            Free_Element (X);
+         end;
 
-   --  NOTE: from post-madison api???
+         return;
+      end if;
 
---   procedure Replace
---     (Container : in out Set;
---      Position  : Cursor;
---      By        : Element_Type)
---   is
---   begin
---      if Position.Container = null then
---         raise Constraint_Error;
---      end if;
+      Tree_Operations.Delete_Node_Sans_Free (Tree, Node);  -- Checks busy-bit
 
---      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
---         raise Program_Error;
---      end if;
+      Insert_New_Item : declare
+         function New_Node return Node_Access;
+         pragma Inline (New_Node);
 
---      Replace_Node (Container, Position.Node, By);
---   end Replace;
+         procedure Insert_Post is
+            new Element_Keys.Generic_Insert_Post (New_Node);
 
-   ------------------
-   -- Replace_Node --
-   ------------------
+         procedure Unconditional_Insert is
+            new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
+
+         --------------
+         -- New_Node --
+         --------------
+
+         function New_Node return Node_Access is
+         begin
+            Node.Element := new Element_Type'(Item);  -- OK if fails
+            return Node;
+         end New_Node;
+
+         Result : Node_Access;
+
+         X : Element_Access := Node.Element;
 
-   --  NOTE: from post-madison api???
-
---   procedure Replace_Node
---     (Container : in out Set;
---      Position  : Node_Access;
---      By        : Element_Type);
---   is
---      Tree : Tree_Type renames Container.Tree;
---      Node : Node_Access := Position;
-
---   begin
---      if By < Node.Element
---        or else Node.Element < By
---      then
---         null;
-
---      else
---         begin
---            Node.Element := By;
-
---         exception
---            when others =>
---               Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
---               Free (Node);
---               raise;
---         end;
-
---         return;
---      end if;
-
---      Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
-
---      begin
---         Node.Element := By;
-
---      exception
---         when others =>
---            Free (Node);
---            raise;
---      end;
-
---      declare
---         Result  : Node_Access;
---         Success : Boolean;
-
---         function New_Node return Node_Access;
---         pragma Inline (New_Node);
-
---         procedure Insert_Post is
---           new Element_Keys.Generic_Insert_Post (New_Node);
-
---         procedure Insert is
---           new Element_Keys.Generic_Conditional_Insert (Insert_Post);
-
---         --------------
---         -- New_Node --
---         --------------
---
---         function New_Node return Node_Access is
---         begin
---            return Node;
---         end New_Node;
-
---      --  Start of processing for Replace_Node
-
---      begin
---         Insert
---           (Tree    => Tree,
---            Key     => Node.Element,
---            Node    => Result,
---            Success => Success);
-
---         if not Success then
---            Free (Node);
---            raise Program_Error;
---         end if;
-
---         pragma Assert (Result = Node);
---      end;
---   end Replace_Node;
+      --  Start of processing for Insert_New_Item
+
+      begin
+         Unconditional_Insert
+           (Tree => Tree,
+            Key  => Item,
+            Node => Result);
+         pragma Assert (Result = Node);
+
+         Free_Element (X);  -- OK if fails
+      end Insert_New_Item;
+   end Replace_Element;
+
+   procedure Replace_Element
+    (Container : Set;
+     Position  : Cursor;
+     By        : Element_Type)
+   is
+      Tree : Tree_Type renames Position.Container.Tree'Unrestricted_Access.all;
+
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
+
+      if Position.Container /= Container'Unrestricted_Access then
+         raise Program_Error;
+      end if;
+
+      Replace_Element (Tree, Position.Node, By);
+   end Replace_Element;
 
    ---------------------
    -- Reverse_Iterate --
@@ -1495,13 +1442,26 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree, Item);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (T, Item);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    procedure Reverse_Iterate
@@ -1520,13 +1480,26 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    -----------
@@ -1580,26 +1553,14 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
    procedure Symmetric_Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
    end Symmetric_Difference;
 
    function Symmetric_Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Symmetric_Difference;
 
    -----------
@@ -1608,23 +1569,14 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
 
    procedure Union (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Union (Target.Tree, Source.Tree);
    end Union;
 
-   function Union (Left, Right : Set) return Set is begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type := Set_Ops.Union (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+   function Union (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Union (Left.Tree, Right.Tree);
+   begin
+      return Set'(Controlled with Tree);
    end Union;
 
    -----------
@@ -1635,25 +1587,30 @@ package body Ada.Containers.Indefinite_Ordered_Multisets is
      (Stream    : access Root_Stream_Type'Class;
       Container : Set)
    is
-      procedure Process (Node : Node_Access);
-      pragma Inline (Process);
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+      pragma Inline (Write_Node);
 
-      procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
+      procedure Write is
+         new Tree_Operations.Generic_Write (Write_Node);
 
-      -------------
-      -- Process --
-      -------------
+      ----------------
+      -- Write_Node --
+      ----------------
 
-      procedure Process (Node : Node_Access) is
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access)
+      is
       begin
          Element_Type'Output (Stream, Node.Element.all);
-      end Process;
+      end Write_Node;
 
    --  Start of processing for Write
 
    begin
-      Count_Type'Base'Write (Stream, Container.Tree.Length);
-      Iterate (Container.Tree);
+      Write (Stream, Container.Tree);
    end Write;
 
 end Ada.Containers.Indefinite_Ordered_Multisets;
index 328d0dded9f3a02c34e0b82f45ea985db074ac76..4bf4857e26c1feceaf89649f0cd98edc3f86140f 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---               ADA.CONTAINERS.INDEFINITE_ORDERED_MULTISETS                --
+--                      A D A . C O N T A I N E R S .                       --
+--         I N D E F I N I T E _ O R D E R E D _ M U L T I S E T S          --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -56,6 +57,8 @@ pragma Preelaborate (Indefinite_Ordered_Multisets);
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -68,6 +71,11 @@ pragma Preelaborate (Indefinite_Ordered_Multisets);
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type));
 
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type);
+
    procedure Move (Target : in out Set; Source : in out Set);
 
    procedure Insert
@@ -79,22 +87,13 @@ pragma Preelaborate (Indefinite_Ordered_Multisets);
 
    procedure Delete (Container : in out Set; Item : Element_Type);
 
-   procedure Exclude (Container : in out Set; Item : Element_Type);
-
    procedure Delete (Container : in out Set; Position : in out Cursor);
 
    procedure Delete_First (Container : in out Set);
 
    procedure Delete_Last (Container : in out Set);
 
-
-   --  NOTE: The following operation is named Replace in the Madison API.
-   --  However, it should be named Replace_Element ???
-   --
-   --   procedure Replace
-   --     (Container : in out Set;
-   --      Position  : Cursor;
-   --      By        : Element_Type);
+   procedure Exclude (Container : in out Set; Item : Element_Type);
 
    procedure Union (Target : in out Set;
                     Source : Set);
@@ -143,10 +142,10 @@ pragma Preelaborate (Indefinite_Ordered_Multisets);
 
    function Next (Position : Cursor) return Cursor;
 
-   function Previous (Position : Cursor) return Cursor;
-
    procedure Next (Position : in out Cursor);
 
+   function Previous (Position : Cursor) return Cursor;
+
    procedure Previous (Position : in out Cursor);
 
    function Has_Element (Position : Cursor) return Boolean;
@@ -207,12 +206,6 @@ pragma Preelaborate (Indefinite_Ordered_Multisets);
 
       function Element (Container : Set; Key : Key_Type) return Element_Type;
 
-      --  NOTE: in post-madison api ???
-      --      procedure Replace
-      --        (Container : in out Set;
-      --         Key       : Key_Type;
-      --         New_Item  : Element_Type);
-
       procedure Delete (Container : in out Set; Key : Key_Type);
 
       procedure Exclude (Container : in out Set; Key : Key_Type);
@@ -225,7 +218,7 @@ pragma Preelaborate (Indefinite_Ordered_Multisets);
 
       function ">" (Left : Key_Type; Right : Cursor) return Boolean;
 
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : Cursor;
          Process   : not null access
@@ -248,21 +241,33 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package Tree_Types is
-      new Red_Black_Trees.Generic_Tree_Types (Node_Access);
+   type Element_Access is access Element_Type;
 
-   use Tree_Types;
-   use Ada.Finalization;
+   type Node_Type is limited record
+      Parent  : Node_Access;
+      Left    : Node_Access;
+      Right   : Node_Access;
+      Color   : Red_Black_Trees.Color_Type := Red_Black_Trees.Red;
+      Element : Element_Access;
+   end record;
 
-   type Set is new Controlled with record
-      Tree : Tree_Type := (Length => 0, others => null);
+   package Tree_Types is new Red_Black_Trees.Generic_Tree_Types
+     (Node_Type,
+      Node_Access);
+
+   type Set is new Ada.Finalization.Controlled with record
+      Tree : Tree_Types.Tree_Type;
    end record;
 
    procedure Adjust (Container : in out Set);
 
    procedure Finalize (Container : in out Set) renames Clear;
 
-   type Set_Access is access constant Set;
+   use Red_Black_Trees;
+   use Tree_Types;
+   use Ada.Finalization;
+
+   type Set_Access is access all Set;
    for Set_Access'Storage_Size use 0;
 
    type Cursor is record
@@ -285,6 +290,11 @@ private
    for Set'Read use Read;
 
    Empty_Set : constant Set :=
-                 (Controlled with Tree => (Length => 0, others => null));
+                 (Controlled with Tree => (First  => null,
+                                           Last   => null,
+                                           Root   => null,
+                                           Length => 0,
+                                           Busy   => 0,
+                                           Lock   => 0));
 
 end Ada.Containers.Indefinite_Ordered_Multisets;
index 9cd5e14db36508784f87a62ee9777b66ef36f842..0f9615cc0286371fd05c60ad1adf79386d9da99b 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_ORDERED_SETS                  --
+--                      A D A . C O N T A I N E R S .                       --
+--              I N D E F I N I T E _ O R D E R E D _ S E T S               --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -44,22 +45,8 @@ pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
 
 with Ada.Unchecked_Deallocation;
 
-with System;  use type System.Address;
-
 package body Ada.Containers.Indefinite_Ordered_Sets is
 
-   type Element_Access is access Element_Type;
-
-   use Red_Black_Trees;
-
-   type Node_Type is limited record
-      Parent  : Node_Access;
-      Left    : Node_Access;
-      Right   : Node_Access;
-      Color   : Red_Black_Trees.Color_Type := Red;
-      Element : Element_Access;
-   end record;
-
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -70,10 +57,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    function Copy_Node (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access;
-
-   procedure Delete_Tree (X : in out Node_Access);
-
    procedure Free (X : in out Node_Access);
 
    procedure Insert_With_Hint
@@ -101,6 +84,11 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    function Parent (Node : Node_Access) return Node_Access;
    pragma Inline (Parent);
 
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type);
+
    function Right (Node : Node_Access) return Node_Access;
    pragma Inline (Right);
 
@@ -124,9 +112,13 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
      new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
 
    package Tree_Operations is
-     new Red_Black_Trees.Generic_Operations
-       (Tree_Types => Tree_Types,
-        Null_Node  => Node_Access'(null));
+     new Red_Black_Trees.Generic_Operations (Tree_Types);
+
+   procedure Delete_Tree is
+     new Tree_Operations.Generic_Delete_Tree (Free);
+
+   function Copy_Tree is
+     new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
 
    use Tree_Operations;
 
@@ -189,14 +181,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    --  Start of processing for "="
 
    begin
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
       return Is_Equal (Left.Tree, Right.Tree);
    end "=";
 
-
    ---------
    -- ">" --
    ---------
@@ -222,25 +209,12 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
+   procedure Adjust is
+      new Tree_Operations.Generic_Adjust (Copy_Tree);
 
+   procedure Adjust (Container : in out Set) is
    begin
-      if Tree.Length = 0 then
-         pragma Assert (Tree.Root = null);
-         return;
-      end if;
-
-      begin
-         Tree.Root := Copy_Tree (Tree.Root);
-      exception
-         when others =>
-            Tree := (Length => 0, others => null);
-            raise;
-      end;
-
-      Tree.First := Min (Tree.Root);
-      Tree.Last := Max (Tree.Root);
+      Adjust (Container.Tree);
    end Adjust;
 
    -------------
@@ -256,19 +230,19 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Ceiling;
 
    -----------
    -- Clear --
    -----------
 
+   procedure Clear is
+      new Tree_Operations.Generic_Clear (Delete_Tree);
+
    procedure Clear (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-      Root : Node_Access := Tree.Root;
    begin
-      Tree := (Length => 0, others => null);
-      Delete_Tree (Root);
+      Clear (Container.Tree);
    end Clear;
 
    -----------
@@ -295,6 +269,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    function Copy_Node (Source : Node_Access) return Node_Access is
       Element : Element_Access := new Element_Type'(Source.Element.all);
+
    begin
       return new Node_Type'(Parent  => null,
                             Left    => null,
@@ -307,66 +282,22 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          raise;
    end Copy_Node;
 
-   ---------------
-   -- Copy_Tree --
-   ---------------
-
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access is
-      Target_Root : Node_Access := Copy_Node (Source_Root);
-      P, X        : Node_Access;
-
-   begin
-      if Source_Root.Right /= null then
-         Target_Root.Right := Copy_Tree (Source_Root.Right);
-         Target_Root.Right.Parent := Target_Root;
-      end if;
-
-      P := Target_Root;
-      X := Source_Root.Left;
-
-      while X /= null loop
-         declare
-            Y : Node_Access := Copy_Node (X);
-
-         begin
-            P.Left := Y;
-            Y.Parent := P;
-
-            if X.Right /= null then
-               Y.Right := Copy_Tree (X.Right);
-               Y.Right.Parent := Y;
-            end if;
-
-            P := Y;
-            X := X.Left;
-         end;
-      end loop;
-
-      return Target_Root;
-
-   exception
-      when others =>
-         Delete_Tree (Target_Root);
-         raise;
-   end Copy_Tree;
-
    ------------
    -- Delete --
    ------------
 
    procedure Delete (Container : in out Set; Position  : in out Cursor) is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
+      if Position.Container /= Container'Unrestricted_Access then
          raise Program_Error;
       end if;
 
-      Delete_Node_Sans_Free (Container.Tree, Position.Node);
+      Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
       Free (Position.Node);
-
       Position.Container := null;
    end Delete;
 
@@ -388,9 +319,14 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    ------------------
 
    procedure Delete_First (Container : in out Set) is
-      C : Cursor := First (Container);
+      Tree : Tree_Type renames Container.Tree;
+      X    : Node_Access := Tree.First;
+
    begin
-      Delete (Container, C);
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Tree, X);
+         Free (X);
+      end if;
    end Delete_First;
 
    -----------------
@@ -398,26 +334,15 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    -----------------
 
    procedure Delete_Last (Container : in out Set) is
-      C : Cursor := Last (Container);
-   begin
-      Delete (Container, C);
-   end Delete_Last;
-
-   -----------------
-   -- Delete_Tree --
-   -----------------
+      Tree : Tree_Type renames Container.Tree;
+      X    : Node_Access := Tree.Last;
 
-   procedure Delete_Tree (X : in out Node_Access) is
-      Y : Node_Access;
    begin
-      while X /= null loop
-         Y := X.Right;
-         Delete_Tree (Y);
-         Y := X.Left;
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Tree, X);
          Free (X);
-         X := Y;
-      end loop;
-   end Delete_Tree;
+      end if;
+   end Delete_Last;
 
    ----------------
    -- Difference --
@@ -425,26 +350,14 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    procedure Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Difference (Target.Tree, Source.Tree);
    end Difference;
 
    function Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-           Set_Ops.Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Difference;
 
    -------------
@@ -456,6 +369,39 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
       return Position.Node.Element.all;
    end Element;
 
+   ---------------------
+   -- Equivalent_Sets --
+   ---------------------
+
+   function Equivalent_Sets (Left, Right : Set) return Boolean is
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
+      pragma Inline (Is_Equivalent_Node_Node);
+
+      function Is_Equivalent is
+         new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
+
+      -----------------------------
+      -- Is_Equivalent_Node_Node --
+      -----------------------------
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
+      begin
+         if L.Element.all < R.Element.all then
+            return False;
+         elsif R.Element.all < L.Element.all then
+            return False;
+         else
+            return True;
+         end if;
+      end Is_Equivalent_Node_Node;
+
+   --  Start of processing for Equivalent_Sets
+
+   begin
+      return Is_Equivalent (Left.Tree, Right.Tree);
+   end Equivalent_Sets;
+
    -------------
    -- Exclude --
    -------------
@@ -463,9 +409,10 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    procedure Exclude (Container : in out Set; Item : Element_Type) is
       X : Node_Access :=
             Element_Keys.Find (Container.Tree, Item);
+
    begin
       if X /= null then
-         Delete_Node_Sans_Free (Container.Tree, X);
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
          Free (X);
       end if;
    end Exclude;
@@ -483,7 +430,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Find;
 
    -----------
@@ -496,7 +443,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.First);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
    end First;
 
    -------------------
@@ -521,7 +468,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Floor;
 
    ----------
@@ -529,13 +476,25 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    ----------
 
    procedure Free (X : in out Node_Access) is
+
       procedure Deallocate is
         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
+
    begin
-      if X /= null then
-         Free_Element (X.Element);
-         Deallocate (X);
+      if X = null then
+         return;
       end if;
+
+      begin
+         Free_Element (X.Element);
+      exception
+         when others =>
+            X.Element := null;
+            Deallocate (X);
+            raise;
+      end;
+
+      Deallocate (X);
    end Free;
 
    ------------------
@@ -610,90 +569,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Ceiling;
 
-      ----------------------------
-      -- Checked_Update_Element --
-      ----------------------------
-
-      procedure Checked_Update_Element
-        (Container : in out Set;
-         Position  : Cursor;
-         Process   : not null access
-                        procedure (Element : in out Element_Type))
-      is
-      begin
-         if Position.Container = null then
-            raise Constraint_Error;
-         end if;
-
-         if Position.Container /= Set_Access'(Container'Unchecked_Access) then
-            raise Program_Error;
-         end if;
-
-         declare
-            Old_Key : Key_Type renames Key (Position.Node.Element.all);
-
-         begin
-            Process (Position.Node.Element.all);
-
-            if Old_Key < Position.Node.Element.all
-              or else Old_Key > Position.Node.Element.all
-            then
-               null;
-            else
-               return;
-            end if;
-         end;
-
-         declare
-            Result  : Node_Access;
-            Success : Boolean;
-
-            function New_Node return Node_Access;
-            pragma Inline (New_Node);
-
-            procedure Insert_Post is
-              new Key_Keys.Generic_Insert_Post (New_Node);
-
-            procedure Insert is
-              new Key_Keys.Generic_Conditional_Insert (Insert_Post);
-
-            --------------
-            -- New_Node --
-            --------------
-
-            function New_Node return Node_Access is
-            begin
-               return Position.Node;
-            end New_Node;
-
-         --  Start of processing for Checked_Update_Element
-
-         begin
-            Delete_Node_Sans_Free (Container.Tree, Position.Node);
-
-            Insert
-              (Tree    => Container.Tree,
-               Key     => Key (Position.Node.Element.all),
-               Node    => Result,
-               Success => Success);
-
-            if not Success then
-               declare
-                  X : Node_Access := Position.Node;
-               begin
-                  Free (X);
-               end;
-
-               raise Program_Error;
-            end if;
-
-            pragma Assert (Result = Position.Node);
-         end;
-      end Checked_Update_Element;
-
       --------------
       -- Contains --
       --------------
@@ -715,7 +593,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
             raise Constraint_Error;
          end if;
 
-         Delete_Node_Sans_Free (Container.Tree, X);
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
          Free (X);
       end Delete;
 
@@ -724,9 +602,11 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
       -------------
 
       function Element (Container : Set; Key : Key_Type) return Element_Type is
-         C : constant Cursor := Find (Container, Key);
+         Node : constant Node_Access :=
+                  Key_Keys.Find (Container.Tree, Key);
+
       begin
-         return C.Node.Element.all;
+         return Node.Element.all;
       end Element;
 
       -------------
@@ -738,7 +618,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
       begin
          if X /= null then
-            Delete_Node_Sans_Free (Container.Tree, X);
+            Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
             Free (X);
          end if;
       end Exclude;
@@ -756,7 +636,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Find;
 
       -----------
@@ -772,7 +652,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Floor;
 
       -------------------------
@@ -806,6 +686,88 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          return Key (Position.Node.Element.all);
       end Key;
 
+      -------------
+      -- Replace --
+      -------------
+
+      procedure Replace
+        (Container : in out Set;
+         Key       : Key_Type;
+         New_Item  : Element_Type)
+      is
+         Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
+
+      begin
+         if Node = null then
+            raise Constraint_Error;
+         end if;
+
+         Replace_Element (Container.Tree, Node, New_Item);
+      end Replace;
+
+      -----------------------------------
+      -- Update_Element_Preserving_Key --
+      -----------------------------------
+
+      procedure Update_Element_Preserving_Key
+        (Container : in out Set;
+         Position  : Cursor;
+         Process   : not null access
+                        procedure (Element : in out Element_Type))
+      is
+         Tree : Tree_Type renames Container.Tree;
+
+      begin
+         if Position.Node = null then
+            raise Constraint_Error;
+         end if;
+
+         if Position.Container /= Container'Unrestricted_Access then
+            raise Program_Error;
+         end if;
+
+         declare
+            E : Element_Type renames Position.Node.Element.all;
+            K : Key_Type renames Key (E);
+
+            B : Natural renames Tree.Busy;
+            L : Natural renames Tree.Lock;
+
+         begin
+            B := B + 1;
+            L := L + 1;
+
+            begin
+               Process (E);
+            exception
+               when others =>
+                  L := L - 1;
+                  B := B - 1;
+                  raise;
+            end;
+
+            L := L - 1;
+            B := B - 1;
+
+            if K < E
+              or else K > E
+            then
+               null;
+            else
+               return;
+            end if;
+         end;
+
+         declare
+            X : Node_Access := Position.Node;
+         begin
+            Tree_Operations.Delete_Node_Sans_Free (Tree, X);
+            Free (X);
+         end;
+
+         raise Program_Error;
+      end Update_Element_Preserving_Key;
+
    end Generic_Keys;
 
    -----------------
@@ -831,6 +793,10 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
       Insert (Container, New_Item, Position, Inserted);
 
       if not Inserted then
+         if Container.Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
+
          X := Position.Node.Element;
          Position.Node.Element := new Element_Type'(New_Item);
          Free_Element (X);
@@ -883,7 +849,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          Position.Node,
          Inserted);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    procedure Insert (Container : in out Set; New_Item  : Element_Type) is
@@ -961,25 +927,14 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    procedure Intersection (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Intersection (Target.Tree, Source.Tree);
    end Intersection;
 
    function Intersection (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Intersection (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Intersection (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Intersection;
 
    --------------
@@ -988,7 +943,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    function Is_Empty (Container : Set) return Boolean is
    begin
-      return Length (Container) = 0;
+      return Container.Tree.Length = 0;
    end Is_Empty;
 
    -----------------------------
@@ -1004,7 +959,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
       return Right.Element.all < Left;
    end Is_Greater_Element_Node;
 
-
    --------------------------
    -- Is_Less_Element_Node --
    --------------------------
@@ -1031,10 +985,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
    begin
-      if Subset'Address = Of_Set'Address then
-         return True;
-      end if;
-
       return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
    end Is_Subset;
 
@@ -1058,13 +1008,26 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
-   --  Start of processing for Iterate
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
+   --  Start of prccessing for Iterate
 
    begin
-      Local_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ----------
@@ -1077,7 +1040,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
    end Last;
 
    ------------------
@@ -1111,12 +1074,11 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    -- Move --
    ----------
 
+   procedure Move is
+      new Tree_Operations.Generic_Move (Clear);
+
    procedure Move (Target : in out Set; Source : in out Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Move (Target => Target.Tree, Source => Source.Tree);
    end Move;
 
@@ -1137,7 +1099,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
       declare
          Node : constant Node_Access :=
-           Tree_Operations.Next (Position.Node);
+                  Tree_Operations.Next (Position.Node);
+
       begin
          if Node = null then
             return No_Element;
@@ -1153,10 +1116,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    function Overlap (Left, Right : Set) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return Left.Tree.Length /= 0;
-      end if;
-
       return Set_Ops.Overlap (Left.Tree, Right.Tree);
    end Overlap;
 
@@ -1186,7 +1145,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
       declare
          Node : constant Node_Access :=
-           Tree_Operations.Previous (Position.Node);
+                  Tree_Operations.Previous (Position.Node);
+
       begin
          if Node = null then
             return No_Element;
@@ -1204,8 +1164,29 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
      (Position  : Cursor;
       Process   : not null access procedure (Element : Element_Type))
    is
+      E : Element_Type renames Position.Node.Element.all;
+
+      S : Set renames Position.Container.all;
+      T : Tree_Type renames S.Tree'Unrestricted_Access.all;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Element.all);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -1213,21 +1194,23 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    ----------
 
    procedure Read
-     (Stream    : access Ada.Streams.Root_Stream_Type'Class;
+     (Stream    : access Root_Stream_Type'Class;
       Container : out Set)
    is
-      N : Count_Type'Base;
-
-      function New_Node return Node_Access;
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+      pragma Inline (Read_Node);
 
       procedure Read is
-        new Tree_Operations.Generic_Read (New_Node);
+         new Tree_Operations.Generic_Read (Clear, Read_Node);
 
-      --------------
-      -- New_Node --
-      --------------
+      ---------------
+      -- Read_Node --
+      ---------------
 
-      function New_Node return Node_Access is
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access
+      is
          Node : Node_Access := new Node_Type;
 
       begin
@@ -1236,17 +1219,14 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
       exception
          when others =>
-            Free (Node);
+            Free (Node);  --  Note that Free deallocates elem too
             raise;
-      end New_Node;
+      end Read_Node;
 
    --  Start of processing for Read
 
    begin
-      Clear (Container);
-      Count_Type'Base'Read (Stream, N);
-      pragma Assert (N >= 0);
-      Read (Container.Tree, N);
+      Read (Stream, Container.Tree);
    end Read;
 
    -------------
@@ -1269,129 +1249,139 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
       Free_Element (X);
    end Replace;
 
---  TODO ???
---        procedure Replace
---          (Container : in out Set;
---           Key       : Key_Type;
---           New_Item  : Element_Type)
---        is
---           Node : Node_Access := Key_Keys.Find (Container.Tree, Key);
-
---        begin
---           if Node = null then
---              raise Constraint_Error;
---           end if;
-
---           Replace_Element (Container, Node, New_Item);
---        end Replace;
-
    ---------------------
    -- Replace_Element --
    ---------------------
 
---  TODO: ???
---     procedure Replace_Element
---       (Container : in out Set;
---        Position  : Node_Access;
---        By        : Element_Type)
---   is
-
---        Node : Node_Access := Position;
-
---     begin
---        if By < Node.Element.all
---          or else Node.Element.all < By
---        then
---           null;
-
---        else
---           declare
---              X : Element_Access := Node.Element;
-
---           begin
---              Node.Element := new Element_Type'(By);
-
---              --  NOTE: If there's an exception here, then just
---              --  let it propagate.  We haven't modified the
---              --  state of the container, so there's nothing else
---              --  we need to do.
-
---              Free_Element (X);
---           end;
-
---           return;
---        end if;
-
---        Delete_Node_Sans_Free (Container.Tree, Node);
-
---        begin
---           Free_Element (Node.Element);
---        exception
---           when others =>
---              Node.Element := null;  --  don't attempt to dealloc X.E again
---              Free (Node);
---              raise;
---        end;
-
---        begin
---           Node.Element := new Element_Type'(By);
---        exception
---           when others =>
---              Free (Node);
---              raise;
---        end;
-
---        declare
---           function New_Node return Node_Access;
---           pragma Inline (New_Node);
-
---           function New_Node return Node_Access is
---           begin
---              return Node;
---           end New_Node;
-
---           procedure Insert_Post is
---             new Element_Keys.Generic_Insert_Post (New_Node);
-
---           procedure Insert is
---             new Element_Keys.Generic_Conditional_Insert (Insert_Post);
-
---           Result  : Node_Access;
---           Success : Boolean;
-
---        begin
---           Insert
---             (Tree    => Container.Tree,
---              Key     => Node.Element.all,
---              Node    => Result,
---              Success => Success);
-
---           if not Success then
---              Free (Node);
---              raise Program_Error;
---           end if;
-
---           pragma Assert (Result = Node);
---        end;
---     end Replace_Element;
-
-
---     procedure Replace_Element
---      (Container : in out Set;
---       Position  : Cursor;
---       By        : Element_Type)
---     is
---     begin
---        if Position.Container = null then
---           raise Constraint_Error;
---        end if;
-
---        if Position.Container /= Set_Access'(Container'Unchecked_Access) then
---           raise Program_Error;
---        end if;
-
---        Replace_Element (Container, Position.Node, By);
---     end Replace_Element;
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type)
+   is
+   begin
+      if Item < Node.Element.all
+        or else Node.Element.all < Item
+      then
+         null;
+      else
+         if Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
+
+         declare
+            X : Element_Access := Node.Element;
+         begin
+            Node.Element := new Element_Type'(Item);
+            Free_Element (X);
+         end;
+
+         return;
+      end if;
+
+      Tree_Operations.Delete_Node_Sans_Free (Tree, Node);  -- Checks busy-bit
+
+      Insert_New_Item : declare
+         function New_Node return Node_Access;
+         pragma Inline (New_Node);
+
+         procedure Insert_Post is
+            new Element_Keys.Generic_Insert_Post (New_Node);
+
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (Insert_Post);
+
+         --------------
+         -- New_Node --
+         --------------
+
+         function New_Node return Node_Access is
+         begin
+            Node.Element := new Element_Type'(Item);  -- OK if fails
+            return Node;
+         end New_Node;
+
+         Result   : Node_Access;
+         Inserted : Boolean;
+
+         X : Element_Access := Node.Element;
+
+      --  Start of processing for Insert_New_Item
+
+      begin
+         Attempt_Insert : begin
+            Insert
+              (Tree    => Tree,
+               Key     => Item,
+               Node    => Result,
+               Success => Inserted);  --  TODO: change name of formal param
+         exception
+            when others =>
+               Inserted := False;
+         end Attempt_Insert;
+
+         if Inserted then
+            pragma Assert (Result = Node);
+            Free_Element (X);  -- OK if fails
+            return;
+         end if;
+      end Insert_New_Item;
+
+      Reinsert_Old_Element : declare
+         function New_Node return Node_Access;
+         pragma Inline (New_Node);
+
+         procedure Insert_Post is
+            new Element_Keys.Generic_Insert_Post (New_Node);
+
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (Insert_Post);
+
+         --------------
+         -- New_Node --
+         --------------
+
+         function New_Node return Node_Access is
+         begin
+            return Node;
+         end New_Node;
+
+         Result   : Node_Access;
+         Inserted : Boolean;
+
+      --  Start of processing for Reinsert_Old_Element
+
+      begin
+         Insert
+           (Tree    => Tree,
+            Key     => Node.Element.all,
+            Node    => Result,
+            Success => Inserted);  --  TODO: change name of formal param
+      exception
+         when others =>
+            null;
+      end Reinsert_Old_Element;
+
+      raise Program_Error;
+   end Replace_Element;
+
+   procedure Replace_Element
+    (Container : Set;
+     Position  : Cursor;
+     By        : Element_Type)
+   is
+      Tree : Tree_Type renames Position.Container.Tree'Unrestricted_Access.all;
+
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
+
+      if Position.Container /= Container'Unrestricted_Access then
+         raise Program_Error;
+      end if;
+
+      Replace_Element (Tree, Position.Node, By);
+   end Replace_Element;
 
    ---------------------
    -- Reverse_Iterate --
@@ -1413,13 +1403,26 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    -----------
@@ -1473,26 +1476,14 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    procedure Symmetric_Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
    end Symmetric_Difference;
 
    function Symmetric_Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Symmetric_Difference;
 
    -----------
@@ -1501,25 +1492,14 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
 
    procedure Union (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Union (Target.Tree, Source.Tree);
    end Union;
 
    function Union (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Union (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Union (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Union;
 
    -----------
@@ -1527,31 +1507,33 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
    -----------
 
    procedure Write
-     (Stream    : access Ada.Streams.Root_Stream_Type'Class;
+     (Stream    : access Root_Stream_Type'Class;
       Container : Set)
    is
-      procedure Process (Node : Node_Access);
-      pragma Inline (Process);
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+      pragma Inline (Write_Node);
 
-      procedure Iterate is
-        new Tree_Operations.Generic_Iteration (Process);
+      procedure Write is
+         new Tree_Operations.Generic_Write (Write_Node);
 
-      -------------
-      -- Process --
-      -------------
+      ----------------
+      -- Write_Node --
+      ----------------
 
-      procedure Process (Node : Node_Access) is
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access)
+      is
       begin
          Element_Type'Output (Stream, Node.Element.all);
-      end Process;
+      end Write_Node;
 
    --  Start of processing for Write
 
    begin
-      Count_Type'Base'Write (Stream, Container.Tree.Length);
-      Iterate (Container.Tree);
+      Write (Stream, Container.Tree);
    end Write;
 
 end Ada.Containers.Indefinite_Ordered_Sets;
-
-
index e05dc1a6638882d2c7767c50188039257662a636..0841bc74560ee7fa6f2f80417dec2dc892abe9a5 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                  ADA.CONTAINERS.INDEFINITE_ORDERED_SETS                  --
+--                      A D A . C O N T A I N E R S .                       --
+--              I N D E F I N I T E _ O R D E R E D _ S E T S               --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -56,6 +57,8 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -68,11 +71,10 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type));
 
-   --  TODO: resolve in Atlanta???
-   --   procedure Replace_Element
-   --     (Container : in out Set;
-   --      Position  : Cursor;
-   --      By        : Element_Type);
+   procedure Replace_Element
+     (Container : Set;   --  TODO: need ruling from ARG
+      Position  : Cursor;
+      By        : Element_Type);
 
    procedure Move (Target : in out Set; Source : in out Set);
 
@@ -98,10 +100,6 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
      (Container : in out Set;
       Item      : Element_Type);
 
-   procedure Exclude
-     (Container : in out Set;
-      Item      : Element_Type);
-
    procedure Delete
      (Container : in out Set;
       Position  : in out Cursor);
@@ -110,6 +108,10 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
 
    procedure Delete_Last (Container : in out Set);
 
+   procedure Exclude
+     (Container : in out Set;
+      Item      : Element_Type);
+
    procedure Union (Target : in out Set; Source : Set);
 
    function Union (Left, Right : Set) return Set;
@@ -157,10 +159,10 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
 
    function Next (Position : Cursor) return Cursor;
 
-   function Previous (Position : Cursor) return Cursor;
-
    procedure Next (Position : in out Cursor);
 
+   function Previous (Position : Cursor) return Cursor;
+
    procedure Previous (Position : in out Cursor);
 
    function Has_Element (Position : Cursor) return Boolean;
@@ -220,11 +222,10 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
         (Container : Set;
          Key       : Key_Type) return Element_Type;
 
-      --  TODO: resolve in Atlanta???
-      --      procedure Replace
-      --        (Container : in out Set;
-      --         Key       : Key_Type;
-      --         New_Item  : Element_Type);
+      procedure Replace
+        (Container : in out Set;  --  TODO: need ruling from ARG
+         Key       : Key_Type;
+         New_Item  : Element_Type);
 
       procedure Delete (Container : in out Set; Key : Key_Type);
 
@@ -238,8 +239,7 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
 
       function ">" (Left : Key_Type; Right : Cursor) return Boolean;
 
-      --  TODO: resolve name in Atlanta???
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : Cursor;
          Process   : not null access
@@ -252,21 +252,33 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package Tree_Types is
-     new Red_Black_Trees.Generic_Tree_Types (Node_Access);
+   type Element_Access is access Element_Type;
 
-   use Tree_Types;
-   use Ada.Finalization;
+   type Node_Type is limited record
+      Parent  : Node_Access;
+      Left    : Node_Access;
+      Right   : Node_Access;
+      Color   : Red_Black_Trees.Color_Type := Red_Black_Trees.Red;
+      Element : Element_Access;
+   end record;
+
+   package Tree_Types is new Red_Black_Trees.Generic_Tree_Types
+     (Node_Type,
+      Node_Access);
 
-   type Set is new Controlled with record
-      Tree : Tree_Type := (Length => 0, others => null);
+   type Set is new Ada.Finalization.Controlled with record
+      Tree : Tree_Types.Tree_Type;
    end record;
 
    procedure Adjust (Container : in out Set);
 
    procedure Finalize (Container : in out Set) renames Clear;
 
-   type Set_Access is access constant Set;
+   use Red_Black_Trees;
+   use Tree_Types;
+   use Ada.Finalization;
+
+   type Set_Access is access all Set;
    for Set_Access'Storage_Size use 0;
 
    type Cursor is record
@@ -291,6 +303,11 @@ private
    for Set'Read use Read;
 
    Empty_Set : constant Set :=
-                 (Controlled with Tree => (Length => 0, others => null));
+                 (Controlled with Tree => (First  => null,
+                                           Last   => null,
+                                           Root   => null,
+                                           Length => 0,
+                                           Busy   => 0,
+                                           Lock   => 0));
 
 end Ada.Containers.Indefinite_Ordered_Sets;
index e1120c1b3577a19838b6e34629a10d4b5f7867b6..97d2723e3362e1317042655486af9ef9b947a19d 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                        ADA.CONTAINERS.HASHED_MAPS                        --
+--            A D A . C O N T A I N E R S . H A S H E D _ M A P S           --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -43,12 +43,6 @@ pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Keys);
 
 package body Ada.Containers.Hashed_Maps is
 
-   type Node_Type is limited record
-      Key     : Key_Type;
-      Element : Element_Type;
-      Next    : Node_Access;
-   end record;
-
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -57,13 +51,15 @@ package body Ada.Containers.Hashed_Maps is
      (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Equivalent_Keys
+   function Equivalent_Key_Node
      (Key  : Key_Type;
       Node : Node_Access) return Boolean;
-   pragma Inline (Equivalent_Keys);
+   pragma Inline (Equivalent_Key_Node);
+
+   procedure Free (X : in out Node_Access);
 
    function Find_Equal_Key
-     (R_Map  : Map;
+     (R_HT   : Hash_Table_Type;
       L_Node : Node_Access) return Boolean;
 
    function Hash_Node (Node : Node_Access) return Hash_Type;
@@ -79,6 +75,8 @@ package body Ada.Containers.Hashed_Maps is
    procedure Set_Next (Node : Node_Access; Next : Node_Access);
    pragma Inline (Set_Next);
 
+   function Vet (Position : Cursor) return Boolean;
+
    procedure Write_Node
      (Stream : access Root_Stream_Type'Class;
       Node   : Node_Access);
@@ -88,14 +86,9 @@ package body Ada.Containers.Hashed_Maps is
    -- Local Instantiations --
    --------------------------
 
-   procedure Free is
-     new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
-
    package HT_Ops is
       new Hash_Tables.Generic_Operations
        (HT_Types          => HT_Types,
-        Hash_Table_Type   => Map,
-        Null_Node         => null,
         Hash_Node         => Hash_Node,
         Next              => Next,
         Set_Next          => Set_Next,
@@ -105,13 +98,11 @@ package body Ada.Containers.Hashed_Maps is
    package Key_Ops is
       new Hash_Tables.Generic_Keys
        (HT_Types  => HT_Types,
-        HT_Type   => Map,
-        Null_Node => null,
         Next      => Next,
         Set_Next  => Set_Next,
         Key_Type  => Key_Type,
         Hash      => Hash,
-        Equivalent_Keys => Equivalent_Keys);
+        Equivalent_Keys => Equivalent_Key_Node);
 
    function Is_Equal is new HT_Ops.Generic_Equal (Find_Equal_Key);
 
@@ -122,26 +113,37 @@ package body Ada.Containers.Hashed_Maps is
    -- "=" --
    ---------
 
-   function "=" (Left, Right : Map) return Boolean renames Is_Equal;
+   function "=" (Left, Right : Map) return Boolean is
+   begin
+      return Is_Equal (Left.HT, Right.HT);
+   end "=";
 
    ------------
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Map) renames HT_Ops.Adjust;
+   procedure Adjust (Container : in out Map) is
+   begin
+      HT_Ops.Adjust (Container.HT);
+   end Adjust;
 
    --------------
    -- Capacity --
    --------------
 
-   function Capacity (Container : Map) return Count_Type
-     renames HT_Ops.Capacity;
+   function Capacity (Container : Map) return Count_Type is
+   begin
+      return HT_Ops.Capacity (Container.HT);
+   end Capacity;
 
    -----------
    -- Clear --
    -----------
 
-   procedure Clear (Container : in out Map) renames HT_Ops.Clear;
+   procedure Clear (Container : in out Map) is
+   begin
+      HT_Ops.Clear (Container.HT);
+   end Clear;
 
    --------------
    -- Contains --
@@ -175,7 +177,7 @@ package body Ada.Containers.Hashed_Maps is
       X : Node_Access;
 
    begin
-      Key_Ops.Delete_Key_Sans_Free (Container, Key, X);
+      Key_Ops.Delete_Key_Sans_Free (Container.HT, Key, X);
 
       if X = null then
          raise Constraint_Error;
@@ -186,17 +188,23 @@ package body Ada.Containers.Hashed_Maps is
 
    procedure Delete (Container : in out Map; Position : in out Cursor) is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
       if Position.Container /= Map_Access'(Container'Unchecked_Access) then
          raise Program_Error;
       end if;
 
-      HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
-      Free (Position.Node);
+      pragma Assert (Position.Node.Next /= Position.Node);
+
+      if Container.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
+      HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node);
+
+      Free (Position.Node);
       Position.Container := null;
    end Delete;
 
@@ -212,19 +220,20 @@ package body Ada.Containers.Hashed_Maps is
 
    function Element (Position : Cursor) return Element_Type is
    begin
+      pragma Assert (Vet (Position));
       return Position.Node.Element;
    end Element;
 
-   ---------------------
-   -- Equivalent_Keys --
-   ---------------------
+   -------------------------
+   -- Equivalent_Key_Node --
+   -------------------------
 
-   function Equivalent_Keys
+   function Equivalent_Key_Node
      (Key  : Key_Type;
       Node : Node_Access) return Boolean is
    begin
       return Equivalent_Keys (Key, Node.Key);
-   end Equivalent_Keys;
+   end Equivalent_Key_Node;
 
    ---------------------
    -- Equivalent_Keys --
@@ -233,16 +242,20 @@ package body Ada.Containers.Hashed_Maps is
    function Equivalent_Keys (Left, Right : Cursor)
      return Boolean is
    begin
+      pragma Assert (Vet (Left));
+      pragma Assert (Vet (Right));
       return Equivalent_Keys (Left.Node.Key, Right.Node.Key);
    end Equivalent_Keys;
 
    function Equivalent_Keys (Left : Cursor; Right : Key_Type) return Boolean is
    begin
+      pragma Assert (Vet (Left));
       return Equivalent_Keys (Left.Node.Key, Right);
    end Equivalent_Keys;
 
    function Equivalent_Keys (Left : Key_Type; Right : Cursor) return Boolean is
    begin
+      pragma Assert (Vet (Right));
       return Equivalent_Keys (Left, Right.Node.Key);
    end Equivalent_Keys;
 
@@ -253,7 +266,7 @@ package body Ada.Containers.Hashed_Maps is
    procedure Exclude (Container : in out Map; Key : Key_Type) is
       X : Node_Access;
    begin
-      Key_Ops.Delete_Key_Sans_Free (Container, Key, X);
+      Key_Ops.Delete_Key_Sans_Free (Container.HT, Key, X);
       Free (X);
    end Exclude;
 
@@ -261,14 +274,17 @@ package body Ada.Containers.Hashed_Maps is
    -- Finalize --
    --------------
 
-   procedure Finalize (Container : in out Map) renames HT_Ops.Finalize;
+   procedure Finalize (Container : in out Map) is
+   begin
+      HT_Ops.Finalize (Container.HT);
+   end Finalize;
 
    ----------
    -- Find --
    ----------
 
    function Find (Container : Map; Key : Key_Type) return Cursor is
-      Node : constant Node_Access := Key_Ops.Find (Container, Key);
+      Node : constant Node_Access := Key_Ops.Find (Container.HT, Key);
 
    begin
       if Node = null then
@@ -283,11 +299,11 @@ package body Ada.Containers.Hashed_Maps is
    --------------------
 
    function Find_Equal_Key
-     (R_Map  : Map;
+     (R_HT   : Hash_Table_Type;
       L_Node : Node_Access) return Boolean
    is
-      R_Index : constant Hash_Type := Key_Ops.Index (R_Map, L_Node.Key);
-      R_Node  : Node_Access := R_Map.Buckets (R_Index);
+      R_Index : constant Hash_Type := Key_Ops.Index (R_HT, L_Node.Key);
+      R_Node  : Node_Access := R_HT.Buckets (R_Index);
 
    begin
       while R_Node /= null loop
@@ -306,7 +322,7 @@ package body Ada.Containers.Hashed_Maps is
    -----------
 
    function First (Container : Map) return Cursor is
-      Node : constant Node_Access := HT_Ops.First (Container);
+      Node : constant Node_Access := HT_Ops.First (Container.HT);
 
    begin
       if Node = null then
@@ -316,13 +332,33 @@ package body Ada.Containers.Hashed_Maps is
       return Cursor'(Container'Unchecked_Access, Node);
    end First;
 
+   ----------
+   -- Free --
+   ----------
+
+   procedure Free (X : in out Node_Access) is
+      procedure Deallocate is
+         new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
+   begin
+      if X /= null then
+         X.Next := X;     --  detect mischief (in Vet)
+         Deallocate (X);
+      end if;
+   end Free;
+
    -----------------
    -- Has_Element --
    -----------------
 
    function Has_Element (Position : Cursor) return Boolean is
    begin
-      return Position /= No_Element;
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return False;
+      end if;
+
+      pragma Assert (Vet (Position));
+      return True;
    end Has_Element;
 
    ---------------
@@ -350,6 +386,10 @@ package body Ada.Containers.Hashed_Maps is
       Insert (Container, Key, New_Item, Position, Inserted);
 
       if not Inserted then
+         if Container.HT.Lock > 0 then
+            raise Program_Error;
+         end if;
+
          Position.Node.Key := Key;
          Position.Node.Element := New_Item;
       end if;
@@ -390,11 +430,30 @@ package body Ada.Containers.Hashed_Maps is
             raise;
       end New_Node;
 
+      HT : Hash_Table_Type renames Container.HT;
+
    --  Start of processing for Insert
 
    begin
-      HT_Ops.Ensure_Capacity (Container, Container.Length + 1);
-      Local_Insert (Container, Key, Position.Node, Inserted);
+      if HT.Length >= HT_Ops.Capacity (HT) then
+
+         --  TODO: 17 Apr 2005
+         --  We should defer the expansion until we're sure that the
+         --  element was successfully inserted.  We can do that by
+         --  first performing the insertion attempt, and allowing the
+         --  invariant len <= cap to be violated temporarily.  After
+         --  the insertion we can restore the invariant.  The
+         --  worst that can happen is that the insertion succeeds
+         --  (new element is added to the map), but the
+         --  invariant is broken (len > cap).  But it's only
+         --  broken by a little (since len = cap + 1), so the
+         --  effect is benign.
+         --  END TODO.
+
+         HT_Ops.Reserve_Capacity (HT, HT.Length + 1);
+      end if;
+
+      Local_Insert (HT, Key, Position.Node, Inserted);
       Position.Container := Container'Unchecked_Access;
    end Insert;
 
@@ -421,11 +480,17 @@ package body Ada.Containers.Hashed_Maps is
          return Node;
       end New_Node;
 
+      HT : Hash_Table_Type renames Container.HT;
+
    --  Start of processing for Insert
 
    begin
-      HT_Ops.Ensure_Capacity (Container, Container.Length + 1);
-      Local_Insert (Container, Key, Position.Node, Inserted);
+      if HT.Length >= HT_Ops.Capacity (HT) then
+         --  TODO: see note above.
+         HT_Ops.Reserve_Capacity (HT, HT.Length + 1);
+      end if;
+
+      Local_Insert (HT, Key, Position.Node, Inserted);
       Position.Container := Container'Unchecked_Access;
    end Insert;
 
@@ -451,7 +516,7 @@ package body Ada.Containers.Hashed_Maps is
 
    function Is_Empty (Container : Map) return Boolean is
    begin
-      return Container.Length = 0;
+      return Container.HT.Length = 0;
    end Is_Empty;
 
    -------------
@@ -479,7 +544,7 @@ package body Ada.Containers.Hashed_Maps is
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container);
+      Local_Iterate (Container.HT);
    end Iterate;
 
    ---------
@@ -488,6 +553,7 @@ package body Ada.Containers.Hashed_Maps is
 
    function Key (Position : Cursor) return Key_Type is
    begin
+      pragma Assert (Vet (Position));
       return Position.Node.Key;
    end Key;
 
@@ -497,7 +563,7 @@ package body Ada.Containers.Hashed_Maps is
 
    function Length (Container : Map) return Count_Type is
    begin
-      return Container.Length;
+      return Container.HT.Length;
    end Length;
 
    ----------
@@ -506,7 +572,11 @@ package body Ada.Containers.Hashed_Maps is
 
    procedure Move
      (Target : in out Map;
-      Source : in out Map) renames HT_Ops.Move;
+      Source : in out Map)
+   is
+   begin
+      HT_Ops.Move (Target => Target.HT, Source => Source.HT);
+   end Move;
 
    ----------
    -- Next --
@@ -519,13 +589,15 @@ package body Ada.Containers.Hashed_Maps is
 
    function Next (Position : Cursor) return Cursor is
    begin
-      if Position = No_Element then
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
          return No_Element;
       end if;
 
       declare
-         M    : Map renames Position.Container.all;
-         Node : constant Node_Access := HT_Ops.Next (M, Position.Node);
+         pragma Assert (Vet (Position));
+         HT   : Hash_Table_Type renames Position.Container.HT;
+         Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
 
       begin
          if Node = null then
@@ -547,10 +619,36 @@ package body Ada.Containers.Hashed_Maps is
 
    procedure Query_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : Element_Type))
+      Process  : not null access
+                   procedure (Key : Key_Type; Element : Element_Type))
+
    is
+      pragma Assert (Vet (Position));
+
+      K : Key_Type renames Position.Node.Key;
+      E : Element_Type renames Position.Node.Element;
+
+      M  : Map renames Position.Container.all;
+      HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
+
+      B : Natural renames HT.Busy;
+      L : Natural renames HT.Lock;
+
    begin
-      Process (Position.Node.Key, Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -559,7 +657,11 @@ package body Ada.Containers.Hashed_Maps is
 
    procedure Read
      (Stream    : access Root_Stream_Type'Class;
-      Container : out Map) renames Read_Nodes;
+      Container : out Map)
+   is
+   begin
+      Read_Nodes (Stream, Container.HT);
+   end Read;
 
    ---------------
    -- Read_Node --
@@ -590,13 +692,17 @@ package body Ada.Containers.Hashed_Maps is
       Key       : Key_Type;
       New_Item  : Element_Type)
    is
-      Node : constant Node_Access := Key_Ops.Find (Container, Key);
+      Node : constant Node_Access := Key_Ops.Find (Container.HT, Key);
 
    begin
       if Node = null then
          raise Constraint_Error;
       end if;
 
+      if Container.HT.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       Node.Key := Key;
       Node.Element := New_Item;
    end Replace;
@@ -606,8 +712,15 @@ package body Ada.Containers.Hashed_Maps is
    ---------------------
 
    procedure Replace_Element (Position : Cursor; By : Element_Type) is
+      pragma Assert (Vet (Position));
+      E : Element_Type renames Position.Node.Element;
+
    begin
-      Position.Node.Element := By;
+      if Position.Container.HT.Lock > 0 then
+         raise Program_Error;
+      end if;
+
+      E := By;
    end Replace_Element;
 
    ----------------------
@@ -616,7 +729,11 @@ package body Ada.Containers.Hashed_Maps is
 
    procedure Reserve_Capacity
      (Container : in out Map;
-      Capacity  : Count_Type) renames HT_Ops.Ensure_Capacity;
+      Capacity  : Count_Type)
+   is
+   begin
+      HT_Ops.Reserve_Capacity (Container.HT, Capacity);
+   end Reserve_Capacity;
 
    --------------
    -- Set_Next --
@@ -633,19 +750,105 @@ package body Ada.Containers.Hashed_Maps is
 
    procedure Update_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : in out Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : in out Element_Type))
    is
+      pragma Assert (Vet (Position));
+
+      K : Key_Type renames Position.Node.Key;
+      E : Element_Type renames Position.Node.Element;
+
+      M  : Map renames Position.Container.all;
+      HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
+
+      B : Natural renames HT.Busy;
+      L : Natural renames HT.Lock;
+
    begin
-      Process (Position.Node.Key, Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
+   ---------
+   -- Vet --
+   ---------
+
+   function Vet (Position : Cursor) return Boolean is
+   begin
+      if Position.Node = null then
+         return False;
+      end if;
+
+      if Position.Node.Next = Position.Node then
+         return False;
+      end if;
+
+      if Position.Container = null then
+         return False;
+      end if;
+
+      declare
+         HT : Hash_Table_Type renames Position.Container.HT;
+         X  : Node_Access;
+      begin
+         if HT.Length = 0 then
+            return False;
+         end if;
+
+         if HT.Buckets = null then
+            return False;
+         end if;
+
+--       NOTE: see notes in Insert.
+--       if HT.Length > HT.Buckets'Length then
+--          return False;
+--       end if;
+
+         X := HT.Buckets (Key_Ops.Index (HT, Position.Node.Key));
+
+         for J in 1 .. HT.Length loop
+            if X = Position.Node then
+               return True;
+            end if;
+
+            if X = null then
+               return False;
+            end if;
+
+            if X = X.Next then  --  weird
+               return False;
+            end if;
+
+            X := X.Next;
+         end loop;
+
+         return False;
+      end;
+   end Vet;
+
    -----------
    -- Write --
    -----------
 
    procedure Write
      (Stream    : access Root_Stream_Type'Class;
-      Container : Map) renames Write_Nodes;
+      Container : Map)
+   is
+   begin
+      Write_Nodes (Stream, Container.HT);
+   end Write;
 
    ----------------
    -- Write_Node --
index 72dd1c2b107785fe62a2c785a36a7d1bddae1308..ceb845b2fbbf5b2df697e36519b027c636e18fbc 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                        ADA.CONTAINERS.HASHED_MAPS                        --
+--            A D A . C O N T A I N E R S . H A S H E D _ M A P S           --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -35,6 +35,7 @@
 
 with Ada.Containers.Hash_Tables;
 with Ada.Streams;
+with Ada.Finalization;
 
 generic
    type Key_Type is private;
@@ -66,8 +67,9 @@ pragma Preelaborate (Hashed_Maps);
 
    procedure Clear (Container : in out Map);
 
-   function Element (Position : Cursor)
-      return Element_Type;
+   function Key (Position : Cursor) return Key_Type;
+
+   function Element (Position : Cursor) return Element_Type;
 
    procedure Query_Element
      (Position : Cursor;
@@ -93,41 +95,36 @@ pragma Preelaborate (Hashed_Maps);
    procedure Insert
      (Container : in out Map;
       Key       : Key_Type;
-      New_Item  : Element_Type);
+      Position  : out Cursor;
+      Inserted  : out Boolean);
 
-   procedure Include
+   procedure Insert
      (Container : in out Map;
       Key       : Key_Type;
       New_Item  : Element_Type);
 
-   procedure Replace
+   procedure Include
      (Container : in out Map;
       Key       : Key_Type;
       New_Item  : Element_Type);
 
-   procedure Insert
+   procedure Replace
      (Container : in out Map;
       Key       : Key_Type;
-      Position  : out Cursor;
-      Inserted  : out Boolean);
+      New_Item  : Element_Type);
 
    procedure Delete (Container : in out Map; Key : Key_Type);
 
-   procedure Exclude (Container : in out Map; Key : Key_Type);
-
    procedure Delete (Container : in out Map; Position : in out Cursor);
 
+   procedure Exclude (Container : in out Map; Key : Key_Type);
+
    function Contains (Container : Map; Key : Key_Type) return Boolean;
 
    function Find (Container : Map; Key : Key_Type) return Cursor;
 
    function Element (Container : Map; Key : Key_Type) return Element_Type;
 
-   function Capacity (Container : Map) return Count_Type;
-
-   procedure Reserve_Capacity (Container : in out Map;
-                               Capacity  : Count_Type);
-
    function First (Container : Map) return Cursor;
 
    function Next (Position : Cursor) return Cursor;
@@ -136,8 +133,6 @@ pragma Preelaborate (Hashed_Maps);
 
    function Has_Element (Position : Cursor) return Boolean;
 
-   function Key (Position : Cursor) return Key_Type;
-
    function Equivalent_Keys (Left, Right : Cursor) return Boolean;
 
    function Equivalent_Keys (Left : Cursor; Right : Key_Type) return Boolean;
@@ -148,16 +143,44 @@ pragma Preelaborate (Hashed_Maps);
      (Container : Map;
       Process   : not null access procedure (Position : Cursor));
 
+   function Capacity (Container : Map) return Count_Type;
+
+   procedure Reserve_Capacity (Container : in out Map;
+                               Capacity  : Count_Type);
+
 private
+   pragma Inline ("=");
+   pragma Inline (Length);
+   pragma Inline (Is_Empty);
+   pragma Inline (Clear);
+   pragma Inline (Key);
+   pragma Inline (Element);
+   pragma Inline (Move);
+   pragma Inline (Contains);
+   pragma Inline (Capacity);
+   pragma Inline (Reserve_Capacity);
+   pragma Inline (Has_Element);
+   pragma Inline (Equivalent_Keys);
 
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package HT_Types is new Hash_Tables.Generic_Hash_Table_Types (Node_Access);
+   type Node_Type is limited record
+      Key     : Key_Type;
+      Element : Element_Type;
+      Next    : Node_Access;
+   end record;
 
-   use HT_Types;
+   package HT_Types is new Hash_Tables.Generic_Hash_Table_Types
+     (Node_Type,
+      Node_Access);
 
-   type Map is new Hash_Table_Type with null record;
+   type Map is new Ada.Finalization.Controlled with record
+      HT : HT_Types.Hash_Table_Type;
+   end record;
+
+   use HT_Types;
+   use Ada.Finalization;
 
    procedure Adjust (Container : in out Map);
 
@@ -177,7 +200,7 @@ private
 
    for Map'Read use Read;
 
-   Empty_Map : constant Map := (Hash_Table_Type with null record);
+   Empty_Map : constant Map := (Controlled with HT => (null, 0, 0, 0));
 
    type Map_Access is access constant Map;
    for Map_Access'Storage_Size use 0;
index 58d04febfd1f3b9b700b3a39e6a7bc34362f7288..7684ace45460526f25af602b6d5984acf74d371e 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                        ADA.CONTAINERS.HASHED_SETS                        --
+--           A D A . C O N T A I N E R S . H A S H E D _ S E T S            --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -41,828 +41,1173 @@ pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Operations);
 with Ada.Containers.Hash_Tables.Generic_Keys;
 pragma Elaborate_All (Ada.Containers.Hash_Tables.Generic_Keys);
 
-with System;  use type System.Address;
-
 with Ada.Containers.Prime_Numbers;
 
-with Ada.Finalization;  use Ada.Finalization;
+with System; use type System.Address;
 
 package body Ada.Containers.Hashed_Sets is
 
-   type Node_Type is
-      limited record
-         Element : Element_Type;
-         Next    : Node_Access;
-      end record;
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
 
-   function Hash_Node
-     (Node : Node_Access) return Hash_Type;
-   pragma Inline (Hash_Node);
+   function Copy_Node (Source : Node_Access) return Node_Access;
+   pragma Inline (Copy_Node);
 
-   function Hash_Node
-     (Node : Node_Access) return Hash_Type is
-   begin
-      return Hash (Node.Element);
-   end Hash_Node;
+   function Equivalent_Keys
+     (Key  : Element_Type;
+      Node : Node_Access) return Boolean;
+   pragma Inline (Equivalent_Keys);
 
-   function Next
-     (Node : Node_Access) return Node_Access;
-   pragma Inline (Next);
+   function Find_Equal_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean;
 
-   function Next
-     (Node : Node_Access) return Node_Access is
-   begin
-      return Node.Next;
-   end Next;
+   function Find_Equivalent_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean;
 
-   procedure Set_Next
-     (Node : Node_Access;
-      Next : Node_Access);
-   pragma Inline (Set_Next);
+   function Hash_Node (Node : Node_Access) return Hash_Type;
+   pragma Inline (Hash_Node);
 
-   procedure Set_Next
-     (Node : Node_Access;
-      Next : Node_Access) is
-   begin
-      Node.Next := Next;
-   end Set_Next;
+   function Is_In
+     (HT  : Hash_Table_Type;
+      Key : Node_Access) return Boolean;
+   pragma Inline (Is_In);
 
-   function Equivalent_Keys
-     (Key  : Element_Type;
-      Node : Node_Access) return Boolean;
-   pragma Inline (Equivalent_Keys);
+   function Next (Node : Node_Access) return Node_Access;
+   pragma Inline (Next);
 
-   function Equivalent_Keys
-     (Key  : Element_Type;
-      Node : Node_Access) return Boolean is
-   begin
-      return Equivalent_Keys (Key, Node.Element);
-   end Equivalent_Keys;
+   function Read_Node (Stream : access Root_Stream_Type'Class)
+     return Node_Access;
+   pragma Inline (Read_Node);
 
-   function Copy_Node
-     (Source : Node_Access) return Node_Access;
-   pragma Inline (Copy_Node);
+   procedure Replace_Element
+     (HT      : in out Hash_Table_Type;
+      Node    : Node_Access;
+      Element : Element_Type);
 
-   function Copy_Node
-     (Source : Node_Access) return Node_Access is
+   procedure Set_Next (Node : Node_Access; Next : Node_Access);
+   pragma Inline (Set_Next);
 
-      Target : constant Node_Access :=
-        new Node_Type'(Element => Source.Element,
-                       Next    => null);
-   begin
-      return Target;
-   end Copy_Node;
+   procedure Write_Node
+     (Stream : access Root_Stream_Type'Class;
+      Node   : Node_Access);
+   pragma Inline (Write_Node);
 
+   --------------------------
+   -- Local Instantiations --
+   --------------------------
 
    procedure Free is
       new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
 
    package HT_Ops is
       new Hash_Tables.Generic_Operations
-       (HT_Types          => HT_Types,
-        Hash_Table_Type   => Set,
-        Null_Node         => null,
-        Hash_Node         => Hash_Node,
-        Next              => Next,
-        Set_Next          => Set_Next,
-        Copy_Node         => Copy_Node,
-        Free              => Free);
+       (HT_Types  => HT_Types,
+        Hash_Node => Hash_Node,
+        Next      => Next,
+        Set_Next  => Set_Next,
+        Copy_Node => Copy_Node,
+        Free      => Free);
 
    package Element_Keys is
       new Hash_Tables.Generic_Keys
        (HT_Types  => HT_Types,
-        HT_Type   => Set,
-        Null_Node => null,
         Next      => Next,
         Set_Next  => Set_Next,
         Key_Type  => Element_Type,
         Hash      => Hash,
         Equivalent_Keys => Equivalent_Keys);
 
+   function Is_Equal is
+      new HT_Ops.Generic_Equal (Find_Equal_Key);
 
-   procedure Adjust (Container : in out Set) renames HT_Ops.Adjust;
-
-   procedure Finalize (Container : in out Set) renames HT_Ops.Finalize;
-
-
-   function Find_Equal_Key
-     (R_Set  : Set;
-      L_Node : Node_Access) return Boolean;
+   function Is_Equivalent is
+      new HT_Ops.Generic_Equal (Find_Equivalent_Key);
 
-   function Find_Equal_Key
-     (R_Set  : Set;
-      L_Node : Node_Access) return Boolean is
+   procedure Read_Nodes is
+      new HT_Ops.Generic_Read (Read_Node);
 
-      R_Index : constant Hash_Type :=
-        Element_Keys.Index (R_Set, L_Node.Element);
+   procedure Write_Nodes is
+      new HT_Ops.Generic_Write (Write_Node);
 
-      R_Node  : Node_Access := R_Set.Buckets (R_Index);
+   ---------
+   -- "=" --
+   ---------
 
+   function "=" (Left, Right : Set) return Boolean is
    begin
+      return Is_Equal (Left.HT, Right.HT);
+   end "=";
 
-      loop
+   ------------
+   -- Adjust --
+   ------------
 
-         if R_Node = null then
-            return False;
-         end if;
+   procedure Adjust (Container : in out Set) is
+   begin
+      HT_Ops.Adjust (Container.HT);
+   end Adjust;
 
-         if L_Node.Element = R_Node.Element then
-            --  pragma Assert (Is_Equal_Key (L_Node.Element, R_Node.Element));
-            return True;
-         end if;
+   --------------
+   -- Capacity --
+   --------------
 
-         R_Node := Next (R_Node);
+   function Capacity (Container : Set) return Count_Type is
+   begin
+      return HT_Ops.Capacity (Container.HT);
+   end Capacity;
 
-      end loop;
+   -----------
+   -- Clear --
+   -----------
 
-   end Find_Equal_Key;
+   procedure Clear (Container : in out Set) is
+   begin
+      HT_Ops.Clear (Container.HT);
+   end Clear;
 
-   function Is_Equal is
-      new HT_Ops.Generic_Equal (Find_Equal_Key);
+   --------------
+   -- Contains --
+   --------------
 
-   function "=" (Left, Right : Set) return Boolean renames Is_Equal;
+   function Contains (Container : Set; Item : Element_Type) return Boolean is
+   begin
+      return Find (Container, Item) /= No_Element;
+   end Contains;
 
+   ---------------
+   -- Copy_Node --
+   ---------------
 
-   function Length (Container : Set) return Count_Type is
+   function Copy_Node (Source : Node_Access) return Node_Access is
    begin
-      return Container.Length;
-   end Length;
+      return new Node_Type'(Element => Source.Element, Next => null);
+   end Copy_Node;
 
+   ------------
+   -- Delete --
+   ------------
 
-   function Is_Empty (Container : Set) return Boolean is
-   begin
-      return Container.Length = 0;
-   end Is_Empty;
+   procedure Delete
+     (Container : in out Set;
+      Item      : Element_Type)
+   is
+      X : Node_Access;
 
+   begin
+      Element_Keys.Delete_Key_Sans_Free (Container.HT, Item, X);
 
-   procedure Clear (Container : in out Set) renames HT_Ops.Clear;
+      if X = null then
+         raise Constraint_Error;
+      end if;
 
+      Free (X);
+   end Delete;
 
-   function Element (Position : Cursor) return Element_Type is
+   procedure Delete
+     (Container : in out Set;
+      Position  : in out Cursor)
+   is
    begin
-      return Position.Node.Element;
-   end Element;
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
 
+      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
+         raise Program_Error;
+      end if;
 
-   procedure Query_Element
-     (Position : in Cursor;
-      Process  : not null access procedure (Element : in Element_Type)) is
-   begin
-      Process (Position.Node.Element);
-   end Query_Element;
+      if Container.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
+      HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node);
 
---  TODO:
---     procedure Replace_Element (Container : in out Set;
---                                Position  : in     Node_Access;
---                                By        : in     Element_Type) is
+      Free (Position.Node);
 
---        Node : Node_Access := Position;
+      Position.Container := null;
+   end Delete;
 
---     begin
+   ----------------
+   -- Difference --
+   ----------------
 
---        if Equivalent_Keys (Node.Element, By) then
+   procedure Difference
+     (Target : in out Set;
+      Source : Set)
+   is
+      Tgt_Node : Node_Access;
 
---           begin
---              Node.Element := By;
---           exception
---              when others =>
---                 HT_Ops.Delete_Node_Sans_Free (Container, Node);
---                 Free (Node);
---                 raise;
---           end;
+   begin
+      if Target'Address = Source'Address then
+         Clear (Target);
+         return;
+      end if;
 
---           return;
+      if Source.Length = 0 then
+         return;
+      end if;
 
---        end if;
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
---        HT_Ops.Delete_Node_Sans_Free (Container, Node);
+      --  TODO: This can be written in terms of a loop instead as
+      --  active-iterator style, sort of like a passive iterator.
 
---        begin
---           Node.Element := By;
---        exception
---           when others =>
---              Free (Node);
---              raise;
---        end;
+      Tgt_Node := HT_Ops.First (Target.HT);
+      while Tgt_Node /= null loop
+         if Is_In (Source.HT, Tgt_Node) then
+            declare
+               X : Node_Access := Tgt_Node;
+            begin
+               Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
+               HT_Ops.Delete_Node_Sans_Free (Target.HT, X);
+               Free (X);
+            end;
 
---        declare
---           function New_Node (Next : Node_Access) return Node_Access;
---           pragma Inline (New_Node);
+         else
+            Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
+         end if;
+      end loop;
+   end Difference;
 
---           function New_Node (Next : Node_Access) return Node_Access is
---           begin
---              Node.Next := Next;
---              return Node;
---           end New_Node;
+   function Difference (Left, Right : Set) return Set is
+      Buckets : HT_Types.Buckets_Access;
+      Length  : Count_Type;
 
---           procedure Insert is
---              new Element_Keys.Generic_Conditional_Insert (New_Node);
+   begin
+      if Left'Address = Right'Address then
+         return Empty_Set;
+      end if;
 
---           Result  : Node_Access;
---           Success : Boolean;
---        begin
---           Insert
---             (HT      => Container,
---              Key     => Node.Element,
---              Node    => Result,
---              Success => Success);
+      if Left.Length = 0 then
+         return Empty_Set;
+      end if;
 
---           if not Success then
---              Free (Node);
---              raise Program_Error;
---           end if;
+      if Right.Length = 0 then
+         return Left;
+      end if;
 
---           pragma Assert (Result = Node);
---        end;
+      declare
+         Size : constant Hash_Type := Prime_Numbers.To_Prime (Left.Length);
+      begin
+         Buckets := new Buckets_Type (0 .. Size - 1);
+      end;
 
---     end Replace_Element;
+      Length := 0;
 
+      Iterate_Left : declare
+         procedure Process (L_Node : Node_Access);
 
---     procedure Replace_Element (Container : in out Set;
---                                Position  : in     Cursor;
---                                By        : in     Element_Type) is
---     begin
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
 
---        if Position.Container = null then
---           raise Constraint_Error;
---        end if;
+         -------------
+         -- Process --
+         -------------
 
---        if Position.Container /= Set_Access'(Container'Unchecked_Access) then
---           raise Program_Error;
---        end if;
+         procedure Process (L_Node : Node_Access) is
+         begin
+            if not Is_In (Right.HT, L_Node) then
+               declare
+                  J : constant Hash_Type :=
+                        Hash (L_Node.Element) mod Buckets'Length;
 
---        Replace_Element (Container, Position.Node, By);
+                  Bucket : Node_Access renames Buckets (J);
 
---     end Replace_Element;
+               begin
+                  Bucket := new Node_Type'(L_Node.Element, Bucket);
+               end;
 
+               Length := Length + 1;
+            end if;
+         end Process;
 
-   procedure Move (Target : in out Set;
-                   Source : in out Set) renames HT_Ops.Move;
+      --  Start of processing for Iterate_Left
 
+      begin
+         Iterate (Left.HT);
+      exception
+         when others =>
+            HT_Ops.Free_Hash_Table (Buckets);
+            raise;
+      end Iterate_Left;
 
-   procedure Insert (Container : in out Set;
-                     New_Item  : in     Element_Type;
-                     Position  :    out Cursor;
-                     Inserted  :    out Boolean) is
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Difference;
 
-      function New_Node (Next : Node_Access) return Node_Access;
-      pragma Inline (New_Node);
+   -------------
+   -- Element --
+   -------------
 
-      function New_Node (Next : Node_Access) return Node_Access is
-         Node : constant Node_Access := new Node_Type'(New_Item, Next);
-      begin
-         return Node;
-      end New_Node;
+   function Element (Position : Cursor) return Element_Type is
+   begin
+      return Position.Node.Element;
+   end Element;
 
-      procedure Insert is
-        new Element_Keys.Generic_Conditional_Insert (New_Node);
+   ---------------------
+   -- Equivalent_Sets --
+   ---------------------
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean is
    begin
+      return Is_Equivalent (Left.HT, Right.HT);
+   end Equivalent_Sets;
 
-      HT_Ops.Ensure_Capacity (Container, Container.Length + 1);
-      Insert (Container, New_Item, Position.Node, Inserted);
-      Position.Container := Container'Unchecked_Access;
+   -------------------------
+   -- Equivalent_Elements --
+   -------------------------
 
-   end Insert;
+   function Equivalent_Elements (Left, Right : Cursor)
+     return Boolean is
+   begin
+      return Equivalent_Elements (Left.Node.Element, Right.Node.Element);
+   end Equivalent_Elements;
 
+   function Equivalent_Elements (Left : Cursor; Right : Element_Type)
+     return Boolean is
+   begin
+      return Equivalent_Elements (Left.Node.Element, Right);
+   end Equivalent_Elements;
 
-   procedure Insert (Container : in out Set;
-                     New_Item  : in     Element_Type) is
+   function Equivalent_Elements (Left : Element_Type; Right : Cursor)
+     return Boolean is
+   begin
+      return Equivalent_Elements (Left, Right.Node.Element);
+   end Equivalent_Elements;
 
-      Position : Cursor;
-      Inserted : Boolean;
+   ---------------------
+   -- Equivalent_Keys --
+   ---------------------
 
+   function Equivalent_Keys (Key : Element_Type; Node : Node_Access)
+     return Boolean is
    begin
+      return Equivalent_Elements (Key, Node.Element);
+   end Equivalent_Keys;
 
-      Insert (Container, New_Item, Position, Inserted);
+   -------------
+   -- Exclude --
+   -------------
 
-      if not Inserted then
-         raise Constraint_Error;
-      end if;
+   procedure Exclude
+     (Container : in out Set;
+      Item      : Element_Type)
+   is
+      X : Node_Access;
+   begin
+      Element_Keys.Delete_Key_Sans_Free (Container.HT, Item, X);
+      Free (X);
+   end Exclude;
 
-   end Insert;
+   --------------
+   -- Finalize --
+   --------------
 
+   procedure Finalize (Container : in out Set) is
+   begin
+      HT_Ops.Finalize (Container.HT);
+   end Finalize;
 
-   procedure Replace (Container : in out Set;
-                      New_Item  : in     Element_Type) is
+   ----------
+   -- Find --
+   ----------
 
-      X : Node_Access := Element_Keys.Find (Container, New_Item);
+   function Find
+     (Container : Set;
+      Item      : Element_Type) return Cursor
+   is
+      Node : constant Node_Access := Element_Keys.Find (Container.HT, Item);
 
    begin
-
-      if X = null then
-         raise Constraint_Error;
+      if Node = null then
+         return No_Element;
       end if;
 
-      X.Element := New_Item;
-
-   end Replace;
+      return Cursor'(Container'Unrestricted_Access, Node);
+   end Find;
 
+   --------------------
+   -- Find_Equal_Key --
+   --------------------
 
-   procedure Include (Container : in out Set;
-                      New_Item  : in     Element_Type) is
+   function Find_Equal_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean
+   is
+      R_Index : constant Hash_Type :=
+                  Element_Keys.Index (R_HT, L_Node.Element);
 
-      Position : Cursor;
-      Inserted : Boolean;
+      R_Node  : Node_Access := R_HT.Buckets (R_Index);
 
    begin
+      loop
+         if R_Node = null then
+            return False;
+         end if;
 
-      Insert (Container, New_Item, Position, Inserted);
-
-      if not Inserted then
-         Position.Node.Element := New_Item;
-      end if;
+         if L_Node.Element = R_Node.Element then
+            return True;
+         end if;
 
-   end Include;
+         R_Node := Next (R_Node);
+      end loop;
+   end Find_Equal_Key;
 
+   -------------------------
+   -- Find_Equivalent_Key --
+   -------------------------
 
-   procedure Delete (Container : in out Set;
-                     Item      : in     Element_Type) is
+   function Find_Equivalent_Key
+     (R_HT   : Hash_Table_Type;
+      L_Node : Node_Access) return Boolean
+   is
+      R_Index : constant Hash_Type :=
+                  Element_Keys.Index (R_HT, L_Node.Element);
 
-      X : Node_Access;
+      R_Node  : Node_Access := R_HT.Buckets (R_Index);
 
    begin
+      loop
+         if R_Node = null then
+            return False;
+         end if;
 
-      Element_Keys.Delete_Key_Sans_Free (Container, Item, X);
+         if Equivalent_Elements (L_Node.Element, R_Node.Element) then
+            return True;
+         end if;
 
-      if X = null then
-         raise Constraint_Error;
-      end if;
+         R_Node := Next (R_Node);
+      end loop;
+   end Find_Equivalent_Key;
 
-      Free (X);
+   -----------
+   -- First --
+   -----------
 
-   end Delete;
+   function First (Container : Set) return Cursor is
+      Node : constant Node_Access := HT_Ops.First (Container.HT);
 
+   begin
+      if Node = null then
+         return No_Element;
+      end if;
 
-   procedure Exclude (Container : in out Set;
-                      Item      : in     Element_Type) is
+      return Cursor'(Container'Unrestricted_Access, Node);
+   end First;
 
-      X : Node_Access;
+   -----------------
+   -- Has_Element --
+   -----------------
 
+   function Has_Element (Position : Cursor) return Boolean is
    begin
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return False;
+      end if;
 
-      Element_Keys.Delete_Key_Sans_Free (Container, Item, X);
-      Free (X);
-
-   end Exclude;
+      return True;
+   end Has_Element;
 
+   ---------------
+   -- Hash_Node --
+   ---------------
 
-   procedure Delete (Container : in out Set;
-                     Position  : in out Cursor) is
+   function Hash_Node (Node : Node_Access) return Hash_Type is
    begin
+      return Hash (Node.Element);
+   end Hash_Node;
 
-      if Position = No_Element then
-         return;
-      end if;
+   -------------
+   -- Include --
+   -------------
 
-      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
-         raise Program_Error;
+   procedure Include
+     (Container : in out Set;
+      New_Item  : Element_Type)
+   is
+      Position : Cursor;
+      Inserted : Boolean;
+
+   begin
+      Insert (Container, New_Item, Position, Inserted);
+
+      if not Inserted then
+         if Container.HT.Lock > 0 then
+            raise Program_Error;
+         end if;
+
+         Position.Node.Element := New_Item;
       end if;
+   end Include;
 
-      HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
-      Free (Position.Node);
+   ------------
+   -- Insert --
+   ------------
 
-      Position.Container := null;
+   procedure Insert
+     (Container : in out Set;
+      New_Item  : Element_Type;
+      Position  : out Cursor;
+      Inserted  : out Boolean)
+   is
+      function New_Node (Next : Node_Access) return Node_Access;
+      pragma Inline (New_Node);
 
-   end Delete;
+      procedure Local_Insert is
+        new Element_Keys.Generic_Conditional_Insert (New_Node);
 
+      --------------
+      -- New_Node --
+      --------------
 
+      function New_Node (Next : Node_Access) return Node_Access is
+         Node : constant Node_Access := new Node_Type'(New_Item, Next);
+      begin
+         return Node;
+      end New_Node;
 
-   procedure Union (Target : in out Set;
-                    Source : in     Set) is
+      HT : Hash_Table_Type renames Container.HT;
 
-      procedure Process (Src_Node : in Node_Access);
+   --  Start of processing for Insert
 
-      procedure Process (Src_Node : in Node_Access) is
+   begin
+      if HT.Length >= HT_Ops.Capacity (HT) then
 
-         function New_Node (Next : Node_Access) return Node_Access;
-         pragma Inline (New_Node);
+         --  TODO:
+         --  Perform the insertion first, and then reserve
+         --  capacity, but only if the insertion succeeds and
+         --  the (new) length is greater then current capacity.
+         --  END TODO.
 
-         function New_Node (Next : Node_Access) return Node_Access is
-            Node : constant Node_Access :=
-              new Node_Type'(Src_Node.Element, Next);
-         begin
-            return Node;
-         end New_Node;
+         HT_Ops.Reserve_Capacity (HT, HT.Length + 1);
+      end if;
 
-         procedure Insert is
-            new Element_Keys.Generic_Conditional_Insert (New_Node);
+      Local_Insert (HT, New_Item, Position.Node, Inserted);
+      Position.Container := Container'Unchecked_Access;
+   end Insert;
 
-         Tgt_Node : Node_Access;
-         Success  : Boolean;
+   procedure Insert
+     (Container : in out Set;
+      New_Item  : Element_Type)
+   is
+      Position : Cursor;
+      Inserted : Boolean;
 
-      begin
+   begin
+      Insert (Container, New_Item, Position, Inserted);
 
-         Insert (Target, Src_Node.Element, Tgt_Node, Success);
+      if not Inserted then
+         raise Constraint_Error;
+      end if;
+   end Insert;
 
-      end Process;
+   ------------------
+   -- Intersection --
+   ------------------
 
-      procedure Iterate is
-         new HT_Ops.Generic_Iteration (Process);
+   procedure Intersection
+     (Target : in out Set;
+      Source : Set)
+   is
+      Tgt_Node : Node_Access;
 
    begin
-
       if Target'Address = Source'Address then
          return;
       end if;
 
-      HT_Ops.Ensure_Capacity (Target, Target.Length + Source.Length);
-
-      Iterate (Source);
+      if Source.Length = 0 then
+         Clear (Target);
+         return;
+      end if;
 
-   end Union;
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
+      --  TODO: optimize this to use an explicit
+      --  loop instead of an active iterator
+      --  (similar to how a passive iterator is
+      --  implemented).
+      --
+      --  Another possibility is to test which
+      --  set is smaller, and iterate over the
+      --  smaller set.
 
+      Tgt_Node := HT_Ops.First (Target.HT);
+      while Tgt_Node /= null loop
+         if Is_In (Source.HT, Tgt_Node) then
+            Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
 
-   function Union (Left, Right : Set) return Set is
+         else
+            declare
+               X : Node_Access := Tgt_Node;
+            begin
+               Tgt_Node := HT_Ops.Next (Target.HT, Tgt_Node);
+               HT_Ops.Delete_Node_Sans_Free (Target.HT, X);
+               Free (X);
+            end;
+         end if;
+      end loop;
+   end Intersection;
 
+   function Intersection (Left, Right : Set) return Set is
       Buckets : HT_Types.Buckets_Access;
       Length  : Count_Type;
 
    begin
-
       if Left'Address = Right'Address then
          return Left;
       end if;
 
-      if Right.Length = 0 then
-         return Left;
-      end if;
+      Length := Count_Type'Min (Left.Length, Right.Length);
 
-      if Left.Length = 0 then
-         return Right;
+      if Length = 0 then
+         return Empty_Set;
       end if;
 
       declare
-         Size : constant Hash_Type :=
-           Prime_Numbers.To_Prime (Left.Length + Right.Length);
+         Size : constant Hash_Type := Prime_Numbers.To_Prime (Length);
       begin
          Buckets := new Buckets_Type (0 .. Size - 1);
       end;
 
-      declare
-         procedure Process (L_Node : Node_Access);
+      Length := 0;
 
-         procedure Process (L_Node : Node_Access) is
-            I : constant Hash_Type :=
-              Hash (L_Node.Element) mod Buckets'Length;
-         begin
-            Buckets (I) := new Node_Type'(L_Node.Element, Buckets (I));
-         end Process;
+      Iterate_Left : declare
+         procedure Process (L_Node : Node_Access);
 
          procedure Iterate is
             new HT_Ops.Generic_Iteration (Process);
-      begin
-         Iterate (Left);
-      exception
-         when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
-            raise;
-      end;
-
-      Length := Left.Length;
-
-      declare
-         procedure Process (Src_Node : Node_Access);
-
-         procedure Process (Src_Node : Node_Access) is
-
-            I : constant Hash_Type :=
-              Hash (Src_Node.Element) mod Buckets'Length;
 
-            Tgt_Node : Node_Access := Buckets (I);
+         -------------
+         -- Process --
+         -------------
 
+         procedure Process (L_Node : Node_Access) is
          begin
+            if Is_In (Right.HT, L_Node) then
+               declare
+                  J : constant Hash_Type :=
+                        Hash (L_Node.Element) mod Buckets'Length;
 
-            while Tgt_Node /= null loop
-
-               if Equivalent_Keys (Src_Node.Element, Tgt_Node.Element) then
-                  return;
-               end if;
-
-               Tgt_Node := Next (Tgt_Node);
+                  Bucket : Node_Access renames Buckets (J);
 
-            end loop;
-
-            Buckets (I) := new Node_Type'(Src_Node.Element, Buckets (I));
-            Length := Length + 1;
+               begin
+                  Bucket := new Node_Type'(L_Node.Element, Bucket);
+               end;
 
+               Length := Length + 1;
+            end if;
          end Process;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
+      --  Start of processing for Iterate_Left
+
       begin
-         Iterate (Right);
+         Iterate (Left.HT);
       exception
          when others =>
             HT_Ops.Free_Hash_Table (Buckets);
             raise;
-      end;
+      end Iterate_Left;
 
-      return (Controlled with Buckets, Length);
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Intersection;
 
-   end Union;
+   --------------
+   -- Is_Empty --
+   --------------
 
+   function Is_Empty (Container : Set) return Boolean is
+   begin
+      return Container.Length = 0;
+   end Is_Empty;
 
-   function Is_In
-     (HT  : Set;
-      Key : Node_Access) return Boolean;
-   pragma Inline (Is_In);
+   -----------
+   -- Is_In --
+   -----------
 
-   function Is_In
-     (HT  : Set;
-      Key : Node_Access) return Boolean is
+   function Is_In (HT : Hash_Table_Type; Key : Node_Access) return Boolean is
    begin
       return Element_Keys.Find (HT, Key.Element) /= null;
    end Is_In;
 
+   ---------------
+   -- Is_Subset --
+   ---------------
 
-   procedure Intersection (Target : in out Set;
-                           Source : in     Set) is
-
-      Tgt_Node : Node_Access;
+   function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
+      Subset_Node : Node_Access;
 
    begin
-
-      if Target'Address = Source'Address then
-         return;
+      if Subset'Address = Of_Set'Address then
+         return True;
       end if;
 
-      if Source.Length = 0 then
-         Clear (Target);
-         return;
+      if Subset.Length > Of_Set.Length then
+         return False;
       end if;
 
-      --  TODO: optimize this to use an explicit
-      --  loop instead of an active iterator
-      --  (similar to how a passive iterator is
-      --  implemented).
-      --
-      --  Another possibility is to test which
-      --  set is smaller, and iterate over the
-      --  smaller set.
+      --  TODO: rewrite this to loop in the
+      --  style of a passive iterator.
 
-      Tgt_Node := HT_Ops.First (Target);
+      Subset_Node := HT_Ops.First (Subset.HT);
+      while Subset_Node /= null loop
+         if not Is_In (Of_Set.HT, Subset_Node) then
+            return False;
+         end if;
+         Subset_Node := HT_Ops.Next (Subset.HT, Subset_Node);
+      end loop;
 
-      while Tgt_Node /= null loop
+      return True;
+   end Is_Subset;
 
-         if Is_In (Source, Tgt_Node) then
+   -------------
+   -- Iterate --
+   -------------
 
-            Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
+   procedure Iterate
+     (Container : Set;
+      Process   : not null access procedure (Position : Cursor))
+   is
+      procedure Process_Node (Node : Node_Access);
+      pragma Inline (Process_Node);
 
-         else
+      procedure Iterate is
+         new HT_Ops.Generic_Iteration (Process_Node);
 
-            declare
-               X : Node_Access := Tgt_Node;
-            begin
-               Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
-               HT_Ops.Delete_Node_Sans_Free (Target, X);
-               Free (X);
-            end;
+      ------------------
+      -- Process_Node --
+      ------------------
 
-         end if;
+      procedure Process_Node (Node : Node_Access) is
+      begin
+         Process (Cursor'(Container'Unrestricted_Access, Node));
+      end Process_Node;
 
-      end loop;
+      HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
+      B  : Natural renames HT.Busy;
 
-   end Intersection;
+   --  Start of processing for Iterate
 
+   begin
+      B := B + 1;
 
-   function Intersection (Left, Right : Set) return Set is
+      begin
+         Iterate (HT);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
 
-      Buckets : HT_Types.Buckets_Access;
-      Length  : Count_Type;
+      B := B - 1;
+   end Iterate;
+
+   ------------
+   -- Length --
+   ------------
 
+   function Length (Container : Set) return Count_Type is
    begin
+      return Container.HT.Length;
+   end Length;
 
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
+   ----------
+   -- Move --
+   ----------
 
-      Length := Count_Type'Min (Left.Length, Right.Length);
+   procedure Move (Target : in out Set; Source : in out Set) is
+   begin
+      HT_Ops.Move (Target => Target.HT, Source => Source.HT);
+   end Move;
 
-      if Length = 0 then
-         return Empty_Set;
+   ----------
+   -- Next --
+   ----------
+
+   function Next (Node : Node_Access) return Node_Access is
+   begin
+      return Node.Next;
+   end Next;
+
+   function Next (Position : Cursor) return Cursor is
+   begin
+      if Position.Node = null then
+         pragma Assert (Position.Container = null);
+         return No_Element;
       end if;
 
       declare
-         Size : constant Hash_Type := Prime_Numbers.To_Prime (Length);
+         HT   : Hash_Table_Type renames Position.Container.HT;
+         Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
+
       begin
-         Buckets := new Buckets_Type (0 .. Size - 1);
+         if Node = null then
+            return No_Element;
+         end if;
+
+         return Cursor'(Position.Container, Node);
       end;
+   end Next;
+
+   procedure Next (Position : in out Cursor) is
+   begin
+      Position := Next (Position);
+   end Next;
+
+   -------------
+   -- Overlap --
+   -------------
+
+   function Overlap (Left, Right : Set) return Boolean is
+      Left_Node : Node_Access;
+
+   begin
+      if Right.Length = 0 then
+         return False;
+      end if;
+
+      if Left'Address = Right'Address then
+         return True;
+      end if;
+
+      Left_Node := HT_Ops.First (Left.HT);
+      while Left_Node /= null loop
+         if Is_In (Right.HT, Left_Node) then
+            return True;
+         end if;
+         Left_Node := HT_Ops.Next (Left.HT, Left_Node);
+      end loop;
 
-      Length := 0;
+      return False;
+   end Overlap;
 
-      declare
-         procedure Process (L_Node : Node_Access);
+   -------------------
+   -- Query_Element --
+   -------------------
 
-         procedure Process (L_Node : Node_Access) is
-         begin
-            if Is_In (Right, L_Node) then
+   procedure Query_Element
+     (Position : Cursor;
+      Process  : not null access procedure (Element : Element_Type))
+   is
+      E : Element_Type renames Position.Node.Element;
 
-               declare
-                  I : constant Hash_Type :=
-                    Hash (L_Node.Element) mod Buckets'Length;
-               begin
-                  Buckets (I) := new Node_Type'(L_Node.Element, Buckets (I));
-               end;
+      HT : Hash_Table_Type renames Position.Container.HT;
 
-               Length := Length + 1;
+      B : Natural renames HT.Busy;
+      L : Natural renames HT.Lock;
 
-            end if;
-         end Process;
+   begin
+      B := B + 1;
+      L := L + 1;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
       begin
-         Iterate (Left);
+         Process (E);
       exception
          when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
+            L := L - 1;
+            B := B - 1;
             raise;
       end;
 
-      return (Controlled with Buckets, Length);
-
-   end Intersection;
+      L := L - 1;
+      B := B - 1;
+   end Query_Element;
 
+   ----------
+   -- Read --
+   ----------
 
-   procedure Difference (Target : in out Set;
-                         Source : in     Set) is
+   procedure Read
+     (Stream    : access Root_Stream_Type'Class;
+      Container :    out Set)
+   is
+   begin
+      Read_Nodes (Stream, Container.HT);
+   end Read;
 
+   ---------------
+   -- Read_Node --
+   ---------------
 
-      Tgt_Node : Node_Access;
+   function Read_Node (Stream : access Root_Stream_Type'Class)
+     return Node_Access
+   is
+      Node : Node_Access := new Node_Type;
 
    begin
+      Element_Type'Read (Stream, Node.Element);
+      return Node;
+   exception
+      when others =>
+         Free (Node);
+         raise;
+   end Read_Node;
 
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
-      if Source.Length = 0 then
-         return;
-      end if;
-
-      --  TODO: As I noted above, this can be
-      --  written in terms of a loop instead as
-      --  active-iterator style, sort of like a
-      --  passive iterator.
+   -------------
+   -- Replace --
+   -------------
 
-      Tgt_Node := HT_Ops.First (Target);
+   procedure Replace
+     (Container : in out Set;    --  TODO: need ruling from ARG
+      New_Item  : Element_Type)
+   is
+      Node : constant Node_Access :=
+               Element_Keys.Find (Container.HT, New_Item);
 
-      while Tgt_Node /= null loop
+   begin
+      if Node = null then
+         raise Constraint_Error;
+      end if;
 
-         if Is_In (Source, Tgt_Node) then
+      if Container.HT.Lock > 0 then
+         raise Program_Error;
+      end if;
 
-            declare
-               X : Node_Access := Tgt_Node;
-            begin
-               Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
-               HT_Ops.Delete_Node_Sans_Free (Target, X);
-               Free (X);
-            end;
+      Node.Element := New_Item;
+   end Replace;
 
-         else
+   ---------------------
+   -- Replace_Element --
+   ---------------------
 
-            Tgt_Node := HT_Ops.Next (Target, Tgt_Node);
+   procedure Replace_Element
+     (HT      : in out Hash_Table_Type;
+      Node    : Node_Access;
+      Element : Element_Type)
+   is
+   begin
+      if Equivalent_Elements (Node.Element, Element) then
+         pragma Assert (Hash (Node.Element) = Hash (Element));
 
+         if HT.Lock > 0 then
+            raise Program_Error;
          end if;
 
-      end loop;
-
-   end Difference;
+         Node.Element := Element;  --  Note that this assignment can fail
+         return;
+      end if;
 
+      if HT.Busy > 0 then
+         raise Program_Error;
+      end if;
 
+      HT_Ops.Delete_Node_Sans_Free (HT, Node);
 
-   function Difference (Left, Right : Set) return Set is
+      Insert_New_Element : declare
+         function New_Node (Next : Node_Access) return Node_Access;
+         pragma Inline (New_Node);
 
-      Buckets : HT_Types.Buckets_Access;
-      Length  : Count_Type;
+         procedure Local_Insert is
+            new Element_Keys.Generic_Conditional_Insert (New_Node);
 
-   begin
+         --------------
+         -- New_Node --
+         --------------
 
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
+         function New_Node (Next : Node_Access) return Node_Access is
+         begin
+            Node.Element := Element;  -- Note that this assignment can fail
+            Node.Next := Next;
+            return Node;
+         end New_Node;
 
-      if Left.Length = 0 then
-         return Empty_Set;
-      end if;
+         Result   : Node_Access;
+         Inserted : Boolean;
 
-      if Right.Length = 0 then
-         return Left;
-      end if;
+      --  Start of processing for Insert_New_Element
 
-      declare
-         Size : constant Hash_Type := Prime_Numbers.To_Prime (Left.Length);
       begin
-         Buckets := new Buckets_Type (0 .. Size - 1);
-      end;
+         Local_Insert
+           (HT       => HT,
+            Key      => Element,
+            Node     => Result,
+            Inserted => Inserted);
+
+         if Inserted then
+            pragma Assert (Result = Node);
+            return;
+         end if;
+      exception
+         when others =>
+            null;   --  Assignment must have failed
+      end Insert_New_Element;
 
-      Length := 0;
+      Reinsert_Old_Element : declare
+         function New_Node (Next : Node_Access) return Node_Access;
+         pragma Inline (New_Node);
 
-      declare
-         procedure Process (L_Node : Node_Access);
+         procedure Local_Insert is
+            new Element_Keys.Generic_Conditional_Insert (New_Node);
 
-         procedure Process (L_Node : Node_Access) is
-         begin
-            if not Is_In (Right, L_Node) then
+         --------------
+         -- New_Node --
+         --------------
 
-               declare
-                  I : constant Hash_Type :=
-                    Hash (L_Node.Element) mod Buckets'Length;
-               begin
-                  Buckets (I) := new Node_Type'(L_Node.Element, Buckets (I));
-               end;
+         function New_Node (Next : Node_Access) return Node_Access is
+         begin
+            Node.Next := Next;
+            return Node;
+         end New_Node;
 
-               Length := Length + 1;
+         Result   : Node_Access;
+         Inserted : Boolean;
 
-            end if;
-         end Process;
+      --  Start of processing for Reinsert_Old_Element
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
       begin
-         Iterate (Left);
+         Local_Insert
+           (HT       => HT,
+            Key      => Node.Element,
+            Node     => Result,
+            Inserted => Inserted);
       exception
          when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
-            raise;
-      end;
+            null;
+      end Reinsert_Old_Element;
 
-      return (Controlled with Buckets, Length);
+      raise Program_Error;
+   end Replace_Element;
 
-   end Difference;
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type)
+   is
+      HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
+
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
+
+      if Position.Container /= Set_Access'(Container'Unrestricted_Access) then
+         raise Program_Error;
+      end if;
+
+      Replace_Element (HT, Position.Node, By);
+   end Replace_Element;
 
+   ----------------------
+   -- Reserve_Capacity --
+   ----------------------
+
+   procedure Reserve_Capacity
+     (Container : in out Set;
+      Capacity  : Count_Type)
+   is
+   begin
+      HT_Ops.Reserve_Capacity (Container.HT, Capacity);
+   end Reserve_Capacity;
 
+   --------------
+   -- Set_Next --
+   --------------
 
-   procedure Symmetric_Difference (Target : in out Set;
-                                   Source : in     Set) is
+   procedure Set_Next (Node : Node_Access; Next : Node_Access) is
    begin
+      Node.Next := Next;
+   end Set_Next;
 
+   --------------------------
+   -- Symmetric_Difference --
+   --------------------------
+
+   procedure Symmetric_Difference
+     (Target : in out Set;
+      Source : Set)
+   is
+   begin
       if Target'Address = Source'Address then
          Clear (Target);
          return;
       end if;
 
-      HT_Ops.Ensure_Capacity (Target, Target.Length + Source.Length);
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      declare
+         N : constant Count_Type := Target.Length + Source.Length;
+      begin
+         if N > HT_Ops.Capacity (Target.HT) then
+            HT_Ops.Reserve_Capacity (Target.HT, N);
+         end if;
+      end;
 
       if Target.Length = 0 then
-
-         declare
+         Iterate_Source_When_Empty_Target : declare
             procedure Process (Src_Node : Node_Access);
 
+            procedure Iterate is
+               new HT_Ops.Generic_Iteration (Process);
+
+            -------------
+            -- Process --
+            -------------
+
             procedure Process (Src_Node : Node_Access) is
                E : Element_Type renames Src_Node.Element;
-               B : Buckets_Type renames Target.Buckets.all;
-               I : constant Hash_Type := Hash (E) mod B'Length;
-               N : Count_Type renames Target.Length;
+               B : Buckets_Type renames Target.HT.Buckets.all;
+               J : constant Hash_Type := Hash (E) mod B'Length;
+               N : Count_Type renames Target.HT.Length;
+
             begin
-               B (I) := new Node_Type'(E, B (I));
+               B (J) := new Node_Type'(E, B (J));
                N := N + 1;
             end Process;
 
-            procedure Iterate is
-               new HT_Ops.Generic_Iteration (Process);
+         --  Start of processing for Iterate_Source_When_Empty_Target
+
          begin
-            Iterate (Source);
-         end;
+            Iterate (Source.HT);
+         end Iterate_Source_When_Empty_Target;
 
       else
-
-         declare
+         Iterate_Source : declare
             procedure Process (Src_Node : Node_Access);
 
+            procedure Iterate is
+               new HT_Ops.Generic_Iteration (Process);
+
+            -------------
+            -- Process --
+            -------------
+
             procedure Process (Src_Node : Node_Access) is
                E : Element_Type renames Src_Node.Element;
-               B : Buckets_Type renames Target.Buckets.all;
-               I : constant Hash_Type := Hash (E) mod B'Length;
-               N : Count_Type renames Target.Length;
-            begin
-               if B (I) = null then
+               B : Buckets_Type renames Target.HT.Buckets.all;
+               J : constant Hash_Type := Hash (E) mod B'Length;
+               N : Count_Type renames Target.HT.Length;
 
-                  B (I) := new Node_Type'(E, null);
+            begin
+               if B (J) = null then
+                  B (J) := new Node_Type'(E, null);
                   N := N + 1;
 
-               elsif Equivalent_Keys (E, B (I).Element) then
-
+               elsif Equivalent_Elements (E, B (J).Element) then
                   declare
-                     X : Node_Access := B (I);
+                     X : Node_Access := B (J);
                   begin
-                     B (I) := B (I).Next;
+                     B (J) := B (J).Next;
                      N := N - 1;
                      Free (X);
                   end;
 
                else
-
                   declare
-                     Prev : Node_Access := B (I);
+                     Prev : Node_Access := B (J);
                      Curr : Node_Access := Prev.Next;
+
                   begin
                      while Curr /= null loop
-                        if Equivalent_Keys (E, Curr.Element) then
+                        if Equivalent_Elements (E, Curr.Element) then
                            Prev.Next := Curr.Next;
                            N := N - 1;
                            Free (Curr);
@@ -873,31 +1218,25 @@ package body Ada.Containers.Hashed_Sets is
                         Curr := Prev.Next;
                      end loop;
 
-                     B (I) := new Node_Type'(E, B (I));
+                     B (J) := new Node_Type'(E, B (J));
                      N := N + 1;
                   end;
-
                end if;
             end Process;
 
-            procedure Iterate is
-               new HT_Ops.Generic_Iteration (Process);
-         begin
-            Iterate (Source);
-         end;
+         --  Start of processing for Iterate_Source
 
+         begin
+            Iterate (Source.HT);
+         end Iterate_Source;
       end if;
-
    end Symmetric_Difference;
 
-
    function Symmetric_Difference (Left, Right : Set) return Set is
-
       Buckets : HT_Types.Buckets_Access;
       Length  : Count_Type;
 
    begin
-
       if Left'Address = Right'Address then
          return Empty_Set;
       end if;
@@ -912,451 +1251,446 @@ package body Ada.Containers.Hashed_Sets is
 
       declare
          Size : constant Hash_Type :=
-           Prime_Numbers.To_Prime (Left.Length + Right.Length);
+                  Prime_Numbers.To_Prime (Left.Length + Right.Length);
       begin
          Buckets := new Buckets_Type (0 .. Size - 1);
       end;
 
       Length := 0;
 
-      declare
+      Iterate_Left : declare
          procedure Process (L_Node : Node_Access);
 
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
+
+         -------------
+         -- Process --
+         -------------
+
          procedure Process (L_Node : Node_Access) is
          begin
-            if not Is_In (Right, L_Node) then
+            if not Is_In (Right.HT, L_Node) then
                declare
                   E : Element_Type renames L_Node.Element;
-                  I : constant Hash_Type := Hash (E) mod Buckets'Length;
+                  J : constant Hash_Type := Hash (E) mod Buckets'Length;
+
                begin
-                  Buckets (I) := new Node_Type'(E, Buckets (I));
+                  Buckets (J) := new Node_Type'(E, Buckets (J));
                   Length := Length + 1;
                end;
             end if;
          end Process;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
+      --  Start of processing for Iterate_Left
+
       begin
-         Iterate (Left);
+         Iterate (Left.HT);
       exception
          when others =>
             HT_Ops.Free_Hash_Table (Buckets);
             raise;
-      end;
+      end Iterate_Left;
 
-      declare
+      Iterate_Right : declare
          procedure Process (R_Node : Node_Access);
 
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
+
+         -------------
+         -- Process --
+         -------------
+
          procedure Process (R_Node : Node_Access) is
          begin
-            if not Is_In (Left, R_Node) then
+            if not Is_In (Left.HT, R_Node) then
                declare
                   E : Element_Type renames R_Node.Element;
-                  I : constant Hash_Type := Hash (E) mod Buckets'Length;
+                  J : constant Hash_Type := Hash (E) mod Buckets'Length;
+
                begin
-                  Buckets (I) := new Node_Type'(E, Buckets (I));
+                  Buckets (J) := new Node_Type'(E, Buckets (J));
                   Length := Length + 1;
                end;
             end if;
          end Process;
 
-         procedure Iterate is
-            new HT_Ops.Generic_Iteration (Process);
-      begin
-         Iterate (Right);
-      exception
-         when others =>
-            HT_Ops.Free_Hash_Table (Buckets);
-            raise;
-      end;
-
-      return (Controlled with Buckets, Length);
-
-   end Symmetric_Difference;
-
-
-   function Is_Subset (Subset : Set;
-                       Of_Set : Set) return Boolean is
-
-      Subset_Node : Node_Access;
-
-   begin
-
-      if Subset'Address = Of_Set'Address then
-         return True;
-      end if;
-
-      if Subset.Length > Of_Set.Length then
-         return False;
-      end if;
-
-      --  TODO: rewrite this to loop in the
-      --  style of a passive iterator.
-
-      Subset_Node := HT_Ops.First (Subset);
-
-      while Subset_Node /= null loop
-         if not Is_In (Of_Set, Subset_Node) then
-            return False;
-         end if;
-
-         Subset_Node := HT_Ops.Next (Subset, Subset_Node);
-      end loop;
-
-      return True;
-
-   end Is_Subset;
-
-
-   function Overlap (Left, Right : Set) return Boolean is
-
-      Left_Node : Node_Access;
-
-   begin
-
-      if Right.Length = 0 then
-         return False;
-      end if;
-
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
-      Left_Node := HT_Ops.First (Left);
-
-      while Left_Node /= null loop
-         if Is_In (Right, Left_Node) then
-            return True;
-         end if;
-
-         Left_Node := HT_Ops.Next (Left, Left_Node);
-      end loop;
-
-      return False;
-
-   end Overlap;
-
-
-   function Find (Container : Set;
-                  Item      : Element_Type) return Cursor is
+      --  Start of processing for Iterate_Right
 
-      Node : constant Node_Access := Element_Keys.Find (Container, Item);
+      begin
+         Iterate (Right.HT);
+      exception
+         when others =>
+            HT_Ops.Free_Hash_Table (Buckets);
+            raise;
+      end Iterate_Right;
 
-   begin
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Symmetric_Difference;
 
-      if Node = null then
-         return No_Element;
-      end if;
+   -----------
+   -- Union --
+   -----------
 
-      return Cursor'(Container'Unchecked_Access, Node);
+   procedure Union
+     (Target : in out Set;
+      Source : Set)
+   is
+      procedure Process (Src_Node : Node_Access);
 
-   end Find;
+      procedure Iterate is
+         new HT_Ops.Generic_Iteration (Process);
 
+      -------------
+      -- Process --
+      -------------
 
-   function Contains (Container : Set;
-                      Item      : Element_Type) return Boolean is
-   begin
-      return Find (Container, Item) /= No_Element;
-   end Contains;
+      procedure Process (Src_Node : Node_Access) is
+         function New_Node (Next : Node_Access) return Node_Access;
+         pragma Inline (New_Node);
 
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (New_Node);
 
+         --------------
+         -- New_Node --
+         --------------
 
-   function First (Container : Set) return Cursor is
-      Node : constant Node_Access := HT_Ops.First (Container);
-   begin
-      if Node = null then
-         return No_Element;
-      end if;
+         function New_Node (Next : Node_Access) return Node_Access is
+            Node : constant Node_Access :=
+                     new Node_Type'(Src_Node.Element, Next);
+         begin
+            return Node;
+         end New_Node;
 
-      return Cursor'(Container'Unchecked_Access, Node);
-   end First;
+         Tgt_Node : Node_Access;
+         Success  : Boolean;
 
+      --  Start of processing for Process
 
---     function First_Element (Container : Set) return Element_Type is
---        Node : constant Node_Access := HT_Ops.First (Container);
---     begin
---        return Node.Element;
---     end First_Element;
+      begin
+         Insert (Target.HT, Src_Node.Element, Tgt_Node, Success);
+      end Process;
 
+   --  Start of processing for Union
 
-   function Next (Position : Cursor) return Cursor is
    begin
-      if Position.Container = null
-        or else Position.Node = null
-      then
-         return No_Element;
+      if Target'Address = Source'Address then
+         return;
+      end if;
+
+      if Target.HT.Busy > 0 then
+         raise Program_Error;
       end if;
 
       declare
-         S : Set renames Position.Container.all;
-         Node : constant Node_Access := HT_Ops.Next (S, Position.Node);
+         N : constant Count_Type := Target.Length + Source.Length;
       begin
-         if Node = null then
-            return No_Element;
+         if N > HT_Ops.Capacity (Target.HT) then
+            HT_Ops.Reserve_Capacity (Target.HT, N);
          end if;
-
-         return Cursor'(Position.Container, Node);
       end;
-   end Next;
-
 
-   procedure Next (Position : in out Cursor) is
-   begin
-      Position := Next (Position);
-   end Next;
+      Iterate (Source.HT);
+   end Union;
 
+   function Union (Left, Right : Set) return Set is
+      Buckets : HT_Types.Buckets_Access;
+      Length  : Count_Type;
 
-   function Has_Element (Position : Cursor) return Boolean is
    begin
-      if Position.Container = null then
-         return False;
+      if Left'Address = Right'Address then
+         return Left;
       end if;
 
-      if Position.Node = null then
-         return False;
+      if Right.Length = 0 then
+         return Left;
       end if;
 
-      return True;
-   end Has_Element;
-
-
-   function Equivalent_Keys (Left, Right : Cursor)
-     return Boolean is
-   begin
-      return Equivalent_Keys (Left.Node.Element, Right.Node.Element);
-   end Equivalent_Keys;
+      if Left.Length = 0 then
+         return Right;
+      end if;
 
+      declare
+         Size : constant Hash_Type :=
+                  Prime_Numbers.To_Prime (Left.Length + Right.Length);
+      begin
+         Buckets := new Buckets_Type (0 .. Size - 1);
+      end;
 
-   function Equivalent_Keys (Left  : Cursor;
-                             Right : Element_Type)
-    return Boolean is
-   begin
-      return Equivalent_Keys (Left.Node.Element, Right);
-   end Equivalent_Keys;
+      Iterate_Left : declare
+         procedure Process (L_Node : Node_Access);
 
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
 
-   function Equivalent_Keys (Left  : Element_Type;
-                             Right : Cursor)
-    return Boolean is
-   begin
-      return Equivalent_Keys (Left, Right.Node.Element);
-   end Equivalent_Keys;
+         -------------
+         -- Process --
+         -------------
 
+         procedure Process (L_Node : Node_Access) is
+            J : constant Hash_Type :=
+                  Hash (L_Node.Element) mod Buckets'Length;
 
-   procedure Iterate
-     (Container : in Set;
-      Process   : not null access procedure (Position : in Cursor)) is
+         begin
+            Buckets (J) := new Node_Type'(L_Node.Element, Buckets (J));
+         end Process;
 
-      procedure Process_Node (Node : in Node_Access);
-      pragma Inline (Process_Node);
+      --  Start of processing for Iterate_Left
 
-      procedure Process_Node (Node : in Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
-      end Process_Node;
-
-      procedure Iterate is
-         new HT_Ops.Generic_Iteration (Process_Node);
-   begin
-      Iterate (Container);
-   end Iterate;
+         Iterate (Left.HT);
+      exception
+         when others =>
+            HT_Ops.Free_Hash_Table (Buckets);
+            raise;
+      end Iterate_Left;
 
+      Length := Left.Length;
 
-   function Capacity (Container : Set) return Count_Type
-     renames HT_Ops.Capacity;
+      Iterate_Right : declare
+         procedure Process (Src_Node : Node_Access);
 
-   procedure Reserve_Capacity
-     (Container : in out Set;
-      Capacity  : in     Count_Type)
-     renames HT_Ops.Ensure_Capacity;
+         procedure Iterate is
+            new HT_Ops.Generic_Iteration (Process);
 
+         -------------
+         -- Process --
+         -------------
 
-   procedure Write_Node
-     (Stream : access Root_Stream_Type'Class;
-      Node   : in     Node_Access);
-   pragma Inline (Write_Node);
+         procedure Process (Src_Node : Node_Access) is
+            J : constant Hash_Type :=
+                  Hash (Src_Node.Element) mod Buckets'Length;
 
-   procedure Write_Node
-     (Stream : access Root_Stream_Type'Class;
-      Node   : in     Node_Access) is
-   begin
-      Element_Type'Write (Stream, Node.Element);
-   end Write_Node;
+            Tgt_Node : Node_Access := Buckets (J);
 
-   procedure Write_Nodes is
-      new HT_Ops.Generic_Write (Write_Node);
+         begin
+            while Tgt_Node /= null loop
+               if Equivalent_Elements (Src_Node.Element, Tgt_Node.Element) then
+                  return;
+               end if;
 
-   procedure Write
-     (Stream    : access Root_Stream_Type'Class;
-      Container : in     Set) renames Write_Nodes;
+               Tgt_Node := Next (Tgt_Node);
+            end loop;
 
+            Buckets (J) := new Node_Type'(Src_Node.Element, Buckets (J));
+            Length := Length + 1;
+         end Process;
 
-   function Read_Node (Stream : access Root_Stream_Type'Class)
-     return Node_Access;
-   pragma Inline (Read_Node);
+      --  Start of processing for Iterate_Right
 
-   function Read_Node (Stream : access Root_Stream_Type'Class)
-     return Node_Access is
+      begin
+         Iterate (Right.HT);
+      exception
+         when others =>
+            HT_Ops.Free_Hash_Table (Buckets);
+            raise;
+      end Iterate_Right;
 
-      Node : Node_Access := new Node_Type;
-   begin
-      Element_Type'Read (Stream, Node.Element);
-      return Node;
-   exception
-      when others =>
-         Free (Node);
-         raise;
-   end Read_Node;
+      return (Controlled with HT => (Buckets, Length, 0, 0));
+   end Union;
 
-   procedure Read_Nodes is
-      new HT_Ops.Generic_Read (Read_Node);
+   -----------
+   -- Write --
+   -----------
 
-   procedure Read
+   procedure Write
      (Stream    : access Root_Stream_Type'Class;
-      Container :    out Set) renames Read_Nodes;
+      Container : Set)
+   is
+   begin
+      Write_Nodes (Stream, Container.HT);
+   end Write;
 
+   ----------------
+   -- Write_Node --
+   ----------------
 
-   package body Generic_Keys is
+   procedure Write_Node
+     (Stream : access Root_Stream_Type'Class;
+      Node   : Node_Access)
+   is
+   begin
+      Element_Type'Write (Stream, Node.Element);
+   end Write_Node;
 
-      function Equivalent_Keys (Left  : Cursor;
-                                Right : Key_Type)
-        return Boolean is
-      begin
-         return Equivalent_Keys (Right, Left.Node.Element);
-      end Equivalent_Keys;
+   package body Generic_Keys is
 
-      function Equivalent_Keys (Left  : Key_Type;
-                                Right : Cursor)
-        return Boolean is
-      begin
-         return Equivalent_Keys (Left, Right.Node.Element);
-      end Equivalent_Keys;
+      -----------------------
+      -- Local Subprograms --
+      -----------------------
 
-      function Equivalent_Keys
+      function Equivalent_Key_Node
         (Key  : Key_Type;
          Node : Node_Access) return Boolean;
-      pragma Inline (Equivalent_Keys);
+      pragma Inline (Equivalent_Key_Node);
 
-      function Equivalent_Keys
-        (Key  : Key_Type;
-         Node : Node_Access) return Boolean is
-      begin
-         return Equivalent_Keys (Key, Node.Element);
-      end Equivalent_Keys;
+      --------------------------
+      -- Local Instantiations --
+      --------------------------
 
       package Key_Keys is
          new Hash_Tables.Generic_Keys
           (HT_Types  => HT_Types,
-           HT_Type   => Set,
-           Null_Node => null,
            Next      => Next,
            Set_Next  => Set_Next,
            Key_Type  => Key_Type,
            Hash      => Hash,
-           Equivalent_Keys => Equivalent_Keys);
-
+           Equivalent_Keys => Equivalent_Key_Node);
 
-      function Find (Container : Set;
-                     Key       : Key_Type)
-         return Cursor is
-
-         Node : constant Node_Access :=
-           Key_Keys.Find (Container, Key);
+      --------------
+      -- Contains --
+      --------------
 
+      function Contains
+        (Container : Set;
+         Key       : Key_Type) return Boolean
+      is
       begin
+         return Find (Container, Key) /= No_Element;
+      end Contains;
 
-         if Node = null then
-            return No_Element;
-         end if;
+      ------------
+      -- Delete --
+      ------------
 
-         return Cursor'(Container'Unchecked_Access, Node);
+      procedure Delete
+        (Container : in out Set;
+         Key       : Key_Type)
+      is
+         X : Node_Access;
 
-      end Find;
+      begin
+         Key_Keys.Delete_Key_Sans_Free (Container.HT, Key, X);
 
+         if X = null then
+            raise Constraint_Error;
+         end if;
 
-      function Contains (Container : Set;
-                         Key       : Key_Type) return Boolean is
-      begin
-         return Find (Container, Key) /= No_Element;
-      end Contains;
+         Free (X);
+      end Delete;
 
+      -------------
+      -- Element --
+      -------------
 
-      function Element (Container : Set;
-                        Key       : Key_Type)
-        return Element_Type is
+      function Element
+        (Container : Set;
+         Key       : Key_Type) return Element_Type
+      is
+         Node : constant Node_Access := Key_Keys.Find (Container.HT, Key);
 
-         Node : constant Node_Access := Key_Keys.Find (Container, Key);
       begin
          return Node.Element;
       end Element;
 
+      -------------------------
+      -- Equivalent_Key_Node --
+      -------------------------
 
-      function Key (Position : Cursor) return Key_Type is
+      function Equivalent_Key_Node
+        (Key  : Key_Type;
+         Node : Node_Access) return Boolean
+      is
       begin
-         return Key (Position.Node.Element);
-      end Key;
-
-
---  TODO:
---        procedure Replace (Container : in out Set;
---                           Key       : in     Key_Type;
---                           New_Item  : in     Element_Type) is
-
---           Node : constant Node_Access :=
---             Key_Keys.Find (Container, Key);
-
---        begin
-
---           if Node = null then
---              raise Constraint_Error;
---           end if;
+         return Equivalent_Keys (Key, Node.Element);
+      end Equivalent_Key_Node;
 
---           Replace_Element (Container, Node, New_Item);
+      ---------------------
+      -- Equivalent_Keys --
+      ---------------------
 
---        end Replace;
+      function Equivalent_Keys
+        (Left  : Cursor;
+         Right : Key_Type) return Boolean is
+      begin
+         return Equivalent_Keys (Right, Left.Node.Element);
+      end Equivalent_Keys;
 
+      function Equivalent_Keys
+        (Left  : Key_Type;
+         Right : Cursor) return Boolean is
+      begin
+         return Equivalent_Keys (Left, Right.Node.Element);
+      end Equivalent_Keys;
 
-      procedure Delete (Container : in out Set;
-                        Key       : in     Key_Type) is
+      -------------
+      -- Exclude --
+      -------------
 
+      procedure Exclude
+        (Container : in out Set;
+         Key       : Key_Type)
+      is
          X : Node_Access;
-
       begin
+         Key_Keys.Delete_Key_Sans_Free (Container.HT, Key, X);
+         Free (X);
+      end Exclude;
 
-         Key_Keys.Delete_Key_Sans_Free (Container, Key, X);
+      ----------
+      -- Find --
+      ----------
 
-         if X = null then
-            raise Constraint_Error;
+      function Find
+        (Container : Set;
+         Key       : Key_Type) return Cursor
+      is
+         Node : constant Node_Access :=
+                  Key_Keys.Find (Container.HT, Key);
+
+      begin
+         if Node = null then
+            return No_Element;
          end if;
 
-         Free (X);
+         return Cursor'(Container'Unrestricted_Access, Node);
+      end Find;
 
-      end Delete;
+      ---------
+      -- Key --
+      ---------
 
+      function Key (Position : Cursor) return Key_Type is
+      begin
+         return Key (Position.Node.Element);
+      end Key;
 
-      procedure Exclude (Container : in out Set;
-                         Key       : in     Key_Type) is
+      -------------
+      -- Replace --
+      -------------
 
-         X : Node_Access;
+      procedure Replace
+        (Container : in out Set;
+         Key       : Key_Type;
+         New_Item  : Element_Type)
+      is
+         Node : constant Node_Access :=
+                  Key_Keys.Find (Container.HT, Key);
 
       begin
+         if Node = null then
+            raise Constraint_Error;
+         end if;
 
-         Key_Keys.Delete_Key_Sans_Free (Container, Key, X);
-         Free (X);
-
-      end Exclude;
+         Replace_Element (Container.HT, Node, New_Item);
+      end Replace;
 
+      -----------------------------------
+      -- Update_Element_Preserving_Key --
+      -----------------------------------
 
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
-         Position  : in     Cursor;
+         Position  : Cursor;
          Process   : not null access
-           procedure (Element : in out Element_Type)) is
+                       procedure (Element : in out Element_Type))
+      is
+         HT : Hash_Table_Type renames Container.HT;
 
       begin
-
-         if Position.Container = null then
+         if Position.Node = null then
             raise Constraint_Error;
          end if;
 
@@ -1365,53 +1699,43 @@ package body Ada.Containers.Hashed_Sets is
          end if;
 
          declare
-            Old_Key : Key_Type renames Key (Position.Node.Element);
-         begin
-            Process (Position.Node.Element);
-
-            if Equivalent_Keys (Old_Key, Position.Node.Element) then
-               return;
-            end if;
-         end;
-
-         declare
-            function New_Node (Next : Node_Access) return Node_Access;
-            pragma Inline (New_Node);
+            E : Element_Type renames Position.Node.Element;
+            K : Key_Type renames Key (E);
 
-            function New_Node (Next : Node_Access) return Node_Access is
-            begin
-               Position.Node.Next := Next;
-               return Position.Node;
-            end New_Node;
-
-            procedure Insert is
-               new Key_Keys.Generic_Conditional_Insert (New_Node);
+            B : Natural renames HT.Busy;
+            L : Natural renames HT.Lock;
 
-            Result  : Node_Access;
-            Success : Boolean;
          begin
-            HT_Ops.Delete_Node_Sans_Free (Container, Position.Node);
+            B := B + 1;
+            L := L + 1;
 
-            Insert
-              (HT      => Container,
-               Key     => Key (Position.Node.Element),
-               Node    => Result,
-               Success => Success);
+            begin
+               Process (E);
+            exception
+               when others =>
+                  L := L - 1;
+                  B := B - 1;
+                  raise;
+            end;
 
-            if not Success then
-               declare
-                  X : Node_Access := Position.Node;
-               begin
-                  Free (X);
-               end;
+            L := L - 1;
+            B := B - 1;
 
-               raise Program_Error;
+            if Equivalent_Keys (K, E) then
+               pragma Assert (Hash (K) = Hash (E));
+               return;
             end if;
+         end;
 
-            pragma Assert (Result = Position.Node);
+         declare
+            X : Node_Access := Position.Node;
+         begin
+            HT_Ops.Delete_Node_Sans_Free (HT, X);
+            Free (X);
          end;
 
-      end Checked_Update_Element;
+         raise Program_Error;
+      end Update_Element_Preserving_Key;
 
    end Generic_Keys;
 
index 9f0cdc387476cfc241db28f427c660ed7c3390b7..16aaf5dc36045cc962b5357a600c6a28e6eb0e1f 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                        ADA.CONTAINERS.HASHED_SETS                        --
+--           A D A . C O N T A I N E R S . H A S H E D _ S E T S            --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
 
 with Ada.Containers.Hash_Tables;
 with Ada.Streams;
+with Ada.Finalization;
 
 generic
    type Element_Type is private;
 
    with function Hash (Element : Element_Type) return Hash_Type;
 
-   --  TODO: get a ruling from ARG in Atlanta re the name and
-   --  order of these declarations. ???
-   --
-   with function Equivalent_Keys (Left, Right : Element_Type) return Boolean;
+   with function Equivalent_Elements (Left, Right : Element_Type)
+                                     return Boolean;
 
    with function "=" (Left, Right : Element_Type) return Boolean is <>;
 
@@ -61,6 +60,8 @@ pragma Preelaborate (Hashed_Sets);
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -73,11 +74,10 @@ pragma Preelaborate (Hashed_Sets);
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type));
 
-   --  TODO: resolve in atlanta
-   --   procedure Replace_Element
-   --     (Container : in out Set;
-   --      Position  : Cursor;
-   --      By        : Element_Type);
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type);
 
    procedure Move (Target : in out Set; Source : in out Set);
 
@@ -95,9 +95,37 @@ pragma Preelaborate (Hashed_Sets);
 
    procedure Delete  (Container : in out Set; Item     : Element_Type);
 
+   procedure Delete (Container : in out Set; Position  : in out Cursor);
+
    procedure Exclude (Container : in out Set; Item     : Element_Type);
 
-   procedure Delete (Container : in out Set; Position  : in out Cursor);
+   function Contains (Container : Set; Item : Element_Type) return Boolean;
+
+   function Find
+     (Container : Set;
+      Item      : Element_Type) return Cursor;
+
+   function First (Container : Set) return Cursor;
+
+   function Next (Position : Cursor) return Cursor;
+
+   procedure Next (Position : in out Cursor);
+
+   function Has_Element (Position : Cursor) return Boolean;
+
+   function Equivalent_Elements (Left, Right : Cursor) return Boolean;
+
+   function Equivalent_Elements
+     (Left  : Cursor;
+      Right : Element_Type) return Boolean;
+
+   function Equivalent_Elements
+     (Left  : Element_Type;
+      Right : Cursor) return Boolean;
+
+   procedure Iterate
+     (Container : Set;
+      Process   : not null access procedure (Position : Cursor));
 
    procedure Union (Target : in out Set; Source : Set);
 
@@ -128,40 +156,12 @@ pragma Preelaborate (Hashed_Sets);
 
    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean;
 
-   function Contains (Container : Set; Item : Element_Type) return Boolean;
-
-   function Find
-     (Container : Set;
-      Item      : Element_Type) return Cursor;
-
    function Capacity (Container : Set) return Count_Type;
 
    procedure Reserve_Capacity
      (Container : in out Set;
       Capacity  : Count_Type);
 
-   function First (Container : Set) return Cursor;
-
-   function Next (Position : Cursor) return Cursor;
-
-   procedure Next (Position : in out Cursor);
-
-   function Has_Element (Position : Cursor) return Boolean;
-
-   function Equivalent_Keys (Left, Right : Cursor) return Boolean;
-
-   function Equivalent_Keys
-     (Left  : Cursor;
-      Right : Element_Type) return Boolean;
-
-   function Equivalent_Keys
-     (Left  : Element_Type;
-      Right : Cursor) return Boolean;
-
-   procedure Iterate
-     (Container : Set;
-      Process   : not null access procedure (Position : Cursor));
-
    generic
       type Key_Type (<>) is limited private;
 
@@ -183,18 +183,16 @@ pragma Preelaborate (Hashed_Sets);
 
       function Element (Container : Set; Key : Key_Type) return Element_Type;
 
-      --  TODO: resolve in atlanta
-      --      procedure Replace
-      --        (Container : in out Set;
-      --         Key       : Key_Type;
-      --         New_Item  : Element_Type);
+      procedure Replace
+        (Container : in out Set;
+         Key       : Key_Type;
+         New_Item  : Element_Type);
 
       procedure Delete (Container : in out Set; Key : Key_Type);
 
       procedure Exclude (Container : in out Set; Key : Key_Type);
 
-      --  TODO: resolve name in atlanta: ???
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : Cursor;
          Process   : not null access
@@ -215,24 +213,35 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package HT_Types is
-     new Hash_Tables.Generic_Hash_Table_Types (Node_Access);
+   type Node_Type is
+      limited record
+         Element : Element_Type;
+         Next    : Node_Access;
+      end record;
 
-   use HT_Types;
+   package HT_Types is new Hash_Tables.Generic_Hash_Table_Types
+     (Node_Type,
+      Node_Access);
 
-   type Set is new Hash_Table_Type with null record;
+   type Set is new Ada.Finalization.Controlled with record
+      HT : HT_Types.Hash_Table_Type;
+   end record;
 
    procedure Adjust (Container : in out Set);
 
    procedure Finalize (Container : in out Set);
 
-   type Set_Access is access constant Set;
+   use HT_Types;
+   use Ada.Finalization;
+
+   type Set_Access is access all Set;
    for Set_Access'Storage_Size use 0;
 
-   type Cursor is record
-      Container : Set_Access;
-      Node      : Node_Access;
-   end record;
+   type Cursor is
+      record
+         Container : Set_Access;
+         Node      : Node_Access;
+      end record;
 
    No_Element : constant Cursor := (Container => null, Node => null);
 
@@ -250,6 +259,6 @@ private
 
    for Set'Read use Read;
 
-   Empty_Set : constant Set := (Hash_Table_Type with null record);
+   Empty_Set : constant Set := (Controlled with HT => (null, 0, 0, 0));
 
 end Ada.Containers.Hashed_Sets;
index 068efc6a2a87b3d5c722d9b4e473cf9d4806d380..08d0532ca7efd1b2c7409a5c7283c67802ae9f4e 100644 (file)
@@ -2,33 +2,55 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                        ADA.CONTAINERS.HASH_TABLES                        --
+--            A D A . C O N T A I N E R S . H A S H _ T A B L E S           --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
--- This specification is adapted from the Ada Reference Manual for use with --
--- GNAT.  In accordance with the copyright of that document, you can freely --
--- copy and modify this specification,  provided that if you redistribute a --
--- modified version,  any changes that you have made are clearly indicated. --
+--          Copyright (C) 2004-2005 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.                  --
 ------------------------------------------------------------------------------
 
-with Ada.Finalization;
-
 package Ada.Containers.Hash_Tables is
 pragma Preelaborate;
 
    generic
-      type Node_Access is private;
+      type Node_Type (<>) is limited private;
+
+      type Node_Access is access Node_Type;
 
    package Generic_Hash_Table_Types is
       type Buckets_Type is array (Hash_Type range <>) of Node_Access;
 
       type Buckets_Access is access Buckets_Type;
 
-      type Hash_Table_Type is new Ada.Finalization.Controlled with record
+      type Hash_Table_Type is tagged record
          Buckets : Buckets_Access;
          Length  : Count_Type := 0;
+         Busy    : Natural := 0;
+         Lock    : Natural := 0;
       end record;
    end Generic_Hash_Table_Types;
 
index c997430f6f0e9710e41076b66f0afb809448ee6b..39ef4e5f190d39ec10be31adb80a1e9bb55c9782 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                    ADA.CONTAINERS.INDEFINITE_VECTORS                     --
+--    A D A . C O N T A I N E R S . I N D E F I N I T E _ V E C T O R S     --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -39,209 +39,186 @@ with System;  use type System.Address;
 
 package body Ada.Containers.Indefinite_Vectors is
 
-
    type Int is range System.Min_Int .. System.Max_Int;
 
    procedure Free is
-      new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
+     new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
 
    procedure Free is
-      new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
-
-
-   procedure Adjust (Container : in out Vector) is
-   begin
-
-      if Container.Elements = null then
-         return;
-      end if;
-
-      if Container.Elements'Length = 0
-        or else Container.Last < Index_Type'First
-      then
-         Container.Elements := null;
-         return;
-      end if;
-
-      declare
-         E : Elements_Type renames Container.Elements.all;
-         L : constant Index_Type := Container.Last;
-      begin
-
-         Container.Elements := null;
-         Container.Last := Index_Type'Pred (Index_Type'First);
-
-         Container.Elements := new Elements_Type (Index_Type'First .. L);
-
-         for I in Container.Elements'Range loop
-
-            if E (I) /= null then
-               Container.Elements (I) := new Element_Type'(E (I).all);
-            end if;
-
-            Container.Last := I;
-
-         end loop;
-
-      end;
-
-   end Adjust;
-
+     new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
 
-   procedure Finalize (Container : in out Vector) is
+   ---------
+   -- "&" --
+   ---------
 
-      E : Elements_Access := Container.Elements;
-      L : constant Index_Type'Base := Container.Last;
+   function "&" (Left, Right : Vector) return Vector is
+      LN : constant Count_Type := Length (Left);
+      RN : constant Count_Type := Length (Right);
 
    begin
+      if LN = 0 then
+         if RN = 0 then
+            return Empty_Vector;
+         end if;
 
-      Container.Elements := null;
-      Container.Last := Index_Type'Pred (Index_Type'First);
-
-      for I in Index_Type'First .. L loop
-         Free (E (I));
-      end loop;
-
-      Free (E);
-
-   end Finalize;
-
+         declare
+            RE : Elements_Type renames
+                   Right.Elements (Index_Type'First .. Right.Last);
 
-   procedure Write
-     (Stream    : access Root_Stream_Type'Class;
-      Container : in     Vector) is
+            Elements : Elements_Access :=
+                         new Elements_Type (RE'Range);
 
-      N : constant Count_Type := Length (Container);
+         begin
+            for I in Elements'Range loop
+               begin
+                  if RE (I) /= null then
+                     Elements (I) := new Element_Type'(RE (I).all);
+                  end if;
+               exception
+                  when others =>
+                     for J in Index_Type'First .. Index_Type'Pred (I) loop
+                        Free (Elements (J));
+                     end loop;
 
-   begin
+                     Free (Elements);
+                     raise;
+               end;
+            end loop;
 
-      Count_Type'Base'Write (Stream, N);
+            return (Controlled with Elements, Right.Last, 0, 0);
+         end;
 
-      if N = 0 then
-         return;
       end if;
 
-      declare
-         E : Elements_Type renames Container.Elements.all;
-      begin
-         for I in Index_Type'First .. Container.Last loop
-
-            --  There's another way to do this.  Instead a separate
-            --  Boolean for each element, you could write a Boolean
-            --  followed by a count of how many nulls or non-nulls
-            --  follow in the array.  Alternately you could use a
-            --  signed integer, and use the sign as the indicator
-            --  or null-ness.
-
-            if E (I) = null then
-               Boolean'Write (Stream, False);
-            else
-               Boolean'Write (Stream, True);
-               Element_Type'Output (Stream, E (I).all);
-            end if;
-
-         end loop;
-      end;
-
-   end Write;
-
-
-   procedure Read
-     (Stream    : access Root_Stream_Type'Class;
-      Container :    out Vector) is
-
-      Length : Count_Type'Base;
-      Last   : Index_Type'Base := Index_Type'Pred (Index_Type'First);
-
-      B : Boolean;
+      if RN = 0 then
+         declare
+            LE : Elements_Type renames
+                   Left.Elements (Index_Type'First .. Left.Last);
 
-   begin
+            Elements : Elements_Access :=
+                         new Elements_Type (LE'Range);
 
-      Clear (Container);
+         begin
+            for I in Elements'Range loop
+               begin
+                  if LE (I) /= null then
+                     Elements (I) := new Element_Type'(LE (I).all);
+                  end if;
+               exception
+                  when others =>
+                     for J in Index_Type'First .. Index_Type'Pred (I) loop
+                        Free (Elements (J));
+                     end loop;
 
-      Count_Type'Base'Read (Stream, Length);
+                     Free (Elements);
+                     raise;
+               end;
+            end loop;
 
-      if Length > Capacity (Container) then
-         Reserve_Capacity (Container, Capacity => Length);
+            return (Controlled with Elements, Left.Last, 0, 0);
+         end;
       end if;
 
-      for I in Count_Type range 1 .. Length loop
-
-         Last := Index_Type'Succ (Last);
-
-         Boolean'Read (Stream, B);
-
-         if B then
-            Container.Elements (Last) :=
-              new Element_Type'(Element_Type'Input (Stream));
-         end if;
-
-         Container.Last := Last;
-
-      end loop;
+      declare
+         Last_As_Int : constant Int'Base :=
+                         Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
 
-   end Read;
+         Last : constant Index_Type := Index_Type (Last_As_Int);
 
+         LE : Elements_Type renames
+                Left.Elements (Index_Type'First .. Left.Last);
 
-   function To_Vector (Length : Count_Type) return Vector is
-   begin
+         RE : Elements_Type renames
+                Right.Elements (Index_Type'First .. Right.Last);
 
-      if Length = 0 then
-         return Empty_Vector;
-      end if;
+         Elements : Elements_Access :=
+                      new Elements_Type (Index_Type'First .. Last);
 
-      declare
+         I : Index_Type'Base := Index_Type'Pred (Index_Type'First);
 
-         First : constant Int := Int (Index_Type'First);
+      begin
+         for LI in LE'Range loop
+            I := Index_Type'Succ (I);
 
-         Last_As_Int : constant Int'Base :=
-           First + Int (Length) - 1;
+            begin
+               if LE (LI) /= null then
+                  Elements (I) := new Element_Type'(LE (LI).all);
+               end if;
+            exception
+               when others =>
+                  for J in Index_Type'First .. Index_Type'Pred (I) loop
+                     Free (Elements (J));
+                  end loop;
 
-         Last : constant Index_Type :=
-           Index_Type (Last_As_Int);
+                  Free (Elements);
+                  raise;
+            end;
+         end loop;
 
-         Elements : constant Elements_Access :=
-           new Elements_Type (Index_Type'First .. Last);
+         for RI in RE'Range loop
+            I := Index_Type'Succ (I);
 
-      begin
+            begin
+               if RE (RI) /= null then
+                  Elements (I) := new Element_Type'(RE (RI).all);
+               end if;
+            exception
+               when others =>
+                  for J in Index_Type'First .. Index_Type'Pred (I) loop
+                     Free (Elements (J));
+                  end loop;
 
-         return (Controlled with Elements, Last);
+                  Free (Elements);
+                  raise;
+            end;
+         end loop;
 
+         return (Controlled with Elements, Last, 0, 0);
       end;
+   end "&";
 
-   end To_Vector;
-
+   function "&" (Left : Vector; Right : Element_Type) return Vector is
+      LN : constant Count_Type := Length (Left);
 
+   begin
+      if LN = 0 then
+         declare
+            subtype Elements_Subtype is
+              Elements_Type (Index_Type'First .. Index_Type'First);
 
-   function To_Vector
-     (New_Item : Element_Type;
-      Length   : Count_Type) return Vector is
+            Elements : Elements_Access := new Elements_Subtype;
 
-   begin
+         begin
+            begin
+               Elements (Elements'First) := new Element_Type'(Right);
+            exception
+               when others =>
+                  Free (Elements);
+                  raise;
+            end;
 
-      if Length = 0 then
-         return Empty_Vector;
+            return (Controlled with Elements, Index_Type'First, 0, 0);
+         end;
       end if;
 
       declare
-
-         First : constant Int := Int (Index_Type'First);
-
          Last_As_Int : constant Int'Base :=
-           First + Int (Length) - 1;
+                         Int (Index_Type'First) + Int (LN);
+
+         Last : constant Index_Type := Index_Type (Last_As_Int);
 
-         Last : constant Index_Type :=
-           Index_Type (Last_As_Int);
+         LE : Elements_Type renames
+                Left.Elements (Index_Type'First .. Left.Last);
 
          Elements : Elements_Access :=
-           new Elements_Type (Index_Type'First .. Last);
+                      new Elements_Type (Index_Type'First .. Last);
 
       begin
-
-         for I in Elements'Range loop
-
+         for I in LE'Range loop
             begin
-               Elements (I) := new Element_Type'(New_Item);
+               if LE (I) /= null then
+                  Elements (I) := new Element_Type'(LE (I).all);
+               end if;
             exception
                when others =>
                   for J in Index_Type'First .. Index_Type'Pred (I) loop
@@ -251,29 +228,140 @@ package body Ada.Containers.Indefinite_Vectors is
                   Free (Elements);
                   raise;
             end;
-
          end loop;
 
-         return (Controlled with Elements, Last);
+         begin
+            Elements (Elements'Last) := new Element_Type'(Right);
+         exception
+            when others =>
+               declare
+                  subtype J_Subtype is Index_Type'Base range
+                    Index_Type'First .. Index_Type'Pred (Elements'Last);
+               begin
+                  for J in J_Subtype loop
+                     Free (Elements (J));
+                  end loop;
+               end;
+
+               Free (Elements);
+               raise;
+         end;
 
+         return (Controlled with Elements, Last, 0, 0);
       end;
+   end "&";
 
-   end To_Vector;
-
+   function "&" (Left : Element_Type; Right : Vector) return Vector is
+      RN : constant Count_Type := Length (Right);
 
-   function "=" (Left, Right : Vector) return Boolean is
    begin
+      if RN = 0 then
+         declare
+            subtype Elements_Subtype is
+              Elements_Type (Index_Type'First .. Index_Type'First);
 
-      if Left'Address = Right'Address then
-         return True;
-      end if;
+            Elements : Elements_Access := new Elements_Subtype;
+
+         begin
+            begin
+               Elements (Elements'First) := new Element_Type'(Left);
+            exception
+               when others =>
+                  Free (Elements);
+                  raise;
+            end;
+
+            return (Controlled with Elements, Index_Type'First, 0, 0);
+         end;
+      end if;
+
+      declare
+         Last_As_Int : constant Int'Base :=
+                         Int (Index_Type'First) + Int (RN);
+
+         Last : constant Index_Type := Index_Type (Last_As_Int);
+
+         RE : Elements_Type renames
+                Right.Elements (Index_Type'First .. Right.Last);
+
+         Elements : Elements_Access :=
+                      new Elements_Type (Index_Type'First .. Last);
+
+         I : Index_Type'Base := Index_Type'First;
+
+      begin
+         begin
+            Elements (I) := new Element_Type'(Left);
+         exception
+            when others =>
+               Free (Elements);
+               raise;
+         end;
+
+         for RI in RE'Range loop
+            I := Index_Type'Succ (I);
+
+            begin
+               if RE (RI) /= null then
+                  Elements (I) := new Element_Type'(RE (RI).all);
+               end if;
+            exception
+               when others =>
+                  for J in Index_Type'First .. Index_Type'Pred (I) loop
+                     Free (Elements (J));
+                  end loop;
+
+                  Free (Elements);
+                  raise;
+            end;
+         end loop;
+
+         return (Controlled with Elements, Last, 0, 0);
+      end;
+   end "&";
+
+   function "&" (Left, Right : Element_Type) return Vector is
+      subtype IT is Index_Type'Base range
+        Index_Type'First .. Index_Type'Succ (Index_Type'First);
+
+      Elements : Elements_Access := new Elements_Type (IT);
+
+   begin
+      begin
+         Elements (Elements'First) := new Element_Type'(Left);
+      exception
+         when others =>
+            Free (Elements);
+            raise;
+      end;
+
+      begin
+         Elements (Elements'Last) := new Element_Type'(Right);
+      exception
+         when others =>
+            Free (Elements (Elements'First));
+            Free (Elements);
+            raise;
+      end;
+
+      return (Controlled with Elements, Elements'Last, 0, 0);
+   end "&";
+
+   ---------
+   -- "=" --
+   ---------
+
+   function "=" (Left, Right : Vector) return Boolean is
+   begin
+      if Left'Address = Right'Address then
+         return True;
+      end if;
 
       if Left.Last /= Right.Last then
          return False;
       end if;
 
-      for I in Index_Type'First .. Left.Last loop
-
+      for J in Index_Type'First .. Left.Last loop
          --  NOTE:
          --  I think it's a bounded error to read or otherwise manipulate
          --  an "empty" element, which here means that it has the value
@@ -285,121 +373,82 @@ package body Ada.Containers.Indefinite_Vectors is
          --  you have a contrary argument then let me know.
          --  END NOTE.
 
-         if Left.Elements (I) = null then
-
-            if Right.Elements (I) /= null then
+         if Left.Elements (J) = null then
+            if Right.Elements (J) /= null then
                return False;
             end if;
 
-         elsif Right.Elements (I) = null then
-
+         elsif Right.Elements (J) = null then
             return False;
 
-         elsif Left.Elements (I).all /= Right.Elements (I).all then
-
+         elsif Left.Elements (J).all /= Right.Elements (J).all then
             return False;
 
          end if;
-
       end loop;
 
       return True;
-
    end "=";
 
+   ------------
+   -- Adjust --
+   ------------
 
-   function Length (Container : Vector) return Count_Type is
-
-      L : constant Int := Int (Container.Last);
-      F : constant Int := Int (Index_Type'First);
-
-      N : constant Int'Base := L - F + 1;
-   begin
-      return Count_Type (N);
-   end Length;
-
-
-   function Is_Empty (Container : Vector) return Boolean is
-   begin
-      return Container.Last < Index_Type'First;
-   end Is_Empty;
-
-
-   procedure Set_Length
-     (Container : in out Vector;
-      Length    : in     Count_Type) is
-
-      N : constant Count_Type := Indefinite_Vectors.Length (Container);
-
+   procedure Adjust (Container : in out Vector) is
    begin
-
-      if Length = N then
+      if Container.Elements = null then
          return;
       end if;
 
-      if Length = 0 then
-         Clear (Container);
+      if Container.Elements'Length = 0
+        or else Container.Last < Index_Type'First
+      then
+         Container.Elements := null;
          return;
       end if;
 
       declare
-         Last_As_Int : constant Int'Base :=
-           Int (Index_Type'First) + Int (Length) - 1;
-
-         Last : constant Index_Type :=
-           Index_Type (Last_As_Int);
+         E : Elements_Type renames Container.Elements.all;
+         L : constant Index_Type := Container.Last;
       begin
+         Container.Elements := null;
+         Container.Last := No_Index;
+         Container.Busy := 0;
+         Container.Lock := 0;
 
-         if Length > N then
+         Container.Elements := new Elements_Type (Index_Type'First .. L);
 
-            if Length > Capacity (Container) then
-               Reserve_Capacity (Container, Capacity => Length);
+         for I in Container.Elements'Range loop
+            if E (I) /= null then
+               Container.Elements (I) := new Element_Type'(E (I).all);
             end if;
 
-            Container.Last := Last;
-
-            return;
-
-         end if;
-
-         for I in reverse Index_Type'Succ (Last) .. Container.Last loop
-
-            declare
-               X : Element_Access := Container.Elements (I);
-            begin
-               Container.Elements (I) := null;
-               Container.Last := Index_Type'Pred (Container.Last);
-               Free (X);
-            end;
-
+            Container.Last := I;
          end loop;
-
       end;
+   end Adjust;
 
-   end Set_Length;
-
+   ------------
+   -- Append --
+   ------------
 
-   procedure Clear (Container : in out Vector) is
+   procedure Append (Container : in out Vector; New_Item : Vector) is
    begin
+      if Is_Empty (New_Item) then
+         return;
+      end if;
 
-      for I in reverse Index_Type'First .. Container.Last loop
-
-         declare
-            X : Element_Access := Container.Elements (I);
-         begin
-            Container.Elements (I) := null;
-            Container.Last := Index_Type'Pred (I);
-            Free (X);
-         end;
-
-      end loop;
-
-   end Clear;
-
+      Insert
+        (Container,
+         Index_Type'Succ (Container.Last),
+         New_Item);
+   end Append;
 
-   procedure Append (Container : in out Vector;
-                     New_Item  : in     Element_Type;
-                     Count     : in     Count_Type := 1) is
+   procedure Append
+     (Container : in out Vector;
+      New_Item  : Element_Type;
+      Count     : Count_Type := 1)
+   is
    begin
       if Count = 0 then
          return;
@@ -412,1200 +461,1225 @@ package body Ada.Containers.Indefinite_Vectors is
          Count);
    end Append;
 
+   ------------
+   -- Assign --
+   ------------
 
-   procedure Insert
-     (Container : in out Vector;
-      Before    : in     Extended_Index;
-      New_Item  : in     Element_Type;
-      Count     : in     Count_Type := 1) is
+   procedure Assign
+     (Target : in out Vector;
+      Source : Vector)
+   is
+      N : constant Count_Type := Length (Source);
 
-      Old_Last_As_Int : constant Int := Int (Container.Last);
+   begin
+      if Target'Address = Source'Address then
+         return;
+      end if;
 
-      N : constant Int := Int (Count);
+      Clear (Target);
 
-      New_Last_As_Int : constant Int'Base := Old_Last_As_Int + N;
+      if N = 0 then
+         return;
+      end if;
+
+      if N > Capacity (Target) then
+         Reserve_Capacity (Target, Capacity => N);
+      end if;
 
-      New_Last : constant Extended_Index := Extended_Index (New_Last_As_Int);
+      for J in Index_Type'First .. Source.Last loop
+         declare
+            EA : constant Element_Access := Source.Elements (J);
+         begin
+            if EA /= null then
+               Target.Elements (J) := new Element_Type'(EA.all);
+            end if;
+         end;
 
-      Index : Index_Type;
+         Target.Last := J;
+      end loop;
+   end Assign;
 
-      Dst_Last : Index_Type;
-      Dst      : Elements_Access;
+   --------------
+   -- Capacity --
+   --------------
 
+   function Capacity (Container : Vector) return Count_Type is
    begin
+      if Container.Elements = null then
+         return 0;
+      end if;
 
-      if Count = 0 then
-         return;
+      return Container.Elements'Length;
+   end Capacity;
+
+   -----------
+   -- Clear --
+   -----------
+
+   procedure Clear (Container : in out Vector) is
+   begin
+      if Container.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      declare
-         subtype Before_Subtype is Index_Type'Base range
-           Index_Type'First .. Index_Type'Succ (Container.Last);
+      for J in reverse Index_Type'First .. Container.Last loop
+         declare
+            X : Element_Access := Container.Elements (J);
+         begin
+            Container.Elements (J) := null;
+            Container.Last := Index_Type'Pred (J);
+            Free (X);
+         end;
+      end loop;
+   end Clear;
 
-         Old_First : constant Before_Subtype := Before;
+   --------------
+   -- Contains --
+   --------------
 
-         Old_First_As_Int : constant Int := Int (Old_First);
+   function Contains
+     (Container : Vector;
+      Item      : Element_Type) return Boolean is
+   begin
+      return Find_Index (Container, Item) /= No_Index;
+   end Contains;
 
-         New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
-      begin
-         Index := Index_Type (New_First_As_Int);
-      end;
+   ------------
+   -- Delete --
+   ------------
 
-      if Container.Elements = null then
+   procedure Delete
+     (Container : in out Vector;
+      Index     : Extended_Index;
+      Count     : Count_Type := 1)
+   is
+   begin
+      if Index < Index_Type'First then
+         raise Constraint_Error;
+      end if;
 
-         declare
-            subtype Elements_Subtype is
-              Elements_Type (Index_Type'First .. New_Last);
-         begin
-            Container.Elements := new Elements_Subtype;
-            Container.Last := Index_Type'Pred (Index_Type'First);
+      if Index > Container.Last then
+         if Index > Container.Last + 1 then
+            raise Constraint_Error;
+         end if;
 
-            for I in Container.Elements'Range loop
-               Container.Elements (I) := new Element_Type'(New_Item);
-               Container.Last := I;
-            end loop;
-         end;
+         return;
+      end if;
 
+      if Count = 0 then
          return;
+      end if;
 
+      if Container.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      if New_Last <= Container.Elements'Last then
+      declare
+         I_As_Int : constant Int := Int (Index);
 
-         declare
-            E : Elements_Type renames Container.Elements.all;
-         begin
-            E (Index .. New_Last) := E (Before .. Container.Last);
-            Container.Last := New_Last;
+         Old_Last_As_Int : constant Int := Int (Container.Last);
 
-            --  NOTE:
-            --  Now we do the allocation.  If it fails, we can propagate the
-            --  exception and invariants are more or less satisfied.  The
-            --  issue is that we have some slots still null, and the client
-            --  has no way of detecting whether the slot is null (unless we
-            --  give him a way).
-            --
-            --  Another way is to allocate a subarray on the stack, do the
-            --  allocation into that array, and if that success then do
-            --  the insertion proper.  The issue there is that you have to
-            --  allocate the subarray on the stack, and that may fail if the
-            --  subarray is long.
-            --
-            --  Or we could try to roll-back the changes: deallocate the
-            --  elements we have successfully deallocated, and then copy
-            --  the elements ptrs back to their original posns.
-            --  END NOTE.
+         Count1 : constant Int'Base := Int (Count);
+         Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
 
-            --  NOTE: I have written the loop manually here.  I could
-            --  have done it this way too:
-            --    E (Before .. Index_Type'Pred (Index)) :=
-            --      (others => new Element_Type'New_Item);
-            --  END NOTE.
+         N : constant Int'Base := Int'Min (Count1, Count2);
 
-            for I in Before .. Index_Type'Pred (Index) loop
+         J_As_Int : constant Int'Base := I_As_Int + N;
+         J        : constant Index_Type'Base := Index_Type'Base (J_As_Int);
 
-               begin
-                  E (I) := new Element_Type'(New_Item);
-               exception
-                  when others =>
-                     E (I .. Index_Type'Pred (Index)) := (others => null);
-                     raise;
-               end;
+         E : Elements_Type renames Container.Elements.all;
 
-            end loop;
-         end;
+         New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
 
-         return;
+         New_Last : constant Extended_Index :=
+                      Extended_Index (New_Last_As_Int);
+
+      begin
+         for K in Index .. Index_Type'Pred (J) loop
+            declare
+               X : Element_Access := E (K);
+            begin
+               E (K) := null;
+               Free (X);
+            end;
+         end loop;
+
+         E (Index .. New_Last) := E (J .. Container.Last);
+         Container.Last := New_Last;
+      end;
+   end Delete;
 
+   procedure Delete
+     (Container : in out Vector;
+      Position  : in out Cursor;
+      Count     : Count_Type := 1)
+   is
+   begin
+      if Position.Container = null then
+         raise Constraint_Error;
       end if;
 
-      declare
+      if Position.Container /=
+           Vector_Access'(Container'Unchecked_Access)
+        or else Position.Index > Container.Last
+      then
+         raise Program_Error;
+      end if;
 
-         First : constant Int := Int (Index_Type'First);
+      Delete (Container, Position.Index, Count);
 
-         New_Size : constant Int'Base :=
-           New_Last_As_Int - First + 1;
+      if Position.Index <= Container.Last then
+         Position := (Container'Unchecked_Access, Position.Index);
+      else
+         Position := No_Element;
+      end if;
+   end Delete;
 
-         Max_Size : constant Int'Base :=
-           Int (Index_Type'Last) - First + 1;
+   ------------------
+   -- Delete_First --
+   ------------------
 
-         Size, Dst_Last_As_Int : Int'Base;
+   procedure Delete_First
+     (Container : in out Vector;
+      Count     : Count_Type := 1)
+   is
+   begin
+      if Count = 0 then
+         return;
+      end if;
 
-      begin
+      if Count >= Length (Container) then
+         Clear (Container);
+         return;
+      end if;
 
-         if New_Size >= Max_Size / 2 then
+      Delete (Container, Index_Type'First, Count);
+   end Delete_First;
 
-            Dst_Last := Index_Type'Last;
+   -----------------
+   -- Delete_Last --
+   -----------------
 
-         else
+   procedure Delete_Last
+     (Container : in out Vector;
+      Count     : Count_Type := 1)
+   is
+      Index : Int'Base;
 
-            Size := Container.Elements'Length;
+   begin
+      if Count = 0 then
+         return;
+      end if;
 
-            if Size = 0 then
-               Size := 1;
-            end if;
+      if Count >= Length (Container) then
+         Clear (Container);
+         return;
+      end if;
 
-            while Size < New_Size loop
-               Size := 2 * Size;
-            end loop;
+      Index := Int'Base (Container.Last) - Int'Base (Count) + 1;
 
-            Dst_Last_As_Int := First + Size - 1;
-            Dst_Last := Index_Type (Dst_Last_As_Int);
+      Delete (Container, Index_Type'Base (Index), Count);
+   end Delete_Last;
 
-         end if;
+   -------------
+   -- Element --
+   -------------
 
-      end;
+   function Element
+     (Container : Vector;
+      Index     : Index_Type) return Element_Type
+   is
+      subtype T is Index_Type'Base range
+        Index_Type'First .. Container.Last;
+   begin
+      return Container.Elements (T'(Index)).all;
+   end Element;
 
-      Dst := new Elements_Type (Index_Type'First .. Dst_Last);
+   function Element (Position : Cursor) return Element_Type is
+   begin
+      return Element (Position.Container.all, Position.Index);
+   end Element;
 
-      declare
-         Src : Elements_Type renames Container.Elements.all;
-      begin
-         Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
-           Src (Index_Type'First .. Index_Type'Pred (Before));
+   --------------
+   -- Finalize --
+   --------------
 
-         Dst (Index .. New_Last) := Src (Before .. Container.Last);
-      end;
+   procedure Finalize (Container : in out Vector) is
+   begin
+      Clear (Container);
 
       declare
          X : Elements_Access := Container.Elements;
       begin
-         Container.Elements := Dst;
-         Container.Last := New_Last;
-
+         Container.Elements := null;
          Free (X);
       end;
+   end Finalize;
 
-      --  NOTE:
-      --  Now do the allocation.  If the allocation fails,
-      --  then the worst thing is that we have a few null slots.
-      --  Our invariants are otherwise satisfied.
-      --  END NOTE.
+   ----------
+   -- Find --
+   ----------
 
-      for I in Before .. Index_Type'Pred (Index) loop
-         Dst (I) := new Element_Type'(New_Item);
-      end loop;
+   function Find
+     (Container : Vector;
+      Item      : Element_Type;
+      Position  : Cursor := No_Element) return Cursor is
 
-   end Insert;
+   begin
+      if Position.Container /= null
+        and then (Position.Container /=
+                    Vector_Access'(Container'Unchecked_Access)
+                  or else Position.Index > Container.Last)
+      then
+         raise Program_Error;
+      end if;
 
+      for J in Position.Index .. Container.Last loop
+         if Container.Elements (J) /= null
+           and then Container.Elements (J).all = Item
+         then
+            return (Container'Unchecked_Access, J);
+         end if;
+      end loop;
 
-   procedure Insert_Space
-     (Container : in out Vector;
-      Before    : in     Extended_Index;
-      Count     : in     Count_Type := 1) is
+      return No_Element;
+   end Find;
 
-      Old_Last_As_Int : constant Int := Int (Container.Last);
+   ----------------
+   -- Find_Index --
+   ----------------
 
-      N : constant Int := Int (Count);
+   function Find_Index
+     (Container : Vector;
+      Item      : Element_Type;
+      Index     : Index_Type := Index_Type'First) return Extended_Index is
+   begin
+      for Indx in Index .. Container.Last loop
+         if Container.Elements (Indx) /= null
+           and then Container.Elements (Indx).all = Item
+         then
+            return Indx;
+         end if;
+      end loop;
+
+      return No_Index;
+   end Find_Index;
 
-      New_Last_As_Int : constant Int'Base := Old_Last_As_Int + N;
+   -----------
+   -- First --
+   -----------
 
-      New_Last : constant Extended_Index := Extended_Index (New_Last_As_Int);
+   function First (Container : Vector) return Cursor is
+   begin
+      if Is_Empty (Container) then
+         return No_Element;
+      end if;
 
-      Index : Index_Type;
+      return (Container'Unchecked_Access, Index_Type'First);
+   end First;
 
-      Dst_Last : Index_Type;
-      Dst      : Elements_Access;
+   -------------------
+   -- First_Element --
+   -------------------
 
+   function First_Element (Container : Vector) return Element_Type is
    begin
+      return Element (Container, Index_Type'First);
+   end First_Element;
 
-      if Count = 0 then
-         return;
-      end if;
+   -----------------
+   -- First_Index --
+   -----------------
 
-      declare
-         subtype Before_Subtype is Index_Type'Base range
-           Index_Type'First .. Index_Type'Succ (Container.Last);
+   function First_Index (Container : Vector) return Index_Type is
+      pragma Unreferenced (Container);
+   begin
+      return Index_Type'First;
+   end First_Index;
 
-         Old_First : constant Before_Subtype := Before;
+   ---------------------
+   -- Generic_Sorting --
+   ---------------------
 
-         Old_First_As_Int : constant Int := Int (Old_First);
+   package body Generic_Sorting is
 
-         New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
-      begin
-         Index := Index_Type (New_First_As_Int);
-      end;
+      -----------------------
+      -- Local Subprograms --
+      -----------------------
 
-      if Container.Elements = null then
+      function Is_Less (L, R : Element_Access) return Boolean;
+      pragma Inline (Is_Less);
 
-         declare
-            subtype Elements_Subtype is
-              Elements_Type (Index_Type'First .. New_Last);
-         begin
-            Container.Elements := new Elements_Subtype;
-            Container.Last := New_Last;
-         end;
+      -------------
+      -- Is_Less --
+      -------------
 
-         return;
+      function Is_Less (L, R : Element_Access) return Boolean is
+      begin
+         if L = null then
+            return R /= null;
+         elsif R = null then
+            return False;
+         else
+            return L.all < R.all;
+         end if;
+      end Is_Less;
 
-      end if;
+      ---------------
+      -- Is_Sorted --
+      ---------------
 
-      if New_Last <= Container.Elements'Last then
+      function Is_Sorted (Container : Vector) return Boolean is
+      begin
+         if Container.Last <= Index_Type'First then
+            return True;
+         end if;
 
          declare
             E : Elements_Type renames Container.Elements.all;
          begin
-            E (Index .. New_Last) := E (Before .. Container.Last);
-            E (Before .. Index_Type'Pred (Index)) := (others => null);
-
-            Container.Last := New_Last;
+            for I in Index_Type'First .. Container.Last - 1 loop
+               if Is_Less (E (I + 1), E (I)) then
+                  return False;
+               end if;
+            end loop;
          end;
 
-         return;
+         return True;
+      end Is_Sorted;
 
-      end if;
+      -----------
+      -- Merge --
+      -----------
 
-      declare
+      procedure Merge (Target, Source : in out Vector) is
+         I : Index_Type'Base := Target.Last;
+         J : Index_Type'Base;
 
-         First : constant Int := Int (Index_Type'First);
+      begin
+         if Target.Last < Index_Type'First then
+            Move (Target => Target, Source => Source);
+            return;
+         end if;
 
-         New_Size : constant Int'Base :=
-           Int (New_Last_As_Int) - First + 1;
+         if Target'Address = Source'Address then
+            return;
+         end if;
 
-         Max_Size : constant Int'Base :=
-           Int (Index_Type'Last) - First + 1;
+         if Source.Last < Index_Type'First then
+            return;
+         end if;
 
-         Size, Dst_Last_As_Int : Int'Base;
+         if Source.Busy > 0 then
+            raise Program_Error;
+         end if;
 
-      begin
+         Target.Set_Length (Length (Target) + Length (Source));
 
-         if New_Size >= Max_Size / 2 then
+         J := Target.Last;
+         while Source.Last >= Index_Type'First loop
+            if I < Index_Type'First then
+               declare
+                  Src : Elements_Type renames
+                    Source.Elements (Index_Type'First .. Source.Last);
 
-            Dst_Last := Index_Type'Last;
+               begin
+                  Target.Elements (Index_Type'First .. J) := Src;
+                  Src := (others => null);
+               end;
 
-         else
+               Source.Last := No_Index;
+               return;
+            end if;
 
-            Size := Container.Elements'Length;
+            declare
+               Src : Element_Access renames Source.Elements (Source.Last);
+               Tgt : Element_Access renames Target.Elements (I);
 
-            if Size = 0 then
-               Size := 1;
-            end if;
+            begin
+               if Is_Less (Src, Tgt) then
+                  Target.Elements (J) := Tgt;
+                  Tgt := null;
+                  I := I - 1;
+
+               else
+                  Target.Elements (J) := Src;
+                  Src := null;
+                  Source.Last := Source.Last - 1;
+               end if;
+            end;
 
-            while Size < New_Size loop
-               Size := 2 * Size;
-            end loop;
+            J := J - 1;
+         end loop;
+      end Merge;
 
-            Dst_Last_As_Int := First + Size - 1;
-            Dst_Last := Index_Type (Dst_Last_As_Int);
-
-         end if;
+      ----------
+      -- Sort --
+      ----------
 
-      end;
+      procedure Sort (Container : in out Vector)
+      is
+         procedure Sort is
+            new Generic_Array_Sort
+             (Index_Type   => Index_Type,
+              Element_Type => Element_Access,
+              Array_Type   => Elements_Type,
+              "<"          => Is_Less);
 
-      Dst := new Elements_Type (Index_Type'First .. Dst_Last);
+      --  Start of processing for Sort
 
-      declare
-         Src : Elements_Type renames Container.Elements.all;
       begin
-         Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
-           Src (Index_Type'First .. Index_Type'Pred (Before));
-
-         Dst (Index .. New_Last) := Src (Before .. Container.Last);
-      end;
+         if Container.Last <= Index_Type'First then
+            return;
+         end if;
 
-      declare
-         X : Elements_Access := Container.Elements;
-      begin
-         Container.Elements := Dst;
-         Container.Last := New_Last;
+         if Container.Lock > 0 then
+            raise Program_Error;
+         end if;
 
-         Free (X);
-      end;
+         Sort (Container.Elements (Index_Type'First .. Container.Last));
+      end Sort;
 
-   end Insert_Space;
+   end Generic_Sorting;
 
+   -----------------
+   -- Has_Element --
+   -----------------
 
-   procedure Delete_First (Container : in out Vector;
-                           Count     : in     Count_Type := 1) is
+   function Has_Element (Position : Cursor) return Boolean is
    begin
-
-      if Count = 0 then
-         return;
+      if Position.Container = null then
+         return False;
       end if;
 
-      if Count >= Length (Container) then
-         Clear (Container);
-         return;
-      end if;
+      return Position.Index <= Position.Container.Last;
+   end Has_Element;
 
-      Delete (Container, Index_Type'First, Count);
+   ------------
+   -- Insert --
+   ------------
 
-   end Delete_First;
+   procedure Insert
+     (Container : in out Vector;
+      Before    : Extended_Index;
+      New_Item  : Element_Type;
+      Count     : Count_Type := 1)
+   is
+      N : constant Int := Int (Count);
 
+      New_Last_As_Int : Int'Base;
+      New_Last        : Index_Type;
 
-   procedure Delete_Last (Container : in out Vector;
-                          Count     : in     Count_Type := 1) is
+      Index : Extended_Index;  -- TODO: see note in a-convec.adb.
 
-      Index : Int'Base;
+      Dst_Last : Index_Type;
+      Dst      : Elements_Access;
 
    begin
+      if Before < Index_Type'First then
+         raise Constraint_Error;
+      end if;
+
+      if Before > Container.Last
+        and then Before > Container.Last + 1
+      then
+         raise Constraint_Error;
+      end if;
 
       if Count = 0 then
          return;
       end if;
 
-      if Count >= Length (Container) then
-         Clear (Container);
-         return;
+      declare
+         Old_Last_As_Int : constant Int := Int (Container.Last);
+
+      begin
+         New_Last_As_Int := Old_Last_As_Int + N;
+         New_Last := Index_Type (New_Last_As_Int);
+      end;
+
+      if Container.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      Index := Int'Base (Container.Last) - Int'Base (Count) + 1;
+      declare
+         Old_First_As_Int : constant Int := Int (Before);
 
-      Delete (Container, Index_Type'Base (Index), Count);
+         New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
 
-   end Delete_Last;
+      begin
+         Index := Extended_Index (New_First_As_Int);  --  TODO
+      end;
 
+      if Container.Elements = null then
+         declare
+            subtype Elements_Subtype is
+              Elements_Type (Index_Type'First .. New_Last);
+         begin
+            Container.Elements := new Elements_Subtype;
+            Container.Last := Index_Type'Pred (Index_Type'First);
 
-   procedure Delete
-     (Container : in out Vector;
-      Index     : in     Extended_Index;  --  TODO: verify in Atlanta
-      Count     : in     Count_Type := 1) is
+            for J in Container.Elements'Range loop
+               Container.Elements (J) := new Element_Type'(New_Item);
+               Container.Last := J;
+            end loop;
+         end;
 
-   begin
+         return;
+      end if;
+
+      if New_Last <= Container.Elements'Last then
+         declare
+            E : Elements_Type renames Container.Elements.all;
+         begin
+            E (Index .. New_Last) := E (Before .. Container.Last);
+            Container.Last := New_Last;
+
+            --  NOTE:
+            --  Now we do the allocation.  If it fails, we can propagate the
+            --  exception and invariants are more or less satisfied.  The
+            --  issue is that we have some slots still null, and the client
+            --  has no way of detecting whether the slot is null (unless we
+            --  give him a way).
+            --
+            --  Another way is to allocate a subarray on the stack, do the
+            --  allocation into that array, and if that success then do
+            --  the insertion proper.  The issue there is that you have to
+            --  allocate the subarray on the stack, and that may fail if the
+            --  subarray is long.
+            --
+            --  Or we could try to roll-back the changes: deallocate the
+            --  elements we have successfully deallocated, and then copy
+            --  the elements ptrs back to their original posns.
+            --  END NOTE.
+
+            --  NOTE: I have written the loop manually here.  I could
+            --  have done it this way too:
+            --    E (Before .. Index_Type'Pred (Index)) :=
+            --      (others => new Element_Type'New_Item);
+            --  END NOTE.
+
+            for J in Before .. Index_Type'Pred (Index) loop
+               begin
+                  E (J) := new Element_Type'(New_Item);
+               exception
+                  when others =>
+                     E (J .. Index_Type'Pred (Index)) := (others => null);
+                     raise;
+               end;
+            end loop;
+         end;
 
-      if Count = 0 then
          return;
       end if;
 
       declare
+         First : constant Int := Int (Index_Type'First);
 
-         subtype I_Subtype is Index_Type'Base range
-           Index_Type'First .. Container.Last;
+         New_Size : constant Int'Base := New_Last_As_Int - First + 1;
+         Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
 
-         I : constant I_Subtype := Index;
-         I_As_Int : constant Int := Int (I);
+         Size, Dst_Last_As_Int : Int'Base;
 
-         Old_Last_As_Int : constant Int := Int (Container.Last);
+      begin
+         if New_Size >= Max_Size / 2 then
+            Dst_Last := Index_Type'Last;
 
-         Count1 : constant Int'Base := Int (Count);
-         Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
+         else
+            Size := Container.Elements'Length;
 
-         N : constant Int'Base := Int'Min (Count1, Count2);
+            if Size = 0 then
+               Size := 1;
+            end if;
 
-         J_As_Int : constant Int'Base := I_As_Int + N;
-         J : constant Index_Type'Base := Index_Type'Base (J_As_Int);
+            while Size < New_Size loop
+               Size := 2 * Size;
+            end loop;
 
-         E : Elements_Type renames Container.Elements.all;
+            Dst_Last_As_Int := First + Size - 1;
+            Dst_Last := Index_Type (Dst_Last_As_Int);
+         end if;
+      end;
 
-         New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
+      Dst := new Elements_Type (Index_Type'First .. Dst_Last);
 
-         New_Last : constant Extended_Index :=
-           Extended_Index (New_Last_As_Int);
+      declare
+         Src : Elements_Type renames Container.Elements.all;
 
       begin
+         Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
+           Src (Index_Type'First .. Index_Type'Pred (Before));
 
-         for K in I .. Index_Type'Pred (J) loop
-
-            begin
-               Free (E (K));
-            exception
-               when others =>
-                  E (K) := null;
-                  raise;
-            end;
-
-         end loop;
+         Dst (Index .. New_Last) := Src (Before .. Container.Last);
+      end;
 
-         E (I .. New_Last) := E (J .. Container.Last);
+      declare
+         X : Elements_Access := Container.Elements;
+      begin
+         Container.Elements := Dst;
          Container.Last := New_Last;
 
+         Free (X);
       end;
 
-   end Delete;
+      --  NOTE:
+      --  Now do the allocation.  If the allocation fails,
+      --  then the worst thing is that we have a few null slots.
+      --  Our invariants are otherwise satisfied.
+      --  END NOTE.
 
+      for J in Before .. Index_Type'Pred (Index) loop
+         Dst (J) := new Element_Type'(New_Item);
+      end loop;
+   end Insert;
+
+   procedure Insert
+     (Container : in out Vector;
+      Before    : Extended_Index;
+      New_Item  : Vector)
+   is
+      N : constant Count_Type := Length (New_Item);
 
-   function Capacity (Container : Vector) return Count_Type is
    begin
-      if Container.Elements = null then
-         return 0;
+      if Before < Index_Type'First then
+         raise Constraint_Error;
       end if;
 
-      return Container.Elements'Length;
-   end Capacity;
+      if Before > Container.Last
+        and then Before > Container.Last + 1
+      then
+         raise Constraint_Error;
+      end if;
 
+      if N = 0 then
+         return;
+      end if;
 
-   procedure Reserve_Capacity (Container : in out Vector;
-                               Capacity  : in     Count_Type) is
+      Insert_Space (Container, Before, Count => N);
 
-      N : constant Count_Type := Length (Container);
+      if Container'Address = New_Item'Address then
+         declare
+            Dst_Last_As_Int : constant Int'Base :=
+                                Int'Base (Before) + Int'Base (N) - 1;
 
-   begin
+            Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
 
-      if Capacity = 0 then
+            Dst_Index : Index_Type'Base := Index_Type'Pred (Before);
 
-         if N = 0 then
+            Dst : Elements_Type renames
+                    Container.Elements (Before .. Dst_Last);
 
+         begin
             declare
-               X : Elements_Access := Container.Elements;
+               subtype Src_Index_Subtype is Index_Type'Base range
+                 Index_Type'First .. Index_Type'Pred (Before);
+
+               Src : Elements_Type renames
+                       Container.Elements (Src_Index_Subtype);
+
             begin
-               Container.Elements := null;
-               Free (X);
-            end;
+               for Src_Index in Src'Range loop
+                  Dst_Index := Index_Type'Succ (Dst_Index);
 
-         elsif N < Container.Elements'Length then
+                  if Src (Src_Index) /= null then
+                     Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
+                  end if;
+               end loop;
+            end;
 
             declare
-               subtype Array_Index_Subtype is Index_Type'Base range
-                 Index_Type'First .. Container.Last;
+               subtype Src_Index_Subtype is Index_Type'Base range
+                 Index_Type'Succ (Dst_Last) .. Container.Last;
 
                Src : Elements_Type renames
-                 Container.Elements (Array_Index_Subtype);
-
-               subtype Array_Subtype is
-                 Elements_Type (Array_Index_Subtype);
+                       Container.Elements (Src_Index_Subtype);
 
-               X : Elements_Access := Container.Elements;
             begin
-               Container.Elements := new Array_Subtype'(Src);
-               Free (X);
-            end;
-
-         end if;
+               for Src_Index in Src'Range loop
+                  Dst_Index := Index_Type'Succ (Dst_Index);
 
-         return;
+                  if Src (Src_Index) /= null then
+                     Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
+                  end if;
+               end loop;
+            end;
+         end;
 
-      end if;
+      else
+         declare
+            Dst_Last_As_Int : constant Int'Base :=
+                                Int'Base (Before) + Int'Base (N) - 1;
 
-      if Container.Elements = null then
+            Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
 
-         declare
-            Last_As_Int : constant Int'Base :=
-              Int (Index_Type'First) + Int (Capacity) - 1;
+            Dst_Index : Index_Type'Base := Index_Type'Pred (Before);
 
-            Last : constant Index_Type :=
-              Index_Type (Last_As_Int);
+            Src : Elements_Type renames
+                    New_Item.Elements (Index_Type'First .. New_Item.Last);
 
-            subtype Array_Subtype is
-              Elements_Type (Index_Type'First .. Last);
+            Dst : Elements_Type renames
+                    Container.Elements (Before .. Dst_Last);
          begin
-            Container.Elements := new Array_Subtype;
-         end;
+            for Src_Index in Src'Range loop
+               Dst_Index := Index_Type'Succ (Dst_Index);
 
-         return;
+               if Src (Src_Index) /= null then
+                  Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
+               end if;
+            end loop;
+         end;
 
       end if;
+   end Insert;
 
-      if Capacity <= N then
-
-         if N < Container.Elements'Length then
-
-            declare
-               subtype Array_Index_Subtype is Index_Type'Base range
-                 Index_Type'First .. Container.Last;
-
-               Src : Elements_Type renames
-                 Container.Elements (Array_Index_Subtype);
-
-               subtype Array_Subtype is
-                 Elements_Type (Array_Index_Subtype);
-
-               X : Elements_Access := Container.Elements;
-            begin
-               Container.Elements := new Array_Subtype'(Src);
-               Free (X);
-            end;
-
-         end if;
-
-         return;
+   procedure Insert
+     (Container : in out Vector;
+      Before    : Cursor;
+      New_Item  : Vector)
+   is
+      Index : Index_Type'Base;
 
+   begin
+      if Before.Container /= null
+        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+      then
+         raise Program_Error;
       end if;
 
-      if Capacity = Container.Elements'Length then
+      if Is_Empty (New_Item) then
          return;
       end if;
 
-      declare
-         Last_As_Int : constant Int'Base :=
-           Int (Index_Type'First) + Int (Capacity) - 1;
-
-         Last : constant Index_Type :=
-           Index_Type (Last_As_Int);
-
-         subtype Array_Subtype is
-           Elements_Type (Index_Type'First .. Last);
-
-         X : Elements_Access := Container.Elements;
-      begin
-         Container.Elements := new Array_Subtype;
-
-         declare
-            Src : Elements_Type renames
-              X (Index_Type'First .. Container.Last);
-
-            Tgt : Elements_Type renames
-              Container.Elements (Index_Type'First .. Container.Last);
-         begin
-            Tgt := Src;
-         end;
-
-         Free (X);
-      end;
-
-   end Reserve_Capacity;
-
-
-   function First_Index (Container : Vector) return Index_Type is
-      pragma Warnings (Off, Container);
-   begin
-      return Index_Type'First;
-   end First_Index;
-
-
-   function First_Element (Container : Vector) return Element_Type is
-   begin
-      return Element (Container, Index_Type'First);
-   end First_Element;
-
-
-   function Last_Index (Container : Vector) return Extended_Index is
-   begin
-      return Container.Last;
-   end Last_Index;
-
-
-   function Last_Element (Container : Vector) return Element_Type is
-   begin
-      return Element (Container, Container.Last);
-   end Last_Element;
-
-
-   function Element (Container : Vector;
-                     Index     : Index_Type)
-      return Element_Type is
-
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
-   begin
-      return Container.Elements (T'(Index)).all;
-   end Element;
-
+      if Before.Container = null
+        or else Before.Index > Container.Last
+      then
+         Index := Index_Type'Succ (Container.Last);
+      else
+         Index := Before.Index;
+      end if;
 
-   procedure Replace_Element (Container : in Vector;
-                              Index     : in Index_Type;
-                              By        : in Element_Type) is
+      Insert (Container, Index, New_Item);
+   end Insert;
 
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
+   procedure Insert
+     (Container : in out Vector;
+      Before    : Cursor;
+      New_Item  : Vector;
+      Position  : out Cursor)
+   is
+      Index : Index_Type'Base;
 
-      X : Element_Access := Container.Elements (T'(Index));
    begin
-      Container.Elements (T'(Index)) := new Element_Type'(By);
-      Free (X);
-   end Replace_Element;
-
-
-   procedure Generic_Sort (Container : in Vector) is
-
-      function Is_Less (L, R : Element_Access) return Boolean;
-      pragma Inline (Is_Less);
+      if Before.Container /= null
+        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+      then
+         raise Program_Error;
+      end if;
 
-      function Is_Less (L, R : Element_Access) return Boolean is
-      begin
-         if L = null then
-            return R /= null;
-         elsif R = null then
-            return False;
+      if Is_Empty (New_Item) then
+         if Before.Container = null
+           or else Before.Index > Container.Last
+         then
+            Position := No_Element;
          else
-            return L.all < R.all;
+            Position := (Container'Unchecked_Access, Before.Index);
          end if;
-      end Is_Less;
 
-      procedure Sort is
-         new Generic_Array_Sort
-          (Index_Type,
-           Element_Access,
-           Elements_Type,
-           "<" => Is_Less);
-
-   begin
-
-      if Container.Elements = null then
          return;
       end if;
 
-      Sort (Container.Elements (Index_Type'First .. Container.Last));
-
-   end Generic_Sort;
-
-
-   function Find_Index
-     (Container : Vector;
-      Item      : Element_Type;
-      Index     : Index_Type := Index_Type'First)
-     return Extended_Index is
-
-   begin
-
-      for I in Index .. Container.Last loop
-         if Container.Elements (I) /= null
-           and then Container.Elements (I).all = Item
-         then
-            return I;
-         end if;
-      end loop;
-
-      return No_Index;
-
-   end Find_Index;
-
-
-   function Reverse_Find_Index
-     (Container : Vector;
-      Item      : Element_Type;
-      Index     : Index_Type := Index_Type'Last)
-     return Extended_Index is
-
-      Last : Index_Type'Base;
-
-   begin
-
-      if Index > Container.Last then
-         Last := Container.Last;
+      if Before.Container = null
+        or else Before.Index > Container.Last
+      then
+         Index := Index_Type'Succ (Container.Last);
       else
-         Last := Index;
+         Index := Before.Index;
       end if;
 
-      for I in reverse Index_Type'First .. Last loop
-         if Container.Elements (I) /= null
-           and then Container.Elements (I).all = Item
-         then
-            return I;
-         end if;
-      end loop;
-
-      return No_Index;
-
-   end Reverse_Find_Index;
-
-
-   function Contains (Container : Vector;
-                      Item      : Element_Type) return Boolean is
-   begin
-      return Find_Index (Container, Item) /= No_Index;
-   end Contains;
-
-
+      Insert (Container, Index, New_Item);
 
-   procedure Assign
-     (Target : in out Vector;
-      Source : in     Vector) is
+      Position := Cursor'(Container'Unchecked_Access, Index);
+   end Insert;
 
-      N : constant Count_Type := Length (Source);
+   procedure Insert
+     (Container : in out Vector;
+      Before    : Cursor;
+      New_Item  : Element_Type;
+      Count     : Count_Type := 1)
+   is
+      Index : Index_Type'Base;
 
    begin
-
-      if Target'Address = Source'Address then
-         return;
+      if Before.Container /= null
+        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+      then
+         raise Program_Error;
       end if;
 
-      Clear (Target);
-
-      if N = 0 then
+      if Count = 0 then
          return;
       end if;
 
-      if N > Capacity (Target) then
-         Reserve_Capacity (Target, Capacity => N);
+      if Before.Container = null
+        or else Before.Index > Container.Last
+      then
+         Index := Index_Type'Succ (Container.Last);
+      else
+         Index := Before.Index;
       end if;
 
-      for I in Index_Type'First .. Source.Last loop
-
-         declare
-            EA : constant Element_Access := Source.Elements (I);
-         begin
-            if EA /= null then
-               Target.Elements (I) := new Element_Type'(EA.all);
-            end if;
-         end;
-
-         Target.Last := I;
-
-      end loop;
-
-   end Assign;
-
-
-   procedure Move
-     (Target : in out Vector;
-      Source : in out Vector) is
+      Insert (Container, Index, New_Item, Count);
+   end Insert;
 
-      X : Elements_Access := Target.Elements;
+   procedure Insert
+     (Container : in out Vector;
+      Before    : Cursor;
+      New_Item  : Element_Type;
+      Position  : out Cursor;
+      Count     : Count_Type := 1)
+   is
+      Index : Index_Type'Base;
 
    begin
+      if Before.Container /= null
+        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+      then
+         raise Program_Error;
+      end if;
+
+      if Count = 0 then
+         if Before.Container = null
+           or else Before.Index > Container.Last
+         then
+            Position := No_Element;
+         else
+            Position := (Container'Unchecked_Access, Before.Index);
+         end if;
 
-      if Target'Address = Source'Address then
          return;
       end if;
 
-      if Target.Last >= Index_Type'First then
-         raise Constraint_Error;
+      if Before.Container = null
+        or else Before.Index > Container.Last
+      then
+         Index := Index_Type'Succ (Container.Last);
+      else
+         Index := Before.Index;
       end if;
 
-      Target.Elements := null;
-      Free (X);  --  shouldn't fail
-
-      Target.Elements := Source.Elements;
-      Target.Last := Source.Last;
-
-      Source.Elements := null;
-      Source.Last := Index_Type'Pred (Index_Type'First);
-
-   end Move;
-
-
-   procedure Query_Element
-     (Container : in Vector;
-      Index     : in Index_Type;
-      Process   : not null access procedure (Element : in Element_Type)) is
-
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
-   begin
-      Process (Container.Elements (T'(Index)).all);
-   end Query_Element;
-
-
-   procedure Update_Element
-     (Container : in Vector;
-      Index     : in Index_Type;
-      Process   : not null access procedure (Element : in out Element_Type)) is
-
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
-   begin
-      Process (Container.Elements (T'(Index)).all);
-   end Update_Element;
-
-
-   procedure Prepend (Container : in out Vector;
-                      New_Item  : in     Element_Type;
-                      Count     : in     Count_Type := 1) is
-   begin
-      Insert (Container,
-              Index_Type'First,
-              New_Item,
-              Count);
-   end Prepend;
-
-
-   procedure Swap
-     (Container : in Vector;
-      I, J      : in Index_Type) is
-
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
-
-      EI : constant Element_Access := Container.Elements (T'(I));
+      Insert (Container, Index, New_Item, Count);
 
-   begin
+      Position := (Container'Unchecked_Access, Index);
+   end Insert;
 
-      Container.Elements (T'(I)) := Container.Elements (T'(J));
-      Container.Elements (T'(J)) := EI;
+   ------------------
+   -- Insert_Space --
+   ------------------
 
-   end Swap;
+   procedure Insert_Space
+     (Container : in out Vector;
+      Before    : Extended_Index;
+      Count     : Count_Type := 1)
+   is
+      N : constant Int := Int (Count);
 
+      New_Last_As_Int : Int'Base;
+      New_Last        : Index_Type;
 
-   function "&" (Left, Right : Vector) return Vector is
+      Index : Extended_Index;  --  TODO: see a-convec.adb.
 
-      LN : constant Count_Type := Length (Left);
-      RN : constant Count_Type := Length (Right);
+      Dst_Last : Index_Type;
+      Dst      : Elements_Access;
 
    begin
-
-      if LN = 0 then
-
-         if RN = 0 then
-            return Empty_Vector;
-         end if;
-
-         declare
-            RE : Elements_Type renames
-              Right.Elements (Index_Type'First .. Right.Last);
-
-            Elements : Elements_Access :=
-              new Elements_Type (RE'Range);
-         begin
-            for I in Elements'Range loop
-               begin
-                  if RE (I) /= null then
-                     Elements (I) := new Element_Type'(RE (I).all);
-                  end if;
-               exception
-                  when others =>
-                     for J in Index_Type'First .. Index_Type'Pred (I) loop
-                        Free (Elements (J));
-                     end loop;
-
-                     Free (Elements);
-                     raise;
-               end;
-            end loop;
-
-            return (Controlled with Elements, Right.Last);
-         end;
-
+      if Before < Index_Type'First then
+         raise Constraint_Error;
       end if;
 
-      if RN = 0 then
-
-         declare
-            LE : Elements_Type renames
-              Left.Elements (Index_Type'First .. Left.Last);
-
-            Elements : Elements_Access :=
-              new Elements_Type (LE'Range);
-         begin
-            for I in Elements'Range loop
-               begin
-                  if LE (I) /= null then
-                     Elements (I) := new Element_Type'(LE (I).all);
-                  end if;
-               exception
-                  when others =>
-                     for J in Index_Type'First .. Index_Type'Pred (I) loop
-                        Free (Elements (J));
-                     end loop;
-
-                     Free (Elements);
-                     raise;
-               end;
-            end loop;
-
-            return (Controlled with Elements, Left.Last);
-         end;
+      if Before > Container.Last
+        and then Before > Container.Last + 1
+      then
+         raise Constraint_Error;
+      end if;
 
+      if Count = 0 then
+         return;
       end if;
 
       declare
-
-         Last_As_Int : constant Int'Base :=
-            Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
-
-         Last : constant Index_Type := Index_Type (Last_As_Int);
-
-         LE : Elements_Type renames
-           Left.Elements (Index_Type'First .. Left.Last);
-
-         RE : Elements_Type renames
-           Right.Elements (Index_Type'First .. Right.Last);
-
-         Elements : Elements_Access :=
-           new Elements_Type (Index_Type'First .. Last);
-
-         I : Index_Type'Base := Index_Type'Pred (Index_Type'First);
+         Old_Last_As_Int : constant Int := Int (Container.Last);
 
       begin
-
-         for LI in LE'Range loop
-
-            I := Index_Type'Succ (I);
-
-            begin
-               if LE (LI) /= null then
-                  Elements (I) := new Element_Type'(LE (LI).all);
-               end if;
-            exception
-               when others =>
-                  for J in Index_Type'First .. Index_Type'Pred (I) loop
-                     Free (Elements (J));
-                  end loop;
-
-                  Free (Elements);
-                  raise;
-            end;
-
-         end loop;
-
-         for RI in RE'Range loop
-
-            I := Index_Type'Succ (I);
-
-            begin
-               if RE (RI) /= null then
-                  Elements (I) := new Element_Type'(RE (RI).all);
-               end if;
-            exception
-               when others =>
-                  for J in Index_Type'First .. Index_Type'Pred (I) loop
-                     Free (Elements (J));
-                  end loop;
-
-                  Free (Elements);
-                  raise;
-            end;
-
-         end loop;
-
-         return (Controlled with Elements, Last);
+         New_Last_As_Int := Old_Last_As_Int + N;
+         New_Last := Index_Type (New_Last_As_Int);
       end;
 
-   end "&";
-
-
-   function "&" (Left  : Vector;
-                 Right : Element_Type) return Vector is
-
-      LN : constant Count_Type := Length (Left);
-
-   begin
-
-      if LN = 0 then
-
-         declare
-            Elements : Elements_Access :=
-              new Elements_Type (Index_Type'First .. Index_Type'First);
-         begin
-
-            begin
-               Elements (Elements'First) := new Element_Type'(Right);
-            exception
-               when others =>
-                  Free (Elements);
-                  raise;
-            end;
-
-            return (Controlled with Elements, Index_Type'First);
-
-         end;
-
+      if Container.Busy > 0 then
+         raise Program_Error;
       end if;
 
       declare
+         Old_First_As_Int : constant Int := Int (Before);
 
-         Last_As_Int : constant Int'Base :=
-            Int (Index_Type'First) + Int (LN);
-
-         Last : constant Index_Type := Index_Type (Last_As_Int);
-
-         LE : Elements_Type renames
-           Left.Elements (Index_Type'First .. Left.Last);
-
-         Elements : Elements_Access :=
-           new Elements_Type (Index_Type'First .. Last);
+         New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
 
       begin
+         Index := Extended_Index (New_First_As_Int);  --  TODO
+      end;
 
-         for I in LE'Range loop
-
-            begin
-               if LE (I) /= null then
-                  Elements (I) := new Element_Type'(LE (I).all);
-               end if;
-            exception
-               when others =>
-                  for J in Index_Type'First .. Index_Type'Pred (I) loop
-                     Free (Elements (J));
-                  end loop;
-
-                  Free (Elements);
-                  raise;
-            end;
-
-         end loop;
-
-         begin
-            Elements (Elements'Last) := new Element_Type'(Right);
-         exception
-            when others =>
-
-               declare
-                  subtype J_Subtype is Index_Type'Base range
-                    Index_Type'First .. Index_Type'Pred (Elements'Last);
-               begin
-                  for J in J_Subtype loop
-                     Free (Elements (J));
-                  end loop;
-               end;
-
-               Free (Elements);
-               raise;
-         end;
-
-         return (Controlled with Elements, Last);
-      end;
-
-   end "&";
-
-
-
-   function "&" (Left  : Element_Type;
-                 Right : Vector) return Vector is
-
-      RN : constant Count_Type := Length (Right);
-
-   begin
-
-      if RN = 0 then
-
+      if Container.Elements = null then
          declare
-            Elements : Elements_Access :=
-              new Elements_Type (Index_Type'First .. Index_Type'First);
+            subtype Elements_Subtype is
+              Elements_Type (Index_Type'First .. New_Last);
          begin
+            Container.Elements := new Elements_Subtype;
+            Container.Last := New_Last;
+         end;
 
-            begin
-               Elements (Elements'First) := new Element_Type'(Left);
-            exception
-               when others =>
-                  Free (Elements);
-                  raise;
-            end;
+         return;
+      end if;
 
-            return (Controlled with Elements, Index_Type'First);
+      if New_Last <= Container.Elements'Last then
+         declare
+            E : Elements_Type renames Container.Elements.all;
+         begin
+            E (Index .. New_Last) := E (Before .. Container.Last);
+            E (Before .. Index_Type'Pred (Index)) := (others => null);
 
+            Container.Last := New_Last;
          end;
 
+         return;
       end if;
 
       declare
+         First : constant Int := Int (Index_Type'First);
 
-         Last_As_Int : constant Int'Base :=
-            Int (Index_Type'First) + Int (RN);
+         New_Size : constant Int'Base :=
+                      Int (New_Last_As_Int) - First + 1;
 
-         Last : constant Index_Type := Index_Type (Last_As_Int);
+         Max_Size : constant Int'Base :=
+                      Int (Index_Type'Last) - First + 1;
 
-         RE : Elements_Type renames
-           Right.Elements (Index_Type'First .. Right.Last);
+         Size, Dst_Last_As_Int : Int'Base;
 
-         Elements : Elements_Access :=
-           new Elements_Type (Index_Type'First .. Last);
+      begin
+         if New_Size >= Max_Size / 2 then
+            Dst_Last := Index_Type'Last;
 
-         I : Index_Type'Base := Index_Type'First;
+         else
+            Size := Container.Elements'Length;
 
-      begin
+            if Size = 0 then
+               Size := 1;
+            end if;
 
-         begin
-            Elements (I) := new Element_Type'(Left);
-         exception
-            when others =>
-               Free (Elements);
-               raise;
-         end;
+            while Size < New_Size loop
+               Size := 2 * Size;
+            end loop;
 
-         for RI in RE'Range loop
+            Dst_Last_As_Int := First + Size - 1;
+            Dst_Last := Index_Type (Dst_Last_As_Int);
+         end if;
+      end;
 
-            I := Index_Type'Succ (I);
+      Dst := new Elements_Type (Index_Type'First .. Dst_Last);
 
-            begin
-               if RE (RI) /= null then
-                  Elements (I) := new Element_Type'(RE (RI).all);
-               end if;
-            exception
-               when others =>
-                  for J in Index_Type'First .. Index_Type'Pred (I) loop
-                     Free (Elements (J));
-                  end loop;
+      declare
+         Src : Elements_Type renames Container.Elements.all;
 
-                  Free (Elements);
-                  raise;
-            end;
+      begin
+         Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
+           Src (Index_Type'First .. Index_Type'Pred (Before));
 
-         end loop;
+         Dst (Index .. New_Last) := Src (Before .. Container.Last);
+      end;
 
-         return (Controlled with Elements, Last);
+      declare
+         X : Elements_Access := Container.Elements;
+      begin
+         Container.Elements := Dst;
+         Container.Last := New_Last;
+
+         Free (X);
       end;
+   end Insert_Space;
 
-   end "&";
+   procedure Insert_Space
+     (Container : in out Vector;
+      Before    : Cursor;
+      Position  : out Cursor;
+      Count     : Count_Type := 1)
+   is
+      Index : Index_Type'Base;
+
+   begin
+      if Before.Container /= null
+        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+      then
+         raise Program_Error;
+      end if;
 
+      if Count = 0 then
+         if Before.Container = null
+           or else Before.Index > Container.Last
+         then
+            Position := No_Element;
+         else
+            Position := (Container'Unchecked_Access, Before.Index);
+         end if;
 
-   function "&" (Left, Right  : Element_Type) return Vector is
+         return;
+      end if;
 
-      subtype IT is Index_Type'Base range
-        Index_Type'First .. Index_Type'Succ (Index_Type'First);
+      if Before.Container = null
+        or else Before.Index > Container.Last
+      then
+         Index := Index_Type'Succ (Container.Last);
+      else
+         Index := Before.Index;
+      end if;
 
-      Elements : Elements_Access := new Elements_Type (IT);
+      Insert_Space (Container, Index, Count);
 
+      Position := Cursor'(Container'Unchecked_Access, Index);
+   end Insert_Space;
+
+   --------------
+   -- Is_Empty --
+   --------------
+
+   function Is_Empty (Container : Vector) return Boolean is
    begin
+      return Container.Last < Index_Type'First;
+   end Is_Empty;
 
-      begin
-         Elements (Elements'First) := new Element_Type'(Left);
-      exception
-         when others =>
-            Free (Elements);
-            raise;
-      end;
+   -------------
+   -- Iterate --
+   -------------
+
+   procedure Iterate
+     (Container : Vector;
+      Process   : not null access procedure (Position : in Cursor))
+   is
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+
+   begin
+      B := B + 1;
 
       begin
-         Elements (Elements'Last) := new Element_Type'(Right);
+         for Indx in Index_Type'First .. Container.Last loop
+            Process (Cursor'(Container'Unchecked_Access, Indx));
+         end loop;
       exception
          when others =>
-            Free (Elements (Elements'First));
-            Free (Elements);
+            B := B - 1;
             raise;
       end;
 
-      return (Controlled with Elements, Elements'Last);
-
-   end "&";
+      B := B - 1;
+   end Iterate;
 
+   ----------
+   -- Last --
+   ----------
 
-   function To_Cursor (Container : Vector;
-                       Index     : Extended_Index)
-      return Cursor is
+   function Last (Container : Vector) return Cursor is
    begin
-      if Index not in Index_Type'First .. Container.Last then
+      if Is_Empty (Container) then
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Index);
-   end To_Cursor;
+      return (Container'Unchecked_Access, Container.Last);
+   end Last;
 
+   ------------------
+   -- Last_Element --
+   ------------------
 
-   function To_Index (Position : Cursor) return Extended_Index is
+   function Last_Element (Container : Vector) return Element_Type is
    begin
-      if Position.Container = null then
-         return No_Index;
-      end if;
+      return Element (Container, Container.Last);
+   end Last_Element;
 
-      if Position.Index <= Position.Container.Last then
-         return Position.Index;
-      end if;
+   ----------------
+   -- Last_Index --
+   ----------------
 
-      return No_Index;
-   end To_Index;
+   function Last_Index (Container : Vector) return Extended_Index is
+   begin
+      return Container.Last;
+   end Last_Index;
 
+   ------------
+   -- Length --
+   ------------
 
-   function Element (Position : Cursor) return Element_Type is
+   function Length (Container : Vector) return Count_Type is
+      L : constant Int := Int (Container.Last);
+      F : constant Int := Int (Index_Type'First);
+      N : constant Int'Base := L - F + 1;
    begin
-      return Element (Position.Container.all, Position.Index);
-   end Element;
+      return Count_Type (N);
+   end Length;
 
+   ----------
+   -- Move --
+   ----------
 
-   function Next (Position : Cursor) return Cursor is
+   procedure Move
+     (Target : in out Vector;
+      Source : in out Vector)
+   is
    begin
-
-      if Position.Container = null then
-         return No_Element;
+      if Target'Address = Source'Address then
+         return;
       end if;
 
-      if Position.Index < Position.Container.Last then
-         return (Position.Container, Index_Type'Succ (Position.Index));
+      if Source.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      return No_Element;
+      Clear (Target);
 
-   end Next;
+      declare
+         X : Elements_Access := Target.Elements;
+      begin
+         Target.Elements := null;
+         Free (X);
+      end;
 
+      Target.Elements := Source.Elements;
+      Target.Last := Source.Last;
 
-   function Previous (Position : Cursor) return Cursor is
-   begin
+      Source.Elements := null;
+      Source.Last := No_Index;
+   end Move;
+
+   ----------
+   -- Next --
+   ----------
 
+   function Next (Position : Cursor) return Cursor is
+   begin
       if Position.Container = null then
          return No_Element;
       end if;
 
-      if Position.Index > Index_Type'First then
-         return (Position.Container, Index_Type'Pred (Position.Index));
+      if Position.Index < Position.Container.Last then
+         return (Position.Container, Index_Type'Succ (Position.Index));
       end if;
 
       return No_Element;
+   end Next;
 
-   end Previous;
-
+   ----------
+   -- Next --
+   ----------
 
    procedure Next (Position : in out Cursor) is
    begin
-
       if Position.Container = null then
          return;
       end if;
@@ -1615,13 +1689,35 @@ package body Ada.Containers.Indefinite_Vectors is
       else
          Position := No_Element;
       end if;
-
    end Next;
 
+   -------------
+   -- Prepend --
+   -------------
 
-   procedure Previous (Position : in out Cursor) is
+   procedure Prepend (Container : in out Vector; New_Item : Vector) is
+   begin
+      Insert (Container, Index_Type'First, New_Item);
+   end Prepend;
+
+   procedure Prepend
+     (Container : in out Vector;
+      New_Item  : Element_Type;
+      Count     : Count_Type := 1)
+   is
    begin
+      Insert (Container,
+              Index_Type'First,
+              New_Item,
+              Count);
+   end Prepend;
 
+   --------------
+   -- Previous --
+   --------------
+
+   procedure Previous (Position : in out Cursor) is
+   begin
       if Position.Container = null then
          return;
       end if;
@@ -1631,541 +1727,618 @@ package body Ada.Containers.Indefinite_Vectors is
       else
          Position := No_Element;
       end if;
-
    end Previous;
 
-
-   function Has_Element (Position : Cursor) return Boolean is
+   function Previous (Position : Cursor) return Cursor is
    begin
-
       if Position.Container = null then
-         return False;
+         return No_Element;
       end if;
 
-      return Position.Index <= Position.Container.Last;
-
-   end Has_Element;
+      if Position.Index > Index_Type'First then
+         return (Position.Container, Index_Type'Pred (Position.Index));
+      end if;
 
+      return No_Element;
+   end Previous;
 
-   procedure Iterate
-     (Container : in Vector;
-      Process   : not null access procedure (Position : in Cursor)) is
-   begin
+   -------------------
+   -- Query_Element --
+   -------------------
 
-      for I in Index_Type'First .. Container.Last loop
-         Process (Cursor'(Container'Unchecked_Access, I));
-      end loop;
+   procedure Query_Element
+     (Container : Vector;
+      Index     : Index_Type;
+      Process   : not null access procedure (Element : in Element_Type))
+   is
+      subtype T is Index_Type'Base range
+        Index_Type'First .. Container.Last;
 
-   end Iterate;
+      E : Element_Type renames Container.Elements (T'(Index)).all;
 
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+      L : Natural renames V.Lock;
 
-   procedure Reverse_Iterate
-     (Container : in Vector;
-      Process   : not null access procedure (Position : in Cursor)) is
    begin
+      B := B + 1;
+      L := L + 1;
 
-      for I in reverse Index_Type'First .. Container.Last loop
-         Process (Cursor'(Container'Unchecked_Access, I));
-      end loop;
-
-   end Reverse_Iterate;
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
 
+      L := L - 1;
+      B := B - 1;
+   end Query_Element;
 
    procedure Query_Element
-     (Position : in Cursor;
-      Process  : not null access procedure (Element : in Element_Type)) is
-
-      C : Vector renames Position.Container.all;
-      E : Elements_Type renames C.Elements.all;
-
-      subtype T is Index_Type'Base range
-        Index_Type'First .. C.Last;
+     (Position : Cursor;
+      Process  : not null access procedure (Element : in Element_Type))
+   is
    begin
-      Process (E (T'(Position.Index)).all);
+      Query_Element (Position.Container.all, Position.Index, Process);
    end Query_Element;
 
+   ----------
+   -- Read --
+   ----------
 
-   procedure Update_Element
-     (Position : in Cursor;
-      Process  : not null access procedure (Element : in out Element_Type)) is
+   procedure Read
+     (Stream    : access Root_Stream_Type'Class;
+      Container : out Vector)
+   is
+      Length : Count_Type'Base;
+      Last   : Index_Type'Base := Index_Type'Pred (Index_Type'First);
 
-      C : Vector renames Position.Container.all;
-      E : Elements_Type renames C.Elements.all;
+      B : Boolean;
 
-      subtype T is Index_Type'Base range
-        Index_Type'First .. C.Last;
    begin
-      Process (E (T'(Position.Index)).all);
-   end Update_Element;
+      Clear (Container);
 
+      Count_Type'Base'Read (Stream, Length);
 
-   procedure Replace_Element (Position : in Cursor;
-                              By       : in Element_Type) is
+      if Length > Capacity (Container) then
+         Reserve_Capacity (Container, Capacity => Length);
+      end if;
 
-      C : Vector renames Position.Container.all;
-      E : Elements_Type renames C.Elements.all;
+      for J in Count_Type range 1 .. Length loop
+         Last := Index_Type'Succ (Last);
 
-      subtype T is Index_Type'Base range
-        Index_Type'First .. C.Last;
+         Boolean'Read (Stream, B);
 
-      X : Element_Access := E (T'(Position.Index));
-   begin
-      E (T'(Position.Index)) := new Element_Type'(By);
-      Free (X);
-   end Replace_Element;
+         if B then
+            Container.Elements (Last) :=
+              new Element_Type'(Element_Type'Input (Stream));
+         end if;
+
+         Container.Last := Last;
+      end loop;
+   end Read;
 
+   ---------------------
+   -- Replace_Element --
+   ---------------------
 
-   procedure Insert (Container : in out Vector;
-                     Before    : in     Extended_Index;
-                     New_Item  : in     Vector) is
+   procedure Replace_Element
+     (Container : Vector;
+      Index     : Index_Type;
+      By        : Element_Type)
+   is
+      subtype T is Index_Type'Base range
+        Index_Type'First .. Container.Last;
 
-      N : constant Count_Type := Length (New_Item);
+      X : Element_Access := Container.Elements (T'(Index));
 
    begin
-
-      if N = 0 then
-         return;
+      if Container.Lock > 0 then
+         raise Program_Error;
       end if;
 
-      Insert_Space (Container, Before, Count => N);
-
-      if Container'Address = New_Item'Address then
-
-         declare
-            Dst_Last_As_Int : constant Int'Base :=
-              Int'Base (Before) + Int'Base (N) - 1;
+      Container.Elements (T'(Index)) := new Element_Type'(By);
+      Free (X);
+   end Replace_Element;
 
-            Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
+   procedure Replace_Element (Position : Cursor; By : Element_Type) is
+   begin
+      Replace_Element (Position.Container.all, Position.Index, By);
+   end Replace_Element;
 
-            Dst_Index : Index_Type'Base := Index_Type'Pred (Before);
+   ----------------------
+   -- Reserve_Capacity --
+   ----------------------
 
-            Dst : Elements_Type renames
-              Container.Elements (Before .. Dst_Last);
-         begin
+   procedure Reserve_Capacity
+     (Container : in out Vector;
+      Capacity  : Count_Type)
+   is
+      N : constant Count_Type := Length (Container);
 
+   begin
+      if Capacity = 0 then
+         if N = 0 then
             declare
-               subtype Src_Index_Subtype is Index_Type'Base range
-                 Index_Type'First .. Index_Type'Pred (Before);
-
-               Src : Elements_Type renames
-                 Container.Elements (Src_Index_Subtype);
+               X : Elements_Access := Container.Elements;
             begin
-               for Src_Index in Src'Range loop
-                  Dst_Index := Index_Type'Succ (Dst_Index);
-
-                  if Src (Src_Index) /= null then
-                     Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
-                  end if;
-               end loop;
+               Container.Elements := null;
+               Free (X);
             end;
 
+         elsif N < Container.Elements'Length then
+            if Container.Busy > 0 then
+               raise Program_Error;
+            end if;
+
             declare
-               subtype Src_Index_Subtype is Index_Type'Base range
-                 Index_Type'Succ (Dst_Last) .. Container.Last;
+               subtype Array_Index_Subtype is Index_Type'Base range
+                 Index_Type'First .. Container.Last;
 
                Src : Elements_Type renames
-                 Container.Elements (Src_Index_Subtype);
-            begin
-               for Src_Index in Src'Range loop
-                  Dst_Index := Index_Type'Succ (Dst_Index);
+                       Container.Elements (Array_Index_Subtype);
 
-                  if Src (Src_Index) /= null then
-                     Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
-                  end if;
-               end loop;
+               subtype Array_Subtype is
+                 Elements_Type (Array_Index_Subtype);
+
+               X : Elements_Access := Container.Elements;
+            begin
+               Container.Elements := new Array_Subtype'(Src);
+               Free (X);
             end;
 
-         end;
+         end if;
 
-      else
+         return;
+      end if;
 
+      if Container.Elements = null then
          declare
-            Dst_Last_As_Int : constant Int'Base :=
-              Int'Base (Before) + Int'Base (N) - 1;
-
-            Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
+            Last_As_Int : constant Int'Base :=
+                            Int (Index_Type'First) + Int (Capacity) - 1;
 
-            Dst_Index : Index_Type'Base := Index_Type'Pred (Before);
+            Last : constant Index_Type :=
+                     Index_Type (Last_As_Int);
 
-            Src : Elements_Type renames
-              New_Item.Elements (Index_Type'First .. New_Item.Last);
+            subtype Array_Subtype is
+              Elements_Type (Index_Type'First .. Last);
 
-            Dst : Elements_Type renames
-              Container.Elements (Before .. Dst_Last);
          begin
-            for Src_Index in Src'Range loop
-               Dst_Index := Index_Type'Succ (Dst_Index);
-
-               if Src (Src_Index) /= null then
-                  Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
-               end if;
-            end loop;
+            Container.Elements := new Array_Subtype;
          end;
 
-      end if;
-
-   end Insert;
-
-
-   procedure Insert (Container : in out Vector;
-                     Before    : in     Cursor;
-                     New_Item  : in     Vector) is
-
-      Index : Index_Type'Base;
-
-   begin
-
-      if Before.Container /= null
-        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
-      end if;
-
-      if Is_Empty (New_Item) then
          return;
       end if;
 
-      if Before.Container = null
-        or else Before.Index > Container.Last
-      then
-         Index := Index_Type'Succ (Container.Last);
-      else
-         Index := Before.Index;
-      end if;
-
-      Insert (Container, Index, New_Item);
-
-   end Insert;
-
-
+      if Capacity <= N then
+         if N < Container.Elements'Length then
+            if Container.Busy > 0 then
+               raise Program_Error;
+            end if;
 
-   procedure Insert (Container : in out Vector;
-                     Before    : in     Cursor;
-                     New_Item  : in     Vector;
-                     Position  :    out Cursor) is
+            declare
+               subtype Array_Index_Subtype is Index_Type'Base range
+                 Index_Type'First .. Container.Last;
 
-      Index : Index_Type'Base;
+               Src : Elements_Type renames
+                       Container.Elements (Array_Index_Subtype);
 
-   begin
+               subtype Array_Subtype is
+                 Elements_Type (Array_Index_Subtype);
 
-      if Before.Container /= null
-        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
-      end if;
+               X : Elements_Access := Container.Elements;
 
-      if Is_Empty (New_Item) then
+            begin
+               Container.Elements := new Array_Subtype'(Src);
+               Free (X);
+            end;
 
-         if Before.Container = null
-           or else Before.Index > Container.Last
-         then
-            Position := No_Element;
-         else
-            Position := (Container'Unchecked_Access, Before.Index);
          end if;
 
          return;
-
       end if;
 
-      if Before.Container = null
-        or else Before.Index > Container.Last
-      then
-         Index := Index_Type'Succ (Container.Last);
-      else
-         Index := Before.Index;
+      if Capacity = Container.Elements'Length then
+         return;
       end if;
 
-      Insert (Container, Index, New_Item);
-
-      Position := (Container'Unchecked_Access, Index);
-
-   end Insert;
-
-
-   procedure Insert (Container : in out Vector;
-                     Before    : in     Cursor;
-                     New_Item  : in     Element_Type;
-                     Count     : in     Count_Type := 1) is
-
-      Index : Index_Type'Base;
-
-   begin
-
-      if Before.Container /= null
-        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
-      then
+      if Container.Busy > 0 then
          raise Program_Error;
       end if;
 
-      if Count = 0 then
-         return;
-      end if;
-
-      if Before.Container = null
-        or else Before.Index > Container.Last
-      then
-         Index := Index_Type'Succ (Container.Last);
-      else
-         Index := Before.Index;
-      end if;
+      declare
+         Last_As_Int : constant Int'Base :=
+                         Int (Index_Type'First) + Int (Capacity) - 1;
 
-      Insert (Container, Index, New_Item, Count);
+         Last        : constant Index_Type := Index_Type (Last_As_Int);
 
-   end Insert;
+         subtype Array_Subtype is
+           Elements_Type (Index_Type'First .. Last);
 
+         X : Elements_Access := Container.Elements;
 
-   procedure Insert (Container : in out Vector;
-                     Before    : in     Cursor;
-                     New_Item  : in     Element_Type;
-                     Position  :    out Cursor;
-                     Count     : in     Count_Type := 1) is
+      begin
+         Container.Elements := new Array_Subtype;
 
-      Index : Index_Type'Base;
+         declare
+            Src : Elements_Type renames
+                    X (Index_Type'First .. Container.Last);
 
-   begin
+            Tgt : Elements_Type renames
+                    Container.Elements (Index_Type'First .. Container.Last);
 
-      if Before.Container /= null
-        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
-      end if;
+         begin
+            Tgt := Src;
+         end;
 
-      if Count = 0 then
+         Free (X);
+      end;
+   end Reserve_Capacity;
 
-         if Before.Container = null
-           or else Before.Index > Container.Last
-         then
-            Position := No_Element;
-         else
-            Position := (Container'Unchecked_Access, Before.Index);
-         end if;
+   ------------------
+   -- Reverse_Find --
+   ------------------
 
-         return;
+   function Reverse_Find
+     (Container : Vector;
+      Item      : Element_Type;
+      Position  : Cursor := No_Element) return Cursor
+   is
+      Last : Index_Type'Base;
 
+   begin
+      if Position.Container /= null
+        and then Position.Container /=
+                   Vector_Access'(Container'Unchecked_Access)
+      then
+         raise Program_Error;
       end if;
 
-      if Before.Container = null
-        or else Before.Index > Container.Last
+      if Position.Container = null
+        or else Position.Index > Container.Last
       then
-         Index := Index_Type'Succ (Container.Last);
+         Last := Container.Last;
       else
-         Index := Before.Index;
+         Last := Position.Index;
       end if;
 
-      Insert (Container, Index, New_Item, Count);
-
-      Position := (Container'Unchecked_Access, Index);
+      for Indx in reverse Index_Type'First .. Last loop
+         if Container.Elements (Indx) /= null
+           and then Container.Elements (Indx).all = Item
+         then
+            return (Container'Unchecked_Access, Indx);
+         end if;
+      end loop;
 
-   end Insert;
+      return No_Element;
+   end Reverse_Find;
 
+   ------------------------
+   -- Reverse_Find_Index --
+   ------------------------
 
+   function Reverse_Find_Index
+     (Container : Vector;
+      Item      : Element_Type;
+      Index     : Index_Type := Index_Type'Last) return Extended_Index
+   is
+      Last : Index_Type'Base;
 
-   procedure Prepend (Container : in out Vector;
-                      New_Item  : in     Vector) is
    begin
-      Insert (Container, Index_Type'First, New_Item);
-   end Prepend;
+      if Index > Container.Last then
+         Last := Container.Last;
+      else
+         Last := Index;
+      end if;
+
+      for Indx in reverse Index_Type'First .. Last loop
+         if Container.Elements (Indx) /= null
+           and then Container.Elements (Indx).all = Item
+         then
+            return Indx;
+         end if;
+      end loop;
 
+      return No_Index;
+   end Reverse_Find_Index;
 
-   procedure Append (Container : in out Vector;
-                     New_Item  : in     Vector) is
-   begin
-      if Is_Empty (New_Item) then
-         return;
-      end if;
+   ---------------------
+   -- Reverse_Iterate --
+   ---------------------
 
-      Insert
-        (Container,
-         Index_Type'Succ (Container.Last),
-         New_Item);
-   end Append;
+   procedure Reverse_Iterate
+     (Container : Vector;
+      Process   : not null access procedure (Position : in Cursor))
+   is
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+
+   begin
+      B := B + 1;
 
+      begin
+         for Indx in reverse Index_Type'First .. Container.Last loop
+            Process (Cursor'(Container'Unchecked_Access, Indx));
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
 
+      B := B - 1;
+   end Reverse_Iterate;
 
-   procedure Insert_Space (Container : in out Vector;
-                           Before    : in     Cursor;
-                           Position  :    out Cursor;
-                           Count     : in     Count_Type := 1) is
+   ----------------
+   -- Set_Length --
+   ----------------
 
-      Index : Index_Type'Base;
+   procedure Set_Length
+     (Container : in out Vector;
+      Length    : Count_Type)
+   is
+      N : constant Count_Type := Indefinite_Vectors.Length (Container);
 
    begin
+      if Length = N then
+         return;
+      end if;
 
-      if Before.Container /= null
-        and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
-      then
+      if Length = 0 then
+         Clear (Container);
+         return;
+      end if;
+
+      if Container.Busy > 0 then
          raise Program_Error;
       end if;
 
-      if Count = 0 then
+      declare
+         Last_As_Int : constant Int'Base :=
+                         Int (Index_Type'First) + Int (Length) - 1;
 
-         if Before.Container = null
-           or else Before.Index > Container.Last
-         then
-            Position := No_Element;
-         else
-            Position := (Container'Unchecked_Access, Before.Index);
-         end if;
+         Last        : constant Index_Type :=
+                         Index_Type (Last_As_Int);
 
-         return;
+      begin
+         if Length > N then
+            if Length > Capacity (Container) then
+               Reserve_Capacity (Container, Capacity => Length);
+            end if;
 
-      end if;
+            Container.Last := Last;
+            return;
+         end if;
 
-      if Before.Container = null
-        or else Before.Index > Container.Last
-      then
-         Index := Index_Type'Succ (Container.Last);
-      else
-         Index := Before.Index;
-      end if;
+         for Indx in reverse Index_Type'Succ (Last) .. Container.Last loop
+            declare
+               X : Element_Access := Container.Elements (Indx);
 
-      Insert_Space (Container, Index, Count);
+            begin
+               Container.Elements (Indx) := null;
+               Container.Last := Index_Type'Pred (Container.Last);
+               Free (X);
+            end;
+         end loop;
+      end;
+   end Set_Length;
 
-      Position := (Container'Unchecked_Access, Index);
+   ----------
+   -- Swap --
+   ----------
 
-   end Insert_Space;
+   procedure Swap
+     (Container : Vector;
+      I, J      : Index_Type)
+   is
+      subtype T is Index_Type'Base range
+        Index_Type'First .. Container.Last;
 
+      EI : Element_Type renames Container.Elements (T'(I)).all;
+      EJ : Element_Type renames Container.Elements (T'(J)).all;
 
-   procedure Delete (Container : in out Vector;
-                     Position  : in out Cursor;
-                     Count     : in     Count_Type := 1) is
    begin
-
-      if Position.Container /= null
-        and then Position.Container /=
-                   Vector_Access'(Container'Unchecked_Access)
-      then
+      if Container.Lock > 0 then
          raise Program_Error;
       end if;
 
-      if Position.Container = null
-        or else Position.Index > Container.Last
+      declare
+         EI_Copy : constant Element_Type := EI;
+      begin
+         EI := EJ;
+         EJ := EI_Copy;
+      end;
+   end Swap;
+
+   procedure Swap (I, J : Cursor)
+   is
+   begin
+      if I.Container = null
+        or else J.Container = null
       then
-         Position := No_Element;
-         return;
+         raise Constraint_Error;
       end if;
 
-      Delete (Container, Position.Index, Count);
-
-      if Position.Index <= Container.Last then
-         Position := (Container'Unchecked_Access, Position.Index);
-      else
-         Position := No_Element;
+      if I.Container /= J.Container then
+         raise Program_Error;
       end if;
 
-   end Delete;
+      Swap (I.Container.all, I.Index, J.Index);
+   end Swap;
 
+   ---------------
+   -- To_Cursor --
+   ---------------
 
-   function First (Container : Vector) return Cursor is
+   function To_Cursor
+     (Container : Vector;
+      Index     : Extended_Index) return Cursor
+   is
    begin
-      if Is_Empty (Container) then
+      if Index not in Index_Type'First .. Container.Last then
          return No_Element;
       end if;
 
-      return (Container'Unchecked_Access, Index_Type'First);
-   end First;
+      return Cursor'(Container'Unchecked_Access, Index);
+   end To_Cursor;
 
+   --------------
+   -- To_Index --
+   --------------
 
-   function Last (Container : Vector) return Cursor is
+   function To_Index (Position : Cursor) return Extended_Index is
    begin
-      if Is_Empty (Container) then
-         return No_Element;
+      if Position.Container = null then
+         return No_Index;
       end if;
 
-      return (Container'Unchecked_Access, Container.Last);
-   end Last;
+      if Position.Index <= Position.Container.Last then
+         return Position.Index;
+      end if;
 
+      return No_Index;
+   end To_Index;
 
-   procedure Swap (I, J : in Cursor) is
+   ---------------
+   -- To_Vector --
+   ---------------
 
-      --  NOTE: I've liberalized the behavior here, to
-      --  allow I and J to designate different containers.
-      --  TODO: I think this is suppose to raise P_E.
+   function To_Vector (Length : Count_Type) return Vector is
+   begin
+      if Length = 0 then
+         return Empty_Vector;
+      end if;
 
-      subtype TI is Index_Type'Base range
-        Index_Type'First .. I.Container.Last;
+      declare
+         First       : constant Int := Int (Index_Type'First);
+         Last_As_Int : constant Int'Base := First + Int (Length) - 1;
+         Last        : constant Index_Type := Index_Type (Last_As_Int);
+         Elements    : constant Elements_Access :=
+                         new Elements_Type (Index_Type'First .. Last);
+      begin
+         return (Controlled with Elements, Last, 0, 0);
+      end;
+   end To_Vector;
 
-      EI : Element_Access renames
-        I.Container.Elements (TI'(I.Index));
+   function To_Vector
+     (New_Item : Element_Type;
+      Length   : Count_Type) return Vector
+   is
+   begin
+      if Length = 0 then
+         return Empty_Vector;
+      end if;
 
-      EI_Copy : constant Element_Access := EI;
+      declare
+         First       : constant Int := Int (Index_Type'First);
+         Last_As_Int : constant Int'Base := First + Int (Length) - 1;
+         Last        : constant Index_Type := Index_Type (Last_As_Int);
+         Elements    : Elements_Access :=
+                         new Elements_Type (Index_Type'First .. Last);
+      begin
+         for Indx in Elements'Range loop
+            begin
+               Elements (Indx) := new Element_Type'(New_Item);
+            exception
+               when others =>
+                  for J in Index_Type'First .. Index_Type'Pred (Indx) loop
+                     Free (Elements (J));
+                  end loop;
 
-      subtype TJ is Index_Type'Base range
-        Index_Type'First .. J.Container.Last;
+                  Free (Elements);
+                  raise;
+            end;
 
-      EJ : Element_Access renames
-        J.Container.Elements (TJ'(J.Index));
+         end loop;
 
-   begin
+         return (Controlled with Elements, Last, 0, 0);
+      end;
+   end To_Vector;
 
-      EI := EJ;
-      EJ := EI_Copy;
+   --------------------
+   -- Update_Element --
+   --------------------
 
-   end Swap;
+   procedure Update_Element
+     (Container : Vector;
+      Index     : Index_Type;
+      Process   : not null access procedure (Element : in out Element_Type))
+   is
+      subtype T is Index_Type'Base range
+        Index_Type'First .. Container.Last;
 
+      E : Element_Type renames Container.Elements (T'(Index)).all;
 
-   function Find (Container : Vector;
-                  Item      : Element_Type;
-                  Position  : Cursor := No_Element) return Cursor is
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+      L : Natural renames V.Lock;
 
    begin
+      B := B + 1;
+      L := L + 1;
 
-      if Position.Container /= null
-        and then Position.Container /=
-                   Vector_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
-      end if;
-
-      for I in Position.Index .. Container.Last loop
-         if Container.Elements (I) /= null
-           and then Container.Elements (I).all = Item
-         then
-            return (Container'Unchecked_Access, I);
-         end if;
-      end loop;
-
-      return No_Element;
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
 
-   end Find;
+      L := L - 1;
+      B := B - 1;
+   end Update_Element;
 
+   procedure Update_Element
+     (Position : Cursor;
+      Process  : not null access procedure (Element : in out Element_Type))
+   is
+   begin
+      Update_Element (Position.Container.all, Position.Index, Process);
+   end Update_Element;
 
-   function Reverse_Find (Container : Vector;
-                          Item      : Element_Type;
-                          Position  : Cursor := No_Element) return Cursor is
+   -----------
+   -- Write --
+   -----------
 
-      Last : Index_Type'Base;
+   procedure Write
+     (Stream    : access Root_Stream_Type'Class;
+      Container : Vector)
+   is
+      N : constant Count_Type := Length (Container);
 
    begin
+      Count_Type'Base'Write (Stream, N);
 
-      if Position.Container /= null
-        and then Position.Container /=
-                   Vector_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
-      end if;
-
-      if Position.Container = null
-        or else Position.Index > Container.Last
-      then
-         Last := Container.Last;
-      else
-         Last := Position.Index;
+      if N = 0 then
+         return;
       end if;
 
-      for I in reverse Index_Type'First .. Last loop
-         if Container.Elements (I) /= null
-           and then Container.Elements (I).all = Item
-         then
-            return (Container'Unchecked_Access, I);
-         end if;
-      end loop;
+      declare
+         E : Elements_Type renames Container.Elements.all;
 
-      return No_Element;
+      begin
+         for Indx in Index_Type'First .. Container.Last loop
 
-   end Reverse_Find;
+            --  There's another way to do this.  Instead a separate
+            --  Boolean for each element, you could write a Boolean
+            --  followed by a count of how many nulls or non-nulls
+            --  follow in the array.  Alternately you could use a
+            --  signed integer, and use the sign as the indicator
+            --  of null-ness.
 
+            if E (Indx) = null then
+               Boolean'Write (Stream, False);
+            else
+               Boolean'Write (Stream, True);
+               Element_Type'Output (Stream, E (Indx).all);
+            end if;
+         end loop;
+      end;
+   end Write;
 
 end Ada.Containers.Indefinite_Vectors;
-
index 6aa79a4fce4dff6e195b0d73d73784a1df1596e7..964247e9c65702a83abc9c7d5cef2114cae183d7 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                    ADA.CONTAINERS.INDEFINITE_VECTORS                     --
+--    A D A . C O N T A I N E R S . I N D E F I N I T E _ V E C T O R S     --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -204,7 +204,7 @@ pragma Preelaborate (Indefinite_Vectors);
 
    procedure Delete
      (Container : in out Vector;
-      Index     : Extended_Index;  --  TODO: verify
+      Index     : Extended_Index;
       Count     : Count_Type := 1);
 
    procedure Delete
@@ -238,7 +238,15 @@ pragma Preelaborate (Indefinite_Vectors);
 
    generic
       with function "<" (Left, Right : Element_Type) return Boolean is <>;
-   procedure Generic_Sort (Container : Vector);
+   package Generic_Sorting is
+
+      function Is_Sorted (Container : Vector) return Boolean;
+
+      procedure Sort (Container : in out Vector);
+
+      procedure Merge (Target, Source : in out Vector);
+
+   end Generic_Sorting;
 
    function Find_Index
      (Container : Vector;
@@ -307,6 +315,8 @@ private
    type Vector is new Controlled with record
       Elements : Elements_Access;
       Last     : Extended_Index := No_Index;
+      Busy     : Natural := 0;
+      Lock     : Natural := 0;
    end record;
 
    procedure Adjust (Container : in out Vector);
@@ -327,7 +337,7 @@ private
 
    for Vector'Read use Read;
 
-   Empty_Vector : constant Vector := Vector'(Controlled with null, No_Index);
+   Empty_Vector : constant Vector := (Controlled with null, No_Index, 0, 0);
 
    type Vector_Access is access constant Vector;
    for Vector_Access'Storage_Size use 0;
@@ -340,4 +350,3 @@ private
    No_Element : constant Cursor := Cursor'(null, Index_Type'First);
 
 end Ada.Containers.Indefinite_Vectors;
-
index c98c58a3b21896dd4057a4e3598c569487c0bd16..77d11243d1c9f8d5a1ec1bd0c0f3c3b4f39c0d31 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                          ADA.CONTAINERS.VECTORS                          --
+--                A D A . C O N T A I N E R S . V E C T O R S               --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -67,7 +67,7 @@ package body Ada.Containers.Vectors is
                          new Elements_Type'(RE);
 
          begin
-            return (Controlled with Elements, Right.Last);
+            return (Controlled with Elements, Right.Last, 0, 0);
          end;
       end if;
 
@@ -80,28 +80,35 @@ package body Ada.Containers.Vectors is
                          new Elements_Type'(LE);
 
          begin
-            return (Controlled with Elements, Left.Last);
+            return (Controlled with Elements, Left.Last, 0, 0);
          end;
 
       end if;
 
       declare
-         Last_As_Int : constant Int'Base :=
+         Last_As_Int : constant Int'Base :=  -- TODO: handle overflow
                          Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
 
-         Last : constant Index_Type := Index_Type (Last_As_Int);
+      begin
+         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
 
-         LE : Elements_Type renames
-                Left.Elements (Index_Type'First .. Left.Last);
+         declare
+            Last : constant Index_Type := Index_Type (Last_As_Int);
 
-         RE : Elements_Type renames
-                Right.Elements (Index_Type'First .. Right.Last);
+            LE : Elements_Type renames
+                   Left.Elements (Index_Type'First .. Left.Last);
 
-         Elements : constant Elements_Access :=
+            RE : Elements_Type renames
+                   Right.Elements (Index_Type'First .. Right.Last);
+
+            Elements : constant Elements_Access :=
                          new Elements_Type'(LE & RE);
 
-      begin
-         return (Controlled with Elements, Last);
+         begin
+            return (Controlled with Elements, Last, 0, 0);
+         end;
       end;
    end "&";
 
@@ -118,25 +125,32 @@ package body Ada.Containers.Vectors is
                          new Elements_Subtype'(others => Right);
 
          begin
-            return (Controlled with Elements, Index_Type'First);
+            return (Controlled with Elements, Index_Type'First, 0, 0);
          end;
       end if;
 
       declare
-         Last_As_Int : constant Int'Base :=
+         Last_As_Int : constant Int'Base :=  -- TODO: handle overflow
                          Int (Index_Type'First) + Int (LN);
 
-         Last : constant Index_Type := Index_Type (Last_As_Int);
+      begin
+         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
 
-         LE : Elements_Type renames
-                Left.Elements (Index_Type'First .. Left.Last);
+         declare
+            Last : constant Index_Type := Index_Type (Last_As_Int);
 
-         subtype ET is Elements_Type (Index_Type'First .. Last);
+            LE : Elements_Type renames
+                   Left.Elements (Index_Type'First .. Left.Last);
 
-         Elements : constant Elements_Access := new ET'(LE & Right);
+            subtype ET is Elements_Type (Index_Type'First .. Last);
 
-      begin
-         return (Controlled with Elements, Last);
+            Elements : constant Elements_Access := new ET'(LE & Right);
+
+         begin
+            return (Controlled with Elements, Last, 0, 0);
+         end;
       end;
    end "&";
 
@@ -153,38 +167,51 @@ package body Ada.Containers.Vectors is
                          new Elements_Subtype'(others => Left);
 
          begin
-            return (Controlled with Elements, Index_Type'First);
+            return (Controlled with Elements, Index_Type'First, 0, 0);
          end;
       end if;
 
       declare
-         Last_As_Int : constant Int'Base :=
+         Last_As_Int : constant Int'Base :=  -- TODO: handle overflow
                          Int (Index_Type'First) + Int (RN);
 
-         Last : constant Index_Type := Index_Type (Last_As_Int);
+      begin
+         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
 
-         RE : Elements_Type renames
-                Right.Elements (Index_Type'First .. Right.Last);
+         declare
+            Last : constant Index_Type := Index_Type (Last_As_Int);
 
-         subtype ET is Elements_Type (Index_Type'First .. Last);
+            RE : Elements_Type renames
+                   Right.Elements (Index_Type'First .. Right.Last);
 
-         Elements : constant Elements_Access := new ET'(Left & RE);
+            subtype ET is Elements_Type (Index_Type'First .. Last);
 
-      begin
-         return (Controlled with Elements, Last);
+            Elements : constant Elements_Access := new ET'(Left & RE);
+
+         begin
+            return (Controlled with Elements, Last, 0, 0);
+         end;
       end;
    end "&";
 
    function "&" (Left, Right  : Element_Type) return Vector is
-      subtype IT is Index_Type'Base range
-        Index_Type'First .. Index_Type'Succ (Index_Type'First);
+   begin
+      if Index_Type'First >= Index_Type'Last then
+         raise Constraint_Error;
+      end if;
 
-      subtype ET is Elements_Type (IT);
+      declare
+         Last : constant Index_Type := Index_Type'First + 1;
 
-      Elements : constant Elements_Access := new ET'(Left, Right);
+         subtype ET is Elements_Type (Index_Type'First .. Last);
 
-   begin
-      return Vector'(Controlled with Elements, Elements'Last);
+         Elements : constant Elements_Access := new ET'(Left, Right);
+
+      begin
+         return (Controlled with Elements, Last, 0, 0);
+      end;
    end "&";
 
    ---------
@@ -216,25 +243,21 @@ package body Ada.Containers.Vectors is
 
    procedure Adjust (Container : in out Vector) is
    begin
-      if Container.Elements = null then
-         return;
-      end if;
-
-      if Container.Elements'Length = 0
-        or else Container.Last < Index_Type'First
-      then
+      if Container.Last = No_Index then
          Container.Elements := null;
          return;
       end if;
 
       declare
-         X : constant Elements_Access := Container.Elements;
-         L : constant Index_Type'Base := Container.Last;
-         E : Elements_Type renames X (Index_Type'First .. L);
+         E : constant Elements_Access := Container.Elements;
+         L : constant Index_Type := Container.Last;
+
       begin
          Container.Elements := null;
-         Container.Last := Index_Type'Pred (Index_Type'First);
-         Container.Elements := new Elements_Type'(E);
+         Container.Last := No_Index;
+         Container.Busy := 0;
+         Container.Lock := 0;
+         Container.Elements := new Elements_Type'(E (Index_Type'First .. L));
          Container.Last := L;
       end;
    end Adjust;
@@ -249,9 +272,13 @@ package body Ada.Containers.Vectors is
          return;
       end if;
 
+      if Container.Last = Index_Type'Last then
+         raise Constraint_Error;
+      end if;
+
       Insert
         (Container,
-         Index_Type'Succ (Container.Last),
+         Container.Last + 1,
          New_Item);
    end Append;
 
@@ -265,9 +292,13 @@ package body Ada.Containers.Vectors is
          return;
       end if;
 
+      if Container.Last = Index_Type'Last then
+         raise Constraint_Error;
+      end if;
+
       Insert
         (Container,
-         Index_Type'Succ (Container.Last),
+         Container.Last + 1,
          New_Item,
          Count);
    end Append;
@@ -322,7 +353,11 @@ package body Ada.Containers.Vectors is
 
    procedure Clear (Container : in out Vector) is
    begin
-      Container.Last := Index_Type'Pred (Index_Type'First);
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      Container.Last := No_Index;
    end Clear;
 
    --------------
@@ -347,39 +382,54 @@ package body Ada.Containers.Vectors is
       Count     : Count_Type := 1)
    is
    begin
-      if Count = 0 then
-         return;
+      if Index < Index_Type'First then
+         raise Constraint_Error;
       end if;
 
-      declare
-         subtype I_Subtype is Index_Type'Base range
-           Index_Type'First .. Container.Last;
+      if Index > Container.Last then
+         if Index > Container.Last + 1 then
+            raise Constraint_Error;
+         end if;
 
-         I : constant I_Subtype := Index;
-         --  TODO: not sure whether to relax this check ???
+         return;
+      end if;
 
-         I_As_Int : constant Int := Int (I);
+      if Count = 0 then
+         return;
+      end if;
 
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      declare
+         I_As_Int        : constant Int := Int (Index);
          Old_Last_As_Int : constant Int := Index_Type'Pos (Container.Last);
 
          Count1 : constant Int'Base := Count_Type'Pos (Count);
          Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
-
-         N : constant Int'Base := Int'Min (Count1, Count2);
+         N      : constant Int'Base := Int'Min (Count1, Count2);
 
          J_As_Int : constant Int'Base := I_As_Int + N;
-         J        : constant Index_Type'Base := Index_Type'Base (J_As_Int);
 
-         E : Elements_Type renames Container.Elements.all;
+      begin
+         if J_As_Int > Old_Last_As_Int then
+            Container.Last := Index - 1;
 
-         New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
+         else
+            declare
+               J : constant Index_Type := Index_Type (J_As_Int);
+               E : Elements_Type renames Container.Elements.all;
 
-         New_Last : constant Extended_Index :=
-                      Extended_Index (New_Last_As_Int);
+               New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
+               New_Last        : constant Index_Type :=
+                                   Index_Type (New_Last_As_Int);
 
-      begin
-         E (I .. New_Last) := E (J .. Container.Last);
-         Container.Last := New_Last;
+            begin
+               E (Index .. New_Last) := E (J .. Container.Last);
+               Container.Last := New_Last;
+            end;
+         end if;
       end;
    end Delete;
 
@@ -389,19 +439,15 @@ package body Ada.Containers.Vectors is
       Count     : Count_Type := 1)
    is
    begin
-
-      if Position.Container /= null
-        and then Position.Container /=
-                   Vector_Access'(Container'Unchecked_Access)
-      then
-         raise Program_Error;
+      if Position.Container = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container = null
+      if Position.Container /=
+           Vector_Access'(Container'Unchecked_Access)
         or else Position.Index > Container.Last
       then
-         Position := No_Element;
-         return;
+         raise Program_Error;
       end if;
 
       Delete (Container, Position.Index, Count);
@@ -449,14 +495,17 @@ package body Ada.Containers.Vectors is
          return;
       end if;
 
-      if Count >= Length (Container) then
-         Clear (Container);
-         return;
+      if Container.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      Index := Int'Base (Container.Last) - Int'Base (Count) + 1;
+      Index := Int'Base (Container.Last) - Int'Base (Count);
 
-      Delete (Container, Index_Type'Base (Index), Count);
+      if Index < Index_Type'Pos (Index_Type'First) then
+         Container.Last := No_Index;
+      else
+         Container.Last := Index_Type (Index);
+      end if;
    end Delete_Last;
 
    -------------
@@ -467,14 +516,20 @@ package body Ada.Containers.Vectors is
      (Container : Vector;
       Index     : Index_Type) return Element_Type
    is
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
    begin
-      return Container.Elements (T'(Index));
+      if Index > Container.Last then
+         raise Constraint_Error;
+      end if;
+
+      return Container.Elements (Index);
    end Element;
 
    function Element (Position : Cursor) return Element_Type is
    begin
+      if Position.Container = null then
+         raise Constraint_Error;
+      end if;
+
       return Element (Position.Container.all, Position.Index);
    end Element;
 
@@ -485,8 +540,12 @@ package body Ada.Containers.Vectors is
    procedure Finalize (Container : in out Vector) is
       X : Elements_Access := Container.Elements;
    begin
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       Container.Elements := null;
-      Container.Last := Index_Type'Pred (Index_Type'First);
+      Container.Last := No_Index;
       Free (X);
    end Finalize;
 
@@ -501,8 +560,9 @@ package body Ada.Containers.Vectors is
 
    begin
       if Position.Container /= null
-        and then Position.Container /=
-                   Vector_Access'(Container'Unchecked_Access)
+        and then (Position.Container /=
+                    Vector_Access'(Container'Unchecked_Access)
+                  or else Position.Index > Container.Last)
       then
          raise Program_Error;
       end if;
@@ -566,26 +626,112 @@ package body Ada.Containers.Vectors is
       return Index_Type'First;
    end First_Index;
 
-   ------------------
-   -- Generic_Sort --
-   ------------------
+   ---------------------
+   -- Generic_Sorting --
+   ---------------------
 
-   procedure Generic_Sort (Container : Vector)
-   is
-      procedure Sort is
-         new Generic_Array_Sort
-          (Index_Type   => Index_Type,
-           Element_Type => Element_Type,
-           Array_Type   => Elements_Type,
-           "<"          => "<");
+   package body Generic_Sorting is
 
-   begin
-      if Container.Elements = null then
-         return;
-      end if;
+      ---------------
+      -- Is_Sorted --
+      ---------------
+
+      function Is_Sorted (Container : Vector) return Boolean is
+      begin
+         if Container.Last <= Index_Type'First then
+            return True;
+         end if;
+
+         declare
+            E : Elements_Type renames Container.Elements.all;
+         begin
+            for I in Index_Type'First .. Container.Last - 1 loop
+               if E (I + 1) < E (I) then
+                  return False;
+               end if;
+            end loop;
+         end;
+
+         return True;
+      end Is_Sorted;
+
+      -----------
+      -- Merge --
+      -----------
 
-      Sort (Container.Elements (Index_Type'First .. Container.Last));
-   end Generic_Sort;
+      procedure Merge (Target, Source : in out Vector) is
+         I : Index_Type'Base := Target.Last;
+         J : Index_Type'Base;
+
+      begin
+         if Target.Last < Index_Type'First then
+            Move (Target => Target, Source => Source);
+            return;
+         end if;
+
+         if Target'Address = Source'Address then
+            return;
+         end if;
+
+         if Source.Last < Index_Type'First then
+            return;
+         end if;
+
+         if Source.Busy > 0 then
+            raise Program_Error;
+         end if;
+
+         Target.Set_Length (Length (Target) + Length (Source));
+
+         J := Target.Last;
+         while Source.Last >= Index_Type'First loop
+            if I < Index_Type'First then
+               Target.Elements (Index_Type'First .. J) :=
+                 Source.Elements (Index_Type'First .. Source.Last);
+
+               Source.Last := No_Index;
+               return;
+            end if;
+
+            if Source.Elements (Source.Last) < Target.Elements (I) then
+               Target.Elements (J) := Target.Elements (I);
+               I := I - 1;
+
+            else
+               Target.Elements (J) := Source.Elements (Source.Last);
+               Source.Last := Source.Last - 1;
+            end if;
+
+            J := J - 1;
+         end loop;
+      end Merge;
+
+      ----------
+      -- Sort --
+      ----------
+
+      procedure Sort (Container : in out Vector)
+      is
+         procedure Sort is
+            new Generic_Array_Sort
+             (Index_Type   => Index_Type,
+              Element_Type => Element_Type,
+              Array_Type   => Elements_Type,
+              "<"          => "<");
+
+      begin
+         if Container.Last <= Index_Type'First then
+            return;
+         end if;
+
+         if Container.Lock > 0 then
+            raise Program_Error;
+         end if;
+
+         Sort (Container.Elements (Index_Type'First .. Container.Last));
+      end Sort;
+
+   end Generic_Sorting;
 
    -----------------
    -- Has_Element --
@@ -610,40 +756,47 @@ package body Ada.Containers.Vectors is
       New_Item  : Element_Type;
       Count     : Count_Type := 1)
    is
-      Old_Last : constant Extended_Index := Container.Last;
-
-      Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
-
       N : constant Int := Count_Type'Pos (Count);
 
-      New_Last_As_Int : constant Int'Base := Old_Last_As_Int + N;
+      New_Last_As_Int : Int'Base;
+      New_Last        : Index_Type;
 
-      New_Last : constant Extended_Index := Extended_Index (New_Last_As_Int);
+      Dst : Elements_Access;
 
-      Index : Index_Type;
+   begin
+      if Before < Index_Type'First then
+         raise Constraint_Error;
+      end if;
 
-      Dst_Last : Index_Type;
-      Dst      : Elements_Access;
+      if Before > Container.Last
+        and then Before > Container.Last + 1
+      then
+         raise Constraint_Error;
+      end if;
 
-   begin
       if Count = 0 then
          return;
       end if;
 
       declare
-         subtype Before_Subtype is Index_Type'Base range
-           Index_Type'First .. Index_Type'Succ (Container.Last);
+         Old_Last : constant Extended_Index := Container.Last;
 
-         Old_First : constant Before_Subtype := Before;
+         Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
 
-         Old_First_As_Int : constant Int := Index_Type'Pos (Old_First);
+      begin
+         New_Last_As_Int := Old_Last_As_Int + N;
 
-         New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
+         if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
 
-      begin
-         Index := Index_Type (New_First_As_Int);
+         New_Last := Index_Type (New_Last_As_Int);
       end;
 
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       if Container.Elements = null then
          declare
             subtype Elements_Subtype is
@@ -660,8 +813,23 @@ package body Ada.Containers.Vectors is
          declare
             E : Elements_Type renames Container.Elements.all;
          begin
-            E (Index .. New_Last) := E (Before .. Container.Last);
-            E (Before .. Index_Type'Pred (Index)) := (others => New_Item);
+            if Before <= Container.Last then
+               declare
+                  Index_As_Int : constant Int'Base :=
+                                   Index_Type'Pos (Before) + N;
+
+                  Index : constant Index_Type := Index_Type (Index_As_Int);
+
+               begin
+                  E (Index .. New_Last) := E (Before .. Container.Last);
+
+                  E (Before .. Index_Type'Pred (Index)) :=
+                      (others => New_Item);
+               end;
+
+            else
+               E (Before .. New_Last) := (others => New_Item);
+            end if;
          end;
 
          Container.Last := New_Last;
@@ -669,35 +837,40 @@ package body Ada.Containers.Vectors is
       end if;
 
       declare
-         First : constant Int := Int (Index_Type'First);
-
+         First    : constant Int := Int (Index_Type'First);
          New_Size : constant Int'Base := New_Last_As_Int - First + 1;
-         Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
-
-         Size, Dst_Last_As_Int : Int'Base;
+         Size     : Int'Base := Int'Max (1, Container.Elements'Length);
 
       begin
-         if New_Size >= Max_Size / 2 then
-            Dst_Last := Index_Type'Last;
+         while Size < New_Size loop
+            if Size > Int'Last / 2 then
+               Size := Int'Last;
+               exit;
+            end if;
 
-         else
-            Size := Container.Elements'Length;
+            Size := 2 * Size;
+         end loop;
 
-            if Size = 0 then
-               Size := 1;
-            end if;
+         --  TODO: The following calculations aren't quite right, since
+         --  there will be overflow if Index_Type'Range is very large
+         --  (e.g. this package is instantiated with a 64-bit integer).
+         --  END TODO.
 
-            while Size < New_Size loop
-               Size := 2 * Size;
-            end loop;
+         declare
+            Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
+         begin
+            if Size > Max_Size then
+               Size := Max_Size;
+            end if;
+         end;
 
-            Dst_Last_As_Int := First + Size - 1;
-            Dst_Last := Index_Type (Dst_Last_As_Int);
-         end if;
+         declare
+            Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
+         begin
+            Dst := new Elements_Type (Index_Type'First .. Dst_Last);
+         end;
       end;
 
-      Dst := new Elements_Type (Index_Type'First .. Dst_Last);
-
       declare
          Src : Elements_Type renames Container.Elements.all;
 
@@ -705,12 +878,21 @@ package body Ada.Containers.Vectors is
          Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
            Src (Index_Type'First .. Index_Type'Pred (Before));
 
-         Dst (Before .. Index_Type'Pred (Index)) :=
-           (others => New_Item);
+         if Before <= Container.Last then
+            declare
+               Index_As_Int : constant Int'Base :=
+                                Index_Type'Pos (Before) + N;
 
-         Dst (Index .. New_Last) :=
-           Src (Before .. Container.Last);
+               Index : constant Index_Type := Index_Type (Index_As_Int);
 
+            begin
+               Dst (Before .. Index_Type'Pred (Index)) := (others => New_Item);
+               Dst (Index .. New_Last) := Src (Before .. Container.Last);
+            end;
+
+         else
+            Dst (Before .. New_Last) := (others => New_Item);
+         end if;
       exception
          when others =>
             Free (Dst);
@@ -734,6 +916,16 @@ package body Ada.Containers.Vectors is
       N : constant Count_Type := Length (New_Item);
 
    begin
+      if Before < Index_Type'First then
+         raise Constraint_Error;
+      end if;
+
+      if Before > Container.Last
+        and then Before > Container.Last + 1
+      then
+         raise Constraint_Error;
+      end if;
+
       if N = 0 then
          return;
       end if;
@@ -747,51 +939,56 @@ package body Ada.Containers.Vectors is
          Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
 
       begin
-         if Container'Address = New_Item'Address then
-            declare
-               subtype Src_Index_Subtype is Index_Type'Base range
-                 Index_Type'First .. Index_Type'Pred (Before);
+         if Container'Address /= New_Item'Address then
+            Container.Elements (Before .. Dst_Last) :=
+              New_Item.Elements (Index_Type'First .. New_Item.Last);
 
-               Src : Elements_Type renames
-                       Container.Elements (Src_Index_Subtype);
+            return;
+         end if;
 
-               Index_As_Int : constant Int'Base :=
-                                Int (Before) + Src'Length - 1;
+         declare
+            subtype Src_Index_Subtype is Index_Type'Base range
+              Index_Type'First .. Before - 1;
 
-               Index : constant Index_Type'Base :=
-                         Index_Type'Base (Index_As_Int);
+            Src : Elements_Type renames
+                    Container.Elements (Src_Index_Subtype);
 
-               Dst : Elements_Type renames
-                       Container.Elements (Before .. Index);
+            Index_As_Int : constant Int'Base :=
+                             Int (Before) + Src'Length - 1;
 
-            begin
-               Dst := Src;
-            end;
+            Index : constant Index_Type'Base :=
+                      Index_Type'Base (Index_As_Int);
 
-            declare
-               subtype Src_Index_Subtype is Index_Type'Base range
-                 Index_Type'Succ (Dst_Last) .. Container.Last;
+            Dst : Elements_Type renames
+                    Container.Elements (Before .. Index);
 
-               Src : Elements_Type renames
-                       Container.Elements (Src_Index_Subtype);
+         begin
+            Dst := Src;
+         end;
 
-               Index_As_Int : constant Int'Base :=
-                                Dst_Last_As_Int - Src'Length + 1;
+         if Dst_Last = Container.Last then
+            return;
+         end if;
 
-               Index : constant Index_Type'Base :=
-                         Index_Type'Base (Index_As_Int);
+         declare
+            subtype Src_Index_Subtype is Index_Type'Base range
+              Dst_Last + 1 .. Container.Last;
 
-               Dst : Elements_Type renames
-                       Container.Elements (Index .. Dst_Last);
+            Src : Elements_Type renames
+                    Container.Elements (Src_Index_Subtype);
 
-            begin
-               Dst := Src;
-            end;
+            Index_As_Int : constant Int'Base :=
+                             Dst_Last_As_Int - Src'Length + 1;
 
-         else
-            Container.Elements (Before .. Dst_Last) :=
-              New_Item.Elements (Index_Type'First .. New_Item.Last);
-         end if;
+            Index : constant Index_Type :=
+                      Index_Type (Index_As_Int);
+
+            Dst : Elements_Type renames
+                    Container.Elements (Index .. Dst_Last);
+
+         begin
+            Dst := Src;
+         end;
       end;
    end Insert;
 
@@ -816,7 +1013,12 @@ package body Ada.Containers.Vectors is
       if Before.Container = null
         or else Before.Index > Container.Last
       then
-         Index := Index_Type'Succ (Container.Last);
+         if Container.Last = Index_Type'Last then
+            raise Constraint_Error;
+         end if;
+
+         Index := Container.Last + 1;
+
       else
          Index := Before.Index;
       end if;
@@ -854,7 +1056,12 @@ package body Ada.Containers.Vectors is
       if Before.Container = null
         or else Before.Index > Container.Last
       then
-         Index := Index_Type'Succ (Container.Last);
+         if Container.Last = Index_Type'Last then
+            raise Constraint_Error;
+         end if;
+
+         Index := Container.Last + 1;
+
       else
          Index := Before.Index;
       end if;
@@ -886,7 +1093,12 @@ package body Ada.Containers.Vectors is
       if Before.Container = null
         or else Before.Index > Container.Last
       then
-         Index := Index_Type'Succ (Container.Last);
+         if Container.Last = Index_Type'Last then
+            raise Constraint_Error;
+         end if;
+
+         Index := Container.Last + 1;
+
       else
          Index := Before.Index;
       end if;
@@ -925,7 +1137,12 @@ package body Ada.Containers.Vectors is
       if Before.Container = null
         or else Before.Index > Container.Last
       then
-         Index := Index_Type'Succ (Container.Last);
+         if Container.Last = Index_Type'Last then
+            raise Constraint_Error;
+         end if;
+
+         Index := Container.Last + 1;
+
       else
          Index := Before.Index;
       end if;
@@ -944,40 +1161,47 @@ package body Ada.Containers.Vectors is
       Before    : Extended_Index;
       Count     : Count_Type := 1)
    is
-      Old_Last : constant Extended_Index := Container.Last;
-
-      Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
-
       N : constant Int := Count_Type'Pos (Count);
 
-      New_Last_As_Int : constant Int'Base := Old_Last_As_Int + N;
+      New_Last_As_Int : Int'Base;
+      New_Last        : Index_Type;
 
-      New_Last : constant Extended_Index := Extended_Index (New_Last_As_Int);
+      Dst : Elements_Access;
 
-      Index : Index_Type;
+   begin
+      if Before < Index_Type'First then
+         raise Constraint_Error;
+      end if;
 
-      Dst_Last : Index_Type;
-      Dst      : Elements_Access;
+      if Before > Container.Last
+        and then Before > Container.Last + 1
+      then
+         raise Constraint_Error;
+      end if;
 
-   begin
       if Count = 0 then
          return;
       end if;
 
       declare
-         subtype Before_Subtype is Index_Type'Base range
-           Index_Type'First .. Index_Type'Succ (Container.Last);
+         Old_Last : constant Extended_Index := Container.Last;
 
-         Old_First : constant Before_Subtype := Before;
+         Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
 
-         Old_First_As_Int : constant Int := Index_Type'Pos (Old_First);
+      begin
+         New_Last_As_Int := Old_Last_As_Int + N;
 
-         New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
+         if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
 
-      begin
-         Index := Index_Type (New_First_As_Int);
+         New_Last := Index_Type (New_Last_As_Int);
       end;
 
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       if Container.Elements = null then
          Container.Elements :=
            new Elements_Type (Index_Type'First .. New_Last);
@@ -990,7 +1214,17 @@ package body Ada.Containers.Vectors is
          declare
             E : Elements_Type renames Container.Elements.all;
          begin
-            E (Index .. New_Last) := E (Before .. Container.Last);
+            if Before <= Container.Last then
+               declare
+                  Index_As_Int : constant Int'Base :=
+                                   Index_Type'Pos (Before) + N;
+
+                  Index : constant Index_Type := Index_Type (Index_As_Int);
+
+               begin
+                  E (Index .. New_Last) := E (Before .. Container.Last);
+               end;
+            end if;
          end;
 
          Container.Last := New_Last;
@@ -998,35 +1232,40 @@ package body Ada.Containers.Vectors is
       end if;
 
       declare
-         First : constant Int := Int (Index_Type'First);
-
+         First    : constant Int := Int (Index_Type'First);
          New_Size : constant Int'Base := New_Last_As_Int - First + 1;
-         Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
-
-         Size, Dst_Last_As_Int : Int'Base;
+         Size     : Int'Base := Int'Max (1, Container.Elements'Length);
 
       begin
-         if New_Size >= Max_Size / 2 then
-            Dst_Last := Index_Type'Last;
+         while Size < New_Size loop
+            if Size > Int'Last / 2 then
+               Size := Int'Last;
+               exit;
+            end if;
 
-         else
-            Size := Container.Elements'Length;
+            Size := 2 * Size;
+         end loop;
 
-            if Size = 0 then
-               Size := 1;
-            end if;
+         --  TODO: The following calculations aren't quite right, since
+         --  there will be overflow if Index_Type'Range is very large
+         --  (e.g. this package is instantiated with a 64-bit integer).
+         --  END TODO.
 
-            while Size < New_Size loop
-               Size := 2 * Size;
-            end loop;
+         declare
+            Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
+         begin
+            if Size > Max_Size then
+               Size := Max_Size;
+            end if;
+         end;
 
-            Dst_Last_As_Int := First + Size - 1;
-            Dst_Last := Index_Type (Dst_Last_As_Int);
-         end if;
+         declare
+            Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
+         begin
+            Dst := new Elements_Type (Index_Type'First .. Dst_Last);
+         end;
       end;
 
-      Dst := new Elements_Type (Index_Type'First .. Dst_Last);
-
       declare
          Src : Elements_Type renames Container.Elements.all;
 
@@ -1034,9 +1273,17 @@ package body Ada.Containers.Vectors is
          Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
            Src (Index_Type'First .. Index_Type'Pred (Before));
 
-         Dst (Index .. New_Last) :=
-           Src (Before .. Container.Last);
+         if Before <= Container.Last then
+            declare
+               Index_As_Int : constant Int'Base :=
+                                Index_Type'Pos (Before) + N;
 
+               Index : constant Index_Type := Index_Type (Index_As_Int);
+
+            begin
+               Dst (Index .. New_Last) := Src (Before .. Container.Last);
+            end;
+         end if;
       exception
          when others =>
             Free (Dst);
@@ -1048,7 +1295,6 @@ package body Ada.Containers.Vectors is
       begin
          Container.Elements := Dst;
          Container.Last := New_Last;
-
          Free (X);
       end;
    end Insert_Space;
@@ -1083,7 +1329,12 @@ package body Ada.Containers.Vectors is
       if Before.Container = null
         or else Before.Index > Container.Last
       then
-         Index := Index_Type'Succ (Container.Last);
+         if Container.Last = Index_Type'Last then
+            raise Constraint_Error;
+         end if;
+
+         Index := Container.Last + 1;
+
       else
          Index := Before.Index;
       end if;
@@ -1110,10 +1361,25 @@ package body Ada.Containers.Vectors is
      (Container : Vector;
       Process   : not null access procedure (Position : Cursor))
    is
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+
    begin
-      for Indx in Index_Type'First .. Container.Last loop
-         Process (Cursor'(Container'Unchecked_Access, Indx));
-      end loop;
+
+      B := B + 1;
+
+      begin
+         for Indx in Index_Type'First .. Container.Last loop
+            Process (Cursor'(Container'Unchecked_Access, Indx));
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
+
    end Iterate;
 
    ----------
@@ -1155,7 +1421,12 @@ package body Ada.Containers.Vectors is
       L : constant Int := Int (Container.Last);
       F : constant Int := Int (Index_Type'First);
       N : constant Int'Base := L - F + 1;
+
    begin
+      if N > Count_Type'Pos (Count_Type'Last) then
+         raise Constraint_Error;
+      end if;
+
       return Count_Type (N);
    end Length;
 
@@ -1167,25 +1438,28 @@ package body Ada.Containers.Vectors is
      (Target : in out Vector;
       Source : in out Vector)
    is
-      X : Elements_Access := Target.Elements;
-
    begin
       if Target'Address = Source'Address then
          return;
       end if;
 
-      if Target.Last >= Index_Type'First then
-         raise Constraint_Error;
+      if Target.Busy > 0 then
+         raise Program_Error;
       end if;
 
-      Target.Elements := null;
-      Free (X);
+      if Source.Busy > 0 then
+         raise Program_Error;
+      end if;
 
-      Target.Elements := Source.Elements;
-      Target.Last := Source.Last;
+      declare
+         Target_Elements : constant Elements_Access := Target.Elements;
+      begin
+         Target.Elements := Source.Elements;
+         Source.Elements := Target_Elements;
+      end;
 
-      Source.Elements := null;
-      Source.Last := Index_Type'Pred (Index_Type'First);
+      Target.Last := Source.Last;
+      Source.Last := No_Index;
    end Move;
 
    ----------
@@ -1199,7 +1473,7 @@ package body Ada.Containers.Vectors is
       end if;
 
       if Position.Index < Position.Container.Last then
-         return (Position.Container, Index_Type'Succ (Position.Index));
+         return (Position.Container, Position.Index + 1);
       end if;
 
       return No_Element;
@@ -1216,7 +1490,7 @@ package body Ada.Containers.Vectors is
       end if;
 
       if Position.Index < Position.Container.Last then
-         Position.Index := Index_Type'Succ (Position.Index);
+         Position.Index := Position.Index + 1;
       else
          Position := No_Element;
       end if;
@@ -1254,7 +1528,7 @@ package body Ada.Containers.Vectors is
       end if;
 
       if Position.Index > Index_Type'First then
-         Position.Index := Index_Type'Pred (Position.Index);
+         Position.Index := Position.Index - 1;
       else
          Position := No_Element;
       end if;
@@ -1267,7 +1541,7 @@ package body Ada.Containers.Vectors is
       end if;
 
       if Position.Index > Index_Type'First then
-         return (Position.Container, Index_Type'Pred (Position.Index));
+         return (Position.Container, Position.Index - 1);
       end if;
 
       return No_Element;
@@ -1282,23 +1556,41 @@ package body Ada.Containers.Vectors is
       Index     : Index_Type;
       Process   : not null access procedure (Element : Element_Type))
    is
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+      L : Natural renames V.Lock;
+
    begin
-      Process (Container.Elements (T'(Index)));
+      if Index > Container.Last then
+         raise Constraint_Error;
+      end if;
+
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (V.Elements (Index));
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    procedure Query_Element
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type))
    is
-      Container : Vector renames Position.Container.all;
-
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
-
    begin
-      Process (Container.Elements (T'(Position.Index)));
+      if Position.Container = null then
+         raise Constraint_Error;
+      end if;
+
+      Query_Element (Position.Container.all, Position.Index, Process);
    end Query_Element;
 
    ----------
@@ -1310,7 +1602,7 @@ package body Ada.Containers.Vectors is
       Container : out Vector)
    is
       Length : Count_Type'Base;
-      Last   : Index_Type'Base := Index_Type'Pred (Index_Type'First);
+      Last   : Index_Type'Base := No_Index;
 
    begin
       Clear (Container);
@@ -1322,7 +1614,7 @@ package body Ada.Containers.Vectors is
       end if;
 
       for J in Count_Type range 1 .. Length loop
-         Last := Index_Type'Succ (Last);
+         Last := Last + 1;
          Element_Type'Read (Stream, Container.Elements (Last));
          Container.Last := Last;
       end loop;
@@ -1337,17 +1629,25 @@ package body Ada.Containers.Vectors is
       Index     : Index_Type;
       By        : Element_Type)
    is
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
    begin
-      Container.Elements (T'(Index)) := By;
+      if Index > Container.Last then
+         raise Constraint_Error;
+      end if;
+
+      if Container.Lock > 0 then
+         raise Program_Error;
+      end if;
+
+      Container.Elements (Index) := By;
    end Replace_Element;
 
    procedure Replace_Element (Position : Cursor; By : Element_Type) is
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Position.Container.Last;
    begin
-      Position.Container.Elements (T'(Position.Index)) := By;
+      if Position.Container = null then
+         raise Constraint_Error;
+      end if;
+
+      Replace_Element (Position.Container.all, Position.Index, By);
    end Replace_Element;
 
    ----------------------
@@ -1371,6 +1671,10 @@ package body Ada.Containers.Vectors is
             end;
 
          elsif N < Container.Elements'Length then
+            if Container.Busy > 0 then
+               raise Program_Error;
+            end if;
+
             declare
                subtype Array_Index_Subtype is Index_Type'Base range
                  Index_Type'First .. Container.Last;
@@ -1397,13 +1701,19 @@ package body Ada.Containers.Vectors is
             Last_As_Int : constant Int'Base :=
                             Int (Index_Type'First) + Int (Capacity) - 1;
 
-            Last : constant Index_Type := Index_Type (Last_As_Int);
+         begin
+            if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+               raise Constraint_Error;
+            end if;
 
-            subtype Array_Subtype is
-              Elements_Type (Index_Type'First .. Last);
+            declare
+               Last : constant Index_Type := Index_Type (Last_As_Int);
 
-         begin
-            Container.Elements := new Array_Subtype;
+               subtype Array_Subtype is
+                 Elements_Type (Index_Type'First .. Last);
+            begin
+               Container.Elements := new Array_Subtype;
+            end;
          end;
 
          return;
@@ -1411,6 +1721,10 @@ package body Ada.Containers.Vectors is
 
       if Capacity <= N then
          if N < Container.Elements'Length then
+            if Container.Busy > 0 then
+               raise Program_Error;
+            end if;
+
             declare
                subtype Array_Index_Subtype is Index_Type'Base range
                  Index_Type'First .. Container.Last;
@@ -1437,39 +1751,50 @@ package body Ada.Containers.Vectors is
          return;
       end if;
 
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       declare
          Last_As_Int : constant Int'Base :=
                          Int (Index_Type'First) + Int (Capacity) - 1;
 
-         Last : constant Index_Type := Index_Type (Last_As_Int);
-
-         subtype Array_Subtype is
-           Elements_Type (Index_Type'First .. Last);
-
-         E : Elements_Access := new Array_Subtype;
-
       begin
+         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
+
          declare
-            Src : Elements_Type renames
-                    Container.Elements (Index_Type'First .. Container.Last);
+            Last : constant Index_Type := Index_Type (Last_As_Int);
+
+            subtype Array_Subtype is
+              Elements_Type (Index_Type'First .. Last);
 
-            Tgt : Elements_Type renames
-                    E (Index_Type'First .. Container.Last);
+            E : Elements_Access := new Array_Subtype;
 
          begin
-            Tgt := Src;
+            declare
+               Src : Elements_Type renames
+                       Container.Elements (Index_Type'First .. Container.Last);
 
-         exception
-            when others =>
-               Free (E);
-               raise;
-         end;
+               Tgt : Elements_Type renames
+                       E (Index_Type'First .. Container.Last);
 
-         declare
-            X : Elements_Access := Container.Elements;
-         begin
-            Container.Elements := E;
-            Free (X);
+            begin
+               Tgt := Src;
+
+            exception
+               when others =>
+                  Free (E);
+                  raise;
+            end;
+
+            declare
+               X : Elements_Access := Container.Elements;
+            begin
+               Container.Elements := E;
+               Free (X);
+            end;
          end;
       end;
    end Reserve_Capacity;
@@ -1545,10 +1870,25 @@ package body Ada.Containers.Vectors is
      (Container : Vector;
       Process   : not null access procedure (Position : Cursor))
    is
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+
    begin
-      for Indx in reverse Index_Type'First .. Container.Last loop
-         Process (Cursor'(Container'Unchecked_Access, Indx));
-      end loop;
+
+      B := B + 1;
+
+      begin
+         for Indx in reverse Index_Type'First .. Container.Last loop
+            Process (Cursor'(Container'Unchecked_Access, Indx));
+         end loop;
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
+
    end Reverse_Iterate;
 
    ----------------
@@ -1557,23 +1897,23 @@ package body Ada.Containers.Vectors is
 
    procedure Set_Length (Container : in out Vector; Length : Count_Type) is
    begin
-      if Length = 0 then
-         Clear (Container);
+      if Length = Vectors.Length (Container) then
          return;
       end if;
 
+      if Container.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      if Length > Capacity (Container) then
+         Reserve_Capacity (Container, Capacity => Length);
+      end if;
+
       declare
          Last_As_Int : constant Int'Base :=
                          Int (Index_Type'First) + Int (Length) - 1;
-
-         Last        : constant Index_Type := Index_Type (Last_As_Int);
-
       begin
-         if Length > Capacity (Container) then
-            Reserve_Capacity (Container, Capacity => Length);
-         end if;
-
-         Container.Last := Last;
+         Container.Last := Index_Type'Base (Last_As_Int);
       end;
    end Set_Length;
 
@@ -1581,44 +1921,47 @@ package body Ada.Containers.Vectors is
    -- Swap --
    ----------
 
-   procedure Swap
-     (Container : Vector;
-      I, J      : Index_Type)
-   is
+   procedure Swap (Container : Vector; I, J : Index_Type) is
+   begin
+      if I > Container.Last
+        or else J > Container.Last
+      then
+         raise Constraint_Error;
+      end if;
 
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
+      if I = J then
+         return;
+      end if;
 
-      EI : constant Element_Type := Container.Elements (T'(I));
+      if Container.Lock > 0 then
+         raise Program_Error;
+      end if;
 
-   begin
+      declare
+         EI : Element_Type renames Container.Elements (I);
+         EJ : Element_Type renames Container.Elements (J);
 
-      Container.Elements (T'(I)) := Container.Elements (T'(J));
-      Container.Elements (T'(J)) := EI;
+         EI_Copy : constant Element_Type := EI;
 
+      begin
+         EI := EJ;
+         EJ := EI_Copy;
+      end;
    end Swap;
 
    procedure Swap (I, J : Cursor) is
+   begin
+      if I.Container = null
+        or else J.Container = null
+      then
+         raise Constraint_Error;
+      end if;
 
-      --  NOTE: The behavior has been liberalized here to
-      --  allow I and J to designate different containers.
-      --  TODO: Probably this is supposed to raise P_E ???
-
-      subtype TI is Index_Type'Base range
-        Index_Type'First .. I.Container.Last;
-
-      EI : Element_Type renames I.Container.Elements (TI'(I.Index));
-
-      EI_Copy : constant Element_Type := EI;
-
-      subtype TJ is Index_Type'Base range
-        Index_Type'First .. J.Container.Last;
-
-      EJ : Element_Type renames J.Container.Elements (TJ'(J.Index));
+      if I.Container /= J.Container then
+         raise Program_Error;
+      end if;
 
-   begin
-      EI := EJ;
-      EJ := EI_Copy;
+      Swap (I.Container.all, I.Index, J.Index);
    end Swap;
 
    ---------------
@@ -1667,11 +2010,18 @@ package body Ada.Containers.Vectors is
       declare
          First       : constant Int := Int (Index_Type'First);
          Last_As_Int : constant Int'Base := First + Int (Length) - 1;
-         Last        : constant Index_Type := Index_Type (Last_As_Int);
-         Elements    : constant Elements_Access :=
-                         new Elements_Type (Index_Type'First .. Last);
+         Last        : Index_Type;
+         Elements    : Elements_Access;
+
       begin
-         return (Controlled with Elements, Last);
+         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
+
+         Last := Index_Type (Last_As_Int);
+         Elements := new Elements_Type (Index_Type'First .. Last);
+
+         return (Controlled with Elements, Last, 0, 0);
       end;
    end To_Vector;
 
@@ -1687,12 +2037,18 @@ package body Ada.Containers.Vectors is
       declare
          First       : constant Int := Int (Index_Type'First);
          Last_As_Int : constant Int'Base := First + Int (Length) - 1;
-         Last        : constant Index_Type := Index_Type (Last_As_Int);
-         Elements    : constant Elements_Access :=
-                         new Elements_Type'
-                                   (Index_Type'First .. Last => New_Item);
+         Last        : Index_Type;
+         Elements    : Elements_Access;
+
       begin
-         return (Controlled with Elements, Last);
+         if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
+            raise Constraint_Error;
+         end if;
+
+         Last := Index_Type (Last_As_Int);
+         Elements := new Elements_Type'(Index_Type'First .. Last => New_Item);
+
+         return (Controlled with Elements, Last, 0, 0);
       end;
    end To_Vector;
 
@@ -1705,20 +2061,41 @@ package body Ada.Containers.Vectors is
       Index     : Index_Type;
       Process   : not null access procedure (Element : in out Element_Type))
    is
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Container.Last;
+      V : Vector renames Container'Unrestricted_Access.all;
+      B : Natural renames V.Busy;
+      L : Natural renames V.Lock;
+
    begin
-      Process (Container.Elements (T'(Index)));
+      if Index > Container.Last then
+         raise Constraint_Error;
+      end if;
+
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (V.Elements (Index));
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
    procedure Update_Element
      (Position : Cursor;
       Process  : not null access procedure (Element : in out Element_Type))
    is
-      subtype T is Index_Type'Base range
-        Index_Type'First .. Position.Container.Last;
    begin
-      Process (Position.Container.Elements (T'(Position.Index)));
+      if Position.Container = null then
+         raise Constraint_Error;
+      end if;
+
+      Update_Element (Position.Container.all, Position.Index, Process);
    end Update_Element;
 
    -----------
@@ -1738,4 +2115,3 @@ package body Ada.Containers.Vectors is
    end Write;
 
 end Ada.Containers.Vectors;
-
index ef877c0f7979bf3d3e662cf23a740adb72c767ca..638c8ddd6cd14a32ea74591c0b2d2631469060d8 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                          ADA.CONTAINERS.VECTORS                          --
+--                A D A . C O N T A I N E R S . V E C T O R S               --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -200,7 +200,7 @@ pragma Preelaborate (Vectors);
 
    procedure Delete
      (Container : in out Vector;
-      Index     : Extended_Index;  --  TODO: verify
+      Index     : Extended_Index;
       Count     : Count_Type := 1);
 
    procedure Delete
@@ -234,7 +234,15 @@ pragma Preelaborate (Vectors);
 
    generic
       with function "<" (Left, Right : Element_Type) return Boolean is <>;
-   procedure Generic_Sort (Container : Vector);
+   package Generic_Sorting is
+
+      function Is_Sorted (Container : Vector) return Boolean;
+
+      procedure Sort (Container : in out Vector);
+
+      procedure Merge (Target, Source : in out Vector);
+
+   end Generic_Sorting;
 
    function Find_Index
      (Container : Vector;
@@ -301,6 +309,8 @@ private
    type Vector is new Controlled with record
       Elements : Elements_Access;
       Last     : Extended_Index := No_Index;
+      Busy     : Natural := 0;
+      Lock     : Natural := 0;
    end record;
 
    procedure Adjust (Container : in out Vector);
@@ -321,7 +331,7 @@ private
 
    for Vector'Read use Read;
 
-   Empty_Vector : constant Vector := (Controlled with null, No_Index);
+   Empty_Vector : constant Vector := (Controlled with null, No_Index, 0, 0);
 
    type Vector_Access is access constant Vector;
    for Vector_Access'Storage_Size use 0;
index 2a706ab4d59e45f6b9b9756ada3636284c76fc85..8b2af9c100be5c2ee4a8263a54955fdf86ae976a 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                       ADA.CONTAINERS.ORDERED_MAPS                        --
+--           A D A . C O N T A I N E R S . O R D E R E D _ M A P S          --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -41,21 +41,8 @@ pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
 with Ada.Containers.Red_Black_Trees.Generic_Keys;
 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
 
-with System;  use type System.Address;
-
 package body Ada.Containers.Ordered_Maps is
 
-   use Red_Black_Trees;
-
-   type Node_Type is limited record
-      Parent  : Node_Access;
-      Left    : Node_Access;
-      Right   : Node_Access;
-      Color   : Red_Black_Trees.Color_Type := Red;
-      Key     : Key_Type;
-      Element : Element_Type;
-   end record;
-
    -----------------------------
    -- Node Access Subprograms --
    -----------------------------
@@ -94,10 +81,6 @@ package body Ada.Containers.Ordered_Maps is
    function Copy_Node (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access;
-
-   procedure Delete_Tree (X : in out Node_Access);
-
    function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
    pragma Inline (Is_Equal_Node_Node);
 
@@ -118,9 +101,13 @@ package body Ada.Containers.Ordered_Maps is
    procedure Free is new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
 
    package Tree_Operations is
-     new Red_Black_Trees.Generic_Operations
-       (Tree_Types => Tree_Types,
-        Null_Node  => Node_Access'(null));
+      new Red_Black_Trees.Generic_Operations (Tree_Types);
+
+   procedure Delete_Tree is
+      new Tree_Operations.Generic_Delete_Tree (Free);
+
+   function Copy_Tree is
+      new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
 
    use Tree_Operations;
 
@@ -159,10 +146,6 @@ package body Ada.Containers.Ordered_Maps is
 
    function "=" (Left, Right : Map) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
       return Is_Equal (Left.Tree, Right.Tree);
    end "=";
 
@@ -189,24 +172,12 @@ package body Ada.Containers.Ordered_Maps is
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Map) is
-      Tree : Tree_Type renames Container.Tree;
-
-      N : constant Count_Type := Tree.Length;
-      X : constant Node_Access := Tree.Root;
+   procedure Adjust is
+      new Tree_Operations.Generic_Adjust (Copy_Tree);
 
+   procedure Adjust (Container : in out Map) is
    begin
-      if N = 0 then
-         pragma Assert (X = null);
-         return;
-      end if;
-
-      Tree := (Length => 0, others => null);
-
-      Tree.Root := Copy_Tree (X);
-      Tree.First := Min (Tree.Root);
-      Tree.Last := Max (Tree.Root);
-      Tree.Length := N;
+      Adjust (Container.Tree);
    end Adjust;
 
    -------------
@@ -221,19 +192,19 @@ package body Ada.Containers.Ordered_Maps is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Ceiling;
 
    -----------
    -- Clear --
    -----------
 
+   procedure Clear is
+      new Tree_Operations.Generic_Clear (Delete_Tree);
+
    procedure Clear (Container : in out Map) is
-      Tree : Tree_Type renames Container.Tree;
-      Root : Node_Access := Tree.Root;
    begin
-      Tree := (Length => 0, others => null);
-      Delete_Tree (Root);
+      Clear (Container.Tree);
    end Clear;
 
    -----------
@@ -270,64 +241,21 @@ package body Ada.Containers.Ordered_Maps is
       return Target;
    end Copy_Node;
 
-   ---------------
-   -- Copy_Tree --
-   ---------------
-
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access is
-      Target_Root : Node_Access := Copy_Node (Source_Root);
-      P, X : Node_Access;
-
-   begin
-      if Source_Root.Right /= null then
-         Target_Root.Right := Copy_Tree (Source_Root.Right);
-         Target_Root.Right.Parent := Target_Root;
-      end if;
-
-      P := Target_Root;
-      X := Source_Root.Left;
-
-      while X /= null loop
-         declare
-            Y : Node_Access := Copy_Node (X);
-
-         begin
-            P.Left := Y;
-            Y.Parent := P;
-
-            if X.Right /= null then
-               Y.Right := Copy_Tree (X.Right);
-               Y.Right.Parent := Y;
-            end if;
-
-            P := Y;
-            X := X.Left;
-         end;
-      end loop;
-
-      return Target_Root;
-
-   exception
-      when others =>
-         Delete_Tree (Target_Root);
-         raise;
-   end Copy_Tree;
-
    ------------
    -- Delete --
    ------------
 
    procedure Delete (Container : in out Map; Position : in out Cursor) is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container /= Map_Access'(Container'Unchecked_Access) then
+      if Position.Container /= Map_Access'(Container'Unrestricted_Access) then
          raise Program_Error;
       end if;
 
-      Delete_Node_Sans_Free (Container.Tree, Position.Node);
+      Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
       Free (Position.Node);
 
       Position.Container := null;
@@ -350,9 +278,12 @@ package body Ada.Containers.Ordered_Maps is
    ------------------
 
    procedure Delete_First (Container : in out Map) is
-      Position : Cursor := First (Container);
+      X : Node_Access := Container.Tree.First;
    begin
-      Delete (Container, Position);
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
+         Free (X);
+      end if;
    end Delete_First;
 
    -----------------
@@ -360,27 +291,13 @@ package body Ada.Containers.Ordered_Maps is
    -----------------
 
    procedure Delete_Last (Container : in out Map) is
-      Position : Cursor := Last (Container);
+      X : Node_Access := Container.Tree.Last;
    begin
-      Delete (Container, Position);
-   end Delete_Last;
-
-
-   -----------------
-   -- Delete_Tree --
-   -----------------
-
-   procedure Delete_Tree (X : in out Node_Access) is
-      Y : Node_Access;
-   begin
-      while X /= null loop
-         Y := X.Right;
-         Delete_Tree (Y);
-         Y := X.Left;
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
          Free (X);
-         X := Y;
-      end loop;
-   end Delete_Tree;
+      end if;
+   end Delete_Last;
 
    -------------
    -- Element --
@@ -423,7 +340,7 @@ package body Ada.Containers.Ordered_Maps is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Find;
 
    -----------
@@ -436,7 +353,7 @@ package body Ada.Containers.Ordered_Maps is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.First);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
    end First;
 
    -------------------
@@ -469,7 +386,7 @@ package body Ada.Containers.Ordered_Maps is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Floor;
 
    -----------------
@@ -497,6 +414,10 @@ package body Ada.Containers.Ordered_Maps is
       Insert (Container, Key, New_Item, Position, Inserted);
 
       if not Inserted then
+         if Container.Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
+
          Position.Node.Key := Key;
          Position.Node.Element := New_Item;
       end if;
@@ -543,7 +464,7 @@ package body Ada.Containers.Ordered_Maps is
          Position.Node,
          Inserted);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    procedure Insert
@@ -609,7 +530,7 @@ package body Ada.Containers.Ordered_Maps is
          Position.Node,
          Inserted);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    --------------
@@ -628,7 +549,15 @@ package body Ada.Containers.Ordered_Maps is
    function Is_Equal_Node_Node
      (L, R : Node_Access) return Boolean is
    begin
-      return L.Element = R.Element;
+      if L.Key < R.Key then
+         return False;
+
+      elsif R.Key < L.Key then
+         return False;
+
+      else
+         return L.Element = R.Element;
+      end if;
    end Is_Equal_Node_Node;
 
    -------------------------
@@ -677,13 +606,25 @@ package body Ada.Containers.Ordered_Maps is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
+
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Iterate (Container.Tree);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ---------
@@ -705,7 +646,7 @@ package body Ada.Containers.Ordered_Maps is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
    end Last;
 
    ------------------
@@ -748,12 +689,11 @@ package body Ada.Containers.Ordered_Maps is
    -- Move --
    ----------
 
+   procedure Move is
+      new Tree_Operations.Generic_Move (Clear);
+
    procedure Move (Target : in out Map; Source : in out Map) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Move (Target => Target.Tree, Source => Source.Tree);
    end Move;
 
@@ -828,10 +768,32 @@ package body Ada.Containers.Ordered_Maps is
 
    procedure Query_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : Element_Type))
    is
+      K : Key_Type renames Position.Node.Key;
+      E : Element_Type renames Position.Node.Element;
+
+      T : Tree_Type renames Position.Container.Tree;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Key, Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -842,41 +804,35 @@ package body Ada.Containers.Ordered_Maps is
      (Stream    : access Root_Stream_Type'Class;
       Container : out Map)
    is
-      N : Count_Type'Base;
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+      pragma Inline (Read_Node);
 
-      function New_Node return Node_Access;
-      pragma Inline (New_Node);
+      procedure Read is
+         new Tree_Operations.Generic_Read (Clear, Read_Node);
 
-      procedure Local_Read is new Tree_Operations.Generic_Read (New_Node);
+      ---------------
+      -- Read_Node --
+      ---------------
 
-      --------------
-      -- New_Node --
-      --------------
-
-      function New_Node return Node_Access is
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access
+      is
          Node : Node_Access := new Node_Type;
-
       begin
-         begin
-            Key_Type'Read (Stream, Node.Key);
-            Element_Type'Read (Stream, Node.Element);
-         exception
-            when others =>
-               Free (Node);
-               raise;
-         end;
-
+         Key_Type'Read (Stream, Node.Key);
+         Element_Type'Read (Stream, Node.Element);
          return Node;
-      end New_Node;
+      exception
+         when others =>
+            Free (Node);
+            raise;
+      end Read_Node;
 
    --  Start of processing for Read
 
    begin
-      Clear (Container);
-      Count_Type'Base'Read (Stream, N);
-      pragma Assert (N >= 0);
-
-      Local_Read (Container.Tree, N);
+      Read (Stream, Container.Tree);
    end Read;
 
    -------------
@@ -895,6 +851,10 @@ package body Ada.Containers.Ordered_Maps is
          raise Constraint_Error;
       end if;
 
+      if Container.Tree.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       Node.Key := Key;
       Node.Element := New_Item;
    end Replace;
@@ -904,8 +864,14 @@ package body Ada.Containers.Ordered_Maps is
    ---------------------
 
    procedure Replace_Element (Position : Cursor; By : Element_Type) is
+      E : Element_Type renames Position.Node.Element;
+
    begin
-      Position.Node.Element := By;
+      if Position.Container.Tree.Lock > 0 then
+         raise Program_Error;
+      end if;
+
+      E := By;
    end Replace_Element;
 
    ---------------------
@@ -928,13 +894,25 @@ package body Ada.Containers.Ordered_Maps is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
+
       --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (Container.Tree);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    -----------
@@ -976,7 +954,6 @@ package body Ada.Containers.Ordered_Maps is
       Node.Parent := Parent;
    end Set_Parent;
 
-
    ---------------
    -- Set_Right --
    ---------------
@@ -992,10 +969,32 @@ package body Ada.Containers.Ordered_Maps is
 
    procedure Update_Element
      (Position : Cursor;
-      Process  : not null access procedure (Element : in out Element_Type))
+      Process  : not null access procedure (Key     : Key_Type;
+                                            Element : in out Element_Type))
    is
+      K : Key_Type renames Position.Node.Key;
+      E : Element_Type renames Position.Node.Element;
+
+      T : Tree_Type renames Position.Container.Tree;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Key, Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (K, E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Update_Element;
 
    -----------
@@ -1006,26 +1005,31 @@ package body Ada.Containers.Ordered_Maps is
      (Stream    : access Root_Stream_Type'Class;
       Container : Map)
    is
-      procedure Process (Node : Node_Access);
-      pragma Inline (Process);
-
-      procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
-
-      -------------
-      -- Process --
-      -------------
-
-      procedure Process (Node : Node_Access) is
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+      pragma Inline (Write_Node);
+
+      procedure Write is
+         new Tree_Operations.Generic_Write (Write_Node);
+
+      ----------------
+      -- Write_Node --
+      ----------------
+
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access)
+      is
       begin
          Key_Type'Write (Stream, Node.Key);
          Element_Type'Write (Stream, Node.Element);
-      end Process;
+      end Write_Node;
 
    --  Start of processing for Write
 
    begin
-      Count_Type'Base'Write (Stream, Container.Tree.Length);
-      Iterate (Container.Tree);
+      Write (Stream, Container.Tree);
    end Write;
 
 end Ada.Containers.Ordered_Maps;
index 7fa06e0e31b5a7ffcb4b9892943e2a85396ad227..c31a7f02ec19ee4addd7b24c319a62c3238f2e39 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                       ADA.CONTAINERS.ORDERED_MAPS                        --
+--           A D A . C O N T A I N E R S . O R D E R E D _ M A P S          --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -93,34 +93,34 @@ pragma Preelaborate (Ordered_Maps);
    procedure Insert
      (Container : in out Map;
       Key       : Key_Type;
-      New_Item  : Element_Type);
+      Position  : out Cursor;
+      Inserted  : out Boolean);
 
-   procedure Include
+   procedure Insert
      (Container : in out Map;
       Key       : Key_Type;
       New_Item  : Element_Type);
 
-   procedure Replace
+   procedure Include
      (Container : in out Map;
       Key       : Key_Type;
       New_Item  : Element_Type);
 
-   procedure Insert
+   procedure Replace
      (Container : in out Map;
       Key       : Key_Type;
-      Position  : out Cursor;
-      Inserted  : out Boolean);
+      New_Item  : Element_Type);
 
    procedure Delete (Container : in out Map; Key : Key_Type);
 
-   procedure Exclude (Container : in out Map; Key : Key_Type);
-
    procedure Delete (Container : in out Map; Position : in out Cursor);
 
    procedure Delete_First (Container : in out Map);
 
    procedure Delete_Last (Container : in out Map);
 
+   procedure Exclude (Container : in out Map; Key : Key_Type);
+
    function Contains (Container : Map; Key : Key_Type) return Boolean;
 
    function Find (Container : Map; Key : Key_Type) return Cursor;
@@ -145,10 +145,10 @@ pragma Preelaborate (Ordered_Maps);
 
    function Next (Position : Cursor) return Cursor;
 
-   function Previous (Position : Cursor) return Cursor;
-
    procedure Next (Position : in out Cursor);
 
+   function Previous (Position : Cursor) return Cursor;
+
    procedure Previous (Position : in out Cursor);
 
    function Has_Element (Position : Cursor) return Boolean;
@@ -178,21 +178,32 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package Tree_Types is
-     new Red_Black_Trees.Generic_Tree_Types (Node_Access);
+   type Node_Type is limited record
+      Parent  : Node_Access;
+      Left    : Node_Access;
+      Right   : Node_Access;
+      Color   : Red_Black_Trees.Color_Type := Red_Black_Trees.Red;
+      Key     : Key_Type;
+      Element : Element_Type;
+   end record;
 
-   use Tree_Types;
-   use Ada.Finalization;
+   package Tree_Types is new Red_Black_Trees.Generic_Tree_Types
+     (Node_Type,
+      Node_Access);
 
-   type Map is new Controlled with record
-      Tree : Tree_Type := (Length => 0, others => null);
+   type Map is new Ada.Finalization.Controlled with record
+      Tree : Tree_Types.Tree_Type;
    end record;
 
    procedure Adjust (Container : in out Map);
 
    procedure Finalize (Container : in out Map) renames Clear;
 
-   type Map_Access is access constant Map;
+   use Red_Black_Trees;
+   use Tree_Types;
+   use Ada.Finalization;
+
+   type Map_Access is access Map;
    for Map_Access'Storage_Size use 0;
 
    type Cursor is record
@@ -210,7 +221,6 @@ private
 
    for Map'Write use Write;
 
-
    procedure Read
      (Stream    : access Root_Stream_Type'Class;
       Container : out Map);
@@ -218,6 +228,11 @@ private
    for Map'Read use Read;
 
    Empty_Map : constant Map :=
-                 (Controlled with Tree => (Length => 0, others => null));
+                 (Controlled with Tree => (First  => null,
+                                           Last   => null,
+                                           Root   => null,
+                                           Length => 0,
+                                           Busy   => 0,
+                                           Lock   => 0));
 
 end Ada.Containers.Ordered_Maps;
index 20712960bf955b9d60a574bc1bd9b63882db5de6..387abfb7ff29af011475bed434a3afcd254a72ee 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                     ADA.CONTAINERS.ORDERED_MULTISETS                     --
+--     A D A . C O N T A I N E R S . O R D E R E D _ M U L T I S E T S      --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -44,20 +44,8 @@ pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
 
-with System;  use type System.Address;
-
 package body Ada.Containers.Ordered_Multisets is
 
-   use Red_Black_Trees;
-
-   type Node_Type is limited record
-      Parent  : Node_Access;
-      Left    : Node_Access;
-      Right   : Node_Access;
-      Color   : Red_Black_Trees.Color_Type := Red;
-      Element : Element_Type;
-   end record;
-
    -----------------------------
    -- Node Access Subprograms --
    -----------------------------
@@ -96,10 +84,6 @@ package body Ada.Containers.Ordered_Multisets is
    function Copy_Node (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access;
-
-   procedure Delete_Tree (X : in out Node_Access);
-
    procedure Insert_With_Hint
      (Dst_Tree : in out Tree_Type;
       Dst_Hint : Node_Access;
@@ -122,19 +106,28 @@ package body Ada.Containers.Ordered_Multisets is
    function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
    pragma Inline (Is_Less_Node_Node);
 
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type);
+
    --------------------------
    -- Local Instantiations --
    --------------------------
 
+   procedure Free is
+     new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
+
    package Tree_Operations is
-     new Red_Black_Trees.Generic_Operations
-       (Tree_Types => Tree_Types,
-        Null_Node  => Node_Access'(null));
+     new Red_Black_Trees.Generic_Operations (Tree_Types);
 
-   use Tree_Operations;
+   procedure Delete_Tree is
+     new Tree_Operations.Generic_Delete_Tree (Free);
 
-   procedure Free is
-     new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
+   function Copy_Tree is
+     new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
+
+   use Tree_Operations;
 
    function Is_Equal is
      new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
@@ -182,10 +175,6 @@ package body Ada.Containers.Ordered_Multisets is
 
    function "=" (Left, Right : Set) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
       return Is_Equal (Left.Tree, Right.Tree);
    end "=";
 
@@ -216,24 +205,12 @@ package body Ada.Containers.Ordered_Multisets is
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-
-      N : constant Count_Type := Tree.Length;
-      X : constant Node_Access := Tree.Root;
+   procedure Adjust is
+      new Tree_Operations.Generic_Adjust (Copy_Tree);
 
+   procedure Adjust (Container : in out Set) is
    begin
-      if N = 0 then
-         pragma Assert (X = null);
-         return;
-      end if;
-
-      Tree := (Length => 0, others => null);
-
-      Tree.Root := Copy_Tree (X);
-      Tree.First := Min (Tree.Root);
-      Tree.Last := Max (Tree.Root);
-      Tree.Length := N;
+      Adjust (Container.Tree);
    end Adjust;
 
    -------------
@@ -249,19 +226,19 @@ package body Ada.Containers.Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Ceiling;
 
    -----------
    -- Clear --
    -----------
 
+   procedure Clear is
+      new Tree_Operations.Generic_Clear (Delete_Tree);
+
    procedure Clear (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-      Root : Node_Access := Tree.Root;
    begin
-      Tree := (Length => 0, others => null);
-      Delete_Tree (Root);
+      Clear (Container.Tree);
    end Clear;
 
    -----------
@@ -297,49 +274,6 @@ package body Ada.Containers.Ordered_Multisets is
       return Target;
    end Copy_Node;
 
-   ---------------
-   -- Copy_Tree --
-   ---------------
-
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access is
-      Target_Root : Node_Access := Copy_Node (Source_Root);
-
-      P, X : Node_Access;
-
-   begin
-      if Source_Root.Right /= null then
-         Target_Root.Right := Copy_Tree (Source_Root.Right);
-         Target_Root.Right.Parent := Target_Root;
-      end if;
-
-      P := Target_Root;
-      X := Source_Root.Left;
-      while X /= null loop
-         declare
-            Y : Node_Access := Copy_Node (X);
-
-         begin
-            P.Left := Y;
-            Y.Parent := P;
-
-            if X.Right /= null then
-               Y.Right := Copy_Tree (X.Right);
-               Y.Right.Parent := Y;
-            end if;
-
-            P := Y;
-            X := X.Left;
-         end;
-      end loop;
-
-      return Target_Root;
-
-   exception
-      when others =>
-         Delete_Tree (Target_Root);
-         raise;
-   end Copy_Tree;
-
    ------------
    -- Delete --
    ------------
@@ -367,11 +301,11 @@ package body Ada.Containers.Ordered_Multisets is
 
    procedure Delete (Container : in out Set; Position  : in out Cursor) is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
+      if Position.Container /= Container'Unrestricted_Access then
          raise Program_Error;
       end if;
 
@@ -415,48 +349,20 @@ package body Ada.Containers.Ordered_Multisets is
       Free (X);
    end Delete_Last;
 
-   -----------------
-   -- Delete_Tree --
-   -----------------
-
-   procedure Delete_Tree (X : in out Node_Access) is
-      Y : Node_Access;
-   begin
-      while X /= null loop
-         Y := X.Right;
-         Delete_Tree (Y);
-         Y := X.Left;
-         Free (X);
-         X := Y;
-      end loop;
-   end Delete_Tree;
-
    ----------------
    -- Difference --
    ----------------
 
    procedure Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Difference (Target.Tree, Source.Tree);
    end Difference;
 
    function Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Difference;
 
    -------------
@@ -468,6 +374,39 @@ package body Ada.Containers.Ordered_Multisets is
       return Position.Node.Element;
    end Element;
 
+   ---------------------
+   -- Equivalent_Sets --
+   ---------------------
+
+   function Equivalent_Sets (Left, Right : Set) return Boolean is
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
+      pragma Inline (Is_Equivalent_Node_Node);
+
+      function Is_Equivalent is
+        new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
+
+      -----------------------------
+      -- Is_Equivalent_Node_Node --
+      -----------------------------
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
+      begin
+         if L.Element < R.Element then
+            return False;
+         elsif R.Element < L.Element then
+            return False;
+         else
+            return True;
+         end if;
+      end Is_Equivalent_Node_Node;
+
+   --  Start of processing for Equivalent_Sets
+
+   begin
+      return Is_Equivalent (Left.Tree, Right.Tree);
+   end Equivalent_Sets;
+
    -------------
    -- Exclude --
    -------------
@@ -499,7 +438,7 @@ package body Ada.Containers.Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Find;
 
    -----------
@@ -512,7 +451,7 @@ package body Ada.Containers.Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.First);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
    end First;
 
    -------------------
@@ -537,7 +476,7 @@ package body Ada.Containers.Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Floor;
 
    ------------------
@@ -612,77 +551,9 @@ package body Ada.Containers.Ordered_Multisets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Ceiling;
 
-      ----------------------------
-      -- Checked_Update_Element --
-      ----------------------------
-
-      procedure Checked_Update_Element
-        (Container : in out Set;
-         Position  : Cursor;
-         Process   : not null access procedure (Element : in out Element_Type))
-      is
-      begin
-         if Position.Container = null then
-            raise Constraint_Error;
-         end if;
-
-         if Position.Container /= Set_Access'(Container'Unchecked_Access) then
-            raise Program_Error;
-         end if;
-
-         declare
-            Old_Key : Key_Type renames Key (Position.Node.Element);
-
-         begin
-            Process (Position.Node.Element);
-
-            if Old_Key < Position.Node.Element
-              or else Old_Key > Position.Node.Element
-            then
-               null;
-            else
-               return;
-            end if;
-         end;
-
-         Delete_Node_Sans_Free (Container.Tree, Position.Node);
-
-         Do_Insert : declare
-            Result  : Node_Access;
-
-            function New_Node return Node_Access;
-            pragma Inline (New_Node);
-
-            procedure Insert_Post is
-              new Key_Keys.Generic_Insert_Post (New_Node);
-
-            procedure Insert is
-              new Key_Keys.Generic_Unconditional_Insert (Insert_Post);
-
-            --------------
-            -- New_Node --
-            --------------
-
-            function New_Node return Node_Access is
-            begin
-               return Position.Node;
-            end New_Node;
-
-         --  Start of processing for Do_Insert
-
-         begin
-            Insert
-              (Tree    => Container.Tree,
-               Key     => Key (Position.Node.Element),
-               Node    => Result);
-
-            pragma Assert (Result = Position.Node);
-         end Do_Insert;
-      end Checked_Update_Element;
-
       --------------
       -- Contains --
       --------------
@@ -759,7 +630,7 @@ package body Ada.Containers.Ordered_Multisets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Find;
 
       -----------
@@ -775,7 +646,7 @@ package body Ada.Containers.Ordered_Multisets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Floor;
 
       -------------------------
@@ -821,13 +692,26 @@ package body Ada.Containers.Ordered_Multisets is
 
          procedure Process_Node (Node : Node_Access) is
          begin
-            Process (Cursor'(Container'Unchecked_Access, Node));
+            Process (Cursor'(Container'Unrestricted_Access, Node));
          end Process_Node;
 
+         T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+         B : Natural renames T.Busy;
+
       --  Start of processing for Iterate
 
       begin
-         Local_Iterate (Container.Tree, Key);
+         B := B + 1;
+
+         begin
+            Local_Iterate (T, Key);
+         exception
+            when others =>
+               B := B - 1;
+               raise;
+         end;
+
+         B := B - 1;
       end Iterate;
 
       ---------
@@ -839,27 +723,6 @@ package body Ada.Containers.Ordered_Multisets is
          return Key (Position.Node.Element);
       end Key;
 
-      -------------
-      -- Replace --
-      -------------
-
-      --  In post-madision api:???
-
---    procedure Replace
---      (Container : in out Set;
---       Key       : Key_Type;
---       New_Item  : Element_Type)
---    is
---       Node : Node_Access := Key_Keys.Find (Container.Tree, Key);
-
---    begin
---       if Node = null then
---          raise Constraint_Error;
---       end if;
-
---       Replace_Node (Container, Node, New_Item);
---    end Replace;
-
       ---------------------
       -- Reverse_Iterate --
       ---------------------
@@ -881,15 +744,90 @@ package body Ada.Containers.Ordered_Multisets is
 
          procedure Process_Node (Node : Node_Access) is
          begin
-            Process (Cursor'(Container'Unchecked_Access, Node));
+            Process (Cursor'(Container'Unrestricted_Access, Node));
          end Process_Node;
 
+         T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+         B : Natural renames T.Busy;
+
       --  Start of processing for Reverse_Iterate
 
       begin
-         Local_Reverse_Iterate (Container.Tree, Key);
+         B := B + 1;
+
+         begin
+            Local_Reverse_Iterate (T, Key);
+         exception
+            when others =>
+               B := B - 1;
+               raise;
+         end;
+
+         B := B - 1;
       end Reverse_Iterate;
 
+      -----------------------------------
+      -- Update_Element_Preserving_Key --
+      -----------------------------------
+
+      procedure Update_Element_Preserving_Key
+        (Container : in out Set;
+         Position  : Cursor;
+         Process   : not null access procedure (Element : in out Element_Type))
+      is
+         Tree : Tree_Type renames Container.Tree;
+
+      begin
+         if Position.Node = null then
+            raise Constraint_Error;
+         end if;
+
+         if Position.Container /= Container'Unrestricted_Access then
+            raise Program_Error;
+         end if;
+
+         declare
+            E : Element_Type renames Position.Node.Element;
+            K : Key_Type renames Key (E);
+
+            B : Natural renames Tree.Busy;
+            L : Natural renames Tree.Lock;
+
+         begin
+            B := B + 1;
+            L := L + 1;
+
+            begin
+               Process (E);
+            exception
+               when others =>
+                  L := L - 1;
+                  B := B - 1;
+                  raise;
+            end;
+
+            L := L - 1;
+            B := B - 1;
+
+            if K < E
+              or else K > E
+            then
+               null;
+            else
+               return;
+            end if;
+         end;
+
+         declare
+            X : Node_Access := Position.Node;
+         begin
+            Tree_Operations.Delete_Node_Sans_Free (Tree, X);
+            Free (X);
+         end;
+
+         raise Program_Error;
+      end Update_Element_Preserving_Key;
+
    end Generic_Keys;
 
    -----------------
@@ -948,7 +886,7 @@ package body Ada.Containers.Ordered_Multisets is
          New_Item,
          Position.Node);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    ----------------------
@@ -1006,25 +944,14 @@ package body Ada.Containers.Ordered_Multisets is
 
    procedure Intersection (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Intersection (Target.Tree, Source.Tree);
    end Intersection;
 
    function Intersection (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Intersection (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Intersection (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Intersection;
 
    --------------
@@ -1086,10 +1013,6 @@ package body Ada.Containers.Ordered_Multisets is
 
    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
    begin
-      if Subset'Address = Of_Set'Address then
-         return True;
-      end if;
-
       return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
    end Is_Subset;
 
@@ -1113,13 +1036,26 @@ package body Ada.Containers.Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    procedure Iterate
@@ -1139,13 +1075,26 @@ package body Ada.Containers.Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Iterate
 
    begin
-      Local_Iterate (Container.Tree, Item);
+      B := B + 1;
+
+      begin
+         Local_Iterate (T, Item);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ----------
@@ -1158,7 +1107,7 @@ package body Ada.Containers.Ordered_Multisets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
    end Last;
 
    ------------------
@@ -1192,12 +1141,11 @@ package body Ada.Containers.Ordered_Multisets is
    -- Move --
    ----------
 
+   procedure Move is
+      new Tree_Operations.Generic_Move (Clear);
+
    procedure Move (Target : in out Set; Source : in out Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Move (Target => Target.Tree, Source => Source.Tree);
    end Move;
 
@@ -1219,7 +1167,7 @@ package body Ada.Containers.Ordered_Multisets is
 
       declare
          Node : constant Node_Access :=
-           Tree_Operations.Next (Position.Node);
+                  Tree_Operations.Next (Position.Node);
       begin
          if Node = null then
             return No_Element;
@@ -1235,10 +1183,6 @@ package body Ada.Containers.Ordered_Multisets is
 
    function Overlap (Left, Right : Set) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return Left.Tree.Length /= 0;
-      end if;
-
       return Set_Ops.Overlap (Left.Tree, Right.Tree);
    end Overlap;
 
@@ -1269,7 +1213,7 @@ package body Ada.Containers.Ordered_Multisets is
 
       declare
          Node : constant Node_Access :=
-           Tree_Operations.Previous (Position.Node);
+                  Tree_Operations.Previous (Position.Node);
       begin
          if Node = null then
             return No_Element;
@@ -1287,8 +1231,29 @@ package body Ada.Containers.Ordered_Multisets is
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type))
    is
+      E : Element_Type renames Position.Node.Element;
+
+      S : Set renames Position.Container.all;
+      T : Tree_Type renames S.Tree'Unrestricted_Access.all;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -1299,151 +1264,113 @@ package body Ada.Containers.Ordered_Multisets is
      (Stream    : access Root_Stream_Type'Class;
       Container : out Set)
    is
-      N : Count_Type'Base;
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+      pragma Inline (Read_Node);
 
-      function New_Node return Node_Access;
-      pragma Inline (New_Node);
-
-      procedure Local_Read is new Tree_Operations.Generic_Read (New_Node);
+      procedure Read is
+         new Tree_Operations.Generic_Read (Clear, Read_Node);
 
-      --------------
-      -- New_Node --
-      --------------
+      ---------------
+      -- Read_Node --
+      ---------------
 
-      function New_Node return Node_Access is
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access
+      is
          Node : Node_Access := new Node_Type;
-
       begin
-         begin
-            Element_Type'Read (Stream, Node.Element);
-
-         exception
-            when others =>
-               Free (Node);
-               raise;
-         end;
-
+         Element_Type'Read (Stream, Node.Element);
          return Node;
-      end New_Node;
+      exception
+         when others =>
+            Free (Node);  --  Note that Free deallocates elem too
+            raise;
+      end Read_Node;
 
    --  Start of processing for Read
 
    begin
-      Clear (Container);
+      Read (Stream, Container.Tree);
+   end Read;
 
-      Count_Type'Base'Read (Stream, N);
-      pragma Assert (N >= 0);
+   ---------------------
+   -- Replace_Element --
+   ---------------------
 
-      Local_Read (Container.Tree, N);
-   end Read;
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type)
+   is
+   begin
+      if Item < Node.Element
+        or else Node.Element < Item
+      then
+         null;
+      else
+         if Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
 
-   -------------
-   -- Replace --
-   -------------
+         Node.Element := Item;
+         return;
+      end if;
 
-   --  NOTE: from post-madison api ???
+      Tree_Operations.Delete_Node_Sans_Free (Tree, Node);  -- Checks busy-bit
 
---   procedure Replace
---     (Container : in out Set;
---      Position  : Cursor;
---      By        : Element_Type)
---   is
---   begin
---      if Position.Container = null then
---         raise Constraint_Error;
---      end if;
+      Insert_New_Item : declare
+         function New_Node return Node_Access;
+         pragma Inline (New_Node);
 
---      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
---         raise Program_Error;
---      end if;
+         procedure Insert_Post is
+            new Element_Keys.Generic_Insert_Post (New_Node);
 
---      Replace_Node (Container, Position.Node, By);
---   end Replace;
+         procedure Unconditional_Insert is
+            new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
 
-   ------------------
-   -- Replace_Node --
-   ------------------
+         --------------
+         -- New_Node --
+         --------------
+
+         function New_Node return Node_Access is
+         begin
+            Node.Element := Item;
+            return Node;
+         end New_Node;
+
+         Result : Node_Access;
+
+      --  Start of processing for Insert_New_Item
+
+      begin
+         Unconditional_Insert
+           (Tree => Tree,
+            Key  => Item,
+            Node => Result);
+
+         pragma Assert (Result = Node);
+      end Insert_New_Item;
+   end Replace_Element;
+
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type)
+   is
+      Tree : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
 
-   --  NOTE: from post-madison api ???
-
---   procedure Replace_Node
---     (Container : in out Set;
---      Position  : Node_Access;
---      By        : Element_Type)
---   is
---      Tree : Tree_Type renames Container.Tree;
---      Node : Node_Access := Position;
-
---   begin
---      if By < Node.Element
---        or else Node.Element < By
---      then
---         null;
-
---      else
---         begin
---            Node.Element := By;
-
---         exception
---            when others =>
---               Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
---               Free (Node);
---               raise;
---         end;
-
---         return;
---      end if;
-
---      Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
-
---      begin
---         Node.Element := By;
-
---      exception
---         when others =>
---            Free (Node);
---            raise;
---      end;
---
---      Do_Insert : declare
---         Result  : Node_Access;
---         Success : Boolean;
-
---         function New_Node return Node_Access;
---         pragma Inline (New_Node);
-
---         procedure Insert_Post is
---           new Element_Keys.Generic_Insert_Post (New_Node);
---
---         procedure Insert is
---           new Element_Keys.Generic_Conditional_Insert (Insert_Post);
-
---         --------------
---         -- New_Node --
---         --------------
-
---         function New_Node return Node_Access is
---         begin
---            return Node;
---         end New_Node;
-
---      --  Start of processing for Do_Insert
-
---      begin
---         Insert
---           (Tree    => Tree,
---            Key     => Node.Element,
---            Node    => Result,
---            Success => Success);
---
---         if not Success then
---            Free (Node);
---            raise Program_Error;
---         end if;
---
---         pragma Assert (Result = Node);
---      end Do_Insert;
---   end Replace_Node;
+      if Position.Container /= Container'Unrestricted_Access then
+         raise Program_Error;
+      end if;
+
+      Replace_Element (Tree, Position.Node, By);
+   end Replace_Element;
 
    ---------------------
    -- Reverse_Iterate --
@@ -1465,13 +1392,26 @@ package body Ada.Containers.Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    procedure Reverse_Iterate
@@ -1491,13 +1431,26 @@ package body Ada.Containers.Ordered_Multisets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree, Item);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (T, Item);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    -----------
@@ -1551,26 +1504,14 @@ package body Ada.Containers.Ordered_Multisets is
 
    procedure Symmetric_Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
    end Symmetric_Difference;
 
    function Symmetric_Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Symmetric_Difference;
 
    -----------
@@ -1579,25 +1520,14 @@ package body Ada.Containers.Ordered_Multisets is
 
    procedure Union (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Union (Target.Tree, Source.Tree);
    end Union;
 
    function Union (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Union (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Union (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Union;
 
    -----------
@@ -1608,28 +1538,30 @@ package body Ada.Containers.Ordered_Multisets is
      (Stream    : access Root_Stream_Type'Class;
       Container : Set)
    is
-      procedure Process (Node : Node_Access);
-      pragma Inline (Process);
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+      pragma Inline (Write_Node);
 
-      procedure Iterate is
-        new Tree_Operations.Generic_Iteration (Process);
+      procedure Write is
+         new Tree_Operations.Generic_Write (Write_Node);
 
-      -------------
-      -- Process --
-      -------------
+      ----------------
+      -- Write_Node --
+      ----------------
 
-      procedure Process (Node : Node_Access) is
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access)
+      is
       begin
          Element_Type'Write (Stream, Node.Element);
-      end Process;
+      end Write_Node;
 
    --  Start of processing for Write
 
    begin
-      Count_Type'Base'Write (Stream, Container.Tree.Length);
-      Iterate (Container.Tree);
+      Write (Stream, Container.Tree);
    end Write;
 
 end Ada.Containers.Ordered_Multisets;
-
-
index 6d848a8215a59d2894cdf3ef0801440de0112215..4fbb653725d85337be0f6258c1486e7e219d9fb3 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                     ADA.CONTAINERS.ORDERED_MULTISETS                     --
+--     A D A . C O N T A I N E R S . O R D E R E D _ M U L T I S E T S      --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -56,6 +56,8 @@ pragma Preelaborate (Ordered_Multisets);
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -68,6 +70,11 @@ pragma Preelaborate (Ordered_Multisets);
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type));
 
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type);
+
    procedure Move
      (Target : in out Set;
       Source : in out Set);
@@ -85,10 +92,6 @@ pragma Preelaborate (Ordered_Multisets);
      (Container : in out Set;
       Item      : Element_Type);
 
-   procedure Exclude
-     (Container : in out Set;
-      Item      : Element_Type);
-
    procedure Delete
      (Container : in out Set;
       Position  : in out Cursor);
@@ -97,13 +100,9 @@ pragma Preelaborate (Ordered_Multisets);
 
    procedure Delete_Last (Container : in out Set);
 
-   --  NOTE: The following operation is named Replace in the Madison API.
-   --  However, it should be named Replace_Element. ???
-   --
-   --   procedure Replace
-   --     (Container : in out Set;
-   --      Position  : Cursor;
-   --      By        : Element_Type);
+   procedure Exclude
+     (Container : in out Set;
+      Item      : Element_Type);
 
    procedure Union (Target : in out Set; Source : Set);
 
@@ -151,10 +150,10 @@ pragma Preelaborate (Ordered_Multisets);
 
    function Next (Position : Cursor) return Cursor;
 
-   function Previous (Position : Cursor) return Cursor;
-
    procedure Next (Position : in out Cursor);
 
+   function Previous (Position : Cursor) return Cursor;
+
    procedure Previous (Position : in out Cursor);
 
    function Has_Element (Position : Cursor) return Boolean;
@@ -214,12 +213,6 @@ pragma Preelaborate (Ordered_Multisets);
 
       function Element (Container : Set; Key : Key_Type) return Element_Type;
 
-      --  NOTE: in post-madison api ???
-      --      procedure Replace
-      --        (Container : in out Set;
-      --         Key       : Key_Type;
-      --         New_Item  : Element_Type);
-
       procedure Delete (Container : in out Set; Key : Key_Type);
 
       procedure Exclude (Container : in out Set; Key : Key_Type);
@@ -232,9 +225,7 @@ pragma Preelaborate (Ordered_Multisets);
 
       function ">" (Left : Key_Type; Right : Cursor) return Boolean;
 
-      --  Should name of following be "Update_Element" ???
-
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : Cursor;
          Process   : not null access
@@ -257,21 +248,31 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package Tree_Types is
-     new Red_Black_Trees.Generic_Tree_Types (Node_Access);
+   type Node_Type is limited record
+      Parent  : Node_Access;
+      Left    : Node_Access;
+      Right   : Node_Access;
+      Color   : Red_Black_Trees.Color_Type := Red_Black_Trees.Red;
+      Element : Element_Type;
+   end record;
 
-   use Tree_Types;
-   use Ada.Finalization;
+   package Tree_Types is new Red_Black_Trees.Generic_Tree_Types
+     (Node_Type,
+      Node_Access);
 
-   type Set is new Controlled with record
-      Tree : Tree_Type := (Length => 0, others => null);
+   type Set is new Ada.Finalization.Controlled with record
+      Tree : Tree_Types.Tree_Type;
    end record;
 
    procedure Adjust (Container : in out Set);
 
    procedure Finalize (Container : in out Set) renames Clear;
 
-   type Set_Access is access constant Set;
+   use Red_Black_Trees;
+   use Tree_Types;
+   use Ada.Finalization;
+
+   type Set_Access is access all Set;
    for Set_Access'Storage_Size use 0;
 
    type Cursor is record
@@ -296,6 +297,11 @@ private
    for Set'Read use Read;
 
    Empty_Set : constant Set :=
-                 (Controlled with Tree => (Length => 0, others => null));
+                 (Controlled with Tree => (First  => null,
+                                           Last   => null,
+                                           Root   => null,
+                                           Length => 0,
+                                           Busy   => 0,
+                                           Lock   => 0));
 
 end Ada.Containers.Ordered_Multisets;
index 03cf0036ddb411ac1cf7c66118ce2990147443f6..6e803984c7bae53d2f12c1307822591c5e0b0536 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                       ADA.CONTAINERS.ORDERED_SETS                        --
+--           A D A . C O N T A I N E R S . O R D E R E D _ S E T S          --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -44,20 +44,8 @@ pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
 
-with System;  use type System.Address;
-
 package body Ada.Containers.Ordered_Sets is
 
-   use Red_Black_Trees;
-
-   type Node_Type is limited record
-      Parent  : Node_Access;
-      Left    : Node_Access;
-      Right   : Node_Access;
-      Color   : Red_Black_Trees.Color_Type := Red;
-      Element : Element_Type;
-   end record;
-
    ------------------------------
    -- Access to Fields of Node --
    ------------------------------
@@ -96,10 +84,6 @@ package body Ada.Containers.Ordered_Sets is
    function Copy_Node (Source : Node_Access) return Node_Access;
    pragma Inline (Copy_Node);
 
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access;
-
-   procedure Delete_Tree (X : in out Node_Access);
-
    procedure Insert_With_Hint
      (Dst_Tree : in out Tree_Type;
       Dst_Hint : Node_Access;
@@ -122,19 +106,28 @@ package body Ada.Containers.Ordered_Sets is
    function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
    pragma Inline (Is_Less_Node_Node);
 
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type);
+
    --------------------------
    -- Local Instantiations --
    --------------------------
 
+   procedure Free is
+     new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
+
    package Tree_Operations is
-     new Red_Black_Trees.Generic_Operations
-      (Tree_Types => Tree_Types,
-       Null_Node  => Node_Access'(null));
+     new Red_Black_Trees.Generic_Operations (Tree_Types);
 
-   use Tree_Operations;
+   procedure Delete_Tree is
+      new Tree_Operations.Generic_Delete_Tree (Free);
 
-   procedure Free is
-     new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
+   function Copy_Tree is
+      new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
+
+   use Tree_Operations;
 
    function Is_Equal is
      new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
@@ -180,10 +173,6 @@ package body Ada.Containers.Ordered_Sets is
 
    function "=" (Left, Right : Set) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return True;
-      end if;
-
       return Is_Equal (Left.Tree, Right.Tree);
    end "=";
 
@@ -212,24 +201,12 @@ package body Ada.Containers.Ordered_Sets is
    -- Adjust --
    ------------
 
-   procedure Adjust (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-
-      N : constant Count_Type := Tree.Length;
-      X : constant Node_Access := Tree.Root;
+   procedure Adjust is
+      new Tree_Operations.Generic_Adjust (Copy_Tree);
 
+   procedure Adjust (Container : in out Set) is
    begin
-      if N = 0 then
-         pragma Assert (X = null);
-         return;
-      end if;
-
-      Tree := (Length => 0, others => null);
-
-      Tree.Root := Copy_Tree (X);
-      Tree.First := Min (Tree.Root);
-      Tree.Last := Max (Tree.Root);
-      Tree.Length := N;
+      Adjust (Container.Tree);
    end Adjust;
 
    -------------
@@ -245,19 +222,19 @@ package body Ada.Containers.Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Ceiling;
 
    -----------
    -- Clear --
    -----------
 
+   procedure Clear is
+      new Tree_Operations.Generic_Clear (Delete_Tree);
+
    procedure Clear (Container : in out Set) is
-      Tree : Tree_Type renames Container.Tree;
-      Root : Node_Access := Tree.Root;
    begin
-      Tree := (Length => 0, others => null);
-      Delete_Tree (Root);
+      Clear (Container.Tree);
    end Clear;
 
    -----------
@@ -296,65 +273,21 @@ package body Ada.Containers.Ordered_Sets is
       return Target;
    end Copy_Node;
 
-   ---------------
-   -- Copy_Tree --
-   ---------------
-
-   function Copy_Tree (Source_Root : Node_Access) return Node_Access is
-      Target_Root : Node_Access := Copy_Node (Source_Root);
-
-      P, X : Node_Access;
-
-   begin
-      if Source_Root.Right /= null then
-         Target_Root.Right := Copy_Tree (Source_Root.Right);
-         Target_Root.Right.Parent := Target_Root;
-      end if;
-
-      P := Target_Root;
-      X := Source_Root.Left;
-      while X /= null loop
-         declare
-            Y : Node_Access := Copy_Node (X);
-
-         begin
-            P.Left := Y;
-            Y.Parent := P;
-
-            if X.Right /= null then
-               Y.Right := Copy_Tree (X.Right);
-               Y.Right.Parent := Y;
-            end if;
-
-            P := Y;
-            X := X.Left;
-         end;
-      end loop;
-
-      return Target_Root;
-
-   exception
-      when others =>
-
-         Delete_Tree (Target_Root);
-         raise;
-   end Copy_Tree;
-
    ------------
    -- Delete --
    ------------
 
    procedure Delete (Container : in out Set; Position : in out Cursor) is
    begin
-      if Position = No_Element then
-         return;
+      if Position.Node = null then
+         raise Constraint_Error;
       end if;
 
-      if Position.Container /= Set_Access'(Container'Unchecked_Access) then
+      if Position.Container /= Container'Unrestricted_Access then
          raise Program_Error;
       end if;
 
-      Delete_Node_Sans_Free (Container.Tree, Position.Node);
+      Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
       Free (Position.Node);
       Position.Container := null;
    end Delete;
@@ -367,7 +300,7 @@ package body Ada.Containers.Ordered_Sets is
          raise Constraint_Error;
       end if;
 
-      Delete_Node_Sans_Free (Container.Tree, X);
+      Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
       Free (X);
    end Delete;
 
@@ -376,9 +309,14 @@ package body Ada.Containers.Ordered_Sets is
    ------------------
 
    procedure Delete_First (Container : in out Set) is
-      C : Cursor := First (Container);
+      Tree : Tree_Type renames Container.Tree;
+      X    : Node_Access := Tree.First;
+
    begin
-      Delete (Container, C);
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Tree, X);
+         Free (X);
+      end if;
    end Delete_First;
 
    -----------------
@@ -386,26 +324,15 @@ package body Ada.Containers.Ordered_Sets is
    -----------------
 
    procedure Delete_Last (Container : in out Set) is
-      C : Cursor := Last (Container);
-   begin
-      Delete (Container, C);
-   end Delete_Last;
-
-   -----------------
-   -- Delete_Tree --
-   -----------------
+      Tree : Tree_Type renames Container.Tree;
+      X    : Node_Access := Tree.Last;
 
-   procedure Delete_Tree (X : in out Node_Access) is
-      Y : Node_Access;
    begin
-      while X /= null loop
-         Y := X.Right;
-         Delete_Tree (Y);
-         Y := X.Left;
+      if X /= null then
+         Tree_Operations.Delete_Node_Sans_Free (Tree, X);
          Free (X);
-         X := Y;
-      end loop;
-   end Delete_Tree;
+      end if;
+   end Delete_Last;
 
    ----------------
    -- Difference --
@@ -413,26 +340,14 @@ package body Ada.Containers.Ordered_Sets is
 
    procedure Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Difference (Target.Tree, Source.Tree);
    end Difference;
 
    function Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Difference;
 
    -------------
@@ -444,6 +359,38 @@ package body Ada.Containers.Ordered_Sets is
       return Position.Node.Element;
    end Element;
 
+   ---------------------
+   -- Equivalent_Sets --
+   ---------------------
+
+   function Equivalent_Sets (Left, Right : Set) return Boolean is
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
+      pragma Inline (Is_Equivalent_Node_Node);
+
+      function Is_Equivalent is
+         new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
+
+      -----------------------------
+      -- Is_Equivalent_Node_Node --
+      -----------------------------
+
+      function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
+      begin
+         if L.Element < R.Element then
+            return False;
+         elsif R.Element < L.Element then
+            return False;
+         else
+            return True;
+         end if;
+      end Is_Equivalent_Node_Node;
+
+   --  Start of processing for Equivalent_Sets
+
+   begin
+      return Is_Equivalent (Left.Tree, Right.Tree);
+   end Equivalent_Sets;
+
    -------------
    -- Exclude --
    -------------
@@ -453,7 +400,7 @@ package body Ada.Containers.Ordered_Sets is
 
    begin
       if X /= null then
-         Delete_Node_Sans_Free (Container.Tree, X);
+         Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
          Free (X);
       end if;
    end Exclude;
@@ -471,7 +418,7 @@ package body Ada.Containers.Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Find;
 
    -----------
@@ -484,7 +431,7 @@ package body Ada.Containers.Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.First);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
    end First;
 
    -------------------
@@ -509,7 +456,7 @@ package body Ada.Containers.Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Node);
+      return Cursor'(Container'Unrestricted_Access, Node);
    end Floor;
 
    ------------------
@@ -584,88 +531,9 @@ package body Ada.Containers.Ordered_Sets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Ceiling;
 
-      ----------------------------
-      -- Checked_Update_Element --
-      ----------------------------
-
-      procedure Checked_Update_Element
-        (Container : in out Set;
-         Position  : Cursor;
-         Process   : not null access procedure (Element : in out Element_Type))
-      is
-      begin
-         if Position.Container = null then
-            raise Constraint_Error;
-         end if;
-
-         if Position.Container /= Set_Access'(Container'Unchecked_Access) then
-            raise Program_Error;
-         end if;
-
-         declare
-            Old_Key : Key_Type renames Key (Position.Node.Element);
-
-         begin
-            Process (Position.Node.Element);
-
-            if Old_Key < Position.Node.Element
-              or else Old_Key > Position.Node.Element
-            then
-               null;
-            else
-               return;
-            end if;
-         end;
-
-         Delete_Node_Sans_Free (Container.Tree, Position.Node);
-
-         declare
-            Result  : Node_Access;
-            Success : Boolean;
-
-            function New_Node return Node_Access;
-            pragma Inline (New_Node);
-
-            procedure Local_Insert_Post is
-              new Key_Keys.Generic_Insert_Post (New_Node);
-
-            procedure Local_Conditional_Insert is
-               new Key_Keys.Generic_Conditional_Insert (Local_Insert_Post);
-
-            --------------
-            -- New_Node --
-            --------------
-
-            function New_Node return Node_Access is
-            begin
-               return Position.Node;
-            end New_Node;
-
-
-         begin
-            Local_Conditional_Insert
-              (Tree    => Container.Tree,
-               Key     => Key (Position.Node.Element),
-               Node    => Result,
-               Success => Success);
-
-            if not Success then
-               declare
-                  X : Node_Access := Position.Node;
-               begin
-                  Free (X);
-               end;
-
-               raise Program_Error;
-            end if;
-
-            pragma Assert (Result = Position.Node);
-         end;
-      end Checked_Update_Element;
-
       --------------
       -- Contains --
       --------------
@@ -700,6 +568,7 @@ package body Ada.Containers.Ordered_Sets is
          Key       : Key_Type) return Element_Type
       is
          Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
+
       begin
          return Node.Element;
       end Element;
@@ -710,6 +579,7 @@ package body Ada.Containers.Ordered_Sets is
 
       procedure Exclude (Container : in out Set; Key : Key_Type) is
          X : Node_Access := Key_Keys.Find (Container.Tree, Key);
+
       begin
          if X /= null then
             Delete_Node_Sans_Free (Container.Tree, X);
@@ -729,7 +599,7 @@ package body Ada.Containers.Ordered_Sets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Find;
 
       -----------
@@ -744,7 +614,7 @@ package body Ada.Containers.Ordered_Sets is
             return No_Element;
          end if;
 
-         return Cursor'(Container'Unchecked_Access, Node);
+         return Cursor'(Container'Unrestricted_Access, Node);
       end Floor;
 
       -------------------------
@@ -784,22 +654,82 @@ package body Ada.Containers.Ordered_Sets is
       -- Replace --
       -------------
 
---    TODO???
+      procedure Replace
+        (Container : in out Set;
+         Key       : Key_Type;
+         New_Item  : Element_Type)
+      is
+         Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
 
---    procedure Replace
---      (Container : in out Set;
---        Key       : Key_Type;
---        New_Item  : Element_Type)
---    is
---       Node : Node_Access := Key_Keys.Find (Container.Tree, Key);
+      begin
+         if Node = null then
+            raise Constraint_Error;
+         end if;
 
---    begin
---       if Node = null then
---          raise Constraint_Error;
---       end if;
+         Replace_Element (Container.Tree, Node, New_Item);
+      end Replace;
 
---        Replace_Element (Container, Node, New_Item);
---     end Replace;
+      -----------------------------------
+      -- Update_Element_Preserving_Key --
+      -----------------------------------
+
+      procedure Update_Element_Preserving_Key
+        (Container : in out Set;
+         Position  : Cursor;
+         Process   : not null access procedure (Element : in out Element_Type))
+      is
+         Tree : Tree_Type renames Container.Tree;
+
+      begin
+         if Position.Node = null then
+            raise Constraint_Error;
+         end if;
+
+         if Position.Container /= Container'Unrestricted_Access then
+            raise Program_Error;
+         end if;
+
+         declare
+            E : Element_Type renames Position.Node.Element;
+            K : Key_Type renames Key (E);
+
+            B : Natural renames Tree.Busy;
+            L : Natural renames Tree.Lock;
+
+         begin
+            B := B + 1;
+            L := L + 1;
+
+            begin
+               Process (E);
+            exception
+               when others =>
+                  L := L - 1;
+                  B := B - 1;
+                  raise;
+            end;
+
+            L := L - 1;
+            B := B - 1;
+
+            if K < E
+              or else K > E
+            then
+               null;
+            else
+               return;
+            end if;
+         end;
+
+         declare
+            X : Node_Access := Position.Node;
+         begin
+            Tree_Operations.Delete_Node_Sans_Free (Tree, X);
+            Free (X);
+         end;
+
+         raise Program_Error;
+      end Update_Element_Preserving_Key;
 
    end Generic_Keys;
 
@@ -824,6 +754,10 @@ package body Ada.Containers.Ordered_Sets is
       Insert (Container, New_Item, Position, Inserted);
 
       if not Inserted then
+         if Container.Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
+
          Position.Node.Element := New_Item;
       end if;
    end Include;
@@ -871,14 +805,13 @@ package body Ada.Containers.Ordered_Sets is
          Position.Node,
          Inserted);
 
-      Position.Container := Container'Unchecked_Access;
+      Position.Container := Container'Unrestricted_Access;
    end Insert;
 
    procedure Insert
      (Container : in out Set;
       New_Item  : Element_Type)
    is
-
       Position : Cursor;
       Inserted : Boolean;
 
@@ -948,25 +881,14 @@ package body Ada.Containers.Ordered_Sets is
 
    procedure Intersection (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Intersection (Target.Tree, Source.Tree);
    end Intersection;
 
    function Intersection (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Intersection (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Intersection (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Intersection;
 
    --------------
@@ -975,7 +897,7 @@ package body Ada.Containers.Ordered_Sets is
 
    function Is_Empty (Container : Set) return Boolean is
    begin
-      return Length (Container) = 0;
+      return Container.Tree.Length = 0;
    end Is_Empty;
 
    ------------------------
@@ -1028,10 +950,6 @@ package body Ada.Containers.Ordered_Sets is
 
    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
    begin
-      if Subset'Address = Of_Set'Address then
-         return True;
-      end if;
-
       return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
    end Is_Subset;
 
@@ -1055,13 +973,26 @@ package body Ada.Containers.Ordered_Sets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of prccessing for Iterate
 
    begin
-      Local_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Iterate;
 
    ----------
@@ -1074,7 +1005,7 @@ package body Ada.Containers.Ordered_Sets is
          return No_Element;
       end if;
 
-      return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
+      return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
    end Last;
 
    ------------------
@@ -1108,12 +1039,11 @@ package body Ada.Containers.Ordered_Sets is
    -- Move --
    ----------
 
+   procedure Move is
+      new Tree_Operations.Generic_Move (Clear);
+
    procedure Move (Target : in out Set; Source : in out Set) is
    begin
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Move (Target => Target.Tree, Source => Source.Tree);
    end Move;
 
@@ -1129,7 +1059,8 @@ package body Ada.Containers.Ordered_Sets is
 
       declare
          Node : constant Node_Access :=
-           Tree_Operations.Next (Position.Node);
+                  Tree_Operations.Next (Position.Node);
+
       begin
          if Node = null then
             return No_Element;
@@ -1150,10 +1081,6 @@ package body Ada.Containers.Ordered_Sets is
 
    function Overlap (Left, Right : Set) return Boolean is
    begin
-      if Left'Address = Right'Address then
-         return Left.Tree.Length /= 0;
-      end if;
-
       return Set_Ops.Overlap (Left.Tree, Right.Tree);
    end Overlap;
 
@@ -1202,8 +1129,29 @@ package body Ada.Containers.Ordered_Sets is
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type))
    is
+      E : Element_Type renames Position.Node.Element;
+
+      S : Set renames Position.Container.all;
+      T : Tree_Type renames S.Tree'Unrestricted_Access.all;
+
+      B : Natural renames T.Busy;
+      L : Natural renames T.Lock;
+
    begin
-      Process (Position.Node.Element);
+      B := B + 1;
+      L := L + 1;
+
+      begin
+         Process (E);
+      exception
+         when others =>
+            L := L - 1;
+            B := B - 1;
+            raise;
+      end;
+
+      L := L - 1;
+      B := B - 1;
    end Query_Element;
 
    ----------
@@ -1214,42 +1162,36 @@ package body Ada.Containers.Ordered_Sets is
      (Stream    : access Root_Stream_Type'Class;
       Container : out Set)
    is
-      N : Count_Type'Base;
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+      pragma Inline (Read_Node);
 
-      function New_Node return Node_Access;
-      pragma Inline (New_Node);
-
-      procedure Local_Read is new Tree_Operations.Generic_Read (New_Node);
+      procedure Read is
+         new Tree_Operations.Generic_Read (Clear, Read_Node);
 
-      --------------
-      -- New_Node --
-      --------------
+      ---------------
+      -- Read_Node --
+      ---------------
 
-      function New_Node return Node_Access is
+      function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access
+      is
          Node : Node_Access := new Node_Type;
 
       begin
-         begin
-            Element_Type'Read (Stream, Node.Element);
-
-         exception
-            when others =>
-               Free (Node);
-               raise;
-         end;
-
+         Element_Type'Read (Stream, Node.Element);
          return Node;
-      end New_Node;
+
+      exception
+         when others =>
+            Free (Node);
+            raise;
+      end Read_Node;
 
    --  Start of processing for Read
 
    begin
-      Clear (Container);
-
-      Count_Type'Base'Read (Stream, N);
-      pragma Assert (N >= 0);
-
-      Local_Read (Container.Tree, N);
+      Read (Stream, Container.Tree);
    end Read;
 
    -------------
@@ -1265,6 +1207,10 @@ package body Ada.Containers.Ordered_Sets is
          raise Constraint_Error;
       end if;
 
+      if Container.Tree.Lock > 0 then
+         raise Program_Error;
+      end if;
+
       Node.Element := New_Item;
    end Replace;
 
@@ -1272,95 +1218,124 @@ package body Ada.Containers.Ordered_Sets is
    -- Replace_Element --
    ---------------------
 
---  TODO: ???
---     procedure Replace_Element
---       (Container : in out Set;
---        Position  : Node_Access;
---        By        : Element_Type)
---     is
---        Node : Node_Access := Position;
-
---     begin
---        if By < Node.Element
---          or else Node.Element < By
---        then
---           null;
-
---        else
---           begin
---              Node.Element := By;
-
---           exception
---              when others =>
---                 Delete_Node_Sans_Free (Container.Tree, Node);
---                 Free (Node);
---                 raise;
---           end;
-
---           return;
---        end if;
-
---        Delete_Node_Sans_Free (Container.Tree, Node);
-
---        begin
---           Node.Element := By;
---        exception
---           when others =>
---              Free (Node);
---              raise;
---        end;
-
---        declare
---           function New_Node return Node_Access;
---           pragma Inline (New_Node);
-
---           function New_Node return Node_Access is
---           begin
---              return Node;
---           end New_Node;
-
---           procedure Insert_Post is
---              new Element_Keys.Generic_Insert_Post (New_Node);
-
---           procedure Insert is
---              new Element_Keys.Generic_Conditional_Insert (Insert_Post);
-
---           Result  : Node_Access;
---           Success : Boolean;
-
---        begin
---           Insert
---             (Tree    => Container.Tree,
---              Key     => Node.Element,
---              Node    => Result,
---              Success => Success);
-
---           if not Success then
---              Free (Node);
---              raise Program_Error;
---           end if;
-
---           pragma Assert (Result = Node);
---        end;
---     end Replace_Element;
-
-
---     procedure Replace_Element
---       (Container : in out Set;
---        Position  : Cursor;
---        By        : Element_Type)
---     is
---     begin
---        if Position.Container = null then
---           raise Constraint_Error;
---        end if;
-
---        if Position.Container /= Set_Access'(Container'Unchecked_Access) then
---           raise Program_Error;
---        end if;
-
---        Replace_Element (Container, Position.Node, By);
---     end Replace_Element;
+   procedure Replace_Element
+     (Tree : in out Tree_Type;
+      Node : Node_Access;
+      Item : Element_Type)
+   is
+   begin
+      if Item < Node.Element
+        or else Node.Element < Item
+      then
+         null;
+      else
+         if Tree.Lock > 0 then
+            raise Program_Error;
+         end if;
+
+         Node.Element := Item;
+         return;
+      end if;
+
+      Tree_Operations.Delete_Node_Sans_Free (Tree, Node);  -- Checks busy-bit
+
+      Insert_New_Item : declare
+         function New_Node return Node_Access;
+         pragma Inline (New_Node);
+
+         procedure Insert_Post is
+            new Element_Keys.Generic_Insert_Post (New_Node);
+
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (Insert_Post);
+
+         --------------
+         -- New_Node --
+         --------------
+
+         function New_Node return Node_Access is
+         begin
+            Node.Element := Item;
+            return Node;
+         end New_Node;
+
+         Result   : Node_Access;
+         Inserted : Boolean;
+
+      --  Start of processing for Insert_New_Item
+
+      begin
+         Insert
+           (Tree    => Tree,
+            Key     => Item,
+            Node    => Result,
+            Success => Inserted);  --  TODO: change param name
+
+         if Inserted then
+            pragma Assert (Result = Node);
+            return;
+         end if;
+      exception
+         when others =>
+            null;  -- Assignment must have failed
+      end Insert_New_Item;
+
+      Reinsert_Old_Element : declare
+         function New_Node return Node_Access;
+         pragma Inline (New_Node);
+
+         procedure Insert_Post is
+            new Element_Keys.Generic_Insert_Post (New_Node);
+
+         procedure Insert is
+            new Element_Keys.Generic_Conditional_Insert (Insert_Post);
+
+         --------------
+         -- New_Node --
+         --------------
+
+         function New_Node return Node_Access is
+         begin
+            return Node;
+         end New_Node;
+
+         Result   : Node_Access;
+         Inserted : Boolean;
+
+      --  Start of processing for Reinsert_Old_Element
+
+      begin
+         Insert
+           (Tree    => Tree,
+            Key     => Node.Element,
+            Node    => Result,
+            Success => Inserted);  --  TODO: change param name
+      exception
+         when others =>
+            null;  -- Assignment must have failed
+      end Reinsert_Old_Element;
+
+      raise Program_Error;
+   end Replace_Element;
+
+   procedure Replace_Element
+     (Container : Set;
+      Position  : Cursor;
+      By        : Element_Type)
+   is
+      Tree : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+
+   begin
+      if Position.Node = null then
+         raise Constraint_Error;
+      end if;
+
+      if Position.Container /= Container'Unrestricted_Access then
+         raise Program_Error;
+      end if;
+
+      Replace_Element (Tree, Position.Node, By);
+   end Replace_Element;
 
    ---------------------
    -- Reverse_Iterate --
@@ -1382,13 +1357,26 @@ package body Ada.Containers.Ordered_Sets is
 
       procedure Process_Node (Node : Node_Access) is
       begin
-         Process (Cursor'(Container'Unchecked_Access, Node));
+         Process (Cursor'(Container'Unrestricted_Access, Node));
       end Process_Node;
 
+      T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
+      B : Natural renames T.Busy;
+
    --  Start of processing for Reverse_Iterate
 
    begin
-      Local_Reverse_Iterate (Container.Tree);
+      B := B + 1;
+
+      begin
+         Local_Reverse_Iterate (T);
+      exception
+         when others =>
+            B := B - 1;
+            raise;
+      end;
+
+      B := B - 1;
    end Reverse_Iterate;
 
    -----------
@@ -1442,26 +1430,14 @@ package body Ada.Containers.Ordered_Sets is
 
    procedure Symmetric_Difference (Target : in out Set; Source : Set) is
    begin
-      if Target'Address = Source'Address then
-         Clear (Target);
-         return;
-      end if;
-
       Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
    end Symmetric_Difference;
 
    function Symmetric_Difference (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Empty_Set;
-      end if;
-
-      declare
-         Tree : constant Tree_Type :=
-                  Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Symmetric_Difference;
 
    -----------
@@ -1470,25 +1446,14 @@ package body Ada.Containers.Ordered_Sets is
 
    procedure Union (Target : in out Set; Source : Set) is
    begin
-
-      if Target'Address = Source'Address then
-         return;
-      end if;
-
       Set_Ops.Union (Target.Tree, Source.Tree);
    end Union;
 
    function Union (Left, Right : Set) return Set is
+      Tree : constant Tree_Type :=
+               Set_Ops.Union (Left.Tree, Right.Tree);
    begin
-      if Left'Address = Right'Address then
-         return Left;
-      end if;
-
-      declare
-         Tree : constant Tree_Type := Set_Ops.Union (Left.Tree, Right.Tree);
-      begin
-         return (Controlled with Tree);
-      end;
+      return Set'(Controlled with Tree);
    end Union;
 
    -----------
@@ -1499,31 +1464,30 @@ package body Ada.Containers.Ordered_Sets is
      (Stream    : access Root_Stream_Type'Class;
       Container : Set)
    is
-      procedure Process (Node : Node_Access);
-      pragma Inline (Process);
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+      pragma Inline (Write_Node);
 
-      procedure Iterate is
-        new Tree_Operations.Generic_Iteration (Process);
+      procedure Write is
+         new Tree_Operations.Generic_Write (Write_Node);
 
-      -------------
-      -- Process --
-      -------------
+      ----------------
+      -- Write_Node --
+      ----------------
 
-      procedure Process (Node : Node_Access) is
+      procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access)
+      is
       begin
          Element_Type'Write (Stream, Node.Element);
-      end Process;
+      end Write_Node;
 
    --  Start of processing for Write
 
    begin
-      Count_Type'Base'Write (Stream, Container.Tree.Length);
-      Iterate (Container.Tree);
+      Write (Stream, Container.Tree);
    end Write;
 
-
-
-
 end Ada.Containers.Ordered_Sets;
-
-
index 1dca837ccb68e6bb6ea37cade1064cfb9fa8791d..179949517134b072be554bad0c94ba45e6f1f07a 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                       ADA.CONTAINERS.ORDERED_SETS                        --
+--           A D A . C O N T A I N E R S . O R D E R E D _ S E T S          --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -57,6 +57,8 @@ pragma Preelaborate (Ordered_Sets);
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -69,11 +71,10 @@ pragma Preelaborate (Ordered_Sets);
      (Position : Cursor;
       Process  : not null access procedure (Element : Element_Type));
 
---  TODO: resolve in Atlanta. ???
---   procedure Replace_Element
---     (Container : in out Set;
---      Position  : Cursor;
---      By        : Element_Type);
+   procedure Replace_Element
+     (Container : Set;  --  TODO: need ARG ruling
+      Position  : Cursor;
+      By        : Element_Type);
 
    procedure Move
      (Target : in out Set;
@@ -94,17 +95,13 @@ pragma Preelaborate (Ordered_Sets);
       New_Item  : Element_Type);
 
    procedure Replace
-     (Container : in out Set;
+     (Container : in out Set;  --  TODO: need ARG ruling
       New_Item  : Element_Type);
 
    procedure Delete
      (Container : in out Set;
       Item      : Element_Type);
 
-   procedure Exclude
-     (Container : in out Set;
-      Item      : Element_Type);
-
    procedure Delete
      (Container : in out Set;
       Position  : in out Cursor);
@@ -113,6 +110,10 @@ pragma Preelaborate (Ordered_Sets);
 
    procedure Delete_Last (Container : in out Set);
 
+   procedure Exclude
+     (Container : in out Set;
+      Item      : Element_Type);
+
    procedure Union (Target : in out Set; Source : Set);
 
    function Union (Left, Right : Set) return Set;
@@ -160,10 +161,10 @@ pragma Preelaborate (Ordered_Sets);
 
    function Next (Position : Cursor) return Cursor;
 
-   function Previous (Position : Cursor) return Cursor;
-
    procedure Next (Position : in out Cursor);
 
+   function Previous (Position : Cursor) return Cursor;
+
    procedure Previous (Position : in out Cursor);
 
    function Has_Element (Position : Cursor) return Boolean;
@@ -215,11 +216,10 @@ pragma Preelaborate (Ordered_Sets);
 
       function Element (Container : Set; Key : Key_Type) return Element_Type;
 
---  TODO: resolve in Atlanta ???
---      procedure Replace
---        (Container : in out Set;
---         Key       : Key_Type;
---         New_Item  : Element_Type);
+      procedure Replace
+        (Container : in out Set;  --  TODO: need ARG ruling
+         Key       : Key_Type;
+         New_Item  : Element_Type);
 
       procedure Delete (Container : in out Set; Key : Key_Type);
 
@@ -233,8 +233,7 @@ pragma Preelaborate (Ordered_Sets);
 
       function ">" (Left : Key_Type; Right : Cursor) return Boolean;
 
---  TODO: resolve name in Atlanta. Should name be just "Update_Element" ???
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : Cursor;
          Process   : not null access
@@ -247,21 +246,32 @@ private
    type Node_Type;
    type Node_Access is access Node_Type;
 
-   package Tree_Types is
-     new Red_Black_Trees.Generic_Tree_Types (Node_Access);
+   type Node_Type is limited record
+      Parent  : Node_Access;
+      Left    : Node_Access;
+      Right   : Node_Access;
+      Color   : Red_Black_Trees.Color_Type := Red_Black_Trees.Red;
+      Element : Element_Type;
+   end record;
 
-   use Tree_Types;
-   use Ada.Finalization;
+   package Tree_Types is new Red_Black_Trees.Generic_Tree_Types
+     (Node_Type,
+      Node_Access);
 
-   type Set is new Controlled with record
-      Tree : Tree_Type := (Length => 0, others => null);
+   type Set is new Ada.Finalization.Controlled with record
+      Tree : Tree_Types.Tree_Type;
    end record;
 
    procedure Adjust (Container : in out Set);
 
    procedure Finalize (Container : in out Set) renames Clear;
 
-   type Set_Access is access constant Set;
+   use Red_Black_Trees;
+   use Tree_Types;
+   use Ada.Finalization;
+
+   type Set_Access is access all Set;
+   for Set_Access'Storage_Size use 0;
 
    type Cursor is record
       Container : Set_Access;
@@ -285,6 +295,11 @@ private
    for Set'Read use Read;
 
    Empty_Set : constant Set :=
-                 (Controlled with Tree => (Length => 0, others => null));
+                 (Controlled with Tree => (First  => null,
+                                           Last   => null,
+                                           Root   => null,
+                                           Length => 0,
+                                           Busy   => 0,
+                                           Lock   => 0));
 
 end Ada.Containers.Ordered_Sets;
index fe20d457c49f9951bf9015e985c16e17ad2ecf56..abf9fa680eac7df75a70b0ce3730eeaa4e4e256c 100644 (file)
@@ -2,15 +2,35 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                      ADA.CONTAINERS.RED_BLACK_TREES                      --
+--       A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S        --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
--- This specification is adapted from the Ada Reference Manual for use with --
--- GNAT.  In accordance with the copyright of that document, you can freely --
--- copy and modify this specification,  provided that if you redistribute a --
--- modified version,  any changes that you have made are clearly indicated. --
+--          Copyright (C) 2004-2005 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 Ada.Containers.Red_Black_Trees is
@@ -19,13 +39,17 @@ pragma Pure (Red_Black_Trees);
    type Color_Type is (Red, Black);
 
    generic
-      type Node_Access is private;
+      type Node_Type (<>) is limited private;
+      type Node_Access is access Node_Type;
    package Generic_Tree_Types is
-      type Tree_Type is record
+      type Tree_Type is tagged record
          First  : Node_Access;
          Last   : Node_Access;
          Root   : Node_Access;
-         Length : Count_Type;
+         Length : Count_Type := 0;
+         Busy   : Natural := 0;
+         Lock   : Natural := 0;
       end record;
    end Generic_Tree_Types;
+
 end Ada.Containers.Red_Black_Trees;
index 70c8f35278c6a92fdae74e27949a255f60da281f..5efd4cdbb101550c0e1a1e913edf897ee0644f0a 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---               ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_KEYS                --
+--        A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S .     --
+--                          G E N E R I C _ K E Y S                         --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -48,7 +49,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       X : Node_Access := Tree.Root;
 
    begin
-      while X /= Ops.Null_Node loop
+      while X /= null loop
          if Is_Greater_Key_Node (Key, X) then
             X := Ops.Right (X);
          else
@@ -69,7 +70,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       X : Node_Access := Tree.Root;
 
    begin
-      while X /= Ops.Null_Node loop
+      while X /= null loop
          if Is_Greater_Key_Node (Key, X) then
             X := Ops.Right (X);
          else
@@ -78,12 +79,12 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
          end if;
       end loop;
 
-      if Y = Ops.Null_Node then
-         return Ops.Null_Node;
+      if Y = null then
+         return null;
       end if;
 
       if Is_Less_Key_Node (Key, Y) then
-         return Ops.Null_Node;
+         return null;
       end if;
 
       return Y;
@@ -98,7 +99,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       X : Node_Access := Tree.Root;
 
    begin
-      while X /= Ops.Null_Node loop
+      while X /= null loop
          if Is_Less_Key_Node (Key, X) then
             X := Ops.Left (X);
          else
@@ -120,12 +121,12 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       Node    : out Node_Access;
       Success : out Boolean)
    is
-      Y : Node_Access := Ops.Null_Node;
+      Y : Node_Access := null;
       X : Node_Access := Tree.Root;
 
    begin
       Success := True;
-      while X /= Ops.Null_Node loop
+      while X /= null loop
          Y := X;
          Success := Is_Less_Key_Node (Key, X);
 
@@ -168,11 +169,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       Success  : out Boolean)
    is
    begin
-      if Position = Ops.Null_Node then  -- largest
+      if Position = null 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);
+            Insert_Post (Tree, null, Tree.Last, Key, Node);
             Success := True;
          else
             Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
@@ -195,8 +196,8 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
 
          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);
+               if Ops.Right (Before) = null then
+                  Insert_Post (Tree, null, Before, Key, Node);
                else
                   Insert_Post (Tree, Position, Position, Key, Node);
                end if;
@@ -213,7 +214,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
 
       if Is_Greater_Key_Node (Key, Position) then
          if Position = Tree.Last then
-            Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
+            Insert_Post (Tree, null, Tree.Last, Key, Node);
             Success := True;
             return;
          end if;
@@ -223,8 +224,8 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
 
          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);
+               if Ops.Right (Position) = null then
+                  Insert_Post (Tree, null, Position, Key, Node);
                else
                   Insert_Post (Tree, After, After, Key, Node);
                end if;
@@ -258,26 +259,30 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       New_Length : constant Count_Type := Length_Subtype'(Tree.Length) + 1;
 
    begin
-      if Y = Ops.Null_Node
-        or else X /= Ops.Null_Node
+      if Tree.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      if Y = null
+        or else X /= null
         or else Is_Less_Key_Node (Key, Y)
       then
-         pragma Assert (Y = Ops.Null_Node
-                          or else Ops.Left (Y) = Ops.Null_Node);
+         pragma Assert (Y = null
+                          or else Ops.Left (Y) = null);
 
          --  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 (Z /= null);
          pragma Assert (Ops.Color (Z) = Red);
 
-         if Y = Ops.Null_Node then
+         if Y = null 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);
+            pragma Assert (Tree.Root = null);
+            pragma Assert (Tree.First = null);
+            pragma Assert (Tree.Last = null);
 
             Tree.Root := Z;
             Tree.First := Z;
@@ -292,14 +297,14 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
          end if;
 
       else
-         pragma Assert (Ops.Right (Y) = Ops.Null_Node);
+         pragma Assert (Ops.Right (Y) = null);
 
          --  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 (Z /= null);
          pragma Assert (Ops.Color (Z) = Red);
 
          Ops.Set_Right (Y, Z);
@@ -331,7 +336,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       procedure Iterate (Node : Node_Access) is
          N : Node_Access := Node;
       begin
-         while N /= Ops.Null_Node loop
+         while N /= null loop
             if Is_Less_Key_Node (Key, N) then
                N := Ops.Left (N);
             elsif Is_Greater_Key_Node (Key, N) then
@@ -367,7 +372,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       procedure Iterate (Node : Node_Access) is
          N : Node_Access := Node;
       begin
-         while N /= Ops.Null_Node loop
+         while N /= null loop
             if Is_Less_Key_Node (Key, N) then
                N := Ops.Left (N);
             elsif Is_Greater_Key_Node (Key, N) then
@@ -395,11 +400,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       Key  : Key_Type;
       Node : out Node_Access)
    is
-      Y : Node_Access := Ops.Null_Node;
+      Y : Node_Access := null;
       X : Node_Access := Tree.Root;
 
    begin
-      while X /= Ops.Null_Node loop
+      while X /= null loop
          Y := X;
 
          if Is_Less_Key_Node (Key, X) then
@@ -431,11 +436,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       --  inserted last in the sequence of equivalent items.) ???
 
    begin
-      if Hint = Ops.Null_Node then  -- largest
+      if Hint = null 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);
+            Insert_Post (Tree, null, Tree.Last, Key, Node);
          else
             Unconditional_Insert_Sans_Hint (Tree, Key, Node);
          end if;
@@ -455,8 +460,8 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
             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);
+               if Ops.Right (Before) = null then
+                  Insert_Post (Tree, null, Before, Key, Node);
                else
                   Insert_Post (Tree, Hint, Hint, Key, Node);
                end if;
@@ -470,7 +475,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
 
       if Is_Greater_Key_Node (Key, Hint) then
          if Hint = Tree.Last then
-            Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
+            Insert_Post (Tree, null, Tree.Last, Key, Node);
             return;
          end if;
 
@@ -478,8 +483,8 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
             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);
+               if Ops.Right (Hint) = null then
+                  Insert_Post (Tree, null, Hint, Key, Node);
                else
                   Insert_Post (Tree, After, After, Key, Node);
                end if;
@@ -506,7 +511,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
       X : Node_Access := Tree.Root;
 
    begin
-      while X /= Ops.Null_Node loop
+      while X /= null loop
          if Is_Less_Key_Node (Key, X) then
             Y := X;
             X := Ops.Left (X);
@@ -519,5 +524,3 @@ package body Ada.Containers.Red_Black_Trees.Generic_Keys is
    end Upper_Bound;
 
 end Ada.Containers.Red_Black_Trees.Generic_Keys;
-
-
index 445c28b1c9df0d987285fd6b3d5877bcc748044f..d20d7004da9005d05dfb691c4b0803e45aed23ed 100644 (file)
@@ -2,7 +2,8 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---               ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_KEYS                --
+--        A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S .     --
+--                          G E N E R I C _ K E Y S                         --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
@@ -133,6 +134,3 @@ pragma Pure (Generic_Keys);
       Key  : Key_Type);
 
 end Ada.Containers.Red_Black_Trees.Generic_Keys;
-
-
-
index 9f9b7125c6f700056c3edfd5035bbc0b2910f97f..dc82e55b02a8931d80e36b8c509db5c48788f065 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---            ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_OPERATIONS             --
+--        A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S .     --
+--                    G E N E R I C _ O P E R A T I O N S                   --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -33,6 +34,8 @@
 -- This unit was originally developed by Matthew J Heaney.                  --
 ------------------------------------------------------------------------------
 
+with System;  use type System.Address;
+
 package body Ada.Containers.Red_Black_Trees.Generic_Operations is
 
    -----------------------
@@ -61,7 +64,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
 
       function Check (Node : Node_Access) return Natural is
       begin
-         if Node = Null_Node then
+         if Node = null then
             return 0;
          end if;
 
@@ -69,14 +72,14 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
             declare
                L : constant Node_Access := Left (Node);
             begin
-               pragma Assert (L = Null_Node or else Color (L) = Black);
+               pragma Assert (L = null or else Color (L) = Black);
                null;
             end;
 
             declare
                R : constant Node_Access := Right (Node);
             begin
-               pragma Assert (R = Null_Node or else Color (R) = Black);
+               pragma Assert (R = null or else Color (R) = Black);
                null;
             end;
 
@@ -101,24 +104,24 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
    --  Start of processing for Check_Invariant
 
    begin
-      if Root = Null_Node then
-         pragma Assert (Tree.First = Null_Node);
-         pragma Assert (Tree.Last = Null_Node);
+      if Root = null then
+         pragma Assert (Tree.First = null);
+         pragma Assert (Tree.Last = null);
          pragma Assert (Tree.Length = 0);
          null;
 
       else
          pragma Assert (Color (Root) = Black);
          pragma Assert (Tree.Length > 0);
-         pragma Assert (Tree.Root /= Null_Node);
-         pragma Assert (Tree.First /= Null_Node);
-         pragma Assert (Tree.Last /= Null_Node);
-         pragma Assert (Parent (Tree.Root) = Null_Node);
+         pragma Assert (Tree.Root /= null);
+         pragma Assert (Tree.First /= null);
+         pragma Assert (Tree.Last /= null);
+         pragma Assert (Parent (Tree.Root) = null);
          pragma Assert ((Tree.Length > 1)
                            or else (Tree.First = Tree.Last
                                       and Tree.First = Tree.Root));
-         pragma Assert (Left (Tree.First) = Null_Node);
-         pragma Assert (Right (Tree.Last) = Null_Node);
+         pragma Assert (Left (Tree.First) = null);
+         pragma Assert (Right (Tree.Last) = null);
 
          declare
             L  : constant Node_Access := Left (Root);
@@ -157,18 +160,18 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
                W := Right (Parent (X));
             end if;
 
-            if (Left (W)  = Null_Node or else Color (Left (W)) = Black)
+            if (Left (W)  = null or else Color (Left (W)) = Black)
               and then
-               (Right (W) = Null_Node or else Color (Right (W)) = Black)
+               (Right (W) = null or else Color (Right (W)) = Black)
             then
                Set_Color (W, Red);
                X := Parent (X);
 
             else
-               if Right (W) = Null_Node
+               if Right (W) = null
                  or else Color (Right (W)) = Black
                then
-                  if Left (W) /= Null_Node then
+                  if Left (W) /= null then
                      Set_Color (Left (W), Black);
                   end if;
 
@@ -196,16 +199,16 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
                W := Left (Parent (X));
             end if;
 
-            if (Left (W)  = Null_Node or else Color (Left (W)) = Black)
+            if (Left (W)  = null or else Color (Left (W)) = Black)
                   and then
-               (Right (W) = Null_Node or else Color (Right (W)) = Black)
+               (Right (W) = null or else Color (Right (W)) = Black)
             then
                Set_Color (W, Red);
                X := Parent (X);
 
             else
-               if Left (W) = Null_Node or else Color (Left (W)) = Black then
-                  if Right (W) /= Null_Node then
+               if Left (W) = null or else Color (Left (W)) = Black then
+                  if Right (W) /= null then
                      Set_Color (Right (W), Black);
                   end if;
 
@@ -239,28 +242,32 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       X, Y : Node_Access;
 
       Z : constant Node_Access := Node;
-      pragma Assert (Z /= Null_Node);
+      pragma Assert (Z /= null);
 
    begin
+      if Tree.Busy > 0 then
+         raise Program_Error;
+      end if;
+
       pragma Assert (Tree.Length > 0);
-      pragma Assert (Tree.Root /= Null_Node);
-      pragma Assert (Tree.First /= Null_Node);
-      pragma Assert (Tree.Last /= Null_Node);
-      pragma Assert (Parent (Tree.Root) = Null_Node);
+      pragma Assert (Tree.Root /= null);
+      pragma Assert (Tree.First /= null);
+      pragma Assert (Tree.Last /= null);
+      pragma Assert (Parent (Tree.Root) = null);
       pragma Assert ((Tree.Length > 1)
                         or else (Tree.First = Tree.Last
                                    and then Tree.First = Tree.Root));
-      pragma Assert ((Left (Node) = Null_Node)
+      pragma Assert ((Left (Node) = null)
                         or else (Parent (Left (Node)) = Node));
-      pragma Assert ((Right (Node) = Null_Node)
+      pragma Assert ((Right (Node) = null)
                         or else (Parent (Right (Node)) = Node));
-      pragma Assert (((Parent (Node) = Null_Node) and then (Tree.Root = Node))
-                        or else ((Parent (Node) /= Null_Node) and then
+      pragma Assert (((Parent (Node) = null) and then (Tree.Root = Node))
+                        or else ((Parent (Node) /= null) and then
                                   ((Left (Parent (Node)) = Node)
                                      or else (Right (Parent (Node)) = Node))));
 
-      if Left (Z) = Null_Node then
-         if Right (Z) = Null_Node then
+      if Left (Z) = null then
+         if Right (Z) = null then
             if Z = Tree.First then
                Tree.First := Parent (Z);
             end if;
@@ -273,18 +280,18 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
                Delete_Fixup (Tree, Z);
             end if;
 
-            pragma Assert (Left (Z) = Null_Node);
-            pragma Assert (Right (Z) = Null_Node);
+            pragma Assert (Left (Z) = null);
+            pragma Assert (Right (Z) = null);
 
             if Z = Tree.Root then
                pragma Assert (Tree.Length = 1);
-               pragma Assert (Parent (Z) = Null_Node);
-               Tree.Root := Null_Node;
+               pragma Assert (Parent (Z) = null);
+               Tree.Root := null;
             elsif Z = Left (Parent (Z)) then
-               Set_Left (Parent (Z), Null_Node);
+               Set_Left (Parent (Z), null);
             else
                pragma Assert (Z = Right (Parent (Z)));
-               Set_Right (Parent (Z), Null_Node);
+               Set_Right (Parent (Z), null);
             end if;
 
          else
@@ -312,7 +319,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
             end if;
          end if;
 
-      elsif Right (Z) = Null_Node then
+      elsif Right (Z) = null then
          pragma Assert (Z /= Tree.First);
 
          X := Left (Z);
@@ -341,11 +348,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
          pragma Assert (Z /= Tree.Last);
 
          Y := Next (Z);
-         pragma Assert (Left (Y) = Null_Node);
+         pragma Assert (Left (Y) = null);
 
          X := Right (Y);
 
-         if X = Null_Node then
+         if X = null then
             if Y = Left (Parent (Y)) then
                pragma Assert (Parent (Y) /= Z);
                Delete_Swap (Tree, Z, Y);
@@ -369,8 +376,8 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
                Set_Parent (Left (Y), Y);
                Set_Right (Y, Z);
                Set_Parent (Z, Y);
-               Set_Left (Z, Null_Node);
-               Set_Right (Z, Null_Node);
+               Set_Left (Z, null);
+               Set_Right (Z, null);
 
                declare
                   Y_Color : constant Color_Type := Color (Y);
@@ -384,14 +391,14 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
                Delete_Fixup (Tree, Z);
             end if;
 
-            pragma Assert (Left (Z) = Null_Node);
-            pragma Assert (Right (Z) = Null_Node);
+            pragma Assert (Left (Z) = null);
+            pragma Assert (Right (Z) = null);
 
             if Z = Right (Parent (Z)) then
-               Set_Right (Parent (Z), Null_Node);
+               Set_Right (Parent (Z), null);
             else
                pragma Assert (Z = Left (Parent (Z)));
-               Set_Left (Parent (Z), Null_Node);
+               Set_Left (Parent (Z), null);
             end if;
 
          else
@@ -467,20 +474,137 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
          Set_Left (Parent (Y), Y);
       end if;
 
-      if Right (Y) /= Null_Node then
+      if Right (Y) /= null then
          Set_Parent (Right (Y), Y);
       end if;
 
-      if Left (Y) /= Null_Node then
+      if Left (Y) /= null then
          Set_Parent (Left (Y), Y);
       end if;
 
       Set_Parent (Z, Y_Parent);
       Set_Color (Z, Y_Color);
-      Set_Left (Z, Null_Node);
-      Set_Right (Z, Null_Node);
+      Set_Left (Z, null);
+      Set_Right (Z, null);
    end Delete_Swap;
 
+   --------------------
+   -- Generic_Adjust --
+   --------------------
+
+   procedure Generic_Adjust (Tree : in out Tree_Type) is
+      N    : constant Count_Type := Tree.Length;
+      Root : constant Node_Access := Tree.Root;
+
+   begin
+      if N = 0 then
+         pragma Assert (Root = null);
+         pragma Assert (Tree.Busy = 0);
+         pragma Assert (Tree.Lock = 0);
+         return;
+      end if;
+
+      Tree.Root := null;
+      Tree.First := null;
+      Tree.Last := null;
+      Tree.Length := 0;
+
+      Tree.Root := Copy_Tree (Root);
+      Tree.First := Min (Tree.Root);
+      Tree.Last := Max (Tree.Root);
+      Tree.Length := N;
+   end Generic_Adjust;
+
+   -------------------
+   -- Generic_Clear --
+   -------------------
+
+   procedure Generic_Clear (Tree : in out Tree_Type) is
+      Root : Node_Access := Tree.Root;
+   begin
+      if Tree.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      Tree := (First  => null,
+               Last   => null,
+               Root   => null,
+               Length => 0,
+               Busy   => 0,
+               Lock   => 0);
+
+      Delete_Tree (Root);
+   end Generic_Clear;
+
+   -----------------------
+   -- Generic_Copy_Tree --
+   -----------------------
+
+   function Generic_Copy_Tree (Source_Root : Node_Access) return Node_Access is
+      Target_Root : Node_Access := Copy_Node (Source_Root);
+      P, X        : Node_Access;
+
+   begin
+
+      if Right (Source_Root) /= null then
+         Set_Right
+           (Node  => Target_Root,
+            Right => Generic_Copy_Tree (Right (Source_Root)));
+
+         Set_Parent
+           (Node   => Right (Target_Root),
+            Parent => Target_Root);
+      end if;
+
+      P := Target_Root;
+
+      X := Left (Source_Root);
+      while X /= null loop
+         declare
+            Y : constant Node_Access := Copy_Node (X);
+         begin
+            Set_Left (Node => P, Left => Y);
+            Set_Parent (Node => Y, Parent => P);
+
+            if Right (X) /= null then
+               Set_Right
+                 (Node  => Y,
+                  Right => Generic_Copy_Tree (Right (X)));
+
+               Set_Parent
+                 (Node   => Right (Y),
+                  Parent => Y);
+            end if;
+
+            P := Y;
+            X := Left (X);
+         end;
+      end loop;
+
+      return Target_Root;
+   exception
+      when others =>
+         Delete_Tree (Target_Root);
+         raise;
+
+   end Generic_Copy_Tree;
+
+   -------------------------
+   -- Generic_Delete_Tree --
+   -------------------------
+
+   procedure Generic_Delete_Tree (X : in out Node_Access) is
+      Y : Node_Access;
+   begin
+      while X /= null loop
+         Y := Right (X);
+         Generic_Delete_Tree (Y);
+         Y := Left (X);
+         Free (X);
+         X := Y;
+      end loop;
+   end Generic_Delete_Tree;
+
    -------------------
    -- Generic_Equal --
    -------------------
@@ -490,13 +614,17 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       R_Node : Node_Access;
 
    begin
+      if Left'Address = Right'Address then
+         return True;
+      end if;
+
       if Left.Length /= Right.Length then
          return False;
       end if;
 
       L_Node := Left.First;
       R_Node := Right.First;
-      while L_Node /= Null_Node loop
+      while L_Node /= null loop
          if not Is_Equal (L_Node, R_Node) then
             return False;
          end if;
@@ -522,7 +650,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       procedure Iterate (P : Node_Access) is
          X : Node_Access := P;
       begin
-         while X /= Null_Node loop
+         while X /= null loop
             Iterate (Left (X));
             Process (X);
             X := Right (X);
@@ -536,23 +664,55 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
    end Generic_Iteration;
 
    ------------------
-   -- Generic_Read --
+   -- Generic_Move --
    ------------------
 
-   procedure Generic_Read (Tree : in out Tree_Type; N : Count_Type) is
+   procedure Generic_Move (Target, Source : in out Tree_Type) is
+   begin
+      if Target'Address = Source'Address then
+         return;
+      end if;
 
-      pragma Assert (Tree.Length = 0);
-      --  Clear and back node reinit was done by caller
+      if Source.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      Clear (Target);
+
+      Target := Source;
+
+      Source := (First  => null,
+                 Last   => null,
+                 Root   => null,
+                 Length => 0,
+                 Busy   => 0,
+                 Lock   => 0);
+   end Generic_Move;
+
+   ------------------
+   -- Generic_Read --
+   ------------------
+
+   procedure Generic_Read
+     (Stream : access Root_Stream_Type'Class;
+      Tree   : in out Tree_Type)
+   is
+      N : Count_Type'Base;
 
       Node, Last_Node : Node_Access;
 
    begin
+      Clear (Tree);
+
+      Count_Type'Base'Read (Stream, N);
+      pragma Assert (N >= 0);
+
       if N = 0 then
          return;
       end if;
 
-      Node := New_Node;
-      pragma Assert (Node /= Null_Node);
+      Node := Read_Node (Stream);
+      pragma Assert (Node /= null);
       pragma Assert (Color (Node) = Red);
 
       Set_Color (Node, Black);
@@ -567,8 +727,8 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
          Last_Node := Node;
          pragma Assert (Last_Node = Tree.Last);
 
-         Node := New_Node;
-         pragma Assert (Node /= Null_Node);
+         Node := Read_Node (Stream);
+         pragma Assert (Node /= null);
          pragma Assert (Color (Node) = Red);
 
          Set_Right (Node => Last_Node, Right => Node);
@@ -594,7 +754,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       procedure Iterate (P : Node_Access) is
          X : Node_Access := P;
       begin
-         while X /= Null_Node loop
+         while X /= null loop
             Iterate (Right (X));
             Process (X);
             X := Left (X);
@@ -607,6 +767,36 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       Iterate (Tree.Root);
    end Generic_Reverse_Iteration;
 
+   -------------------
+   -- Generic_Write --
+   -------------------
+
+   procedure Generic_Write
+     (Stream : access Root_Stream_Type'Class;
+      Tree   : in     Tree_Type)
+   is
+      procedure Process (Node : Node_Access);
+      pragma Inline (Process);
+
+      procedure Iterate is
+         new Generic_Iteration (Process);
+
+      -------------
+      -- Process --
+      -------------
+
+      procedure Process (Node : Node_Access) is
+      begin
+         Write_Node (Stream, Node);
+      end Process;
+
+   --  Start of processing for Generic_Write
+
+   begin
+      Count_Type'Base'Write (Stream, Tree.Length);
+      Iterate (Tree);
+   end Generic_Write;
+
    -----------------
    -- Left_Rotate --
    -----------------
@@ -616,12 +806,12 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       --  CLR p266 ???
 
       Y : constant Node_Access := Right (X);
-      pragma Assert (Y /= Null_Node);
+      pragma Assert (Y /= null);
 
    begin
       Set_Right (X, Left (Y));
 
-      if Left (Y) /= Null_Node then
+      if Left (Y) /= null then
          Set_Parent (Left (Y), X);
       end if;
 
@@ -655,7 +845,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       loop
          Y := Right (X);
 
-         if Y = Null_Node then
+         if Y = null then
             return X;
          end if;
 
@@ -678,7 +868,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       loop
          Y := Left (X);
 
-         if Y = Null_Node then
+         if Y = null then
             return X;
          end if;
 
@@ -686,23 +876,6 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       end loop;
    end Min;
 
-   ----------
-   -- Move --
-   ----------
-
-   procedure Move (Target, Source : in out Tree_Type) is
-   begin
-      if Target.Length > 0 then
-         raise Constraint_Error;
-      end if;
-
-      Target := Source;
-      Source := (First => Null_Node,
-                 Last  => Null_Node,
-                 Root  => Null_Node,
-                 Length => 0);
-   end Move;
-
    ----------
    -- Next --
    ----------
@@ -711,11 +884,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
    begin
       --  CLR p249 ???
 
-      if Node = Null_Node then
-         return Null_Node;
+      if Node = null then
+         return null;
       end if;
 
-      if Right (Node) /= Null_Node then
+      if Right (Node) /= null then
          return Min (Right (Node));
       end if;
 
@@ -724,7 +897,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
          Y : Node_Access := Parent (Node);
 
       begin
-         while Y /= Null_Node
+         while Y /= null
            and then X = Right (Y)
          loop
             X := Y;
@@ -749,11 +922,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
 
    function Previous (Node : Node_Access) return Node_Access is
    begin
-      if Node = Null_Node then
-         return Null_Node;
+      if Node = null then
+         return null;
       end if;
 
-      if Left (Node) /= Null_Node then
+      if Left (Node) /= null then
          return Max (Left (Node));
       end if;
 
@@ -762,7 +935,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
          Y : Node_Access := Parent (Node);
 
       begin
-         while Y /= Null_Node
+         while Y /= null
            and then X = Left (Y)
          loop
             X := Y;
@@ -792,7 +965,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
       --  CLR p.268 ???
 
       X : Node_Access := Node;
-      pragma Assert (X /= Null_Node);
+      pragma Assert (X /= null);
       pragma Assert (Color (X) = Red);
 
       Y : Node_Access;
@@ -802,7 +975,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
          if Parent (X) = Left (Parent (Parent (X))) then
             Y := Right (Parent (Parent (X)));
 
-            if Y /= Null_Node and then Color (Y) = Red then
+            if Y /= null and then Color (Y) = Red then
                Set_Color (Parent (X), Black);
                Set_Color (Y, Black);
                Set_Color (Parent (Parent (X)), Red);
@@ -824,7 +997,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
 
             Y := Left (Parent (Parent (X)));
 
-            if Y /= Null_Node and then Color (Y) = Red then
+            if Y /= null and then Color (Y) = Red then
                Set_Color (Parent (X), Black);
                Set_Color (Y, Black);
                Set_Color (Parent (Parent (X)), Red);
@@ -852,12 +1025,12 @@ package body Ada.Containers.Red_Black_Trees.Generic_Operations is
 
    procedure Right_Rotate (Tree : in out Tree_Type; Y : Node_Access) is
       X : constant Node_Access := Left (Y);
-      pragma Assert (X /= Null_Node);
+      pragma Assert (X /= null);
 
    begin
       Set_Left (Y, Right (X));
 
-      if Right (X) /= Null_Node then
+      if Right (X) /= null then
          Set_Parent (Right (X), Y);
       end if;
 
index 3e13ae58e855a74e5210bfdb741fa723e65e6ff6..84ab26041456dd70e4aab269d235ccec7f61af85 100644 (file)
@@ -2,23 +2,44 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---            ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_OPERATIONS             --
+--        A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S .     --
+--                    G E N E R I C _ O P E R A T I O N S                   --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
--- This specification is adapted from the Ada Reference Manual for use with --
--- GNAT.  In accordance with the copyright of that document, you can freely --
--- copy and modify this specification,  provided that if you redistribute a --
--- modified version,  any changes that you have made are clearly indicated. --
+--          Copyright (C) 2004-2005 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.                  --
 ------------------------------------------------------------------------------
 
+with Ada.Streams; use Ada.Streams;
+
 generic
    with package Tree_Types is new Generic_Tree_Types (<>);
    use Tree_Types;
 
-   Null_Node : Node_Access;
-
    with function  Parent (Node : Node_Access) return Node_Access is <>;
    with procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is <>;
    with function  Left (Node : Node_Access) return Node_Access is <>;
@@ -41,8 +62,6 @@ pragma Pure;
 
    function Previous (Node : Node_Access) return Node_Access;
 
-   procedure Move (Target, Source : in out Tree_Type);
-
    generic
       with function Is_Equal (L, R : Node_Access) return Boolean;
    function Generic_Equal (Left, Right : Tree_Type) return Boolean;
@@ -51,6 +70,27 @@ pragma Pure;
      (Tree : in out Tree_Type;
       Node : Node_Access);
 
+   generic
+      with procedure Free (X : in out Node_Access);
+   procedure Generic_Delete_Tree (X : in out Node_Access);
+
+   generic
+      with function Copy_Node (Source : Node_Access) return Node_Access;
+      with procedure Delete_Tree (X : in out Node_Access);
+   function Generic_Copy_Tree (Source_Root : Node_Access) return Node_Access;
+
+   generic
+      with function Copy_Tree (Root : Node_Access) return Node_Access;
+   procedure Generic_Adjust (Tree : in out Tree_Type);
+
+   generic
+      with procedure Delete_Tree (X : in out Node_Access);
+   procedure Generic_Clear (Tree : in out Tree_Type);
+
+   generic
+      with procedure Clear (Tree : in out Tree_Type);
+   procedure Generic_Move (Target, Source : in out Tree_Type);
+
    generic
       with procedure Process (Node : Node_Access) is <>;
    procedure Generic_Iteration (Tree : Tree_Type);
@@ -60,8 +100,20 @@ pragma Pure;
    procedure Generic_Reverse_Iteration (Tree : Tree_Type);
 
    generic
-      with function New_Node return Node_Access is <>;
-   procedure Generic_Read (Tree : in out Tree_Type; N : Count_Type);
+      with procedure Write_Node
+        (Stream : access Root_Stream_Type'Class;
+         Node   : Node_Access);
+   procedure Generic_Write
+     (Stream : access Root_Stream_Type'Class;
+      Tree   : Tree_Type);
+
+   generic
+      with procedure Clear (Tree : in out Tree_Type);
+      with function Read_Node
+        (Stream : access Root_Stream_Type'Class) return Node_Access;
+   procedure Generic_Read
+     (Stream : access Root_Stream_Type'Class;
+      Tree   : in out Tree_Type);
 
    procedure Rebalance_For_Insert
      (Tree : in out Tree_Type;
index d775234a9c333a1c31999232946a0d1d087bec5e..2c0b39fd245a7af622d1e6cccca24f2894646db7 100644 (file)
@@ -2,11 +2,12 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---          ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_SET_OPERATIONS           --
+--       A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S .      --
+--               G E N E R I C _ S E T _ O P E R A T I O N S                --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
 -- This unit was originally developed by Matthew J Heaney.                  --
 ------------------------------------------------------------------------------
 
+with System; use type System.Address;
+
 package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
 
+   -----------------------
+   -- Local Subprograms --
+   -----------------------
+
+   procedure Clear (Tree : in out Tree_Type);
+
+   function Copy (Source : Tree_Type) return Tree_Type;
+
+   -----------
+   -- Clear --
+   -----------
+
+   procedure Clear (Tree : in out Tree_Type) is
+      pragma Assert (Tree.Busy = 0);
+      pragma Assert (Tree.Lock = 0);
+
+      Root : Node_Access := Tree.Root;
+
+   begin
+      Tree.Root := null;
+      Tree.First := null;
+      Tree.Last := null;
+      Tree.Length := 0;
+
+      Delete_Tree (Root);
+   end Clear;
+
+   ----------
+   -- Copy --
+   ----------
+
+   function Copy (Source : Tree_Type) return Tree_Type is
+      Target : Tree_Type;
+
+   begin
+      if Source.Length = 0 then
+         return Target;
+      end if;
+
+      Target.Root := Copy_Tree (Source.Root);
+      Target.First := Tree_Operations.Min (Target.Root);
+      Target.Last := Tree_Operations.Max (Target.Root);
+      Target.Length := Source.Length;
+
+      return Target;
+   end Copy;
+
    ----------------
    -- Difference --
    ----------------
@@ -44,19 +94,29 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       Src : Node_Access := Source.First;
 
    begin
+      if Target'Address = Source'Address then
+         if Target.Busy > 0 then
+            raise Program_Error;
+         end if;
+
+         Clear (Target);
+         return;
+      end if;
+
+      if Source.Length = 0 then
+         return;
+      end if;
 
-      --  NOTE: must be done by client:
-      --      if Target'Address = Source'Address then
-      --         Clear (Target);
-      --         return;
-      --      end if;
+      if Target.Busy > 0 then
+         raise Program_Error;
+      end if;
 
       loop
-         if Tgt = Tree_Operations.Null_Node then
+         if Tgt = null then
             return;
          end if;
 
-         if Src = Tree_Operations.Null_Node then
+         if Src = null then
             return;
          end if;
 
@@ -81,7 +141,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
    end Difference;
 
    function Difference (Left, Right : Tree_Type) return Tree_Type is
-      Tree : Tree_Type := (Length => 0, others => Tree_Operations.Null_Node);
+      Tree : Tree_Type;
 
       L_Node : Node_Access := Left.First;
       R_Node : Node_Access := Right.First;
@@ -89,21 +149,28 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       Dst_Node : Node_Access;
 
    begin
-      --  NOTE: must by done by client:
-      --      if Left'Address = Right'Address then
-      --         return Empty_Set;
-      --      end if;
+      if Left'Address = Right'Address then
+         return Tree;  -- Empty set
+      end if;
+
+      if Left.Length = 0 then
+         return Tree;  -- Empty set
+      end if;
+
+      if Right.Length = 0 then
+         return Copy (Left);
+      end if;
 
       loop
-         if L_Node = Tree_Operations.Null_Node then
+         if L_Node = null then
             return Tree;
          end if;
 
-         if R_Node = Tree_Operations.Null_Node then
-            while L_Node /= Tree_Operations.Null_Node loop
+         if R_Node = null then
+            while L_Node /= null loop
                Insert_With_Hint
                  (Dst_Tree => Tree,
-                  Dst_Hint => Tree_Operations.Null_Node,
+                  Dst_Hint => null,
                   Src_Node => L_Node,
                   Dst_Node => Dst_Node);
 
@@ -117,7 +184,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
          if Is_Less (L_Node, R_Node) then
             Insert_With_Hint
               (Dst_Tree => Tree,
-               Dst_Hint => Tree_Operations.Null_Node,
+               Dst_Hint => null,
                Src_Node => L_Node,
                Dst_Node => Dst_Node);
 
@@ -150,13 +217,21 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       Src : Node_Access := Source.First;
 
    begin
-      --  NOTE: must be done by caller: ???
-      --      if Target'Address = Source'Address then
-      --         return;
-      --      end if;
+      if Target'Address = Source'Address then
+         return;
+      end if;
+
+      if Target.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      if Source.Length = 0 then
+         Clear (Target);
+         return;
+      end if;
 
-      while Tgt /= Tree_Operations.Null_Node
-        and then Src /= Tree_Operations.Null_Node
+      while Tgt /= null
+        and then Src /= null
       loop
          if Is_Less (Tgt, Src) then
             declare
@@ -175,10 +250,20 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
             Src := Tree_Operations.Next (Src);
          end if;
       end loop;
+
+      while Tgt /= null loop
+         declare
+            X : Node_Access := Tgt;
+         begin
+            Tgt := Tree_Operations.Next (Tgt);
+            Tree_Operations.Delete_Node_Sans_Free (Target, X);
+            Free (X);
+         end;
+      end loop;
    end Intersection;
 
    function Intersection (Left, Right : Tree_Type) return Tree_Type is
-      Tree : Tree_Type := (Length => 0, others => Tree_Operations.Null_Node);
+      Tree : Tree_Type;
 
       L_Node : Node_Access := Left.First;
       R_Node : Node_Access := Right.First;
@@ -186,17 +271,16 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       Dst_Node : Node_Access;
 
    begin
-      --  NOTE: must be done by caller: ???
-      --      if Left'Address = Right'Address then
-      --         return Left;
-      --      end if;
+      if Left'Address = Right'Address then
+         return Copy (Left);
+      end if;
 
       loop
-         if L_Node = Tree_Operations.Null_Node then
+         if L_Node = null then
             return Tree;
          end if;
 
-         if R_Node = Tree_Operations.Null_Node then
+         if R_Node = null then
             return Tree;
          end if;
 
@@ -209,7 +293,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
          else
             Insert_With_Hint
               (Dst_Tree => Tree,
-               Dst_Hint => Tree_Operations.Null_Node,
+               Dst_Hint => null,
                Src_Node => L_Node,
                Dst_Node => Dst_Node);
 
@@ -233,10 +317,9 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       Of_Set : Tree_Type) return Boolean
    is
    begin
-      --  NOTE: must by done by caller:
-      --      if Subset'Address = Of_Set'Address then
-      --         return True;
-      --      end if;
+      if Subset'Address = Of_Set'Address then
+         return True;
+      end if;
 
       if Subset.Length > Of_Set.Length then
          return False;
@@ -244,15 +327,15 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
 
       declare
          Subset_Node : Node_Access := Subset.First;
-         Set_Node : Node_Access := Of_Set.First;
+         Set_Node    : Node_Access := Of_Set.First;
 
       begin
          loop
-            if Set_Node = Tree_Operations.Null_Node then
-               return Subset_Node = Tree_Operations.Null_Node;
+            if Set_Node = null then
+               return Subset_Node = null;
             end if;
 
-            if Subset_Node = Tree_Operations.Null_Node then
+            if Subset_Node = null then
                return True;
             end if;
 
@@ -279,14 +362,13 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       R_Node : Node_Access := Right.First;
 
    begin
-      --  NOTE: must be done by caller: ???
-      --      if Left'Address = Right'Address then
-      --         return Left.Tree.Length /= 0;
-      --      end if;
+      if Left'Address = Right'Address then
+         return Left.Length /= 0;
+      end if;
 
       loop
-         if L_Node = Tree_Operations.Null_Node
-           or else R_Node = Tree_Operations.Null_Node
+         if L_Node = null
+           or else R_Node = null
          then
             return False;
          end if;
@@ -317,18 +399,21 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       New_Tgt_Node : Node_Access;
 
    begin
-      --  NOTE: must by done by client: ???
-      --      if Target'Address = Source'Address then
-      --         Clear (Target);
-      --         return;
-      --      end if;
+      if Target.Busy > 0 then
+         raise Program_Error;
+      end if;
+
+      if Target'Address = Source'Address then
+         Clear (Target);
+         return;
+      end if;
 
       loop
-         if Tgt = Tree_Operations.Null_Node then
-            while Src /= Tree_Operations.Null_Node loop
+         if Tgt = null then
+            while Src /= null loop
                Insert_With_Hint
                  (Dst_Tree => Target,
-                  Dst_Hint => Tree_Operations.Null_Node,
+                  Dst_Hint => null,
                   Src_Node => Src,
                   Dst_Node => New_Tgt_Node);
 
@@ -338,7 +423,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
             return;
          end if;
 
-         if Src = Tree_Operations.Null_Node then
+         if Src = null then
             return;
          end if;
 
@@ -369,7 +454,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
    end Symmetric_Difference;
 
    function Symmetric_Difference (Left, Right : Tree_Type) return Tree_Type is
-      Tree : Tree_Type := (Length => 0, others => Tree_Operations.Null_Node);
+      Tree : Tree_Type;
 
       L_Node : Node_Access := Left.First;
       R_Node : Node_Access := Right.First;
@@ -377,17 +462,24 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
       Dst_Node : Node_Access;
 
    begin
-      --  NOTE: must by done by caller ???
-      --      if Left'Address = Right'Address then
-      --         return Empty_Set;
-      --      end if;
+      if Left'Address = Right'Address then
+         return Tree;  -- Empty set
+      end if;
+
+      if Right.Length = 0 then
+         return Copy (Left);
+      end if;
+
+      if Left.Length = 0 then
+         return Copy (Right);
+      end if;
 
       loop
-         if L_Node = Tree_Operations.Null_Node then
-            while R_Node /= Tree_Operations.Null_Node loop
+         if L_Node = null then
+            while R_Node /= null loop
                Insert_With_Hint
                  (Dst_Tree => Tree,
-                  Dst_Hint => Tree_Operations.Null_Node,
+                  Dst_Hint => null,
                   Src_Node => R_Node,
                   Dst_Node => Dst_Node);
                R_Node := Tree_Operations.Next (R_Node);
@@ -396,11 +488,11 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
             return Tree;
          end if;
 
-         if R_Node = Tree_Operations.Null_Node then
-            while L_Node /= Tree_Operations.Null_Node loop
+         if R_Node = null then
+            while L_Node /= null loop
                Insert_With_Hint
                  (Dst_Tree => Tree,
-                  Dst_Hint => Tree_Operations.Null_Node,
+                  Dst_Hint => null,
                   Src_Node => L_Node,
                   Dst_Node => Dst_Node);
 
@@ -413,7 +505,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
          if Is_Less (L_Node, R_Node) then
             Insert_With_Hint
               (Dst_Tree => Tree,
-               Dst_Hint => Tree_Operations.Null_Node,
+               Dst_Hint => null,
                Src_Node => L_Node,
                Dst_Node => Dst_Node);
 
@@ -422,7 +514,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
          elsif Is_Less (R_Node, L_Node) then
             Insert_With_Hint
               (Dst_Tree => Tree,
-               Dst_Hint => Tree_Operations.Null_Node,
+               Dst_Hint => null,
                Src_Node => R_Node,
                Dst_Node => Dst_Node);
 
@@ -469,33 +561,34 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
    --  Start of processing for Union
 
    begin
-      --  NOTE: must be done by caller: ???
-      --      if Target'Address = Source'Address then
-      --         return;
-      --      end if;
+      if Target'Address = Source'Address then
+         return;
+      end if;
+
+      if Target.Busy > 0 then
+         raise Program_Error;
+      end if;
 
       Iterate (Source);
    end Union;
 
    function Union (Left, Right : Tree_Type) return Tree_Type is
-      Tree : Tree_Type;
-
    begin
-      --  NOTE: must be done by caller:
-      --      if Left'Address = Right'Address then
-      --         return Left;
-      --      end if;
+      if Left'Address = Right'Address then
+         return Copy (Left);
+      end if;
 
-      declare
-         Root : constant Node_Access := Copy_Tree (Left.Root);
-      begin
-         Tree := (Root   => Root,
-                  First  => Tree_Operations.Min (Root),
-                  Last   => Tree_Operations.Max (Root),
-                  Length => Left.Length);
-      end;
+      if Left.Length = 0 then
+         return Copy (Right);
+      end if;
+
+      if Right.Length = 0 then
+         return Copy (Left);
+      end if;
 
       declare
+         Tree : Tree_Type := Copy (Left);
+
          Hint : Node_Access;
 
          procedure Process (Node : Node_Access);
@@ -521,6 +614,7 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
 
       begin
          Iterate (Right);
+         return Tree;
 
       exception
          when others =>
@@ -528,7 +622,6 @@ package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
             raise;
       end;
 
-      return Tree;
    end Union;
 
 end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
index 1c6e78f7f682a20570746014db8bbdb8ce052000..95d893648e24420fd66b8185e4d0a99aa5c27230 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                    ADA.STRINGS.HASH_CASE_INSENSITIVE                     --
+--    A D A . S T R I N G S . H A S H _ C A S E _ I N S E N S I T I V E     --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -52,17 +52,8 @@ is
 begin
    Tmp := 0;
    for J in Key'Range loop
-      Tmp := Rotate_Left (Tmp, 1) + Character'Pos (To_Lower (Key (J)));
+      Tmp := Rotate_Left (Tmp, 3) + Character'Pos (To_Lower (Key (J)));
    end loop;
 
    return Tmp;
 end Ada.Strings.Hash_Case_Insensitive;
-
-
-
-
-
-
-
-
-
index 24bd62c597863188fc500a60b5c5c51a1c866d05..a6e083c1e472c6539ac5e0edad7266d3ebaa4077 100644 (file)
@@ -2,7 +2,7 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                    ADA.STRINGS.HASH_CASE_INSENSITIVE                     --
+--    A D A . S T R I N G S . H A S H _ C A S E _ I N S E N S I T I V E     --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
index 3dffb2006d92f3c7626a03c2e39969e69220bd0a..62c4610b93cec55b4b0fcb145d3f805577cf8737 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                             ADA.STRINGS.HASH                             --
+--                     A D A . S T R I N G S . H A S H                      --
 --                                                                          --
---                                 B o d y                                  --
+--                                B o d y                                   --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--           Copyright (C) 2004-2005 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 --
@@ -48,16 +48,8 @@ function Ada.Strings.Hash (Key : String) return Containers.Hash_Type is
 begin
    Tmp := 0;
    for J in Key'Range loop
-      Tmp := Rotate_Left (Tmp, 1) + Character'Pos (Key (J));
+      Tmp := Rotate_Left (Tmp, 3) + Character'Pos (Key (J));
    end loop;
 
    return Tmp;
 end Ada.Strings.Hash;
-
-
-
-
-
-
-
-
index a6b6920514e6517f2475e012ef3b369afa956b94..1f8d6bcf3e5d6f161b1bc09064fb8d0b77c6d5b0 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                        ADA.STRINGS.UNBOUNDED.HASH                        --
+--           A D A . S T R I N G S . U N B O U N D E D . H A S H            --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -50,7 +50,7 @@ is
 begin
    Tmp := 0;
    for J in 1 .. Key.Last loop
-      Tmp := Rotate_Left (Tmp, 1) + Character'Pos (Key.Reference (J));
+      Tmp := Rotate_Left (Tmp, 3) + Character'Pos (Key.Reference (J));
    end loop;
 
    return Tmp;
index f218b486cc3b287beb4ae4089cb5c7b00298f53f..17ccfb8e5bb1f94a39d263ef2f28bd197cbf0c5f 100644 (file)
@@ -2,11 +2,11 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                          ADA.STRINGS.WIDE_HASH                           --
+--                A D A . S T R I N G S . W I D E _ H A S H                 --
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---             Copyright (C) 2004 Free Software Foundation, Inc.            --
+--          Copyright (C) 2004-2005 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 --
@@ -50,10 +50,8 @@ is
 begin
    Tmp := 0;
    for J in Key'Range loop
-      Tmp := Rotate_Left (Tmp, 1) + Wide_Character'Pos (Key (J));
+      Tmp := Rotate_Left (Tmp, 3) + Wide_Character'Pos (Key (J));
    end loop;
 
    return Tmp;
 end Ada.Strings.Wide_Hash;
-
-
index 349b8919f1635e8c1b6c2a53a6b6f10a132ec6f2..3b0af1fc751ade8f1a655d84ea07e2658bc6319e 100644 (file)
@@ -2,7 +2,7 @@
 --                                                                          --
 --                         GNAT LIBRARY COMPONENTS                          --
 --                                                                          --
---                          ADA.STRINGS.WIDE_HASH                           --
+--                A D A . S T R I N G S . W I D E _ H A S H                 --
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
@@ -19,6 +19,3 @@ function Ada.Strings.Wide_Hash
   (Key : Wide_String) return Containers.Hash_Type;
 
 pragma Pure (Ada.Strings.Wide_Hash);
-
-
-
index b6fa3a9904e2504ff649234ef0771d01519ccec2..9c1b752c4182f34ad9e32b94f1ef37359b2c2960 100644 (file)
@@ -50,10 +50,8 @@ is
 begin
    Tmp := 0;
    for J in Key'Range loop
-      Tmp := Rotate_Left (Tmp, 1) + Wide_Wide_Character'Pos (Key (J));
+      Tmp := Rotate_Left (Tmp, 3) + Wide_Wide_Character'Pos (Key (J));
    end loop;
 
    return Tmp;
 end Ada.Strings.Wide_Wide_Hash;
-
-
diff --git a/gcc/ada/a-swunha.adb b/gcc/ada/a-swunha.adb
deleted file mode 100644 (file)
index 8229494..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-------------------------------------------------------------------------------
---                                                                          --
---                         GNAT LIBRARY COMPONENTS                          --
---                                                                          --
---                     ADA.STRINGS.WIDE_UNBOUNDED.HASH                      --
---                                                                          --
---                                 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.                  --
-------------------------------------------------------------------------------
-
---  Note: source of this algorithm: GNAT.HTable.Hash (g-htable.adb)
-
-function Ada.Strings.Wide_Unbounded.Hash
-  (Key : Unbounded_Wide_String) return Containers.Hash_Type
-is
-   use Ada.Containers;
-
-   function Rotate_Left
-     (Value  : Hash_Type;
-      Amount : Natural) return Hash_Type;
-   pragma Import (Intrinsic, Rotate_Left);
-
-   Tmp : Hash_Type;
-
-begin
-   Tmp := 0;
-   for J in 1 .. Key.Last loop
-      Tmp := Rotate_Left (Tmp, 1) + Wide_Character'Pos (Key.Reference (J));
-   end loop;
-
-   return Tmp;
-end Ada.Strings.Wide_Unbounded.Hash;
diff --git a/gcc/ada/a-swunha.ads b/gcc/ada/a-swunha.ads
deleted file mode 100644 (file)
index 267392f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-------------------------------------------------------------------------------
---                                                                          --
---                         GNAT LIBRARY COMPONENTS                          --
---                                                                          --
---                     ADA.STRINGS.WIDE_UNBOUNDED.HASH                      --
---                                                                          --
---                                 S p e c                                  --
---                                                                          --
--- This specification is adapted from the Ada Reference Manual for use with --
--- GNAT.  In accordance with the copyright of that document, you can freely --
--- copy and modify this specification,  provided that if you redistribute a --
--- modified version,  any changes that you have made are clearly indicated. --
---                                                                          --
-------------------------------------------------------------------------------
-
-with Ada.Containers;
-
-function Ada.Strings.Wide_Unbounded.Hash
-  (Key : Unbounded_Wide_String) return Containers.Hash_Type;
-
-pragma Preelaborate (Ada.Strings.Wide_Unbounded.Hash);
diff --git a/gcc/ada/a-swuwha.adb b/gcc/ada/a-swuwha.adb
new file mode 100644 (file)
index 0000000..77912e7
--- /dev/null
@@ -0,0 +1,57 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT LIBRARY COMPONENTS                          --
+--                                                                          --
+--  A D A . S T R I N G S . W I D E _ U N B O U N D E D . W I D E _ H A S H --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--          Copyright (C) 2004-2005 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.                  --
+------------------------------------------------------------------------------
+
+--  Note: source of this algorithm: GNAT.HTable.Hash (g-htable.adb)
+
+function Ada.Strings.Wide_Unbounded.Wide_Hash
+  (Key : Unbounded_Wide_String) return Containers.Hash_Type
+is
+   use Ada.Containers;
+
+   function Rotate_Left
+     (Value  : Hash_Type;
+      Amount : Natural) return Hash_Type;
+   pragma Import (Intrinsic, Rotate_Left);
+
+   Tmp : Hash_Type;
+
+begin
+   Tmp := 0;
+   for J in 1 .. Key.Last loop
+      Tmp := Rotate_Left (Tmp, 3) + Wide_Character'Pos (Key.Reference (J));
+   end loop;
+
+   return Tmp;
+end Ada.Strings.Wide_Unbounded.Wide_Hash;
diff --git a/gcc/ada/a-swuwha.ads b/gcc/ada/a-swuwha.ads
new file mode 100644 (file)
index 0000000..078094a
--- /dev/null
@@ -0,0 +1,23 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT LIBRARY COMPONENTS                          --
+--                                                                          --
+--  A D A . S T R I N G S . W I D E _ U N B O U N D E D . W I D E _ H A S H --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--          Copyright (C) 2004-2005 Free Software Foundation, Inc.          --
+--                                                                          --
+-- This specification is adapted from the Ada Reference Manual for use with --
+-- GNAT.  In accordance with the copyright of that document, you can freely --
+-- copy and modify this specification,  provided that if you redistribute a --
+-- modified version,  any changes that you have made are clearly indicated. --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Containers;
+
+function Ada.Strings.Wide_Unbounded.Wide_Hash
+  (Key : Unbounded_Wide_String) return Containers.Hash_Type;
+
+pragma Preelaborate (Ada.Strings.Wide_Unbounded.Wide_Hash);
diff --git a/gcc/ada/a-szunha.adb b/gcc/ada/a-szunha.adb
deleted file mode 100644 (file)
index 68e6056..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-------------------------------------------------------------------------------
---                                                                          --
---                         GNAT LIBRARY COMPONENTS                          --
---                                                                          --
---       A D A . S T R I N G S . W I D E _ U N B O U N D E D . H A S H      --
---                                                                          --
---                                 B o d y                                  --
---                                                                          --
---          Copyright (C) 2004-2005 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.                  --
-------------------------------------------------------------------------------
-
---  Note: source of this algorithm: GNAT.HTable.Hash (g-htable.adb)
-
-function Ada.Strings.Wide_Wide_Unbounded.Hash
-  (Key : Unbounded_Wide_Wide_String) return Containers.Hash_Type
-is
-   use Ada.Containers;
-
-   function Rotate_Left
-     (Value  : Hash_Type;
-      Amount : Natural) return Hash_Type;
-   pragma Import (Intrinsic, Rotate_Left);
-
-   Tmp : Hash_Type;
-
-begin
-   Tmp := 0;
-   for J in 1 .. Key.Last loop
-      Tmp := Rotate_Left (Tmp, 1) +
-        Wide_Wide_Character'Pos (Key.Reference (J));
-   end loop;
-
-   return Tmp;
-end Ada.Strings.Wide_Wide_Unbounded.Hash;
diff --git a/gcc/ada/a-szunha.ads b/gcc/ada/a-szunha.ads
deleted file mode 100644 (file)
index e1b8721..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-------------------------------------------------------------------------------
---                                                                          --
---                         GNAT LIBRARY COMPONENTS                          --
---                                                                          --
---       A D A . S T R I N G S . W I D E _ U N B O U N D E D . H A S H      --
---                                                                          --
---                                 S p e c                                  --
---                                                                          --
--- This specification is adapted from the Ada Reference Manual for use with --
--- GNAT.  In accordance with the copyright of that document, you can freely --
--- copy and modify this specification,  provided that if you redistribute a --
--- modified version,  any changes that you have made are clearly indicated. --
---                                                                          --
-------------------------------------------------------------------------------
-
-with Ada.Containers;
-
-function Ada.Strings.Wide_Wide_Unbounded.Hash
-  (Key : Unbounded_Wide_Wide_String) return Containers.Hash_Type;
-
-pragma Preelaborate (Ada.Strings.Wide_Wide_Unbounded.Hash);
diff --git a/gcc/ada/a-szuzha.adb b/gcc/ada/a-szuzha.adb
new file mode 100644 (file)
index 0000000..2f3df5e
--- /dev/null
@@ -0,0 +1,58 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT LIBRARY COMPONENTS                          --
+--                                                                          --
+--  A D A . S T R I N G S . W I D E _ U N B O U N D E D . W I D E _ H A S H --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--          Copyright (C) 2004-2005 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.                  --
+------------------------------------------------------------------------------
+
+--  Note: source of this algorithm: GNAT.HTable.Hash (g-htable.adb)
+
+function Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Hash
+  (Key : Unbounded_Wide_Wide_String) return Containers.Hash_Type
+is
+   use Ada.Containers;
+
+   function Rotate_Left
+     (Value  : Hash_Type;
+      Amount : Natural) return Hash_Type;
+   pragma Import (Intrinsic, Rotate_Left);
+
+   Tmp : Hash_Type;
+
+begin
+   Tmp := 0;
+   for J in 1 .. Key.Last loop
+      Tmp := Rotate_Left (Tmp, 3) +
+        Wide_Wide_Character'Pos (Key.Reference (J));
+   end loop;
+
+   return Tmp;
+end Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Hash;
diff --git a/gcc/ada/a-szuzha.ads b/gcc/ada/a-szuzha.ads
new file mode 100644 (file)
index 0000000..2aaf66b
--- /dev/null
@@ -0,0 +1,23 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT LIBRARY COMPONENTS                          --
+--                                                                          --
+--  A D A . S T R I N G S . W I D E _ U N B O U N D E D . W I D E _ H A S H --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--          Copyright (C) 2004-2005 Free Software Foundation, Inc.          --
+--                                                                          --
+-- This specification is adapted from the Ada Reference Manual for use with --
+-- GNAT.  In accordance with the copyright of that document, you can freely --
+-- copy and modify this specification,  provided that if you redistribute a --
+-- modified version,  any changes that you have made are clearly indicated. --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with Ada.Containers;
+
+function Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Hash
+  (Key : Unbounded_Wide_Wide_String) return Containers.Hash_Type;
+
+pragma Preelaborate (Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Hash);