OSDN Git Service

2012-12-15 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-cborma.adb
index 344f11d..b39d9ae 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 2004-2010, Free Software Foundation, Inc.         --
+--          Copyright (C) 2004-2011, 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- --
@@ -35,15 +35,20 @@ with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
 pragma Elaborate_All
   (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
 
-with System;  use type System.Address;
+with Ada.Finalization; use Ada.Finalization;
+
+with System; use type System.Address;
 
 package body Ada.Containers.Bounded_Ordered_Maps is
 
-   type Iterator is new
-     Map_Iterator_Interfaces.Reversible_Iterator with record
-        Container : Map_Access;
-        Node      : Count_Type;
-     end record;
+   type Iterator is new Limited_Controlled and
+     Map_Iterator_Interfaces.Reversible_Iterator with
+   record
+      Container : Map_Access;
+      Node      : Count_Type;
+   end record;
+
+   overriding procedure Finalize (Object : in out Iterator);
 
    overriding function First (Object : Iterator) return Cursor;
    overriding function Last  (Object : Iterator) return Cursor;
@@ -255,7 +260,6 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
       declare
          LN : Node_Type renames Left.Container.Nodes (Left.Node);
-
       begin
          return Right < LN.Key;
       end;
@@ -514,13 +518,12 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
    function Element (Container : Map; Key : Key_Type) return Element_Type is
       Node : constant Count_Type := Key_Ops.Find (Container, Key);
-
    begin
       if Node = 0 then
          raise Constraint_Error with "key not in map";
+      else
+         return Container.Nodes (Node).Element;
       end if;
-
-      return Container.Nodes (Node).Element;
    end Element;
 
    ---------------------
@@ -552,19 +555,33 @@ package body Ada.Containers.Bounded_Ordered_Maps is
       end if;
    end Exclude;
 
+   --------------
+   -- Finalize --
+   --------------
+
+   procedure Finalize (Object : in out Iterator) is
+   begin
+      if Object.Container /= null then
+         declare
+            B : Natural renames Object.Container.all.Busy;
+         begin
+            B := B - 1;
+         end;
+      end if;
+   end Finalize;
+
    ----------
    -- Find --
    ----------
 
    function Find (Container : Map; Key : Key_Type) return Cursor is
       Node : constant Count_Type := Key_Ops.Find (Container, Key);
-
    begin
       if Node = 0 then
          return No_Element;
+      else
+         return Cursor'(Container'Unrestricted_Access, Node);
       end if;
-
-      return Cursor'(Container'Unrestricted_Access, Node);
    end Find;
 
    -----------
@@ -575,20 +592,31 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    begin
       if Container.First = 0 then
          return No_Element;
+      else
+         return Cursor'(Container'Unrestricted_Access, Container.First);
       end if;
-
-      return Cursor'(Container'Unrestricted_Access, Container.First);
    end First;
 
    function First (Object : Iterator) return Cursor is
-      F : constant Count_Type := Object.Container.First;
    begin
-      if F = 0 then
-         return No_Element;
-      end if;
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the First (and Last) selector function.
 
-      return
-        Cursor'(Object.Container.all'Unchecked_Access, F);
+      --  When the Node component is 0, this means the iterator object was
+      --  constructed without a start expression, in which case the (forward)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  of items (corresponding to Container.First, for a forward iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is positive, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (forward) partial iteration begins.
+
+      if Object.Node = 0 then
+         return Bounded_Ordered_Maps.First (Object.Container.all);
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end First;
 
    -------------------
@@ -599,9 +627,9 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    begin
       if Container.First = 0 then
          raise Constraint_Error with "map is empty";
+      else
+         return Container.Nodes (Container.First).Element;
       end if;
-
-      return Container.Nodes (Container.First).Element;
    end First_Element;
 
    ---------------
@@ -612,9 +640,9 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    begin
       if Container.First = 0 then
          raise Constraint_Error with "map is empty";
+      else
+         return Container.Nodes (Container.First).Key;
       end if;
-
-      return Container.Nodes (Container.First).Key;
    end First_Key;
 
    -----------
@@ -623,13 +651,12 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
    function Floor (Container : Map; Key : Key_Type) return Cursor is
       Node : constant Count_Type := Key_Ops.Floor (Container, Key);
-
    begin
       if Node = 0 then
          return No_Element;
+      else
+         return Cursor'(Container'Unrestricted_Access, Node);
       end if;
