package body Ada.Containers.Indefinite_Vectors is
type Int is range System.Min_Int .. System.Max_Int;
+ type UInt is mod System.Max_Binary_Modulus;
procedure Free is
new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
end if;
declare
- Last_As_Int : constant Int'Base := -- TODO: handle overflow
- Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
+ N : constant Int'Base := Int (LN) + Int (RN);
+ Last_As_Int : Int'Base;
begin
- if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if Int (No_Index) > Int'Last - N then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ Last_As_Int := Int (No_Index) + N;
+
+ if Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
declare
- Last_As_Int : constant Int'Base :=
- Int (Index_Type'First) + Int (LN);
+ Last_As_Int : Int'Base;
begin
- if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if Int (Index_Type'First) > Int'Last - Int (LN) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ Last_As_Int := Int (Index_Type'First) + Int (LN);
+
+ if Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
declare
- Last_As_Int : constant Int'Base :=
- Int (Index_Type'First) + Int (RN);
+ Last_As_Int : Int'Base;
begin
- if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if Int (Index_Type'First) > Int'Last - Int (RN) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ Last_As_Int := Int (Index_Type'First) + Int (RN);
+
+ if Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
end if;
declare
function "&" (Left, Right : Element_Type) return Vector is
begin
if Index_Type'First >= Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with "new length is out of range";
end if;
declare
subtype ET is Elements_Type (Index_Type'First .. Last);
Elements : Elements_Access := new ET;
+
begin
begin
Elements (Elements'First) := new Element_Type'(Left);
end if;
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with "vector is already at its maximum length";
end if;
Insert
end if;
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with "vector is already at its maximum length";
end if;
Insert
procedure Clear (Container : in out Vector) is
begin
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
while Container.Last >= Index_Type'First loop
is
begin
if Index < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range (too small)";
end if;
if Index > Container.Last then
if Index > Container.Last + 1 then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range (too large)";
end if;
return;
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
Index_As_Int : constant Int := Int (Index);
Old_Last_As_Int : constant Int := Int (Container.Last);
- -- TODO: somewhat vestigial...fix ???
Count1 : constant Int'Base := Int (Count);
Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
N : constant Int'Base := Int'Min (Count1, Count2);
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
- if Position.Container /= Container'Unchecked_Access
- or else Position.Index > Container.Last
- then
- raise Program_Error;
+ if Position.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "Position cursor denotes wrong container";
+ end if;
+
+ if Position.Index > Container.Last then
+ raise Program_Error with "Position index is out of range";
end if;
Delete (Container, Position.Index, Count);
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
is
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
declare
begin
if EA = null then
- raise Constraint_Error;
+ raise Constraint_Error with "element is empty";
end if;
return EA.all;
function Element (Position : Cursor) return Element_Type is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
return Element (Position.Container.all, Position.Index);
procedure Finalize (Container : in out Vector) is
begin
- Clear (Container);
+ Clear (Container); -- Checks busy-bit
declare
X : Elements_Access := Container.Elements;
Position : Cursor := No_Element) return Cursor
is
begin
- if Position.Container /= null
- and then (Position.Container /= Container'Unchecked_Access
- or else Position.Index > Container.Last)
- then
- raise Program_Error;
+ if Position.Container /= null then
+ if Position.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "Position cursor denotes wrong container";
+ end if;
+
+ if Position.Index > Container.Last then
+ raise Program_Error with "Position index is out of range";
+ end if;
end if;
for J in Position.Index .. Container.Last loop
end if;
if Source.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
Target.Set_Length (Length (Target) + Length (Source));
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
Sort (Container.Elements (Index_Type'First .. Container.Last));
is
N : constant Int := Int (Count);
+ First : constant Int := Int (Index_Type'First);
New_Last_As_Int : Int'Base;
New_Last : Index_Type;
+ New_Length : UInt;
+ Max_Length : constant UInt := UInt (Count_Type'Last);
Dst : Elements_Access;
begin
if Before < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too small)";
end if;
if Before > Container.Last
and then Before > Container.Last + 1
then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too large)";
end if;
if Count = 0 then
Old_Last_As_Int : constant Int := Int (Container.Last);
begin
+ if Old_Last_As_Int > Int'Last - N then -- see a-convec.adb ???
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
New_Last_As_Int := Old_Last_As_Int + N;
- if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if New_Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ New_Length := UInt (New_Last_As_Int - First + 1);
+
+ if New_Length > Max_Length then
+ raise Constraint_Error with "new length is out of range";
end if;
New_Last := Index_Type (New_Last_As_Int);
end;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
if Container.Elements = null then
if New_Last <= Container.Elements'Last then
declare
E : Elements_Type renames Container.Elements.all;
+
begin
if Before <= Container.Last then
declare
Index : constant Index_Type := Index_Type (Index_As_Int);
- J : Index_Type'Base := Before;
+ J : Index_Type'Base;
begin
E (Index .. New_Last) := E (Before .. Container.Last);
Container.Last := New_Last;
+ J := Before;
while J < Index loop
E (J) := new Element_Type'(New_Item);
J := J + 1;
end loop;
+
exception
when others =>
E (J .. Index - 1) := (others => null);
end if;
declare
- First : constant Int := Int (Index_Type'First);
- New_Size : constant Int'Base := New_Last_As_Int - First + 1;
- Size : Int'Base := Int'Max (1, Container.Elements'Length);
+ C, CC : UInt;
begin
- while Size < New_Size loop
- if Size > Int'Last / 2 then
- Size := Int'Last;
+ C := UInt'Max (1, Container.Elements'Length);
+ while C < New_Length loop
+ if C > UInt'Last / 2 then
+ C := UInt'Last;
exit;
end if;
- Size := 2 * Size;
+ C := 2 * C;
end loop;
- -- TODO: The following calculations aren't quite right, since
- -- there will be overflow if Index_Type'Range is very large
- -- (e.g. this package is instantiated with a 64-bit integer).
- -- END TODO.
+ if C > Max_Length then
+ C := Max_Length;
+ end if;
- declare
- Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
- begin
- if Size > Max_Size then
- Size := Max_Size;
- end if;
- end;
+ if Index_Type'First <= 0
+ and then Index_Type'Last >= 0
+ then
+ CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
+
+ else
+ CC := UInt (Int (Index_Type'Last) - First + 1);
+ end if;
+
+ if C > CC then
+ C := CC;
+ end if;
declare
- Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
+ Dst_Last : constant Index_Type :=
+ Index_Type (First + UInt'Pos (C) - Int'(1));
+
begin
Dst := new Elements_Type (Index_Type'First .. Dst_Last);
end;
begin
if Before < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too small)";
end if;
if Before > Container.Last
and then Before > Container.Last + 1
then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too large)";
end if;
if N = 0 then
if Before.Container /= null
and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Is_Empty (New_Item) then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
if Before.Container /= null
and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Is_Empty (New_Item) then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Count = 0 then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Count = 0 then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
is
N : constant Int := Int (Count);
+ First : constant Int := Int (Index_Type'First);
New_Last_As_Int : Int'Base;
New_Last : Index_Type;
+ New_Length : UInt;
+ Max_Length : constant UInt := UInt (Count_Type'Last);
Dst : Elements_Access;
begin
if Before < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too small)";
end if;
if Before > Container.Last
and then Before > Container.Last + 1
then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too large)";
end if;
if Count = 0 then
Old_Last_As_Int : constant Int := Int (Container.Last);
begin
+ if Old_Last_As_Int > Int'Last - N then -- see a-convec.adb ???
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
New_Last_As_Int := Old_Last_As_Int + N;
- if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if New_Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ New_Length := UInt (New_Last_As_Int - First + 1);
+
+ if New_Length > Max_Length then
+ raise Constraint_Error with "new length is out of range";
end if;
New_Last := Index_Type (New_Last_As_Int);
end;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
if Container.Elements = null then
end if;
declare
- First : constant Int := Int (Index_Type'First);
- New_Size : constant Int'Base := New_Last_As_Int - First + 1;
- Size : Int'Base := Int'Max (1, Container.Elements'Length);
+ C, CC : UInt;
begin
- while Size < New_Size loop
- if Size > Int'Last / 2 then
- Size := Int'Last;
+ C := UInt'Max (1, Container.Elements'Length);
+ while C < New_Length loop
+ if C > UInt'Last / 2 then
+ C := UInt'Last;
exit;
end if;
- Size := 2 * Size;
+ C := 2 * C;
end loop;
- -- TODO: The following calculations aren't quite right, since
- -- there will be overflow if Index_Type'Range is very large
- -- (e.g. this package is instantiated with a 64-bit integer).
- -- END TODO.
+ if C > Max_Length then
+ C := Max_Length;
+ end if;
- declare
- Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
- begin
- if Size > Max_Size then
- Size := Max_Size;
- end if;
- end;
+ if Index_Type'First <= 0
+ and then Index_Type'Last >= 0
+ then
+ CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
+
+ else
+ CC := UInt (Int (Index_Type'Last) - First + 1);
+ end if;
+
+ if C > CC then
+ C := CC;
+ end if;
declare
- Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
+ Dst_Last : constant Index_Type :=
+ Index_Type (First + UInt'Pos (C) - 1);
+
begin
Dst := new Elements_Type (Index_Type'First .. Dst_Last);
end;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Count = 0 then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
N : constant Int'Base := L - F + 1;
begin
- if N > Count_Type'Pos (Count_Type'Last) then
- raise Constraint_Error;
- end if;
-
return Count_Type (N);
end Length;
end if;
if Source.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (Source is busy)";
end if;
- Clear (Target);
+ Clear (Target); -- Checks busy-bit
declare
Target_Elements : constant Elements_Access := Target.Elements;
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
if V.Elements (Index) = null then
- raise Constraint_Error;
+ raise Constraint_Error with "element is null";
end if;
B := B + 1;
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
Query_Element (Position.Container.all, Position.Index, Process);
----------
procedure Read
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Container : out Vector)
is
Length : Count_Type'Base;
end Read;
procedure Read
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Position : out Cursor)
is
begin
- raise Program_Error;
+ raise Program_Error with "attempt to stream vector cursor";
end Read;
---------------------
is
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
declare
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
if Position.Container /= Container'Unrestricted_Access then
- raise Program_Error;
+ raise Program_Error with "Position cursor denotes wrong container";
end if;
Replace_Element (Container, Position.Index, New_Item);
elsif N < Container.Elements'Length then
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "new length is out of range";
end if;
declare
if Capacity <= N then
if N < Container.Elements'Length then
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
declare
- I : Index_Type := Index_Type'First;
- J : Index_Type := Container.Last;
+ I : Index_Type;
+ J : Index_Type;
E : Elements_Type renames Container.Elements.all;
begin
+ I := Index_Type'First;
+ J := Container.Last;
while I < J loop
declare
EI : constant Element_Access := E (I);
if Position.Container /= null
and then Position.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Position cursor denotes wrong container";
end if;
if Position.Container = null
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
if Length < N then
I, J : Index_Type)
is
begin
- if I > Container.Last
- or else J > Container.Last
- then
- raise Constraint_Error;
+ if I > Container.Last then
+ raise Constraint_Error with "I index is out of range";
+ end if;
+
+ if J > Container.Last then
+ raise Constraint_Error with "J index is out of range";
end if;
if I = J then
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
declare
I, J : Cursor)
is
begin
- if I.Container = null
- or else J.Container = null
- then
- raise Constraint_Error;
+ if I.Container = null then
+ raise Constraint_Error with "I cursor has no element";
end if;
- if I.Container /= Container'Unrestricted_Access
- or else J.Container /= Container'Unrestricted_Access
- then
- raise Program_Error;
+ if J.Container = null then
+ raise Constraint_Error with "J cursor has no element";
+ end if;
+
+ if I.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "I cursor denotes wrong container";
+ end if;
+
+ if J.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "J cursor denotes wrong container";
end if;
Swap (Container, I.Index, J.Index);
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "Length is out of range";
end if;
Last := Index_Type (Last_As_Int);
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "Length is out of range";
end if;
Last := Index_Type (Last_As_Int);
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
if Container.Elements (Index) = null then
- raise Constraint_Error;
+ raise Constraint_Error with "element is null";
end if;
B := B + 1;
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
if Position.Container /= Container'Unrestricted_Access then
- raise Program_Error;
+ raise Program_Error with "Position cursor denotes wrong container";
end if;
Update_Element (Container, Position.Index, Process);
-----------
procedure Write
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Container : Vector)
is
N : constant Count_Type := Length (Container);
-- There's another way to do this. Instead a separate
-- Boolean for each element, you could write a Boolean
-- followed by a count of how many nulls or non-nulls
- -- follow in the array.
+ -- follow in the array. ???
if E (Indx) = null then
Boolean'Write (Stream, False);
end Write;
procedure Write
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Position : Cursor)
is
begin
- raise Program_Error;
+ raise Program_Error with "attempt to stream vector cursor";
end Write;
end Ada.Containers.Indefinite_Vectors;
-- --
-- B o d y --
-- --
--- Copyright (C) 2004-2005 Free Software Foundation, Inc. --
+-- Copyright (C) 2004-2006 Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
package body Ada.Containers.Vectors is
type Int is range System.Min_Int .. System.Max_Int;
+ type UInt is mod System.Max_Binary_Modulus;
procedure Free is
new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
end if;
declare
- Last_As_Int : constant Int'Base := -- TODO: handle overflow
- Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
+ N : constant Int'Base := Int (LN) + Int (RN);
+ Last_As_Int : Int'Base;
begin
- if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if Int (No_Index) > Int'Last - N then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ Last_As_Int := Int (No_Index) + N;
+
+ if Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
declare
- Last_As_Int : constant Int'Base := -- TODO: handle overflow
- Int (Index_Type'First) + Int (LN);
+ Last_As_Int : Int'Base;
begin
- if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if Int (Index_Type'First) > Int'Last - Int (LN) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ Last_As_Int := Int (Index_Type'First) + Int (LN);
+
+ if Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
declare
- Last_As_Int : constant Int'Base := -- TODO: handle overflow
- Int (Index_Type'First) + Int (RN);
+ Last_As_Int : Int'Base;
begin
- if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if Int (Index_Type'First) > Int'Last - Int (RN) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ Last_As_Int := Int (Index_Type'First) + Int (RN);
+
+ if Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end;
end "&";
- function "&" (Left, Right : Element_Type) return Vector is
+ function "&" (Left, Right : Element_Type) return Vector is
begin
if Index_Type'First >= Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with "vector is already at its maximum length";
end if;
Insert
end if;
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with "vector is already at its maximum length";
end if;
Insert
procedure Clear (Container : in out Vector) is
begin
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
Container.Last := No_Index;
is
begin
if Index < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range (too small)";
end if;
if Index > Container.Last then
if Index > Container.Last + 1 then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range (too large)";
end if;
return;
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
- if Position.Container /= Container'Unrestricted_Access
- or else Position.Index > Container.Last
- then
- raise Program_Error;
+ if Position.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "Position cursor denotes wrong container";
+ end if;
+
+ if Position.Index > Container.Last then
+ raise Program_Error with "Position index is out of range";
end if;
Delete (Container, Position.Index, Count);
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
Index := Int'Base (Container.Last) - Int'Base (Count);
is
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
return Container.Elements (Index);
function Element (Position : Cursor) return Element_Type is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
return Element (Position.Container.all, Position.Index);
begin
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
Container.Elements := null;
Position : Cursor := No_Element) return Cursor
is
begin
- if Position.Container /= null
- and then (Position.Container /= Container'Unrestricted_Access
- or else Position.Index > Container.Last)
- then
- raise Program_Error;
+ if Position.Container /= null then
+ if Position.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "Position cursor denotes wrong container";
+ end if;
+
+ if Position.Index > Container.Last then
+ raise Program_Error with "Position index is out of range";
+ end if;
end if;
for J in Position.Index .. Container.Last loop
end if;
if Source.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
Target.Set_Length (Length (Target) + Length (Source));
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
Sort (Container.Elements (Index_Type'First .. Container.Last));
is
N : constant Int := Count_Type'Pos (Count);
+ First : constant Int := Int (Index_Type'First);
New_Last_As_Int : Int'Base;
New_Last : Index_Type;
+ New_Length : UInt;
+ Max_Length : constant UInt := UInt (Count_Type'Last);
Dst : Elements_Access;
begin
if Before < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too small)";
end if;
if Before > Container.Last
and then Before > Container.Last + 1
then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too large)";
end if;
if Count = 0 then
end if;
declare
- Old_Last : constant Extended_Index := Container.Last;
-
- Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
+ Old_Last_As_Int : constant Int := Int (Container.Last);
begin
+ if Old_Last_As_Int > Int'Last - N then
+
+ -- ???
+
+ -- The purpose of this test is to ensure that the calculation of
+ -- New_Last_As_Int (see below) doesn't overflow.
+
+ -- This isn't quite right, since the only requirements are:
+ -- V.Last <= Index_Type'Last
+ -- V.Length <= Count_Type'Last
+
+ -- To be strictly correct there's no (explicit) requirement that
+ -- Old_Last + N <= Int'Last
+
+ -- However, there might indeed be an implied requirement, since
+ -- machine constraints dictate that
+ -- Index_Type'Last <= Int'Last
+ -- and so this check is perhaps proper after all.
+
+ -- This shouldn't be an issue in practice, since it can only
+ -- happen when N is very large, or V.Last is near Int'Last.
+
+ -- N isn't likely to be large, since there's probably not enough
+ -- storage.
+
+ -- V.Last would only be large if IT'First is very large (and
+ -- V.Length has some "normal" size). But typically IT'First is
+ -- either 0 or 1.
+
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
New_Last_As_Int := Old_Last_As_Int + N;
- if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if New_Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ New_Length := UInt (New_Last_As_Int - First + Int'(1));
+
+ if New_Length > Max_Length then
+ raise Constraint_Error with "new length is out of range";
end if;
New_Last := Index_Type (New_Last_As_Int);
end;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
if Container.Elements = null then
if New_Last <= Container.Elements'Last then
declare
E : Elements_Type renames Container.Elements.all;
+
begin
if Before <= Container.Last then
declare
end if;
declare
- First : constant Int := Int (Index_Type'First);
- New_Size : constant Int'Base := New_Last_As_Int - First + 1;
- Size : Int'Base := Int'Max (1, Container.Elements'Length);
+ C, CC : UInt;
begin
- while Size < New_Size loop
- if Size > Int'Last / 2 then
- Size := Int'Last;
+ C := UInt'Max (1, Container.Elements'Length);
+ while C < New_Length loop
+ if C > UInt'Last / 2 then
+ C := UInt'Last;
exit;
end if;
- Size := 2 * Size;
+ C := 2 * C;
end loop;
- -- TODO: The following calculations aren't quite right, since
- -- there will be overflow if Index_Type'Range is very large
- -- (e.g. this package is instantiated with a 64-bit integer).
- -- END TODO.
+ if C > Max_Length then
+ C := Max_Length;
+ end if;
- declare
- Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
- begin
- if Size > Max_Size then
- Size := Max_Size;
- end if;
- end;
+ if Index_Type'First <= 0
+ and then Index_Type'Last >= 0
+ then
+ CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
+
+ else
+ CC := UInt (Int (Index_Type'Last) - First + 1);
+ end if;
+
+ if C > CC then
+ C := CC;
+ end if;
declare
- Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
+ Dst_Last : constant Index_Type :=
+ Index_Type (First + UInt'Pos (C) - 1);
+
begin
Dst := new Elements_Type (Index_Type'First .. Dst_Last);
end;
begin
if Before < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too small)";
end if;
if Before > Container.Last
and then Before > Container.Last + 1
then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too large)";
end if;
if N = 0 then
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Is_Empty (New_Item) then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Is_Empty (New_Item) then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Count = 0 then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Count = 0 then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
is
N : constant Int := Count_Type'Pos (Count);
+ First : constant Int := Int (Index_Type'First);
New_Last_As_Int : Int'Base;
New_Last : Index_Type;
+ New_Length : UInt;
+ Max_Length : constant UInt := UInt (Count_Type'Last);
Dst : Elements_Access;
begin
if Before < Index_Type'First then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too small)";
end if;
if Before > Container.Last
and then Before > Container.Last + 1
then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "Before index is out of range (too large)";
end if;
if Count = 0 then
end if;
declare
- Old_Last : constant Extended_Index := Container.Last;
-
- Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
+ Old_Last_As_Int : constant Int := Int (Container.Last);
begin
+ if Old_Last_As_Int > Int'Last - N then -- see Insert ???
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
New_Last_As_Int := Old_Last_As_Int + N;
- if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ if New_Last_As_Int > Int (Index_Type'Last) then
+ raise Constraint_Error with "new length is out of range";
+ end if;
+
+ New_Length := UInt (New_Last_As_Int - First + Int'(1));
+
+ if New_Length > Max_Length then
+ raise Constraint_Error with "new length is out of range";
end if;
New_Last := Index_Type (New_Last_As_Int);
end;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
if Container.Elements = null then
end if;
declare
- First : constant Int := Int (Index_Type'First);
- New_Size : constant Int'Base := New_Last_As_Int - First + 1;
- Size : Int'Base := Int'Max (1, Container.Elements'Length);
+ C, CC : UInt;
begin
- while Size < New_Size loop
- if Size > Int'Last / 2 then
- Size := Int'Last;
+ C := UInt'Max (1, Container.Elements'Length);
+ while C < New_Length loop
+ if C > UInt'Last / 2 then
+ C := UInt'Last;
exit;
end if;
- Size := 2 * Size;
+ C := 2 * C;
end loop;
- -- TODO: The following calculations aren't quite right, since
- -- there will be overflow if Index_Type'Range is very large
- -- (e.g. this package is instantiated with a 64-bit integer).
- -- END TODO.
+ if C > Max_Length then
+ C := Max_Length;
+ end if;
- declare
- Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
- begin
- if Size > Max_Size then
- Size := Max_Size;
- end if;
- end;
+ if Index_Type'First <= 0
+ and then Index_Type'Last >= 0
+ then
+ CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
+
+ else
+ CC := UInt (Int (Index_Type'Last) - First + 1);
+ end if;
+
+ if C > CC then
+ C := CC;
+ end if;
declare
- Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
+ Dst_Last : constant Index_Type :=
+ Index_Type (First + UInt'Pos (C) - 1);
+
begin
Dst := new Elements_Type (Index_Type'First .. Dst_Last);
end;
begin
if Before.Container /= null
- and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
+ and then Before.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Before cursor denotes wrong container";
end if;
if Count = 0 then
or else Before.Index > Container.Last
then
if Container.Last = Index_Type'Last then
- raise Constraint_Error;
+ raise Constraint_Error with
+ "vector is already at its maximum length";
end if;
Index := Container.Last + 1;
N : constant Int'Base := L - F + 1;
begin
- if N > Count_Type'Pos (Count_Type'Last) then
- raise Constraint_Error;
- end if;
-
return Count_Type (N);
end Length;
end if;
if Target.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (Target is busy)";
end if;
if Source.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (Source is busy)";
end if;
declare
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
B := B + 1;
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
Query_Element (Position.Container.all, Position.Index, Process);
----------
procedure Read
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Container : out Vector)
is
Length : Count_Type'Base;
end Read;
procedure Read
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Position : out Cursor)
is
begin
- raise Program_Error;
+ raise Program_Error with "attempt to stream vector cursor";
end Read;
---------------------
is
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
Container.Elements (Index) := New_Item;
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
if Position.Container /= Container'Unrestricted_Access then
- raise Program_Error;
+ raise Program_Error with "Position cursor denotes wrong container";
end if;
Replace_Element (Container, Position.Index, New_Item);
elsif N < Container.Elements'Length then
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "new length is out of range";
end if;
declare
subtype Array_Subtype is
Elements_Type (Index_Type'First .. Last);
+
begin
Container.Elements := new Array_Subtype;
end;
if Capacity <= N then
if N < Container.Elements'Length then
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
declare
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "new length is out of range";
end if;
declare
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
declare
- I : Index_Type := Index_Type'First;
- J : Index_Type := Container.Last;
- E : Elements_Type renames Container.Elements.all;
+ I, J : Index_Type;
+ E : Elements_Type renames Container.Elements.all;
begin
+ I := Index_Type'First;
+ J := Container.Last;
while I < J loop
declare
EI : constant Element_Type := E (I);
begin
if Position.Container /= null
- and then Position.Container /=
- Vector_Access'(Container'Unchecked_Access)
+ and then Position.Container /= Container'Unchecked_Access
then
- raise Program_Error;
+ raise Program_Error with "Position cursor denotes wrong container";
end if;
if Position.Container = null
end if;
if Container.Busy > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with elements (vector is busy)";
end if;
if Length > Capacity (Container) then
procedure Swap (Container : in out Vector; I, J : Index_Type) is
begin
- if I > Container.Last
- or else J > Container.Last
- then
- raise Constraint_Error;
+ if I > Container.Last then
+ raise Constraint_Error with "I index is out of range";
+ end if;
+
+ if J > Container.Last then
+ raise Constraint_Error with "J index is out of range";
end if;
if I = J then
end if;
if Container.Lock > 0 then
- raise Program_Error;
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
end if;
declare
procedure Swap (Container : in out Vector; I, J : Cursor) is
begin
- if I.Container = null
- or else J.Container = null
- then
- raise Constraint_Error;
+ if I.Container = null then
+ raise Constraint_Error with "I cursor has no element";
end if;
- if I.Container /= Container'Unrestricted_Access
- or else J.Container /= Container'Unrestricted_Access
- then
- raise Program_Error;
+ if J.Container = null then
+ raise Constraint_Error with "J cursor has no element";
+ end if;
+
+ if I.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "I cursor denotes wrong container";
+ end if;
+
+ if J.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "J cursor denotes wrong container";
end if;
Swap (Container, I.Index, J.Index);
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "Length is out of range";
end if;
Last := Index_Type (Last_As_Int);
Elements := new Elements_Type (Index_Type'First .. Last);
- return (Controlled with Elements, Last, 0, 0);
+ return Vector'(Controlled with Elements, Last, 0, 0);
end;
end To_Vector;
begin
if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
- raise Constraint_Error;
+ raise Constraint_Error with "Length is out of range";
end if;
Last := Index_Type (Last_As_Int);
Elements := new Elements_Type'(Index_Type'First .. Last => New_Item);
- return (Controlled with Elements, Last, 0, 0);
+ return Vector'(Controlled with Elements, Last, 0, 0);
end;
end To_Vector;
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
B := B + 1;
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
if Position.Container /= Container'Unrestricted_Access then
- raise Program_Error;
+ raise Program_Error with "Position cursor denotes wrong container";
end if;
Update_Element (Container, Position.Index, Process);
-----------
procedure Write
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Container : Vector)
is
begin
end Write;
procedure Write
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Position : Cursor)
is
begin
- raise Program_Error;
+ raise Program_Error with "attempt to stream vector cursor";
end Write;
end Ada.Containers.Vectors;