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-2008, 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
29 -- This unit has originally being developed by Matthew J Heaney. --
30 ------------------------------------------------------------------------------
32 with Ada.Containers.Generic_Array_Sort;
33 with Ada.Unchecked_Deallocation;
34 with System; use type System.Address;
36 package body Ada.Containers.Indefinite_Vectors is
38 type Int is range System.Min_Int .. System.Max_Int;
39 type UInt is mod System.Max_Binary_Modulus;
42 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
45 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
51 function "&" (Left, Right : Vector) return Vector is
52 LN : constant Count_Type := Length (Left);
53 RN : constant Count_Type := Length (Right);
62 RE : Elements_Array renames
63 Right.Elements.EA (Index_Type'First .. Right.Last);
65 Elements : Elements_Access :=
66 new Elements_Type (Right.Last);
69 for I in Elements.EA'Range loop
71 if RE (I) /= null then
72 Elements.EA (I) := new Element_Type'(RE (I).all);
77 for J in Index_Type'First .. I - 1 loop
78 Free (Elements.EA (J));
86 return (Controlled with Elements, Right.Last, 0, 0);
93 LE : Elements_Array renames
94 Left.Elements.EA (Index_Type'First .. Left.Last);
96 Elements : Elements_Access :=
97 new Elements_Type (Left.Last);
100 for I in Elements.EA'Range loop
102 if LE (I) /= null then
103 Elements.EA (I) := new Element_Type'(LE (I).all);
108 for J in Index_Type'First .. I - 1 loop
109 Free (Elements.EA (J));
117 return (Controlled with Elements, Left.Last, 0, 0);
122 N : constant Int'Base := Int (LN) + Int (RN);
123 Last_As_Int : Int'Base;
126 if Int (No_Index) > Int'Last - N then
127 raise Constraint_Error with "new length is out of range";
130 Last_As_Int := Int (No_Index) + N;
132 if Last_As_Int > Int (Index_Type'Last) then
133 raise Constraint_Error with "new length is out of range";
137 Last : constant Index_Type := Index_Type (Last_As_Int);
139 LE : Elements_Array renames
140 Left.Elements.EA (Index_Type'First .. Left.Last);
142 RE : Elements_Array renames
143 Right.Elements.EA (Index_Type'First .. Right.Last);
145 Elements : Elements_Access := new Elements_Type (Last);
147 I : Index_Type'Base := No_Index;
150 for LI in LE'Range loop
154 if LE (LI) /= null then
155 Elements.EA (I) := new Element_Type'(LE (LI).all);
160 for J in Index_Type'First .. I - 1 loop
161 Free (Elements.EA (J));
169 for RI in RE'Range loop
173 if RE (RI) /= null then
174 Elements.EA (I) := new Element_Type'(RE (RI).all);
179 for J in Index_Type'First .. I - 1 loop
180 Free (Elements.EA (J));
188 return (Controlled with Elements, Last, 0, 0);
193 function "&" (Left : Vector; Right : Element_Type) return Vector is
194 LN : constant Count_Type := Length (Left);
199 Elements : Elements_Access := new Elements_Type (Index_Type'First);
203 Elements.EA (Index_Type'First) := new Element_Type'(Right);
210 return (Controlled with Elements, Index_Type'First, 0, 0);
215 Last_As_Int : Int'Base;
218 if Int (Index_Type'First) > Int'Last - Int (LN) then
219 raise Constraint_Error with "new length is out of range";
222 Last_As_Int := Int (Index_Type'First) + Int (LN);
224 if Last_As_Int > Int (Index_Type'Last) then
225 raise Constraint_Error with "new length is out of range";
229 Last : constant Index_Type := Index_Type (Last_As_Int);
231 LE : Elements_Array renames
232 Left.Elements.EA (Index_Type'First .. Left.Last);
234 Elements : Elements_Access :=
235 new Elements_Type (Last);
238 for I in LE'Range loop
240 if LE (I) /= null then
241 Elements.EA (I) := new Element_Type'(LE (I).all);
246 for J in Index_Type'First .. I - 1 loop
247 Free (Elements.EA (J));
256 Elements.EA (Last) := new Element_Type'(Right);
260 for J in Index_Type'First .. Last - 1 loop
261 Free (Elements.EA (J));
268 return (Controlled with Elements, Last, 0, 0);
273 function "&" (Left : Element_Type; Right : Vector) return Vector is
274 RN : constant Count_Type := Length (Right);
279 Elements : Elements_Access := new Elements_Type (Index_Type'First);
283 Elements.EA (Index_Type'First) := new Element_Type'(Left);
290 return (Controlled with Elements, Index_Type'First, 0, 0);
295 Last_As_Int : Int'Base;
298 if Int (Index_Type'First) > Int'Last - Int (RN) then
299 raise Constraint_Error with "new length is out of range";
302 Last_As_Int := Int (Index_Type'First) + Int (RN);
304 if Last_As_Int > Int (Index_Type'Last) then
305 raise Constraint_Error with "new length is out of range";
309 Last : constant Index_Type := Index_Type (Last_As_Int);
311 RE : Elements_Array renames
312 Right.Elements.EA (Index_Type'First .. Right.Last);
314 Elements : Elements_Access :=
315 new Elements_Type (Last);
317 I : Index_Type'Base := Index_Type'First;
321 Elements.EA (I) := new Element_Type'(Left);
328 for RI in RE'Range loop
332 if RE (RI) /= null then
333 Elements.EA (I) := new Element_Type'(RE (RI).all);
338 for J in Index_Type'First .. I - 1 loop
339 Free (Elements.EA (J));
347 return (Controlled with Elements, Last, 0, 0);
352 function "&" (Left, Right : Element_Type) return Vector is
354 if Index_Type'First >= Index_Type'Last then
355 raise Constraint_Error with "new length is out of range";
359 Last : constant Index_Type := Index_Type'First + 1;
360 Elements : Elements_Access := new Elements_Type (Last);
364 Elements.EA (Index_Type'First) := new Element_Type'(Left);
372 Elements.EA (Last) := new Element_Type'(Right);
375 Free (Elements.EA (Index_Type'First));
380 return (Controlled with Elements, Last, 0, 0);
388 function "=" (Left, Right : Vector) return Boolean is
390 if Left'Address = Right'Address then
394 if Left.Last /= Right.Last then
398 for J in Index_Type'First .. Left.Last loop
399 if Left.Elements.EA (J) = null then
400 if Right.Elements.EA (J) /= null then
404 elsif Right.Elements.EA (J) = null then
407 elsif Left.Elements.EA (J).all /= Right.Elements.EA (J).all then
419 procedure Adjust (Container : in out Vector) is
421 if Container.Last = No_Index then
422 Container.Elements := null;
427 L : constant Index_Type := Container.Last;
428 E : Elements_Array renames
429 Container.Elements.EA (Index_Type'First .. L);
432 Container.Elements := null;
433 Container.Last := No_Index;
437 Container.Elements := new Elements_Type (L);
439 for I in E'Range loop
440 if E (I) /= null then
441 Container.Elements.EA (I) := new Element_Type'(E (I).all);
453 procedure Append (Container : in out Vector; New_Item : Vector) is
455 if Is_Empty (New_Item) then
459 if Container.Last = Index_Type'Last then
460 raise Constraint_Error with "vector is already at its maximum length";
470 (Container : in out Vector;
471 New_Item : Element_Type;
472 Count : Count_Type := 1)
479 if Container.Last = Index_Type'Last then
480 raise Constraint_Error with "vector is already at its maximum length";
494 function Capacity (Container : Vector) return Count_Type is
496 if Container.Elements = null then
500 return Container.Elements.EA'Length;
507 procedure Clear (Container : in out Vector) is
509 if Container.Busy > 0 then
510 raise Program_Error with
511 "attempt to tamper with elements (vector is busy)";
514 while Container.Last >= Index_Type'First loop
516 X : Element_Access := Container.Elements.EA (Container.Last);
518 Container.Elements.EA (Container.Last) := null;
519 Container.Last := Container.Last - 1;
531 Item : Element_Type) return Boolean
534 return Find_Index (Container, Item) /= No_Index;
542 (Container : in out Vector;
543 Index : Extended_Index;
544 Count : Count_Type := 1)
547 if Index < Index_Type'First then
548 raise Constraint_Error with "Index is out of range (too small)";
551 if Index > Container.Last then
552 if Index > Container.Last + 1 then
553 raise Constraint_Error with "Index is out of range (too large)";
563 if Container.Busy > 0 then
564 raise Program_Error with
565 "attempt to tamper with elements (vector is busy)";
569 Index_As_Int : constant Int := Int (Index);
570 Old_Last_As_Int : constant Int := Int (Container.Last);
572 Count1 : constant Int'Base := Int (Count);
573 Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
574 N : constant Int'Base := Int'Min (Count1, Count2);
576 J_As_Int : constant Int'Base := Index_As_Int + N;
577 E : Elements_Array renames Container.Elements.EA;
580 if J_As_Int > Old_Last_As_Int then
581 while Container.Last >= Index loop
583 K : constant Index_Type := Container.Last;
584 X : Element_Access := E (K);
588 Container.Last := K - 1;
595 J : constant Index_Type := Index_Type (J_As_Int);
597 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
598 New_Last : constant Index_Type :=
599 Index_Type (New_Last_As_Int);
602 for K in Index .. J - 1 loop
604 X : Element_Access := E (K);
611 E (Index .. New_Last) := E (J .. Container.Last);
612 Container.Last := New_Last;
619 (Container : in out Vector;
620 Position : in out Cursor;
621 Count : Count_Type := 1)
623 pragma Warnings (Off, Position);
626 if Position.Container = null then
627 raise Constraint_Error with "Position cursor has no element";
630 if Position.Container /= Container'Unrestricted_Access then
631 raise Program_Error with "Position cursor denotes wrong container";
634 if Position.Index > Container.Last then
635 raise Program_Error with "Position index is out of range";
638 Delete (Container, Position.Index, Count);
640 Position := No_Element;
647 procedure Delete_First
648 (Container : in out Vector;
649 Count : Count_Type := 1)
656 if Count >= Length (Container) then
661 Delete (Container, Index_Type'First, Count);
668 procedure Delete_Last
669 (Container : in out Vector;
670 Count : Count_Type := 1)
672 N : constant Count_Type := Length (Container);
681 if Container.Busy > 0 then
682 raise Program_Error with
683 "attempt to tamper with elements (vector is busy)";
687 E : Elements_Array renames Container.Elements.EA;
690 for Indx in 1 .. Count_Type'Min (Count, N) loop
692 J : constant Index_Type := Container.Last;
693 X : Element_Access := E (J);
697 Container.Last := J - 1;
710 Index : Index_Type) return Element_Type
713 if Index > Container.Last then
714 raise Constraint_Error with "Index is out of range";
718 EA : constant Element_Access := Container.Elements.EA (Index);
722 raise Constraint_Error with "element is empty";
729 function Element (Position : Cursor) return Element_Type is
731 if Position.Container = null then
732 raise Constraint_Error with "Position cursor has no element";
735 if Position.Index > Position.Container.Last then
736 raise Constraint_Error with "Position cursor is out of range";
740 EA : constant Element_Access :=
741 Position.Container.Elements.EA (Position.Index);
745 raise Constraint_Error with "element is empty";
756 procedure Finalize (Container : in out Vector) is
758 Clear (Container); -- Checks busy-bit
761 X : Elements_Access := Container.Elements;
763 Container.Elements := null;
775 Position : Cursor := No_Element) return Cursor
778 if Position.Container /= null then
779 if Position.Container /= Container'Unrestricted_Access then
780 raise Program_Error with "Position cursor denotes wrong container";
783 if Position.Index > Container.Last then
784 raise Program_Error with "Position index is out of range";
788 for J in Position.Index .. Container.Last loop
789 if Container.Elements.EA (J) /= null
790 and then Container.Elements.EA (J).all = Item
792 return (Container'Unchecked_Access, J);
806 Index : Index_Type := Index_Type'First) return Extended_Index
809 for Indx in Index .. Container.Last loop
810 if Container.Elements.EA (Indx) /= null
811 and then Container.Elements.EA (Indx).all = Item
824 function First (Container : Vector) return Cursor is
826 if Is_Empty (Container) then
830 return (Container'Unchecked_Access, Index_Type'First);
837 function First_Element (Container : Vector) return Element_Type is
839 if Container.Last = No_Index then
840 raise Constraint_Error with "Container is empty";
844 EA : constant Element_Access :=
845 Container.Elements.EA (Index_Type'First);
849 raise Constraint_Error with "first element is empty";
860 function First_Index (Container : Vector) return Index_Type is
861 pragma Unreferenced (Container);
863 return Index_Type'First;
866 ---------------------
867 -- Generic_Sorting --
868 ---------------------
870 package body Generic_Sorting is
872 -----------------------
873 -- Local Subprograms --
874 -----------------------
876 function Is_Less (L, R : Element_Access) return Boolean;
877 pragma Inline (Is_Less);
883 function Is_Less (L, R : Element_Access) return Boolean is
890 return L.all < R.all;
898 function Is_Sorted (Container : Vector) return Boolean is
900 if Container.Last <= Index_Type'First then
905 E : Elements_Array renames Container.Elements.EA;
907 for I in Index_Type'First .. Container.Last - 1 loop
908 if Is_Less (E (I + 1), E (I)) then
921 procedure Merge (Target, Source : in out Vector) is
922 I, J : Index_Type'Base;
925 if Target.Last < Index_Type'First then
926 Move (Target => Target, Source => Source);
930 if Target'Address = Source'Address then
934 if Source.Last < Index_Type'First then
938 if Source.Busy > 0 then
939 raise Program_Error with
940 "attempt to tamper with elements (vector is busy)";
943 I := Target.Last; -- original value (before Set_Length)
944 Target.Set_Length (Length (Target) + Length (Source));
946 J := Target.Last; -- new value (after Set_Length)
947 while Source.Last >= Index_Type'First loop
949 (Source.Last <= Index_Type'First
951 (Source.Elements.EA (Source.Last),
952 Source.Elements.EA (Source.Last - 1))));
954 if I < Index_Type'First then
956 Src : Elements_Array renames
957 Source.Elements.EA (Index_Type'First .. Source.Last);
960 Target.Elements.EA (Index_Type'First .. J) := Src;
961 Src := (others => null);
964 Source.Last := No_Index;
969 (I <= Index_Type'First
971 (Target.Elements.EA (I),
972 Target.Elements.EA (I - 1))));
975 Src : Element_Access renames Source.Elements.EA (Source.Last);
976 Tgt : Element_Access renames Target.Elements.EA (I);
979 if Is_Less (Src, Tgt) then
980 Target.Elements.EA (J) := Tgt;
985 Target.Elements.EA (J) := Src;
987 Source.Last := Source.Last - 1;
999 procedure Sort (Container : in out Vector)
1002 new Generic_Array_Sort
1003 (Index_Type => Index_Type,
1004 Element_Type => Element_Access,
1005 Array_Type => Elements_Array,
1008 -- Start of processing for Sort
1011 if Container.Last <= Index_Type'First then
1015 if Container.Lock > 0 then
1016 raise Program_Error with
1017 "attempt to tamper with cursors (vector is locked)";
1020 Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
1023 end Generic_Sorting;
1029 function Has_Element (Position : Cursor) return Boolean is
1031 if Position.Container = null then
1035 return Position.Index <= Position.Container.Last;
1043 (Container : in out Vector;
1044 Before : Extended_Index;
1045 New_Item : Element_Type;
1046 Count : Count_Type := 1)
1048 N : constant Int := Int (Count);
1050 First : constant Int := Int (Index_Type'First);
1051 New_Last_As_Int : Int'Base;
1052 New_Last : Index_Type;
1054 Max_Length : constant UInt := UInt (Count_Type'Last);
1056 Dst : Elements_Access;
1059 if Before < Index_Type'First then
1060 raise Constraint_Error with
1061 "Before index is out of range (too small)";
1064 if Before > Container.Last
1065 and then Before > Container.Last + 1
1067 raise Constraint_Error with
1068 "Before index is out of range (too large)";
1076 Old_Last_As_Int : constant Int := Int (Container.Last);
1079 if Old_Last_As_Int > Int'Last - N then
1080 raise Constraint_Error with "new length is out of range";
1083 New_Last_As_Int := Old_Last_As_Int + N;
1085 if New_Last_As_Int > Int (Index_Type'Last) then
1086 raise Constraint_Error with "new length is out of range";
1089 New_Length := UInt (New_Last_As_Int - First + 1);
1091 if New_Length > Max_Length then
1092 raise Constraint_Error with "new length is out of range";
1095 New_Last := Index_Type (New_Last_As_Int);
1098 if Container.Busy > 0 then
1099 raise Program_Error with
1100 "attempt to tamper with elements (vector is busy)";
1103 if Container.Elements = null then
1104 Container.Elements := new Elements_Type (New_Last);
1105 Container.Last := No_Index;
1107 for J in Container.Elements.EA'Range loop
1108 Container.Elements.EA (J) := new Element_Type'(New_Item);
1109 Container.Last := J;
1115 if New_Last <= Container.Elements.Last then
1117 E : Elements_Array renames Container.Elements.EA;
1120 if Before <= Container.Last then
1122 Index_As_Int : constant Int'Base :=
1123 Index_Type'Pos (Before) + N;
1125 Index : constant Index_Type := Index_Type (Index_As_Int);
1127 J : Index_Type'Base := Before;
1130 E (Index .. New_Last) := E (Before .. Container.Last);
1131 Container.Last := New_Last;
1133 while J < Index loop
1134 E (J) := new Element_Type'(New_Item);
1140 E (J .. Index - 1) := (others => null);
1145 for J in Before .. New_Last loop
1146 E (J) := new Element_Type'(New_Item);
1147 Container.Last := J;
1159 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1160 while C < New_Length loop
1161 if C > UInt'Last / 2 then
1169 if C > Max_Length then
1173 if Index_Type'First <= 0
1174 and then Index_Type'Last >= 0
1176 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1179 CC := UInt (Int (Index_Type'Last) - First + 1);
1187 Dst_Last : constant Index_Type :=
1188 Index_Type (First + UInt'Pos (C) - Int'(1));
1191 Dst := new Elements_Type (Dst_Last);
1195 if Before <= Container.Last then
1197 Index_As_Int : constant Int'Base :=
1198 Index_Type'Pos (Before) + N;
1200 Index : constant Index_Type := Index_Type (Index_As_Int);
1202 Src : Elements_Access := Container.Elements;
1205 Dst.EA (Index_Type'First .. Before - 1) :=
1206 Src.EA (Index_Type'First .. Before - 1);
1208 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1210 Container.Elements := Dst;
1211 Container.Last := New_Last;
1214 for J in Before .. Index - 1 loop
1215 Dst.EA (J) := new Element_Type'(New_Item);
1221 Src : Elements_Access := Container.Elements;
1224 Dst.EA (Index_Type'First .. Container.Last) :=
1225 Src.EA (Index_Type'First .. Container.Last);
1227 Container.Elements := Dst;
1230 for J in Before .. New_Last loop
1231 Dst.EA (J) := new Element_Type'(New_Item);
1232 Container.Last := J;
1239 (Container : in out Vector;
1240 Before : Extended_Index;
1243 N : constant Count_Type := Length (New_Item);
1246 if Before < Index_Type'First then
1247 raise Constraint_Error with
1248 "Before index is out of range (too small)";
1251 if Before > Container.Last
1252 and then Before > Container.Last + 1
1254 raise Constraint_Error with
1255 "Before index is out of range (too large)";
1262 Insert_Space (Container, Before, Count => N);
1265 Dst_Last_As_Int : constant Int'Base :=
1266 Int'Base (Before) + Int'Base (N) - 1;
1268 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1270 Dst : Elements_Array renames
1271 Container.Elements.EA (Before .. Dst_Last);
1273 Dst_Index : Index_Type'Base := Before - 1;
1276 if Container'Address /= New_Item'Address then
1278 subtype Src_Index_Subtype is Index_Type'Base range
1279 Index_Type'First .. New_Item.Last;
1281 Src : Elements_Array renames
1282 New_Item.Elements.EA (Src_Index_Subtype);
1285 for Src_Index in Src'Range loop
1286 Dst_Index := Dst_Index + 1;
1288 if Src (Src_Index) /= null then
1289 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1298 subtype Src_Index_Subtype is Index_Type'Base range
1299 Index_Type'First .. Before - 1;
1301 Src : Elements_Array renames
1302 Container.Elements.EA (Src_Index_Subtype);
1305 for Src_Index in Src'Range loop
1306 Dst_Index := Dst_Index + 1;
1308 if Src (Src_Index) /= null then
1309 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1314 if Dst_Last = Container.Last then
1319 subtype Src_Index_Subtype is Index_Type'Base range
1320 Dst_Last + 1 .. Container.Last;
1322 Src : Elements_Array renames
1323 Container.Elements.EA (Src_Index_Subtype);
1326 for Src_Index in Src'Range loop
1327 Dst_Index := Dst_Index + 1;
1329 if Src (Src_Index) /= null then
1330 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1338 (Container : in out Vector;
1342 Index : Index_Type'Base;
1345 if Before.Container /= null
1346 and then Before.Container /= Container'Unchecked_Access
1348 raise Program_Error with "Before cursor denotes wrong container";
1351 if Is_Empty (New_Item) then
1355 if Before.Container = null
1356 or else Before.Index > Container.Last
1358 if Container.Last = Index_Type'Last then
1359 raise Constraint_Error with
1360 "vector is already at its maximum length";
1363 Index := Container.Last + 1;
1366 Index := Before.Index;
1369 Insert (Container, Index, New_Item);
1373 (Container : in out Vector;
1376 Position : out Cursor)
1378 Index : Index_Type'Base;
1381 if Before.Container /= null
1382 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1384 raise Program_Error with "Before cursor denotes wrong container";
1387 if Is_Empty (New_Item) then
1388 if Before.Container = null
1389 or else Before.Index > Container.Last
1391 Position := No_Element;
1393 Position := (Container'Unchecked_Access, Before.Index);
1399 if Before.Container = null
1400 or else Before.Index > Container.Last
1402 if Container.Last = Index_Type'Last then
1403 raise Constraint_Error with
1404 "vector is already at its maximum length";
1407 Index := Container.Last + 1;
1410 Index := Before.Index;
1413 Insert (Container, Index, New_Item);
1415 Position := Cursor'(Container'Unchecked_Access, Index);
1419 (Container : in out Vector;
1421 New_Item : Element_Type;
1422 Count : Count_Type := 1)
1424 Index : Index_Type'Base;
1427 if Before.Container /= null
1428 and then Before.Container /= Container'Unchecked_Access
1430 raise Program_Error with "Before cursor denotes wrong container";
1437 if Before.Container = null
1438 or else Before.Index > Container.Last
1440 if Container.Last = Index_Type'Last then
1441 raise Constraint_Error with
1442 "vector is already at its maximum length";
1445 Index := Container.Last + 1;
1448 Index := Before.Index;
1451 Insert (Container, Index, New_Item, Count);
1455 (Container : in out Vector;
1457 New_Item : Element_Type;
1458 Position : out Cursor;
1459 Count : Count_Type := 1)
1461 Index : Index_Type'Base;
1464 if Before.Container /= null
1465 and then Before.Container /= Container'Unchecked_Access
1467 raise Program_Error with "Before cursor denotes wrong container";
1471 if Before.Container = null
1472 or else Before.Index > Container.Last
1474 Position := No_Element;
1476 Position := (Container'Unchecked_Access, Before.Index);
1482 if Before.Container = null
1483 or else Before.Index > Container.Last
1485 if Container.Last = Index_Type'Last then
1486 raise Constraint_Error with
1487 "vector is already at its maximum length";
1490 Index := Container.Last + 1;
1493 Index := Before.Index;
1496 Insert (Container, Index, New_Item, Count);
1498 Position := (Container'Unchecked_Access, Index);
1505 procedure Insert_Space
1506 (Container : in out Vector;
1507 Before : Extended_Index;
1508 Count : Count_Type := 1)
1510 N : constant Int := Int (Count);
1512 First : constant Int := Int (Index_Type'First);
1513 New_Last_As_Int : Int'Base;
1514 New_Last : Index_Type;
1516 Max_Length : constant UInt := UInt (Count_Type'Last);
1518 Dst : Elements_Access;
1521 if Before < Index_Type'First then
1522 raise Constraint_Error with
1523 "Before index is out of range (too small)";
1526 if Before > Container.Last
1527 and then Before > Container.Last + 1
1529 raise Constraint_Error with
1530 "Before index is out of range (too large)";
1538 Old_Last_As_Int : constant Int := Int (Container.Last);
1541 if Old_Last_As_Int > Int'Last - N then
1542 raise Constraint_Error with "new length is out of range";
1545 New_Last_As_Int := Old_Last_As_Int + N;
1547 if New_Last_As_Int > Int (Index_Type'Last) then
1548 raise Constraint_Error with "new length is out of range";
1551 New_Length := UInt (New_Last_As_Int - First + 1);
1553 if New_Length > Max_Length then
1554 raise Constraint_Error with "new length is out of range";
1557 New_Last := Index_Type (New_Last_As_Int);
1560 if Container.Busy > 0 then
1561 raise Program_Error with
1562 "attempt to tamper with elements (vector is busy)";
1565 if Container.Elements = null then
1566 Container.Elements := new Elements_Type (New_Last);
1567 Container.Last := New_Last;
1571 if New_Last <= Container.Elements.Last then
1573 E : Elements_Array renames Container.Elements.EA;
1576 if Before <= Container.Last then
1578 Index_As_Int : constant Int'Base :=
1579 Index_Type'Pos (Before) + N;
1581 Index : constant Index_Type := Index_Type (Index_As_Int);
1584 E (Index .. New_Last) := E (Before .. Container.Last);
1585 E (Before .. Index - 1) := (others => null);
1590 Container.Last := New_Last;
1598 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1599 while C < New_Length loop
1600 if C > UInt'Last / 2 then
1608 if C > Max_Length then
1612 if Index_Type'First <= 0
1613 and then Index_Type'Last >= 0
1615 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1618 CC := UInt (Int (Index_Type'Last) - First + 1);
1626 Dst_Last : constant Index_Type :=
1627 Index_Type (First + UInt'Pos (C) - 1);
1630 Dst := new Elements_Type (Dst_Last);
1635 Src : Elements_Access := Container.Elements;
1638 if Before <= Container.Last then
1640 Index_As_Int : constant Int'Base :=
1641 Index_Type'Pos (Before) + N;
1643 Index : constant Index_Type := Index_Type (Index_As_Int);
1646 Dst.EA (Index_Type'First .. Before - 1) :=
1647 Src.EA (Index_Type'First .. Before - 1);
1649 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1653 Dst.EA (Index_Type'First .. Container.Last) :=
1654 Src.EA (Index_Type'First .. Container.Last);
1657 Container.Elements := Dst;
1658 Container.Last := New_Last;
1663 procedure Insert_Space
1664 (Container : in out Vector;
1666 Position : out Cursor;
1667 Count : Count_Type := 1)
1669 Index : Index_Type'Base;
1672 if Before.Container /= null
1673 and then Before.Container /= Container'Unchecked_Access
1675 raise Program_Error with "Before cursor denotes wrong container";
1679 if Before.Container = null
1680 or else Before.Index > Container.Last
1682 Position := No_Element;
1684 Position := (Container'Unchecked_Access, Before.Index);
1690 if Before.Container = null
1691 or else Before.Index > Container.Last
1693 if Container.Last = Index_Type'Last then
1694 raise Constraint_Error with
1695 "vector is already at its maximum length";
1698 Index := Container.Last + 1;
1701 Index := Before.Index;
1704 Insert_Space (Container, Index, Count);
1706 Position := Cursor'(Container'Unchecked_Access, Index);
1713 function Is_Empty (Container : Vector) return Boolean is
1715 return Container.Last < Index_Type'First;
1723 (Container : Vector;
1724 Process : not null access procedure (Position : Cursor))
1726 V : Vector renames Container'Unrestricted_Access.all;
1727 B : Natural renames V.Busy;
1733 for Indx in Index_Type'First .. Container.Last loop
1734 Process (Cursor'(Container'Unchecked_Access, Indx));
1749 function Last (Container : Vector) return Cursor is
1751 if Is_Empty (Container) then
1755 return (Container'Unchecked_Access, Container.Last);
1762 function Last_Element (Container : Vector) return Element_Type is
1764 if Container.Last = No_Index then
1765 raise Constraint_Error with "Container is empty";
1769 EA : constant Element_Access :=
1770 Container.Elements.EA (Container.Last);
1774 raise Constraint_Error with "last element is empty";
1785 function Last_Index (Container : Vector) return Extended_Index is
1787 return Container.Last;
1794 function Length (Container : Vector) return Count_Type is
1795 L : constant Int := Int (Container.Last);
1796 F : constant Int := Int (Index_Type'First);
1797 N : constant Int'Base := L - F + 1;
1800 return Count_Type (N);
1808 (Target : in out Vector;
1809 Source : in out Vector)
1812 if Target'Address = Source'Address then
1816 if Source.Busy > 0 then
1817 raise Program_Error with
1818 "attempt to tamper with elements (Source is busy)";
1821 Clear (Target); -- Checks busy-bit
1824 Target_Elements : constant Elements_Access := Target.Elements;
1826 Target.Elements := Source.Elements;
1827 Source.Elements := Target_Elements;
1830 Target.Last := Source.Last;
1831 Source.Last := No_Index;
1838 function Next (Position : Cursor) return Cursor is
1840 if Position.Container = null then
1844 if Position.Index < Position.Container.Last then
1845 return (Position.Container, Position.Index + 1);
1855 procedure Next (Position : in out Cursor) is
1857 if Position.Container = null then
1861 if Position.Index < Position.Container.Last then
1862 Position.Index := Position.Index + 1;
1864 Position := No_Element;
1872 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1874 Insert (Container, Index_Type'First, New_Item);
1878 (Container : in out Vector;
1879 New_Item : Element_Type;
1880 Count : Count_Type := 1)
1893 procedure Previous (Position : in out Cursor) is
1895 if Position.Container = null then
1899 if Position.Index > Index_Type'First then
1900 Position.Index := Position.Index - 1;
1902 Position := No_Element;
1906 function Previous (Position : Cursor) return Cursor is
1908 if Position.Container = null then
1912 if Position.Index > Index_Type'First then
1913 return (Position.Container, Position.Index - 1);
1923 procedure Query_Element
1924 (Container : Vector;
1926 Process : not null access procedure (Element : Element_Type))
1928 V : Vector renames Container'Unrestricted_Access.all;
1929 B : Natural renames V.Busy;
1930 L : Natural renames V.Lock;
1933 if Index > Container.Last then
1934 raise Constraint_Error with "Index is out of range";
1937 if V.Elements.EA (Index) = null then
1938 raise Constraint_Error with "element is null";
1945 Process (V.Elements.EA (Index).all);
1957 procedure Query_Element
1959 Process : not null access procedure (Element : Element_Type))
1962 if Position.Container = null then
1963 raise Constraint_Error with "Position cursor has no element";
1966 Query_Element (Position.Container.all, Position.Index, Process);
1974 (Stream : not null access Root_Stream_Type'Class;
1975 Container : out Vector)
1977 Length : Count_Type'Base;
1978 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1985 Count_Type'Base'Read (Stream, Length);
1987 if Length > Capacity (Container) then
1988 Reserve_Capacity (Container, Capacity => Length);
1991 for J in Count_Type range 1 .. Length loop
1994 Boolean'Read (Stream, B);
1997 Container.Elements.EA (Last) :=
1998 new Element_Type'(Element_Type'Input (Stream));
2001 Container.Last := Last;
2006 (Stream : not null access Root_Stream_Type'Class;
2007 Position : out Cursor)
2010 raise Program_Error with "attempt to stream vector cursor";
2013 ---------------------
2014 -- Replace_Element --
2015 ---------------------
2017 procedure Replace_Element
2018 (Container : in out Vector;
2020 New_Item : Element_Type)
2023 if Index > Container.Last then
2024 raise Constraint_Error with "Index is out of range";
2027 if Container.Lock > 0 then
2028 raise Program_Error with
2029 "attempt to tamper with cursors (vector is locked)";
2033 X : Element_Access := Container.Elements.EA (Index);
2035 Container.Elements.EA (Index) := new Element_Type'(New_Item);
2038 end Replace_Element;
2040 procedure Replace_Element
2041 (Container : in out Vector;
2043 New_Item : Element_Type)
2046 if Position.Container = null then
2047 raise Constraint_Error with "Position cursor has no element";
2050 if Position.Container /= Container'Unrestricted_Access then
2051 raise Program_Error with "Position cursor denotes wrong container";
2054 if Position.Index > Container.Last then
2055 raise Constraint_Error with "Position cursor is out of range";
2058 if Container.Lock > 0 then
2059 raise Program_Error with
2060 "attempt to tamper with cursors (vector is locked)";
2064 X : Element_Access := Container.Elements.EA (Position.Index);
2066 Container.Elements.EA (Position.Index) := new Element_Type'(New_Item);
2069 end Replace_Element;
2071 ----------------------
2072 -- Reserve_Capacity --
2073 ----------------------
2075 procedure Reserve_Capacity
2076 (Container : in out Vector;
2077 Capacity : Count_Type)
2079 N : constant Count_Type := Length (Container);
2082 if Capacity = 0 then
2085 X : Elements_Access := Container.Elements;
2087 Container.Elements := null;
2091 elsif N < Container.Elements.EA'Length then
2092 if Container.Busy > 0 then
2093 raise Program_Error with
2094 "attempt to tamper with elements (vector is busy)";
2098 subtype Array_Index_Subtype is Index_Type'Base range
2099 Index_Type'First .. Container.Last;
2101 Src : Elements_Array renames
2102 Container.Elements.EA (Array_Index_Subtype);
2104 X : Elements_Access := Container.Elements;
2107 Container.Elements := new Elements_Type'(Container.Last, Src);
2115 if Container.Elements = null then
2117 Last_As_Int : constant Int'Base :=
2118 Int (Index_Type'First) + Int (Capacity) - 1;
2121 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2122 raise Constraint_Error with "new length is out of range";
2126 Last : constant Index_Type := Index_Type (Last_As_Int);
2129 Container.Elements := new Elements_Type (Last);
2136 if Capacity <= N then
2137 if N < Container.Elements.EA'Length then
2138 if Container.Busy > 0 then
2139 raise Program_Error with
2140 "attempt to tamper with elements (vector is busy)";
2144 subtype Array_Index_Subtype is Index_Type'Base range
2145 Index_Type'First .. Container.Last;
2147 Src : Elements_Array renames
2148 Container.Elements.EA (Array_Index_Subtype);
2150 X : Elements_Access := Container.Elements;
2153 Container.Elements := new Elements_Type'(Container.Last, Src);
2161 if Capacity = Container.Elements.EA'Length then
2165 if Container.Busy > 0 then
2166 raise Program_Error with
2167 "attempt to tamper with elements (vector is busy)";
2171 Last_As_Int : constant Int'Base :=
2172 Int (Index_Type'First) + Int (Capacity) - 1;
2175 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2176 raise Constraint_Error with "new length is out of range";
2180 Last : constant Index_Type := Index_Type (Last_As_Int);
2181 X : Elements_Access := Container.Elements;
2183 subtype Index_Subtype is Index_Type'Base range
2184 Index_Type'First .. Container.Last;
2187 Container.Elements := new Elements_Type (Last);
2190 Src : Elements_Array renames
2191 X.EA (Index_Subtype);
2193 Tgt : Elements_Array renames
2194 Container.Elements.EA (Index_Subtype);
2203 end Reserve_Capacity;
2205 ----------------------
2206 -- Reverse_Elements --
2207 ----------------------
2209 procedure Reverse_Elements (Container : in out Vector) is
2211 if Container.Length <= 1 then
2215 if Container.Lock > 0 then
2216 raise Program_Error with
2217 "attempt to tamper with cursors (vector is locked)";
2223 E : Elements_Array renames Container.Elements.EA;
2226 I := Index_Type'First;
2227 J := Container.Last;
2230 EI : constant Element_Access := E (I);
2241 end Reverse_Elements;
2247 function Reverse_Find
2248 (Container : Vector;
2249 Item : Element_Type;
2250 Position : Cursor := No_Element) return Cursor
2252 Last : Index_Type'Base;
2255 if Position.Container /= null
2256 and then Position.Container /= Container'Unchecked_Access
2258 raise Program_Error with "Position cursor denotes wrong container";
2261 if Position.Container = null
2262 or else Position.Index > Container.Last
2264 Last := Container.Last;
2266 Last := Position.Index;
2269 for Indx in reverse Index_Type'First .. Last loop
2270 if Container.Elements.EA (Indx) /= null
2271 and then Container.Elements.EA (Indx).all = Item
2273 return (Container'Unchecked_Access, Indx);
2280 ------------------------
2281 -- Reverse_Find_Index --
2282 ------------------------
2284 function Reverse_Find_Index
2285 (Container : Vector;
2286 Item : Element_Type;
2287 Index : Index_Type := Index_Type'Last) return Extended_Index
2289 Last : Index_Type'Base;
2292 if Index > Container.Last then
2293 Last := Container.Last;
2298 for Indx in reverse Index_Type'First .. Last loop
2299 if Container.Elements.EA (Indx) /= null
2300 and then Container.Elements.EA (Indx).all = Item
2307 end Reverse_Find_Index;
2309 ---------------------
2310 -- Reverse_Iterate --
2311 ---------------------
2313 procedure Reverse_Iterate
2314 (Container : Vector;
2315 Process : not null access procedure (Position : Cursor))
2317 V : Vector renames Container'Unrestricted_Access.all;
2318 B : Natural renames V.Busy;
2324 for Indx in reverse Index_Type'First .. Container.Last loop
2325 Process (Cursor'(Container'Unchecked_Access, Indx));
2334 end Reverse_Iterate;
2340 procedure Set_Length
2341 (Container : in out Vector;
2342 Length : Count_Type)
2344 N : constant Count_Type := Indefinite_Vectors.Length (Container);
2351 if Container.Busy > 0 then
2352 raise Program_Error with
2353 "attempt to tamper with elements (vector is busy)";
2357 for Index in 1 .. N - Length loop
2359 J : constant Index_Type := Container.Last;
2360 X : Element_Access := Container.Elements.EA (J);
2363 Container.Elements.EA (J) := null;
2364 Container.Last := J - 1;
2372 if Length > Capacity (Container) then
2373 Reserve_Capacity (Container, Capacity => Length);
2377 Last_As_Int : constant Int'Base :=
2378 Int (Index_Type'First) + Int (Length) - 1;
2381 Container.Last := Index_Type (Last_As_Int);
2390 (Container : in out Vector;
2394 if I > Container.Last then
2395 raise Constraint_Error with "I index is out of range";
2398 if J > Container.Last then
2399 raise Constraint_Error with "J index is out of range";
2406 if Container.Lock > 0 then
2407 raise Program_Error with
2408 "attempt to tamper with cursors (vector is locked)";
2412 EI : Element_Access renames Container.Elements.EA (I);
2413 EJ : Element_Access renames Container.Elements.EA (J);
2415 EI_Copy : constant Element_Access := EI;
2424 (Container : in out Vector;
2428 if I.Container = null then
2429 raise Constraint_Error with "I cursor has no element";
2432 if J.Container = null then
2433 raise Constraint_Error with "J cursor has no element";
2436 if I.Container /= Container'Unrestricted_Access then
2437 raise Program_Error with "I cursor denotes wrong container";
2440 if J.Container /= Container'Unrestricted_Access then
2441 raise Program_Error with "J cursor denotes wrong container";
2444 Swap (Container, I.Index, J.Index);
2452 (Container : Vector;
2453 Index : Extended_Index) return Cursor
2456 if Index not in Index_Type'First .. Container.Last then
2460 return Cursor'(Container'Unchecked_Access, Index);
2467 function To_Index (Position : Cursor) return Extended_Index is
2469 if Position.Container = null then
2473 if Position.Index <= Position.Container.Last then
2474 return Position.Index;
2484 function To_Vector (Length : Count_Type) return Vector is
2487 return Empty_Vector;
2491 First : constant Int := Int (Index_Type'First);
2492 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2494 Elements : Elements_Access;
2497 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2498 raise Constraint_Error with "Length is out of range";
2501 Last := Index_Type (Last_As_Int);
2502 Elements := new Elements_Type (Last);
2504 return (Controlled with Elements, Last, 0, 0);
2509 (New_Item : Element_Type;
2510 Length : Count_Type) return Vector
2514 return Empty_Vector;
2518 First : constant Int := Int (Index_Type'First);
2519 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2520 Last : Index_Type'Base;
2521 Elements : Elements_Access;
2524 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2525 raise Constraint_Error with "Length is out of range";
2528 Last := Index_Type (Last_As_Int);
2529 Elements := new Elements_Type (Last);
2531 Last := Index_Type'First;
2535 Elements.EA (Last) := new Element_Type'(New_Item);
2536 exit when Last = Elements.Last;
2542 for J in Index_Type'First .. Last - 1 loop
2543 Free (Elements.EA (J));
2550 return (Controlled with Elements, Last, 0, 0);
2554 --------------------
2555 -- Update_Element --
2556 --------------------
2558 procedure Update_Element
2559 (Container : in out Vector;
2561 Process : not null access procedure (Element : in out Element_Type))
2563 B : Natural renames Container.Busy;
2564 L : Natural renames Container.Lock;
2567 if Index > Container.Last then
2568 raise Constraint_Error with "Index is out of range";
2571 if Container.Elements.EA (Index) = null then
2572 raise Constraint_Error with "element is null";
2579 Process (Container.Elements.EA (Index).all);
2591 procedure Update_Element
2592 (Container : in out Vector;
2594 Process : not null access procedure (Element : in out Element_Type))
2597 if Position.Container = null then
2598 raise Constraint_Error with "Position cursor has no element";
2601 if Position.Container /= Container'Unrestricted_Access then
2602 raise Program_Error with "Position cursor denotes wrong container";
2605 Update_Element (Container, Position.Index, Process);
2613 (Stream : not null access Root_Stream_Type'Class;
2616 N : constant Count_Type := Length (Container);
2619 Count_Type'Base'Write (Stream, N);
2626 E : Elements_Array renames Container.Elements.EA;
2629 for Indx in Index_Type'First .. Container.Last loop
2630 if E (Indx) = null then
2631 Boolean'Write (Stream, False);
2633 Boolean'Write (Stream, True);
2634 Element_Type'Output (Stream, E (Indx).all);
2641 (Stream : not null access Root_Stream_Type'Class;
2645 raise Program_Error with "attempt to stream vector cursor";
2648 end Ada.Containers.Indefinite_Vectors;