The concrete type Iterator is declared as limited, because there is no need for
assignment for iterator objects.  Hashed maps also do not support partial
iteration, so the unnecessary node component is also removed from that type.

The Next operation vets the cursor parameter to ensure that it designates a
node in the same container as the iterator. The function then forwards to the
call to the corresponding cursor-based operation.

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-11-23  Matthew Heaney  <hea...@adacore.com>

        * a-cohama.adb, a-cihama.adb, a-cbhama.adb (Iterator): Declare
        type as limited, and remove node component.
        (First, Next): Forward call to corresponding cursor-based operation.
        (Iterate): Representation of iterator no longer has node component.

Index: a-cihama.adb
===================================================================
--- a-cihama.adb        (revision 181654)
+++ a-cihama.adb        (working copy)
@@ -45,10 +45,9 @@
    procedure Free_Element is
       new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
 
-   type Iterator is new
+   type Iterator is limited new
      Map_Iterator_Interfaces.Forward_Iterator with record
         Container : Map_Access;
-        Node      : Node_Access;
      end record;
 
    overriding function First (Object : Iterator) return Cursor;
@@ -476,14 +475,8 @@
    end First;
 
    function First (Object : Iterator) return Cursor is
-      M : constant Map_Access  := Object.Container;
-      N : constant Node_Access := HT_Ops.First (M.HT);
    begin
-      if N = null then
-         return No_Element;
-      else
-         return Cursor'(Object.Container.all'Unchecked_Access, N);
-      end if;
+      return Object.Container.First;
    end First;
 
    ----------
@@ -715,13 +708,11 @@
       B := B - 1;
    end Iterate;
 
-   function Iterate (Container : Map)
-      return Map_Iterator_Interfaces.Forward_Iterator'class
+   function Iterate
+     (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
    is
-      Node : constant Node_Access := HT_Ops.First (Container.HT);
-      It   : constant Iterator := (Container'Unrestricted_Access, Node);
    begin
-      return It;
+      return Iterator'(Container => Container'Unrestricted_Access);
    end Iterate;
 
    ---------
@@ -809,11 +800,16 @@
 
    function Next (Object : Iterator; Position : Cursor) return Cursor is
    begin
-      if Position.Node = null then
+      if Position.Container = null then
          return No_Element;
-      else
-         return (Object.Container, Next (Position).Node);
       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;
 
    -------------------
Index: a-cohama.adb
===================================================================
--- a-cohama.adb        (revision 181654)
+++ a-cohama.adb        (working copy)
@@ -39,10 +39,9 @@
 
 package body Ada.Containers.Hashed_Maps is
 
-   type Iterator is new
+   type Iterator is limited new
      Map_Iterator_Interfaces.Forward_Iterator with record
         Container : Map_Access;
-        Node      : Node_Access;
      end record;
 
    overriding function First (Object : Iterator) return Cursor;
@@ -440,14 +439,8 @@
    end First;
 
    function First (Object : Iterator) return Cursor is
-      M : constant Map_Access  := Object.Container;
-      N : constant Node_Access := HT_Ops.First (M.HT);
    begin
-      if N = null then
-         return No_Element;
-      end if;
-
-      return Cursor'(Object.Container.all'Unchecked_Access, N);
+      return Object.Container.First;
    end First;
 
    ----------
@@ -667,12 +660,10 @@
    end Iterate;
 
    function Iterate
-     (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+     (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
    is
-      Node : constant Node_Access := HT_Ops.First (Container.HT);
-      It   : constant Iterator := (Container'Unrestricted_Access, Node);
    begin
-      return It;
+      return Iterator'(Container => Container'Unrestricted_Access);
    end Iterate;
 
    ---------
@@ -752,11 +743,16 @@
       Position : Cursor) return Cursor
    is
    begin
-      if Position.Node = null then
+      if Position.Container = null then
          return No_Element;
-      else
-         return (Object.Container, Next (Position).Node);
       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;
 
    -------------------
Index: a-cbhama.adb
===================================================================
--- a-cbhama.adb        (revision 181654)
+++ a-cbhama.adb        (working copy)
@@ -41,7 +41,6 @@
    type Iterator is new
      Map_Iterator_Interfaces.Forward_Iterator with record
         Container : Map_Access;
-        Node      : Count_Type;
      end record;
 
    overriding function First (Object : Iterator) return Cursor;
@@ -424,14 +423,8 @@
    end First;
 
    function First (Object : Iterator) return Cursor is
-      M : constant Map_Access := Object.Container;
-      N : constant Count_Type := HT_Ops.First (M.all);
    begin
-      if N = 0 then
-         return No_Element;
-      else
-         return Cursor'(Object.Container.all'Unchecked_Access, N);
-      end if;
+      return Object.Container.First;
    end First;
 
    -----------------
@@ -675,12 +668,10 @@
    end Iterate;
 
    function Iterate
-     (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'class
+     (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
    is
-      Node : constant Count_Type := HT_Ops.First (Container);
-      It   : constant Iterator   := (Container'Unrestricted_Access, Node);
    begin
-      return It;
+      return Iterator'(Container => Container'Unrestricted_Access);
    end Iterate;
 
    ---------
@@ -770,11 +761,16 @@
       Position : Cursor) return Cursor
    is
    begin
-      if Position.Node = 0 then
+      if Position.Container = null then
          return No_Element;
-      else
-         return (Object.Container, Next (Position).Node);
       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;
 
    -------------------

Reply via email to