-- --
-- B o d y --
-- --
--- Copyright (C) 2004-2005 Free Software Foundation, Inc. --
--- --
--- This specification is derived from the Ada Reference Manual for use with --
--- GNAT. The copyright notice above, and the license provisions that follow --
--- apply solely to the contents of the part following the private keyword. --
+-- Copyright (C) 2004-2009, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 2, or (at your option) any later ver- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
--- for more details. You should have received a copy of the GNU General --
--- Public License distributed with GNAT; see file COPYING. If not, write --
--- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
--- Boston, MA 02110-1301, USA. --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
-- --
--- As a special exception, if other files instantiate generics from this --
--- unit, or you link this unit with other files to produce an executable, --
--- this unit does not by itself cause the resulting executable to be --
--- covered by the GNU General Public License. This exception does not --
--- however invalidate any other reasons why the executable file might be --
--- covered by the GNU Public License. --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
-- --
-- This unit was originally developed by Matthew J Heaney. --
------------------------------------------------------------------------------
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
- RE : Elements_Type renames
- Right.Elements (Index_Type'First .. Right.Last);
+ RE : Elements_Array renames
+ Right.Elements.EA (Index_Type'First .. Right.Last);
Elements : constant Elements_Access :=
- new Elements_Type'(RE);
+ new Elements_Type'(Right.Last, RE);
begin
return (Controlled with Elements, Right.Last, 0, 0);
if RN = 0 then
declare
- LE : Elements_Type renames
- Left.Elements (Index_Type'First .. Left.Last);
+ LE : Elements_Array renames
+ Left.Elements.EA (Index_Type'First .. Left.Last);
Elements : constant Elements_Access :=
- new Elements_Type'(LE);
+ new Elements_Type'(Left.Last, LE);
begin
return (Controlled with Elements, Left.Last, 0, 0);
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
Last : constant Index_Type := Index_Type (Last_As_Int);
- LE : Elements_Type renames
- Left.Elements (Index_Type'First .. Left.Last);
+ LE : Elements_Array renames
+ Left.Elements.EA (Index_Type'First .. Left.Last);
- RE : Elements_Type renames
- Right.Elements (Index_Type'First .. Right.Last);
+ RE : Elements_Array renames
+ Right.Elements.EA (Index_Type'First .. Right.Last);
Elements : constant Elements_Access :=
- new Elements_Type'(LE & RE);
+ new Elements_Type'(Last, LE & RE);
begin
return (Controlled with Elements, Last, 0, 0);
begin
if LN = 0 then
declare
- subtype Elements_Subtype is
- Elements_Type (Index_Type'First .. Index_Type'First);
-
Elements : constant Elements_Access :=
- new Elements_Subtype'(others => Right);
+ new Elements_Type'
+ (Last => Index_Type'First,
+ EA => (others => Right));
begin
return (Controlled with Elements, Index_Type'First, 0, 0);
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
Last : constant Index_Type := Index_Type (Last_As_Int);
- LE : Elements_Type renames
- Left.Elements (Index_Type'First .. Left.Last);
-
- subtype ET is Elements_Type (Index_Type'First .. Last);
+ LE : Elements_Array renames
+ Left.Elements.EA (Index_Type'First .. Left.Last);
- Elements : constant Elements_Access := new ET'(LE & Right);
+ Elements : constant Elements_Access :=
+ new Elements_Type'
+ (Last => Last,
+ EA => LE & Right);
begin
return (Controlled with Elements, Last, 0, 0);
begin
if RN = 0 then
declare
- subtype Elements_Subtype is
- Elements_Type (Index_Type'First .. Index_Type'First);
-
Elements : constant Elements_Access :=
- new Elements_Subtype'(others => Left);
+ new Elements_Type'
+ (Last => Index_Type'First,
+ EA => (others => Left));
begin
return (Controlled with Elements, Index_Type'First, 0, 0);
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
Last : constant Index_Type := Index_Type (Last_As_Int);
- RE : Elements_Type renames
- Right.Elements (Index_Type'First .. Right.Last);
-
- subtype ET is Elements_Type (Index_Type'First .. Last);
+ RE : Elements_Array renames
+ Right.Elements.EA (Index_Type'First .. Right.Last);
- Elements : constant Elements_Access := new ET'(Left & RE);
+ Elements : constant Elements_Access :=
+ new Elements_Type'
+ (Last => Last,
+ EA => Left & RE);
begin
return (Controlled with Elements, Last, 0, 0);
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
Last : constant Index_Type := Index_Type'First + 1;
- subtype ET is Elements_Type (Index_Type'First .. Last);
-
- Elements : constant Elements_Access := new ET'(Left, Right);
+ Elements : constant Elements_Access :=
+ new Elements_Type'
+ (Last => Last,
+ EA => (Left, Right));
begin
return (Controlled with Elements, Last, 0, 0);
-- "=" --
---------
- function "=" (Left, Right : Vector) return Boolean is
+ overriding function "=" (Left, Right : Vector) return Boolean is
begin
if Left'Address = Right'Address then
return True;
end if;
for J in Index_Type range Index_Type'First .. Left.Last loop
- if Left.Elements (J) /= Right.Elements (J) then
+ if Left.Elements.EA (J) /= Right.Elements.EA (J) then
return False;
end if;
end loop;
end if;
declare
- E : constant Elements_Access := Container.Elements;
- L : constant Index_Type := Container.Last;
+ L : constant Index_Type := Container.Last;
+ EA : Elements_Array renames
+ Container.Elements.EA (Index_Type'First .. L);
begin
Container.Elements := null;
- Container.Last := No_Index;
Container.Busy := 0;
Container.Lock := 0;
- Container.Elements := new Elements_Type'(E (Index_Type'First .. L));
+
+ -- Note: it may seem that the following assignment to Container.Last
+ -- is useless, since we assign it to L below. However this code is
+ -- used in case 'new Elements_Type' below raises an exception, to
+ -- keep Container in a consistent state.
+
+ Container.Last := No_Index;
+ Container.Elements := new Elements_Type'(L, EA);
Container.Last := L;
end;
end Adjust;
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
Count);
end Append;
- ------------
- -- Assign --
- ------------
-
- procedure Assign
- (Target : in out Vector;
- Source : Vector)
- is
- N : constant Count_Type := Length (Source);
-
- begin
- if Target'Address = Source'Address then
- return;
- end if;
-
- Clear (Target);
-
- if N = 0 then
- return;
- end if;
-
- if N > Capacity (Target) then
- Reserve_Capacity (Target, Capacity => N);
- end if;
-
- Target.Elements (Index_Type'First .. Source.Last) :=
- Source.Elements (Index_Type'First .. Source.Last);
-
- Target.Last := Source.Last;
- end Assign;
-
--------------
-- Capacity --
--------------
return 0;
end if;
- return Container.Elements'Length;
+ return Container.Elements.EA'Length;
end Capacity;
-----------
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
else
declare
- J : constant Index_Type := Index_Type (J_As_Int);
- E : Elements_Type renames Container.Elements.all;
+ J : constant Index_Type := Index_Type (J_As_Int);
+ EA : Elements_Array renames Container.Elements.EA;
New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
New_Last : constant Index_Type :=
Index_Type (New_Last_As_Int);
begin
- E (Index .. New_Last) := E (J .. Container.Last);
+ EA (Index .. New_Last) := EA (J .. Container.Last);
Container.Last := New_Last;
end;
end if;
Position : in out Cursor;
Count : Count_Type := 1)
is
+ pragma Warnings (Off, Position);
+
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
- if Position.Container /=
- Vector_Access'(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;
- Delete (Container, Position.Index, Count);
-
- if Position.Index <= Container.Last then
- Position := (Container'Unchecked_Access, Position.Index);
- else
- Position := No_Element;
+ if Position.Index > Container.Last then
+ raise Program_Error with "Position index is out of range";
end if;
+
+ Delete (Container, Position.Index, Count);
+ Position := No_Element;
end Delete;
------------------
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);
- if Index < Index_Type'Pos (Index_Type'First) then
- Container.Last := No_Index;
- else
- Container.Last := Index_Type (Index);
- end if;
+ Container.Last :=
+ (if Index < Index_Type'Pos (Index_Type'First)
+ then No_Index
+ else Index_Type (Index));
end Delete_Last;
-------------
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);
+ return Container.Elements.EA (Index);
end Element;
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;
+
+ if Position.Index > Position.Container.Last then
+ raise Constraint_Error with "Position cursor is out of range";
end if;
- return Element (Position.Container.all, Position.Index);
+ return Position.Container.Elements.EA (Position.Index);
end Element;
--------------
procedure Finalize (Container : in out Vector) is
X : Elements_Access := Container.Elements;
+
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;
function Find
(Container : Vector;
Item : Element_Type;
- Position : Cursor := No_Element) return Cursor is
-
+ Position : Cursor := No_Element) return Cursor
+ is
begin
- if Position.Container /= null
- and then (Position.Container /=
- Vector_Access'(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
- if Container.Elements (J) = Item then
+ if Container.Elements.EA (J) = Item then
return (Container'Unchecked_Access, J);
end if;
end loop;
function Find_Index
(Container : Vector;
Item : Element_Type;
- Index : Index_Type := Index_Type'First) return Extended_Index is
+ Index : Index_Type := Index_Type'First) return Extended_Index
+ is
begin
for Indx in Index .. Container.Last loop
- if Container.Elements (Indx) = Item then
+ if Container.Elements.EA (Indx) = Item then
return Indx;
end if;
end loop;
function First_Element (Container : Vector) return Element_Type is
begin
- return Element (Container, Index_Type'First);
+ if Container.Last = No_Index then
+ raise Constraint_Error with "Container is empty";
+ end if;
+
+ return Container.Elements.EA (Index_Type'First);
end First_Element;
-----------------
end if;
declare
- E : Elements_Type renames Container.Elements.all;
+ EA : Elements_Array renames Container.Elements.EA;
begin
for I in Index_Type'First .. Container.Last - 1 loop
- if E (I + 1) < E (I) then
+ if EA (I + 1) < EA (I) then
return False;
end if;
end 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));
- J := Target.Last;
- while Source.Last >= Index_Type'First loop
- if I < Index_Type'First then
- Target.Elements (Index_Type'First .. J) :=
- Source.Elements (Index_Type'First .. Source.Last);
+ declare
+ TA : Elements_Array renames Target.Elements.EA;
+ SA : Elements_Array renames Source.Elements.EA;
- Source.Last := No_Index;
- return;
- end if;
+ begin
+ J := Target.Last;
+ while Source.Last >= Index_Type'First loop
+ pragma Assert (Source.Last <= Index_Type'First
+ or else not (SA (Source.Last) <
+ SA (Source.Last - 1)));
+
+ if I < Index_Type'First then
+ TA (Index_Type'First .. J) :=
+ SA (Index_Type'First .. Source.Last);
+
+ Source.Last := No_Index;
+ return;
+ end if;
- if Source.Elements (Source.Last) < Target.Elements (I) then
- Target.Elements (J) := Target.Elements (I);
- I := I - 1;
+ pragma Assert (I <= Index_Type'First
+ or else not (TA (I) < TA (I - 1)));
- else
- Target.Elements (J) := Source.Elements (Source.Last);
- Source.Last := Source.Last - 1;
- end if;
+ if SA (Source.Last) < TA (I) then
+ TA (J) := TA (I);
+ I := I - 1;
- J := J - 1;
- end loop;
+ else
+ TA (J) := SA (Source.Last);
+ Source.Last := Source.Last - 1;
+ end if;
+
+ J := J - 1;
+ end loop;
+ end;
end Merge;
----------
new Generic_Array_Sort
(Index_Type => Index_Type,
Element_Type => Element_Type,
- Array_Type => Elements_Type,
+ Array_Type => Elements_Array,
"<" => "<");
begin
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));
+ Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
end Sort;
end Generic_Sorting;
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
+ 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
- declare
- subtype Elements_Subtype is
- Elements_Type (Index_Type'First .. New_Last);
- begin
- Container.Elements := new Elements_Subtype'(others => New_Item);
- end;
-
+ Container.Elements := new Elements_Type'
+ (Last => New_Last,
+ EA => (others => New_Item));
Container.Last := New_Last;
return;
end if;
- if New_Last <= Container.Elements'Last then
+ if New_Last <= Container.Elements.Last then
declare
- E : Elements_Type renames Container.Elements.all;
+ EA : Elements_Array renames Container.Elements.EA;
+
begin
if Before <= Container.Last then
declare
Index : constant Index_Type := Index_Type (Index_As_Int);
begin
- E (Index .. New_Last) := E (Before .. Container.Last);
+ EA (Index .. New_Last) := EA (Before .. Container.Last);
- E (Before .. Index_Type'Pred (Index)) :=
+ EA (Before .. Index_Type'Pred (Index)) :=
(others => New_Item);
end;
else
- E (Before .. New_Last) := (others => New_Item);
+ EA (Before .. New_Last) := (others => New_Item);
end if;
end;
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.EA'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);
+ Dst := new Elements_Type (Dst_Last);
end;
end;
declare
- Src : Elements_Type renames Container.Elements.all;
+ SA : Elements_Array renames Container.Elements.EA;
+ DA : Elements_Array renames Dst.EA;
begin
- Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
- Src (Index_Type'First .. Index_Type'Pred (Before));
+ DA (Index_Type'First .. Index_Type'Pred (Before)) :=
+ SA (Index_Type'First .. Index_Type'Pred (Before));
if Before <= Container.Last then
declare
Index : constant Index_Type := Index_Type (Index_As_Int);
begin
- Dst (Before .. Index_Type'Pred (Index)) := (others => New_Item);
- Dst (Index .. New_Last) := Src (Before .. Container.Last);
+ DA (Before .. Index_Type'Pred (Index)) := (others => New_Item);
+ DA (Index .. New_Last) := SA (Before .. Container.Last);
end;
else
- Dst (Before .. New_Last) := (others => New_Item);
+ DA (Before .. New_Last) := (others => New_Item);
end if;
exception
when others =>
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 Container'Address /= New_Item'Address then
- Container.Elements (Before .. Dst_Last) :=
- New_Item.Elements (Index_Type'First .. New_Item.Last);
+ Container.Elements.EA (Before .. Dst_Last) :=
+ New_Item.Elements.EA (Index_Type'First .. New_Item.Last);
return;
end if;
subtype Src_Index_Subtype is Index_Type'Base range
Index_Type'First .. Before - 1;
- Src : Elements_Type renames
- Container.Elements (Src_Index_Subtype);
+ Src : Elements_Array renames
+ Container.Elements.EA (Src_Index_Subtype);
Index_As_Int : constant Int'Base :=
Int (Before) + Src'Length - 1;
Index : constant Index_Type'Base :=
Index_Type'Base (Index_As_Int);
- Dst : Elements_Type renames
- Container.Elements (Before .. Index);
+ Dst : Elements_Array renames
+ Container.Elements.EA (Before .. Index);
begin
Dst := Src;
subtype Src_Index_Subtype is Index_Type'Base range
Dst_Last + 1 .. Container.Last;
- Src : Elements_Type renames
- Container.Elements (Src_Index_Subtype);
+ Src : Elements_Array renames
+ Container.Elements.EA (Src_Index_Subtype);
Index_As_Int : constant Int'Base :=
Dst_Last_As_Int - Src'Length + 1;
Index : constant Index_Type :=
Index_Type (Index_As_Int);
- Dst : Elements_Type renames
- Container.Elements (Index .. Dst_Last);
+ Dst : Elements_Array renames
+ Container.Elements.EA (Index .. Dst_Last);
begin
Dst := Src;
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;
Position := Cursor'(Container'Unchecked_Access, Index);
end Insert;
+ procedure Insert
+ (Container : in out Vector;
+ Before : Extended_Index;
+ Count : Count_Type := 1)
+ is
+ New_Item : Element_Type; -- Default-initialized value
+ pragma Warnings (Off, New_Item);
+
+ begin
+ Insert (Container, Before, New_Item, Count);
+ end Insert;
+
+ procedure Insert
+ (Container : in out Vector;
+ Before : Cursor;
+ Position : out Cursor;
+ Count : Count_Type := 1)
+ is
+ New_Item : Element_Type; -- Default-initialized value
+ pragma Warnings (Off, New_Item);
+
+ begin
+ Insert (Container, Before, New_Item, Position, Count);
+ end Insert;
+
------------------
-- Insert_Space --
------------------
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
+ 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
- Container.Elements :=
- new Elements_Type (Index_Type'First .. New_Last);
-
+ Container.Elements := new Elements_Type (New_Last);
Container.Last := New_Last;
return;
end if;
- if New_Last <= Container.Elements'Last then
+ if New_Last <= Container.Elements.Last then
declare
- E : Elements_Type renames Container.Elements.all;
+ EA : Elements_Array renames Container.Elements.EA;
begin
if Before <= Container.Last then
declare
Index : constant Index_Type := Index_Type (Index_As_Int);
begin
- E (Index .. New_Last) := E (Before .. Container.Last);
+ EA (Index .. New_Last) := EA (Before .. Container.Last);
end;
end if;
end;
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.EA'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);
+ Dst := new Elements_Type (Dst_Last);
end;
end;
declare
- Src : Elements_Type renames Container.Elements.all;
+ SA : Elements_Array renames Container.Elements.EA;
+ DA : Elements_Array renames Dst.EA;
begin
- Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
- Src (Index_Type'First .. Index_Type'Pred (Before));
+ DA (Index_Type'First .. Index_Type'Pred (Before)) :=
+ SA (Index_Type'First .. Index_Type'Pred (Before));
if Before <= Container.Last then
declare
Index : constant Index_Type := Index_Type (Index_As_Int);
begin
- Dst (Index .. New_Last) := Src (Before .. Container.Last);
+ DA (Index .. New_Last) := SA (Before .. Container.Last);
end;
end if;
exception
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;
Index := Before.Index;
end if;
- Insert_Space (Container, Index, Count);
+ Insert_Space (Container, Index, Count => Count);
Position := Cursor'(Container'Unchecked_Access, Index);
end Insert_Space;
B : Natural renames V.Busy;
begin
-
B := B + 1;
begin
end;
B := B - 1;
-
end Iterate;
----------
function Last_Element (Container : Vector) return Element_Type is
begin
- return Element (Container, Container.Last);
+ if Container.Last = No_Index then
+ raise Constraint_Error with "Container is empty";
+ end if;
+
+ return Container.Elements.EA (Container.Last);
end Last_Element;
----------------
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;
L := L + 1;
begin
- Process (V.Elements (Index));
+ Process (V.Elements.EA (Index));
exception
when others =>
L := L - 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;
for J in Count_Type range 1 .. Length loop
Last := Last + 1;
- Element_Type'Read (Stream, Container.Elements (Last));
+ Element_Type'Read (Stream, Container.Elements.EA (Last));
Container.Last := Last;
end loop;
end Read;
+ procedure Read
+ (Stream : not null access Root_Stream_Type'Class;
+ Position : out Cursor)
+ is
+ begin
+ raise Program_Error with "attempt to stream vector cursor";
+ end Read;
+
---------------------
-- Replace_Element --
---------------------
procedure Replace_Element
- (Container : Vector;
+ (Container : in out Vector;
Index : Index_Type;
- By : Element_Type)
+ New_Item : Element_Type)
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) := By;
+ Container.Elements.EA (Index) := New_Item;
end Replace_Element;
- procedure Replace_Element (Position : Cursor; By : Element_Type) is
+ procedure Replace_Element
+ (Container : in out Vector;
+ Position : Cursor;
+ New_Item : Element_Type)
+ is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
- Replace_Element (Position.Container.all, Position.Index, By);
+ 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 Constraint_Error with "Position cursor is out of range";
+ end if;
+
+ if Container.Lock > 0 then
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
+ end if;
+
+ Container.Elements.EA (Position.Index) := New_Item;
end Replace_Element;
----------------------
Free (X);
end;
- elsif N < Container.Elements'Length then
+ elsif N < Container.Elements.EA'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
- subtype Array_Index_Subtype is Index_Type'Base range
+ subtype Src_Index_Subtype is Index_Type'Base range
Index_Type'First .. Container.Last;
- Src : Elements_Type renames
- Container.Elements (Array_Index_Subtype);
-
- subtype Array_Subtype is
- Elements_Type (Array_Index_Subtype);
+ Src : Elements_Array renames
+ Container.Elements.EA (Src_Index_Subtype);
X : Elements_Access := Container.Elements;
begin
- Container.Elements := new Array_Subtype'(Src);
+ Container.Elements := new Elements_Type'(Container.Last, Src);
Free (X);
end;
end if;
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
Last : constant Index_Type := Index_Type (Last_As_Int);
- subtype Array_Subtype is
- Elements_Type (Index_Type'First .. Last);
begin
- Container.Elements := new Array_Subtype;
+ Container.Elements := new Elements_Type (Last);
end;
end;
end if;
if Capacity <= N then
- if N < Container.Elements'Length then
+ if N < Container.Elements.EA'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
- subtype Array_Index_Subtype is Index_Type'Base range
+ subtype Src_Index_Subtype is Index_Type'Base range
Index_Type'First .. Container.Last;
- Src : Elements_Type renames
- Container.Elements (Array_Index_Subtype);
-
- subtype Array_Subtype is
- Elements_Type (Array_Index_Subtype);
+ Src : Elements_Array renames
+ Container.Elements.EA (Src_Index_Subtype);
X : Elements_Access := Container.Elements;
begin
- Container.Elements := new Array_Subtype'(Src);
+ Container.Elements := new Elements_Type'(Container.Last, Src);
Free (X);
end;
return;
end if;
- if Capacity = Container.Elements'Length then
+ if Capacity = Container.Elements.EA'Length then
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
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
Last : constant Index_Type := Index_Type (Last_As_Int);
- subtype Array_Subtype is
- Elements_Type (Index_Type'First .. Last);
-
- E : Elements_Access := new Array_Subtype;
+ E : Elements_Access := new Elements_Type (Last);
begin
declare
- Src : Elements_Type renames
- Container.Elements (Index_Type'First .. Container.Last);
+ subtype Index_Subtype is Index_Type'Base range
+ Index_Type'First .. Container.Last;
- Tgt : Elements_Type renames
- E (Index_Type'First .. Container.Last);
+ Src : Elements_Array renames
+ Container.Elements.EA (Index_Subtype);
+
+ Tgt : Elements_Array renames E.EA (Index_Subtype);
begin
Tgt := Src;
end;
end Reserve_Capacity;
+ ----------------------
+ -- Reverse_Elements --
+ ----------------------
+
+ procedure Reverse_Elements (Container : in out Vector) is
+ begin
+ if Container.Length <= 1 then
+ return;
+ end if;
+
+ if Container.Lock > 0 then
+ raise Program_Error with
+ "attempt to tamper with cursors (vector is locked)";
+ end if;
+
+ declare
+ 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.EA (I);
+
+ begin
+ E.EA (I) := E.EA (J);
+ E.EA (J) := EI;
+ end;
+
+ I := I + 1;
+ J := J - 1;
+ end loop;
+ end;
+ end Reverse_Elements;
+
------------------
-- Reverse_Find --
------------------
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
- or else Position.Index > Container.Last
- then
- Last := Container.Last;
- else
- Last := Position.Index;
- end if;
+ Last :=
+ (if Position.Container = null or else Position.Index > Container.Last
+ then Container.Last
+ else Position.Index);
for Indx in reverse Index_Type'First .. Last loop
- if Container.Elements (Indx) = Item then
+ if Container.Elements.EA (Indx) = Item then
return (Container'Unchecked_Access, Indx);
end if;
end loop;
Item : Element_Type;
Index : Index_Type := Index_Type'Last) return Extended_Index
is
- Last : Index_Type'Base;
+ Last : constant Index_Type'Base :=
+ Index_Type'Min (Container.Last, Index);
begin
- if Index > Container.Last then
- Last := Container.Last;
- else
- Last := Index;
- end if;
-
for Indx in reverse Index_Type'First .. Last loop
- if Container.Elements (Indx) = Item then
+ if Container.Elements.EA (Indx) = Item then
return Indx;
end if;
end loop;
B : Natural renames V.Busy;
begin
-
B := B + 1;
begin
end;
B := B - 1;
-
end Reverse_Iterate;
----------------
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
-- Swap --
----------
- procedure Swap (Container : Vector; I, J : Index_Type) is
+ 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
- EI : Element_Type renames Container.Elements (I);
- EJ : Element_Type renames Container.Elements (J);
-
- EI_Copy : constant Element_Type := EI;
-
+ EI_Copy : constant Element_Type := Container.Elements.EA (I);
begin
- EI := EJ;
- EJ := EI_Copy;
+ Container.Elements.EA (I) := Container.Elements.EA (J);
+ Container.Elements.EA (J) := EI_Copy;
end;
end Swap;
- procedure Swap (I, J : Cursor) is
+ 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 /= J.Container then
- raise Program_Error;
+ if J.Container = null then
+ raise Constraint_Error with "J cursor has no element";
end if;
- Swap (I.Container.all, I.Index, J.Index);
+ 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);
end Swap;
---------------
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);
+ Elements := new Elements_Type (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);
+ Elements := new Elements_Type'(Last, EA => (others => New_Item));
- return (Controlled with Elements, Last, 0, 0);
+ return Vector'(Controlled with Elements, Last, 0, 0);
end;
end To_Vector;
--------------------
procedure Update_Element
- (Container : Vector;
+ (Container : in out Vector;
Index : Index_Type;
Process : not null access procedure (Element : in out Element_Type))
is
- V : Vector renames Container'Unrestricted_Access.all;
- B : Natural renames V.Busy;
- L : Natural renames V.Lock;
+ B : Natural renames Container.Busy;
+ L : Natural renames Container.Lock;
begin
if Index > Container.Last then
- raise Constraint_Error;
+ raise Constraint_Error with "Index is out of range";
end if;
B := B + 1;
L := L + 1;
begin
- Process (V.Elements (Index));
+ Process (Container.Elements.EA (Index));
exception
when others =>
L := L - 1;
end Update_Element;
procedure Update_Element
- (Position : Cursor;
- Process : not null access procedure (Element : in out Element_Type))
+ (Container : in out Vector;
+ Position : Cursor;
+ Process : not null access procedure (Element : in out Element_Type))
is
begin
if Position.Container = null then
- raise Constraint_Error;
+ raise Constraint_Error with "Position cursor has no element";
end if;
- Update_Element (Position.Container.all, Position.Index, Process);
+ if Position.Container /= Container'Unrestricted_Access then
+ raise Program_Error with "Position cursor denotes wrong container";
+ end if;
+
+ Update_Element (Container, Position.Index, Process);
end Update_Element;
-----------
-----------
procedure Write
- (Stream : access Root_Stream_Type'Class;
+ (Stream : not null access Root_Stream_Type'Class;
Container : Vector)
is
begin
Count_Type'Base'Write (Stream, Length (Container));
for J in Index_Type'First .. Container.Last loop
- Element_Type'Write (Stream, Container.Elements (J));
+ Element_Type'Write (Stream, Container.Elements.EA (J));
end loop;
end Write;
+ procedure Write
+ (Stream : not null access Root_Stream_Type'Class;
+ Position : Cursor)
+ is
+ begin
+ raise Program_Error with "attempt to stream vector cursor";
+ end Write;
+
end Ada.Containers.Vectors;