Commit ba355842 by Matthew Heaney Committed by Arnaud Charlet

a-cihase.adb, [...]: Synchronized with latest draft (Draft 13, August 2005) of Ada Amendment 1.

2005-09-01  Matthew Heaney  <heaney@adacore.com>

	* a-cihase.adb, a-coorse.ads, a-coorse.adb, a-cohama.adb,
	a-ciorse.ads, a-ciorse.adb, a-cihama.adb, a-cdlili.adb,
	a-cidlli.adb, a-chtgop.adb, a-cihase.adb, a-cihase.ads,
	a-cohase.adb, a-cohase.adb, a-cohase.ads: Synchronized with latest
	draft (Draft 13, August 2005) of Ada Amendment 1.

From-SVN: r103892
parent c1cd0d96
...@@ -38,18 +38,19 @@ with Ada.Unchecked_Deallocation; ...@@ -38,18 +38,19 @@ with Ada.Unchecked_Deallocation;
package body Ada.Containers.Doubly_Linked_Lists is package body Ada.Containers.Doubly_Linked_Lists is
procedure Free is
new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
----------------------- -----------------------
-- Local Subprograms -- -- Local Subprograms --
----------------------- -----------------------
procedure Free (X : in out Node_Access);
procedure Insert_Internal procedure Insert_Internal
(Container : in out List; (Container : in out List;
Before : Node_Access; Before : Node_Access;
New_Node : Node_Access); New_Node : Node_Access);
function Vet (Position : Cursor) return Boolean;
--------- ---------
-- "=" -- -- "=" --
--------- ---------
...@@ -110,7 +111,6 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -110,7 +111,6 @@ package body Ada.Containers.Doubly_Linked_Lists is
Container.Length := 1; Container.Length := 1;
Src := Src.Next; Src := Src.Next;
while Src /= null loop while Src /= null loop
Container.Last.Next := new Node_Type'(Element => Src.Element, Container.Last.Next := new Node_Type'(Element => Src.Element,
Prev => Container.Last, Prev => Container.Last,
...@@ -162,9 +162,8 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -162,9 +162,8 @@ package body Ada.Containers.Doubly_Linked_Lists is
pragma Assert (X.Next.Prev = Container.First); pragma Assert (X.Next.Prev = Container.First);
Container.First := X.Next; Container.First := X.Next;
X.Next := null; -- prevent mischief
Container.First.Prev := null; Container.First.Prev := null;
Container.Length := Container.Length - 1; Container.Length := Container.Length - 1;
Free (X); Free (X);
...@@ -181,7 +180,7 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -181,7 +180,7 @@ package body Ada.Containers.Doubly_Linked_Lists is
end Clear; end Clear;
-------------- --------------
-- Continue -- -- Contains --
-------------- --------------
function Contains function Contains
...@@ -203,28 +202,16 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -203,28 +202,16 @@ package body Ada.Containers.Doubly_Linked_Lists is
X : Node_Access; X : Node_Access;
begin begin
pragma Assert (Vet (Position), "bad cursor in Delete");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= List_Access'(Container'Unchecked_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; 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 if Position.Node = Container.First then
Delete_First (Container, Count); Delete_First (Container, Count);
Position := First (Container); Position := First (Container);
...@@ -249,7 +236,6 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -249,7 +236,6 @@ package body Ada.Containers.Doubly_Linked_Lists is
Container.Last := X.Prev; Container.Last := X.Prev;
Container.Last.Next := null; Container.Last.Next := null;
X.Prev := null; -- prevent mischief
Free (X); Free (X);
return; return;
end if; end if;
...@@ -259,8 +245,6 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -259,8 +245,6 @@ package body Ada.Containers.Doubly_Linked_Lists is
X.Next.Prev := X.Prev; X.Next.Prev := X.Prev;
X.Prev.Next := X.Next; X.Prev.Next := X.Next;
X.Next := null;
X.Prev := null;
Free (X); Free (X);
end loop; end loop;
end Delete; end Delete;
...@@ -298,7 +282,6 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -298,7 +282,6 @@ package body Ada.Containers.Doubly_Linked_Lists is
Container.Length := Container.Length - 1; Container.Length := Container.Length - 1;
X.Next := null; -- prevent mischief
Free (X); Free (X);
end loop; end loop;
end Delete_First; end Delete_First;
...@@ -336,7 +319,6 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -336,7 +319,6 @@ package body Ada.Containers.Doubly_Linked_Lists is
Container.Length := Container.Length - 1; Container.Length := Container.Length - 1;
X.Prev := null; -- prevent mischief
Free (X); Free (X);
end loop; end loop;
end Delete_Last; end Delete_Last;
...@@ -347,20 +329,11 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -347,20 +329,11 @@ package body Ada.Containers.Doubly_Linked_Lists is
function Element (Position : Cursor) return Element_Type is function Element (Position : Cursor) return Element_Type is
begin begin
pragma Assert (Position.Container /= null); pragma Assert (Vet (Position), "bad cursor in Element");
pragma Assert (Position.Container.Length > 0);
pragma Assert (Position.Container.First.Prev = null); if Position.Node = null then
pragma Assert (Position.Container.Last.Next = null); raise Constraint_Error;
end if;
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; return Position.Node.Element;
end Element; end Element;
...@@ -379,23 +352,13 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -379,23 +352,13 @@ package body Ada.Containers.Doubly_Linked_Lists is
begin begin
if Node = null then if Node = null then
Node := Container.First; Node := Container.First;
else else
if Position.Container /= List_Access'(Container'Unchecked_Access) then pragma Assert (Vet (Position), "bad cursor in Find");
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; 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; end if;
while Node /= null loop while Node /= null loop
...@@ -428,9 +391,27 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -428,9 +391,27 @@ package body Ada.Containers.Doubly_Linked_Lists is
function First_Element (Container : List) return Element_Type is function First_Element (Container : List) return Element_Type is
begin begin
if Container.First = null then
raise Constraint_Error;
end if;
return Container.First.Element; return Container.First.Element;
end First_Element; end First_Element;
----------
-- Free --
----------
procedure Free (X : in out Node_Access) is
procedure Deallocate is
new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
begin
X.Prev := X;
X.Next := X;
Deallocate (X);
end Free;
--------------------- ---------------------
-- Generic_Sorting -- -- Generic_Sorting --
--------------------- ---------------------
...@@ -605,26 +586,8 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -605,26 +586,8 @@ package body Ada.Containers.Doubly_Linked_Lists is
function Has_Element (Position : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then pragma Assert (Vet (Position), "bad cursor in Has_Element");
pragma Assert (Position.Container = null); return Position.Node /= 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; end Has_Element;
------------ ------------
...@@ -641,23 +604,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -641,23 +604,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
New_Node : Node_Access; New_Node : Node_Access;
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad cursor in Insert");
if Before.Container /= List_Access'(Container'Unchecked_Access) then
raise Program_Error;
end if;
pragma Assert (Container.Length > 0); if Before.Container /= null
pragma Assert (Container.First.Prev = null); and then Before.Container /= Container'Unrestricted_Access
pragma Assert (Container.Last.Next = null); then
raise Program_Error;
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; end if;
if Count = 0 then if Count = 0 then
...@@ -704,23 +656,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -704,23 +656,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
New_Node : Node_Access; New_Node : Node_Access;
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad cursor in Insert");
if Before.Container /= List_Access'(Container'Unchecked_Access) then
raise Program_Error;
end if;
pragma Assert (Container.Length > 0); if Before.Container /= null
pragma Assert (Container.First.Prev = null); and then Before.Container /= Container'Unrestricted_Access
pragma Assert (Container.Last.Next = null); then
raise Program_Error;
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; end if;
if Count = 0 then if Count = 0 then
...@@ -853,6 +794,10 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -853,6 +794,10 @@ package body Ada.Containers.Doubly_Linked_Lists is
function Last_Element (Container : List) return Element_Type is function Last_Element (Container : List) return Element_Type is
begin begin
if Container.Last = null then
raise Constraint_Error;
end if;
return Container.Last.Element; return Container.Last.Element;
end Last_Element; end Last_Element;
...@@ -900,25 +845,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -900,25 +845,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
procedure Next (Position : in out Cursor) is procedure Next (Position : in out Cursor) is
begin begin
pragma Assert (Vet (Position), "bad cursor in procedure Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return; return;
end if; 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; Position.Node := Position.Node.Next;
if Position.Node = null then if Position.Node = null then
...@@ -928,25 +860,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -928,25 +860,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
function Next (Position : Cursor) return Cursor is function Next (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; 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 declare
Next_Node : constant Node_Access := Position.Node.Next; Next_Node : constant Node_Access := Position.Node.Next;
begin begin
...@@ -977,25 +896,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -977,25 +896,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
procedure Previous (Position : in out Cursor) is procedure Previous (Position : in out Cursor) is
begin begin
pragma Assert (Vet (Position), "bad cursor in procedure Previous");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return; return;
end if; 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; Position.Node := Position.Node.Prev;
if Position.Node = null then if Position.Node = null then
...@@ -1005,25 +911,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1005,25 +911,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
function Previous (Position : Cursor) return Cursor is function Previous (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Previous");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; 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 declare
Prev_Node : constant Node_Access := Position.Node.Prev; Prev_Node : constant Node_Access := Position.Node.Prev;
begin begin
...@@ -1043,42 +936,34 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1043,42 +936,34 @@ package body Ada.Containers.Doubly_Linked_Lists is
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : in Element_Type)) Process : not null access procedure (Element : in Element_Type))
is 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 begin
B := B + 1; pragma Assert (Vet (Position), "bad cursor in Query_Element");
L := L + 1;
if Position.Node = null then
raise Constraint_Error;
end if;
declare
C : List renames Position.Container.all'Unrestricted_Access.all;
B : Natural renames C.Busy;
L : Natural renames C.Lock;
begin begin
Process (E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; begin
B := B - 1; Process (Position.Node.Element);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Query_Element; end Query_Element;
---------- ----------
...@@ -1141,29 +1026,18 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1141,29 +1026,18 @@ package body Ada.Containers.Doubly_Linked_Lists is
(Position : Cursor; (Position : Cursor;
By : Element_Type) By : Element_Type)
is 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 begin
pragma Assert (Vet (Position), "bad cursor in Replace_Element");
if Position.Container = null then
raise Constraint_Error;
end if;
if Position.Container.Lock > 0 then if Position.Container.Lock > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
E := By; Position.Node.Element := By;
end Replace_Element; end Replace_Element;
------------------ ------------------
...@@ -1180,23 +1054,13 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1180,23 +1054,13 @@ package body Ada.Containers.Doubly_Linked_Lists is
begin begin
if Node = null then if Node = null then
Node := Container.Last; Node := Container.Last;
else else
if Position.Container /= List_Access'(Container'Unchecked_Access) then pragma Assert (Vet (Position), "bad cursor in Reverse_Find");
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; 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; end if;
while Node /= null loop while Node /= null loop
...@@ -1336,23 +1200,12 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1336,23 +1200,12 @@ package body Ada.Containers.Doubly_Linked_Lists is
Source : in out List) Source : in out List)
is is
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad cursor in Splice");
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 if Before.Container /= null
or else Before.Node.Prev.Next = Before.Node); and then Before.Container /= Target'Unrestricted_Access
pragma Assert (Before.Node.Next = null then
or else Before.Node.Next.Prev = Before.Node); raise Program_Error;
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; end if;
if Target'Address = Source'Address if Target'Address = Source'Address
...@@ -1421,46 +1274,23 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1421,46 +1274,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
Position : Cursor) Position : Cursor)
is is
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad Before cursor in Splice");
if Before.Container /= List_Access'(Target'Unchecked_Access) then pragma Assert (Vet (Position), "bad Position cursor in Splice");
raise Program_Error;
end if;
pragma Assert (Target.Length >= 1); if Before.Container /= null
pragma Assert (Target.First.Prev = null); and then Before.Container /= Target'Unchecked_Access
pragma Assert (Target.Last.Next = null); then
raise Program_Error;
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; end if;
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= List_Access'(Target'Unchecked_Access) then if Position.Container /= Target'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
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 if Position.Node = Before.Node
or else Position.Node.Next = Before.Node or else Position.Node.Next = Before.Node
then then
...@@ -1548,46 +1378,23 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1548,46 +1378,23 @@ package body Ada.Containers.Doubly_Linked_Lists is
return; return;
end if; end if;
if Before.Node /= null then pragma Assert (Vet (Before), "bad Before cursor in Splice");
if Before.Container /= List_Access'(Target'Unchecked_Access) then pragma Assert (Vet (Position), "bad Position cursor in Splice");
raise Program_Error;
end if;
pragma Assert (Target.Length >= 1); if Before.Container /= null
pragma Assert (Target.First.Prev = null); and then Before.Container /= Target'Unrestricted_Access
pragma Assert (Target.Last.Next = null); then
raise Program_Error;
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; end if;
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= List_Access'(Source'Unchecked_Access) then if Position.Container /= Source'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
pragma Assert (Source.Length >= 1);
pragma Assert (Source.First.Prev = null);
pragma Assert (Source.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 = Source.First);
pragma Assert (Position.Node.Next /= null
or else Position.Node = Source.Last);
if Target.Length = Count_Type'Last then if Target.Length = Count_Type'Last then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
...@@ -1600,12 +1407,14 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1600,12 +1407,14 @@ package body Ada.Containers.Doubly_Linked_Lists is
if Position.Node = Source.First then if Position.Node = Source.First then
Source.First := Position.Node.Next; Source.First := Position.Node.Next;
Source.First.Prev := null;
if Position.Node = Source.Last then if Position.Node = Source.Last then
pragma Assert (Source.First = null); pragma Assert (Source.First = null);
pragma Assert (Source.Length = 1); pragma Assert (Source.Length = 1);
Source.Last := null; Source.Last := null;
else
Source.First.Prev := null;
end if; end if;
elsif Position.Node = Source.Last then elsif Position.Node = Source.Last then
...@@ -1667,8 +1476,11 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1667,8 +1476,11 @@ package body Ada.Containers.Doubly_Linked_Lists is
procedure Swap (I, J : Cursor) is procedure Swap (I, J : Cursor) is
begin begin
if I.Container = null pragma Assert (Vet (I), "bad I cursor in Swap");
or else J.Container = null pragma Assert (Vet (J), "bad J cursor in Swap");
if I.Node = null
or else J.Node = null
then then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
...@@ -1677,51 +1489,22 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1677,51 +1489,22 @@ package body Ada.Containers.Doubly_Linked_Lists is
raise Program_Error; raise Program_Error;
end if; end if;
declare if I.Node = J.Node then
C : List renames I.Container.all; return;
begin end if;
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); if I.Container.Lock > 0 then
pragma Assert (J.Node /= null); raise Program_Error;
pragma Assert (J.Node.Prev = null end if;
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 declare
EI : Element_Type renames I.Node.Element; EI : Element_Type renames I.Node.Element;
EJ : Element_Type renames J.Node.Element; EJ : Element_Type renames J.Node.Element;
EI_Copy : constant Element_Type := EI; EI_Copy : constant Element_Type := EI;
begin begin
EI := EJ; EI := EJ;
EJ := EI_Copy; EJ := EI_Copy;
end;
end; end;
end Swap; end Swap;
...@@ -1733,50 +1516,25 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1733,50 +1516,25 @@ package body Ada.Containers.Doubly_Linked_Lists is
(Container : in out List; (Container : in out List;
I, J : Cursor) is I, J : Cursor) is
begin begin
if I.Container = null pragma Assert (Vet (I), "bad I cursor in Swap_Links");
or else J.Container = null pragma Assert (Vet (J), "bad J cursor in Swap_Links");
if I.Node = null
or else J.Node = null
then then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if I.Container /= List_Access'(Container'Unchecked_Access) then if I.Container /= Container'Unrestricted_Access
raise Program_Error; or else I.Container /= J.Container
end if; then
if J.Container /= I.Container then
raise Program_Error; raise Program_Error;
end if; 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 if I.Node = J.Node then
return; return;
end if; end if;
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 if Container.Busy > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
...@@ -1813,46 +1571,177 @@ package body Ada.Containers.Doubly_Linked_Lists is ...@@ -1813,46 +1571,177 @@ package body Ada.Containers.Doubly_Linked_Lists is
procedure Update_Element procedure Update_Element
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : in out Element_Type)) is 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 begin
B := B + 1; pragma Assert (Vet (Position), "bad cursor in Update_Element");
L := L + 1;
if Position.Node = null then
raise Constraint_Error;
end if;
declare
C : List renames Position.Container.all'Unrestricted_Access.all;
B : Natural renames C.Busy;
L : Natural renames C.Lock;
begin begin
Process (E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; begin
B := B - 1; Process (Position.Node.Element);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Update_Element; end Update_Element;
---------
-- Vet --
---------
function Vet (Position : Cursor) return Boolean is
begin
if Position.Node = null then
return Position.Container = null;
end if;
if Position.Container = null then
return False;
end if;
if Position.Node.Next = Position.Node then
return False;
end if;
if Position.Node.Prev = Position.Node then
return False;
end if;
declare
L : List renames Position.Container.all;
begin
if L.Length = 0 then
return False;
end if;
if L.First = null then
return False;
end if;
if L.Last = null then
return False;
end if;
if L.First.Prev /= null then
return False;
end if;
if L.Last.Next /= null then
return False;
end if;
if Position.Node.Prev = null
and then Position.Node /= L.First
then
return False;
end if;
if Position.Node.Next = null
and then Position.Node /= L.Last
then
return False;
end if;
if L.Length = 1 then
return L.First = L.Last;
end if;
if L.First = L.Last then
return False;
end if;
if L.First.Next = null then
return False;
end if;
if L.Last.Prev = null then
return False;
end if;
if L.First.Next.Prev /= L.First then
return False;
end if;
if L.Last.Prev.Next /= L.Last then
return False;
end if;
if L.Length = 2 then
if L.First.Next /= L.Last then
return False;
end if;
if L.Last.Prev /= L.First then
return False;
end if;
return True;
end if;
if L.First.Next = L.Last then
return False;
end if;
if L.Last.Prev = L.First then
return False;
end if;
if Position.Node = L.First then
return True;
end if;
if Position.Node = L.Last then
return True;
end if;
if Position.Node.Next = null then
return False;
end if;
if Position.Node.Prev = null then
return False;
end if;
if Position.Node.Next.Prev /= Position.Node then
return False;
end if;
if Position.Node.Prev.Next /= Position.Node then
return False;
end if;
if L.Length = 3 then
if L.First.Next /= Position.Node then
return False;
end if;
if L.Last.Prev /= Position.Node then
return False;
end if;
end if;
return True;
end;
end Vet;
----------- -----------
-- Write -- -- Write --
----------- -----------
......
...@@ -42,14 +42,6 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is ...@@ -42,14 +42,6 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
procedure Free is procedure Free is
new Ada.Unchecked_Deallocation (Buckets_Type, Buckets_Access); new Ada.Unchecked_Deallocation (Buckets_Type, Buckets_Access);
-----------------------
-- Local Subprograms --
-----------------------
procedure Rehash
(HT : in out Hash_Table_Type;
Size : Hash_Type);
------------ ------------
-- Adjust -- -- Adjust --
------------ ------------
...@@ -405,27 +397,33 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is ...@@ -405,27 +397,33 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
begin begin
Clear (HT); Clear (HT);
declare
B : Buckets_Access := HT.Buckets;
begin
HT.Buckets := null;
HT.Length := 0;
Free (B); -- can this fail???
end;
Hash_Type'Read (Stream, Last); Hash_Type'Read (Stream, Last);
-- TODO: don't immediately deallocate the buckets array we Count_Type'Base'Read (Stream, N);
-- already have. Instead, allocate a new buckets array only pragma Assert (N >= 0);
-- if it needs to expanded because of the value of Last.
if N = 0 then
return;
end if;
if Last /= 0 then if HT.Buckets = null
or else HT.Buckets'Last /= Last
then
Free (HT.Buckets);
HT.Buckets := new Buckets_Type (0 .. Last); HT.Buckets := new Buckets_Type (0 .. Last);
end if; end if;
Count_Type'Base'Read (Stream, N); -- TODO: should we rewrite this algorithm so that it doesn't
pragma Assert (N >= 0); -- depend on preserving the exactly length of the hash table
while N > 0 loop -- array? We would prefer to not have to (re)allocate a
-- buckets array (the array that HT already has might be large
-- enough), and to not have to stream the count of the number
-- of nodes in each bucket. The algorithm below is vestigial,
-- as it was written prior to the meeting in Palma, when the
-- semantics of equality were changed (and which obviated the
-- need to preserve the hash table length).
loop
Hash_Type'Read (Stream, I); Hash_Type'Read (Stream, I);
pragma Assert (I in HT.Buckets'Range); pragma Assert (I in HT.Buckets'Range);
pragma Assert (HT.Buckets (I) = null); pragma Assert (HT.Buckets (I) = null);
...@@ -454,6 +452,8 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is ...@@ -454,6 +452,8 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
end loop; end loop;
N := N - M; N := N - M;
exit when N = 0;
end loop; end loop;
end Generic_Read; end Generic_Read;
...@@ -481,6 +481,8 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is ...@@ -481,6 +481,8 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
return; return;
end if; end if;
-- TODO: see note in Generic_Read???
for Indx in HT.Buckets'Range loop for Indx in HT.Buckets'Range loop
X := HT.Buckets (Indx); X := HT.Buckets (Indx);
...@@ -577,104 +579,6 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is ...@@ -577,104 +579,6 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
return null; return null;
end Next; end Next;
------------
-- Rehash --
------------
procedure Rehash
(HT : in out Hash_Table_Type;
Size : Hash_Type)
is
subtype Buckets_Range is Hash_Type range 0 .. Size - 1;
Dst_Buckets : Buckets_Access := new Buckets_Type (Buckets_Range);
Src_Buckets : Buckets_Access := HT.Buckets;
L : Count_Type renames HT.Length;
LL : constant Count_Type := L;
begin
if Src_Buckets = null then
pragma Assert (L = 0);
HT.Buckets := Dst_Buckets;
return;
end if;
if L = 0 then
HT.Buckets := Dst_Buckets;
Free (Src_Buckets);
return;
end if;
-- We might want to change this to iter from 1 .. L instead ???
for Src_Index in Src_Buckets'Range loop
declare
Src_Bucket : Node_Access renames Src_Buckets (Src_Index);
begin
while Src_Bucket /= null loop
declare
Src_Node : constant Node_Access := Src_Bucket;
Dst_Index : constant Hash_Type :=
Index (Dst_Buckets.all, Src_Node);
Dst_Bucket : Node_Access renames Dst_Buckets (Dst_Index);
begin
Src_Bucket := Next (Src_Node);
Set_Next (Src_Node, Dst_Bucket);
Dst_Bucket := Src_Node;
end;
pragma Assert (L > 0);
L := L - 1;
end loop;
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... ???
-- for J in NB'Range loop
-- declare
-- Dst : Node_Access renames NB (J);
-- X : Node_Access;
-- begin
-- while Dst /= null loop
-- X := Dst;
-- Dst := Succ (Dst);
-- Free (X);
-- end loop;
-- 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; -- TODO: raise Program_Error instead
end;
-- exit when L = 0;
-- need to bother???
end loop;
pragma Assert (L = 0);
HT.Buckets := Dst_Buckets;
HT.Length := LL;
Free (Src_Buckets);
end Rehash;
---------------------- ----------------------
-- Reserve_Capacity -- -- Reserve_Capacity --
---------------------- ----------------------
...@@ -686,74 +590,142 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is ...@@ -686,74 +590,142 @@ package body Ada.Containers.Hash_Tables.Generic_Operations is
NN : Hash_Type; NN : Hash_Type;
begin begin
if N = 0 then if HT.Buckets = null then
if HT.Length = 0 then if N > 0 then
Free (HT.Buckets); NN := Prime_Numbers.To_Prime (N);
HT.Buckets := new Buckets_Type (0 .. NN - 1);
end if;
elsif HT.Length < HT.Buckets'Length then return;
NN := Prime_Numbers.To_Prime (HT.Length); end if;
-- ASSERT: NN >= HT.Length if HT.Length = 0 then
if N = 0 then
Free (HT.Buckets);
return;
end if;
if NN < HT.Buckets'Length then if N = HT.Buckets'Length then
if HT.Busy > 0 then return;
raise Program_Error; end if;
end if;
Rehash (HT, Size => NN); NN := Prime_Numbers.To_Prime (N);
end if;
if NN = HT.Buckets'Length then
return;
end if; end if;
declare
X : Buckets_Access := HT.Buckets;
begin
HT.Buckets := new Buckets_Type (0 .. NN - 1);
Free (X);
end;
return; return;
end if; end if;
if HT.Buckets = null then if N = HT.Buckets'Length then
NN := Prime_Numbers.To_Prime (N);
-- ASSERT: NN >= N
Rehash (HT, Size => NN);
return; return;
end if; end if;
if N <= HT.Length then if N < HT.Buckets'Length then
if HT.Length >= HT.Buckets'Length then if HT.Length >= HT.Buckets'Length then
return; return;
end if; end if;
NN := Prime_Numbers.To_Prime (HT.Length); NN := Prime_Numbers.To_Prime (HT.Length);
-- ASSERT: NN >= HT.Length if NN >= HT.Buckets'Length then
return;
end if;
if NN < HT.Buckets'Length then else
if HT.Busy > 0 then NN := Prime_Numbers.To_Prime (Count_Type'Max (N, HT.Length));
raise Program_Error;
end if;
Rehash (HT, Size => NN); if NN = HT.Buckets'Length then -- can't expand any more
return;
end if; end if;
end if;
return; if HT.Busy > 0 then
raise Program_Error;
end if; end if;
-- ASSERT: N > HT.Length Rehash : declare
Dst_Buckets : Buckets_Access := new Buckets_Type (0 .. NN - 1);
Src_Buckets : Buckets_Access := HT.Buckets;
if N = HT.Buckets'Length then L : Count_Type renames HT.Length;
return; LL : constant Count_Type := L;
end if;
NN := Prime_Numbers.To_Prime (N); Src_Index : Hash_Type := Src_Buckets'First;
-- ASSERT: NN >= N begin
-- ASSERT: NN > HT.Length while L > 0 loop
declare
Src_Bucket : Node_Access renames Src_Buckets (Src_Index);
if NN /= HT.Buckets'Length then begin
if HT.Busy > 0 then while Src_Bucket /= null loop
raise Program_Error; declare
end if; Src_Node : constant Node_Access := Src_Bucket;
Dst_Index : constant Hash_Type :=
Index (Dst_Buckets.all, Src_Node);
Dst_Bucket : Node_Access renames Dst_Buckets (Dst_Index);
begin
Src_Bucket := Next (Src_Node);
Set_Next (Src_Node, Dst_Bucket);
Dst_Bucket := Src_Node;
end;
pragma Assert (L > 0);
L := L - 1;
end loop;
exception
when others =>
-- If there's an error computing a hash value during a
-- rehash, then AI-302 says the nodes "become lost." The
-- issue is whether to actually deallocate these lost nodes,
-- since they might be designated by extant cursors. Here
-- we decide to deallocate the nodes, since it's better to
-- solve real problems (storage consumption) rather than
-- imaginary ones (the user might, or might not, dereference
-- a cursor designating a node that has been deallocated),
-- and because we have a way to vet a dangling cursor
-- reference anyway, and hence can actually detect the
-- problem.
for Dst_Index in Dst_Buckets'Range loop
declare
B : Node_Access renames Dst_Buckets (Dst_Index);
X : Node_Access;
begin
while B /= null loop
X := B;
B := Next (X);
Free (X);
end loop;
end;
end loop;
Free (Dst_Buckets);
raise Program_Error;
end;
Rehash (HT, Size => NN); Src_Index := Src_Index + 1;
end if; end loop;
HT.Buckets := Dst_Buckets;
HT.Length := LL;
Free (Src_Buckets);
end Rehash;
end Reserve_Capacity; end Reserve_Capacity;
end Ada.Containers.Hash_Tables.Generic_Operations; end Ada.Containers.Hash_Tables.Generic_Operations;
...@@ -40,20 +40,21 @@ with Ada.Unchecked_Deallocation; ...@@ -40,20 +40,21 @@ with Ada.Unchecked_Deallocation;
package body Ada.Containers.Indefinite_Doubly_Linked_Lists is package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
procedure Free is procedure Free is
new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
procedure Free is
new Ada.Unchecked_Deallocation (Element_Type, Element_Access); new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
----------------------- -----------------------
-- Local Subprograms -- -- Local Subprograms --
----------------------- -----------------------
procedure Free (X : in out Node_Access);
procedure Insert_Internal procedure Insert_Internal
(Container : in out List; (Container : in out List;
Before : Node_Access; Before : Node_Access;
New_Node : Node_Access); New_Node : Node_Access);
function Vet (Position : Cursor) return Boolean;
--------- ---------
-- "=" -- -- "=" --
--------- ---------
...@@ -188,18 +189,8 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -188,18 +189,8 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Container.First := X.Next; Container.First := X.Next;
Container.First.Prev := null; Container.First.Prev := null;
Container.Length := Container.Length - 1;
X.Next := null; -- prevent mischief
begin Container.Length := Container.Length - 1;
Free (X.Element);
exception
when others =>
X.Element := null;
Free (X);
raise;
end;
Free (X); Free (X);
end loop; end loop;
...@@ -211,15 +202,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -211,15 +202,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Container.Last := null; Container.Last := null;
Container.Length := 0; Container.Length := 0;
begin
Free (X.Element);
exception
when others =>
X.Element := null;
Free (X);
raise;
end;
Free (X); Free (X);
end Clear; end Clear;
...@@ -246,28 +228,16 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -246,28 +228,16 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
X : Node_Access; X : Node_Access;
begin begin
pragma Assert (Vet (Position), "bad cursor in Delete");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= List_Access'(Container'Unchecked_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; 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 if Position.Node = Container.First then
Delete_First (Container, Count); Delete_First (Container, Count);
Position := First (Container); Position := First (Container);
...@@ -292,17 +262,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -292,17 +262,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Container.Last := X.Prev; Container.Last := X.Prev;
Container.Last.Next := null; 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); Free (X);
return; return;
end if; end if;
...@@ -312,18 +271,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -312,18 +271,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
X.Next.Prev := X.Prev; X.Next.Prev := X.Prev;
X.Prev.Next := X.Next; 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); Free (X);
end loop; end loop;
end Delete; end Delete;
...@@ -361,17 +308,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -361,17 +308,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Container.Length := Container.Length - 1; 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); Free (X);
end loop; end loop;
end Delete_First; end Delete_First;
...@@ -409,17 +345,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -409,17 +345,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Container.Length := Container.Length - 1; Container.Length := Container.Length - 1;
X.Prev := null; -- prevent mischief
begin
Free (X.Element);
exception
when others =>
X.Element := null;
Free (X);
raise;
end;
Free (X); Free (X);
end loop; end loop;
end Delete_Last; end Delete_Last;
...@@ -430,21 +355,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -430,21 +355,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Element (Position : Cursor) return Element_Type is function Element (Position : Cursor) return Element_Type is
begin begin
pragma Assert (Position.Container /= null); pragma Assert (Vet (Position), "bad cursor in Element");
pragma Assert (Position.Container.Length > 0);
pragma Assert (Position.Container.First.Prev = null); if Position.Node = null then
pragma Assert (Position.Container.Last.Next = null); raise Constraint_Error;
end if;
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; return Position.Node.Element.all;
end Element; end Element;
...@@ -465,23 +380,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -465,23 +380,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Node := Container.First; Node := Container.First;
else else
if Position.Container /= List_Access'(Container'Unchecked_Access) then pragma Assert (Vet (Position), "bad cursor in Find");
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; 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; end if;
while Node /= null loop while Node /= null loop
...@@ -514,9 +417,37 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -514,9 +417,37 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function First_Element (Container : List) return Element_Type is function First_Element (Container : List) return Element_Type is
begin begin
if Container.First = null then
raise Constraint_Error;
end if;
return Container.First.Element.all; return Container.First.Element.all;
end First_Element; end First_Element;
----------
-- Free --
----------
procedure Free (X : in out Node_Access) is
procedure Deallocate is
new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
begin
X.Next := X;
X.Prev := X;
begin
Free (X.Element);
exception
when others =>
X.Element := null;
Deallocate (X);
raise;
end;
Deallocate (X);
end Free;
--------------------- ---------------------
-- Generic_Sorting -- -- Generic_Sorting --
--------------------- ---------------------
...@@ -686,27 +617,8 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -686,27 +617,8 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Has_Element (Position : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then pragma Assert (Vet (Position), "bad cursor in Has_Element");
pragma Assert (Position.Container = null); return Position.Node /= 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; end Has_Element;
------------ ------------
...@@ -723,24 +635,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -723,24 +635,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
New_Node : Node_Access; New_Node : Node_Access;
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad cursor in Insert");
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); if Before.Container /= null
pragma Assert (Before.Node.Prev = null and then Before.Container /= Container'Unrestricted_Access
or else Before.Node.Prev.Next = Before.Node); then
pragma Assert (Before.Node.Next = null raise Program_Error;
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; end if;
if Count = 0 then if Count = 0 then
...@@ -884,32 +784,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -884,32 +784,6 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
end Iterate; end Iterate;
---------- ----------
-- Move --
----------
procedure Move (Target : in out List; Source : in out List) is
begin
if Target'Address = Source'Address then
return;
end if;
if Source.Busy > 0 then
raise Program_Error;
end if;
Clear (Target);
Target.First := Source.First;
Source.First := null;
Target.Last := Source.Last;
Source.Last := null;
Target.Length := Source.Length;
Source.Length := 0;
end Move;
----------
-- Last -- -- Last --
---------- ----------
...@@ -928,6 +802,10 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -928,6 +802,10 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Last_Element (Container : List) return Element_Type is function Last_Element (Container : List) return Element_Type is
begin begin
if Container.Last = null then
raise Constraint_Error;
end if;
return Container.Last.Element.all; return Container.Last.Element.all;
end Last_Element; end Last_Element;
...@@ -941,31 +819,43 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -941,31 +819,43 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
end Length; end Length;
---------- ----------
-- Move --
----------
procedure Move (Target : in out List; Source : in out List) is
begin
if Target'Address = Source'Address then
return;
end if;
if Source.Busy > 0 then
raise Program_Error;
end if;
Clear (Target);
Target.First := Source.First;
Source.First := null;
Target.Last := Source.Last;
Source.Last := null;
Target.Length := Source.Length;
Source.Length := 0;
end Move;
----------
-- Next -- -- Next --
---------- ----------
procedure Next (Position : in out Cursor) is procedure Next (Position : in out Cursor) is
begin begin
pragma Assert (Vet (Position), "bad cursor in procedure Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return; return;
end if; 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; Position.Node := Position.Node.Next;
if Position.Node = null then if Position.Node = null then
...@@ -975,26 +865,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -975,26 +865,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Next (Position : Cursor) return Cursor is function Next (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; 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 declare
Next_Node : constant Node_Access := Position.Node.Next; Next_Node : constant Node_Access := Position.Node.Next;
begin begin
...@@ -1025,26 +901,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1025,26 +901,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
procedure Previous (Position : in out Cursor) is procedure Previous (Position : in out Cursor) is
begin begin
pragma Assert (Vet (Position), "bad cursor in procedure Previous");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return; return;
end if; 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; Position.Node := Position.Node.Prev;
if Position.Node = null then if Position.Node = null then
...@@ -1054,26 +916,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1054,26 +916,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
function Previous (Position : Cursor) return Cursor is function Previous (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Previous");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; 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 declare
Prev_Node : constant Node_Access := Position.Node.Prev; Prev_Node : constant Node_Access := Position.Node.Prev;
begin begin
...@@ -1093,43 +941,34 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1093,43 +941,34 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : in Element_Type)) Process : not null access procedure (Element : in Element_Type))
is 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 begin
B := B + 1; pragma Assert (Vet (Position), "bad cursor in Query_Element");
L := L + 1;
if Position.Node = null then
raise Constraint_Error;
end if;
declare
C : List renames Position.Container.all'Unrestricted_Access.all;
B : Natural renames C.Busy;
L : Natural renames C.Lock;
begin begin
Process (E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; begin
B := B - 1; Process (Position.Node.Element.all);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Query_Element; end Query_Element;
---------- ----------
...@@ -1193,31 +1032,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1193,31 +1032,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
(Position : Cursor; (Position : Cursor;
By : Element_Type) By : Element_Type)
is 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 begin
pragma Assert (Vet (Position), "bad cursor in Replace_Element");
if Position.Container = null then
raise Constraint_Error;
end if;
if Position.Container.Lock > 0 then if Position.Container.Lock > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
Position.Node.Element := new Element_Type'(By); declare
Free (X); X : Element_Access := Position.Node.Element;
begin
Position.Node.Element := new Element_Type'(By);
Free (X);
end;
end Replace_Element; end Replace_Element;
------------------ ------------------
...@@ -1236,23 +1067,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1236,23 +1067,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Node := Container.Last; Node := Container.Last;
else else
if Position.Container /= List_Access'(Container'Unchecked_Access) then pragma Assert (Vet (Position), "bad cursor in Reverse_Find");
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; 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; end if;
while Node /= null loop while Node /= null loop
...@@ -1392,24 +1211,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1392,24 +1211,12 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Source : in out List) Source : in out List)
is is
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad cursor in Splice");
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); if Before.Container /= null
pragma Assert (Before.Node.Prev = null and then Before.Container /= Target'Unrestricted_Access
or else Before.Node.Prev.Next = Before.Node); then
pragma Assert (Before.Node.Next = null raise Program_Error;
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; end if;
if Target'Address = Source'Address if Target'Address = Source'Address
...@@ -1477,48 +1284,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1477,48 +1284,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Position : Cursor) Position : Cursor)
is is
begin begin
if Before.Node /= null then pragma Assert (Vet (Before), "bad Before cursor in Splice");
if Before.Container /= List_Access'(Target'Unchecked_Access) then pragma Assert (Vet (Position), "bad Position cursor in Splice");
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); if Before.Container /= null
pragma Assert (Before.Node.Prev = null and then Before.Container /= Target'Unchecked_Access
or else Before.Node.Prev.Next = Before.Node); then
pragma Assert (Before.Node.Next = null raise Program_Error;
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; end if;
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= List_Access'(Target'Unchecked_Access) then if Position.Container /= Target'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
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 if Position.Node = Before.Node
or else Position.Node.Next = Before.Node or else Position.Node.Next = Before.Node
then then
...@@ -1606,48 +1388,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1606,48 +1388,23 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
return; return;
end if; end if;
if Before.Node /= null then pragma Assert (Vet (Before), "bad Before cursor in Splice");
if Before.Container /= List_Access'(Target'Unchecked_Access) then pragma Assert (Vet (Position), "bad Position cursor in Splice");
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); if Before.Container /= null
pragma Assert (Before.Node.Prev = null and then Before.Container /= Target'Unrestricted_Access
or else Before.Node.Prev.Next = Before.Node); then
pragma Assert (Before.Node.Next = null raise Program_Error;
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; end if;
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= List_Access'(Source'Unchecked_Access) then if Position.Container /= Source'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
pragma Assert (Source.Length >= 1);
pragma Assert (Source.First.Prev = null);
pragma Assert (Source.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 = Source.First);
pragma Assert (Position.Node.Next /= null
or else Position.Node = Source.Last);
if Target.Length = Count_Type'Last then if Target.Length = Count_Type'Last then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
...@@ -1660,12 +1417,14 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1660,12 +1417,14 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
if Position.Node = Source.First then if Position.Node = Source.First then
Source.First := Position.Node.Next; Source.First := Position.Node.Next;
Source.First.Prev := null;
if Position.Node = Source.Last then if Position.Node = Source.Last then
pragma Assert (Source.First = null); pragma Assert (Source.First = null);
pragma Assert (Source.Length = 1); pragma Assert (Source.Length = 1);
Source.Last := null; Source.Last := null;
else
Source.First.Prev := null;
end if; end if;
elsif Position.Node = Source.Last then elsif Position.Node = Source.Last then
...@@ -1727,8 +1486,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1727,8 +1486,11 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
procedure Swap (I, J : Cursor) is procedure Swap (I, J : Cursor) is
begin begin
if I.Container = null pragma Assert (Vet (I), "bad I cursor in Swap");
or else J.Container = null pragma Assert (Vet (J), "bad J cursor in Swap");
if I.Node = null
or else J.Node = null
then then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
...@@ -1737,50 +1499,19 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1737,50 +1499,19 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
raise Program_Error; raise Program_Error;
end if; end if;
declare if I.Node = J.Node then
C : List renames I.Container.all; return;
begin end if;
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;
pragma Assert (C.Length > 1); if I.Container.Lock > 0 then
pragma Assert (J.Node /= null); raise Program_Error;
pragma Assert (J.Node.Element /= null); end if;
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 declare
EI_Copy : constant Element_Access := I.Node.Element; EI_Copy : constant Element_Access := I.Node.Element;
begin begin
I.Node.Element := J.Node.Element; I.Node.Element := J.Node.Element;
J.Node.Element := EI_Copy; J.Node.Element := EI_Copy;
end;
end; end;
end Swap; end Swap;
...@@ -1793,51 +1524,25 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1793,51 +1524,25 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
I, J : Cursor) I, J : Cursor)
is is
begin begin
if I.Container = null pragma Assert (Vet (I), "bad I cursor in Swap_Links");
or else J.Container = null pragma Assert (Vet (J), "bad J cursor in Swap_Links");
if I.Node = null
or else J.Node = null
then then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if I.Container /= List_Access'(Container'Unchecked_Access) then if I.Container /= Container'Unrestricted_Access
raise Program_Error; or else I.Container /= J.Container
end if; then
if J.Container /= I.Container then
raise Program_Error; raise Program_Error;
end if; 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 if I.Node = J.Node then
return; return;
end if; 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 if Container.Busy > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
...@@ -1878,45 +1583,179 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1878,45 +1583,179 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : in out Element_Type)) Process : not null access procedure (Element : in out Element_Type))
is 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 begin
B := B + 1; pragma Assert (Vet (Position), "bad cursor in Update_Element");
L := L + 1;
if Position.Node = null then
raise Constraint_Error;
end if;
declare
C : List renames Position.Container.all'Unrestricted_Access.all;
B : Natural renames C.Busy;
L : Natural renames C.Lock;
begin begin
Process (E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; begin
B := B - 1; Process (Position.Node.Element.all);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Update_Element; end Update_Element;
---------
-- Vet --
---------
function Vet (Position : Cursor) return Boolean is
begin
if Position.Node = null then
return Position.Container = null;
end if;
if Position.Container = null then
return False;
end if;
if Position.Node.Next = Position.Node then
return False;
end if;
if Position.Node.Prev = Position.Node then
return False;
end if;
if Position.Node.Element = null then
return False;
end if;
declare
L : List renames Position.Container.all;
begin
if L.Length = 0 then
return False;
end if;
if L.First = null then
return False;
end if;
if L.Last = null then
return False;
end if;
if L.First.Prev /= null then
return False;
end if;
if L.Last.Next /= null then
return False;
end if;
if Position.Node.Prev = null
and then Position.Node /= L.First
then
return False;
end if;
if Position.Node.Next = null
and then Position.Node /= L.Last
then
return False;
end if;
if L.Length = 1 then
return L.First = L.Last;
end if;
if L.First = L.Last then
return False;
end if;
if L.First.Next = null then
return False;
end if;
if L.Last.Prev = null then
return False;
end if;
if L.First.Next.Prev /= L.First then
return False;
end if;
if L.Last.Prev.Next /= L.Last then
return False;
end if;
if L.Length = 2 then
if L.First.Next /= L.Last then
return False;
end if;
if L.Last.Prev /= L.First then
return False;
end if;
return True;
end if;
if L.First.Next = L.Last then
return False;
end if;
if L.Last.Prev = L.First then
return False;
end if;
if Position.Node = L.First then
return True;
end if;
if Position.Node = L.Last then
return True;
end if;
if Position.Node.Next = null then
return False;
end if;
if Position.Node.Prev = null then
return False;
end if;
if Position.Node.Next.Prev /= Position.Node then
return False;
end if;
if Position.Node.Prev.Next /= Position.Node then
return False;
end if;
if L.Length = 3 then
if L.First.Next /= Position.Node then
return False;
end if;
if L.Last.Prev /= Position.Node then
return False;
end if;
end if;
return True;
end;
end Vet;
----------- -----------
-- Write -- -- Write --
----------- -----------
...@@ -1926,8 +1765,10 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is ...@@ -1926,8 +1765,10 @@ package body Ada.Containers.Indefinite_Doubly_Linked_Lists is
Item : List) Item : List)
is is
Node : Node_Access := Item.First; Node : Node_Access := Item.First;
begin begin
Count_Type'Base'Write (Stream, Item.Length); Count_Type'Base'Write (Stream, Item.Length);
while Node /= null loop while Node /= null loop
Element_Type'Output (Stream, Node.Element.all); -- X.all Element_Type'Output (Stream, Node.Element.all); -- X.all
Node := Node.Next; Node := Node.Next;
......
...@@ -194,19 +194,16 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -194,19 +194,16 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
procedure Delete (Container : in out Map; Position : in out Cursor) is procedure Delete (Container : in out Map; Position : in out Cursor) is
begin begin
pragma Assert (Vet (Position), "bad cursor in Delete");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
return;
end if; end if;
if Position.Container /= Map_Access'(Container'Unchecked_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
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 if Container.HT.Busy > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
...@@ -222,14 +219,24 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -222,14 +219,24 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
------------- -------------
function Element (Container : Map; Key : Key_Type) return Element_Type is function Element (Container : Map; Key : Key_Type) return Element_Type is
C : constant Cursor := Find (Container, Key); Node : constant Node_Access := Key_Ops.Find (Container.HT, Key);
begin begin
return C.Node.Element.all; if Node = null then
raise Constraint_Error;
end if;
return Node.Element.all;
end Element; end Element;
function Element (Position : Cursor) return Element_Type is function Element (Position : Cursor) return Element_Type is
begin begin
pragma Assert (Vet (Position)); pragma Assert (Vet (Position), "bad cursor in function Element");
if Position.Node = null then
raise Constraint_Error;
end if;
return Position.Node.Element.all; return Position.Node.Element.all;
end Element; end Element;
...@@ -251,8 +258,15 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -251,8 +258,15 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function Equivalent_Keys (Left, Right : Cursor) return Boolean is function Equivalent_Keys (Left, Right : Cursor) return Boolean is
begin begin
pragma Assert (Vet (Left)); pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
pragma Assert (Vet (Right)); pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Left.Node = null
or else Right.Node = null
then
raise Constraint_Error;
end if;
return Equivalent_Keys (Left.Node.Key.all, Right.Node.Key.all); return Equivalent_Keys (Left.Node.Key.all, Right.Node.Key.all);
end Equivalent_Keys; end Equivalent_Keys;
...@@ -261,7 +275,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -261,7 +275,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
Right : Key_Type) return Boolean Right : Key_Type) return Boolean
is is
begin begin
pragma Assert (Vet (Left)); pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
if Left.Node = null then
raise Constraint_Error;
end if;
return Equivalent_Keys (Left.Node.Key.all, Right); return Equivalent_Keys (Left.Node.Key.all, Right);
end Equivalent_Keys; end Equivalent_Keys;
...@@ -270,7 +289,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -270,7 +289,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
Right : Cursor) return Boolean Right : Cursor) return Boolean
is is
begin begin
pragma Assert (Vet (Right)); pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Right.Node = null then
raise Constraint_Error;
end if;
return Equivalent_Keys (Left, Right.Node.Key.all); return Equivalent_Keys (Left, Right.Node.Key.all);
end Equivalent_Keys; end Equivalent_Keys;
...@@ -338,6 +362,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -338,6 +362,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function First (Container : Map) return Cursor is function First (Container : Map) return Cursor is
Node : constant Node_Access := HT_Ops.First (Container.HT); Node : constant Node_Access := HT_Ops.First (Container.HT);
begin begin
if Node = null then if Node = null then
return No_Element; return No_Element;
...@@ -396,13 +421,8 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -396,13 +421,8 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function Has_Element (Position : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then pragma Assert (Vet (Position), "bad cursor in Has_Element");
pragma Assert (Position.Container = null); return Position.Node /= null;
return False;
end if;
pragma Assert (Vet (Position));
return True;
end Has_Element; end Has_Element;
--------------- ---------------
...@@ -468,7 +488,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -468,7 +488,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
is is
function New_Node (Next : Node_Access) return Node_Access; function New_Node (Next : Node_Access) return Node_Access;
procedure Insert is procedure Local_Insert is
new Key_Ops.Generic_Conditional_Insert (New_Node); new Key_Ops.Generic_Conditional_Insert (New_Node);
-------------- --------------
...@@ -478,6 +498,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -478,6 +498,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function New_Node (Next : Node_Access) return Node_Access is function New_Node (Next : Node_Access) return Node_Access is
K : Key_Access := new Key_Type'(Key); K : Key_Access := new Key_Type'(Key);
E : Element_Access; E : Element_Access;
begin begin
E := new Element_Type'(New_Item); E := new Element_Type'(New_Item);
return new Node_Type'(K, E, Next); return new Node_Type'(K, E, Next);
...@@ -493,12 +514,18 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -493,12 +514,18 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
-- Start of processing for Insert -- Start of processing for Insert
begin begin
if HT.Length >= HT_Ops.Capacity (HT) then if HT_Ops.Capacity (HT) = 0 then
-- TODO: see note in a-cohama.adb. HT_Ops.Reserve_Capacity (HT, 1);
HT_Ops.Reserve_Capacity (HT, HT.Length + 1); end if;
Local_Insert (HT, Key, Position.Node, Inserted);
if Inserted
and then HT.Length > HT_Ops.Capacity (HT)
then
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if; end if;
Insert (HT, Key, Position.Node, Inserted);
Position.Container := Container'Unchecked_Access; Position.Container := Container'Unchecked_Access;
end Insert; end Insert;
...@@ -562,7 +589,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -562,7 +589,12 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function Key (Position : Cursor) return Key_Type is function Key (Position : Cursor) return Key_Type is
begin begin
pragma Assert (Vet (Position)); pragma Assert (Vet (Position), "bad cursor in function Key");
if Position.Node = null then
raise Constraint_Error;
end if;
return Position.Node.Key.all; return Position.Node.Key.all;
end Key; end Key;
...@@ -603,13 +635,13 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -603,13 +635,13 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function Next (Position : Cursor) return Cursor is function Next (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; end if;
declare declare
pragma Assert (Vet (Position));
HT : Hash_Table_Type renames Position.Container.HT; HT : Hash_Table_Type renames Position.Container.HT;
Node : constant Node_Access := HT_Ops.Next (HT, Position.Node); Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
...@@ -631,32 +663,40 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -631,32 +663,40 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
Process : not null access procedure (Key : Key_Type; Process : not null access procedure (Key : Key_Type;
Element : Element_Type)) Element : Element_Type))
is is
pragma Assert (Vet (Position)); begin
pragma Assert (Vet (Position), "bad cursor in Query_Element");
K : Key_Type renames Position.Node.Key.all;
E : Element_Type renames Position.Node.Element.all;
M : Map renames Position.Container.all; if Position.Node = null then
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all; raise Constraint_Error;
end if;
B : Natural renames HT.Busy; declare
L : Natural renames HT.Lock; M : Map renames Position.Container.all;
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
begin B : Natural renames HT.Busy;
B := B + 1; L : Natural renames HT.Lock;
L := L + 1;
begin begin
Process (K, E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; declare
B := B - 1; K : Key_Type renames Position.Node.Key.all;
E : Element_Type renames Position.Node.Element.all;
begin
Process (K, E);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Query_Element; end Query_Element;
---------- ----------
...@@ -748,15 +788,24 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -748,15 +788,24 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
--------------------- ---------------------
procedure Replace_Element (Position : Cursor; By : Element_Type) is procedure Replace_Element (Position : Cursor; By : Element_Type) is
pragma Assert (Vet (Position));
X : Element_Access := Position.Node.Element;
begin begin
pragma Assert (Vet (Position), "bad cursor in Replace_Element");
if Position.Node = null then
raise Constraint_Error;
end if;
if Position.Container.HT.Lock > 0 then if Position.Container.HT.Lock > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
Position.Node.Element := new Element_Type'(By); declare
Free_Element (X); X : Element_Access := Position.Node.Element;
begin
Position.Node.Element := new Element_Type'(By);
Free_Element (X);
end;
end Replace_Element; end Replace_Element;
---------------------- ----------------------
...@@ -789,32 +838,40 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -789,32 +838,40 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
Process : not null access procedure (Key : Key_Type; Process : not null access procedure (Key : Key_Type;
Element : in out Element_Type)) Element : in out Element_Type))
is is
pragma Assert (Vet (Position)); begin
pragma Assert (Vet (Position), "bad cursor in Update_Element");
K : Key_Type renames Position.Node.Key.all; if Position.Node = null then
E : Element_Type renames Position.Node.Element.all; raise Constraint_Error;
end if;
M : Map renames Position.Container.all; declare
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all; M : Map renames Position.Container.all;
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
B : Natural renames HT.Busy; B : Natural renames HT.Busy;
L : Natural renames HT.Lock; L : Natural renames HT.Lock;
begin
B := B + 1;
L := L + 1;
begin begin
Process (K, E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; declare
B := B - 1; K : Key_Type renames Position.Node.Key.all;
E : Element_Type renames Position.Node.Element.all;
begin
Process (K, E);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Update_Element; end Update_Element;
--------- ---------
...@@ -824,6 +881,10 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -824,6 +881,10 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
function Vet (Position : Cursor) return Boolean is function Vet (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then if Position.Node = null then
return Position.Container = null;
end if;
if Position.Container = null then
return False; return False;
end if; end if;
...@@ -842,12 +903,15 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -842,12 +903,15 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
declare declare
HT : Hash_Table_Type renames Position.Container.HT; HT : Hash_Table_Type renames Position.Container.HT;
X : Node_Access; X : Node_Access;
begin begin
if HT.Length = 0 then if HT.Length = 0 then
return False; return False;
end if; end if;
if HT.Buckets = null then if HT.Buckets = null
or else HT.Buckets'Length = 0
then
return False; return False;
end if; end if;
...@@ -862,7 +926,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is ...@@ -862,7 +926,7 @@ package body Ada.Containers.Indefinite_Hashed_Maps is
return False; return False;
end if; end if;
if X = X.Next then -- weird if X = X.Next then -- to prevent endless loop
return False; return False;
end if; end if;
......
...@@ -84,13 +84,15 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -84,13 +84,15 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
pragma Inline (Read_Node); pragma Inline (Read_Node);
procedure Replace_Element procedure Replace_Element
(HT : in out Hash_Table_Type; (HT : in out Hash_Table_Type;
Node : Node_Access; Node : Node_Access;
Element : Element_Type); New_Item : Element_Type);
procedure Set_Next (Node : Node_Access; Next : Node_Access); procedure Set_Next (Node : Node_Access; Next : Node_Access);
pragma Inline (Set_Next); pragma Inline (Set_Next);
function Vet (Position : Cursor) return Boolean;
procedure Write_Node procedure Write_Node
(Stream : access Root_Stream_Type'Class; (Stream : access Root_Stream_Type'Class;
Node : Node_Access); Node : Node_Access);
...@@ -217,11 +219,17 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -217,11 +219,17 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Position : in out Cursor) Position : in out Cursor)
is is
begin begin
pragma Assert (Vet (Position), "bad cursor in Delete");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Set_Access'(Container'Unchecked_Access) then if Position.Node.Element = null then
raise Program_Error;
end if;
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
...@@ -232,7 +240,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -232,7 +240,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node); HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node);
Free (Position.Node); Free (Position.Node);
Position.Container := null; Position.Container := null;
end Delete; end Delete;
...@@ -351,6 +358,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -351,6 +358,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Element (Position : Cursor) return Element_Type is function Element (Position : Cursor) return Element_Type is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Element");
if Position.Node = null then
raise Constraint_Error;
end if;
if Position.Node.Element = null then -- handle dangling reference
raise Program_Error;
end if;
return Position.Node.Element.all; return Position.Node.Element.all;
end Element; end Element;
...@@ -370,6 +387,21 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -370,6 +387,21 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Equivalent_Elements (Left, Right : Cursor) function Equivalent_Elements (Left, Right : Cursor)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Left.Node = null
or else Right.Node = null
then
raise Constraint_Error;
end if;
if Left.Node.Element = null -- handle dangling cursor reference
or else Right.Node.Element = null
then
raise Program_Error;
end if;
return Equivalent_Elements return Equivalent_Elements
(Left.Node.Element.all, (Left.Node.Element.all,
Right.Node.Element.all); Right.Node.Element.all);
...@@ -378,12 +410,32 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -378,12 +410,32 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Equivalent_Elements (Left : Cursor; Right : Element_Type) function Equivalent_Elements (Left : Cursor; Right : Element_Type)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
if Left.Node = null then
raise Constraint_Error;
end if;
if Left.Node.Element = null then -- handling dangling reference
raise Program_Error;
end if;
return Equivalent_Elements (Left.Node.Element.all, Right); return Equivalent_Elements (Left.Node.Element.all, Right);
end Equivalent_Elements; end Equivalent_Elements;
function Equivalent_Elements (Left : Element_Type; Right : Cursor) function Equivalent_Elements (Left : Element_Type; Right : Cursor)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Right.Node = null then
raise Constraint_Error;
end if;
if Right.Node.Element = null then -- handle dangling cursor reference
raise Program_Error;
end if;
return Equivalent_Elements (Left, Right.Node.Element.all); return Equivalent_Elements (Left, Right.Node.Element.all);
end Equivalent_Elements; end Equivalent_Elements;
...@@ -520,6 +572,8 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -520,6 +572,8 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
return; return;
end if; end if;
X.Next := X; -- detect mischief (in Vet)
begin begin
Free_Element (X.Element); Free_Element (X.Element);
exception exception
...@@ -538,12 +592,8 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -538,12 +592,8 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Has_Element (Position : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then pragma Assert (Vet (Position), "bad cursor in Has_Element");
pragma Assert (Position.Container = null); return Position.Node /= null;
return False;
end if;
return True;
end Has_Element; end Has_Element;
--------------- ---------------
...@@ -597,7 +647,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -597,7 +647,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function New_Node (Next : Node_Access) return Node_Access; function New_Node (Next : Node_Access) return Node_Access;
pragma Inline (New_Node); pragma Inline (New_Node);
procedure Insert is procedure Local_Insert is
new Element_Keys.Generic_Conditional_Insert (New_Node); new Element_Keys.Generic_Conditional_Insert (New_Node);
-------------- --------------
...@@ -620,12 +670,18 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -620,12 +670,18 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
-- Start of processing for Insert -- Start of processing for Insert
begin begin
if HT.Length >= HT_Ops.Capacity (HT) then if HT_Ops.Capacity (HT) = 0 then
-- TODO: optimize this (see a-cohase.adb) HT_Ops.Reserve_Capacity (HT, 1);
HT_Ops.Reserve_Capacity (HT, HT.Length + 1); end if;
Local_Insert (HT, New_Item, Position.Node, Inserted);
if Inserted
and then HT.Length > HT_Ops.Capacity (HT)
then
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if; end if;
Insert (HT, New_Item, Position.Node, Inserted);
Position.Container := Container'Unchecked_Access; Position.Container := Container'Unchecked_Access;
end Insert; end Insert;
...@@ -763,7 +819,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -763,7 +819,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Is_Empty (Container : Set) return Boolean is function Is_Empty (Container : Set) return Boolean is
begin begin
return Container.Length = 0; return Container.HT.Length = 0;
end Is_Empty; end Is_Empty;
----------- -----------
...@@ -833,22 +889,14 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -833,22 +889,14 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
end Process_Node; end Process_Node;
HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT; HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
B : Natural renames HT.Busy;
-- Start of processing for Iterate -- Start of processing for Iterate
begin begin
B := B + 1; -- TODO: resolve whether HT_Ops.Generic_Iteration should
-- manipulate busy bit.
begin
Iterate (HT);
exception
when others =>
B := B - 1;
raise;
end;
B := B - 1; Iterate (HT);
end Iterate; end Iterate;
------------ ------------
...@@ -880,11 +928,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -880,11 +928,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Next (Position : Cursor) return Cursor is function Next (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; end if;
if Position.Node.Element = null then
raise Program_Error;
end if;
declare declare
HT : Hash_Table_Type renames Position.Container.HT; HT : Hash_Table_Type renames Position.Container.HT;
Node : constant Node_Access := HT_Ops.Next (HT, Position.Node); Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
...@@ -939,29 +992,40 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -939,29 +992,40 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : Element_Type)) Process : not null access procedure (Element : Element_Type))
is is
E : Element_Type renames Position.Node.Element.all; begin
pragma Assert (Vet (Position), "bad cursor in Query_Element");
HT : Hash_Table_Type renames if Position.Node = null then
Position.Container'Unrestricted_Access.all.HT; raise Constraint_Error;
end if;
B : Natural renames HT.Busy; if Position.Node.Element = null then
L : Natural renames HT.Lock; raise Program_Error;
end if;
begin declare
B := B + 1; HT : Hash_Table_Type renames
L := L + 1; Position.Container'Unrestricted_Access.all.HT;
B : Natural renames HT.Busy;
L : Natural renames HT.Lock;
begin begin
Process (E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; begin
B := B - 1; Process (Position.Node.Element.all);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end;
end Query_Element; end Query_Element;
---------- ----------
...@@ -1027,13 +1091,13 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1027,13 +1091,13 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
--------------------- ---------------------
procedure Replace_Element procedure Replace_Element
(HT : in out Hash_Table_Type; (HT : in out Hash_Table_Type;
Node : Node_Access; Node : Node_Access;
Element : Element_Type) New_Item : Element_Type)
is is
begin begin
if Equivalent_Elements (Node.Element.all, Element) then if Equivalent_Elements (Node.Element.all, New_Item) then
pragma Assert (Hash (Node.Element.all) = Hash (Element)); pragma Assert (Hash (Node.Element.all) = Hash (New_Item));
if HT.Lock > 0 then if HT.Lock > 0 then
raise Program_Error; raise Program_Error;
...@@ -1042,7 +1106,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1042,7 +1106,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
declare declare
X : Element_Access := Node.Element; X : Element_Access := Node.Element;
begin begin
Node.Element := new Element_Type'(Element); -- OK if fails Node.Element := new Element_Type'(New_Item); -- OK if fails
Free_Element (X); Free_Element (X);
end; end;
...@@ -1068,7 +1132,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1068,7 +1132,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function New_Node (Next : Node_Access) return Node_Access is function New_Node (Next : Node_Access) return Node_Access is
begin begin
Node.Element := new Element_Type'(Element); -- OK if fails Node.Element := new Element_Type'(New_Item); -- OK if fails
Node.Next := Next; Node.Next := Next;
return Node; return Node;
end New_Node; end New_Node;
...@@ -1084,7 +1148,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1084,7 +1148,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Attempt_Insert : begin Attempt_Insert : begin
Insert Insert
(HT => HT, (HT => HT,
Key => Element, Key => New_Item,
Node => Result, Node => Result,
Inserted => Inserted); Inserted => Inserted);
exception exception
...@@ -1093,7 +1157,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1093,7 +1157,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
end Attempt_Insert; end Attempt_Insert;
if Inserted then if Inserted then
pragma Assert (Result = Node);
Free_Element (X); -- Just propagate if fails Free_Element (X); -- Just propagate if fails
return; return;
end if; end if;
...@@ -1137,22 +1200,26 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1137,22 +1200,26 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
end Replace_Element; end Replace_Element;
procedure Replace_Element procedure Replace_Element
(Container : Set; (Container : in out Set;
Position : Cursor; Position : Cursor;
By : Element_Type) New_Item : Element_Type)
is is
HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
begin begin
pragma Assert (Vet (Position), "bad cursor in Replace_Element");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Set_Access'(Container'Unrestricted_Access) then if Position.Node.Element = null then
raise Program_Error;
end if;
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
Replace_Element (HT, Position.Node, By); Replace_Element (Container.HT, Position.Node, New_Item);
end Replace_Element; end Replace_Element;
---------------------- ----------------------
...@@ -1613,6 +1680,65 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1613,6 +1680,65 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
return (Controlled with HT => (Buckets, Length, 0, 0)); return (Controlled with HT => (Buckets, Length, 0, 0));
end Union; end Union;
---------
-- Vet --
---------
function Vet (Position : Cursor) return Boolean is
begin
if Position.Node = null then
return Position.Container = null;
end if;
if Position.Container = null then
return False;
end if;
if Position.Node.Next = Position.Node 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
or else HT.Buckets'Length = 0
then
return False;
end if;
X := HT.Buckets (Element_Keys.Index (HT, Position.Node.Element.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 -- to prevent unnecessary looping
return False;
end if;
X := X.Next;
end loop;
return False;
end;
end Vet;
----------- -----------
-- Write -- -- Write --
----------- -----------
...@@ -1714,29 +1840,9 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1714,29 +1840,9 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
(Key : Key_Type; (Key : Key_Type;
Node : Node_Access) return Boolean is Node : Node_Access) return Boolean is
begin begin
return Equivalent_Keys (Key, Node.Element.all); return Equivalent_Keys (Key, Generic_Keys.Key (Node.Element.all));
end Equivalent_Key_Node; end Equivalent_Key_Node;
---------------------
-- Equivalent_Keys --
---------------------
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;
------------- -------------
-- Exclude -- -- Exclude --
------------- -------------
...@@ -1775,6 +1881,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1775,6 +1881,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function Key (Position : Cursor) return Key_Type is function Key (Position : Cursor) return Key_Type is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Key");
if Position.Node = null then
raise Constraint_Error;
end if;
if Position.Node.Element = null then
raise Program_Error;
end if;
return Key (Position.Node.Element.all); return Key (Position.Node.Element.all);
end Key; end Key;
...@@ -1804,20 +1920,40 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1804,20 +1920,40 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Process : not null access Process : not null access
procedure (Element : in out Element_Type)) procedure (Element : in out Element_Type))
is is
HT : Hash_Table_Type renames Container.HT; HT : Hash_Table_Type renames Container.HT;
Indx : Hash_Type;
begin begin
pragma Assert
(Vet (Position),
"bad cursor in Update_Element_Preserving_Key");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Set_Access'(Container'Unchecked_Access) then if Position.Node.Element = null
or else Position.Node.Next = Position.Node
then
raise Program_Error; raise Program_Error;
end if; end if;
if Position.Container /= Container'Unrestricted_Access then
raise Program_Error;
end if;
if HT.Buckets = null
or else HT.Buckets'Length = 0
or else HT.Length = 0
then
raise Program_Error;
end if;
Indx := HT_Ops.Index (HT, Position.Node);
declare declare
E : Element_Type renames Position.Node.Element.all; E : Element_Type renames Position.Node.Element.all;
K : Key_Type renames Key (E); K : constant Key_Type := Key (E);
B : Natural renames HT.Busy; B : Natural renames HT.Busy;
L : Natural renames HT.Lock; L : Natural renames HT.Lock;
...@@ -1838,16 +1974,38 @@ package body Ada.Containers.Indefinite_Hashed_Sets is ...@@ -1838,16 +1974,38 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
L := L - 1; L := L - 1;
B := B - 1; B := B - 1;
if Equivalent_Keys (K, E) then if Equivalent_Keys (K, Key (E)) then
pragma Assert (Hash (K) = Hash (E)); pragma Assert (Hash (K) = Hash (E));
return; return;
end if; end if;
end; end;
if HT.Buckets (Indx) = Position.Node then
HT.Buckets (Indx) := Position.Node.Next;
else
declare
Prev : Node_Access := HT.Buckets (Indx);
begin
while Prev.Next /= Position.Node loop
Prev := Prev.Next;
if Prev = null then
raise Program_Error;
end if;
end loop;
Prev.Next := Position.Node.Next;
end;
end if;
HT.Length := HT.Length - 1;
declare declare
X : Node_Access := Position.Node; X : Node_Access := Position.Node;
begin begin
HT_Ops.Delete_Node_Sans_Free (HT, X);
Free (X); Free (X);
end; end;
......
...@@ -49,8 +49,7 @@ generic ...@@ -49,8 +49,7 @@ generic
with function "=" (Left, Right : Element_Type) return Boolean is <>; with function "=" (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Indefinite_Hashed_Sets is package Ada.Containers.Indefinite_Hashed_Sets is
pragma Preelaborate;
pragma Preelaborate (Indefinite_Hashed_Sets);
type Set is tagged private; type Set is tagged private;
...@@ -64,6 +63,12 @@ package Ada.Containers.Indefinite_Hashed_Sets is ...@@ -64,6 +63,12 @@ package Ada.Containers.Indefinite_Hashed_Sets is
function Equivalent_Sets (Left, Right : Set) return Boolean; function Equivalent_Sets (Left, Right : Set) return Boolean;
function Capacity (Container : Set) return Count_Type;
procedure Reserve_Capacity
(Container : in out Set;
Capacity : Count_Type);
function Length (Container : Set) return Count_Type; function Length (Container : Set) return Count_Type;
function Is_Empty (Container : Set) return Boolean; function Is_Empty (Container : Set) return Boolean;
...@@ -72,15 +77,15 @@ package Ada.Containers.Indefinite_Hashed_Sets is ...@@ -72,15 +77,15 @@ package Ada.Containers.Indefinite_Hashed_Sets is
function Element (Position : Cursor) return Element_Type; function Element (Position : Cursor) return Element_Type;
procedure Replace_Element
(Container : in out Set;
Position : Cursor;
New_Item : Element_Type);
procedure Query_Element procedure Query_Element
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : Element_Type)); Process : not null access procedure (Element : Element_Type));
procedure Replace_Element
(Container : Set;
Position : Cursor;
By : Element_Type);
procedure Move procedure Move
(Target : in out Set; (Target : in out Set;
Source : in out Set); Source : in out Set);
...@@ -97,37 +102,11 @@ package Ada.Containers.Indefinite_Hashed_Sets is ...@@ -97,37 +102,11 @@ package Ada.Containers.Indefinite_Hashed_Sets is
procedure Replace (Container : in out Set; New_Item : Element_Type); procedure Replace (Container : in out Set; New_Item : Element_Type);
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 Exclude (Container : in out Set; Item : Element_Type);
function Contains (Container : Set; Item : Element_Type) return Boolean; procedure Delete (Container : in out Set; Item : Element_Type);
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 procedure Delete (Container : in out Set; Position : in out Cursor);
(Container : Set;
Process : not null access procedure (Position : Cursor));
procedure Union (Target : in out Set; Source : Set); procedure Union (Target : in out Set; Source : Set);
...@@ -158,41 +137,59 @@ package Ada.Containers.Indefinite_Hashed_Sets is ...@@ -158,41 +137,59 @@ package Ada.Containers.Indefinite_Hashed_Sets is
function Is_Subset (Subset : Set; Of_Set : Set) return Boolean; function Is_Subset (Subset : Set; Of_Set : Set) return Boolean;
function Capacity (Container : Set) return Count_Type; function First (Container : Set) return Cursor;
procedure Reserve_Capacity function Next (Position : Cursor) return Cursor;
(Container : in out Set;
Capacity : Count_Type); procedure Next (Position : in out Cursor);
function Find (Container : Set; Item : Element_Type) return Cursor;
function Contains (Container : Set; Item : Element_Type) return Boolean;
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));
generic generic
type Key_Type (<>) is limited private; type Key_Type (<>) is private;
with function Key (Element : Element_Type) return Key_Type; with function Key (Element : Element_Type) return Key_Type;
with function Hash (Key : Key_Type) return Hash_Type; with function Hash (Key : Key_Type) return Hash_Type;
with function Equivalent_Keys with function Equivalent_Keys (Left, Right : Key_Type) return Boolean;
(Key : Key_Type;
Element : Element_Type) return Boolean;
package Generic_Keys is package Generic_Keys is
function Contains (Container : Set; Key : Key_Type) return Boolean;
function Find (Container : Set; Key : Key_Type) return Cursor;
function Key (Position : Cursor) return Key_Type; function Key (Position : Cursor) return Key_Type;
function Element (Container : Set; Key : Key_Type) return Element_Type; function Element (Container : Set; Key : Key_Type) return Element_Type;
procedure Replace procedure Replace -- TODO: ask Randy why this is still here
(Container : in out Set; (Container : in out Set;
Key : Key_Type; Key : Key_Type;
New_Item : Element_Type); New_Item : Element_Type);
procedure Exclude (Container : in out Set; Key : Key_Type);
procedure Delete (Container : in out Set; Key : Key_Type); procedure Delete (Container : in out Set; Key : Key_Type);
procedure Exclude (Container : in out Set; Key : Key_Type); function Find (Container : Set; Key : Key_Type) return Cursor;
function Contains (Container : Set; Key : Key_Type) return Boolean;
procedure Update_Element_Preserving_Key procedure Update_Element_Preserving_Key
(Container : in out Set; (Container : in out Set;
...@@ -200,13 +197,6 @@ package Ada.Containers.Indefinite_Hashed_Sets is ...@@ -200,13 +197,6 @@ package Ada.Containers.Indefinite_Hashed_Sets is
Process : not null access Process : not null access
procedure (Element : in out Element_Type)); procedure (Element : in out Element_Type));
function Equivalent_Keys
(Left : Cursor;
Right : Key_Type) return Boolean;
function Equivalent_Keys
(Left : Key_Type;
Right : Cursor) return Boolean;
end Generic_Keys; end Generic_Keys;
private private
......
...@@ -369,6 +369,21 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -369,6 +369,21 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
return Position.Node.Element.all; return Position.Node.Element.all;
end Element; end Element;
-------------------------
-- Equivalent_Elements --
-------------------------
function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
begin
if Left < Right
or else Right < Left
then
return False;
else
return True;
end if;
end Equivalent_Elements;
--------------------- ---------------------
-- Equivalent_Sets -- -- Equivalent_Sets --
--------------------- ---------------------
...@@ -528,34 +543,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -528,34 +543,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
Is_Less_Key_Node => Is_Less_Key_Node, Is_Less_Key_Node => Is_Less_Key_Node,
Is_Greater_Key_Node => Is_Greater_Key_Node); Is_Greater_Key_Node => Is_Greater_Key_Node);
---------
-- "<" --
---------
function "<" (Left : Key_Type; Right : Cursor) return Boolean is
begin
return Left < Right.Node.Element.all;
end "<";
function "<" (Left : Cursor; Right : Key_Type) return Boolean is
begin
return Right > Left.Node.Element.all;
end "<";
---------
-- ">" --
---------
function ">" (Left : Key_Type; Right : Cursor) return Boolean is
begin
return Left > Right.Node.Element.all;
end ">";
function ">" (Left : Cursor; Right : Key_Type) return Boolean is
begin
return Right < Left.Node.Element.all;
end ">";
------------- -------------
-- Ceiling -- -- Ceiling --
------------- -------------
...@@ -609,6 +596,21 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -609,6 +596,21 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
return Node.Element.all; return Node.Element.all;
end Element; end Element;
---------------------
-- Equivalent_Keys --
---------------------
function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
begin
if Left < Right
or else Right < Left
then
return False;
else
return True;
end if;
end Equivalent_Keys;
------------- -------------
-- Exclude -- -- Exclude --
------------- -------------
...@@ -663,7 +665,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -663,7 +665,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
(Left : Key_Type; (Left : Key_Type;
Right : Node_Access) return Boolean is Right : Node_Access) return Boolean is
begin begin
return Left > Right.Element.all; return Key (Right.Element.all) < Left;
end Is_Greater_Key_Node; end Is_Greater_Key_Node;
---------------------- ----------------------
...@@ -674,7 +676,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -674,7 +676,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
(Left : Key_Type; (Left : Key_Type;
Right : Node_Access) return Boolean is Right : Node_Access) return Boolean is
begin begin
return Left < Right.Element.all; return Left < Key (Right.Element.all);
end Is_Less_Key_Node; end Is_Less_Key_Node;
--------- ---------
...@@ -728,7 +730,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -728,7 +730,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
declare declare
E : Element_Type renames Position.Node.Element.all; E : Element_Type renames Position.Node.Element.all;
K : Key_Type renames Key (E); K : constant Key_Type := Key (E);
B : Natural renames Tree.Busy; B : Natural renames Tree.Busy;
L : Natural renames Tree.Lock; L : Natural renames Tree.Lock;
...@@ -749,11 +751,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -749,11 +751,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
L := L - 1; L := L - 1;
B := B - 1; B := B - 1;
if K < E if Equivalent_Keys (K, Key (E)) then
or else K > E
then
null;
else
return; return;
end if; end if;
end; end;
...@@ -1365,12 +1363,10 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -1365,12 +1363,10 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
end Replace_Element; end Replace_Element;
procedure Replace_Element procedure Replace_Element
(Container : Set; (Container : in out Set;
Position : Cursor; Position : Cursor;
By : Element_Type) New_Item : Element_Type)
is is
Tree : Tree_Type renames Position.Container.Tree'Unrestricted_Access.all;
begin begin
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
...@@ -1380,7 +1376,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is ...@@ -1380,7 +1376,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
raise Program_Error; raise Program_Error;
end if; end if;
Replace_Element (Tree, Position.Node, By); Replace_Element (Container.Tree, Position.Node, New_Item);
end Replace_Element; end Replace_Element;
--------------------- ---------------------
......
...@@ -45,7 +45,9 @@ generic ...@@ -45,7 +45,9 @@ generic
with function "=" (Left, Right : Element_Type) return Boolean is <>; with function "=" (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Indefinite_Ordered_Sets is package Ada.Containers.Indefinite_Ordered_Sets is
pragma Preelaborate (Indefinite_Ordered_Sets); pragma Preelaborate;
function Equivalent_Elements (Left, Right : Element_Type) return Boolean;
type Set is tagged private; type Set is tagged private;
...@@ -67,15 +69,15 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -67,15 +69,15 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
function Element (Position : Cursor) return Element_Type; function Element (Position : Cursor) return Element_Type;
procedure Replace_Element
(Container : in out Set;
Position : Cursor;
New_Item : Element_Type);
procedure Query_Element procedure Query_Element
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : Element_Type)); Process : not null access procedure (Element : 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); procedure Move (Target : in out Set; Source : in out Set);
procedure Insert procedure Insert
...@@ -96,6 +98,10 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -96,6 +98,10 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
(Container : in out Set; (Container : in out Set;
New_Item : Element_Type); New_Item : Element_Type);
procedure Exclude
(Container : in out Set;
Item : Element_Type);
procedure Delete procedure Delete
(Container : in out Set; (Container : in out Set;
Item : Element_Type); Item : Element_Type);
...@@ -108,10 +114,6 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -108,10 +114,6 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
procedure Delete_Last (Container : in out Set); procedure Delete_Last (Container : in out Set);
procedure Exclude
(Container : in out Set;
Item : Element_Type);
procedure Union (Target : in out Set; Source : Set); procedure Union (Target : in out Set; Source : Set);
function Union (Left, Right : Set) return Set; function Union (Left, Right : Set) return Set;
...@@ -124,8 +126,7 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -124,8 +126,7 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
function "and" (Left, Right : Set) return Set renames Intersection; function "and" (Left, Right : Set) return Set renames Intersection;
procedure Difference (Target : in out Set; procedure Difference (Target : in out Set; Source : Set);
Source : Set);
function Difference (Left, Right : Set) return Set; function Difference (Left, Right : Set) return Set;
...@@ -141,14 +142,6 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -141,14 +142,6 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
function Is_Subset (Subset : Set; Of_Set : Set) return Boolean; 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 Floor (Container : Set; Item : Element_Type) return Cursor;
function Ceiling (Container : Set; Item : Element_Type) return Cursor;
function First (Container : Set) return Cursor; function First (Container : Set) return Cursor;
function First_Element (Container : Set) return Element_Type; function First_Element (Container : Set) return Element_Type;
...@@ -165,6 +158,14 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -165,6 +158,14 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
procedure Previous (Position : in out Cursor); procedure Previous (Position : in out Cursor);
function Find (Container : Set; Item : Element_Type) return Cursor;
function Floor (Container : Set; Item : Element_Type) return Cursor;
function Ceiling (Container : Set; Item : Element_Type) return Cursor;
function Contains (Container : Set; Item : Element_Type) return Boolean;
function Has_Element (Position : Cursor) return Boolean; function Has_Element (Position : Cursor) return Boolean;
function "<" (Left, Right : Cursor) return Boolean; function "<" (Left, Right : Cursor) return Boolean;
...@@ -188,21 +189,28 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -188,21 +189,28 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
Process : not null access procedure (Position : Cursor)); Process : not null access procedure (Position : Cursor));
generic generic
type Key_Type (<>) is limited private; type Key_Type (<>) is private;
with function Key (Element : Element_Type) return Key_Type; with function Key (Element : Element_Type) return Key_Type;
with function "<" (Left : Key_Type; Right : Element_Type) with function "<" (Left, Right : Key_Type) return Boolean is <>;
return Boolean is <>;
with function ">" (Left : Key_Type; Right : Element_Type)
return Boolean is <>;
package Generic_Keys is package Generic_Keys is
function Contains function Equivalent_Keys (Left, Right : Key_Type) return Boolean;
(Container : Set;
Key : Key_Type) return Boolean; function Key (Position : Cursor) return Key_Type;
function Element (Container : Set; Key : Key_Type) return Element_Type;
procedure Replace
(Container : in out Set;
Key : Key_Type;
New_Item : Element_Type);
procedure Exclude (Container : in out Set; Key : Key_Type);
procedure Delete (Container : in out Set; Key : Key_Type);
function Find function Find
(Container : Set; (Container : Set;
...@@ -216,28 +224,9 @@ pragma Preelaborate (Indefinite_Ordered_Sets); ...@@ -216,28 +224,9 @@ pragma Preelaborate (Indefinite_Ordered_Sets);
(Container : Set; (Container : Set;
Key : Key_Type) return Cursor; Key : Key_Type) return Cursor;
function Key (Position : Cursor) return Key_Type; function Contains
function Element
(Container : Set; (Container : Set;
Key : Key_Type) return Element_Type; Key : Key_Type) return Boolean;
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);
procedure Exclude (Container : in out Set; Key : Key_Type);
function "<" (Left : Cursor; Right : Key_Type) return Boolean;
function ">" (Left : Cursor; Right : Key_Type) return Boolean;
function "<" (Left : Key_Type; Right : Cursor) return Boolean;
function ">" (Left : Key_Type; Right : Cursor) return Boolean;
procedure Update_Element_Preserving_Key procedure Update_Element_Preserving_Key
(Container : in out Set; (Container : in out Set;
......
...@@ -188,16 +188,16 @@ package body Ada.Containers.Hashed_Maps is ...@@ -188,16 +188,16 @@ package body Ada.Containers.Hashed_Maps is
procedure Delete (Container : in out Map; Position : in out Cursor) is procedure Delete (Container : in out Map; Position : in out Cursor) is
begin begin
pragma Assert (Vet (Position), "bad cursor in Delete");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Map_Access'(Container'Unchecked_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
pragma Assert (Position.Node.Next /= Position.Node);
if Container.HT.Busy > 0 then if Container.HT.Busy > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
...@@ -213,14 +213,24 @@ package body Ada.Containers.Hashed_Maps is ...@@ -213,14 +213,24 @@ package body Ada.Containers.Hashed_Maps is
------------- -------------
function Element (Container : Map; Key : Key_Type) return Element_Type is function Element (Container : Map; Key : Key_Type) return Element_Type is
C : constant Cursor := Find (Container, Key); Node : constant Node_Access := Key_Ops.Find (Container.HT, Key);
begin begin
return C.Node.Element; if Node = null then
raise Constraint_Error;
end if;
return Node.Element;
end Element; end Element;
function Element (Position : Cursor) return Element_Type is function Element (Position : Cursor) return Element_Type is
begin begin
pragma Assert (Vet (Position)); pragma Assert (Vet (Position), "bad cursor in function Element");
if Position.Node = null then
raise Constraint_Error;
end if;
return Position.Node.Element; return Position.Node.Element;
end Element; end Element;
...@@ -242,20 +252,37 @@ package body Ada.Containers.Hashed_Maps is ...@@ -242,20 +252,37 @@ package body Ada.Containers.Hashed_Maps is
function Equivalent_Keys (Left, Right : Cursor) function Equivalent_Keys (Left, Right : Cursor)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Left)); pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
pragma Assert (Vet (Right)); pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Left.Node = null
or else Right.Node = null
then
raise Constraint_Error;
end if;
return Equivalent_Keys (Left.Node.Key, Right.Node.Key); return Equivalent_Keys (Left.Node.Key, Right.Node.Key);
end Equivalent_Keys; end Equivalent_Keys;
function Equivalent_Keys (Left : Cursor; Right : Key_Type) return Boolean is function Equivalent_Keys (Left : Cursor; Right : Key_Type) return Boolean is
begin begin
pragma Assert (Vet (Left)); pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
if Left.Node = null then
raise Constraint_Error;
end if;
return Equivalent_Keys (Left.Node.Key, Right); return Equivalent_Keys (Left.Node.Key, Right);
end Equivalent_Keys; end Equivalent_Keys;
function Equivalent_Keys (Left : Key_Type; Right : Cursor) return Boolean is function Equivalent_Keys (Left : Key_Type; Right : Cursor) return Boolean is
begin begin
pragma Assert (Vet (Right)); pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Right.Node = null then
raise Constraint_Error;
end if;
return Equivalent_Keys (Left, Right.Node.Key); return Equivalent_Keys (Left, Right.Node.Key);
end Equivalent_Keys; end Equivalent_Keys;
...@@ -352,13 +379,8 @@ package body Ada.Containers.Hashed_Maps is ...@@ -352,13 +379,8 @@ package body Ada.Containers.Hashed_Maps is
function Has_Element (Position : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then pragma Assert (Vet (Position), "bad cursor in Has_Element");
pragma Assert (Position.Container = null); return Position.Node /= null;
return False;
end if;
pragma Assert (Vet (Position));
return True;
end Has_Element; end Has_Element;
--------------- ---------------
...@@ -435,25 +457,18 @@ package body Ada.Containers.Hashed_Maps is ...@@ -435,25 +457,18 @@ package body Ada.Containers.Hashed_Maps is
-- Start of processing for Insert -- Start of processing for Insert
begin begin
if HT.Length >= HT_Ops.Capacity (HT) then if HT_Ops.Capacity (HT) = 0 then
HT_Ops.Reserve_Capacity (HT, 1);
end if;
-- TODO: 17 Apr 2005 Local_Insert (HT, Key, Position.Node, Inserted);
-- 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); if Inserted
and then HT.Length > HT_Ops.Capacity (HT)
then
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if; end if;
Local_Insert (HT, Key, Position.Node, Inserted);
Position.Container := Container'Unchecked_Access; Position.Container := Container'Unchecked_Access;
end Insert; end Insert;
...@@ -485,12 +500,18 @@ package body Ada.Containers.Hashed_Maps is ...@@ -485,12 +500,18 @@ package body Ada.Containers.Hashed_Maps is
-- Start of processing for Insert -- Start of processing for Insert
begin begin
if HT.Length >= HT_Ops.Capacity (HT) then if HT_Ops.Capacity (HT) = 0 then
-- TODO: see note above. HT_Ops.Reserve_Capacity (HT, 1);
HT_Ops.Reserve_Capacity (HT, HT.Length + 1);
end if; end if;
Local_Insert (HT, Key, Position.Node, Inserted); Local_Insert (HT, Key, Position.Node, Inserted);
if Inserted
and then HT.Length > HT_Ops.Capacity (HT)
then
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if;
Position.Container := Container'Unchecked_Access; Position.Container := Container'Unchecked_Access;
end Insert; end Insert;
...@@ -553,7 +574,12 @@ package body Ada.Containers.Hashed_Maps is ...@@ -553,7 +574,12 @@ package body Ada.Containers.Hashed_Maps is
function Key (Position : Cursor) return Key_Type is function Key (Position : Cursor) return Key_Type is
begin begin
pragma Assert (Vet (Position)); pragma Assert (Vet (Position), "bad cursor in function Key");
if Position.Node = null then
raise Constraint_Error;
end if;
return Position.Node.Key; return Position.Node.Key;
end Key; end Key;
...@@ -589,16 +615,15 @@ package body Ada.Containers.Hashed_Maps is ...@@ -589,16 +615,15 @@ package body Ada.Containers.Hashed_Maps is
function Next (Position : Cursor) return Cursor is function Next (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; end if;
declare declare
pragma Assert (Vet (Position));
HT : Hash_Table_Type renames Position.Container.HT; HT : Hash_Table_Type renames Position.Container.HT;
Node : constant Node_Access := HT_Ops.Next (HT, Position.Node); Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
begin begin
if Node = null then if Node = null then
return No_Element; return No_Element;
...@@ -621,34 +646,41 @@ package body Ada.Containers.Hashed_Maps is ...@@ -621,34 +646,41 @@ package body Ada.Containers.Hashed_Maps is
(Position : Cursor; (Position : Cursor;
Process : not null access Process : not null access
procedure (Key : Key_Type; Element : Element_Type)) procedure (Key : Key_Type; Element : Element_Type))
is is
pragma Assert (Vet (Position)); begin
pragma Assert (Vet (Position), "bad cursor in Query_Element");
K : Key_Type renames Position.Node.Key;
E : Element_Type renames Position.Node.Element;
M : Map renames Position.Container.all; if Position.Node = null then
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all; raise Constraint_Error;
end if;
B : Natural renames HT.Busy; declare
L : Natural renames HT.Lock; M : Map renames Position.Container.all;
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
begin B : Natural renames HT.Busy;
B := B + 1; L : Natural renames HT.Lock;
L := L + 1;
begin begin
Process (K, E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1; declare
B := B - 1; K : Key_Type renames Position.Node.Key;
raise; E : Element_Type renames Position.Node.Element;
begin
Process (K, E);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end; end;
L := L - 1;
B := B - 1;
end Query_Element; end Query_Element;
---------- ----------
...@@ -712,15 +744,18 @@ package body Ada.Containers.Hashed_Maps is ...@@ -712,15 +744,18 @@ package body Ada.Containers.Hashed_Maps is
--------------------- ---------------------
procedure Replace_Element (Position : Cursor; By : Element_Type) is procedure Replace_Element (Position : Cursor; By : Element_Type) is
pragma Assert (Vet (Position));
E : Element_Type renames Position.Node.Element;
begin begin
pragma Assert (Vet (Position), "bad cursor in Replace_Element");
if Position.Node = null then
raise Constraint_Error;
end if;
if Position.Container.HT.Lock > 0 then if Position.Container.HT.Lock > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
E := By; Position.Node.Element := By;
end Replace_Element; end Replace_Element;
---------------------- ----------------------
...@@ -753,32 +788,40 @@ package body Ada.Containers.Hashed_Maps is ...@@ -753,32 +788,40 @@ package body Ada.Containers.Hashed_Maps is
Process : not null access procedure (Key : Key_Type; Process : not null access procedure (Key : Key_Type;
Element : in out Element_Type)) Element : in out Element_Type))
is is
pragma Assert (Vet (Position)); begin
pragma Assert (Vet (Position), "bad cursor in Update_Element");
K : Key_Type renames Position.Node.Key;
E : Element_Type renames Position.Node.Element;
M : Map renames Position.Container.all; if Position.Node = null then
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all; raise Constraint_Error;
end if;
B : Natural renames HT.Busy; declare
L : Natural renames HT.Lock; M : Map renames Position.Container.all;
HT : Hash_Table_Type renames M.HT'Unrestricted_Access.all;
begin B : Natural renames HT.Busy;
B := B + 1; L : Natural renames HT.Lock;
L := L + 1;
begin begin
Process (K, E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1; declare
B := B - 1; K : Key_Type renames Position.Node.Key;
raise; E : Element_Type renames Position.Node.Element;
begin
Process (K, E);
exception
when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1;
B := B - 1;
end; end;
L := L - 1;
B := B - 1;
end Update_Element; end Update_Element;
--------- ---------
...@@ -788,34 +831,32 @@ package body Ada.Containers.Hashed_Maps is ...@@ -788,34 +831,32 @@ package body Ada.Containers.Hashed_Maps is
function Vet (Position : Cursor) return Boolean is function Vet (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then if Position.Node = null then
return False; return Position.Container = null;
end if; end if;
if Position.Node.Next = Position.Node then if Position.Container = null then
return False; return False;
end if; end if;
if Position.Container = null then if Position.Node.Next = Position.Node then
return False; return False;
end if; end if;
declare declare
HT : Hash_Table_Type renames Position.Container.HT; HT : Hash_Table_Type renames Position.Container.HT;
X : Node_Access; X : Node_Access;
begin begin
if HT.Length = 0 then if HT.Length = 0 then
return False; return False;
end if; end if;
if HT.Buckets = null then if HT.Buckets = null
or else HT.Buckets'Length = 0
then
return False; return False;
end if; 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)); X := HT.Buckets (Key_Ops.Index (HT, Position.Node.Key));
for J in 1 .. HT.Length loop for J in 1 .. HT.Length loop
...@@ -827,7 +868,7 @@ package body Ada.Containers.Hashed_Maps is ...@@ -827,7 +868,7 @@ package body Ada.Containers.Hashed_Maps is
return False; return False;
end if; end if;
if X = X.Next then -- weird if X = X.Next then -- to prevent endless loop
return False; return False;
end if; end if;
......
...@@ -67,6 +67,8 @@ package body Ada.Containers.Hashed_Sets is ...@@ -67,6 +67,8 @@ package body Ada.Containers.Hashed_Sets is
(R_HT : Hash_Table_Type; (R_HT : Hash_Table_Type;
L_Node : Node_Access) return Boolean; L_Node : Node_Access) return Boolean;
procedure Free (X : in out Node_Access);
function Hash_Node (Node : Node_Access) return Hash_Type; function Hash_Node (Node : Node_Access) return Hash_Type;
pragma Inline (Hash_Node); pragma Inline (Hash_Node);
...@@ -83,13 +85,15 @@ package body Ada.Containers.Hashed_Sets is ...@@ -83,13 +85,15 @@ package body Ada.Containers.Hashed_Sets is
pragma Inline (Read_Node); pragma Inline (Read_Node);
procedure Replace_Element procedure Replace_Element
(HT : in out Hash_Table_Type; (HT : in out Hash_Table_Type;
Node : Node_Access; Node : Node_Access;
Element : Element_Type); New_Item : Element_Type);
procedure Set_Next (Node : Node_Access; Next : Node_Access); procedure Set_Next (Node : Node_Access; Next : Node_Access);
pragma Inline (Set_Next); pragma Inline (Set_Next);
function Vet (Position : Cursor) return Boolean;
procedure Write_Node procedure Write_Node
(Stream : access Root_Stream_Type'Class; (Stream : access Root_Stream_Type'Class;
Node : Node_Access); Node : Node_Access);
...@@ -99,9 +103,6 @@ package body Ada.Containers.Hashed_Sets is ...@@ -99,9 +103,6 @@ package body Ada.Containers.Hashed_Sets is
-- Local Instantiations -- -- Local Instantiations --
-------------------------- --------------------------
procedure Free is
new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
package HT_Ops is package HT_Ops is
new Hash_Tables.Generic_Operations new Hash_Tables.Generic_Operations
(HT_Types => HT_Types, (HT_Types => HT_Types,
...@@ -211,11 +212,13 @@ package body Ada.Containers.Hashed_Sets is ...@@ -211,11 +212,13 @@ package body Ada.Containers.Hashed_Sets is
Position : in out Cursor) Position : in out Cursor)
is is
begin begin
pragma Assert (Vet (Position), "bad cursor in Delete");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Set_Access'(Container'Unchecked_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
...@@ -226,7 +229,6 @@ package body Ada.Containers.Hashed_Sets is ...@@ -226,7 +229,6 @@ package body Ada.Containers.Hashed_Sets is
HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node); HT_Ops.Delete_Node_Sans_Free (Container.HT, Position.Node);
Free (Position.Node); Free (Position.Node);
Position.Container := null; Position.Container := null;
end Delete; end Delete;
...@@ -345,6 +347,12 @@ package body Ada.Containers.Hashed_Sets is ...@@ -345,6 +347,12 @@ package body Ada.Containers.Hashed_Sets is
function Element (Position : Cursor) return Element_Type is function Element (Position : Cursor) return Element_Type is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Element");
if Position.Node = null then
raise Constraint_Error;
end if;
return Position.Node.Element; return Position.Node.Element;
end Element; end Element;
...@@ -364,18 +372,39 @@ package body Ada.Containers.Hashed_Sets is ...@@ -364,18 +372,39 @@ package body Ada.Containers.Hashed_Sets is
function Equivalent_Elements (Left, Right : Cursor) function Equivalent_Elements (Left, Right : Cursor)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Left.Node = null
or else Right.Node = null
then
raise Constraint_Error;
end if;
return Equivalent_Elements (Left.Node.Element, Right.Node.Element); return Equivalent_Elements (Left.Node.Element, Right.Node.Element);
end Equivalent_Elements; end Equivalent_Elements;
function Equivalent_Elements (Left : Cursor; Right : Element_Type) function Equivalent_Elements (Left : Cursor; Right : Element_Type)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Left), "bad Left cursor in Equivalent_Keys");
if Left.Node = null then
raise Constraint_Error;
end if;
return Equivalent_Elements (Left.Node.Element, Right); return Equivalent_Elements (Left.Node.Element, Right);
end Equivalent_Elements; end Equivalent_Elements;
function Equivalent_Elements (Left : Element_Type; Right : Cursor) function Equivalent_Elements (Left : Element_Type; Right : Cursor)
return Boolean is return Boolean is
begin begin
pragma Assert (Vet (Right), "bad Right cursor in Equivalent_Keys");
if Right.Node = null then
raise Constraint_Error;
end if;
return Equivalent_Elements (Left, Right.Node.Element); return Equivalent_Elements (Left, Right.Node.Element);
end Equivalent_Elements; end Equivalent_Elements;
...@@ -499,18 +528,29 @@ package body Ada.Containers.Hashed_Sets is ...@@ -499,18 +528,29 @@ package body Ada.Containers.Hashed_Sets is
return Cursor'(Container'Unrestricted_Access, Node); return Cursor'(Container'Unrestricted_Access, Node);
end First; 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 -- -- Has_Element --
----------------- -----------------
function Has_Element (Position : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
begin begin
if Position.Node = null then pragma Assert (Vet (Position), "bad cursor in Has_Element");
pragma Assert (Position.Container = null); return Position.Node /= null;
return False;
end if;
return True;
end Has_Element; end Has_Element;
--------------- ---------------
...@@ -576,18 +616,18 @@ package body Ada.Containers.Hashed_Sets is ...@@ -576,18 +616,18 @@ package body Ada.Containers.Hashed_Sets is
-- Start of processing for Insert -- Start of processing for Insert
begin begin
if HT.Length >= HT_Ops.Capacity (HT) then if HT_Ops.Capacity (HT) = 0 then
HT_Ops.Reserve_Capacity (HT, 1);
end if;
-- TODO: Local_Insert (HT, New_Item, Position.Node, Inserted);
-- 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.
HT_Ops.Reserve_Capacity (HT, HT.Length + 1); if Inserted
and then HT.Length > HT_Ops.Capacity (HT)
then
HT_Ops.Reserve_Capacity (HT, HT.Length);
end if; end if;
Local_Insert (HT, New_Item, Position.Node, Inserted);
Position.Container := Container'Unchecked_Access; Position.Container := Container'Unchecked_Access;
end Insert; end Insert;
...@@ -725,7 +765,7 @@ package body Ada.Containers.Hashed_Sets is ...@@ -725,7 +765,7 @@ package body Ada.Containers.Hashed_Sets is
function Is_Empty (Container : Set) return Boolean is function Is_Empty (Container : Set) return Boolean is
begin begin
return Container.Length = 0; return Container.HT.Length = 0;
end Is_Empty; end Is_Empty;
----------- -----------
...@@ -790,23 +830,13 @@ package body Ada.Containers.Hashed_Sets is ...@@ -790,23 +830,13 @@ package body Ada.Containers.Hashed_Sets is
Process (Cursor'(Container'Unrestricted_Access, Node)); Process (Cursor'(Container'Unrestricted_Access, Node));
end Process_Node; end Process_Node;
HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
B : Natural renames HT.Busy;
-- Start of processing for Iterate -- Start of processing for Iterate
begin begin
B := B + 1; -- TODO: resolve whether HT_Ops.Generic_Iteration should
-- manipulate busy bit.
begin
Iterate (HT);
exception
when others =>
B := B - 1;
raise;
end;
B := B - 1; Iterate (Container.HT);
end Iterate; end Iterate;
------------ ------------
...@@ -838,8 +868,9 @@ package body Ada.Containers.Hashed_Sets is ...@@ -838,8 +868,9 @@ package body Ada.Containers.Hashed_Sets is
function Next (Position : Cursor) return Cursor is function Next (Position : Cursor) return Cursor is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Next");
if Position.Node = null then if Position.Node = null then
pragma Assert (Position.Container = null);
return No_Element; return No_Element;
end if; end if;
...@@ -896,28 +927,35 @@ package body Ada.Containers.Hashed_Sets is ...@@ -896,28 +927,35 @@ package body Ada.Containers.Hashed_Sets is
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : Element_Type)) Process : not null access procedure (Element : Element_Type))
is is
E : Element_Type renames Position.Node.Element; begin
pragma Assert (Vet (Position), "bad cursor in Query_Element");
HT : Hash_Table_Type renames Position.Container.HT; if Position.Node = null then
raise Constraint_Error;
end if;
B : Natural renames HT.Busy; declare
L : Natural renames HT.Lock; HT : Hash_Table_Type renames Position.Container.HT;
begin B : Natural renames HT.Busy;
B := B + 1; L : Natural renames HT.Lock;
L := L + 1;
begin begin
Process (E); B := B + 1;
exception L := L + 1;
when others =>
L := L - 1; begin
B := B - 1; Process (Position.Node.Element);
raise; exception
end; when others =>
L := L - 1;
B := B - 1;
raise;
end;
L := L - 1; L := L - 1;
B := B - 1; B := B - 1;
end;
end Query_Element; end Query_Element;
---------- ----------
...@@ -955,7 +993,7 @@ package body Ada.Containers.Hashed_Sets is ...@@ -955,7 +993,7 @@ package body Ada.Containers.Hashed_Sets is
------------- -------------
procedure Replace procedure Replace
(Container : in out Set; -- TODO: need ruling from ARG (Container : in out Set;
New_Item : Element_Type) New_Item : Element_Type)
is is
Node : constant Node_Access := Node : constant Node_Access :=
...@@ -978,19 +1016,19 @@ package body Ada.Containers.Hashed_Sets is ...@@ -978,19 +1016,19 @@ package body Ada.Containers.Hashed_Sets is
--------------------- ---------------------
procedure Replace_Element procedure Replace_Element
(HT : in out Hash_Table_Type; (HT : in out Hash_Table_Type;
Node : Node_Access; Node : Node_Access;
Element : Element_Type) New_Item : Element_Type)
is is
begin begin
if Equivalent_Elements (Node.Element, Element) then if Equivalent_Elements (Node.Element, New_Item) then
pragma Assert (Hash (Node.Element) = Hash (Element)); pragma Assert (Hash (Node.Element) = Hash (New_Item));
if HT.Lock > 0 then if HT.Lock > 0 then
raise Program_Error; raise Program_Error;
end if; end if;
Node.Element := Element; -- Note that this assignment can fail Node.Element := New_Item; -- Note that this assignment can fail
return; return;
end if; end if;
...@@ -1013,7 +1051,7 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1013,7 +1051,7 @@ package body Ada.Containers.Hashed_Sets is
function New_Node (Next : Node_Access) return Node_Access is function New_Node (Next : Node_Access) return Node_Access is
begin begin
Node.Element := Element; -- Note that this assignment can fail Node.Element := New_Item; -- Note that this assignment can fail
Node.Next := Next; Node.Next := Next;
return Node; return Node;
end New_Node; end New_Node;
...@@ -1026,12 +1064,11 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1026,12 +1064,11 @@ package body Ada.Containers.Hashed_Sets is
begin begin
Local_Insert Local_Insert
(HT => HT, (HT => HT,
Key => Element, Key => New_Item,
Node => Result, Node => Result,
Inserted => Inserted); Inserted => Inserted);
if Inserted then if Inserted then
pragma Assert (Result = Node);
return; return;
end if; end if;
exception exception
...@@ -1076,22 +1113,22 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1076,22 +1113,22 @@ package body Ada.Containers.Hashed_Sets is
end Replace_Element; end Replace_Element;
procedure Replace_Element procedure Replace_Element
(Container : Set; (Container : in out Set;
Position : Cursor; Position : Cursor;
By : Element_Type) New_Item : Element_Type)
is is
HT : Hash_Table_Type renames Container'Unrestricted_Access.all.HT;
begin begin
pragma Assert (Vet (Position), "bad cursor in Replace_Element");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Set_Access'(Container'Unrestricted_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
Replace_Element (HT, Position.Node, By); Replace_Element (Container.HT, Position.Node, New_Item);
end Replace_Element; end Replace_Element;
---------------------- ----------------------
...@@ -1491,6 +1528,61 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1491,6 +1528,61 @@ package body Ada.Containers.Hashed_Sets is
return (Controlled with HT => (Buckets, Length, 0, 0)); return (Controlled with HT => (Buckets, Length, 0, 0));
end Union; end Union;
---------
-- Vet --
---------
function Vet (Position : Cursor) return Boolean is
begin
if Position.Node = null then
return Position.Container = null;
end if;
if Position.Container = null then
return False;
end if;
if Position.Node.Next = Position.Node 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
or else HT.Buckets'Length = 0
then
return False;
end if;
X := HT.Buckets (Element_Keys.Index (HT, Position.Node.Element));
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 -- to prevent unnecessary looping
return False;
end if;
X := X.Next;
end loop;
return False;
end;
end Vet;
----------- -----------
-- Write -- -- Write --
----------- -----------
...@@ -1594,27 +1686,9 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1594,27 +1686,9 @@ package body Ada.Containers.Hashed_Sets is
Node : Node_Access) return Boolean Node : Node_Access) return Boolean
is is
begin begin
return Equivalent_Keys (Key, Node.Element); return Equivalent_Keys (Key, Generic_Keys.Key (Node.Element));
end Equivalent_Key_Node; end Equivalent_Key_Node;
---------------------
-- Equivalent_Keys --
---------------------
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;
------------- -------------
-- Exclude -- -- Exclude --
------------- -------------
...@@ -1654,6 +1728,12 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1654,6 +1728,12 @@ package body Ada.Containers.Hashed_Sets is
function Key (Position : Cursor) return Key_Type is function Key (Position : Cursor) return Key_Type is
begin begin
pragma Assert (Vet (Position), "bad cursor in function Key");
if Position.Node = null then
raise Constraint_Error;
end if;
return Key (Position.Node.Element); return Key (Position.Node.Element);
end Key; end Key;
...@@ -1687,20 +1767,35 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1687,20 +1767,35 @@ package body Ada.Containers.Hashed_Sets is
Process : not null access Process : not null access
procedure (Element : in out Element_Type)) procedure (Element : in out Element_Type))
is is
HT : Hash_Table_Type renames Container.HT; HT : Hash_Table_Type renames Container.HT;
Indx : Hash_Type;
begin begin
pragma Assert
(Vet (Position),
"bad cursor in Update_Element_Preserving_Key");
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
end if; end if;
if Position.Container /= Set_Access'(Container'Unchecked_Access) then if Position.Container /= Container'Unrestricted_Access then
raise Program_Error; raise Program_Error;
end if; end if;
if HT.Buckets = null
or else HT.Buckets'Length = 0
or else HT.Length = 0
or else Position.Node.Next = Position.Node
then
raise Program_Error;
end if;
Indx := HT_Ops.Index (HT, Position.Node);
declare declare
E : Element_Type renames Position.Node.Element; E : Element_Type renames Position.Node.Element;
K : Key_Type renames Key (E); K : constant Key_Type := Key (E);
B : Natural renames HT.Busy; B : Natural renames HT.Busy;
L : Natural renames HT.Lock; L : Natural renames HT.Lock;
...@@ -1721,16 +1816,38 @@ package body Ada.Containers.Hashed_Sets is ...@@ -1721,16 +1816,38 @@ package body Ada.Containers.Hashed_Sets is
L := L - 1; L := L - 1;
B := B - 1; B := B - 1;
if Equivalent_Keys (K, E) then if Equivalent_Keys (K, Key (E)) then
pragma Assert (Hash (K) = Hash (E)); pragma Assert (Hash (K) = Hash (E));
return; return;
end if; end if;
end; end;
if HT.Buckets (Indx) = Position.Node then
HT.Buckets (Indx) := Position.Node.Next;
else
declare
Prev : Node_Access := HT.Buckets (Indx);
begin
while Prev.Next /= Position.Node loop
Prev := Prev.Next;
if Prev = null then
raise Program_Error;
end if;
end loop;
Prev.Next := Position.Node.Next;
end;
end if;
HT.Length := HT.Length - 1;
declare declare
X : Node_Access := Position.Node; X : Node_Access := Position.Node;
begin begin
HT_Ops.Delete_Node_Sans_Free (HT, X);
Free (X); Free (X);
end; end;
......
...@@ -48,7 +48,7 @@ generic ...@@ -48,7 +48,7 @@ generic
with function "=" (Left, Right : Element_Type) return Boolean is <>; with function "=" (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Hashed_Sets is package Ada.Containers.Hashed_Sets is
pragma Preelaborate (Hashed_Sets); pragma Preelaborate;
type Set is tagged private; type Set is tagged private;
...@@ -62,6 +62,12 @@ pragma Preelaborate (Hashed_Sets); ...@@ -62,6 +62,12 @@ pragma Preelaborate (Hashed_Sets);
function Equivalent_Sets (Left, Right : Set) return Boolean; function Equivalent_Sets (Left, Right : Set) return Boolean;
function Capacity (Container : Set) return Count_Type;
procedure Reserve_Capacity
(Container : in out Set;
Capacity : Count_Type);
function Length (Container : Set) return Count_Type; function Length (Container : Set) return Count_Type;
function Is_Empty (Container : Set) return Boolean; function Is_Empty (Container : Set) return Boolean;
...@@ -70,15 +76,15 @@ pragma Preelaborate (Hashed_Sets); ...@@ -70,15 +76,15 @@ pragma Preelaborate (Hashed_Sets);
function Element (Position : Cursor) return Element_Type; function Element (Position : Cursor) return Element_Type;
procedure Replace_Element
(Container : in out Set;
Position : Cursor;
New_Item : Element_Type);
procedure Query_Element procedure Query_Element
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : Element_Type)); 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 Move (Target : in out Set; Source : in out Set);
procedure Insert procedure Insert
...@@ -93,39 +99,11 @@ pragma Preelaborate (Hashed_Sets); ...@@ -93,39 +99,11 @@ pragma Preelaborate (Hashed_Sets);
procedure Replace (Container : in out Set; New_Item : Element_Type); procedure Replace (Container : in out Set; New_Item : Element_Type);
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 Exclude (Container : in out Set; Item : Element_Type);
function Contains (Container : Set; Item : Element_Type) return Boolean; procedure Delete (Container : in out Set; Item : Element_Type);
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 procedure Delete (Container : in out Set; Position : in out Cursor);
(Container : Set;
Process : not null access procedure (Position : Cursor));
procedure Union (Target : in out Set; Source : Set); procedure Union (Target : in out Set; Source : Set);
...@@ -156,41 +134,61 @@ pragma Preelaborate (Hashed_Sets); ...@@ -156,41 +134,61 @@ pragma Preelaborate (Hashed_Sets);
function Is_Subset (Subset : Set; Of_Set : Set) return Boolean; function Is_Subset (Subset : Set; Of_Set : Set) return Boolean;
function Capacity (Container : Set) return Count_Type; function First (Container : Set) return Cursor;
procedure Reserve_Capacity function Next (Position : Cursor) return Cursor;
(Container : in out Set;
Capacity : Count_Type); procedure Next (Position : in out Cursor);
function Find
(Container : Set;
Item : Element_Type) return Cursor;
function Contains (Container : Set; Item : Element_Type) return Boolean;
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));
generic generic
type Key_Type (<>) is limited private; type Key_Type (<>) is private;
with function Key (Element : Element_Type) return Key_Type; with function Key (Element : Element_Type) return Key_Type;
with function Hash (Key : Key_Type) return Hash_Type; with function Hash (Key : Key_Type) return Hash_Type;
with function Equivalent_Keys with function Equivalent_Keys (Left, Right : Key_Type) return Boolean;
(Key : Key_Type;
Element : Element_Type) return Boolean;
package Generic_Keys is package Generic_Keys is
function Contains (Container : Set; Key : Key_Type) return Boolean;
function Find (Container : Set; Key : Key_Type) return Cursor;
function Key (Position : Cursor) return Key_Type; function Key (Position : Cursor) return Key_Type;
function Element (Container : Set; Key : Key_Type) return Element_Type; function Element (Container : Set; Key : Key_Type) return Element_Type;
procedure Replace procedure Replace -- TODO: ask Randy why this wasn't removed
(Container : in out Set; (Container : in out Set;
Key : Key_Type; Key : Key_Type;
New_Item : Element_Type); New_Item : Element_Type);
procedure Exclude (Container : in out Set; Key : Key_Type);
procedure Delete (Container : in out Set; Key : Key_Type); procedure Delete (Container : in out Set; Key : Key_Type);
procedure Exclude (Container : in out Set; Key : Key_Type); function Find (Container : Set; Key : Key_Type) return Cursor;
function Contains (Container : Set; Key : Key_Type) return Boolean;
procedure Update_Element_Preserving_Key procedure Update_Element_Preserving_Key
(Container : in out Set; (Container : in out Set;
...@@ -198,18 +196,9 @@ pragma Preelaborate (Hashed_Sets); ...@@ -198,18 +196,9 @@ pragma Preelaborate (Hashed_Sets);
Process : not null access Process : not null access
procedure (Element : in out Element_Type)); procedure (Element : in out Element_Type));
function Equivalent_Keys
(Left : Cursor;
Right : Key_Type) return Boolean;
function Equivalent_Keys
(Left : Key_Type;
Right : Cursor) return Boolean;
end Generic_Keys; end Generic_Keys;
private private
type Node_Type; type Node_Type;
type Node_Access is access Node_Type; type Node_Access is access Node_Type;
......
...@@ -359,6 +359,21 @@ package body Ada.Containers.Ordered_Sets is ...@@ -359,6 +359,21 @@ package body Ada.Containers.Ordered_Sets is
return Position.Node.Element; return Position.Node.Element;
end Element; end Element;
-------------------------
-- Equivalent_Elements --
-------------------------
function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
begin
if Left < Right
or else Right < Left
then
return False;
else
return True;
end if;
end Equivalent_Elements;
--------------------- ---------------------
-- Equivalent_Sets -- -- Equivalent_Sets --
--------------------- ---------------------
...@@ -490,34 +505,6 @@ package body Ada.Containers.Ordered_Sets is ...@@ -490,34 +505,6 @@ package body Ada.Containers.Ordered_Sets is
Is_Less_Key_Node => Is_Less_Key_Node, Is_Less_Key_Node => Is_Less_Key_Node,
Is_Greater_Key_Node => Is_Greater_Key_Node); Is_Greater_Key_Node => Is_Greater_Key_Node);
---------
-- "<" --
---------
function "<" (Left : Key_Type; Right : Cursor) return Boolean is
begin
return Left < Right.Node.Element;
end "<";
function "<" (Left : Cursor; Right : Key_Type) return Boolean is
begin
return Right > Left.Node.Element;
end "<";
---------
-- ">" --
---------
function ">" (Left : Key_Type; Right : Cursor) return Boolean is
begin
return Left > Right.Node.Element;
end ">";
function ">" (Left : Cursor; Right : Key_Type) return Boolean is
begin
return Right < Left.Node.Element;
end ">";
------------- -------------
-- Ceiling -- -- Ceiling --
------------- -------------
...@@ -573,6 +560,21 @@ package body Ada.Containers.Ordered_Sets is ...@@ -573,6 +560,21 @@ package body Ada.Containers.Ordered_Sets is
return Node.Element; return Node.Element;
end Element; end Element;
---------------------
-- Equivalent_Keys --
---------------------
function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
begin
if Left < Right
or else Right < Left
then
return False;
else
return True;
end if;
end Equivalent_Keys;
------------- -------------
-- Exclude -- -- Exclude --
------------- -------------
...@@ -626,7 +628,7 @@ package body Ada.Containers.Ordered_Sets is ...@@ -626,7 +628,7 @@ package body Ada.Containers.Ordered_Sets is
Right : Node_Access) return Boolean Right : Node_Access) return Boolean
is is
begin begin
return Left > Right.Element; return Key (Right.Element) < Left;
end Is_Greater_Key_Node; end Is_Greater_Key_Node;
---------------------- ----------------------
...@@ -638,7 +640,7 @@ package body Ada.Containers.Ordered_Sets is ...@@ -638,7 +640,7 @@ package body Ada.Containers.Ordered_Sets is
Right : Node_Access) return Boolean Right : Node_Access) return Boolean
is is
begin begin
return Left < Right.Element; return Left < Key (Right.Element);
end Is_Less_Key_Node; end Is_Less_Key_Node;
--------- ---------
...@@ -691,7 +693,7 @@ package body Ada.Containers.Ordered_Sets is ...@@ -691,7 +693,7 @@ package body Ada.Containers.Ordered_Sets is
declare declare
E : Element_Type renames Position.Node.Element; E : Element_Type renames Position.Node.Element;
K : Key_Type renames Key (E); K : constant Key_Type := Key (E);
B : Natural renames Tree.Busy; B : Natural renames Tree.Busy;
L : Natural renames Tree.Lock; L : Natural renames Tree.Lock;
...@@ -712,11 +714,7 @@ package body Ada.Containers.Ordered_Sets is ...@@ -712,11 +714,7 @@ package body Ada.Containers.Ordered_Sets is
L := L - 1; L := L - 1;
B := B - 1; B := B - 1;
if K < E if Equivalent_Keys (K, Key (E)) then
or else K > E
then
null;
else
return; return;
end if; end if;
end; end;
...@@ -1319,12 +1317,10 @@ package body Ada.Containers.Ordered_Sets is ...@@ -1319,12 +1317,10 @@ package body Ada.Containers.Ordered_Sets is
end Replace_Element; end Replace_Element;
procedure Replace_Element procedure Replace_Element
(Container : Set; (Container : in out Set;
Position : Cursor; Position : Cursor;
By : Element_Type) New_Item : Element_Type)
is is
Tree : Tree_Type renames Container.Tree'Unrestricted_Access.all;
begin begin
if Position.Node = null then if Position.Node = null then
raise Constraint_Error; raise Constraint_Error;
...@@ -1334,7 +1330,7 @@ package body Ada.Containers.Ordered_Sets is ...@@ -1334,7 +1330,7 @@ package body Ada.Containers.Ordered_Sets is
raise Program_Error; raise Program_Error;
end if; end if;
Replace_Element (Tree, Position.Node, By); Replace_Element (Container.Tree, Position.Node, New_Item);
end Replace_Element; end Replace_Element;
--------------------- ---------------------
......
...@@ -38,14 +38,15 @@ with Ada.Finalization; ...@@ -38,14 +38,15 @@ with Ada.Finalization;
with Ada.Streams; with Ada.Streams;
generic generic
type Element_Type is private; type Element_Type is private;
with function "<" (Left, Right : Element_Type) return Boolean is <>; with function "<" (Left, Right : Element_Type) return Boolean is <>;
with function "=" (Left, Right : Element_Type) return Boolean is <>; with function "=" (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Ordered_Sets is package Ada.Containers.Ordered_Sets is
pragma Preelaborate (Ordered_Sets); pragma Preelaborate;
function Equivalent_Elements (Left, Right : Element_Type) return Boolean;
type Set is tagged private; type Set is tagged private;
...@@ -67,18 +68,16 @@ pragma Preelaborate (Ordered_Sets); ...@@ -67,18 +68,16 @@ pragma Preelaborate (Ordered_Sets);
function Element (Position : Cursor) return Element_Type; function Element (Position : Cursor) return Element_Type;
procedure Replace_Element
(Container : in out Set;
Position : Cursor;
New_Item : Element_Type);
procedure Query_Element procedure Query_Element
(Position : Cursor; (Position : Cursor;
Process : not null access procedure (Element : Element_Type)); Process : not null access procedure (Element : Element_Type));
procedure Replace_Element procedure Move (Target : in out Set; Source : in out Set);
(Container : Set; -- TODO: need ARG ruling
Position : Cursor;
By : Element_Type);
procedure Move
(Target : in out Set;
Source : in out Set);
procedure Insert procedure Insert
(Container : in out Set; (Container : in out Set;
...@@ -95,9 +94,13 @@ pragma Preelaborate (Ordered_Sets); ...@@ -95,9 +94,13 @@ pragma Preelaborate (Ordered_Sets);
New_Item : Element_Type); New_Item : Element_Type);
procedure Replace procedure Replace
(Container : in out Set; -- TODO: need ARG ruling (Container : in out Set;
New_Item : Element_Type); New_Item : Element_Type);
procedure Exclude
(Container : in out Set;
Item : Element_Type);
procedure Delete procedure Delete
(Container : in out Set; (Container : in out Set;
Item : Element_Type); Item : Element_Type);
...@@ -110,10 +113,6 @@ pragma Preelaborate (Ordered_Sets); ...@@ -110,10 +113,6 @@ pragma Preelaborate (Ordered_Sets);
procedure Delete_Last (Container : in out Set); procedure Delete_Last (Container : in out Set);
procedure Exclude
(Container : in out Set;
Item : Element_Type);
procedure Union (Target : in out Set; Source : Set); procedure Union (Target : in out Set; Source : Set);
function Union (Left, Right : Set) return Set; function Union (Left, Right : Set) return Set;
...@@ -126,8 +125,7 @@ pragma Preelaborate (Ordered_Sets); ...@@ -126,8 +125,7 @@ pragma Preelaborate (Ordered_Sets);
function "and" (Left, Right : Set) return Set renames Intersection; function "and" (Left, Right : Set) return Set renames Intersection;
procedure Difference (Target : in out Set; procedure Difference (Target : in out Set; Source : Set);
Source : Set);
function Difference (Left, Right : Set) return Set; function Difference (Left, Right : Set) return Set;
...@@ -143,14 +141,6 @@ pragma Preelaborate (Ordered_Sets); ...@@ -143,14 +141,6 @@ pragma Preelaborate (Ordered_Sets);
function Is_Subset (Subset : Set; Of_Set : Set) return Boolean; 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 Floor (Container : Set; Item : Element_Type) return Cursor;
function Ceiling (Container : Set; Item : Element_Type) return Cursor;
function First (Container : Set) return Cursor; function First (Container : Set) return Cursor;
function First_Element (Container : Set) return Element_Type; function First_Element (Container : Set) return Element_Type;
...@@ -167,6 +157,14 @@ pragma Preelaborate (Ordered_Sets); ...@@ -167,6 +157,14 @@ pragma Preelaborate (Ordered_Sets);
procedure Previous (Position : in out Cursor); procedure Previous (Position : in out Cursor);
function Find (Container : Set; Item : Element_Type) return Cursor;
function Floor (Container : Set; Item : Element_Type) return Cursor;
function Ceiling (Container : Set; Item : Element_Type) return Cursor;
function Contains (Container : Set; Item : Element_Type) return Boolean;
function Has_Element (Position : Cursor) return Boolean; function Has_Element (Position : Cursor) return Boolean;
function "<" (Left, Right : Cursor) return Boolean; function "<" (Left, Right : Cursor) return Boolean;
...@@ -190,48 +188,36 @@ pragma Preelaborate (Ordered_Sets); ...@@ -190,48 +188,36 @@ pragma Preelaborate (Ordered_Sets);
Process : not null access procedure (Position : Cursor)); Process : not null access procedure (Position : Cursor));
generic generic
type Key_Type (<>) is limited private; type Key_Type (<>) is private;
with function Key (Element : Element_Type) return Key_Type; with function Key (Element : Element_Type) return Key_Type;
with function "<" with function "<" (Left, Right : Key_Type) return Boolean is <>;
(Left : Key_Type;
Right : Element_Type) return Boolean is <>;
with function ">"
(Left : Key_Type;
Right : Element_Type) return Boolean is <>;
package Generic_Keys is package Generic_Keys is
function Contains (Container : Set; Key : Key_Type) return Boolean; function Equivalent_Keys (Left, Right : Key_Type) return Boolean;
function Find (Container : Set; Key : Key_Type) return Cursor;
function Floor (Container : Set; Key : Key_Type) return Cursor;
function Ceiling (Container : Set; Key : Key_Type) return Cursor;
function Key (Position : Cursor) return Key_Type; function Key (Position : Cursor) return Key_Type;
function Element (Container : Set; Key : Key_Type) return Element_Type; function Element (Container : Set; Key : Key_Type) return Element_Type;
procedure Replace procedure Replace
(Container : in out Set; -- TODO: need ARG ruling (Container : in out Set;
Key : Key_Type; Key : Key_Type;
New_Item : Element_Type); New_Item : Element_Type);
procedure Delete (Container : in out Set; Key : Key_Type);
procedure Exclude (Container : in out Set; Key : Key_Type); procedure Exclude (Container : in out Set; Key : Key_Type);
function "<" (Left : Cursor; Right : Key_Type) return Boolean; procedure Delete (Container : in out Set; Key : Key_Type);
function Find (Container : Set; Key : Key_Type) return Cursor;
function ">" (Left : Cursor; Right : Key_Type) return Boolean; function Floor (Container : Set; Key : Key_Type) return Cursor;
function "<" (Left : Key_Type; Right : Cursor) return Boolean; function Ceiling (Container : Set; Key : Key_Type) return Cursor;
function ">" (Left : Key_Type; Right : Cursor) return Boolean; function Contains (Container : Set; Key : Key_Type) return Boolean;
procedure Update_Element_Preserving_Key procedure Update_Element_Preserving_Key
(Container : in out Set; (Container : in out Set;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment