1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . 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 was originally developed by Matthew J Heaney. --
34 ------------------------------------------------------------------------------
36 with Ada.Containers.Generic_Array_Sort;
37 with Ada.Unchecked_Deallocation;
39 with System; use type System.Address;
41 package body Ada.Containers.Vectors is
43 type Int is range System.Min_Int .. System.Max_Int;
46 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
52 function "&" (Left, Right : Vector) return Vector is
53 LN : constant Count_Type := Length (Left);
54 RN : constant Count_Type := Length (Right);
63 RE : Elements_Type renames
64 Right.Elements (Index_Type'First .. Right.Last);
66 Elements : constant Elements_Access :=
67 new Elements_Type'(RE);
70 return (Controlled with Elements, Right.Last, 0, 0);
76 LE : Elements_Type renames
77 Left.Elements (Index_Type'First .. Left.Last);
79 Elements : constant Elements_Access :=
80 new Elements_Type'(LE);
83 return (Controlled with Elements, Left.Last, 0, 0);
89 Last_As_Int : constant Int'Base := -- TODO: handle overflow
90 Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
93 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
94 raise Constraint_Error;
98 Last : constant Index_Type := Index_Type (Last_As_Int);
100 LE : Elements_Type renames
101 Left.Elements (Index_Type'First .. Left.Last);
103 RE : Elements_Type renames
104 Right.Elements (Index_Type'First .. Right.Last);
106 Elements : constant Elements_Access :=
107 new Elements_Type'(LE & RE);
110 return (Controlled with Elements, Last, 0, 0);
115 function "&" (Left : Vector; Right : Element_Type) return Vector is
116 LN : constant Count_Type := Length (Left);
121 subtype Elements_Subtype is
122 Elements_Type (Index_Type'First .. Index_Type'First);
124 Elements : constant Elements_Access :=
125 new Elements_Subtype'(others => Right);
128 return (Controlled with Elements, Index_Type'First, 0, 0);
133 Last_As_Int : constant Int'Base := -- TODO: handle overflow
134 Int (Index_Type'First) + Int (LN);
137 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
138 raise Constraint_Error;
142 Last : constant Index_Type := Index_Type (Last_As_Int);
144 LE : Elements_Type renames
145 Left.Elements (Index_Type'First .. Left.Last);
147 subtype ET is Elements_Type (Index_Type'First .. Last);
149 Elements : constant Elements_Access := new ET'(LE & Right);
152 return (Controlled with Elements, Last, 0, 0);
157 function "&" (Left : Element_Type; Right : Vector) return Vector is
158 RN : constant Count_Type := Length (Right);
163 subtype Elements_Subtype is
164 Elements_Type (Index_Type'First .. Index_Type'First);
166 Elements : constant Elements_Access :=
167 new Elements_Subtype'(others => Left);
170 return (Controlled with Elements, Index_Type'First, 0, 0);
175 Last_As_Int : constant Int'Base := -- TODO: handle overflow
176 Int (Index_Type'First) + Int (RN);
179 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
180 raise Constraint_Error;
184 Last : constant Index_Type := Index_Type (Last_As_Int);
186 RE : Elements_Type renames
187 Right.Elements (Index_Type'First .. Right.Last);
189 subtype ET is Elements_Type (Index_Type'First .. Last);
191 Elements : constant Elements_Access := new ET'(Left & RE);
194 return (Controlled with Elements, Last, 0, 0);
199 function "&" (Left, Right : Element_Type) return Vector is
201 if Index_Type'First >= Index_Type'Last then
202 raise Constraint_Error;
206 Last : constant Index_Type := Index_Type'First + 1;
208 subtype ET is Elements_Type (Index_Type'First .. Last);
210 Elements : constant Elements_Access := new ET'(Left, Right);
213 return (Controlled with Elements, Last, 0, 0);
221 function "=" (Left, Right : Vector) return Boolean is
223 if Left'Address = Right'Address then
227 if Left.Last /= Right.Last then
231 for J in Index_Type range Index_Type'First .. Left.Last loop
232 if Left.Elements (J) /= Right.Elements (J) then
244 procedure Adjust (Container : in out Vector) is
246 if Container.Last = No_Index then
247 Container.Elements := null;
252 E : constant Elements_Access := Container.Elements;
253 L : constant Index_Type := Container.Last;
256 Container.Elements := null;
257 Container.Last := No_Index;
260 Container.Elements := new Elements_Type'(E (Index_Type'First .. L));
269 procedure Append (Container : in out Vector; New_Item : Vector) is
271 if Is_Empty (New_Item) then
275 if Container.Last = Index_Type'Last then
276 raise Constraint_Error;
286 (Container : in out Vector;
287 New_Item : Element_Type;
288 Count : Count_Type := 1)
295 if Container.Last = Index_Type'Last then
296 raise Constraint_Error;
310 function Capacity (Container : Vector) return Count_Type is
312 if Container.Elements = null then
316 return Container.Elements'Length;
323 procedure Clear (Container : in out Vector) is
325 if Container.Busy > 0 then
329 Container.Last := No_Index;
338 Item : Element_Type) return Boolean
341 return Find_Index (Container, Item) /= No_Index;
349 (Container : in out Vector;
350 Index : Extended_Index;
351 Count : Count_Type := 1)
354 if Index < Index_Type'First then
355 raise Constraint_Error;
358 if Index > Container.Last then
359 if Index > Container.Last + 1 then
360 raise Constraint_Error;
370 if Container.Busy > 0 then
375 I_As_Int : constant Int := Int (Index);
376 Old_Last_As_Int : constant Int := Index_Type'Pos (Container.Last);
378 Count1 : constant Int'Base := Count_Type'Pos (Count);
379 Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
380 N : constant Int'Base := Int'Min (Count1, Count2);
382 J_As_Int : constant Int'Base := I_As_Int + N;
385 if J_As_Int > Old_Last_As_Int then
386 Container.Last := Index - 1;
390 J : constant Index_Type := Index_Type (J_As_Int);
391 E : Elements_Type renames Container.Elements.all;
393 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
394 New_Last : constant Index_Type :=
395 Index_Type (New_Last_As_Int);
398 E (Index .. New_Last) := E (J .. Container.Last);
399 Container.Last := New_Last;
406 (Container : in out Vector;
407 Position : in out Cursor;
408 Count : Count_Type := 1)
411 if Position.Container = null then
412 raise Constraint_Error;
415 if Position.Container /= Container'Unrestricted_Access
416 or else Position.Index > Container.Last
421 Delete (Container, Position.Index, Count);
423 -- This is the old behavior, prior to the York API (2005/06):
425 -- if Position.Index <= Container.Last then
426 -- Position := (Container'Unchecked_Access, Position.Index);
428 -- Position := No_Element;
431 -- This is the behavior specified by the York API:
433 Position := No_Element;
440 procedure Delete_First
441 (Container : in out Vector;
442 Count : Count_Type := 1)
449 if Count >= Length (Container) then
454 Delete (Container, Index_Type'First, Count);
461 procedure Delete_Last
462 (Container : in out Vector;
463 Count : Count_Type := 1)
472 if Container.Busy > 0 then
476 Index := Int'Base (Container.Last) - Int'Base (Count);
478 if Index < Index_Type'Pos (Index_Type'First) then
479 Container.Last := No_Index;
481 Container.Last := Index_Type (Index);
491 Index : Index_Type) return Element_Type
494 if Index > Container.Last then
495 raise Constraint_Error;
498 return Container.Elements (Index);
501 function Element (Position : Cursor) return Element_Type is
503 if Position.Container = null then
504 raise Constraint_Error;
507 return Element (Position.Container.all, Position.Index);
514 procedure Finalize (Container : in out Vector) is
515 X : Elements_Access := Container.Elements;
518 if Container.Busy > 0 then
522 Container.Elements := null;
523 Container.Last := No_Index;
534 Position : Cursor := No_Element) return Cursor
537 if Position.Container /= null
538 and then (Position.Container /= Container'Unrestricted_Access
539 or else Position.Index > Container.Last)
544 for J in Position.Index .. Container.Last loop
545 if Container.Elements (J) = Item then
546 return (Container'Unchecked_Access, J);
560 Index : Index_Type := Index_Type'First) return Extended_Index
563 for Indx in Index .. Container.Last loop
564 if Container.Elements (Indx) = Item then
576 function First (Container : Vector) return Cursor is
578 if Is_Empty (Container) then
582 return (Container'Unchecked_Access, Index_Type'First);
589 function First_Element (Container : Vector) return Element_Type is
591 return Element (Container, Index_Type'First);
598 function First_Index (Container : Vector) return Index_Type is
599 pragma Unreferenced (Container);
601 return Index_Type'First;
604 ---------------------
605 -- Generic_Sorting --
606 ---------------------
608 package body Generic_Sorting is
614 function Is_Sorted (Container : Vector) return Boolean is
616 if Container.Last <= Index_Type'First then
621 E : Elements_Type renames Container.Elements.all;
623 for I in Index_Type'First .. Container.Last - 1 loop
624 if E (I + 1) < E (I) then
637 procedure Merge (Target, Source : in out Vector) is
638 I : Index_Type'Base := Target.Last;
642 if Target.Last < Index_Type'First then
643 Move (Target => Target, Source => Source);
647 if Target'Address = Source'Address then
651 if Source.Last < Index_Type'First then
655 if Source.Busy > 0 then
659 Target.Set_Length (Length (Target) + Length (Source));
662 while Source.Last >= Index_Type'First loop
663 if I < Index_Type'First then
664 Target.Elements (Index_Type'First .. J) :=
665 Source.Elements (Index_Type'First .. Source.Last);
667 Source.Last := No_Index;
671 if Source.Elements (Source.Last) < Target.Elements (I) then
672 Target.Elements (J) := Target.Elements (I);
676 Target.Elements (J) := Source.Elements (Source.Last);
677 Source.Last := Source.Last - 1;
688 procedure Sort (Container : in out Vector)
691 new Generic_Array_Sort
692 (Index_Type => Index_Type,
693 Element_Type => Element_Type,
694 Array_Type => Elements_Type,
698 if Container.Last <= Index_Type'First then
702 if Container.Lock > 0 then
706 Sort (Container.Elements (Index_Type'First .. Container.Last));
715 function Has_Element (Position : Cursor) return Boolean is
717 if Position.Container = null then
721 return Position.Index <= Position.Container.Last;
729 (Container : in out Vector;
730 Before : Extended_Index;
731 New_Item : Element_Type;
732 Count : Count_Type := 1)
734 N : constant Int := Count_Type'Pos (Count);
736 New_Last_As_Int : Int'Base;
737 New_Last : Index_Type;
739 Dst : Elements_Access;
742 if Before < Index_Type'First then
743 raise Constraint_Error;
746 if Before > Container.Last
747 and then Before > Container.Last + 1
749 raise Constraint_Error;
757 Old_Last : constant Extended_Index := Container.Last;
759 Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
762 New_Last_As_Int := Old_Last_As_Int + N;
764 if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
765 raise Constraint_Error;
768 New_Last := Index_Type (New_Last_As_Int);
771 if Container.Busy > 0 then
775 if Container.Elements = null then
777 subtype Elements_Subtype is
778 Elements_Type (Index_Type'First .. New_Last);
780 Container.Elements := new Elements_Subtype'(others => New_Item);
783 Container.Last := New_Last;
787 if New_Last <= Container.Elements'Last then
789 E : Elements_Type renames Container.Elements.all;
791 if Before <= Container.Last then
793 Index_As_Int : constant Int'Base :=
794 Index_Type'Pos (Before) + N;
796 Index : constant Index_Type := Index_Type (Index_As_Int);
799 E (Index .. New_Last) := E (Before .. Container.Last);
801 E (Before .. Index_Type'Pred (Index)) :=
802 (others => New_Item);
806 E (Before .. New_Last) := (others => New_Item);
810 Container.Last := New_Last;
815 First : constant Int := Int (Index_Type'First);
816 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
817 Size : Int'Base := Int'Max (1, Container.Elements'Length);
820 while Size < New_Size loop
821 if Size > Int'Last / 2 then
829 -- TODO: The following calculations aren't quite right, since
830 -- there will be overflow if Index_Type'Range is very large
831 -- (e.g. this package is instantiated with a 64-bit integer).
835 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
837 if Size > Max_Size then
843 Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
845 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
850 Src : Elements_Type renames Container.Elements.all;
853 Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
854 Src (Index_Type'First .. Index_Type'Pred (Before));
856 if Before <= Container.Last then
858 Index_As_Int : constant Int'Base :=
859 Index_Type'Pos (Before) + N;
861 Index : constant Index_Type := Index_Type (Index_As_Int);
864 Dst (Before .. Index_Type'Pred (Index)) := (others => New_Item);
865 Dst (Index .. New_Last) := Src (Before .. Container.Last);
869 Dst (Before .. New_Last) := (others => New_Item);
878 X : Elements_Access := Container.Elements;
880 Container.Elements := Dst;
881 Container.Last := New_Last;
887 (Container : in out Vector;
888 Before : Extended_Index;
891 N : constant Count_Type := Length (New_Item);
894 if Before < Index_Type'First then
895 raise Constraint_Error;
898 if Before > Container.Last
899 and then Before > Container.Last + 1
901 raise Constraint_Error;
908 Insert_Space (Container, Before, Count => N);
911 Dst_Last_As_Int : constant Int'Base :=
912 Int'Base (Before) + Int'Base (N) - 1;
914 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
917 if Container'Address /= New_Item'Address then
918 Container.Elements (Before .. Dst_Last) :=
919 New_Item.Elements (Index_Type'First .. New_Item.Last);
925 subtype Src_Index_Subtype is Index_Type'Base range
926 Index_Type'First .. Before - 1;
928 Src : Elements_Type renames
929 Container.Elements (Src_Index_Subtype);
931 Index_As_Int : constant Int'Base :=
932 Int (Before) + Src'Length - 1;
934 Index : constant Index_Type'Base :=
935 Index_Type'Base (Index_As_Int);
937 Dst : Elements_Type renames
938 Container.Elements (Before .. Index);
944 if Dst_Last = Container.Last then
949 subtype Src_Index_Subtype is Index_Type'Base range
950 Dst_Last + 1 .. Container.Last;
952 Src : Elements_Type renames
953 Container.Elements (Src_Index_Subtype);
955 Index_As_Int : constant Int'Base :=
956 Dst_Last_As_Int - Src'Length + 1;
958 Index : constant Index_Type :=
959 Index_Type (Index_As_Int);
961 Dst : Elements_Type renames
962 Container.Elements (Index .. Dst_Last);
971 (Container : in out Vector;
975 Index : Index_Type'Base;
978 if Before.Container /= null
979 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
984 if Is_Empty (New_Item) then
988 if Before.Container = null
989 or else Before.Index > Container.Last
991 if Container.Last = Index_Type'Last then
992 raise Constraint_Error;
995 Index := Container.Last + 1;
998 Index := Before.Index;
1001 Insert (Container, Index, New_Item);
1005 (Container : in out Vector;
1008 Position : out Cursor)
1010 Index : Index_Type'Base;
1013 if Before.Container /= null
1014 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1016 raise Program_Error;
1019 if Is_Empty (New_Item) then
1020 if Before.Container = null
1021 or else Before.Index > Container.Last
1023 Position := No_Element;
1025 Position := (Container'Unchecked_Access, Before.Index);
1031 if Before.Container = null
1032 or else Before.Index > Container.Last
1034 if Container.Last = Index_Type'Last then
1035 raise Constraint_Error;
1038 Index := Container.Last + 1;
1041 Index := Before.Index;
1044 Insert (Container, Index, New_Item);
1046 Position := Cursor'(Container'Unchecked_Access, Index);
1050 (Container : in out Vector;
1052 New_Item : Element_Type;
1053 Count : Count_Type := 1)
1055 Index : Index_Type'Base;
1058 if Before.Container /= null
1059 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1061 raise Program_Error;
1068 if Before.Container = null
1069 or else Before.Index > Container.Last
1071 if Container.Last = Index_Type'Last then
1072 raise Constraint_Error;
1075 Index := Container.Last + 1;
1078 Index := Before.Index;
1081 Insert (Container, Index, New_Item, Count);
1085 (Container : in out Vector;
1087 New_Item : Element_Type;
1088 Position : out Cursor;
1089 Count : Count_Type := 1)
1091 Index : Index_Type'Base;
1094 if Before.Container /= null
1095 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1097 raise Program_Error;
1101 if Before.Container = null
1102 or else Before.Index > Container.Last
1104 Position := No_Element;
1106 Position := (Container'Unchecked_Access, Before.Index);
1112 if Before.Container = null
1113 or else Before.Index > Container.Last
1115 if Container.Last = Index_Type'Last then
1116 raise Constraint_Error;
1119 Index := Container.Last + 1;
1122 Index := Before.Index;
1125 Insert (Container, Index, New_Item, Count);
1127 Position := Cursor'(Container'Unchecked_Access, Index);
1131 (Container : in out Vector;
1132 Before : Extended_Index;
1133 Count : Count_Type := 1)
1135 New_Item : Element_Type; -- Default-initialized value
1136 pragma Warnings (Off, New_Item);
1139 Insert (Container, Before, New_Item, Count);
1143 (Container : in out Vector;
1145 Position : out Cursor;
1146 Count : Count_Type := 1)
1148 New_Item : Element_Type; -- Default-initialized value
1149 pragma Warnings (Off, New_Item);
1152 Insert (Container, Before, New_Item, Position, Count);
1159 procedure Insert_Space
1160 (Container : in out Vector;
1161 Before : Extended_Index;
1162 Count : Count_Type := 1)
1164 N : constant Int := Count_Type'Pos (Count);
1166 New_Last_As_Int : Int'Base;
1167 New_Last : Index_Type;
1169 Dst : Elements_Access;
1172 if Before < Index_Type'First then
1173 raise Constraint_Error;
1176 if Before > Container.Last
1177 and then Before > Container.Last + 1
1179 raise Constraint_Error;
1187 Old_Last : constant Extended_Index := Container.Last;
1189 Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
1192 New_Last_As_Int := Old_Last_As_Int + N;
1194 if New_Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1195 raise Constraint_Error;
1198 New_Last := Index_Type (New_Last_As_Int);
1201 if Container.Busy > 0 then
1202 raise Program_Error;
1205 if Container.Elements = null then
1206 Container.Elements :=
1207 new Elements_Type (Index_Type'First .. New_Last);
1209 Container.Last := New_Last;
1213 if New_Last <= Container.Elements'Last then
1215 E : Elements_Type renames Container.Elements.all;
1217 if Before <= Container.Last then
1219 Index_As_Int : constant Int'Base :=
1220 Index_Type'Pos (Before) + N;
1222 Index : constant Index_Type := Index_Type (Index_As_Int);
1225 E (Index .. New_Last) := E (Before .. Container.Last);
1230 Container.Last := New_Last;
1235 First : constant Int := Int (Index_Type'First);
1236 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
1237 Size : Int'Base := Int'Max (1, Container.Elements'Length);
1240 while Size < New_Size loop
1241 if Size > Int'Last / 2 then
1249 -- TODO: The following calculations aren't quite right, since
1250 -- there will be overflow if Index_Type'Range is very large
1251 -- (e.g. this package is instantiated with a 64-bit integer).
1255 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
1257 if Size > Max_Size then
1263 Dst_Last : constant Index_Type := Index_Type (First + Size - 1);
1265 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1270 Src : Elements_Type renames Container.Elements.all;
1273 Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
1274 Src (Index_Type'First .. Index_Type'Pred (Before));
1276 if Before <= Container.Last then
1278 Index_As_Int : constant Int'Base :=
1279 Index_Type'Pos (Before) + N;
1281 Index : constant Index_Type := Index_Type (Index_As_Int);
1284 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1294 X : Elements_Access := Container.Elements;
1296 Container.Elements := Dst;
1297 Container.Last := New_Last;
1302 procedure Insert_Space
1303 (Container : in out Vector;
1305 Position : out Cursor;
1306 Count : Count_Type := 1)
1308 Index : Index_Type'Base;
1311 if Before.Container /= null
1312 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1314 raise Program_Error;
1318 if Before.Container = null
1319 or else Before.Index > Container.Last
1321 Position := No_Element;
1323 Position := (Container'Unchecked_Access, Before.Index);
1329 if Before.Container = null
1330 or else Before.Index > Container.Last
1332 if Container.Last = Index_Type'Last then
1333 raise Constraint_Error;
1336 Index := Container.Last + 1;
1339 Index := Before.Index;
1342 Insert_Space (Container, Index, Count => Count);
1344 Position := Cursor'(Container'Unchecked_Access, Index);
1351 function Is_Empty (Container : Vector) return Boolean is
1353 return Container.Last < Index_Type'First;
1361 (Container : Vector;
1362 Process : not null access procedure (Position : Cursor))
1364 V : Vector renames Container'Unrestricted_Access.all;
1365 B : Natural renames V.Busy;
1371 for Indx in Index_Type'First .. Container.Last loop
1372 Process (Cursor'(Container'Unchecked_Access, Indx));
1387 function Last (Container : Vector) return Cursor is
1389 if Is_Empty (Container) then
1393 return (Container'Unchecked_Access, Container.Last);
1400 function Last_Element (Container : Vector) return Element_Type is
1402 return Element (Container, Container.Last);
1409 function Last_Index (Container : Vector) return Extended_Index is
1411 return Container.Last;
1418 function Length (Container : Vector) return Count_Type is
1419 L : constant Int := Int (Container.Last);
1420 F : constant Int := Int (Index_Type'First);
1421 N : constant Int'Base := L - F + 1;
1424 if N > Count_Type'Pos (Count_Type'Last) then
1425 raise Constraint_Error;
1428 return Count_Type (N);
1436 (Target : in out Vector;
1437 Source : in out Vector)
1440 if Target'Address = Source'Address then
1444 if Target.Busy > 0 then
1445 raise Program_Error;
1448 if Source.Busy > 0 then
1449 raise Program_Error;
1453 Target_Elements : constant Elements_Access := Target.Elements;
1455 Target.Elements := Source.Elements;
1456 Source.Elements := Target_Elements;
1459 Target.Last := Source.Last;
1460 Source.Last := No_Index;
1467 function Next (Position : Cursor) return Cursor is
1469 if Position.Container = null then
1473 if Position.Index < Position.Container.Last then
1474 return (Position.Container, Position.Index + 1);
1484 procedure Next (Position : in out Cursor) is
1486 if Position.Container = null then
1490 if Position.Index < Position.Container.Last then
1491 Position.Index := Position.Index + 1;
1493 Position := No_Element;
1501 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1503 Insert (Container, Index_Type'First, New_Item);
1507 (Container : in out Vector;
1508 New_Item : Element_Type;
1509 Count : Count_Type := 1)
1522 procedure Previous (Position : in out Cursor) is
1524 if Position.Container = null then
1528 if Position.Index > Index_Type'First then
1529 Position.Index := Position.Index - 1;
1531 Position := No_Element;
1535 function Previous (Position : Cursor) return Cursor is
1537 if Position.Container = null then
1541 if Position.Index > Index_Type'First then
1542 return (Position.Container, Position.Index - 1);
1552 procedure Query_Element
1553 (Container : Vector;
1555 Process : not null access procedure (Element : Element_Type))
1557 V : Vector renames Container'Unrestricted_Access.all;
1558 B : Natural renames V.Busy;
1559 L : Natural renames V.Lock;
1562 if Index > Container.Last then
1563 raise Constraint_Error;
1570 Process (V.Elements (Index));
1582 procedure Query_Element
1584 Process : not null access procedure (Element : Element_Type))
1587 if Position.Container = null then
1588 raise Constraint_Error;
1591 Query_Element (Position.Container.all, Position.Index, Process);
1599 (Stream : access Root_Stream_Type'Class;
1600 Container : out Vector)
1602 Length : Count_Type'Base;
1603 Last : Index_Type'Base := No_Index;
1608 Count_Type'Base'Read (Stream, Length);
1610 if Length > Capacity (Container) then
1611 Reserve_Capacity (Container, Capacity => Length);
1614 for J in Count_Type range 1 .. Length loop
1616 Element_Type'Read (Stream, Container.Elements (Last));
1617 Container.Last := Last;
1622 (Stream : access Root_Stream_Type'Class;
1623 Position : out Cursor)
1626 raise Program_Error;
1629 ---------------------
1630 -- Replace_Element --
1631 ---------------------
1633 procedure Replace_Element
1634 (Container : in out Vector;
1636 New_Item : Element_Type)
1639 if Index > Container.Last then
1640 raise Constraint_Error;
1643 if Container.Lock > 0 then
1644 raise Program_Error;
1647 Container.Elements (Index) := New_Item;
1648 end Replace_Element;
1650 procedure Replace_Element
1651 (Container : in out Vector;
1653 New_Item : Element_Type)
1656 if Position.Container = null then
1657 raise Constraint_Error;
1660 if Position.Container /= Container'Unrestricted_Access then
1661 raise Program_Error;
1664 Replace_Element (Container, Position.Index, New_Item);
1665 end Replace_Element;
1667 ----------------------
1668 -- Reserve_Capacity --
1669 ----------------------
1671 procedure Reserve_Capacity
1672 (Container : in out Vector;
1673 Capacity : Count_Type)
1675 N : constant Count_Type := Length (Container);
1678 if Capacity = 0 then
1681 X : Elements_Access := Container.Elements;
1683 Container.Elements := null;
1687 elsif N < Container.Elements'Length then
1688 if Container.Busy > 0 then
1689 raise Program_Error;
1693 subtype Array_Index_Subtype is Index_Type'Base range
1694 Index_Type'First .. Container.Last;
1696 Src : Elements_Type renames
1697 Container.Elements (Array_Index_Subtype);
1699 subtype Array_Subtype is
1700 Elements_Type (Array_Index_Subtype);
1702 X : Elements_Access := Container.Elements;
1705 Container.Elements := new Array_Subtype'(Src);
1713 if Container.Elements = null then
1715 Last_As_Int : constant Int'Base :=
1716 Int (Index_Type'First) + Int (Capacity) - 1;
1719 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1720 raise Constraint_Error;
1724 Last : constant Index_Type := Index_Type (Last_As_Int);
1726 subtype Array_Subtype is
1727 Elements_Type (Index_Type'First .. Last);
1729 Container.Elements := new Array_Subtype;
1736 if Capacity <= N then
1737 if N < Container.Elements'Length then
1738 if Container.Busy > 0 then
1739 raise Program_Error;
1743 subtype Array_Index_Subtype is Index_Type'Base range
1744 Index_Type'First .. Container.Last;
1746 Src : Elements_Type renames
1747 Container.Elements (Array_Index_Subtype);
1749 subtype Array_Subtype is
1750 Elements_Type (Array_Index_Subtype);
1752 X : Elements_Access := Container.Elements;
1755 Container.Elements := new Array_Subtype'(Src);
1764 if Capacity = Container.Elements'Length then
1768 if Container.Busy > 0 then
1769 raise Program_Error;
1773 Last_As_Int : constant Int'Base :=
1774 Int (Index_Type'First) + Int (Capacity) - 1;
1777 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1778 raise Constraint_Error;
1782 Last : constant Index_Type := Index_Type (Last_As_Int);
1784 subtype Array_Subtype is
1785 Elements_Type (Index_Type'First .. Last);
1787 E : Elements_Access := new Array_Subtype;
1791 Src : Elements_Type renames
1792 Container.Elements (Index_Type'First .. Container.Last);
1794 Tgt : Elements_Type renames
1795 E (Index_Type'First .. Container.Last);
1807 X : Elements_Access := Container.Elements;
1809 Container.Elements := E;
1814 end Reserve_Capacity;
1816 ----------------------
1817 -- Reverse_Elements --
1818 ----------------------
1820 procedure Reverse_Elements (Container : in out Vector) is
1822 if Container.Length <= 1 then
1826 if Container.Lock > 0 then
1827 raise Program_Error;
1831 I : Index_Type := Index_Type'First;
1832 J : Index_Type := Container.Last;
1833 E : Elements_Type renames Container.Elements.all;
1838 EI : constant Element_Type := E (I);
1849 end Reverse_Elements;
1855 function Reverse_Find
1856 (Container : Vector;
1857 Item : Element_Type;
1858 Position : Cursor := No_Element) return Cursor
1860 Last : Index_Type'Base;
1863 if Position.Container /= null
1864 and then Position.Container /=
1865 Vector_Access'(Container'Unchecked_Access)
1867 raise Program_Error;
1870 if Position.Container = null
1871 or else Position.Index > Container.Last
1873 Last := Container.Last;
1875 Last := Position.Index;
1878 for Indx in reverse Index_Type'First .. Last loop
1879 if Container.Elements (Indx) = Item then
1880 return (Container'Unchecked_Access, Indx);
1887 ------------------------
1888 -- Reverse_Find_Index --
1889 ------------------------
1891 function Reverse_Find_Index
1892 (Container : Vector;
1893 Item : Element_Type;
1894 Index : Index_Type := Index_Type'Last) return Extended_Index
1896 Last : Index_Type'Base;
1899 if Index > Container.Last then
1900 Last := Container.Last;
1905 for Indx in reverse Index_Type'First .. Last loop
1906 if Container.Elements (Indx) = Item then
1912 end Reverse_Find_Index;
1914 ---------------------
1915 -- Reverse_Iterate --
1916 ---------------------
1918 procedure Reverse_Iterate
1919 (Container : Vector;
1920 Process : not null access procedure (Position : Cursor))
1922 V : Vector renames Container'Unrestricted_Access.all;
1923 B : Natural renames V.Busy;
1930 for Indx in reverse Index_Type'First .. Container.Last loop
1931 Process (Cursor'(Container'Unchecked_Access, Indx));
1941 end Reverse_Iterate;
1947 procedure Set_Length (Container : in out Vector; Length : Count_Type) is
1949 if Length = Vectors.Length (Container) then
1953 if Container.Busy > 0 then
1954 raise Program_Error;
1957 if Length > Capacity (Container) then
1958 Reserve_Capacity (Container, Capacity => Length);
1962 Last_As_Int : constant Int'Base :=
1963 Int (Index_Type'First) + Int (Length) - 1;
1965 Container.Last := Index_Type'Base (Last_As_Int);
1973 procedure Swap (Container : in out Vector; I, J : Index_Type) is
1975 if I > Container.Last
1976 or else J > Container.Last
1978 raise Constraint_Error;
1985 if Container.Lock > 0 then
1986 raise Program_Error;
1990 EI : Element_Type renames Container.Elements (I);
1991 EJ : Element_Type renames Container.Elements (J);
1993 EI_Copy : constant Element_Type := EI;
2001 procedure Swap (Container : in out Vector; I, J : Cursor) is
2003 if I.Container = null
2004 or else J.Container = null
2006 raise Constraint_Error;
2009 if I.Container /= Container'Unrestricted_Access
2010 or else J.Container /= Container'Unrestricted_Access
2012 raise Program_Error;
2015 Swap (Container, I.Index, J.Index);
2023 (Container : Vector;
2024 Index : Extended_Index) return Cursor
2027 if Index not in Index_Type'First .. Container.Last then
2031 return Cursor'(Container'Unchecked_Access, Index);
2038 function To_Index (Position : Cursor) return Extended_Index is
2040 if Position.Container = null then
2044 if Position.Index <= Position.Container.Last then
2045 return Position.Index;
2055 function To_Vector (Length : Count_Type) return Vector is
2058 return Empty_Vector;
2062 First : constant Int := Int (Index_Type'First);
2063 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2065 Elements : Elements_Access;
2068 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2069 raise Constraint_Error;
2072 Last := Index_Type (Last_As_Int);
2073 Elements := new Elements_Type (Index_Type'First .. Last);
2075 return (Controlled with Elements, Last, 0, 0);
2080 (New_Item : Element_Type;
2081 Length : Count_Type) return Vector
2085 return Empty_Vector;
2089 First : constant Int := Int (Index_Type'First);
2090 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2092 Elements : Elements_Access;
2095 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2096 raise Constraint_Error;
2099 Last := Index_Type (Last_As_Int);
2100 Elements := new Elements_Type'(Index_Type'First .. Last => New_Item);
2102 return (Controlled with Elements, Last, 0, 0);
2106 --------------------
2107 -- Update_Element --
2108 --------------------
2110 procedure Update_Element
2111 (Container : in out Vector;
2113 Process : not null access procedure (Element : in out Element_Type))
2115 B : Natural renames Container.Busy;
2116 L : Natural renames Container.Lock;
2119 if Index > Container.Last then
2120 raise Constraint_Error;
2127 Process (Container.Elements (Index));
2139 procedure Update_Element
2140 (Container : in out Vector;
2142 Process : not null access procedure (Element : in out Element_Type))
2145 if Position.Container = null then
2146 raise Constraint_Error;
2149 if Position.Container /= Container'Unrestricted_Access then
2150 raise Program_Error;
2153 Update_Element (Container, Position.Index, Process);
2161 (Stream : access Root_Stream_Type'Class;
2165 Count_Type'Base'Write (Stream, Length (Container));
2167 for J in Index_Type'First .. Container.Last loop
2168 Element_Type'Write (Stream, Container.Elements (J));
2173 (Stream : access Root_Stream_Type'Class;
2177 raise Program_Error;
2180 end Ada.Containers.Vectors;