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;
482 function Capacity (Container : Vector) return Count_Type is
484 if Container.Elements = null then
488 return Container.Elements'Length;
495 procedure Clear (Container : in out Vector) is
497 if Container.Busy > 0 then
501 while Container.Last >= Index_Type'First loop
503 X : Element_Access := Container.Elements (Container.Last);
505 Container.Elements (Container.Last) := null;
506 Container.Last := Container.Last - 1;
518 Item : Element_Type) return Boolean
521 return Find_Index (Container, Item) /= No_Index;
529 (Container : in out Vector;
530 Index : Extended_Index;
531 Count : Count_Type := 1)
534 if Index < Index_Type'First then
535 raise Constraint_Error;
538 if Index > Container.Last then
539 if Index > Container.Last + 1 then
540 raise Constraint_Error;
550 if Container.Busy > 0 then
555 Index_As_Int : constant Int := Int (Index);
556 Old_Last_As_Int : constant Int := Int (Container.Last);
558 -- TODO: somewhat vestigial...fix ???
559 Count1 : constant Int'Base := Int (Count);
560 Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
561 N : constant Int'Base := Int'Min (Count1, Count2);
563 J_As_Int : constant Int'Base := Index_As_Int + N;
564 E : Elements_Type renames Container.Elements.all;
567 if J_As_Int > Old_Last_As_Int then
568 while Container.Last >= Index loop
570 K : constant Index_Type := Container.Last;
571 X : Element_Access := E (K);
575 Container.Last := K - 1;
582 J : constant Index_Type := Index_Type (J_As_Int);
584 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
585 New_Last : constant Index_Type :=
586 Index_Type (New_Last_As_Int);
589 for K in Index .. J - 1 loop
591 X : Element_Access := E (K);
598 E (Index .. New_Last) := E (J .. Container.Last);
599 Container.Last := New_Last;
606 (Container : in out Vector;
607 Position : in out Cursor;
608 Count : Count_Type := 1)
611 if Position.Container = null then
612 raise Constraint_Error;
615 if Position.Container /= Container'Unchecked_Access
616 or else Position.Index > Container.Last
621 Delete (Container, Position.Index, Count);
623 Position := No_Element; -- See comment in a-convec.adb
630 procedure Delete_First
631 (Container : in out Vector;
632 Count : Count_Type := 1)
639 if Count >= Length (Container) then
644 Delete (Container, Index_Type'First, Count);
651 procedure Delete_Last
652 (Container : in out Vector;
653 Count : Count_Type := 1)
655 N : constant Count_Type := Length (Container);
664 if Container.Busy > 0 then
669 E : Elements_Type renames Container.Elements.all;
672 for Indx in 1 .. Count_Type'Min (Count, N) loop
674 J : constant Index_Type := Container.Last;
675 X : Element_Access := E (J);
679 Container.Last := J - 1;
692 Index : Index_Type) return Element_Type
695 if Index > Container.Last then
696 raise Constraint_Error;
700 EA : constant Element_Access := Container.Elements (Index);
704 raise Constraint_Error;
711 function Element (Position : Cursor) return Element_Type is
713 if Position.Container = null then
714 raise Constraint_Error;
717 return Element (Position.Container.all, Position.Index);
724 procedure Finalize (Container : in out Vector) is
729 X : Elements_Access := Container.Elements;
731 Container.Elements := null;
743 Position : Cursor := No_Element) return Cursor
746 if Position.Container /= null
747 and then (Position.Container /= Container'Unchecked_Access
748 or else Position.Index > Container.Last)
753 for J in Position.Index .. Container.Last loop
754 if Container.Elements (J) /= null
755 and then Container.Elements (J).all = Item
757 return (Container'Unchecked_Access, J);
771 Index : Index_Type := Index_Type'First) return Extended_Index
774 for Indx in Index .. Container.Last loop
775 if Container.Elements (Indx) /= null
776 and then Container.Elements (Indx).all = Item
789 function First (Container : Vector) return Cursor is
791 if Is_Empty (Container) then
795 return (Container'Unchecked_Access, Index_Type'First);
802 function First_Element (Container : Vector) return Element_Type is
804 return Element (Container, Index_Type'First);
811 function First_Index (Container : Vector) return Index_Type is
812 pragma Unreferenced (Container);
814 return Index_Type'First;
817 ---------------------
818 -- Generic_Sorting --
819 ---------------------
821 package body Generic_Sorting is
823 -----------------------
824 -- Local Subprograms --
825 -----------------------
827 function Is_Less (L, R : Element_Access) return Boolean;
828 pragma Inline (Is_Less);
834 function Is_Less (L, R : Element_Access) return Boolean is
841 return L.all < R.all;
849 function Is_Sorted (Container : Vector) return Boolean is
851 if Container.Last <= Index_Type'First then
856 E : Elements_Type renames Container.Elements.all;
858 for I in Index_Type'First .. Container.Last - 1 loop
859 if Is_Less (E (I + 1), E (I)) then
872 procedure Merge (Target, Source : in out Vector) is
873 I : Index_Type'Base := Target.Last;
877 if Target.Last < Index_Type'First then
878 Move (Target => Target, Source => Source);
882 if Target'Address = Source'Address then
886 if Source.Last < Index_Type'First then
890 if Source.Busy > 0 then
894 Target.Set_Length (Length (Target) + Length (Source));
897 while Source.Last >= Index_Type'First loop
898 if I < Index_Type'First then
900 Src : Elements_Type renames
901 Source.Elements (Index_Type'First .. Source.Last);
904 Target.Elements (Index_Type'First .. J) := Src;
905 Src := (others => null);
908 Source.Last := No_Index;
913 Src : Element_Access renames Source.Elements (Source.Last);
914 Tgt : Element_Access renames Target.Elements (I);
917 if Is_Less (Src, Tgt) then
918 Target.Elements (J) := Tgt;
923 Target.Elements (J) := Src;
925 Source.Last := Source.Last - 1;
937 procedure Sort (Container : in out Vector)
940 new Generic_Array_Sort
941 (Index_Type => Index_Type,
942 Element_Type => Element_Access,
943 Array_Type => Elements_Type,
946 -- Start of processing for Sort
949 if Container.Last <= Index_Type'First then
953 if Container.Lock > 0 then
957 Sort (Container.Elements (Index_Type'First .. Container.Last));
966 function Has_Element (Position : Cursor) return Boolean is
968 if Position.Container = null then
972 return Position.Index <= Position.Container.Last;
980 (Container : in out Vector;
981 Before : Extended_Index;
982 New_Item : Element_Type;
983 Count : Count_Type := 1)
985 N : constant Int := Int (Count);
987 New_Last_As_Int : Int'Base;
988 New_Last : Index_Type;
990 Dst : Elements_Access;
993 if Before < Index_Type'First then
994 raise Constraint_Error;
997 if Before > Container.Last
998 and then Before > Container.Last + 1
1000 raise Constraint_Error;
1008 Old_Last_As_Int : constant Int := Int (Container.Last);
1011 New_Last_As_Int := Old_Last_As_Int + N;
1013 if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1014 raise Constraint_Error;
1017 New_Last := Index_Type (New_Last_As_Int);
1020 if Container.Busy > 0 then
1021 raise Program_Error;
1024 if Container.Elements = null then
1025 Container.Elements :=
1026 new Elements_Type (Index_Type'First .. New_Last);
1028 Container.Last := No_Index;
1030 for J in Container.Elements'Range loop
1031 Container.Elements (J) := new Element_Type'(New_Item);
1032 Container.Last := J;
1038 if New_Last <= Container.Elements'Last then
1040 E : Elements_Type renames Container.Elements.all;
1042 if Before <= Container.Last then
1044 Index_As_Int : constant Int'Base :=
1045 Index_Type'Pos (Before) + N;
1047 Index : constant Index_Type := Index_Type (Index_As_Int);
1049 J : Index_Type'Base := Before;
1052 E (Index .. New_Last) := E (Before .. Container.Last);
1053 Container.Last := New_Last;
1055 while J < Index loop
1056 E (J) := new Element_Type'(New_Item);
1061 E (J .. Index - 1) := (others => null);
1066 for J in Before .. New_Last loop
1067 E (J) := new Element_Type'(New_Item);
1068 Container.Last := J;
1077 First : constant Int := Int (Index_Type'First);
1078 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
1079 Size : Int'Base := Int'Max (1, Container.Elements'Length);
1082 while Size < New_Size loop
1083 if Size > Int'Last / 2 then
1091 -- TODO: The following calculations aren't quite right, since
1092 -- there will be overflow if Index_Type'Range is very large
1093 -- (e.g. this package is instantiated with a 64-bit integer).
1097 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
1099 if Size > Max_Size then
1105 Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
1107 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1111 if Before <= Container.Last then
1113 Index_As_Int : constant Int'Base :=
1114 Index_Type'Pos (Before) + N;
1116 Index : constant Index_Type := Index_Type (Index_As_Int);
1118 Src : Elements_Access := Container.Elements;
1121 Dst (Index_Type'First .. Before - 1) :=
1122 Src (Index_Type'First .. Before - 1);
1124 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1126 Container.Elements := Dst;
1127 Container.Last := New_Last;
1130 for J in Before .. Index - 1 loop
1131 Dst (J) := new Element_Type'(New_Item);
1137 Src : Elements_Access := Container.Elements;
1140 Dst (Index_Type'First .. Container.Last) :=
1141 Src (Index_Type'First .. Container.Last);
1143 Container.Elements := Dst;
1146 for J in Before .. New_Last loop
1147 Dst (J) := new Element_Type'(New_Item);
1148 Container.Last := J;
1155 (Container : in out Vector;
1156 Before : Extended_Index;
1159 N : constant Count_Type := Length (New_Item);
1162 if Before < Index_Type'First then
1163 raise Constraint_Error;
1166 if Before > Container.Last
1167 and then Before > Container.Last + 1
1169 raise Constraint_Error;
1176 Insert_Space (Container, Before, Count => N);
1179 Dst_Last_As_Int : constant Int'Base :=
1180 Int'Base (Before) + Int'Base (N) - 1;
1182 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1184 Dst : Elements_Type renames
1185 Container.Elements (Before .. Dst_Last);
1187 Dst_Index : Index_Type'Base := Before - 1;
1190 if Container'Address /= New_Item'Address then
1192 Src : Elements_Type renames
1193 New_Item.Elements (Index_Type'First .. New_Item.Last);
1196 for Src_Index in Src'Range loop
1197 Dst_Index := Dst_Index + 1;
1199 if Src (Src_Index) /= null then
1200 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1209 subtype Src_Index_Subtype is Index_Type'Base range
1210 Index_Type'First .. Before - 1;
1212 Src : Elements_Type renames
1213 Container.Elements (Src_Index_Subtype);
1216 for Src_Index in Src'Range loop
1217 Dst_Index := Dst_Index + 1;
1219 if Src (Src_Index) /= null then
1220 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1225 if Dst_Last = Container.Last then
1230 subtype Src_Index_Subtype is Index_Type'Base range
1231 Dst_Last + 1 .. Container.Last;
1233 Src : Elements_Type renames
1234 Container.Elements (Src_Index_Subtype);
1237 for Src_Index in Src'Range loop
1238 Dst_Index := Dst_Index + 1;
1240 if Src (Src_Index) /= null then
1241 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1249 (Container : in out Vector;
1253 Index : Index_Type'Base;
1256 if Before.Container /= null
1257 and then Before.Container /= Container'Unchecked_Access
1259 raise Program_Error;
1262 if Is_Empty (New_Item) then
1266 if Before.Container = null
1267 or else Before.Index > Container.Last
1269 if Container.Last = Index_Type'Last then
1270 raise Constraint_Error;
1273 Index := Container.Last + 1;
1276 Index := Before.Index;
1279 Insert (Container, Index, New_Item);
1283 (Container : in out Vector;
1286 Position : out Cursor)
1288 Index : Index_Type'Base;
1291 if Before.Container /= null
1292 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1294 raise Program_Error;
1297 if Is_Empty (New_Item) then
1298 if Before.Container = null
1299 or else Before.Index > Container.Last
1301 Position := No_Element;
1303 Position := (Container'Unchecked_Access, Before.Index);
1309 if Before.Container = null
1310 or else Before.Index > Container.Last
1312 if Container.Last = Index_Type'Last then
1313 raise Constraint_Error;
1316 Index := Container.Last + 1;
1319 Index := Before.Index;
1322 Insert (Container, Index, New_Item);
1324 Position := Cursor'(Container'Unchecked_Access, Index);
1328 (Container : in out Vector;
1330 New_Item : Element_Type;
1331 Count : Count_Type := 1)
1333 Index : Index_Type'Base;
1336 if Before.Container /= null
1337 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1339 raise Program_Error;
1346 if Before.Container = null
1347 or else Before.Index > Container.Last
1349 if Container.Last = Index_Type'Last then
1350 raise Constraint_Error;
1353 Index := Container.Last + 1;
1356 Index := Before.Index;
1359 Insert (Container, Index, New_Item, Count);
1363 (Container : in out Vector;
1365 New_Item : Element_Type;
1366 Position : out Cursor;
1367 Count : Count_Type := 1)
1369 Index : Index_Type'Base;
1372 if Before.Container /= null
1373 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1375 raise Program_Error;
1379 if Before.Container = null
1380 or else Before.Index > Container.Last
1382 Position := No_Element;
1384 Position := (Container'Unchecked_Access, Before.Index);
1390 if Before.Container = null
1391 or else Before.Index > Container.Last
1393 if Container.Last = Index_Type'Last then
1394 raise Constraint_Error;
1397 Index := Container.Last + 1;
1400 Index := Before.Index;
1403 Insert (Container, Index, New_Item, Count);
1405 Position := (Container'Unchecked_Access, Index);
1412 procedure Insert_Space
1413 (Container : in out Vector;
1414 Before : Extended_Index;
1415 Count : Count_Type := 1)
1417 N : constant Int := Int (Count);
1419 New_Last_As_Int : Int'Base;
1420 New_Last : Index_Type;
1422 Dst : Elements_Access;
1425 if Before < Index_Type'First then
1426 raise Constraint_Error;
1429 if Before > Container.Last
1430 and then Before > Container.Last + 1
1432 raise Constraint_Error;
1440 Old_Last_As_Int : constant Int := Int (Container.Last);
1443 New_Last_As_Int := Old_Last_As_Int + N;
1445 if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1446 raise Constraint_Error;
1449 New_Last := Index_Type (New_Last_As_Int);
1452 if Container.Busy > 0 then
1453 raise Program_Error;
1456 if Container.Elements = null then
1457 Container.Elements :=
1458 new Elements_Type (Index_Type'First .. New_Last);
1460 Container.Last := New_Last;
1464 if New_Last <= Container.Elements'Last then
1466 E : Elements_Type renames Container.Elements.all;
1469 if Before <= Container.Last then
1471 Index_As_Int : constant Int'Base :=
1472 Index_Type'Pos (Before) + N;
1474 Index : constant Index_Type := Index_Type (Index_As_Int);
1477 E (Index .. New_Last) := E (Before .. Container.Last);
1478 E (Before .. Index - 1) := (others => null);
1483 Container.Last := New_Last;
1488 First : constant Int := Int (Index_Type'First);
1489 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
1490 Size : Int'Base := Int'Max (1, Container.Elements'Length);
1493 while Size < New_Size loop
1494 if Size > Int'Last / 2 then
1502 -- TODO: The following calculations aren't quite right, since
1503 -- there will be overflow if Index_Type'Range is very large
1504 -- (e.g. this package is instantiated with a 64-bit integer).
1508 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
1510 if Size > Max_Size then
1516 Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
1518 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1523 Src : Elements_Access := Container.Elements;
1526 if Before <= Container.Last then
1528 Index_As_Int : constant Int'Base :=
1529 Index_Type'Pos (Before) + N;
1531 Index : constant Index_Type := Index_Type (Index_As_Int);
1534 Dst (Index_Type'First .. Before - 1) :=
1535 Src (Index_Type'First .. Before - 1);
1537 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1541 Dst (Index_Type'First .. Container.Last) :=
1542 Src (Index_Type'First .. Container.Last);
1545 Container.Elements := Dst;
1546 Container.Last := New_Last;
1551 procedure Insert_Space
1552 (Container : in out Vector;
1554 Position : out Cursor;
1555 Count : Count_Type := 1)
1557 Index : Index_Type'Base;
1560 if Before.Container /= null
1561 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1563 raise Program_Error;
1567 if Before.Container = null
1568 or else Before.Index > Container.Last
1570 Position := No_Element;
1572 Position := (Container'Unchecked_Access, Before.Index);
1578 if Before.Container = null
1579 or else Before.Index > Container.Last
1581 if Container.Last = Index_Type'Last then
1582 raise Constraint_Error;
1585 Index := Container.Last + 1;
1588 Index := Before.Index;
1591 Insert_Space (Container, Index, Count);
1593 Position := Cursor'(Container'Unchecked_Access, Index);
1600 function Is_Empty (Container : Vector) return Boolean is
1602 return Container.Last < Index_Type'First;
1610 (Container : Vector;
1611 Process : not null access procedure (Position : in Cursor))
1613 V : Vector renames Container'Unrestricted_Access.all;
1614 B : Natural renames V.Busy;
1620 for Indx in Index_Type'First .. Container.Last loop
1621 Process (Cursor'(Container'Unchecked_Access, Indx));
1636 function Last (Container : Vector) return Cursor is
1638 if Is_Empty (Container) then
1642 return (Container'Unchecked_Access, Container.Last);
1649 function Last_Element (Container : Vector) return Element_Type is
1651 return Element (Container, Container.Last);
1658 function Last_Index (Container : Vector) return Extended_Index is
1660 return Container.Last;
1667 function Length (Container : Vector) return Count_Type is
1668 L : constant Int := Int (Container.Last);
1669 F : constant Int := Int (Index_Type'First);
1670 N : constant Int'Base := L - F + 1;
1673 if N > Count_Type'Pos (Count_Type'Last) then
1674 raise Constraint_Error;
1677 return Count_Type (N);
1685 (Target : in out Vector;
1686 Source : in out Vector)
1689 if Target'Address = Source'Address then
1693 if Source.Busy > 0 then
1694 raise Program_Error;
1700 Target_Elements : constant Elements_Access := Target.Elements;
1702 Target.Elements := Source.Elements;
1703 Source.Elements := Target_Elements;
1706 Target.Last := Source.Last;
1707 Source.Last := No_Index;
1714 function Next (Position : Cursor) return Cursor is
1716 if Position.Container = null then
1720 if Position.Index < Position.Container.Last then
1721 return (Position.Container, Position.Index + 1);
1731 procedure Next (Position : in out Cursor) is
1733 if Position.Container = null then
1737 if Position.Index < Position.Container.Last then
1738 Position.Index := Position.Index + 1;
1740 Position := No_Element;
1748 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1750 Insert (Container, Index_Type'First, New_Item);
1754 (Container : in out Vector;
1755 New_Item : Element_Type;
1756 Count : Count_Type := 1)
1769 procedure Previous (Position : in out Cursor) is
1771 if Position.Container = null then
1775 if Position.Index > Index_Type'First then
1776 Position.Index := Position.Index - 1;
1778 Position := No_Element;
1782 function Previous (Position : Cursor) return Cursor is
1784 if Position.Container = null then
1788 if Position.Index > Index_Type'First then
1789 return (Position.Container, Position.Index - 1);
1799 procedure Query_Element
1800 (Container : Vector;
1802 Process : not null access procedure (Element : in Element_Type))
1804 V : Vector renames Container'Unrestricted_Access.all;
1805 B : Natural renames V.Busy;
1806 L : Natural renames V.Lock;
1809 if Index > Container.Last then
1810 raise Constraint_Error;
1813 if V.Elements (Index) = null then
1814 raise Constraint_Error;
1821 Process (V.Elements (Index).all);
1833 procedure Query_Element
1835 Process : not null access procedure (Element : in Element_Type))
1838 if Position.Container = null then
1839 raise Constraint_Error;
1842 Query_Element (Position.Container.all, Position.Index, Process);
1850 (Stream : access Root_Stream_Type'Class;
1851 Container : out Vector)
1853 Length : Count_Type'Base;
1854 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1861 Count_Type'Base'Read (Stream, Length);
1863 if Length > Capacity (Container) then
1864 Reserve_Capacity (Container, Capacity => Length);
1867 for J in Count_Type range 1 .. Length loop
1870 Boolean'Read (Stream, B);
1873 Container.Elements (Last) :=
1874 new Element_Type'(Element_Type'Input (Stream));
1877 Container.Last := Last;
1882 (Stream : access Root_Stream_Type'Class;
1883 Position : out Cursor)
1886 raise Program_Error;
1889 ---------------------
1890 -- Replace_Element --
1891 ---------------------
1893 procedure Replace_Element
1894 (Container : in out Vector;
1896 New_Item : Element_Type)
1899 if Index > Container.Last then
1900 raise Constraint_Error;
1903 if Container.Lock > 0 then
1904 raise Program_Error;
1908 X : Element_Access := Container.Elements (Index);
1910 Container.Elements (Index) := new Element_Type'(New_Item);
1913 end Replace_Element;
1915 procedure Replace_Element
1916 (Container : in out Vector;
1918 New_Item : Element_Type)
1921 if Position.Container = null then
1922 raise Constraint_Error;
1925 if Position.Container /= Container'Unrestricted_Access then
1926 raise Program_Error;
1929 Replace_Element (Container, Position.Index, New_Item);
1930 end Replace_Element;
1932 ----------------------
1933 -- Reserve_Capacity --
1934 ----------------------
1936 procedure Reserve_Capacity
1937 (Container : in out Vector;
1938 Capacity : Count_Type)
1940 N : constant Count_Type := Length (Container);
1943 if Capacity = 0 then
1946 X : Elements_Access := Container.Elements;
1948 Container.Elements := null;
1952 elsif N < Container.Elements'Length then
1953 if Container.Busy > 0 then
1954 raise Program_Error;
1958 subtype Array_Index_Subtype is Index_Type'Base range
1959 Index_Type'First .. Container.Last;
1961 Src : Elements_Type renames
1962 Container.Elements (Array_Index_Subtype);
1964 subtype Array_Subtype is
1965 Elements_Type (Array_Index_Subtype);
1967 X : Elements_Access := Container.Elements;
1970 Container.Elements := new Array_Subtype'(Src);
1978 if Container.Elements = null then
1980 Last_As_Int : constant Int'Base :=
1981 Int (Index_Type'First) + Int (Capacity) - 1;
1984 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1985 raise Constraint_Error;
1989 Last : constant Index_Type := Index_Type (Last_As_Int);
1991 subtype Array_Subtype is
1992 Elements_Type (Index_Type'First .. Last);
1995 Container.Elements := new Array_Subtype;
2002 if Capacity <= N then
2003 if N < Container.Elements'Length then
2004 if Container.Busy > 0 then
2005 raise Program_Error;
2009 subtype Array_Index_Subtype is Index_Type'Base range
2010 Index_Type'First .. Container.Last;
2012 Src : Elements_Type renames
2013 Container.Elements (Array_Index_Subtype);
2015 subtype Array_Subtype is
2016 Elements_Type (Array_Index_Subtype);
2018 X : Elements_Access := Container.Elements;
2021 Container.Elements := new Array_Subtype'(Src);
2029 if Capacity = Container.Elements'Length then
2033 if Container.Busy > 0 then
2034 raise Program_Error;
2038 Last_As_Int : constant Int'Base :=
2039 Int (Index_Type'First) + Int (Capacity) - 1;
2042 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2043 raise Constraint_Error;
2047 Last : constant Index_Type := Index_Type (Last_As_Int);
2049 subtype Array_Subtype is
2050 Elements_Type (Index_Type'First .. Last);
2052 X : Elements_Access := Container.Elements;
2055 Container.Elements := new Array_Subtype;
2058 Src : Elements_Type renames
2059 X (Index_Type'First .. Container.Last);
2061 Tgt : Elements_Type renames
2062 Container.Elements (Index_Type'First .. Container.Last);
2071 end Reserve_Capacity;
2073 ----------------------
2074 -- Reverse_Elements --
2075 ----------------------
2077 procedure Reverse_Elements (Container : in out Vector) is
2079 if Container.Length <= 1 then
2083 if Container.Lock > 0 then
2084 raise Program_Error;
2088 I : Index_Type := Index_Type'First;
2089 J : Index_Type := Container.Last;
2090 E : Elements_Type renames Container.Elements.all;
2095 EI : constant Element_Access := E (I);
2106 end Reverse_Elements;
2112 function Reverse_Find
2113 (Container : Vector;
2114 Item : Element_Type;
2115 Position : Cursor := No_Element) return Cursor
2117 Last : Index_Type'Base;
2120 if Position.Container /= null
2121 and then Position.Container /= Container'Unchecked_Access
2123 raise Program_Error;
2126 if Position.Container = null
2127 or else Position.Index > Container.Last
2129 Last := Container.Last;
2131 Last := Position.Index;
2134 for Indx in reverse Index_Type'First .. Last loop
2135 if Container.Elements (Indx) /= null
2136 and then Container.Elements (Indx).all = Item
2138 return (Container'Unchecked_Access, Indx);
2145 ------------------------
2146 -- Reverse_Find_Index --
2147 ------------------------
2149 function Reverse_Find_Index
2150 (Container : Vector;
2151 Item : Element_Type;
2152 Index : Index_Type := Index_Type'Last) return Extended_Index
2154 Last : Index_Type'Base;
2157 if Index > Container.Last then
2158 Last := Container.Last;
2163 for Indx in reverse Index_Type'First .. Last loop
2164 if Container.Elements (Indx) /= null
2165 and then Container.Elements (Indx).all = Item
2172 end Reverse_Find_Index;
2174 ---------------------
2175 -- Reverse_Iterate --
2176 ---------------------
2178 procedure Reverse_Iterate
2179 (Container : Vector;
2180 Process : not null access procedure (Position : in Cursor))
2182 V : Vector renames Container'Unrestricted_Access.all;
2183 B : Natural renames V.Busy;
2189 for Indx in reverse Index_Type'First .. Container.Last loop
2190 Process (Cursor'(Container'Unchecked_Access, Indx));
2199 end Reverse_Iterate;
2205 procedure Set_Length
2206 (Container : in out Vector;
2207 Length : Count_Type)
2209 N : constant Count_Type := Indefinite_Vectors.Length (Container);
2216 if Container.Busy > 0 then
2217 raise Program_Error;
2221 for Index in 1 .. N - Length loop
2223 J : constant Index_Type := Container.Last;
2224 X : Element_Access := Container.Elements (J);
2227 Container.Elements (J) := null;
2228 Container.Last := J - 1;
2236 if Length > Capacity (Container) then
2237 Reserve_Capacity (Container, Capacity => Length);
2241 Last_As_Int : constant Int'Base :=
2242 Int (Index_Type'First) + Int (Length) - 1;
2245 Container.Last := Index_Type (Last_As_Int);
2254 (Container : in out Vector;
2258 if I > Container.Last
2259 or else J > Container.Last
2261 raise Constraint_Error;
2268 if Container.Lock > 0 then
2269 raise Program_Error;
2273 EI : Element_Access renames Container.Elements (I);
2274 EJ : Element_Access renames Container.Elements (J);
2276 EI_Copy : constant Element_Access := EI;
2285 (Container : in out Vector;
2289 if I.Container = null
2290 or else J.Container = null
2292 raise Constraint_Error;
2295 if I.Container /= Container'Unrestricted_Access
2296 or else J.Container /= Container'Unrestricted_Access
2298 raise Program_Error;
2301 Swap (Container, I.Index, J.Index);
2309 (Container : Vector;
2310 Index : Extended_Index) return Cursor
2313 if Index not in Index_Type'First .. Container.Last then
2317 return Cursor'(Container'Unchecked_Access, Index);
2324 function To_Index (Position : Cursor) return Extended_Index is
2326 if Position.Container = null then
2330 if Position.Index <= Position.Container.Last then
2331 return Position.Index;
2341 function To_Vector (Length : Count_Type) return Vector is
2344 return Empty_Vector;
2348 First : constant Int := Int (Index_Type'First);
2349 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2351 Elements : Elements_Access;
2354 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2355 raise Constraint_Error;
2358 Last := Index_Type (Last_As_Int);
2359 Elements := new Elements_Type (Index_Type'First .. Last);
2361 return (Controlled with Elements, Last, 0, 0);
2366 (New_Item : Element_Type;
2367 Length : Count_Type) return Vector
2371 return Empty_Vector;
2375 First : constant Int := Int (Index_Type'First);
2376 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2377 Last : Index_Type'Base;
2378 Elements : Elements_Access;
2381 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2382 raise Constraint_Error;
2385 Last := Index_Type (Last_As_Int);
2386 Elements := new Elements_Type (Index_Type'First .. Last);
2388 Last := Index_Type'First;
2392 Elements (Last) := new Element_Type'(New_Item);
2393 exit when Last = Elements'Last;
2398 for J in Index_Type'First .. Last - 1 loop
2399 Free (Elements (J));
2406 return (Controlled with Elements, Last, 0, 0);
2410 --------------------
2411 -- Update_Element --
2412 --------------------
2414 procedure Update_Element
2415 (Container : in out Vector;
2417 Process : not null access procedure (Element : in out Element_Type))
2419 B : Natural renames Container.Busy;
2420 L : Natural renames Container.Lock;
2423 if Index > Container.Last then
2424 raise Constraint_Error;
2427 if Container.Elements (Index) = null then
2428 raise Constraint_Error;
2435 Process (Container.Elements (Index).all);
2447 procedure Update_Element
2448 (Container : in out Vector;
2450 Process : not null access procedure (Element : in out Element_Type))
2453 if Position.Container = null then
2454 raise Constraint_Error;
2457 if Position.Container /= Container'Unrestricted_Access then
2458 raise Program_Error;
2461 Update_Element (Container, Position.Index, Process);
2469 (Stream : access Root_Stream_Type'Class;
2472 N : constant Count_Type := Length (Container);
2475 Count_Type'Base'Write (Stream, N);
2482 E : Elements_Type renames Container.Elements.all;
2485 for Indx in Index_Type'First .. Container.Last loop
2487 -- There's another way to do this. Instead a separate
2488 -- Boolean for each element, you could write a Boolean
2489 -- followed by a count of how many nulls or non-nulls
2490 -- follow in the array.
2492 if E (Indx) = null then
2493 Boolean'Write (Stream, False);
2495 Boolean'Write (Stream, True);
2496 Element_Type'Output (Stream, E (Indx).all);
2503 (Stream : access Root_Stream_Type'Class;
2507 raise Program_Error;
2510 end Ada.Containers.Indefinite_Vectors;