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-2005 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;
45 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
48 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
54 function "&" (Left, Right : Vector) return Vector is
55 LN : constant Count_Type := Length (Left);
56 RN : constant Count_Type := Length (Right);
65 RE : Elements_Type renames
66 Right.Elements (Index_Type'First .. Right.Last);
68 Elements : Elements_Access :=
69 new Elements_Type (RE'Range);
72 for I in Elements'Range loop
74 if RE (I) /= null then
75 Elements (I) := new Element_Type'(RE (I).all);
79 for J in Index_Type'First .. I - 1 loop
88 return (Controlled with Elements, Right.Last, 0, 0);
95 LE : Elements_Type renames
96 Left.Elements (Index_Type'First .. Left.Last);
98 Elements : Elements_Access :=
99 new Elements_Type (LE'Range);
102 for I in Elements'Range loop
104 if LE (I) /= null then
105 Elements (I) := new Element_Type'(LE (I).all);
109 for J in Index_Type'First .. I - 1 loop
118 return (Controlled with Elements, Left.Last, 0, 0);
123 Last_As_Int : constant Int'Base := -- TODO: handle overflow
124 Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
127 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
128 raise Constraint_Error;
132 Last : constant Index_Type := Index_Type (Last_As_Int);
134 LE : Elements_Type renames
135 Left.Elements (Index_Type'First .. Left.Last);
137 RE : Elements_Type renames
138 Right.Elements (Index_Type'First .. Right.Last);
140 Elements : Elements_Access :=
141 new Elements_Type (Index_Type'First .. Last);
143 I : Index_Type'Base := No_Index;
146 for LI in LE'Range loop
150 if LE (LI) /= null then
151 Elements (I) := new Element_Type'(LE (LI).all);
155 for J in Index_Type'First .. I - 1 loop
164 for RI in RE'Range loop
168 if RE (RI) /= null then
169 Elements (I) := new Element_Type'(RE (RI).all);
173 for J in Index_Type'First .. I - 1 loop
182 return (Controlled with Elements, Last, 0, 0);
187 function "&" (Left : Vector; Right : Element_Type) return Vector is
188 LN : constant Count_Type := Length (Left);
193 subtype Elements_Subtype is
194 Elements_Type (Index_Type'First .. Index_Type'First);
196 Elements : Elements_Access := new Elements_Subtype;
200 Elements (Elements'First) := new Element_Type'(Right);
207 return (Controlled with Elements, Index_Type'First, 0, 0);
212 Last_As_Int : constant Int'Base :=
213 Int (Index_Type'First) + Int (LN);
216 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
217 raise Constraint_Error;
221 Last : constant Index_Type := Index_Type (Last_As_Int);
223 LE : Elements_Type renames
224 Left.Elements (Index_Type'First .. Left.Last);
226 Elements : Elements_Access :=
227 new Elements_Type (Index_Type'First .. Last);
230 for I in LE'Range loop
232 if LE (I) /= null then
233 Elements (I) := new Element_Type'(LE (I).all);
237 for J in Index_Type'First .. I - 1 loop
247 Elements (Elements'Last) := new Element_Type'(Right);
250 for J in Index_Type'First .. Elements'Last - 1 loop
258 return (Controlled with Elements, Last, 0, 0);
263 function "&" (Left : Element_Type; Right : Vector) return Vector is
264 RN : constant Count_Type := Length (Right);
269 subtype Elements_Subtype is
270 Elements_Type (Index_Type'First .. Index_Type'First);
272 Elements : Elements_Access := new Elements_Subtype;
276 Elements (Elements'First) := new Element_Type'(Left);
283 return (Controlled with Elements, Index_Type'First, 0, 0);
288 Last_As_Int : constant Int'Base :=
289 Int (Index_Type'First) + Int (RN);
292 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
293 raise Constraint_Error;
297 Last : constant Index_Type := Index_Type (Last_As_Int);
299 RE : Elements_Type renames
300 Right.Elements (Index_Type'First .. Right.Last);
302 Elements : Elements_Access :=
303 new Elements_Type (Index_Type'First .. Last);
305 I : Index_Type'Base := Index_Type'First;
309 Elements (I) := new Element_Type'(Left);
316 for RI in RE'Range loop
320 if RE (RI) /= null then
321 Elements (I) := new Element_Type'(RE (RI).all);
325 for J in Index_Type'First .. I - 1 loop
334 return (Controlled with Elements, Last, 0, 0);
339 function "&" (Left, Right : Element_Type) return Vector is
341 if Index_Type'First >= Index_Type'Last then
342 raise Constraint_Error;
346 Last : constant Index_Type := Index_Type'First + 1;
348 subtype ET is Elements_Type (Index_Type'First .. Last);
350 Elements : Elements_Access := new ET;
353 Elements (Elements'First) := new Element_Type'(Left);
361 Elements (Elements'Last) := new Element_Type'(Right);
364 Free (Elements (Elements'First));
369 return (Controlled with Elements, Elements'Last, 0, 0);
377 function "=" (Left, Right : Vector) return Boolean is
379 if Left'Address = Right'Address then
383 if Left.Last /= Right.Last then
387 for J in Index_Type'First .. Left.Last loop
388 if Left.Elements (J) = null then
389 if Right.Elements (J) /= null then
393 elsif Right.Elements (J) = null then
396 elsif Left.Elements (J).all /= Right.Elements (J).all then
408 procedure Adjust (Container : in out Vector) is
410 if Container.Last = No_Index then
411 Container.Elements := null;
416 E : Elements_Type renames Container.Elements.all;
417 L : constant Index_Type := Container.Last;
420 Container.Elements := null;
421 Container.Last := No_Index;
425 Container.Elements := new Elements_Type (Index_Type'First .. L);
427 for I in Container.Elements'Range loop
428 if E (I) /= null then
429 Container.Elements (I) := new Element_Type'(E (I).all);
441 procedure Append (Container : in out Vector; New_Item : Vector) is
443 if Is_Empty (New_Item) then
447 if Container.Last = Index_Type'Last then
448 raise Constraint_Error;
458 (Container : in out Vector;
459 New_Item : Element_Type;
460 Count : Count_Type := 1)
467 if Container.Last = Index_Type'Last then
468 raise Constraint_Error;
483 (Target : in out Vector;
486 N : constant Count_Type := Length (Source);
489 if Target'Address = Source'Address then
499 if N > Capacity (Target) then
500 Reserve_Capacity (Target, Capacity => N);
503 for J in Index_Type'First .. Source.Last loop
505 EA : constant Element_Access := Source.Elements (J);
508 Target.Elements (J) := new Element_Type'(EA.all);
520 function Capacity (Container : Vector) return Count_Type is
522 if Container.Elements = null then
526 return Container.Elements'Length;
533 procedure Clear (Container : in out Vector) is
535 if Container.Busy > 0 then
539 while Container.Last >= Index_Type'First loop
541 X : Element_Access := Container.Elements (Container.Last);
543 Container.Elements (Container.Last) := null;
544 Container.Last := Container.Last - 1;
556 Item : Element_Type) return Boolean is
558 return Find_Index (Container, Item) /= No_Index;
566 (Container : in out Vector;
567 Index : Extended_Index;
568 Count : Count_Type := 1)
571 if Index < Index_Type'First then
572 raise Constraint_Error;
575 if Index > Container.Last then
576 if Index > Container.Last + 1 then
577 raise Constraint_Error;
587 if Container.Busy > 0 then
592 Index_As_Int : constant Int := Int (Index);
593 Old_Last_As_Int : constant Int := Int (Container.Last);
595 -- TODO: somewhat vestigial...fix ???
596 Count1 : constant Int'Base := Int (Count);
597 Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
598 N : constant Int'Base := Int'Min (Count1, Count2);
600 J_As_Int : constant Int'Base := Index_As_Int + N;
601 E : Elements_Type renames Container.Elements.all;
604 if J_As_Int > Old_Last_As_Int then
605 while Container.Last >= Index loop
607 K : constant Index_Type := Container.Last;
608 X : Element_Access := E (K);
612 Container.Last := K - 1;
619 J : constant Index_Type := Index_Type (J_As_Int);
621 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
622 New_Last : constant Index_Type :=
623 Index_Type (New_Last_As_Int);
626 for K in Index .. J - 1 loop
628 X : Element_Access := E (K);
635 E (Index .. New_Last) := E (J .. Container.Last);
636 Container.Last := New_Last;
643 (Container : in out Vector;
644 Position : in out Cursor;
645 Count : Count_Type := 1)
648 if Position.Container = null then
649 raise Constraint_Error;
652 if Position.Container /=
653 Vector_Access'(Container'Unchecked_Access)
654 or else Position.Index > Container.Last
659 Delete (Container, Position.Index, Count);
661 if Position.Index <= Container.Last then
662 Position := (Container'Unchecked_Access, Position.Index);
664 Position := No_Element;
672 procedure Delete_First
673 (Container : in out Vector;
674 Count : Count_Type := 1)
681 if Count >= Length (Container) then
686 Delete (Container, Index_Type'First, Count);
693 procedure Delete_Last
694 (Container : in out Vector;
695 Count : Count_Type := 1)
697 N : constant Count_Type := Length (Container);
706 if Container.Busy > 0 then
711 E : Elements_Type renames Container.Elements.all;
714 for Indx in 1 .. Count_Type'Min (Count, N) loop
716 J : constant Index_Type := Container.Last;
717 X : Element_Access := E (J);
721 Container.Last := J - 1;
734 Index : Index_Type) return Element_Type
737 if Index > Container.Last then
738 raise Constraint_Error;
741 return Container.Elements (Index).all;
744 function Element (Position : Cursor) return Element_Type is
746 if Position.Container = null then
747 raise Constraint_Error;
750 return Element (Position.Container.all, Position.Index);
757 procedure Finalize (Container : in out Vector) is
762 X : Elements_Access := Container.Elements;
764 Container.Elements := null;
776 Position : Cursor := No_Element) return Cursor is
779 if Position.Container /= null
780 and then (Position.Container /=
781 Vector_Access'(Container'Unchecked_Access)
782 or else Position.Index > Container.Last)
787 for J in Position.Index .. Container.Last loop
788 if Container.Elements (J) /= null
789 and then Container.Elements (J).all = Item
791 return (Container'Unchecked_Access, J);
805 Index : Index_Type := Index_Type'First) return Extended_Index is
807 for Indx in Index .. Container.Last loop
808 if Container.Elements (Indx) /= null
809 and then Container.Elements (Indx).all = Item
822 function First (Container : Vector) return Cursor is
824 if Is_Empty (Container) then
828 return (Container'Unchecked_Access, Index_Type'First);
835 function First_Element (Container : Vector) return Element_Type is
837 return Element (Container, Index_Type'First);
844 function First_Index (Container : Vector) return Index_Type is
845 pragma Unreferenced (Container);
847 return Index_Type'First;
850 ---------------------
851 -- Generic_Sorting --
852 ---------------------
854 package body Generic_Sorting is
856 -----------------------
857 -- Local Subprograms --
858 -----------------------
860 function Is_Less (L, R : Element_Access) return Boolean;
861 pragma Inline (Is_Less);
867 function Is_Less (L, R : Element_Access) return Boolean is
874 return L.all < R.all;
882 function Is_Sorted (Container : Vector) return Boolean is
884 if Container.Last <= Index_Type'First then
889 E : Elements_Type renames Container.Elements.all;
891 for I in Index_Type'First .. Container.Last - 1 loop
892 if Is_Less (E (I + 1), E (I)) then
905 procedure Merge (Target, Source : in out Vector) is
906 I : Index_Type'Base := Target.Last;
910 if Target.Last < Index_Type'First then
911 Move (Target => Target, Source => Source);
915 if Target'Address = Source'Address then
919 if Source.Last < Index_Type'First then
923 if Source.Busy > 0 then
927 Target.Set_Length (Length (Target) + Length (Source));
930 while Source.Last >= Index_Type'First loop
931 if I < Index_Type'First then
933 Src : Elements_Type renames
934 Source.Elements (Index_Type'First .. Source.Last);
937 Target.Elements (Index_Type'First .. J) := Src;
938 Src := (others => null);
941 Source.Last := No_Index;
946 Src : Element_Access renames Source.Elements (Source.Last);
947 Tgt : Element_Access renames Target.Elements (I);
950 if Is_Less (Src, Tgt) then
951 Target.Elements (J) := Tgt;
956 Target.Elements (J) := Src;
958 Source.Last := Source.Last - 1;
970 procedure Sort (Container : in out Vector)
973 new Generic_Array_Sort
974 (Index_Type => Index_Type,
975 Element_Type => Element_Access,
976 Array_Type => Elements_Type,
979 -- Start of processing for Sort
982 if Container.Last <= Index_Type'First then
986 if Container.Lock > 0 then
990 Sort (Container.Elements (Index_Type'First .. Container.Last));
999 function Has_Element (Position : Cursor) return Boolean is
1001 if Position.Container = null then
1005 return Position.Index <= Position.Container.Last;
1013 (Container : in out Vector;
1014 Before : Extended_Index;
1015 New_Item : Element_Type;
1016 Count : Count_Type := 1)
1018 N : constant Int := Int (Count);
1020 New_Last_As_Int : Int'Base;
1021 New_Last : Index_Type;
1023 Dst : Elements_Access;
1026 if Before < Index_Type'First then
1027 raise Constraint_Error;
1030 if Before > Container.Last
1031 and then Before > Container.Last + 1
1033 raise Constraint_Error;
1041 Old_Last_As_Int : constant Int := Int (Container.Last);
1044 New_Last_As_Int := Old_Last_As_Int + N;
1046 if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1047 raise Constraint_Error;
1050 New_Last := Index_Type (New_Last_As_Int);
1053 if Container.Busy > 0 then
1054 raise Program_Error;
1057 if Container.Elements = null then
1058 Container.Elements :=
1059 new Elements_Type (Index_Type'First .. New_Last);
1061 Container.Last := No_Index;
1063 for J in Container.Elements'Range loop
1064 Container.Elements (J) := new Element_Type'(New_Item);
1065 Container.Last := J;
1071 if New_Last <= Container.Elements'Last then
1073 E : Elements_Type renames Container.Elements.all;
1075 if Before <= Container.Last then
1077 Index_As_Int : constant Int'Base :=
1078 Index_Type'Pos (Before) + N;
1080 Index : constant Index_Type := Index_Type (Index_As_Int);
1082 J : Index_Type'Base := Before;
1085 E (Index .. New_Last) := E (Before .. Container.Last);
1086 Container.Last := New_Last;
1088 while J < Index loop
1089 E (J) := new Element_Type'(New_Item);
1094 E (J .. Index - 1) := (others => null);
1099 for J in Before .. New_Last loop
1100 E (J) := new Element_Type'(New_Item);
1101 Container.Last := J;
1110 First : constant Int := Int (Index_Type'First);
1111 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
1112 Size : Int'Base := Int'Max (1, Container.Elements'Length);
1115 while Size < New_Size loop
1116 if Size > Int'Last / 2 then
1124 -- TODO: The following calculations aren't quite right, since
1125 -- there will be overflow if Index_Type'Range is very large
1126 -- (e.g. this package is instantiated with a 64-bit integer).
1130 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
1132 if Size > Max_Size then
1138 Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
1140 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1144 if Before <= Container.Last then
1146 Index_As_Int : constant Int'Base :=
1147 Index_Type'Pos (Before) + N;
1149 Index : constant Index_Type := Index_Type (Index_As_Int);
1151 Src : Elements_Access := Container.Elements;
1154 Dst (Index_Type'First .. Before - 1) :=
1155 Src (Index_Type'First .. Before - 1);
1157 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1159 Container.Elements := Dst;
1160 Container.Last := New_Last;
1163 for J in Before .. Index - 1 loop
1164 Dst (J) := new Element_Type'(New_Item);
1170 Src : Elements_Access := Container.Elements;
1173 Dst (Index_Type'First .. Container.Last) :=
1174 Src (Index_Type'First .. Container.Last);
1176 Container.Elements := Dst;
1179 for J in Before .. New_Last loop
1180 Dst (J) := new Element_Type'(New_Item);
1181 Container.Last := J;
1188 (Container : in out Vector;
1189 Before : Extended_Index;
1192 N : constant Count_Type := Length (New_Item);
1195 if Before < Index_Type'First then
1196 raise Constraint_Error;
1199 if Before > Container.Last
1200 and then Before > Container.Last + 1
1202 raise Constraint_Error;
1209 Insert_Space (Container, Before, Count => N);
1212 Dst_Last_As_Int : constant Int'Base :=
1213 Int'Base (Before) + Int'Base (N) - 1;
1215 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1217 Dst : Elements_Type renames
1218 Container.Elements (Before .. Dst_Last);
1220 Dst_Index : Index_Type'Base := Before - 1;
1223 if Container'Address /= New_Item'Address then
1225 Src : Elements_Type renames
1226 New_Item.Elements (Index_Type'First .. New_Item.Last);
1229 for Src_Index in Src'Range loop
1230 Dst_Index := Dst_Index + 1;
1232 if Src (Src_Index) /= null then
1233 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1242 subtype Src_Index_Subtype is Index_Type'Base range
1243 Index_Type'First .. Before - 1;
1245 Src : Elements_Type renames
1246 Container.Elements (Src_Index_Subtype);
1249 for Src_Index in Src'Range loop
1250 Dst_Index := Dst_Index + 1;
1252 if Src (Src_Index) /= null then
1253 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1258 if Dst_Last = Container.Last then
1263 subtype Src_Index_Subtype is Index_Type'Base range
1264 Dst_Last + 1 .. Container.Last;
1266 Src : Elements_Type renames
1267 Container.Elements (Src_Index_Subtype);
1270 for Src_Index in Src'Range loop
1271 Dst_Index := Dst_Index + 1;
1273 if Src (Src_Index) /= null then
1274 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1282 (Container : in out Vector;
1286 Index : Index_Type'Base;
1289 if Before.Container /= null
1290 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1292 raise Program_Error;
1295 if Is_Empty (New_Item) then
1299 if Before.Container = null
1300 or else Before.Index > Container.Last
1302 if Container.Last = Index_Type'Last then
1303 raise Constraint_Error;
1306 Index := Container.Last + 1;
1309 Index := Before.Index;
1312 Insert (Container, Index, New_Item);
1316 (Container : in out Vector;
1319 Position : out Cursor)
1321 Index : Index_Type'Base;
1324 if Before.Container /= null
1325 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1327 raise Program_Error;
1330 if Is_Empty (New_Item) then
1331 if Before.Container = null
1332 or else Before.Index > Container.Last
1334 Position := No_Element;
1336 Position := (Container'Unchecked_Access, Before.Index);
1342 if Before.Container = null
1343 or else Before.Index > Container.Last
1345 if Container.Last = Index_Type'Last then
1346 raise Constraint_Error;
1349 Index := Container.Last + 1;
1352 Index := Before.Index;
1355 Insert (Container, Index, New_Item);
1357 Position := Cursor'(Container'Unchecked_Access, Index);
1361 (Container : in out Vector;
1363 New_Item : Element_Type;
1364 Count : Count_Type := 1)
1366 Index : Index_Type'Base;
1369 if Before.Container /= null
1370 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1372 raise Program_Error;
1379 if Before.Container = null
1380 or else Before.Index > Container.Last
1382 if Container.Last = Index_Type'Last then
1383 raise Constraint_Error;
1386 Index := Container.Last + 1;
1389 Index := Before.Index;
1392 Insert (Container, Index, New_Item, Count);
1396 (Container : in out Vector;
1398 New_Item : Element_Type;
1399 Position : out Cursor;
1400 Count : Count_Type := 1)
1402 Index : Index_Type'Base;
1405 if Before.Container /= null
1406 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1408 raise Program_Error;
1412 if Before.Container = null
1413 or else Before.Index > Container.Last
1415 Position := No_Element;
1417 Position := (Container'Unchecked_Access, Before.Index);
1423 if Before.Container = null
1424 or else Before.Index > Container.Last
1426 if Container.Last = Index_Type'Last then
1427 raise Constraint_Error;
1430 Index := Container.Last + 1;
1433 Index := Before.Index;
1436 Insert (Container, Index, New_Item, Count);
1438 Position := (Container'Unchecked_Access, Index);
1445 procedure Insert_Space
1446 (Container : in out Vector;
1447 Before : Extended_Index;
1448 Count : Count_Type := 1)
1450 N : constant Int := Int (Count);
1452 New_Last_As_Int : Int'Base;
1453 New_Last : Index_Type;
1455 Dst : Elements_Access;
1458 if Before < Index_Type'First then
1459 raise Constraint_Error;
1462 if Before > Container.Last
1463 and then Before > Container.Last + 1
1465 raise Constraint_Error;
1473 Old_Last_As_Int : constant Int := Int (Container.Last);
1476 New_Last_As_Int := Old_Last_As_Int + N;
1478 if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1479 raise Constraint_Error;
1482 New_Last := Index_Type (New_Last_As_Int);
1485 if Container.Busy > 0 then
1486 raise Program_Error;
1489 if Container.Elements = null then
1490 Container.Elements :=
1491 new Elements_Type (Index_Type'First .. New_Last);
1493 Container.Last := New_Last;
1497 if New_Last <= Container.Elements'Last then
1499 E : Elements_Type renames Container.Elements.all;
1502 if Before <= Container.Last then
1504 Index_As_Int : constant Int'Base :=
1505 Index_Type'Pos (Before) + N;
1507 Index : constant Index_Type := Index_Type (Index_As_Int);
1510 E (Index .. New_Last) := E (Before .. Container.Last);
1511 E (Before .. Index - 1) := (others => null);
1516 Container.Last := New_Last;
1521 First : constant Int := Int (Index_Type'First);
1522 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
1523 Size : Int'Base := Int'Max (1, Container.Elements'Length);
1526 while Size < New_Size loop
1527 if Size > Int'Last / 2 then
1535 -- TODO: The following calculations aren't quite right, since
1536 -- there will be overflow if Index_Type'Range is very large
1537 -- (e.g. this package is instantiated with a 64-bit integer).
1541 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
1543 if Size > Max_Size then
1549 Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
1551 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1556 Src : Elements_Access := Container.Elements;
1559 if Before <= Container.Last then
1561 Index_As_Int : constant Int'Base :=
1562 Index_Type'Pos (Before) + N;
1564 Index : constant Index_Type := Index_Type (Index_As_Int);
1567 Dst (Index_Type'First .. Before - 1) :=
1568 Src (Index_Type'First .. Before - 1);
1570 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1574 Dst (Index_Type'First .. Container.Last) :=
1575 Src (Index_Type'First .. Container.Last);
1578 Container.Elements := Dst;
1579 Container.Last := New_Last;
1584 procedure Insert_Space
1585 (Container : in out Vector;
1587 Position : out Cursor;
1588 Count : Count_Type := 1)
1590 Index : Index_Type'Base;
1593 if Before.Container /= null
1594 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1596 raise Program_Error;
1600 if Before.Container = null
1601 or else Before.Index > Container.Last
1603 Position := No_Element;
1605 Position := (Container'Unchecked_Access, Before.Index);
1611 if Before.Container = null
1612 or else Before.Index > Container.Last
1614 if Container.Last = Index_Type'Last then
1615 raise Constraint_Error;
1618 Index := Container.Last + 1;
1621 Index := Before.Index;
1624 Insert_Space (Container, Index, Count);
1626 Position := Cursor'(Container'Unchecked_Access, Index);
1633 function Is_Empty (Container : Vector) return Boolean is
1635 return Container.Last < Index_Type'First;
1643 (Container : Vector;
1644 Process : not null access procedure (Position : in Cursor))
1646 V : Vector renames Container'Unrestricted_Access.all;
1647 B : Natural renames V.Busy;
1653 for Indx in Index_Type'First .. Container.Last loop
1654 Process (Cursor'(Container'Unchecked_Access, Indx));
1669 function Last (Container : Vector) return Cursor is
1671 if Is_Empty (Container) then
1675 return (Container'Unchecked_Access, Container.Last);
1682 function Last_Element (Container : Vector) return Element_Type is
1684 return Element (Container, Container.Last);
1691 function Last_Index (Container : Vector) return Extended_Index is
1693 return Container.Last;
1700 function Length (Container : Vector) return Count_Type is
1701 L : constant Int := Int (Container.Last);
1702 F : constant Int := Int (Index_Type'First);
1703 N : constant Int'Base := L - F + 1;
1706 if N > Count_Type'Pos (Count_Type'Last) then
1707 raise Constraint_Error;
1710 return Count_Type (N);
1718 (Target : in out Vector;
1719 Source : in out Vector)
1722 if Target'Address = Source'Address then
1726 if Source.Busy > 0 then
1727 raise Program_Error;
1733 Target_Elements : constant Elements_Access := Target.Elements;
1735 Target.Elements := Source.Elements;
1736 Source.Elements := Target_Elements;
1739 Target.Last := Source.Last;
1740 Source.Last := No_Index;
1747 function Next (Position : Cursor) return Cursor is
1749 if Position.Container = null then
1753 if Position.Index < Position.Container.Last then
1754 return (Position.Container, Position.Index + 1);
1764 procedure Next (Position : in out Cursor) is
1766 if Position.Container = null then
1770 if Position.Index < Position.Container.Last then
1771 Position.Index := Position.Index + 1;
1773 Position := No_Element;
1781 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1783 Insert (Container, Index_Type'First, New_Item);
1787 (Container : in out Vector;
1788 New_Item : Element_Type;
1789 Count : Count_Type := 1)
1802 procedure Previous (Position : in out Cursor) is
1804 if Position.Container = null then
1808 if Position.Index > Index_Type'First then
1809 Position.Index := Position.Index - 1;
1811 Position := No_Element;
1815 function Previous (Position : Cursor) return Cursor is
1817 if Position.Container = null then
1821 if Position.Index > Index_Type'First then
1822 return (Position.Container, Position.Index - 1);
1832 procedure Query_Element
1833 (Container : Vector;
1835 Process : not null access procedure (Element : in Element_Type))
1837 V : Vector renames Container'Unrestricted_Access.all;
1838 B : Natural renames V.Busy;
1839 L : Natural renames V.Lock;
1842 if Index > Container.Last then
1843 raise Constraint_Error;
1850 Process (V.Elements (Index).all);
1862 procedure Query_Element
1864 Process : not null access procedure (Element : in Element_Type))
1867 if Position.Container = null then
1868 raise Constraint_Error;
1871 Query_Element (Position.Container.all, Position.Index, Process);
1879 (Stream : access Root_Stream_Type'Class;
1880 Container : out Vector)
1882 Length : Count_Type'Base;
1883 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1890 Count_Type'Base'Read (Stream, Length);
1892 if Length > Capacity (Container) then
1893 Reserve_Capacity (Container, Capacity => Length);
1896 for J in Count_Type range 1 .. Length loop
1899 Boolean'Read (Stream, B);
1902 Container.Elements (Last) :=
1903 new Element_Type'(Element_Type'Input (Stream));
1906 Container.Last := Last;
1910 ---------------------
1911 -- Replace_Element --
1912 ---------------------
1914 procedure Replace_Element
1915 (Container : Vector;
1920 if Index > Container.Last then
1921 raise Constraint_Error;
1924 if Container.Lock > 0 then
1925 raise Program_Error;
1929 X : Element_Access := Container.Elements (Index);
1931 Container.Elements (Index) := new Element_Type'(By);
1934 end Replace_Element;
1936 procedure Replace_Element (Position : Cursor; By : Element_Type) is
1938 if Position.Container = null then
1939 raise Constraint_Error;
1942 Replace_Element (Position.Container.all, Position.Index, By);
1943 end Replace_Element;
1945 ----------------------
1946 -- Reserve_Capacity --
1947 ----------------------
1949 procedure Reserve_Capacity
1950 (Container : in out Vector;
1951 Capacity : Count_Type)
1953 N : constant Count_Type := Length (Container);
1956 if Capacity = 0 then
1959 X : Elements_Access := Container.Elements;
1961 Container.Elements := null;
1965 elsif N < Container.Elements'Length then
1966 if Container.Busy > 0 then
1967 raise Program_Error;
1971 subtype Array_Index_Subtype is Index_Type'Base range
1972 Index_Type'First .. Container.Last;
1974 Src : Elements_Type renames
1975 Container.Elements (Array_Index_Subtype);
1977 subtype Array_Subtype is
1978 Elements_Type (Array_Index_Subtype);
1980 X : Elements_Access := Container.Elements;
1983 Container.Elements := new Array_Subtype'(Src);
1991 if Container.Elements = null then
1993 Last_As_Int : constant Int'Base :=
1994 Int (Index_Type'First) + Int (Capacity) - 1;
1997 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1998 raise Constraint_Error;
2002 Last : constant Index_Type := Index_Type (Last_As_Int);
2004 subtype Array_Subtype is
2005 Elements_Type (Index_Type'First .. Last);
2008 Container.Elements := new Array_Subtype;
2015 if Capacity <= N then
2016 if N < Container.Elements'Length then
2017 if Container.Busy > 0 then
2018 raise Program_Error;
2022 subtype Array_Index_Subtype is Index_Type'Base range
2023 Index_Type'First .. Container.Last;
2025 Src : Elements_Type renames
2026 Container.Elements (Array_Index_Subtype);
2028 subtype Array_Subtype is
2029 Elements_Type (Array_Index_Subtype);
2031 X : Elements_Access := Container.Elements;
2034 Container.Elements := new Array_Subtype'(Src);
2042 if Capacity = Container.Elements'Length then
2046 if Container.Busy > 0 then
2047 raise Program_Error;
2051 Last_As_Int : constant Int'Base :=
2052 Int (Index_Type'First) + Int (Capacity) - 1;
2055 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2056 raise Constraint_Error;
2060 Last : constant Index_Type := Index_Type (Last_As_Int);
2062 subtype Array_Subtype is
2063 Elements_Type (Index_Type'First .. Last);
2065 X : Elements_Access := Container.Elements;
2068 Container.Elements := new Array_Subtype;
2071 Src : Elements_Type renames
2072 X (Index_Type'First .. Container.Last);
2074 Tgt : Elements_Type renames
2075 Container.Elements (Index_Type'First .. Container.Last);
2084 end Reserve_Capacity;
2090 function Reverse_Find
2091 (Container : Vector;
2092 Item : Element_Type;
2093 Position : Cursor := No_Element) return Cursor
2095 Last : Index_Type'Base;
2098 if Position.Container /= null
2099 and then Position.Container /=
2100 Vector_Access'(Container'Unchecked_Access)
2102 raise Program_Error;
2105 if Position.Container = null
2106 or else Position.Index > Container.Last
2108 Last := Container.Last;
2110 Last := Position.Index;
2113 for Indx in reverse Index_Type'First .. Last loop
2114 if Container.Elements (Indx) /= null
2115 and then Container.Elements (Indx).all = Item
2117 return (Container'Unchecked_Access, Indx);
2124 ------------------------
2125 -- Reverse_Find_Index --
2126 ------------------------
2128 function Reverse_Find_Index
2129 (Container : Vector;
2130 Item : Element_Type;
2131 Index : Index_Type := Index_Type'Last) return Extended_Index
2133 Last : Index_Type'Base;
2136 if Index > Container.Last then
2137 Last := Container.Last;
2142 for Indx in reverse Index_Type'First .. Last loop
2143 if Container.Elements (Indx) /= null
2144 and then Container.Elements (Indx).all = Item
2151 end Reverse_Find_Index;
2153 ---------------------
2154 -- Reverse_Iterate --
2155 ---------------------
2157 procedure Reverse_Iterate
2158 (Container : Vector;
2159 Process : not null access procedure (Position : in Cursor))
2161 V : Vector renames Container'Unrestricted_Access.all;
2162 B : Natural renames V.Busy;
2168 for Indx in reverse Index_Type'First .. Container.Last loop
2169 Process (Cursor'(Container'Unchecked_Access, Indx));
2178 end Reverse_Iterate;
2184 procedure Set_Length
2185 (Container : in out Vector;
2186 Length : Count_Type)
2188 N : constant Count_Type := Indefinite_Vectors.Length (Container);
2195 if Container.Busy > 0 then
2196 raise Program_Error;
2200 for Index in 1 .. N - Length loop
2202 J : constant Index_Type := Container.Last;
2203 X : Element_Access := Container.Elements (J);
2206 Container.Elements (J) := null;
2207 Container.Last := J - 1;
2215 if Length > Capacity (Container) then
2216 Reserve_Capacity (Container, Capacity => Length);
2220 Last_As_Int : constant Int'Base :=
2221 Int (Index_Type'First) + Int (Length) - 1;
2224 Container.Last := Index_Type (Last_As_Int);
2233 (Container : Vector;
2237 if I > Container.Last
2238 or else J > Container.Last
2240 raise Constraint_Error;
2247 if Container.Lock > 0 then
2248 raise Program_Error;
2252 EI : Element_Access renames Container.Elements (I);
2253 EJ : Element_Access renames Container.Elements (J);
2255 EI_Copy : constant Element_Access := EI;
2263 procedure Swap (I, J : Cursor)
2266 if I.Container = null
2267 or else J.Container = null
2269 raise Constraint_Error;
2272 if I.Container /= J.Container then
2273 raise Program_Error;
2276 Swap (I.Container.all, I.Index, J.Index);
2284 (Container : Vector;
2285 Index : Extended_Index) return Cursor
2288 if Index not in Index_Type'First .. Container.Last then
2292 return Cursor'(Container'Unchecked_Access, Index);
2299 function To_Index (Position : Cursor) return Extended_Index is
2301 if Position.Container = null then
2305 if Position.Index <= Position.Container.Last then
2306 return Position.Index;
2316 function To_Vector (Length : Count_Type) return Vector is
2319 return Empty_Vector;
2323 First : constant Int := Int (Index_Type'First);
2324 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2326 Elements : Elements_Access;
2329 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2330 raise Constraint_Error;
2333 Last := Index_Type (Last_As_Int);
2334 Elements := new Elements_Type (Index_Type'First .. Last);
2336 return (Controlled with Elements, Last, 0, 0);
2341 (New_Item : Element_Type;
2342 Length : Count_Type) return Vector
2346 return Empty_Vector;
2350 First : constant Int := Int (Index_Type'First);
2351 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2352 Last : Index_Type'Base;
2353 Elements : Elements_Access;
2356 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2357 raise Constraint_Error;
2360 Last := Index_Type (Last_As_Int);
2361 Elements := new Elements_Type (Index_Type'First .. Last);
2363 Last := Index_Type'First;
2367 Elements (Last) := new Element_Type'(New_Item);
2368 exit when Last = Elements'Last;
2373 for J in Index_Type'First .. Last - 1 loop
2374 Free (Elements (J));
2381 return (Controlled with Elements, Last, 0, 0);
2385 --------------------
2386 -- Update_Element --
2387 --------------------
2389 procedure Update_Element
2390 (Container : Vector;
2392 Process : not null access procedure (Element : in out Element_Type))
2394 V : Vector renames Container'Unrestricted_Access.all;
2395 B : Natural renames V.Busy;
2396 L : Natural renames V.Lock;
2399 if Index > Container.Last then
2400 raise Constraint_Error;
2407 Process (V.Elements (Index).all);
2419 procedure Update_Element
2421 Process : not null access procedure (Element : in out Element_Type))
2424 if Position.Container = null then
2425 raise Constraint_Error;
2428 Update_Element (Position.Container.all, Position.Index, Process);
2436 (Stream : access Root_Stream_Type'Class;
2439 N : constant Count_Type := Length (Container);
2442 Count_Type'Base'Write (Stream, N);
2449 E : Elements_Type renames Container.Elements.all;
2452 for Indx in Index_Type'First .. Container.Last loop
2454 -- There's another way to do this. Instead a separate
2455 -- Boolean for each element, you could write a Boolean
2456 -- followed by a count of how many nulls or non-nulls
2457 -- follow in the array.
2459 if E (Indx) = null then
2460 Boolean'Write (Stream, False);
2462 Boolean'Write (Stream, True);
2463 Element_Type'Output (Stream, E (Indx).all);
2469 end Ada.Containers.Indefinite_Vectors;