1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . I N D E F I N I T E _ V E C T O R S --
9 -- Copyright (C) 2004-2006, Free Software Foundation, Inc. --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 2, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21 -- for more details. You should have received a copy of the GNU General --
22 -- Public License distributed with GNAT; see file COPYING. If not, write --
23 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
24 -- Boston, MA 02110-1301, USA. --
26 -- As a special exception, if other files instantiate generics from this --
27 -- unit, or you link this unit with other files to produce an executable, --
28 -- this unit does not by itself cause the resulting executable to be --
29 -- covered by the GNU General Public License. This exception does not --
30 -- however invalidate any other reasons why the executable file might be --
31 -- covered by the GNU Public License. --
33 -- This unit has originally being developed by Matthew J Heaney. --
34 ------------------------------------------------------------------------------
36 with Ada
.Containers
.Generic_Array_Sort
;
37 with Ada
.Unchecked_Deallocation
;
38 with System
; use type System
.Address
;
40 package body Ada
.Containers
.Indefinite_Vectors
is
42 type Int
is range System
.Min_Int
.. System
.Max_Int
;
43 type UInt
is mod System
.Max_Binary_Modulus
;
46 new Ada
.Unchecked_Deallocation
(Elements_Type
, Elements_Access
);
49 new Ada
.Unchecked_Deallocation
(Element_Type
, Element_Access
);
55 function "&" (Left
, Right
: Vector
) return Vector
is
56 LN
: constant Count_Type
:= Length
(Left
);
57 RN
: constant Count_Type
:= Length
(Right
);
66 RE
: Elements_Type
renames
67 Right
.Elements
(Index_Type
'First .. Right
.Last
);
69 Elements
: Elements_Access
:=
70 new Elements_Type
(RE
'Range);
73 for I
in Elements
'Range loop
75 if RE
(I
) /= null then
76 Elements
(I
) := new Element_Type
'(RE (I).all);
80 for J in Index_Type'First .. I - 1 loop
89 return (Controlled with Elements, Right.Last, 0, 0);
96 LE : Elements_Type renames
97 Left.Elements (Index_Type'First .. Left.Last);
99 Elements : Elements_Access :=
100 new Elements_Type (LE'Range);
103 for I in Elements'Range loop
105 if LE (I) /= null then
106 Elements (I) := new Element_Type'(LE
(I
).all);
110 for J
in Index_Type
'First .. I
- 1 loop
119 return (Controlled
with Elements
, Left
.Last
, 0, 0);
124 N
: constant Int
'Base := Int
(LN
) + Int
(RN
);
125 Last_As_Int
: Int
'Base;
128 if Int
(No_Index
) > Int
'Last - N
then
129 raise Constraint_Error
with "new length is out of range";
132 Last_As_Int
:= Int
(No_Index
) + N
;
134 if Last_As_Int
> Int
(Index_Type
'Last) then
135 raise Constraint_Error
with "new length is out of range";
139 Last
: constant Index_Type
:= Index_Type
(Last_As_Int
);
141 LE
: Elements_Type
renames
142 Left
.Elements
(Index_Type
'First .. Left
.Last
);
144 RE
: Elements_Type
renames
145 Right
.Elements
(Index_Type
'First .. Right
.Last
);
147 Elements
: Elements_Access
:=
148 new Elements_Type
(Index_Type
'First .. Last
);
150 I
: Index_Type
'Base := No_Index
;
153 for LI
in LE
'Range loop
157 if LE
(LI
) /= null then
158 Elements
(I
) := new Element_Type
'(LE (LI).all);
162 for J in Index_Type'First .. I - 1 loop
171 for RI in RE'Range loop
175 if RE (RI) /= null then
176 Elements (I) := new Element_Type'(RE
(RI
).all);
180 for J
in Index_Type
'First .. I
- 1 loop
189 return (Controlled
with Elements
, Last
, 0, 0);
194 function "&" (Left
: Vector
; Right
: Element_Type
) return Vector
is
195 LN
: constant Count_Type
:= Length
(Left
);
200 subtype Elements_Subtype
is
201 Elements_Type
(Index_Type
'First .. Index_Type
'First);
203 Elements
: Elements_Access
:= new Elements_Subtype
;
207 Elements
(Elements
'First) := new Element_Type
'(Right);
214 return (Controlled with Elements, Index_Type'First, 0, 0);
219 Last_As_Int : Int'Base;
222 if Int (Index_Type'First) > Int'Last - Int (LN) then
223 raise Constraint_Error with "new length is out of range";
226 Last_As_Int := Int (Index_Type'First) + Int (LN);
228 if Last_As_Int > Int (Index_Type'Last) then
229 raise Constraint_Error with "new length is out of range";
233 Last : constant Index_Type := Index_Type (Last_As_Int);
235 LE : Elements_Type renames
236 Left.Elements (Index_Type'First .. Left.Last);
238 Elements : Elements_Access :=
239 new Elements_Type (Index_Type'First .. Last);
242 for I in LE'Range loop
244 if LE (I) /= null then
245 Elements (I) := new Element_Type'(LE
(I
).all);
249 for J
in Index_Type
'First .. I
- 1 loop
259 Elements
(Elements
'Last) := new Element_Type
'(Right);
262 for J in Index_Type'First .. Elements'Last - 1 loop
270 return (Controlled with Elements, Last, 0, 0);
275 function "&" (Left : Element_Type; Right : Vector) return Vector is
276 RN : constant Count_Type := Length (Right);
281 subtype Elements_Subtype is
282 Elements_Type (Index_Type'First .. Index_Type'First);
284 Elements : Elements_Access := new Elements_Subtype;
288 Elements (Elements'First) := new Element_Type'(Left
);
295 return (Controlled
with Elements
, Index_Type
'First, 0, 0);
300 Last_As_Int
: Int
'Base;
303 if Int
(Index_Type
'First) > Int
'Last - Int
(RN
) then
304 raise Constraint_Error
with "new length is out of range";
307 Last_As_Int
:= Int
(Index_Type
'First) + Int
(RN
);
309 if Last_As_Int
> Int
(Index_Type
'Last) then
310 raise Constraint_Error
with "new length is out of range";
314 Last
: constant Index_Type
:= Index_Type
(Last_As_Int
);
316 RE
: Elements_Type
renames
317 Right
.Elements
(Index_Type
'First .. Right
.Last
);
319 Elements
: Elements_Access
:=
320 new Elements_Type
(Index_Type
'First .. Last
);
322 I
: Index_Type
'Base := Index_Type
'First;
326 Elements
(I
) := new Element_Type
'(Left);
333 for RI in RE'Range loop
337 if RE (RI) /= null then
338 Elements (I) := new Element_Type'(RE
(RI
).all);
342 for J
in Index_Type
'First .. I
- 1 loop
351 return (Controlled
with Elements
, Last
, 0, 0);
356 function "&" (Left
, Right
: Element_Type
) return Vector
is
358 if Index_Type
'First >= Index_Type
'Last then
359 raise Constraint_Error
with "new length is out of range";
363 Last
: constant Index_Type
:= Index_Type
'First + 1;
365 subtype ET
is Elements_Type
(Index_Type
'First .. Last
);
367 Elements
: Elements_Access
:= new ET
;
371 Elements
(Elements
'First) := new Element_Type
'(Left);
379 Elements (Elements'Last) := new Element_Type'(Right
);
382 Free
(Elements
(Elements
'First));
387 return (Controlled
with Elements
, Elements
'Last, 0, 0);
395 function "=" (Left
, Right
: Vector
) return Boolean is
397 if Left
'Address = Right
'Address then
401 if Left
.Last
/= Right
.Last
then
405 for J
in Index_Type
'First .. Left
.Last
loop
406 if Left
.Elements
(J
) = null then
407 if Right
.Elements
(J
) /= null then
411 elsif Right
.Elements
(J
) = null then
414 elsif Left
.Elements
(J
).all /= Right
.Elements
(J
).all then
426 procedure Adjust
(Container
: in out Vector
) is
428 if Container
.Last
= No_Index
then
429 Container
.Elements
:= null;
434 E
: Elements_Type
renames Container
.Elements
.all;
435 L
: constant Index_Type
:= Container
.Last
;
438 Container
.Elements
:= null;
439 Container
.Last
:= No_Index
;
443 Container
.Elements
:= new Elements_Type
(Index_Type
'First .. L
);
445 for I
in Container
.Elements
'Range loop
446 if E
(I
) /= null then
447 Container
.Elements
(I
) := new Element_Type
'(E (I).all);
459 procedure Append (Container : in out Vector; New_Item : Vector) is
461 if Is_Empty (New_Item) then
465 if Container.Last = Index_Type'Last then
466 raise Constraint_Error with "vector is already at its maximum length";
476 (Container : in out Vector;
477 New_Item : Element_Type;
478 Count : Count_Type := 1)
485 if Container.Last = Index_Type'Last then
486 raise Constraint_Error with "vector is already at its maximum length";
500 function Capacity (Container : Vector) return Count_Type is
502 if Container.Elements = null then
506 return Container.Elements'Length;
513 procedure Clear (Container : in out Vector) is
515 if Container.Busy > 0 then
516 raise Program_Error with
517 "attempt to tamper with elements (vector is busy)";
520 while Container.Last >= Index_Type'First loop
522 X : Element_Access := Container.Elements (Container.Last);
524 Container.Elements (Container.Last) := null;
525 Container.Last := Container.Last - 1;
537 Item : Element_Type) return Boolean
540 return Find_Index (Container, Item) /= No_Index;
548 (Container : in out Vector;
549 Index : Extended_Index;
550 Count : Count_Type := 1)
553 if Index < Index_Type'First then
554 raise Constraint_Error with "Index is out of range (too small)";
557 if Index > Container.Last then
558 if Index > Container.Last + 1 then
559 raise Constraint_Error with "Index is out of range (too large)";
569 if Container.Busy > 0 then
570 raise Program_Error with
571 "attempt to tamper with elements (vector is busy)";
575 Index_As_Int : constant Int := Int (Index);
576 Old_Last_As_Int : constant Int := Int (Container.Last);
578 Count1 : constant Int'Base := Int (Count);
579 Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
580 N : constant Int'Base := Int'Min (Count1, Count2);
582 J_As_Int : constant Int'Base := Index_As_Int + N;
583 E : Elements_Type renames Container.Elements.all;
586 if J_As_Int > Old_Last_As_Int then
587 while Container.Last >= Index loop
589 K : constant Index_Type := Container.Last;
590 X : Element_Access := E (K);
594 Container.Last := K - 1;
601 J : constant Index_Type := Index_Type (J_As_Int);
603 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
604 New_Last : constant Index_Type :=
605 Index_Type (New_Last_As_Int);
608 for K in Index .. J - 1 loop
610 X : Element_Access := E (K);
617 E (Index .. New_Last) := E (J .. Container.Last);
618 Container.Last := New_Last;
625 (Container : in out Vector;
626 Position : in out Cursor;
627 Count : Count_Type := 1)
630 if Position.Container = null then
631 raise Constraint_Error with "Position cursor has no element";
634 if Position.Container /= Container'Unrestricted_Access then
635 raise Program_Error with "Position cursor denotes wrong container";
638 if Position.Index > Container.Last then
639 raise Program_Error with "Position index is out of range";
642 Delete (Container, Position.Index, Count);
644 Position := No_Element; -- See comment in a-convec.adb
651 procedure Delete_First
652 (Container : in out Vector;
653 Count : Count_Type := 1)
660 if Count >= Length (Container) then
665 Delete (Container, Index_Type'First, Count);
672 procedure Delete_Last
673 (Container : in out Vector;
674 Count : Count_Type := 1)
676 N : constant Count_Type := Length (Container);
685 if Container.Busy > 0 then
686 raise Program_Error with
687 "attempt to tamper with elements (vector is busy)";
691 E : Elements_Type renames Container.Elements.all;
694 for Indx in 1 .. Count_Type'Min (Count, N) loop
696 J : constant Index_Type := Container.Last;
697 X : Element_Access := E (J);
701 Container.Last := J - 1;
714 Index : Index_Type) return Element_Type
717 if Index > Container.Last then
718 raise Constraint_Error with "Index is out of range";
722 EA : constant Element_Access := Container.Elements (Index);
726 raise Constraint_Error with "element is empty";
733 function Element (Position : Cursor) return Element_Type is
735 if Position.Container = null then
736 raise Constraint_Error with "Position cursor has no element";
739 return Element (Position.Container.all, Position.Index);
746 procedure Finalize (Container : in out Vector) is
748 Clear (Container); -- Checks busy-bit
751 X : Elements_Access := Container.Elements;
753 Container.Elements := null;
765 Position : Cursor := No_Element) return Cursor
768 if Position.Container /= null then
769 if Position.Container /= Container'Unrestricted_Access then
770 raise Program_Error with "Position cursor denotes wrong container";
773 if Position.Index > Container.Last then
774 raise Program_Error with "Position index is out of range";
778 for J in Position.Index .. Container.Last loop
779 if Container.Elements (J) /= null
780 and then Container.Elements (J).all = Item
782 return (Container'Unchecked_Access, J);
796 Index : Index_Type := Index_Type'First) return Extended_Index
799 for Indx in Index .. Container.Last loop
800 if Container.Elements (Indx) /= null
801 and then Container.Elements (Indx).all = Item
814 function First (Container : Vector) return Cursor is
816 if Is_Empty (Container) then
820 return (Container'Unchecked_Access, Index_Type'First);
827 function First_Element (Container : Vector) return Element_Type is
829 return Element (Container, Index_Type'First);
836 function First_Index (Container : Vector) return Index_Type is
837 pragma Unreferenced (Container);
839 return Index_Type'First;
842 ---------------------
843 -- Generic_Sorting --
844 ---------------------
846 package body Generic_Sorting is
848 -----------------------
849 -- Local Subprograms --
850 -----------------------
852 function Is_Less (L, R : Element_Access) return Boolean;
853 pragma Inline (Is_Less);
859 function Is_Less (L, R : Element_Access) return Boolean is
866 return L.all < R.all;
874 function Is_Sorted (Container : Vector) return Boolean is
876 if Container.Last <= Index_Type'First then
881 E : Elements_Type renames Container.Elements.all;
883 for I in Index_Type'First .. Container.Last - 1 loop
884 if Is_Less (E (I + 1), E (I)) then
897 procedure Merge (Target, Source : in out Vector) is
898 I : Index_Type'Base := Target.Last;
902 if Target.Last < Index_Type'First then
903 Move (Target => Target, Source => Source);
907 if Target'Address = Source'Address then
911 if Source.Last < Index_Type'First then
915 if Source.Busy > 0 then
916 raise Program_Error with
917 "attempt to tamper with elements (vector is busy)";
920 Target.Set_Length (Length (Target) + Length (Source));
923 while Source.Last >= Index_Type'First loop
925 (Source.Last <= Index_Type'First
927 (Source.Elements (Source.Last),
928 Source.Elements (Source.Last - 1))));
930 if I < Index_Type'First then
932 Src : Elements_Type renames
933 Source.Elements (Index_Type'First .. Source.Last);
936 Target.Elements (Index_Type'First .. J) := Src;
937 Src := (others => null);
940 Source.Last := No_Index;
945 (I <= Index_Type'First
947 (Target.Elements (I),
948 Target.Elements (I - 1))));
951 Src : Element_Access renames Source.Elements (Source.Last);
952 Tgt : Element_Access renames Target.Elements (I);
955 if Is_Less (Src, Tgt) then
956 Target.Elements (J) := Tgt;
961 Target.Elements (J) := Src;
963 Source.Last := Source.Last - 1;
975 procedure Sort (Container : in out Vector)
978 new Generic_Array_Sort
979 (Index_Type => Index_Type,
980 Element_Type => Element_Access,
981 Array_Type => Elements_Type,
984 -- Start of processing for Sort
987 if Container.Last <= Index_Type'First then
991 if Container.Lock > 0 then
992 raise Program_Error with
993 "attempt to tamper with cursors (vector is locked)";
996 Sort (Container.Elements (Index_Type'First .. Container.Last));
1005 function Has_Element (Position : Cursor) return Boolean is
1007 if Position.Container = null then
1011 return Position.Index <= Position.Container.Last;
1019 (Container : in out Vector;
1020 Before : Extended_Index;
1021 New_Item : Element_Type;
1022 Count : Count_Type := 1)
1024 N : constant Int := Int (Count);
1026 First : constant Int := Int (Index_Type'First);
1027 New_Last_As_Int : Int'Base;
1028 New_Last : Index_Type;
1030 Max_Length : constant UInt := UInt (Count_Type'Last);
1032 Dst : Elements_Access;
1035 if Before < Index_Type'First then
1036 raise Constraint_Error with
1037 "Before index is out of range (too small)";
1040 if Before > Container.Last
1041 and then Before > Container.Last + 1
1043 raise Constraint_Error with
1044 "Before index is out of range (too large)";
1052 Old_Last_As_Int : constant Int := Int (Container.Last);
1055 if Old_Last_As_Int > Int'Last - N then -- see a-convec.adb ???
1056 raise Constraint_Error with "new length is out of range";
1059 New_Last_As_Int := Old_Last_As_Int + N;
1061 if New_Last_As_Int > Int (Index_Type'Last) then
1062 raise Constraint_Error with "new length is out of range";
1065 New_Length := UInt (New_Last_As_Int - First + 1);
1067 if New_Length > Max_Length then
1068 raise Constraint_Error with "new length is out of range";
1071 New_Last := Index_Type (New_Last_As_Int);
1074 if Container.Busy > 0 then
1075 raise Program_Error with
1076 "attempt to tamper with elements (vector is busy)";
1079 if Container.Elements = null then
1080 Container.Elements :=
1081 new Elements_Type (Index_Type'First .. New_Last);
1083 Container.Last := No_Index;
1085 for J in Container.Elements'Range loop
1086 Container.Elements (J) := new Element_Type'(New_Item
);
1087 Container
.Last
:= J
;
1093 if New_Last
<= Container
.Elements
'Last then
1095 E
: Elements_Type
renames Container
.Elements
.all;
1098 if Before
<= Container
.Last
then
1100 Index_As_Int
: constant Int
'Base :=
1101 Index_Type
'Pos (Before
) + N
;
1103 Index
: constant Index_Type
:= Index_Type
(Index_As_Int
);
1105 J
: Index_Type
'Base;
1108 E
(Index
.. New_Last
) := E
(Before
.. Container
.Last
);
1109 Container
.Last
:= New_Last
;
1112 while J
< Index
loop
1113 E
(J
) := new Element_Type
'(New_Item);
1119 E (J .. Index - 1) := (others => null);
1124 for J in Before .. New_Last loop
1125 E (J) := new Element_Type'(New_Item
);
1126 Container
.Last
:= J
;
1138 C
:= UInt
'Max (1, Container
.Elements
'Length);
1139 while C
< New_Length
loop
1140 if C
> UInt
'Last / 2 then
1148 if C
> Max_Length
then
1152 if Index_Type
'First <= 0
1153 and then Index_Type
'Last >= 0
1155 CC
:= UInt
(Index_Type
'Last) + UInt
(-Index_Type
'First) + 1;
1158 CC
:= UInt
(Int
(Index_Type
'Last) - First
+ 1);
1166 Dst_Last
: constant Index_Type
:=
1167 Index_Type
(First
+ UInt
'Pos (C
) - Int
'(1));
1170 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1174 if Before <= Container.Last then
1176 Index_As_Int : constant Int'Base :=
1177 Index_Type'Pos (Before) + N;
1179 Index : constant Index_Type := Index_Type (Index_As_Int);
1181 Src : Elements_Access := Container.Elements;
1184 Dst (Index_Type'First .. Before - 1) :=
1185 Src (Index_Type'First .. Before - 1);
1187 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1189 Container.Elements := Dst;
1190 Container.Last := New_Last;
1193 for J in Before .. Index - 1 loop
1194 Dst (J) := new Element_Type'(New_Item
);
1200 Src
: Elements_Access
:= Container
.Elements
;
1203 Dst
(Index_Type
'First .. Container
.Last
) :=
1204 Src
(Index_Type
'First .. Container
.Last
);
1206 Container
.Elements
:= Dst
;
1209 for J
in Before
.. New_Last
loop
1210 Dst
(J
) := new Element_Type
'(New_Item);
1211 Container.Last := J;
1218 (Container : in out Vector;
1219 Before : Extended_Index;
1222 N : constant Count_Type := Length (New_Item);
1225 if Before < Index_Type'First then
1226 raise Constraint_Error with
1227 "Before index is out of range (too small)";
1230 if Before > Container.Last
1231 and then Before > Container.Last + 1
1233 raise Constraint_Error with
1234 "Before index is out of range (too large)";
1241 Insert_Space (Container, Before, Count => N);
1244 Dst_Last_As_Int : constant Int'Base :=
1245 Int'Base (Before) + Int'Base (N) - 1;
1247 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1249 Dst : Elements_Type renames
1250 Container.Elements (Before .. Dst_Last);
1252 Dst_Index : Index_Type'Base := Before - 1;
1255 if Container'Address /= New_Item'Address then
1257 Src : Elements_Type renames
1258 New_Item.Elements (Index_Type'First .. New_Item.Last);
1261 for Src_Index in Src'Range loop
1262 Dst_Index := Dst_Index + 1;
1264 if Src (Src_Index) /= null then
1265 Dst (Dst_Index) := new Element_Type'(Src
(Src_Index
).all);
1274 subtype Src_Index_Subtype
is Index_Type
'Base range
1275 Index_Type
'First .. Before
- 1;
1277 Src
: Elements_Type
renames
1278 Container
.Elements
(Src_Index_Subtype
);
1281 for Src_Index
in Src
'Range loop
1282 Dst_Index
:= Dst_Index
+ 1;
1284 if Src
(Src_Index
) /= null then
1285 Dst
(Dst_Index
) := new Element_Type
'(Src (Src_Index).all);
1290 if Dst_Last = Container.Last then
1295 subtype Src_Index_Subtype is Index_Type'Base range
1296 Dst_Last + 1 .. Container.Last;
1298 Src : Elements_Type renames
1299 Container.Elements (Src_Index_Subtype);
1302 for Src_Index in Src'Range loop
1303 Dst_Index := Dst_Index + 1;
1305 if Src (Src_Index) /= null then
1306 Dst (Dst_Index) := new Element_Type'(Src
(Src_Index
).all);
1314 (Container
: in out Vector
;
1318 Index
: Index_Type
'Base;
1321 if Before
.Container
/= null
1322 and then Before
.Container
/= Container
'Unchecked_Access
1324 raise Program_Error
with "Before cursor denotes wrong container";
1327 if Is_Empty
(New_Item
) then
1331 if Before
.Container
= null
1332 or else Before
.Index
> Container
.Last
1334 if Container
.Last
= Index_Type
'Last then
1335 raise Constraint_Error
with
1336 "vector is already at its maximum length";
1339 Index
:= Container
.Last
+ 1;
1342 Index
:= Before
.Index
;
1345 Insert
(Container
, Index
, New_Item
);
1349 (Container
: in out Vector
;
1352 Position
: out Cursor
)
1354 Index
: Index_Type
'Base;
1357 if Before
.Container
/= null
1358 and then Before
.Container
/= Vector_Access
'(Container'Unchecked_Access)
1360 raise Program_Error with "Before cursor denotes wrong container";
1363 if Is_Empty (New_Item) then
1364 if Before.Container = null
1365 or else Before.Index > Container.Last
1367 Position := No_Element;
1369 Position := (Container'Unchecked_Access, Before.Index);
1375 if Before.Container = null
1376 or else Before.Index > Container.Last
1378 if Container.Last = Index_Type'Last then
1379 raise Constraint_Error with
1380 "vector is already at its maximum length";
1383 Index := Container.Last + 1;
1386 Index := Before.Index;
1389 Insert (Container, Index, New_Item);
1391 Position := Cursor'(Container
'Unchecked_Access, Index
);
1395 (Container
: in out Vector
;
1397 New_Item
: Element_Type
;
1398 Count
: Count_Type
:= 1)
1400 Index
: Index_Type
'Base;
1403 if Before
.Container
/= null
1404 and then Before
.Container
/= Container
'Unchecked_Access
1406 raise Program_Error
with "Before cursor denotes wrong container";
1413 if Before
.Container
= null
1414 or else Before
.Index
> Container
.Last
1416 if Container
.Last
= Index_Type
'Last then
1417 raise Constraint_Error
with
1418 "vector is already at its maximum length";
1421 Index
:= Container
.Last
+ 1;
1424 Index
:= Before
.Index
;
1427 Insert
(Container
, Index
, New_Item
, Count
);
1431 (Container
: in out Vector
;
1433 New_Item
: Element_Type
;
1434 Position
: out Cursor
;
1435 Count
: Count_Type
:= 1)
1437 Index
: Index_Type
'Base;
1440 if Before
.Container
/= null
1441 and then Before
.Container
/= Container
'Unchecked_Access
1443 raise Program_Error
with "Before cursor denotes wrong container";
1447 if Before
.Container
= null
1448 or else Before
.Index
> Container
.Last
1450 Position
:= No_Element
;
1452 Position
:= (Container
'Unchecked_Access, Before
.Index
);
1458 if Before
.Container
= null
1459 or else Before
.Index
> Container
.Last
1461 if Container
.Last
= Index_Type
'Last then
1462 raise Constraint_Error
with
1463 "vector is already at its maximum length";
1466 Index
:= Container
.Last
+ 1;
1469 Index
:= Before
.Index
;
1472 Insert
(Container
, Index
, New_Item
, Count
);
1474 Position
:= (Container
'Unchecked_Access, Index
);
1481 procedure Insert_Space
1482 (Container
: in out Vector
;
1483 Before
: Extended_Index
;
1484 Count
: Count_Type
:= 1)
1486 N
: constant Int
:= Int
(Count
);
1488 First
: constant Int
:= Int
(Index_Type
'First);
1489 New_Last_As_Int
: Int
'Base;
1490 New_Last
: Index_Type
;
1492 Max_Length
: constant UInt
:= UInt
(Count_Type
'Last);
1494 Dst
: Elements_Access
;
1497 if Before
< Index_Type
'First then
1498 raise Constraint_Error
with
1499 "Before index is out of range (too small)";
1502 if Before
> Container
.Last
1503 and then Before
> Container
.Last
+ 1
1505 raise Constraint_Error
with
1506 "Before index is out of range (too large)";
1514 Old_Last_As_Int
: constant Int
:= Int
(Container
.Last
);
1517 if Old_Last_As_Int
> Int
'Last - N
then -- see a-convec.adb ???
1518 raise Constraint_Error
with "new length is out of range";
1521 New_Last_As_Int
:= Old_Last_As_Int
+ N
;
1523 if New_Last_As_Int
> Int
(Index_Type
'Last) then
1524 raise Constraint_Error
with "new length is out of range";
1527 New_Length
:= UInt
(New_Last_As_Int
- First
+ 1);
1529 if New_Length
> Max_Length
then
1530 raise Constraint_Error
with "new length is out of range";
1533 New_Last
:= Index_Type
(New_Last_As_Int
);
1536 if Container
.Busy
> 0 then
1537 raise Program_Error
with
1538 "attempt to tamper with elements (vector is busy)";
1541 if Container
.Elements
= null then
1542 Container
.Elements
:=
1543 new Elements_Type
(Index_Type
'First .. New_Last
);
1545 Container
.Last
:= New_Last
;
1549 if New_Last
<= Container
.Elements
'Last then
1551 E
: Elements_Type
renames Container
.Elements
.all;
1554 if Before
<= Container
.Last
then
1556 Index_As_Int
: constant Int
'Base :=
1557 Index_Type
'Pos (Before
) + N
;
1559 Index
: constant Index_Type
:= Index_Type
(Index_As_Int
);
1562 E
(Index
.. New_Last
) := E
(Before
.. Container
.Last
);
1563 E
(Before
.. Index
- 1) := (others => null);
1568 Container
.Last
:= New_Last
;
1576 C
:= UInt
'Max (1, Container
.Elements
'Length);
1577 while C
< New_Length
loop
1578 if C
> UInt
'Last / 2 then
1586 if C
> Max_Length
then
1590 if Index_Type
'First <= 0
1591 and then Index_Type
'Last >= 0
1593 CC
:= UInt
(Index_Type
'Last) + UInt
(-Index_Type
'First) + 1;
1596 CC
:= UInt
(Int
(Index_Type
'Last) - First
+ 1);
1604 Dst_Last
: constant Index_Type
:=
1605 Index_Type
(First
+ UInt
'Pos (C
) - 1);
1608 Dst
:= new Elements_Type
(Index_Type
'First .. Dst_Last
);
1613 Src
: Elements_Access
:= Container
.Elements
;
1616 if Before
<= Container
.Last
then
1618 Index_As_Int
: constant Int
'Base :=
1619 Index_Type
'Pos (Before
) + N
;
1621 Index
: constant Index_Type
:= Index_Type
(Index_As_Int
);
1624 Dst
(Index_Type
'First .. Before
- 1) :=
1625 Src
(Index_Type
'First .. Before
- 1);
1627 Dst
(Index
.. New_Last
) := Src
(Before
.. Container
.Last
);
1631 Dst
(Index_Type
'First .. Container
.Last
) :=
1632 Src
(Index_Type
'First .. Container
.Last
);
1635 Container
.Elements
:= Dst
;
1636 Container
.Last
:= New_Last
;
1641 procedure Insert_Space
1642 (Container
: in out Vector
;
1644 Position
: out Cursor
;
1645 Count
: Count_Type
:= 1)
1647 Index
: Index_Type
'Base;
1650 if Before
.Container
/= null
1651 and then Before
.Container
/= Container
'Unchecked_Access
1653 raise Program_Error
with "Before cursor denotes wrong container";
1657 if Before
.Container
= null
1658 or else Before
.Index
> Container
.Last
1660 Position
:= No_Element
;
1662 Position
:= (Container
'Unchecked_Access, Before
.Index
);
1668 if Before
.Container
= null
1669 or else Before
.Index
> Container
.Last
1671 if Container
.Last
= Index_Type
'Last then
1672 raise Constraint_Error
with
1673 "vector is already at its maximum length";
1676 Index
:= Container
.Last
+ 1;
1679 Index
:= Before
.Index
;
1682 Insert_Space
(Container
, Index
, Count
);
1684 Position
:= Cursor
'(Container'Unchecked_Access, Index);
1691 function Is_Empty (Container : Vector) return Boolean is
1693 return Container.Last < Index_Type'First;
1701 (Container : Vector;
1702 Process : not null access procedure (Position : Cursor))
1704 V : Vector renames Container'Unrestricted_Access.all;
1705 B : Natural renames V.Busy;
1711 for Indx in Index_Type'First .. Container.Last loop
1712 Process (Cursor'(Container
'Unchecked_Access, Indx
));
1727 function Last
(Container
: Vector
) return Cursor
is
1729 if Is_Empty
(Container
) then
1733 return (Container
'Unchecked_Access, Container
.Last
);
1740 function Last_Element
(Container
: Vector
) return Element_Type
is
1742 return Element
(Container
, Container
.Last
);
1749 function Last_Index
(Container
: Vector
) return Extended_Index
is
1751 return Container
.Last
;
1758 function Length
(Container
: Vector
) return Count_Type
is
1759 L
: constant Int
:= Int
(Container
.Last
);
1760 F
: constant Int
:= Int
(Index_Type
'First);
1761 N
: constant Int
'Base := L
- F
+ 1;
1764 return Count_Type
(N
);
1772 (Target
: in out Vector
;
1773 Source
: in out Vector
)
1776 if Target
'Address = Source
'Address then
1780 if Source
.Busy
> 0 then
1781 raise Program_Error
with
1782 "attempt to tamper with elements (Source is busy)";
1785 Clear
(Target
); -- Checks busy-bit
1788 Target_Elements
: constant Elements_Access
:= Target
.Elements
;
1790 Target
.Elements
:= Source
.Elements
;
1791 Source
.Elements
:= Target_Elements
;
1794 Target
.Last
:= Source
.Last
;
1795 Source
.Last
:= No_Index
;
1802 function Next
(Position
: Cursor
) return Cursor
is
1804 if Position
.Container
= null then
1808 if Position
.Index
< Position
.Container
.Last
then
1809 return (Position
.Container
, Position
.Index
+ 1);
1819 procedure Next
(Position
: in out Cursor
) is
1821 if Position
.Container
= null then
1825 if Position
.Index
< Position
.Container
.Last
then
1826 Position
.Index
:= Position
.Index
+ 1;
1828 Position
:= No_Element
;
1836 procedure Prepend
(Container
: in out Vector
; New_Item
: Vector
) is
1838 Insert
(Container
, Index_Type
'First, New_Item
);
1842 (Container
: in out Vector
;
1843 New_Item
: Element_Type
;
1844 Count
: Count_Type
:= 1)
1857 procedure Previous
(Position
: in out Cursor
) is
1859 if Position
.Container
= null then
1863 if Position
.Index
> Index_Type
'First then
1864 Position
.Index
:= Position
.Index
- 1;
1866 Position
:= No_Element
;
1870 function Previous
(Position
: Cursor
) return Cursor
is
1872 if Position
.Container
= null then
1876 if Position
.Index
> Index_Type
'First then
1877 return (Position
.Container
, Position
.Index
- 1);
1887 procedure Query_Element
1888 (Container
: Vector
;
1890 Process
: not null access procedure (Element
: Element_Type
))
1892 V
: Vector
renames Container
'Unrestricted_Access.all;
1893 B
: Natural renames V
.Busy
;
1894 L
: Natural renames V
.Lock
;
1897 if Index
> Container
.Last
then
1898 raise Constraint_Error
with "Index is out of range";
1901 if V
.Elements
(Index
) = null then
1902 raise Constraint_Error
with "element is null";
1909 Process
(V
.Elements
(Index
).all);
1921 procedure Query_Element
1923 Process
: not null access procedure (Element
: Element_Type
))
1926 if Position
.Container
= null then
1927 raise Constraint_Error
with "Position cursor has no element";
1930 Query_Element
(Position
.Container
.all, Position
.Index
, Process
);
1938 (Stream
: not null access Root_Stream_Type
'Class;
1939 Container
: out Vector
)
1941 Length
: Count_Type
'Base;
1942 Last
: Index_Type
'Base := Index_Type
'Pred (Index_Type
'First);
1949 Count_Type
'Base'Read (Stream, Length);
1951 if Length > Capacity (Container) then
1952 Reserve_Capacity (Container, Capacity => Length);
1955 for J in Count_Type range 1 .. Length loop
1958 Boolean'Read (Stream, B);
1961 Container.Elements (Last) :=
1962 new Element_Type'(Element_Type
'Input (Stream
));
1965 Container
.Last
:= Last
;
1970 (Stream
: not null access Root_Stream_Type
'Class;
1971 Position
: out Cursor
)
1974 raise Program_Error
with "attempt to stream vector cursor";
1977 ---------------------
1978 -- Replace_Element --
1979 ---------------------
1981 procedure Replace_Element
1982 (Container
: in out Vector
;
1984 New_Item
: Element_Type
)
1987 if Index
> Container
.Last
then
1988 raise Constraint_Error
with "Index is out of range";
1991 if Container
.Lock
> 0 then
1992 raise Program_Error
with
1993 "attempt to tamper with cursors (vector is locked)";
1997 X
: Element_Access
:= Container
.Elements
(Index
);
1999 Container
.Elements
(Index
) := new Element_Type
'(New_Item);
2002 end Replace_Element;
2004 procedure Replace_Element
2005 (Container : in out Vector;
2007 New_Item : Element_Type)
2010 if Position.Container = null then
2011 raise Constraint_Error with "Position cursor has no element";
2014 if Position.Container /= Container'Unrestricted_Access then
2015 raise Program_Error with "Position cursor denotes wrong container";
2018 Replace_Element (Container, Position.Index, New_Item);
2019 end Replace_Element;
2021 ----------------------
2022 -- Reserve_Capacity --
2023 ----------------------
2025 procedure Reserve_Capacity
2026 (Container : in out Vector;
2027 Capacity : Count_Type)
2029 N : constant Count_Type := Length (Container);
2032 if Capacity = 0 then
2035 X : Elements_Access := Container.Elements;
2037 Container.Elements := null;
2041 elsif N < Container.Elements'Length then
2042 if Container.Busy > 0 then
2043 raise Program_Error with
2044 "attempt to tamper with elements (vector is busy)";
2048 subtype Array_Index_Subtype is Index_Type'Base range
2049 Index_Type'First .. Container.Last;
2051 Src : Elements_Type renames
2052 Container.Elements (Array_Index_Subtype);
2054 subtype Array_Subtype is
2055 Elements_Type (Array_Index_Subtype);
2057 X : Elements_Access := Container.Elements;
2060 Container.Elements := new Array_Subtype'(Src
);
2068 if Container
.Elements
= null then
2070 Last_As_Int
: constant Int
'Base :=
2071 Int
(Index_Type
'First) + Int
(Capacity
) - 1;
2074 if Last_As_Int
> Index_Type
'Pos (Index_Type
'Last) then
2075 raise Constraint_Error
with "new length is out of range";
2079 Last
: constant Index_Type
:= Index_Type
(Last_As_Int
);
2081 subtype Array_Subtype
is
2082 Elements_Type
(Index_Type
'First .. Last
);
2085 Container
.Elements
:= new Array_Subtype
;
2092 if Capacity
<= N
then
2093 if N
< Container
.Elements
'Length then
2094 if Container
.Busy
> 0 then
2095 raise Program_Error
with
2096 "attempt to tamper with elements (vector is busy)";
2100 subtype Array_Index_Subtype
is Index_Type
'Base range
2101 Index_Type
'First .. Container
.Last
;
2103 Src
: Elements_Type
renames
2104 Container
.Elements
(Array_Index_Subtype
);
2106 subtype Array_Subtype
is
2107 Elements_Type
(Array_Index_Subtype
);
2109 X
: Elements_Access
:= Container
.Elements
;
2112 Container
.Elements
:= new Array_Subtype
'(Src);
2120 if Capacity = Container.Elements'Length then
2124 if Container.Busy > 0 then
2125 raise Program_Error with
2126 "attempt to tamper with elements (vector is busy)";
2130 Last_As_Int : constant Int'Base :=
2131 Int (Index_Type'First) + Int (Capacity) - 1;
2134 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2135 raise Constraint_Error with "new length is out of range";
2139 Last : constant Index_Type := Index_Type (Last_As_Int);
2141 subtype Array_Subtype is
2142 Elements_Type (Index_Type'First .. Last);
2144 X : Elements_Access := Container.Elements;
2147 Container.Elements := new Array_Subtype;
2150 Src : Elements_Type renames
2151 X (Index_Type'First .. Container.Last);
2153 Tgt : Elements_Type renames
2154 Container.Elements (Index_Type'First .. Container.Last);
2163 end Reserve_Capacity;
2165 ----------------------
2166 -- Reverse_Elements --
2167 ----------------------
2169 procedure Reverse_Elements (Container : in out Vector) is
2171 if Container.Length <= 1 then
2175 if Container.Lock > 0 then
2176 raise Program_Error with
2177 "attempt to tamper with cursors (vector is locked)";
2183 E : Elements_Type renames Container.Elements.all;
2186 I := Index_Type'First;
2187 J := Container.Last;
2190 EI : constant Element_Access := E (I);
2201 end Reverse_Elements;
2207 function Reverse_Find
2208 (Container : Vector;
2209 Item : Element_Type;
2210 Position : Cursor := No_Element) return Cursor
2212 Last : Index_Type'Base;
2215 if Position.Container /= null
2216 and then Position.Container /= Container'Unchecked_Access
2218 raise Program_Error with "Position cursor denotes wrong container";
2221 if Position.Container = null
2222 or else Position.Index > Container.Last
2224 Last := Container.Last;
2226 Last := Position.Index;
2229 for Indx in reverse Index_Type'First .. Last loop
2230 if Container.Elements (Indx) /= null
2231 and then Container.Elements (Indx).all = Item
2233 return (Container'Unchecked_Access, Indx);
2240 ------------------------
2241 -- Reverse_Find_Index --
2242 ------------------------
2244 function Reverse_Find_Index
2245 (Container : Vector;
2246 Item : Element_Type;
2247 Index : Index_Type := Index_Type'Last) return Extended_Index
2249 Last : Index_Type'Base;
2252 if Index > Container.Last then
2253 Last := Container.Last;
2258 for Indx in reverse Index_Type'First .. Last loop
2259 if Container.Elements (Indx) /= null
2260 and then Container.Elements (Indx).all = Item
2267 end Reverse_Find_Index;
2269 ---------------------
2270 -- Reverse_Iterate --
2271 ---------------------
2273 procedure Reverse_Iterate
2274 (Container : Vector;
2275 Process : not null access procedure (Position : Cursor))
2277 V : Vector renames Container'Unrestricted_Access.all;
2278 B : Natural renames V.Busy;
2284 for Indx in reverse Index_Type'First .. Container.Last loop
2285 Process (Cursor'(Container
'Unchecked_Access, Indx
));
2294 end Reverse_Iterate
;
2300 procedure Set_Length
2301 (Container
: in out Vector
;
2302 Length
: Count_Type
)
2304 N
: constant Count_Type
:= Indefinite_Vectors
.Length
(Container
);
2311 if Container
.Busy
> 0 then
2312 raise Program_Error
with
2313 "attempt to tamper with elements (vector is busy)";
2317 for Index
in 1 .. N
- Length
loop
2319 J
: constant Index_Type
:= Container
.Last
;
2320 X
: Element_Access
:= Container
.Elements
(J
);
2323 Container
.Elements
(J
) := null;
2324 Container
.Last
:= J
- 1;
2332 if Length
> Capacity
(Container
) then
2333 Reserve_Capacity
(Container
, Capacity
=> Length
);
2337 Last_As_Int
: constant Int
'Base :=
2338 Int
(Index_Type
'First) + Int
(Length
) - 1;
2341 Container
.Last
:= Index_Type
(Last_As_Int
);
2350 (Container
: in out Vector
;
2354 if I
> Container
.Last
then
2355 raise Constraint_Error
with "I index is out of range";
2358 if J
> Container
.Last
then
2359 raise Constraint_Error
with "J index is out of range";
2366 if Container
.Lock
> 0 then
2367 raise Program_Error
with
2368 "attempt to tamper with cursors (vector is locked)";
2372 EI
: Element_Access
renames Container
.Elements
(I
);
2373 EJ
: Element_Access
renames Container
.Elements
(J
);
2375 EI_Copy
: constant Element_Access
:= EI
;
2384 (Container
: in out Vector
;
2388 if I
.Container
= null then
2389 raise Constraint_Error
with "I cursor has no element";
2392 if J
.Container
= null then
2393 raise Constraint_Error
with "J cursor has no element";
2396 if I
.Container
/= Container
'Unrestricted_Access then
2397 raise Program_Error
with "I cursor denotes wrong container";
2400 if J
.Container
/= Container
'Unrestricted_Access then
2401 raise Program_Error
with "J cursor denotes wrong container";
2404 Swap
(Container
, I
.Index
, J
.Index
);
2412 (Container
: Vector
;
2413 Index
: Extended_Index
) return Cursor
2416 if Index
not in Index_Type
'First .. Container
.Last
then
2420 return Cursor
'(Container'Unchecked_Access, Index);
2427 function To_Index (Position : Cursor) return Extended_Index is
2429 if Position.Container = null then
2433 if Position.Index <= Position.Container.Last then
2434 return Position.Index;
2444 function To_Vector (Length : Count_Type) return Vector is
2447 return Empty_Vector;
2451 First : constant Int := Int (Index_Type'First);
2452 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2454 Elements : Elements_Access;
2457 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2458 raise Constraint_Error with "Length is out of range";
2461 Last := Index_Type (Last_As_Int);
2462 Elements := new Elements_Type (Index_Type'First .. Last);
2464 return (Controlled with Elements, Last, 0, 0);
2469 (New_Item : Element_Type;
2470 Length : Count_Type) return Vector
2474 return Empty_Vector;
2478 First : constant Int := Int (Index_Type'First);
2479 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2480 Last : Index_Type'Base;
2481 Elements : Elements_Access;
2484 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2485 raise Constraint_Error with "Length is out of range";
2488 Last := Index_Type (Last_As_Int);
2489 Elements := new Elements_Type (Index_Type'First .. Last);
2491 Last := Index_Type'First;
2495 Elements (Last) := new Element_Type'(New_Item
);
2496 exit when Last
= Elements
'Last;
2501 for J
in Index_Type
'First .. Last
- 1 loop
2502 Free
(Elements
(J
));
2509 return (Controlled
with Elements
, Last
, 0, 0);
2513 --------------------
2514 -- Update_Element --
2515 --------------------
2517 procedure Update_Element
2518 (Container
: in out Vector
;
2520 Process
: not null access procedure (Element
: in out Element_Type
))
2522 B
: Natural renames Container
.Busy
;
2523 L
: Natural renames Container
.Lock
;
2526 if Index
> Container
.Last
then
2527 raise Constraint_Error
with "Index is out of range";
2530 if Container
.Elements
(Index
) = null then
2531 raise Constraint_Error
with "element is null";
2538 Process
(Container
.Elements
(Index
).all);
2550 procedure Update_Element
2551 (Container
: in out Vector
;
2553 Process
: not null access procedure (Element
: in out Element_Type
))
2556 if Position
.Container
= null then
2557 raise Constraint_Error
with "Position cursor has no element";
2560 if Position
.Container
/= Container
'Unrestricted_Access then
2561 raise Program_Error
with "Position cursor denotes wrong container";
2564 Update_Element
(Container
, Position
.Index
, Process
);
2572 (Stream
: not null access Root_Stream_Type
'Class;
2575 N
: constant Count_Type
:= Length
(Container
);
2578 Count_Type
'Base'Write (Stream, N);
2585 E : Elements_Type renames Container.Elements.all;
2588 for Indx in Index_Type'First .. Container.Last loop
2590 -- There's another way to do this. Instead a separate
2591 -- Boolean for each element, you could write a Boolean
2592 -- followed by a count of how many nulls or non-nulls
2593 -- follow in the array. ???
2595 if E (Indx) = null then
2596 Boolean'Write (Stream, False);
2598 Boolean'Write (Stream, True);
2599 Element_Type'Output (Stream, E (Indx).all);
2606 (Stream : not null access Root_Stream_Type'Class;
2610 raise Program_Error with "attempt to stream vector cursor";
2613 end Ada.Containers.Indefinite_Vectors;