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-2009, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada.Containers.Generic_Array_Sort;
31 with Ada.Unchecked_Deallocation;
32 with System; use type System.Address;
34 package body Ada.Containers.Indefinite_Vectors is
36 type Int is range System.Min_Int .. System.Max_Int;
37 type UInt is mod System.Max_Binary_Modulus;
40 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
43 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
49 function "&" (Left, Right : Vector) return Vector is
50 LN : constant Count_Type := Length (Left);
51 RN : constant Count_Type := Length (Right);
60 RE : Elements_Array renames
61 Right.Elements.EA (Index_Type'First .. Right.Last);
63 Elements : Elements_Access :=
64 new Elements_Type (Right.Last);
67 for I in Elements.EA'Range loop
69 if RE (I) /= null then
70 Elements.EA (I) := new Element_Type'(RE (I).all);
75 for J in Index_Type'First .. I - 1 loop
76 Free (Elements.EA (J));
84 return (Controlled with Elements, Right.Last, 0, 0);
91 LE : Elements_Array renames
92 Left.Elements.EA (Index_Type'First .. Left.Last);
94 Elements : Elements_Access :=
95 new Elements_Type (Left.Last);
98 for I in Elements.EA'Range loop
100 if LE (I) /= null then
101 Elements.EA (I) := new Element_Type'(LE (I).all);
106 for J in Index_Type'First .. I - 1 loop
107 Free (Elements.EA (J));
115 return (Controlled with Elements, Left.Last, 0, 0);
120 N : constant Int'Base := Int (LN) + Int (RN);
121 Last_As_Int : Int'Base;
124 if Int (No_Index) > Int'Last - N then
125 raise Constraint_Error with "new length is out of range";
128 Last_As_Int := Int (No_Index) + N;
130 if Last_As_Int > Int (Index_Type'Last) then
131 raise Constraint_Error with "new length is out of range";
135 Last : constant Index_Type := Index_Type (Last_As_Int);
137 LE : Elements_Array renames
138 Left.Elements.EA (Index_Type'First .. Left.Last);
140 RE : Elements_Array renames
141 Right.Elements.EA (Index_Type'First .. Right.Last);
143 Elements : Elements_Access := new Elements_Type (Last);
145 I : Index_Type'Base := No_Index;
148 for LI in LE'Range loop
152 if LE (LI) /= null then
153 Elements.EA (I) := new Element_Type'(LE (LI).all);
158 for J in Index_Type'First .. I - 1 loop
159 Free (Elements.EA (J));
167 for RI in RE'Range loop
171 if RE (RI) /= null then
172 Elements.EA (I) := new Element_Type'(RE (RI).all);
177 for J in Index_Type'First .. I - 1 loop
178 Free (Elements.EA (J));
186 return (Controlled with Elements, Last, 0, 0);
191 function "&" (Left : Vector; Right : Element_Type) return Vector is
192 LN : constant Count_Type := Length (Left);
197 Elements : Elements_Access := new Elements_Type (Index_Type'First);
201 Elements.EA (Index_Type'First) := new Element_Type'(Right);
208 return (Controlled with Elements, Index_Type'First, 0, 0);
213 Last_As_Int : Int'Base;
216 if Int (Index_Type'First) > Int'Last - Int (LN) then
217 raise Constraint_Error with "new length is out of range";
220 Last_As_Int := Int (Index_Type'First) + Int (LN);
222 if Last_As_Int > Int (Index_Type'Last) then
223 raise Constraint_Error with "new length is out of range";
227 Last : constant Index_Type := Index_Type (Last_As_Int);
229 LE : Elements_Array renames
230 Left.Elements.EA (Index_Type'First .. Left.Last);
232 Elements : Elements_Access :=
233 new Elements_Type (Last);
236 for I in LE'Range loop
238 if LE (I) /= null then
239 Elements.EA (I) := new Element_Type'(LE (I).all);
244 for J in Index_Type'First .. I - 1 loop
245 Free (Elements.EA (J));
254 Elements.EA (Last) := new Element_Type'(Right);
258 for J in Index_Type'First .. Last - 1 loop
259 Free (Elements.EA (J));
266 return (Controlled with Elements, Last, 0, 0);
271 function "&" (Left : Element_Type; Right : Vector) return Vector is
272 RN : constant Count_Type := Length (Right);
277 Elements : Elements_Access := new Elements_Type (Index_Type'First);
281 Elements.EA (Index_Type'First) := new Element_Type'(Left);
288 return (Controlled with Elements, Index_Type'First, 0, 0);
293 Last_As_Int : Int'Base;
296 if Int (Index_Type'First) > Int'Last - Int (RN) then
297 raise Constraint_Error with "new length is out of range";
300 Last_As_Int := Int (Index_Type'First) + Int (RN);
302 if Last_As_Int > Int (Index_Type'Last) then
303 raise Constraint_Error with "new length is out of range";
307 Last : constant Index_Type := Index_Type (Last_As_Int);
309 RE : Elements_Array renames
310 Right.Elements.EA (Index_Type'First .. Right.Last);
312 Elements : Elements_Access :=
313 new Elements_Type (Last);
315 I : Index_Type'Base := Index_Type'First;
319 Elements.EA (I) := new Element_Type'(Left);
326 for RI in RE'Range loop
330 if RE (RI) /= null then
331 Elements.EA (I) := new Element_Type'(RE (RI).all);
336 for J in Index_Type'First .. I - 1 loop
337 Free (Elements.EA (J));
345 return (Controlled with Elements, Last, 0, 0);
350 function "&" (Left, Right : Element_Type) return Vector is
352 if Index_Type'First >= Index_Type'Last then
353 raise Constraint_Error with "new length is out of range";
357 Last : constant Index_Type := Index_Type'First + 1;
358 Elements : Elements_Access := new Elements_Type (Last);
362 Elements.EA (Index_Type'First) := new Element_Type'(Left);
370 Elements.EA (Last) := new Element_Type'(Right);
373 Free (Elements.EA (Index_Type'First));
378 return (Controlled with Elements, Last, 0, 0);
386 overriding function "=" (Left, Right : Vector) return Boolean is
388 if Left'Address = Right'Address then
392 if Left.Last /= Right.Last then
396 for J in Index_Type'First .. Left.Last loop
397 if Left.Elements.EA (J) = null then
398 if Right.Elements.EA (J) /= null then
402 elsif Right.Elements.EA (J) = null then
405 elsif Left.Elements.EA (J).all /= Right.Elements.EA (J).all then
417 procedure Adjust (Container : in out Vector) is
419 if Container.Last = No_Index then
420 Container.Elements := null;
425 L : constant Index_Type := Container.Last;
426 E : Elements_Array renames
427 Container.Elements.EA (Index_Type'First .. L);
430 Container.Elements := null;
431 Container.Last := No_Index;
435 Container.Elements := new Elements_Type (L);
437 for I in E'Range loop
438 if E (I) /= null then
439 Container.Elements.EA (I) := new Element_Type'(E (I).all);
451 procedure Append (Container : in out Vector; New_Item : Vector) is
453 if Is_Empty (New_Item) then
457 if Container.Last = Index_Type'Last then
458 raise Constraint_Error with "vector is already at its maximum length";
468 (Container : in out Vector;
469 New_Item : Element_Type;
470 Count : Count_Type := 1)
477 if Container.Last = Index_Type'Last then
478 raise Constraint_Error with "vector is already at its maximum length";
492 function Capacity (Container : Vector) return Count_Type is
494 if Container.Elements = null then
498 return Container.Elements.EA'Length;
505 procedure Clear (Container : in out Vector) is
507 if Container.Busy > 0 then
508 raise Program_Error with
509 "attempt to tamper with elements (vector is busy)";
512 while Container.Last >= Index_Type'First loop
514 X : Element_Access := Container.Elements.EA (Container.Last);
516 Container.Elements.EA (Container.Last) := null;
517 Container.Last := Container.Last - 1;
529 Item : Element_Type) return Boolean
532 return Find_Index (Container, Item) /= No_Index;
540 (Container : in out Vector;
541 Index : Extended_Index;
542 Count : Count_Type := 1)
545 if Index < Index_Type'First then
546 raise Constraint_Error with "Index is out of range (too small)";
549 if Index > Container.Last then
550 if Index > Container.Last + 1 then
551 raise Constraint_Error with "Index is out of range (too large)";
561 if Container.Busy > 0 then
562 raise Program_Error with
563 "attempt to tamper with elements (vector is busy)";
567 Index_As_Int : constant Int := Int (Index);
568 Old_Last_As_Int : constant Int := Int (Container.Last);
570 Count1 : constant Int'Base := Int (Count);
571 Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
572 N : constant Int'Base := Int'Min (Count1, Count2);
574 J_As_Int : constant Int'Base := Index_As_Int + N;
575 E : Elements_Array renames Container.Elements.EA;
578 if J_As_Int > Old_Last_As_Int then
579 while Container.Last >= Index loop
581 K : constant Index_Type := Container.Last;
582 X : Element_Access := E (K);
586 Container.Last := K - 1;
593 J : constant Index_Type := Index_Type (J_As_Int);
595 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
596 New_Last : constant Index_Type :=
597 Index_Type (New_Last_As_Int);
600 for K in Index .. J - 1 loop
602 X : Element_Access := E (K);
609 E (Index .. New_Last) := E (J .. Container.Last);
610 Container.Last := New_Last;
617 (Container : in out Vector;
618 Position : in out Cursor;
619 Count : Count_Type := 1)
621 pragma Warnings (Off, Position);
624 if Position.Container = null then
625 raise Constraint_Error with "Position cursor has no element";
628 if Position.Container /= Container'Unrestricted_Access then
629 raise Program_Error with "Position cursor denotes wrong container";
632 if Position.Index > Container.Last then
633 raise Program_Error with "Position index is out of range";
636 Delete (Container, Position.Index, Count);
638 Position := No_Element;
645 procedure Delete_First
646 (Container : in out Vector;
647 Count : Count_Type := 1)
654 if Count >= Length (Container) then
659 Delete (Container, Index_Type'First, Count);
666 procedure Delete_Last
667 (Container : in out Vector;
668 Count : Count_Type := 1)
670 N : constant Count_Type := Length (Container);
679 if Container.Busy > 0 then
680 raise Program_Error with
681 "attempt to tamper with elements (vector is busy)";
685 E : Elements_Array renames Container.Elements.EA;
688 for Indx in 1 .. Count_Type'Min (Count, N) loop
690 J : constant Index_Type := Container.Last;
691 X : Element_Access := E (J);
695 Container.Last := J - 1;
708 Index : Index_Type) return Element_Type
711 if Index > Container.Last then
712 raise Constraint_Error with "Index is out of range";
716 EA : constant Element_Access := Container.Elements.EA (Index);
720 raise Constraint_Error with "element is empty";
727 function Element (Position : Cursor) return Element_Type is
729 if Position.Container = null then
730 raise Constraint_Error with "Position cursor has no element";
733 if Position.Index > Position.Container.Last then
734 raise Constraint_Error with "Position cursor is out of range";
738 EA : constant Element_Access :=
739 Position.Container.Elements.EA (Position.Index);
743 raise Constraint_Error with "element is empty";
754 procedure Finalize (Container : in out Vector) is
756 Clear (Container); -- Checks busy-bit
759 X : Elements_Access := Container.Elements;
761 Container.Elements := null;
773 Position : Cursor := No_Element) return Cursor
776 if Position.Container /= null then
777 if Position.Container /= Container'Unrestricted_Access then
778 raise Program_Error with "Position cursor denotes wrong container";
781 if Position.Index > Container.Last then
782 raise Program_Error with "Position index is out of range";
786 for J in Position.Index .. Container.Last loop
787 if Container.Elements.EA (J) /= null
788 and then Container.Elements.EA (J).all = Item
790 return (Container'Unchecked_Access, J);
804 Index : Index_Type := Index_Type'First) return Extended_Index
807 for Indx in Index .. Container.Last loop
808 if Container.Elements.EA (Indx) /= null
809 and then Container.Elements.EA (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 if Container.Last = No_Index then
838 raise Constraint_Error with "Container is empty";
842 EA : constant Element_Access :=
843 Container.Elements.EA (Index_Type'First);
847 raise Constraint_Error with "first element is empty";
858 function First_Index (Container : Vector) return Index_Type is
859 pragma Unreferenced (Container);
861 return Index_Type'First;
864 ---------------------
865 -- Generic_Sorting --
866 ---------------------
868 package body Generic_Sorting is
870 -----------------------
871 -- Local Subprograms --
872 -----------------------
874 function Is_Less (L, R : Element_Access) return Boolean;
875 pragma Inline (Is_Less);
881 function Is_Less (L, R : Element_Access) return Boolean is
888 return L.all < R.all;
896 function Is_Sorted (Container : Vector) return Boolean is
898 if Container.Last <= Index_Type'First then
903 E : Elements_Array renames Container.Elements.EA;
905 for I in Index_Type'First .. Container.Last - 1 loop
906 if Is_Less (E (I + 1), E (I)) then
919 procedure Merge (Target, Source : in out Vector) is
920 I, J : Index_Type'Base;
923 if Target.Last < Index_Type'First then
924 Move (Target => Target, Source => Source);
928 if Target'Address = Source'Address then
932 if Source.Last < Index_Type'First then
936 if Source.Busy > 0 then
937 raise Program_Error with
938 "attempt to tamper with elements (vector is busy)";
941 I := Target.Last; -- original value (before Set_Length)
942 Target.Set_Length (Length (Target) + Length (Source));
944 J := Target.Last; -- new value (after Set_Length)
945 while Source.Last >= Index_Type'First loop
947 (Source.Last <= Index_Type'First
949 (Source.Elements.EA (Source.Last),
950 Source.Elements.EA (Source.Last - 1))));
952 if I < Index_Type'First then
954 Src : Elements_Array renames
955 Source.Elements.EA (Index_Type'First .. Source.Last);
958 Target.Elements.EA (Index_Type'First .. J) := Src;
959 Src := (others => null);
962 Source.Last := No_Index;
967 (I <= Index_Type'First
969 (Target.Elements.EA (I),
970 Target.Elements.EA (I - 1))));
973 Src : Element_Access renames Source.Elements.EA (Source.Last);
974 Tgt : Element_Access renames Target.Elements.EA (I);
977 if Is_Less (Src, Tgt) then
978 Target.Elements.EA (J) := Tgt;
983 Target.Elements.EA (J) := Src;
985 Source.Last := Source.Last - 1;
997 procedure Sort (Container : in out Vector) is
999 procedure Sort is new Generic_Array_Sort
1000 (Index_Type => Index_Type,
1001 Element_Type => Element_Access,
1002 Array_Type => Elements_Array,
1005 -- Start of processing for Sort
1008 if Container.Last <= Index_Type'First then
1012 if Container.Lock > 0 then
1013 raise Program_Error with
1014 "attempt to tamper with cursors (vector is locked)";
1017 Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
1020 end Generic_Sorting;
1026 function Has_Element (Position : Cursor) return Boolean is
1028 if Position.Container = null then
1032 return Position.Index <= Position.Container.Last;
1040 (Container : in out Vector;
1041 Before : Extended_Index;
1042 New_Item : Element_Type;
1043 Count : Count_Type := 1)
1045 N : constant Int := Int (Count);
1047 First : constant Int := Int (Index_Type'First);
1048 New_Last_As_Int : Int'Base;
1049 New_Last : Index_Type;
1051 Max_Length : constant UInt := UInt (Count_Type'Last);
1053 Dst : Elements_Access;
1056 if Before < Index_Type'First then
1057 raise Constraint_Error with
1058 "Before index is out of range (too small)";
1061 if Before > Container.Last
1062 and then Before > Container.Last + 1
1064 raise Constraint_Error with
1065 "Before index is out of range (too large)";
1073 Old_Last_As_Int : constant Int := Int (Container.Last);
1076 if Old_Last_As_Int > Int'Last - N then
1077 raise Constraint_Error with "new length is out of range";
1080 New_Last_As_Int := Old_Last_As_Int + N;
1082 if New_Last_As_Int > Int (Index_Type'Last) then
1083 raise Constraint_Error with "new length is out of range";
1086 New_Length := UInt (New_Last_As_Int - First + 1);
1088 if New_Length > Max_Length then
1089 raise Constraint_Error with "new length is out of range";
1092 New_Last := Index_Type (New_Last_As_Int);
1095 if Container.Busy > 0 then
1096 raise Program_Error with
1097 "attempt to tamper with elements (vector is busy)";
1100 if Container.Elements = null then
1101 Container.Elements := new Elements_Type (New_Last);
1102 Container.Last := No_Index;
1104 for J in Container.Elements.EA'Range loop
1105 Container.Elements.EA (J) := new Element_Type'(New_Item);
1106 Container.Last := J;
1112 if New_Last <= Container.Elements.Last then
1114 E : Elements_Array renames Container.Elements.EA;
1117 if Before <= Container.Last then
1119 Index_As_Int : constant Int'Base :=
1120 Index_Type'Pos (Before) + N;
1122 Index : constant Index_Type := Index_Type (Index_As_Int);
1124 J : Index_Type'Base := Before;
1127 E (Index .. New_Last) := E (Before .. Container.Last);
1128 Container.Last := New_Last;
1130 while J < Index loop
1131 E (J) := new Element_Type'(New_Item);
1137 E (J .. Index - 1) := (others => null);
1142 for J in Before .. New_Last loop
1143 E (J) := new Element_Type'(New_Item);
1144 Container.Last := J;
1156 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1157 while C < New_Length loop
1158 if C > UInt'Last / 2 then
1166 if C > Max_Length then
1170 if Index_Type'First <= 0
1171 and then Index_Type'Last >= 0
1173 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1175 CC := UInt (Int (Index_Type'Last) - First + 1);
1183 Dst_Last : constant Index_Type :=
1184 Index_Type (First + UInt'Pos (C) - Int'(1));
1187 Dst := new Elements_Type (Dst_Last);
1191 if Before <= Container.Last then
1193 Index_As_Int : constant Int'Base :=
1194 Index_Type'Pos (Before) + N;
1196 Index : constant Index_Type := Index_Type (Index_As_Int);
1198 Src : Elements_Access := Container.Elements;
1201 Dst.EA (Index_Type'First .. Before - 1) :=
1202 Src.EA (Index_Type'First .. Before - 1);
1204 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1206 Container.Elements := Dst;
1207 Container.Last := New_Last;
1210 for J in Before .. Index - 1 loop
1211 Dst.EA (J) := new Element_Type'(New_Item);
1217 Src : Elements_Access := Container.Elements;
1220 Dst.EA (Index_Type'First .. Container.Last) :=
1221 Src.EA (Index_Type'First .. Container.Last);
1223 Container.Elements := Dst;
1226 for J in Before .. New_Last loop
1227 Dst.EA (J) := new Element_Type'(New_Item);
1228 Container.Last := J;
1235 (Container : in out Vector;
1236 Before : Extended_Index;
1239 N : constant Count_Type := Length (New_Item);
1242 if Before < Index_Type'First then
1243 raise Constraint_Error with
1244 "Before index is out of range (too small)";
1247 if Before > Container.Last
1248 and then Before > Container.Last + 1
1250 raise Constraint_Error with
1251 "Before index is out of range (too large)";
1258 Insert_Space (Container, Before, Count => N);
1261 Dst_Last_As_Int : constant Int'Base :=
1262 Int'Base (Before) + Int'Base (N) - 1;
1264 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1266 Dst : Elements_Array renames
1267 Container.Elements.EA (Before .. Dst_Last);
1269 Dst_Index : Index_Type'Base := Before - 1;
1272 if Container'Address /= New_Item'Address then
1274 subtype Src_Index_Subtype is Index_Type'Base range
1275 Index_Type'First .. New_Item.Last;
1277 Src : Elements_Array renames
1278 New_Item.Elements.EA (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);
1294 subtype Src_Index_Subtype is Index_Type'Base range
1295 Index_Type'First .. Before - 1;
1297 Src : Elements_Array renames
1298 Container.Elements.EA (Src_Index_Subtype);
1301 for Src_Index in Src'Range loop
1302 Dst_Index := Dst_Index + 1;
1304 if Src (Src_Index) /= null then
1305 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1310 if Dst_Last = Container.Last then
1315 subtype Src_Index_Subtype is Index_Type'Base range
1316 Dst_Last + 1 .. Container.Last;
1318 Src : Elements_Array renames
1319 Container.Elements.EA (Src_Index_Subtype);
1322 for Src_Index in Src'Range loop
1323 Dst_Index := Dst_Index + 1;
1325 if Src (Src_Index) /= null then
1326 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1334 (Container : in out Vector;
1338 Index : Index_Type'Base;
1341 if Before.Container /= null
1342 and then Before.Container /= Container'Unchecked_Access
1344 raise Program_Error with "Before cursor denotes wrong container";
1347 if Is_Empty (New_Item) then
1351 if Before.Container = null
1352 or else Before.Index > Container.Last
1354 if Container.Last = Index_Type'Last then
1355 raise Constraint_Error with
1356 "vector is already at its maximum length";
1359 Index := Container.Last + 1;
1362 Index := Before.Index;
1365 Insert (Container, Index, New_Item);
1369 (Container : in out Vector;
1372 Position : out Cursor)
1374 Index : Index_Type'Base;
1377 if Before.Container /= null
1378 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1380 raise Program_Error with "Before cursor denotes wrong container";
1383 if Is_Empty (New_Item) then
1384 if Before.Container = null
1385 or else Before.Index > Container.Last
1387 Position := No_Element;
1389 Position := (Container'Unchecked_Access, Before.Index);
1395 if Before.Container = null
1396 or else Before.Index > Container.Last
1398 if Container.Last = Index_Type'Last then
1399 raise Constraint_Error with
1400 "vector is already at its maximum length";
1403 Index := Container.Last + 1;
1406 Index := Before.Index;
1409 Insert (Container, Index, New_Item);
1411 Position := Cursor'(Container'Unchecked_Access, Index);
1415 (Container : in out Vector;
1417 New_Item : Element_Type;
1418 Count : Count_Type := 1)
1420 Index : Index_Type'Base;
1423 if Before.Container /= null
1424 and then Before.Container /= Container'Unchecked_Access
1426 raise Program_Error with "Before cursor denotes wrong container";
1433 if Before.Container = null
1434 or else Before.Index > Container.Last
1436 if Container.Last = Index_Type'Last then
1437 raise Constraint_Error with
1438 "vector is already at its maximum length";
1441 Index := Container.Last + 1;
1444 Index := Before.Index;
1447 Insert (Container, Index, New_Item, Count);
1451 (Container : in out Vector;
1453 New_Item : Element_Type;
1454 Position : out Cursor;
1455 Count : Count_Type := 1)
1457 Index : Index_Type'Base;
1460 if Before.Container /= null
1461 and then Before.Container /= Container'Unchecked_Access
1463 raise Program_Error with "Before cursor denotes wrong container";
1467 if Before.Container = null
1468 or else Before.Index > Container.Last
1470 Position := No_Element;
1472 Position := (Container'Unchecked_Access, Before.Index);
1478 if Before.Container = null
1479 or else Before.Index > Container.Last
1481 if Container.Last = Index_Type'Last then
1482 raise Constraint_Error with
1483 "vector is already at its maximum length";
1486 Index := Container.Last + 1;
1489 Index := Before.Index;
1492 Insert (Container, Index, New_Item, Count);
1494 Position := (Container'Unchecked_Access, Index);
1501 procedure Insert_Space
1502 (Container : in out Vector;
1503 Before : Extended_Index;
1504 Count : Count_Type := 1)
1506 N : constant Int := Int (Count);
1508 First : constant Int := Int (Index_Type'First);
1509 New_Last_As_Int : Int'Base;
1510 New_Last : Index_Type;
1512 Max_Length : constant UInt := UInt (Count_Type'Last);
1514 Dst : Elements_Access;
1517 if Before < Index_Type'First then
1518 raise Constraint_Error with
1519 "Before index is out of range (too small)";
1522 if Before > Container.Last
1523 and then Before > Container.Last + 1
1525 raise Constraint_Error with
1526 "Before index is out of range (too large)";
1534 Old_Last_As_Int : constant Int := Int (Container.Last);
1537 if Old_Last_As_Int > Int'Last - N then
1538 raise Constraint_Error with "new length is out of range";
1541 New_Last_As_Int := Old_Last_As_Int + N;
1543 if New_Last_As_Int > Int (Index_Type'Last) then
1544 raise Constraint_Error with "new length is out of range";
1547 New_Length := UInt (New_Last_As_Int - First + 1);
1549 if New_Length > Max_Length then
1550 raise Constraint_Error with "new length is out of range";
1553 New_Last := Index_Type (New_Last_As_Int);
1556 if Container.Busy > 0 then
1557 raise Program_Error with
1558 "attempt to tamper with elements (vector is busy)";
1561 if Container.Elements = null then
1562 Container.Elements := new Elements_Type (New_Last);
1563 Container.Last := New_Last;
1567 if New_Last <= Container.Elements.Last then
1569 E : Elements_Array renames Container.Elements.EA;
1572 if Before <= Container.Last then
1574 Index_As_Int : constant Int'Base :=
1575 Index_Type'Pos (Before) + N;
1577 Index : constant Index_Type := Index_Type (Index_As_Int);
1580 E (Index .. New_Last) := E (Before .. Container.Last);
1581 E (Before .. Index - 1) := (others => null);
1586 Container.Last := New_Last;
1594 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1595 while C < New_Length loop
1596 if C > UInt'Last / 2 then
1604 if C > Max_Length then
1608 if Index_Type'First <= 0
1609 and then Index_Type'Last >= 0
1611 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1613 CC := UInt (Int (Index_Type'Last) - First + 1);
1621 Dst_Last : constant Index_Type :=
1622 Index_Type (First + UInt'Pos (C) - 1);
1625 Dst := new Elements_Type (Dst_Last);
1630 Src : Elements_Access := Container.Elements;
1633 if Before <= Container.Last then
1635 Index_As_Int : constant Int'Base :=
1636 Index_Type'Pos (Before) + N;
1638 Index : constant Index_Type := Index_Type (Index_As_Int);
1641 Dst.EA (Index_Type'First .. Before - 1) :=
1642 Src.EA (Index_Type'First .. Before - 1);
1644 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1648 Dst.EA (Index_Type'First .. Container.Last) :=
1649 Src.EA (Index_Type'First .. Container.Last);
1652 Container.Elements := Dst;
1653 Container.Last := New_Last;
1658 procedure Insert_Space
1659 (Container : in out Vector;
1661 Position : out Cursor;
1662 Count : Count_Type := 1)
1664 Index : Index_Type'Base;
1667 if Before.Container /= null
1668 and then Before.Container /= Container'Unchecked_Access
1670 raise Program_Error with "Before cursor denotes wrong container";
1674 if Before.Container = null
1675 or else Before.Index > Container.Last
1677 Position := No_Element;
1679 Position := (Container'Unchecked_Access, Before.Index);
1685 if Before.Container = null
1686 or else Before.Index > Container.Last
1688 if Container.Last = Index_Type'Last then
1689 raise Constraint_Error with
1690 "vector is already at its maximum length";
1693 Index := Container.Last + 1;
1696 Index := Before.Index;
1699 Insert_Space (Container, Index, Count);
1701 Position := Cursor'(Container'Unchecked_Access, Index);
1708 function Is_Empty (Container : Vector) return Boolean is
1710 return Container.Last < Index_Type'First;
1718 (Container : Vector;
1719 Process : not null access procedure (Position : Cursor))
1721 V : Vector renames Container'Unrestricted_Access.all;
1722 B : Natural renames V.Busy;
1728 for Indx in Index_Type'First .. Container.Last loop
1729 Process (Cursor'(Container'Unchecked_Access, Indx));
1744 function Last (Container : Vector) return Cursor is
1746 if Is_Empty (Container) then
1750 return (Container'Unchecked_Access, Container.Last);
1757 function Last_Element (Container : Vector) return Element_Type is
1759 if Container.Last = No_Index then
1760 raise Constraint_Error with "Container is empty";
1764 EA : constant Element_Access :=
1765 Container.Elements.EA (Container.Last);
1769 raise Constraint_Error with "last element is empty";
1780 function Last_Index (Container : Vector) return Extended_Index is
1782 return Container.Last;
1789 function Length (Container : Vector) return Count_Type is
1790 L : constant Int := Int (Container.Last);
1791 F : constant Int := Int (Index_Type'First);
1792 N : constant Int'Base := L - F + 1;
1795 return Count_Type (N);
1803 (Target : in out Vector;
1804 Source : in out Vector)
1807 if Target'Address = Source'Address then
1811 if Source.Busy > 0 then
1812 raise Program_Error with
1813 "attempt to tamper with elements (Source is busy)";
1816 Clear (Target); -- Checks busy-bit
1819 Target_Elements : constant Elements_Access := Target.Elements;
1821 Target.Elements := Source.Elements;
1822 Source.Elements := Target_Elements;
1825 Target.Last := Source.Last;
1826 Source.Last := No_Index;
1833 function Next (Position : Cursor) return Cursor is
1835 if Position.Container = null then
1839 if Position.Index < Position.Container.Last then
1840 return (Position.Container, Position.Index + 1);
1850 procedure Next (Position : in out Cursor) is
1852 if Position.Container = null then
1856 if Position.Index < Position.Container.Last then
1857 Position.Index := Position.Index + 1;
1859 Position := No_Element;
1867 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1869 Insert (Container, Index_Type'First, New_Item);
1873 (Container : in out Vector;
1874 New_Item : Element_Type;
1875 Count : Count_Type := 1)
1888 procedure Previous (Position : in out Cursor) is
1890 if Position.Container = null then
1894 if Position.Index > Index_Type'First then
1895 Position.Index := Position.Index - 1;
1897 Position := No_Element;
1901 function Previous (Position : Cursor) return Cursor is
1903 if Position.Container = null then
1907 if Position.Index > Index_Type'First then
1908 return (Position.Container, Position.Index - 1);
1918 procedure Query_Element
1919 (Container : Vector;
1921 Process : not null access procedure (Element : Element_Type))
1923 V : Vector renames Container'Unrestricted_Access.all;
1924 B : Natural renames V.Busy;
1925 L : Natural renames V.Lock;
1928 if Index > Container.Last then
1929 raise Constraint_Error with "Index is out of range";
1932 if V.Elements.EA (Index) = null then
1933 raise Constraint_Error with "element is null";
1940 Process (V.Elements.EA (Index).all);
1952 procedure Query_Element
1954 Process : not null access procedure (Element : Element_Type))
1957 if Position.Container = null then
1958 raise Constraint_Error with "Position cursor has no element";
1961 Query_Element (Position.Container.all, Position.Index, Process);
1969 (Stream : not null access Root_Stream_Type'Class;
1970 Container : out Vector)
1972 Length : Count_Type'Base;
1973 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1980 Count_Type'Base'Read (Stream, Length);
1982 if Length > Capacity (Container) then
1983 Reserve_Capacity (Container, Capacity => Length);
1986 for J in Count_Type range 1 .. Length loop
1989 Boolean'Read (Stream, B);
1992 Container.Elements.EA (Last) :=
1993 new Element_Type'(Element_Type'Input (Stream));
1996 Container.Last := Last;
2001 (Stream : not null access Root_Stream_Type'Class;
2002 Position : out Cursor)
2005 raise Program_Error with "attempt to stream vector cursor";
2008 ---------------------
2009 -- Replace_Element --
2010 ---------------------
2012 procedure Replace_Element
2013 (Container : in out Vector;
2015 New_Item : Element_Type)
2018 if Index > Container.Last then
2019 raise Constraint_Error with "Index is out of range";
2022 if Container.Lock > 0 then
2023 raise Program_Error with
2024 "attempt to tamper with cursors (vector is locked)";
2028 X : Element_Access := Container.Elements.EA (Index);
2030 Container.Elements.EA (Index) := new Element_Type'(New_Item);
2033 end Replace_Element;
2035 procedure Replace_Element
2036 (Container : in out Vector;
2038 New_Item : Element_Type)
2041 if Position.Container = null then
2042 raise Constraint_Error with "Position cursor has no element";
2045 if Position.Container /= Container'Unrestricted_Access then
2046 raise Program_Error with "Position cursor denotes wrong container";
2049 if Position.Index > Container.Last then
2050 raise Constraint_Error with "Position cursor is out of range";
2053 if Container.Lock > 0 then
2054 raise Program_Error with
2055 "attempt to tamper with cursors (vector is locked)";
2059 X : Element_Access := Container.Elements.EA (Position.Index);
2061 Container.Elements.EA (Position.Index) := new Element_Type'(New_Item);
2064 end Replace_Element;
2066 ----------------------
2067 -- Reserve_Capacity --
2068 ----------------------
2070 procedure Reserve_Capacity
2071 (Container : in out Vector;
2072 Capacity : Count_Type)
2074 N : constant Count_Type := Length (Container);
2077 if Capacity = 0 then
2080 X : Elements_Access := Container.Elements;
2082 Container.Elements := null;
2086 elsif N < Container.Elements.EA'Length then
2087 if Container.Busy > 0 then
2088 raise Program_Error with
2089 "attempt to tamper with elements (vector is busy)";
2093 subtype Array_Index_Subtype is Index_Type'Base range
2094 Index_Type'First .. Container.Last;
2096 Src : Elements_Array renames
2097 Container.Elements.EA (Array_Index_Subtype);
2099 X : Elements_Access := Container.Elements;
2102 Container.Elements := new Elements_Type'(Container.Last, Src);
2110 if Container.Elements = null then
2112 Last_As_Int : constant Int'Base :=
2113 Int (Index_Type'First) + Int (Capacity) - 1;
2116 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2117 raise Constraint_Error with "new length is out of range";
2121 Last : constant Index_Type := Index_Type (Last_As_Int);
2124 Container.Elements := new Elements_Type (Last);
2131 if Capacity <= N then
2132 if N < Container.Elements.EA'Length then
2133 if Container.Busy > 0 then
2134 raise Program_Error with
2135 "attempt to tamper with elements (vector is busy)";
2139 subtype Array_Index_Subtype is Index_Type'Base range
2140 Index_Type'First .. Container.Last;
2142 Src : Elements_Array renames
2143 Container.Elements.EA (Array_Index_Subtype);
2145 X : Elements_Access := Container.Elements;
2148 Container.Elements := new Elements_Type'(Container.Last, Src);
2156 if Capacity = Container.Elements.EA'Length then
2160 if Container.Busy > 0 then
2161 raise Program_Error with
2162 "attempt to tamper with elements (vector is busy)";
2166 Last_As_Int : constant Int'Base :=
2167 Int (Index_Type'First) + Int (Capacity) - 1;
2170 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2171 raise Constraint_Error with "new length is out of range";
2175 Last : constant Index_Type := Index_Type (Last_As_Int);
2176 X : Elements_Access := Container.Elements;
2178 subtype Index_Subtype is Index_Type'Base range
2179 Index_Type'First .. Container.Last;
2182 Container.Elements := new Elements_Type (Last);
2185 Src : Elements_Array renames
2186 X.EA (Index_Subtype);
2188 Tgt : Elements_Array renames
2189 Container.Elements.EA (Index_Subtype);
2198 end Reserve_Capacity;
2200 ----------------------
2201 -- Reverse_Elements --
2202 ----------------------
2204 procedure Reverse_Elements (Container : in out Vector) is
2206 if Container.Length <= 1 then
2210 if Container.Lock > 0 then
2211 raise Program_Error with
2212 "attempt to tamper with cursors (vector is locked)";
2218 E : Elements_Array renames Container.Elements.EA;
2221 I := Index_Type'First;
2222 J := Container.Last;
2225 EI : constant Element_Access := E (I);
2236 end Reverse_Elements;
2242 function Reverse_Find
2243 (Container : Vector;
2244 Item : Element_Type;
2245 Position : Cursor := No_Element) return Cursor
2247 Last : Index_Type'Base;
2250 if Position.Container /= null
2251 and then Position.Container /= Container'Unchecked_Access
2253 raise Program_Error with "Position cursor denotes wrong container";
2256 if Position.Container = null
2257 or else Position.Index > Container.Last
2259 Last := Container.Last;
2261 Last := Position.Index;
2264 for Indx in reverse Index_Type'First .. Last loop
2265 if Container.Elements.EA (Indx) /= null
2266 and then Container.Elements.EA (Indx).all = Item
2268 return (Container'Unchecked_Access, Indx);
2275 ------------------------
2276 -- Reverse_Find_Index --
2277 ------------------------
2279 function Reverse_Find_Index
2280 (Container : Vector;
2281 Item : Element_Type;
2282 Index : Index_Type := Index_Type'Last) return Extended_Index
2284 Last : constant Index_Type'Base :=
2285 (if Index > Container.Last then Container.Last else Index);
2287 for Indx in reverse Index_Type'First .. Last loop
2288 if Container.Elements.EA (Indx) /= null
2289 and then Container.Elements.EA (Indx).all = Item
2296 end Reverse_Find_Index;
2298 ---------------------
2299 -- Reverse_Iterate --
2300 ---------------------
2302 procedure Reverse_Iterate
2303 (Container : Vector;
2304 Process : not null access procedure (Position : Cursor))
2306 V : Vector renames Container'Unrestricted_Access.all;
2307 B : Natural renames V.Busy;
2313 for Indx in reverse Index_Type'First .. Container.Last loop
2314 Process (Cursor'(Container'Unchecked_Access, Indx));
2323 end Reverse_Iterate;
2329 procedure Set_Length
2330 (Container : in out Vector;
2331 Length : Count_Type)
2333 N : constant Count_Type := Indefinite_Vectors.Length (Container);
2340 if Container.Busy > 0 then
2341 raise Program_Error with
2342 "attempt to tamper with elements (vector is busy)";
2346 for Index in 1 .. N - Length loop
2348 J : constant Index_Type := Container.Last;
2349 X : Element_Access := Container.Elements.EA (J);
2352 Container.Elements.EA (J) := null;
2353 Container.Last := J - 1;
2361 if Length > Capacity (Container) then
2362 Reserve_Capacity (Container, Capacity => Length);
2366 Last_As_Int : constant Int'Base :=
2367 Int (Index_Type'First) + Int (Length) - 1;
2370 Container.Last := Index_Type (Last_As_Int);
2379 (Container : in out Vector;
2383 if I > Container.Last then
2384 raise Constraint_Error with "I index is out of range";
2387 if J > Container.Last then
2388 raise Constraint_Error with "J index is out of range";
2395 if Container.Lock > 0 then
2396 raise Program_Error with
2397 "attempt to tamper with cursors (vector is locked)";
2401 EI : Element_Access renames Container.Elements.EA (I);
2402 EJ : Element_Access renames Container.Elements.EA (J);
2404 EI_Copy : constant Element_Access := EI;
2413 (Container : in out Vector;
2417 if I.Container = null then
2418 raise Constraint_Error with "I cursor has no element";
2421 if J.Container = null then
2422 raise Constraint_Error with "J cursor has no element";
2425 if I.Container /= Container'Unrestricted_Access then
2426 raise Program_Error with "I cursor denotes wrong container";
2429 if J.Container /= Container'Unrestricted_Access then
2430 raise Program_Error with "J cursor denotes wrong container";
2433 Swap (Container, I.Index, J.Index);
2441 (Container : Vector;
2442 Index : Extended_Index) return Cursor
2445 if Index not in Index_Type'First .. Container.Last then
2449 return Cursor'(Container'Unchecked_Access, Index);
2456 function To_Index (Position : Cursor) return Extended_Index is
2458 if Position.Container = null then
2462 if Position.Index <= Position.Container.Last then
2463 return Position.Index;
2473 function To_Vector (Length : Count_Type) return Vector is
2476 return Empty_Vector;
2480 First : constant Int := Int (Index_Type'First);
2481 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2483 Elements : Elements_Access;
2486 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2487 raise Constraint_Error with "Length is out of range";
2490 Last := Index_Type (Last_As_Int);
2491 Elements := new Elements_Type (Last);
2493 return (Controlled with Elements, Last, 0, 0);
2498 (New_Item : Element_Type;
2499 Length : Count_Type) return Vector
2503 return Empty_Vector;
2507 First : constant Int := Int (Index_Type'First);
2508 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2509 Last : Index_Type'Base;
2510 Elements : Elements_Access;
2513 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2514 raise Constraint_Error with "Length is out of range";
2517 Last := Index_Type (Last_As_Int);
2518 Elements := new Elements_Type (Last);
2520 Last := Index_Type'First;
2524 Elements.EA (Last) := new Element_Type'(New_Item);
2525 exit when Last = Elements.Last;
2531 for J in Index_Type'First .. Last - 1 loop
2532 Free (Elements.EA (J));
2539 return (Controlled with Elements, Last, 0, 0);
2543 --------------------
2544 -- Update_Element --
2545 --------------------
2547 procedure Update_Element
2548 (Container : in out Vector;
2550 Process : not null access procedure (Element : in out Element_Type))
2552 B : Natural renames Container.Busy;
2553 L : Natural renames Container.Lock;
2556 if Index > Container.Last then
2557 raise Constraint_Error with "Index is out of range";
2560 if Container.Elements.EA (Index) = null then
2561 raise Constraint_Error with "element is null";
2568 Process (Container.Elements.EA (Index).all);
2580 procedure Update_Element
2581 (Container : in out Vector;
2583 Process : not null access procedure (Element : in out Element_Type))
2586 if Position.Container = null then
2587 raise Constraint_Error with "Position cursor has no element";
2590 if Position.Container /= Container'Unrestricted_Access then
2591 raise Program_Error with "Position cursor denotes wrong container";
2594 Update_Element (Container, Position.Index, Process);
2602 (Stream : not null access Root_Stream_Type'Class;
2605 N : constant Count_Type := Length (Container);
2608 Count_Type'Base'Write (Stream, N);
2615 E : Elements_Array renames Container.Elements.EA;
2618 for Indx in Index_Type'First .. Container.Last loop
2619 if E (Indx) = null then
2620 Boolean'Write (Stream, False);
2622 Boolean'Write (Stream, True);
2623 Element_Type'Output (Stream, E (Indx).all);
2630 (Stream : not null access Root_Stream_Type'Class;
2634 raise Program_Error with "attempt to stream vector cursor";
2637 end Ada.Containers.Indefinite_Vectors;