-
-      return Cursor'(Container'Unrestricted_Access, Node);
    end Floor;
 
    -----------------
@@ -664,7 +691,6 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
          declare
             N : Node_Type renames Container.Nodes (Position.Node);
-
          begin
             N.Key := Key;
             N.Element := New_Item;
@@ -714,7 +740,6 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
       function New_Node return Count_Type is
          Result : Count_Type;
-
       begin
          Allocate (Container, Result);
          return Result;
@@ -778,6 +803,17 @@ package body Ada.Containers.Bounded_Ordered_Maps is
       procedure Assign (Node : in out Node_Type) is
       begin
          Node.Key := Key;
+
+         --  Were this insertion operation to accept an element parameter, this
+         --  is the point where the element value would be used, to update the
+         --  element component of the new node. However, this insertion
+         --  operation is special, in the sense that it does not accept an
+         --  element parameter. Rather, this version of Insert allocates a node
+         --  (inserting it among the active nodes of the container in the
+         --  normal way, with the node's position being determined by the Key),
+         --  and passes back a cursor designating the node. It is then up to
+         --  the caller to assign a value to the node's element.
+
          --  Node.Element := New_Item;
       end Assign;
 
@@ -787,7 +823,6 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
       function New_Node return Count_Type is
          Result : Count_Type;
-
       begin
          Allocate (Container, Result);
          return Result;
@@ -823,7 +858,7 @@ package body Ada.Containers.Bounded_Ordered_Maps is
       Right : Node_Type) return Boolean
    is
    begin
-      --  k > node same as node < k
+      --  Left > Right same as Right < Left
 
       return Right.Key < Left;
    end Is_Greater_Key_Node;
@@ -882,20 +917,77 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    end Iterate;
 
    function Iterate
-     (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+     (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
    is
-      It : constant Iterator :=
-                      (Container'Unrestricted_Access, Container.First);
+      B  : Natural renames Container'Unrestricted_Access.all.Busy;
+
    begin
-      return It;
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is 0 (as is the case here), this means the iterator object
+      --  was constructed without a start expression. This is a complete
+      --  iterator, meaning that the iteration starts from the (logical)
+      --  beginning of the sequence of items.
+
+      --  Note: For a forward iterator, Container.First is the beginning, and
+      --  for a reverse iterator, Container.Last is the beginning.
+
+      return It : constant Iterator :=
+                    (Limited_Controlled with
+                       Container => Container'Unrestricted_Access,
+                       Node      => 0)
+      do
+         B := B + 1;
+      end return;
    end Iterate;
 
-   function Iterate (Container : Map; Start : Cursor)
-      return Map_Iterator_Interfaces.Reversible_Iterator'class
+   function Iterate
+     (Container : Map;
+      Start     : Cursor)
+      return Map_Iterator_Interfaces.Reversible_Iterator'Class
    is
-      It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
+      B  : Natural renames Container'Unrestricted_Access.all.Busy;
+
    begin
-      return It;
+      --  Iterator was defined to behave the same as for a complete iterator,
+      --  and iterate over the entire sequence of items. However, those
+      --  semantics were unintuitive and arguably error-prone (it is too easy
+      --  to accidentally create an endless loop), and so they were changed,
+      --  per the ARG meeting in Denver on 2011/11. However, there was no
+      --  consensus about what positive meaning this corner case should have,
+      --  and so it was decided to simply raise an exception. This does imply,
+      --  however, that it is not possible to use a partial iterator to specify
+      --  an empty sequence of items.
+
+      if Start = No_Element then
+         raise Constraint_Error with
+           "Start position for iterator equals No_Element";
+      end if;
+
+      if Start.Container /= Container'Unrestricted_Access then
+         raise Program_Error with
+           "Start cursor of Iterate designates wrong map";
+      end if;
+
+      pragma Assert (Vet (Container, Start.Node),
+                     "Start cursor of Iterate is bad");
+
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is positive (as is the case here), it means that this
+      --  is a partial iteration, over a subset of the complete sequence of
+      --  items. The iterator object was constructed with a start expression,
+      --  indicating the position from which the iteration begins. (Note that
+      --  the start position has the same value irrespective of whether this
+      --  is a forward or reverse iteration.)
+
+      return It : constant Iterator :=
+                    (Limited_Controlled with
+                       Container => Container'Unrestricted_Access,
+                       Node      => Start.Node)
+      do
+         B := B + 1;
+      end return;
    end Iterate;
 
    ---------
@@ -923,20 +1015,31 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    begin
       if Container.Last = 0 then
          return No_Element;
+      else
+         return Cursor'(Container'Unrestricted_Access, Container.Last);
       end if;
-
-      return Cursor'(Container'Unrestricted_Access, Container.Last);
    end Last;
 
    function Last (Object : Iterator) return Cursor is
-      F : constant Count_Type := Object.Container.Last;
    begin
-      if F = 0 then
-         return No_Element;
-      end if;
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the Last (and First) selector function.
+
+      --  When the Node component is 0, this means the iterator object was
+      --  constructed without a start expression, in which case the (reverse)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  (corresponding to Container.Last, for a reverse iterator).
 
-      return
-        Cursor'(Object.Container.all'Unchecked_Access, F);
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is positive, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (reverse) partial iteration begins.
+
+      if Object.Node = 0 then
+         return Bounded_Ordered_Maps.Last (Object.Container.all);
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end Last;
 
    ------------------
