1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . F O R M A L _ V E C T O R S --
9 -- Copyright (C) 2010-2011, 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/>. --
26 ------------------------------------------------------------------------------
28 with Ada.Containers.Generic_Array_Sort;
29 with System; use type System.Address;
31 package body Ada.Containers.Formal_Vectors is
33 type Int is range System.Min_Int .. System.Max_Int;
34 type UInt is mod System.Max_Binary_Modulus;
38 Position : Count_Type) return Element_Type;
44 function "&" (Left, Right : Vector) return Vector is
45 LN : constant Count_Type := Length (Left);
46 RN : constant Count_Type := Length (Right);
55 E : constant Elements_Array (1 .. Length (Right)) :=
56 Right.Elements (1 .. RN);
58 return (Length (Right), E,
59 Last => Right.Last, others => <>);
65 E : constant Elements_Array (1 .. Length (Left)) :=
66 Left.Elements (1 .. LN);
68 return (Length (Left), E,
69 Last => Left.Last, others => <>);
75 N : constant Int'Base := Int (LN) + Int (RN);
76 Last_As_Int : Int'Base;
79 if Int (No_Index) > Int'Last - N then
80 raise Constraint_Error with "new length is out of range";
83 Last_As_Int := Int (No_Index) + N;
85 if Last_As_Int > Int (Index_Type'Last) then
86 raise Constraint_Error with "new length is out of range";
89 -- TODO: should check whether length > max capacity (cnt_t'last) ???
92 Last : constant Index_Type := Index_Type (Last_As_Int);
94 LE : constant Elements_Array (1 .. LN) :=
95 Left.Elements (1 .. LN);
97 RE : Elements_Array renames Right.Elements (1 .. RN);
99 Capacity : constant Count_Type := Length (Left) + Length (Right);
102 return (Capacity, LE & RE,
103 Last => Last, others => <>);
108 function "&" (Left : Vector; Right : Element_Type) return Vector is
109 LN : constant Count_Type := Length (Left);
110 Last_As_Int : Int'Base;
114 return (1, (1 .. 1 => Right),
115 Index_Type'First, others => <>);
118 if Int (Index_Type'First) > Int'Last - Int (LN) then
119 raise Constraint_Error with "new length is out of range";
122 Last_As_Int := Int (Index_Type'First) + Int (LN);
124 if Last_As_Int > Int (Index_Type'Last) then
125 raise Constraint_Error with "new length is out of range";
129 Last : constant Index_Type := Index_Type (Last_As_Int);
131 LE : constant Elements_Array (1 .. LN) :=
132 Left.Elements (1 .. LN);
134 Capacity : constant Count_Type := Length (Left) + 1;
137 return (Capacity, LE & Right,
138 Last => Last, others => <>);
143 function "&" (Left : Element_Type; Right : Vector) return Vector is
144 RN : constant Count_Type := Length (Right);
145 Last_As_Int : Int'Base;
149 return (1, (1 .. 1 => Left),
150 Index_Type'First, others => <>);
153 if Int (Index_Type'First) > Int'Last - Int (RN) then
154 raise Constraint_Error with "new length is out of range";
157 Last_As_Int := Int (Index_Type'First) + Int (RN);
159 if Last_As_Int > Int (Index_Type'Last) then
160 raise Constraint_Error with "new length is out of range";
164 Last : constant Index_Type := Index_Type (Last_As_Int);
166 RE : Elements_Array renames Right.Elements (1 .. RN);
168 Capacity : constant Count_Type := 1 + Length (Right);
171 return (Capacity, Left & RE,
172 Last => Last, others => <>);
176 function "&" (Left, Right : Element_Type) return Vector is
178 if Index_Type'First >= Index_Type'Last then
179 raise Constraint_Error with "new length is out of range";
183 Last : constant Index_Type := Index_Type'First + 1;
186 return (2, (Left, Right),
187 Last => Last, others => <>);
195 function "=" (Left, Right : Vector) return Boolean is
197 if Left'Address = Right'Address then
201 if Length (Left) /= Length (Right) then
205 for J in Count_Type range 1 .. Length (Left) loop
206 if Get_Element (Left, J) /= Get_Element (Right, J) then
218 procedure Append (Container : in out Vector; New_Item : Vector) is
221 if Is_Empty (New_Item) then
225 if Container.Last = Index_Type'Last then
226 raise Constraint_Error with "vector is already at its maximum length";
236 (Container : in out Vector;
237 New_Item : Element_Type;
238 Count : Count_Type := 1)
246 if Container.Last = Index_Type'Last then
247 raise Constraint_Error with "vector is already at its maximum length";
250 -- TODO: should check whether length > max capacity (cnt_t'last) ???
263 procedure Assign (Target : in out Vector; Source : Vector) is
264 LS : constant Count_Type := Length (Source);
267 if Target'Address = Source'Address then
271 if Target.Capacity < LS then
272 raise Constraint_Error;
277 Target.Elements (1 .. LS) :=
278 Source.Elements (1 .. LS);
279 Target.Last := Source.Last;
287 function Capacity (Container : Vector) return Capacity_Subtype is
289 return Container.Elements'Length;
296 procedure Clear (Container : in out Vector) is
299 if Container.Busy > 0 then
300 raise Program_Error with
301 "attempt to tamper with elements (vector is busy)";
304 Container.Last := No_Index;
313 Item : Element_Type) return Boolean
316 return Find_Index (Container, Item) /= No_Index;
325 Capacity : Capacity_Subtype := 0) return Vector
327 LS : constant Count_Type := Length (Source);
328 C : Capacity_Subtype;
334 elsif Capacity >= LS then
338 raise Constraint_Error;
341 return Target : Vector (C) do
342 Target.Elements (1 .. LS) :=
343 Source.Elements (1 .. LS);
344 Target.Last := Source.Last;
354 (Container : in out Vector;
355 Index : Extended_Index;
356 Count : Count_Type := 1)
360 if Index < Index_Type'First then
361 raise Constraint_Error with "Index is out of range (too small)";
364 if Index > Container.Last then
365 if Index > Container.Last + 1 then
366 raise Constraint_Error with "Index is out of range (too large)";
376 if Container.Busy > 0 then
377 raise Program_Error with
378 "attempt to tamper with elements (vector is busy)";
382 I_As_Int : constant Int := Int (Index);
383 Old_Last_As_Int : constant Int :=
384 Index_Type'Pos (Container.Last);
386 Count1 : constant Int'Base := Count_Type'Pos (Count);
387 Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
388 N : constant Int'Base := Int'Min (Count1, Count2);
390 J_As_Int : constant Int'Base := I_As_Int + N;
393 if J_As_Int > Old_Last_As_Int then
394 Container.Last := Index - 1;
398 EA : Elements_Array renames Container.Elements;
400 II : constant Int'Base := I_As_Int - Int (No_Index);
401 I : constant Count_Type := Count_Type (II);
403 JJ : constant Int'Base := J_As_Int - Int (No_Index);
404 J : constant Count_Type := Count_Type (JJ);
406 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
407 New_Last : constant Index_Type :=
408 Index_Type (New_Last_As_Int);
410 KK : constant Int := New_Last_As_Int - Int (No_Index);
411 K : constant Count_Type := Count_Type (KK);
414 EA (I .. K) := EA (J .. Length (Container));
415 Container.Last := New_Last;
422 (Container : in out Vector;
423 Position : in out Cursor;
424 Count : Count_Type := 1)
428 if not Position.Valid then
429 raise Constraint_Error with "Position cursor has no element";
432 if Position.Index > Container.Last then
433 raise Program_Error with "Position index is out of range";
436 Delete (Container, Position.Index, Count);
437 Position := No_Element;
444 procedure Delete_First
445 (Container : in out Vector;
446 Count : Count_Type := 1)
454 if Count >= Length (Container) then
459 Delete (Container, Index_Type'First, Count);
466 procedure Delete_Last
467 (Container : in out Vector;
468 Count : Count_Type := 1)
478 if Container.Busy > 0 then
479 raise Program_Error with
480 "attempt to tamper with elements (vector is busy)";
483 Index := Int'Base (Container.Last) - Int'Base (Count);
485 if Index < Index_Type'Pos (Index_Type'First) then
486 Container.Last := No_Index;
488 Container.Last := Index_Type (Index);
498 Index : Index_Type) return Element_Type
501 if Index > Container.Last then
502 raise Constraint_Error with "Index is out of range";
506 II : constant Int'Base := Int (Index) - Int (No_Index);
507 I : constant Count_Type := Count_Type (II);
511 return Get_Element (Container, I);
517 Position : Cursor) return Element_Type
519 Lst : constant Index_Type := Last_Index (Container);
521 if not Position.Valid then
522 raise Constraint_Error with "Position cursor has no element";
525 if Position.Index > Lst then
526 raise Constraint_Error with "Position cursor is out of range";
530 II : constant Int'Base := Int (Position.Index) - Int (No_Index);
531 I : constant Count_Type := Count_Type (II);
535 return Get_Element (Container, I);
546 Position : Cursor := No_Element) return Cursor
549 Last : constant Index_Type := Last_Index (Container);
553 if Position.Valid then
554 if Position.Index > Last_Index (Container) then
555 raise Program_Error with "Position index is out of range";
559 K := Count_Type (Int (Position.Index) - Int (No_Index));
561 for J in Position.Index .. Last loop
562 if Get_Element (Container, K) = Item then
563 return Cursor'(Index => J, others => <>);
579 Index : Index_Type := Index_Type'First) return Extended_Index
582 Last : constant Index_Type := Last_Index (Container);
586 K := Count_Type (Int (Index) - Int (No_Index));
587 for Indx in Index .. Last loop
588 if Get_Element (Container, K) = Item then
601 function First (Container : Vector) return Cursor is
603 if Is_Empty (Container) then
607 return (True, Index_Type'First);
614 function First_Element (Container : Vector) return Element_Type is
616 if Is_Empty (Container) then
617 raise Constraint_Error with "Container is empty";
620 return Get_Element (Container, 1);
627 function First_Index (Container : Vector) return Index_Type is
628 pragma Unreferenced (Container);
630 return Index_Type'First;
633 ---------------------
634 -- Generic_Sorting --
635 ---------------------
637 package body Generic_Sorting is
643 function Is_Sorted (Container : Vector) return Boolean is
644 Last : constant Index_Type := Last_Index (Container);
647 if Container.Last <= Last then
652 L : constant Capacity_Subtype := Length (Container);
655 for J in Count_Type range 1 .. L - 1 loop
656 if Get_Element (Container, J + 1)
657 < Get_Element (Container, J) then
670 procedure Merge (Target, Source : in out Vector) is
674 TA : Elements_Array renames Target.Elements;
675 SA : Elements_Array renames Source.Elements;
681 -- if Target.Last < Index_Type'First then
682 -- Move (Target => Target, Source => Source);
686 if Target'Address = Source'Address then
690 if Source.Last < Index_Type'First then
694 -- I think we're missing this check in a-convec.adb... ???
695 if Target.Busy > 0 then
696 raise Program_Error with
697 "attempt to tamper with elements (vector is busy)";
700 if Source.Busy > 0 then
701 raise Program_Error with
702 "attempt to tamper with elements (vector is busy)";
705 I := Length (Target);
706 Target.Set_Length (I + Length (Source));
708 J := Length (Target);
709 while not Source.Is_Empty loop
710 pragma Assert (Length (Source) <= 1
711 or else not (SA (Length (Source)) <
712 SA (Length (Source) - 1)));
715 TA (1 .. J) := SA (1 .. Length (Source));
716 Source.Last := No_Index;
720 pragma Assert (I <= 1
721 or else not (TA (I) < TA (I - 1)));
723 if SA (Length (Source)) < TA (I) then
728 TA (J) := SA (Length (Source));
729 Source.Last := Source.Last - 1;
741 procedure Sort (Container : in out Vector)
744 new Generic_Array_Sort
745 (Index_Type => Count_Type,
746 Element_Type => Element_Type,
747 Array_Type => Elements_Array,
751 if Container.Last <= Index_Type'First then
755 if Container.Lock > 0 then
756 raise Program_Error with
757 "attempt to tamper with cursors (vector is locked)";
760 Sort (Container.Elements (1 .. Length (Container)));
771 Position : Count_Type) return Element_Type is
774 return Container.Elements (Position);
784 Position : Cursor) return Boolean is
786 if not Position.Valid then
790 return Position.Index <= Last_Index (Container);
798 (Container : in out Vector;
799 Before : Extended_Index;
800 New_Item : Element_Type;
801 Count : Count_Type := 1)
803 N : constant Int := Count_Type'Pos (Count);
805 First : constant Int := Int (Index_Type'First);
806 New_Last_As_Int : Int'Base;
807 New_Last : Index_Type;
809 Max_Length : constant UInt := UInt (Container.Capacity);
813 if Before < Index_Type'First then
814 raise Constraint_Error with
815 "Before index is out of range (too small)";
818 if Before > Container.Last
819 and then Before > Container.Last + 1
821 raise Constraint_Error with
822 "Before index is out of range (too large)";
830 Old_Last_As_Int : constant Int := Int (Container.Last);
833 if Old_Last_As_Int > Int'Last - N then
834 raise Constraint_Error with "new length is out of range";
837 New_Last_As_Int := Old_Last_As_Int + N;
839 if New_Last_As_Int > Int (Index_Type'Last) then
840 raise Constraint_Error with "new length is out of range";
843 New_Length := UInt (New_Last_As_Int - First + Int'(1));
845 if New_Length > Max_Length then
846 raise Constraint_Error with "new length is out of range";
849 New_Last := Index_Type (New_Last_As_Int);
851 -- Resolve issue of capacity vs. max index ???
854 if Container.Busy > 0 then
855 raise Program_Error with
856 "attempt to tamper with elements (vector is busy)";
860 EA : Elements_Array renames Container.Elements;
862 BB : constant Int'Base := Int (Before) - Int (No_Index);
863 B : constant Count_Type := Count_Type (BB);
865 LL : constant Int'Base := New_Last_As_Int - Int (No_Index);
866 L : constant Count_Type := Count_Type (LL);
869 if Before <= Container.Last then
871 II : constant Int'Base := BB + N;
872 I : constant Count_Type := Count_Type (II);
875 EA (I .. L) := EA (B .. Length (Container));
876 EA (B .. I - 1) := (others => New_Item);
880 EA (B .. L) := (others => New_Item);
884 Container.Last := New_Last;
888 (Container : in out Vector;
889 Before : Extended_Index;
892 N : constant Count_Type := Length (New_Item);
896 if Before < Index_Type'First then
897 raise Constraint_Error with
898 "Before index is out of range (too small)";
901 if Before > Container.Last
902 and then Before > Container.Last + 1
904 raise Constraint_Error with
905 "Before index is out of range (too large)";
912 Insert_Space (Container, Before, Count => N);
915 Dst_Last_As_Int : constant Int'Base :=
916 Int (Before) + Int (N) - 1 - Int (No_Index);
918 Dst_Last : constant Count_Type := Count_Type (Dst_Last_As_Int);
920 BB : constant Int'Base := Int (Before) - Int (No_Index);
921 B : constant Count_Type := Count_Type (BB);
925 if Container'Address /= New_Item'Address then
926 Container.Elements (B .. Dst_Last) :=
927 New_Item.Elements (1 .. N);
933 Src : Elements_Array renames Container.Elements (1 .. B - 1);
935 Index_As_Int : constant Int'Base := BB + Src'Length - 1;
937 Index : constant Count_Type := Count_Type (Index_As_Int);
939 Dst : Elements_Array renames Container.Elements (B .. Index);
945 if Dst_Last = Length (Container) then
950 Src : Elements_Array renames
952 (Dst_Last + 1 .. Length (Container));
954 Index_As_Int : constant Int'Base :=
955 Dst_Last_As_Int - Src'Length + 1;
957 Index : constant Count_Type := Count_Type (Index_As_Int);
959 Dst : Elements_Array renames
960 Container.Elements (Index .. Dst_Last);
969 (Container : in out Vector;
973 Index : Index_Type'Base;
977 if Is_Empty (New_Item) then
982 or else Before.Index > Container.Last
984 if Container.Last = Index_Type'Last then
985 raise Constraint_Error with
986 "vector is already at its maximum length";
989 Index := Container.Last + 1;
992 Index := Before.Index;
995 Insert (Container, Index, New_Item);
999 (Container : in out Vector;
1002 Position : out Cursor)
1004 Index : Index_Type'Base;
1008 if Is_Empty (New_Item) then
1010 or else Before.Index > Container.Last
1012 Position := No_Element;
1014 Position := (True, Before.Index);
1021 or else Before.Index > Container.Last
1023 if Container.Last = Index_Type'Last then
1024 raise Constraint_Error with
1025 "vector is already at its maximum length";
1028 Index := Container.Last + 1;
1031 Index := Before.Index;
1034 Insert (Container, Index, New_Item);
1036 Position := Cursor'(True, Index);
1040 (Container : in out Vector;
1042 New_Item : Element_Type;
1043 Count : Count_Type := 1)
1045 Index : Index_Type'Base;
1054 or else Before.Index > Container.Last
1056 if Container.Last = Index_Type'Last then
1057 raise Constraint_Error with
1058 "vector is already at its maximum length";
1061 Index := Container.Last + 1;
1064 Index := Before.Index;
1067 Insert (Container, Index, New_Item, Count);
1071 (Container : in out Vector;
1073 New_Item : Element_Type;
1074 Position : out Cursor;
1075 Count : Count_Type := 1)
1077 Index : Index_Type'Base;
1083 or else Before.Index > Container.Last
1085 Position := No_Element;
1087 Position := (True, Before.Index);
1094 or else Before.Index > Container.Last
1096 if Container.Last = Index_Type'Last then
1097 raise Constraint_Error with
1098 "vector is already at its maximum length";
1101 Index := Container.Last + 1;
1104 Index := Before.Index;
1107 Insert (Container, Index, New_Item, Count);
1109 Position := Cursor'(True, Index);
1113 (Container : in out Vector;
1114 Before : Extended_Index;
1115 Count : Count_Type := 1)
1117 New_Item : Element_Type; -- Default-initialized value
1118 pragma Warnings (Off, New_Item);
1121 Insert (Container, Before, New_Item, Count);
1125 (Container : in out Vector;
1127 Position : out Cursor;
1128 Count : Count_Type := 1)
1130 New_Item : Element_Type; -- Default-initialized value
1131 pragma Warnings (Off, New_Item);
1134 Insert (Container, Before, New_Item, Position, Count);
1141 procedure Insert_Space
1142 (Container : in out Vector;
1143 Before : Extended_Index;
1144 Count : Count_Type := 1)
1146 N : constant Int := Count_Type'Pos (Count);
1148 First : constant Int := Int (Index_Type'First);
1149 New_Last_As_Int : Int'Base;
1150 New_Last : Index_Type;
1152 Max_Length : constant UInt := UInt (Count_Type'Last);
1156 if Before < Index_Type'First then
1157 raise Constraint_Error with
1158 "Before index is out of range (too small)";
1161 if Before > Container.Last
1162 and then Before > Container.Last + 1
1164 raise Constraint_Error with
1165 "Before index is out of range (too large)";
1173 Old_Last_As_Int : constant Int := Int (Container.Last);
1176 if Old_Last_As_Int > Int'Last - N then
1177 raise Constraint_Error with "new length is out of range";
1180 New_Last_As_Int := Old_Last_As_Int + N;
1182 if New_Last_As_Int > Int (Index_Type'Last) then
1183 raise Constraint_Error with "new length is out of range";
1186 New_Length := UInt (New_Last_As_Int - First + Int'(1));
1188 if New_Length > Max_Length then
1189 raise Constraint_Error with "new length is out of range";
1192 New_Last := Index_Type (New_Last_As_Int);
1194 -- Resolve issue of capacity vs. max index ???
1197 if Container.Busy > 0 then
1198 raise Program_Error with
1199 "attempt to tamper with elements (vector is busy)";
1203 EA : Elements_Array renames Container.Elements;
1205 BB : constant Int'Base := Int (Before) - Int (No_Index);
1206 B : constant Count_Type := Count_Type (BB);
1208 LL : constant Int'Base := New_Last_As_Int - Int (No_Index);
1209 L : constant Count_Type := Count_Type (LL);
1212 if Before <= Container.Last then
1214 II : constant Int'Base := BB + N;
1215 I : constant Count_Type := Count_Type (II);
1218 EA (I .. L) := EA (B .. Length (Container));
1223 Container.Last := New_Last;
1226 procedure Insert_Space
1227 (Container : in out Vector;
1229 Position : out Cursor;
1230 Count : Count_Type := 1)
1232 Index : Index_Type'Base;
1238 or else Before.Index > Container.Last
1240 Position := No_Element;
1242 Position := (True, Before.Index);
1249 or else Before.Index > Container.Last
1251 if Container.Last = Index_Type'Last then
1252 raise Constraint_Error with
1253 "vector is already at its maximum length";
1256 Index := Container.Last + 1;
1259 Index := Before.Index;
1262 Insert_Space (Container, Index, Count => Count);
1264 Position := Cursor'(True, Index);
1271 function Is_Empty (Container : Vector) return Boolean is
1273 return Last_Index (Container) < Index_Type'First;
1281 (Container : Vector;
1283 not null access procedure (Container : Vector; Position : Cursor))
1285 V : Vector renames Container'Unrestricted_Access.all;
1286 B : Natural renames V.Busy;
1292 for Indx in Index_Type'First .. Last_Index (Container) loop
1293 Process (Container, Cursor'(True, Indx));
1308 function Last (Container : Vector) return Cursor is
1310 if Is_Empty (Container) then
1314 return (True, Last_Index (Container));
1321 function Last_Element (Container : Vector) return Element_Type is
1323 if Is_Empty (Container) then
1324 raise Constraint_Error with "Container is empty";
1327 return Get_Element (Container, Length (Container));
1334 function Last_Index (Container : Vector) return Extended_Index is
1336 return Container.Last;
1343 function Length (Container : Vector) return Capacity_Subtype is
1344 L : constant Int := Int (Last_Index (Container));
1345 F : constant Int := Int (Index_Type'First);
1346 N : constant Int'Base := L - F + 1;
1349 return Capacity_Subtype (N);
1356 function Left (Container : Vector; Position : Cursor) return Vector is
1357 C : Vector (Container.Capacity) :=
1358 Copy (Container, Container.Capacity);
1360 if Position = No_Element then
1363 if not Has_Element (Container, Position) then
1364 raise Constraint_Error;
1367 while C.Last /= Position.Index - 1 loop
1378 (Target : in out Vector;
1379 Source : in out Vector)
1381 N : constant Count_Type := Length (Source);
1385 if Target'Address = Source'Address then
1389 if Target.Busy > 0 then
1390 raise Program_Error with
1391 "attempt to tamper with elements (Target is busy)";
1394 if Source.Busy > 0 then
1395 raise Program_Error with
1396 "attempt to tamper with elements (Source is busy)";
1399 if N > Target.Capacity then
1400 raise Constraint_Error with -- correct exception here???
1401 "length of Source is greater than capacity of Target";
1404 -- We could also write this as a loop, and incrementally
1405 -- copy elements from source to target.
1407 Target.Last := No_Index; -- in case array assignment files
1408 Target.Elements (1 .. N) := Source.Elements (1 .. N);
1410 Target.Last := Source.Last;
1411 Source.Last := No_Index;
1418 function Next (Container : Vector; Position : Cursor) return Cursor is
1420 if not Position.Valid then
1424 if Position.Index < Last_Index (Container) then
1425 return (True, Position.Index + 1);
1435 procedure Next (Container : Vector; Position : in out Cursor) is
1437 if not Position.Valid then
1441 if Position.Index < Last_Index (Container) then
1442 Position.Index := Position.Index + 1;
1444 Position := No_Element;
1452 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1454 Insert (Container, Index_Type'First, New_Item);
1458 (Container : in out Vector;
1459 New_Item : Element_Type;
1460 Count : Count_Type := 1)
1473 procedure Previous (Container : Vector; Position : in out Cursor) is
1475 if not Position.Valid then
1479 if Position.Index > Index_Type'First and
1480 Position.Index <= Last_Index (Container) then
1481 Position.Index := Position.Index - 1;
1483 Position := No_Element;
1487 function Previous (Container : Vector; Position : Cursor) return Cursor is
1489 if not Position.Valid then
1493 if Position.Index > Index_Type'First and
1494 Position.Index <= Last_Index (Container) then
1495 return (True, Position.Index - 1);
1505 procedure Query_Element
1506 (Container : Vector;
1508 Process : not null access procedure (Element : Element_Type))
1510 V : Vector renames Container'Unrestricted_Access.all;
1511 B : Natural renames V.Busy;
1512 L : Natural renames V.Lock;
1515 if Index > Last_Index (Container) then
1516 raise Constraint_Error with "Index is out of range";
1523 II : constant Int'Base := Int (Index) - Int (No_Index);
1524 I : constant Count_Type := Count_Type (II);
1527 Process (Get_Element (V, I));
1539 procedure Query_Element
1540 (Container : Vector;
1542 Process : not null access procedure (Element : Element_Type))
1545 if not Position.Valid then
1546 raise Constraint_Error with "Position cursor has no element";
1549 Query_Element (Container, Position.Index, Process);
1557 (Stream : not null access Root_Stream_Type'Class;
1558 Container : out Vector)
1560 Length : Count_Type'Base;
1561 Last : Index_Type'Base := No_Index;
1566 Count_Type'Base'Read (Stream, Length);
1569 raise Program_Error with "stream appears to be corrupt";
1572 if Length > Container.Capacity then
1573 raise Storage_Error with "not enough capacity"; -- ???
1576 for J in Count_Type range 1 .. Length loop
1578 Element_Type'Read (Stream, Container.Elements (J));
1579 Container.Last := Last;
1584 (Stream : not null access Root_Stream_Type'Class;
1585 Position : out Cursor)
1588 raise Program_Error with "attempt to stream vector cursor";
1591 ---------------------
1592 -- Replace_Element --
1593 ---------------------
1595 procedure Replace_Element
1596 (Container : in out Vector;
1598 New_Item : Element_Type)
1602 if Index > Container.Last then
1603 raise Constraint_Error with "Index is out of range";
1606 if Container.Lock > 0 then
1607 raise Program_Error with
1608 "attempt to tamper with cursors (vector is locked)";
1612 II : constant Int'Base := Int (Index) - Int (No_Index);
1613 I : constant Count_Type := Count_Type (II);
1616 Container.Elements (I) := New_Item;
1618 end Replace_Element;
1620 procedure Replace_Element
1621 (Container : in out Vector;
1623 New_Item : Element_Type)
1627 if not Position.Valid then
1628 raise Constraint_Error with "Position cursor has no element";
1631 if Position.Index > Container.Last then
1632 raise Constraint_Error with "Position cursor is out of range";
1635 if Container.Lock > 0 then
1636 raise Program_Error with
1637 "attempt to tamper with cursors (vector is locked)";
1641 II : constant Int'Base := Int (Position.Index) - Int (No_Index);
1642 I : constant Count_Type := Count_Type (II);
1645 Container.Elements (I) := New_Item;
1647 end Replace_Element;
1649 ----------------------
1650 -- Reserve_Capacity --
1651 ----------------------
1653 procedure Reserve_Capacity
1654 (Container : in out Vector;
1655 Capacity : Capacity_Subtype)
1659 if Capacity > Container.Capacity then
1660 raise Constraint_Error; -- ???
1662 end Reserve_Capacity;
1664 ----------------------
1665 -- Reverse_Elements --
1666 ----------------------
1668 procedure Reverse_Elements (Container : in out Vector) is
1671 if Length (Container) <= 1 then
1675 if Container.Lock > 0 then
1676 raise Program_Error with
1677 "attempt to tamper with cursors (vector is locked)";
1682 E : Elements_Array renames Container.Elements;
1686 J := Length (Container);
1689 EI : constant Element_Type := E (I);
1700 end Reverse_Elements;
1706 function Reverse_Find
1707 (Container : Vector;
1708 Item : Element_Type;
1709 Position : Cursor := No_Element) return Cursor
1711 Last : Index_Type'Base;
1716 if not Position.Valid
1717 or else Position.Index > Last_Index (Container)
1719 Last := Last_Index (Container);
1721 Last := Position.Index;
1724 K := Count_Type (Int (Last) - Int (No_Index));
1725 for Indx in reverse Index_Type'First .. Last loop
1726 if Get_Element (Container, K) = Item then
1727 return (True, Indx);
1735 ------------------------
1736 -- Reverse_Find_Index --
1737 ------------------------
1739 function Reverse_Find_Index
1740 (Container : Vector;
1741 Item : Element_Type;
1742 Index : Index_Type := Index_Type'Last) return Extended_Index
1744 Last : Index_Type'Base;
1748 if Index > Last_Index (Container) then
1749 Last := Last_Index (Container);
1754 K := Count_Type (Int (Last) - Int (No_Index));
1755 for Indx in reverse Index_Type'First .. Last loop
1756 if Get_Element (Container, K) = Item then
1763 end Reverse_Find_Index;
1765 ---------------------
1766 -- Reverse_Iterate --
1767 ---------------------
1769 procedure Reverse_Iterate
1770 (Container : Vector;
1772 not null access procedure (Container : Vector; Position : Cursor))
1774 V : Vector renames Container'Unrestricted_Access.all;
1775 B : Natural renames V.Busy;
1781 for Indx in reverse Index_Type'First .. Last_Index (Container) loop
1782 Process (Container, Cursor'(True, Indx));
1791 end Reverse_Iterate;
1797 function Right (Container : Vector; Position : Cursor) return Vector is
1798 C : Vector (Container.Capacity) :=
1799 Copy (Container, Container.Capacity);
1801 if Position = No_Element then
1805 if not Has_Element (Container, Position) then
1806 raise Constraint_Error;
1809 while C.Last /= Container.Last - Position.Index + 1 loop
1819 procedure Set_Length
1820 (Container : in out Vector;
1821 Length : Capacity_Subtype)
1825 if Length = Formal_Vectors.Length (Container) then
1829 if Container.Busy > 0 then
1830 raise Program_Error with
1831 "attempt to tamper with elements (vector is busy)";
1834 if Length > Container.Capacity then
1835 raise Constraint_Error; -- ???
1839 Last_As_Int : constant Int'Base :=
1840 Int (Index_Type'First) + Int (Length) - 1;
1842 Container.Last := Index_Type'Base (Last_As_Int);
1850 procedure Swap (Container : in out Vector; I, J : Index_Type) is
1853 if I > Container.Last then
1854 raise Constraint_Error with "I index is out of range";
1857 if J > Container.Last then
1858 raise Constraint_Error with "J index is out of range";
1865 if Container.Lock > 0 then
1866 raise Program_Error with
1867 "attempt to tamper with cursors (vector is locked)";
1871 II : constant Int'Base := Int (I) - Int (No_Index);
1872 JJ : constant Int'Base := Int (J) - Int (No_Index);
1874 EI : Element_Type renames Container.Elements (Count_Type (II));
1875 EJ : Element_Type renames Container.Elements (Count_Type (JJ));
1877 EI_Copy : constant Element_Type := EI;
1885 procedure Swap (Container : in out Vector; I, J : Cursor) is
1889 raise Constraint_Error with "I cursor has no element";
1893 raise Constraint_Error with "J cursor has no element";
1896 Swap (Container, I.Index, J.Index);
1904 (Container : Vector;
1905 Index : Extended_Index) return Cursor
1908 if Index not in Index_Type'First .. Last_Index (Container) then
1912 return Cursor'(True, Index);
1919 function To_Index (Position : Cursor) return Extended_Index is
1921 if not Position.Valid then
1925 return Position.Index;
1932 function To_Vector (Length : Capacity_Subtype) return Vector is
1935 return Empty_Vector;
1939 First : constant Int := Int (Index_Type'First);
1940 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
1944 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1945 raise Constraint_Error with "Length is out of range"; -- ???
1948 Last := Index_Type (Last_As_Int);
1950 return (Length, (others => <>), Last => Last,
1956 (New_Item : Element_Type;
1957 Length : Capacity_Subtype) return Vector
1961 return Empty_Vector;
1965 First : constant Int := Int (Index_Type'First);
1966 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
1970 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1971 raise Constraint_Error with "Length is out of range"; -- ???
1974 Last := Index_Type (Last_As_Int);
1976 return (Length, (others => New_Item), Last => Last,
1981 --------------------
1982 -- Update_Element --
1983 --------------------
1985 procedure Update_Element
1986 (Container : in out Vector;
1988 Process : not null access procedure (Element : in out Element_Type))
1990 B : Natural renames Container.Busy;
1991 L : Natural renames Container.Lock;
1995 if Index > Container.Last then
1996 raise Constraint_Error with "Index is out of range";
2003 II : constant Int'Base := Int (Index) - Int (No_Index);
2004 I : constant Count_Type := Count_Type (II);
2007 Process (Container.Elements (I));
2019 procedure Update_Element
2020 (Container : in out Vector;
2022 Process : not null access procedure (Element : in out Element_Type))
2025 if not Position.Valid then
2026 raise Constraint_Error with "Position cursor has no element";
2029 Update_Element (Container, Position.Index, Process);
2037 (Stream : not null access Root_Stream_Type'Class;
2041 Count_Type'Base'Write (Stream, Length (Container));
2043 for J in 1 .. Length (Container) loop
2044 Element_Type'Write (Stream, Container.Elements (J));
2049 (Stream : not null access Root_Stream_Type'Class;
2053 raise Program_Error with "attempt to stream vector cursor";
2056 end Ada.Containers.Formal_Vectors;