@@ -947,9 +1050,9 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    begin
       if Container.Last = 0 then
          raise Constraint_Error with "map is empty";
+      else
+         return Container.Nodes (Container.Last).Element;
       end if;
-
-      return Container.Nodes (Container.Last).Element;
    end Last_Element;
 
    --------------
@@ -960,9 +1063,9 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    begin
       if Container.Last = 0 then
          raise Constraint_Error with "map is empty";
+      else
+         return Container.Nodes (Container.Last).Key;
       end if;
-
-      return Container.Nodes (Container.Last).Key;
    end Last_Key;
 
    ----------
@@ -998,7 +1101,8 @@ package body Ada.Containers.Bounded_Ordered_Maps is
            "attempt to tamper with cursors (container is busy)";
       end if;
 
-      Assign (Target => Target, Source => Source);
+      Target.Assign (Source);
+      Source.Clear;
    end Move;
 
    ----------
@@ -1038,8 +1142,16 @@ package body Ada.Containers.Bounded_Ordered_Maps is
      (Object   : Iterator;
       Position : Cursor) return Cursor
    is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Next designates wrong map";
+      end if;
+
       return Next (Position);
    end Next;
 
@@ -1089,8 +1201,16 @@ package body Ada.Containers.Bounded_Ordered_Maps is
      (Object   : Iterator;
       Position : Cursor) return Cursor
    is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Previous designates wrong map";
+      end if;
+
       return Previous (Position);
    end Previous;
 
@@ -1198,15 +1318,17 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    -- Reference --
    ---------------
 
-   function Constant_Reference (Container : Map; Key : Key_Type)
-     return Constant_Reference_Type
+   function Constant_Reference
+     (Container : Map;
+      Key       : Key_Type) return Constant_Reference_Type
    is
    begin
       return (Element => Container.Element (Key)'Unrestricted_Access);
    end Constant_Reference;
 
-   function Reference (Container : Map; Key : Key_Type)
-     return Reference_Type
+   function Reference
+     (Container : Map;
+      Key       : Key_Type) return Reference_Type
    is
    begin
       return (Element => Container.Element (Key)'Unrestricted_Access);
@@ -1298,7 +1420,7 @@ package body Ada.Containers.Bounded_Ordered_Maps is
 
       B : Natural renames Container'Unrestricted_Access.all.Busy;
 
-      --  Start of processing for Reverse_Iterate
+   --  Start of processing for Reverse_Iterate
 
    begin
       B := B + 1;