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, 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 if Right.K = Plain then
60 RLst := Right.First + RN - 1;
63 if Left.K = Plain then
68 LLst := Left.First + LN - 1;
77 E : constant Elements_Array (1 .. Length (Right)) :=
78 Right.Plain.Elements (RFst .. RLst);
80 return (Length (Right),
81 new Plain_Vector'(Length (Right), E,
82 Last => Right.Plain.Last, others => <>),
89 E : constant Elements_Array (1 .. Length (Left)) :=
90 Left.Plain.Elements (LFst .. LLst);
92 return (Length (Left),
93 new Plain_Vector'(Length (Left), E,
94 Last => Left.Plain.Last, others => <>),
101 N : constant Int'Base := Int (LN) + Int (RN);
102 Last_As_Int : Int'Base;
105 if Int (No_Index) > Int'Last - N then
106 raise Constraint_Error with "new length is out of range";
109 Last_As_Int := Int (No_Index) + N;
111 if Last_As_Int > Int (Index_Type'Last) then
112 raise Constraint_Error with "new length is out of range";
115 -- TODO: should check whether length > max capacity (cnt_t'last) ???
118 Last : constant Index_Type := Index_Type (Last_As_Int);
120 LE : constant Elements_Array (1 .. Length (Left)) :=
121 Left.Plain.Elements (LFst .. LLst);
123 RE : Elements_Array renames Right.Plain.Elements (RFst .. RLst);
125 Capacity : constant Count_Type := Length (Left) + Length (Right);
129 new Plain_Vector'(Capacity, LE & RE,
130 Last => Last, others => <>),
136 function "&" (Left : Vector; Right : Element_Type) return Vector is
137 LN : constant Count_Type := Length (Left);
138 Last_As_Int : Int'Base;
145 new Plain_Vector'(1, (1 .. 1 => Right),
146 Index_Type'First, others => <>),
150 if Int (Index_Type'First) > Int'Last - Int (LN) then
151 raise Constraint_Error with "new length is out of range";
154 Last_As_Int := Int (Index_Type'First) + Int (LN);
156 if Last_As_Int > Int (Index_Type'Last) then
157 raise Constraint_Error with "new length is out of range";
160 if Left.K = Plain then
165 LLst := Left.First + LN - 1;
169 Last : constant Index_Type := Index_Type (Last_As_Int);
171 LE : constant Elements_Array (1 .. LN) :=
172 Left.Plain.Elements (LFst .. LLst);
174 Capacity : constant Count_Type := Length (Left) + 1;
178 new Plain_Vector'(Capacity, LE & Right,
179 Last => Last, others => <>),
185 function "&" (Left : Element_Type; Right : Vector) return Vector is
186 RN : constant Count_Type := Length (Right);
187 Last_As_Int : Int'Base;
195 new Plain_Vector'(1, (1 .. 1 => Left),
196 Index_Type'First, others => <>),
200 if Int (Index_Type'First) > Int'Last - Int (RN) then
201 raise Constraint_Error with "new length is out of range";
204 Last_As_Int := Int (Index_Type'First) + Int (RN);
206 if Last_As_Int > Int (Index_Type'Last) then
207 raise Constraint_Error with "new length is out of range";
210 if Right.K = Plain then
215 RLst := Right.First + RN - 1;
219 Last : constant Index_Type := Index_Type (Last_As_Int);
221 RE : Elements_Array renames Right.Plain.Elements (RFst .. RLst);
223 Capacity : constant Count_Type := 1 + Length (Right);
227 new Plain_Vector'(Capacity, Left & RE,
228 Last => Last, others => <>),
233 function "&" (Left, Right : Element_Type) return Vector is
235 if Index_Type'First >= Index_Type'Last then
236 raise Constraint_Error with "new length is out of range";
240 Last : constant Index_Type := Index_Type'First + 1;
244 new Plain_Vector'(2, (Left, Right),
245 Last => Last, others => <>),
254 function "=" (Left, Right : Vector) return Boolean is
256 if Left'Address = Right'Address then
260 if Length (Left) /= Length (Right) then
264 for J in Count_Type range 1 .. Length (Left) loop
265 if Get_Element (Left, J) /= Get_Element (Right, J) then
277 procedure Append (Container : in out Vector; New_Item : Vector) is
280 if Container.K /= Plain then
281 raise Constraint_Error
282 with "Can't modify part of container";
285 if Is_Empty (New_Item) then
289 if Container.Plain.Last = Index_Type'Last then
290 raise Constraint_Error with "vector is already at its maximum length";
295 Container.Plain.Last + 1,
300 (Container : in out Vector;
301 New_Item : Element_Type;
302 Count : Count_Type := 1)
306 if Container.K /= Plain then
307 raise Constraint_Error
308 with "Can't modify part of container";
315 if Container.Plain.Last = Index_Type'Last then
316 raise Constraint_Error with "vector is already at its maximum length";
319 -- TODO: should check whether length > max capacity (cnt_t'last) ???
323 Container.Plain.Last + 1,
332 procedure Assign (Target : in out Vector; Source : Vector) is
333 LS : constant Count_Type := Length (Source);
336 if Target.K /= Plain then
337 raise Constraint_Error
338 with "Can't modify part of container";
341 if Target'Address = Source'Address then
345 if Target.Capacity < LS then
346 raise Constraint_Error;
351 if Source.K = Plain then
352 Target.Plain.Elements (1 .. LS) :=
353 Source.Plain.Elements (1 .. LS);
354 Target.Plain.Last := Source.Plain.Last;
356 Target.Plain.Elements (1 .. LS) :=
357 Source.Plain.Elements (Source.First .. (Source.First + LS - 1));
358 Target.Plain.Last := Source.Last;
367 function Capacity (Container : Vector) return Capacity_Subtype is
369 return Container.Plain.Elements'Length;
376 procedure Clear (Container : in out Vector) is
379 if Container.K /= Plain then
380 raise Constraint_Error
381 with "Can't modify part of container";
384 if Container.Plain.Busy > 0 then
385 raise Program_Error with
386 "attempt to tamper with elements (vector is busy)";
389 Container.Plain.Last := No_Index;
398 Item : Element_Type) return Boolean
401 return Find_Index (Container, Item) /= No_Index;
410 Capacity : Capacity_Subtype := 0) return Vector
412 LS : constant Count_Type := Length (Source);
413 C : Capacity_Subtype;
419 elsif Capacity >= LS then
423 raise Constraint_Error;
426 return Target : Vector (C) do
427 if Source.K = Plain then
428 Target.Plain.Elements (1 .. LS) :=
429 Source.Plain.Elements (1 .. LS);
430 Target.Plain.Last := Source.Plain.Last;
432 Target.Plain.Elements (1 .. LS) :=
433 Source.Plain.Elements (Source.First .. (Source.First + LS - 1));
434 Target.Plain.Last := Source.Last;
445 (Container : in out Vector;
446 Index : Extended_Index;
447 Count : Count_Type := 1)
451 if Container.K /= Plain then
452 raise Constraint_Error
453 with "Can't modify part of container";
456 if Index < Index_Type'First then
457 raise Constraint_Error with "Index is out of range (too small)";
460 if Index > Container.Plain.Last then
461 if Index > Container.Plain.Last + 1 then
462 raise Constraint_Error with "Index is out of range (too large)";
472 if Container.Plain.Busy > 0 then
473 raise Program_Error with
474 "attempt to tamper with elements (vector is busy)";
478 I_As_Int : constant Int := Int (Index);
479 Old_Last_As_Int : constant Int :=
480 Index_Type'Pos (Container.Plain.Last);
482 Count1 : constant Int'Base := Count_Type'Pos (Count);
483 Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
484 N : constant Int'Base := Int'Min (Count1, Count2);
486 J_As_Int : constant Int'Base := I_As_Int + N;
489 if J_As_Int > Old_Last_As_Int then
490 Container.Plain.Last := Index - 1;
494 EA : Elements_Array renames Container.Plain.Elements;
496 II : constant Int'Base := I_As_Int - Int (No_Index);
497 I : constant Count_Type := Count_Type (II);
499 JJ : constant Int'Base := J_As_Int - Int (No_Index);
500 J : constant Count_Type := Count_Type (JJ);
502 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
503 New_Last : constant Index_Type :=
504 Index_Type (New_Last_As_Int);
506 KK : constant Int := New_Last_As_Int - Int (No_Index);
507 K : constant Count_Type := Count_Type (KK);
510 EA (I .. K) := EA (J .. Length (Container));
511 Container.Plain.Last := New_Last;
518 (Container : in out Vector;
519 Position : in out Cursor;
520 Count : Count_Type := 1)
524 if Container.K /= Plain then
525 raise Constraint_Error
526 with "Can't modify part of container";
529 if not Position.Valid then
530 raise Constraint_Error with "Position cursor has no element";
533 if Position.Index > Container.Plain.Last then
534 raise Program_Error with "Position index is out of range";
537 Delete (Container, Position.Index, Count);
538 Position := No_Element;
545 procedure Delete_First
546 (Container : in out Vector;
547 Count : Count_Type := 1)
551 if Container.K /= Plain then
552 raise Constraint_Error
553 with "Can't modify part of container";
560 if Count >= Length (Container) then
565 Delete (Container, Index_Type'First, Count);
572 procedure Delete_Last
573 (Container : in out Vector;
574 Count : Count_Type := 1)
580 if Container.K /= Plain then
581 raise Constraint_Error
582 with "Can't modify part of container";
589 if Container.Plain.Busy > 0 then
590 raise Program_Error with
591 "attempt to tamper with elements (vector is busy)";
594 Index := Int'Base (Container.Plain.Last) - Int'Base (Count);
596 if Index < Index_Type'Pos (Index_Type'First) then
597 Container.Plain.Last := No_Index;
599 Container.Plain.Last := Index_Type (Index);
609 Index : Index_Type) return Element_Type
612 if Index > Container.Plain.Last then
613 raise Constraint_Error with "Index is out of range";
617 II : constant Int'Base := Int (Index) - Int (No_Index);
618 I : constant Count_Type := Count_Type (II);
622 if Container.K = Part and then
623 (I > Length (Container)) then
624 raise Constraint_Error with "Index is out of range";
627 return Get_Element (Container, I);
633 Position : Cursor) return Element_Type
635 Lst : constant Index_Type := Last_Index (Container);
637 if not Position.Valid then
638 raise Constraint_Error with "Position cursor has no element";
641 if Position.Index > Lst then
642 raise Constraint_Error with "Position cursor is out of range";
646 II : constant Int'Base := Int (Position.Index) - Int (No_Index);
647 I : constant Count_Type := Count_Type (II);
651 return Get_Element (Container, I);
662 Position : Cursor := No_Element) return Cursor
665 Last : constant Index_Type := Last_Index (Container);
669 if Position.Valid then
670 if Position.Index > Last_Index (Container) then
671 raise Program_Error with "Position index is out of range";
675 K := Count_Type (Int (Position.Index) - Int (No_Index));
677 for J in Position.Index .. Last loop
678 if Get_Element (Container, K) = Item then
679 return Cursor'(Index => J, others => <>);
695 Index : Index_Type := Index_Type'First) return Extended_Index
698 Last : constant Index_Type := Last_Index (Container);
702 K := Count_Type (Int (Index) - Int (No_Index));
703 for Indx in Index .. Last loop
704 if Get_Element (Container, K) = Item then
717 function First (Container : Vector) return Cursor is
719 if Is_Empty (Container) then
723 return (True, Index_Type'First);
730 function First_Element (Container : Vector) return Element_Type is
732 if Is_Empty (Container) then
733 raise Constraint_Error with "Container is empty";
736 return Get_Element (Container, 1);
743 function First_Index (Container : Vector) return Index_Type is
744 pragma Unreferenced (Container);
746 return Index_Type'First;
749 ---------------------
750 -- Generic_Sorting --
751 ---------------------
753 package body Generic_Sorting is
759 function Is_Sorted (Container : Vector) return Boolean is
760 Last : constant Index_Type := Last_Index (Container);
763 if Container.Plain.Last <= Last then
768 L : constant Capacity_Subtype := Length (Container);
771 for J in Count_Type range 1 .. L - 1 loop
772 if Get_Element (Container, J + 1)
773 < Get_Element (Container, J) then
786 procedure Merge (Target, Source : in out Vector) is
789 if Target.K /= Plain or Source.K /= Plain then
790 raise Constraint_Error
791 with "Can't modify part of container";
795 TA : Elements_Array renames Target.Plain.Elements;
796 SA : Elements_Array renames Source.Plain.Elements;
802 -- if Target.Last < Index_Type'First then
803 -- Move (Target => Target, Source => Source);
807 if Target'Address = Source'Address then
811 if Source.Plain.Last < Index_Type'First then
815 -- I think we're missing this check in a-convec.adb... ???
816 if Target.Plain.Busy > 0 then
817 raise Program_Error with
818 "attempt to tamper with elements (vector is busy)";
821 if Source.Plain.Busy > 0 then
822 raise Program_Error with
823 "attempt to tamper with elements (vector is busy)";
826 I := Length (Target);
827 Target.Set_Length (I + Length (Source));
829 J := Length (Target);
830 while not Source.Is_Empty loop
831 pragma Assert (Length (Source) <= 1
832 or else not (SA (Length (Source)) <
833 SA (Length (Source) - 1)));
836 TA (1 .. J) := SA (1 .. Length (Source));
837 Source.Plain.Last := No_Index;
841 pragma Assert (I <= 1
842 or else not (TA (I) < TA (I - 1)));
844 if SA (Length (Source)) < TA (I) then
849 TA (J) := SA (Length (Source));
850 Source.Plain.Last := Source.Plain.Last - 1;
862 procedure Sort (Container : in out Vector)
865 new Generic_Array_Sort
866 (Index_Type => Count_Type,
867 Element_Type => Element_Type,
868 Array_Type => Elements_Array,
873 if Container.K /= Plain then
874 raise Constraint_Error
875 with "Can't modify part of container";
878 if Container.Plain.Last <= Index_Type'First then
882 if Container.Plain.Lock > 0 then
883 raise Program_Error with
884 "attempt to tamper with cursors (vector is locked)";
887 Sort (Container.Plain.Elements (1 .. Length (Container)));
898 Position : Count_Type) return Element_Type is
900 if Container.K = Plain then
901 return Container.Plain.Elements (Position);
904 return Container.Plain.Elements (Position + Container.First - 1);
913 Position : Cursor) return Boolean is
915 if not Position.Valid then
919 return Position.Index <= Last_Index (Container);
927 (Container : in out Vector;
928 Before : Extended_Index;
929 New_Item : Element_Type;
930 Count : Count_Type := 1)
932 N : constant Int := Count_Type'Pos (Count);
934 First : constant Int := Int (Index_Type'First);
935 New_Last_As_Int : Int'Base;
936 New_Last : Index_Type;
938 Max_Length : constant UInt := UInt (Container.Capacity);
942 if Container.K /= Plain then
943 raise Constraint_Error
944 with "Can't modify part of container";
947 if Before < Index_Type'First then
948 raise Constraint_Error with
949 "Before index is out of range (too small)";
952 if Before > Container.Plain.Last
953 and then Before > Container.Plain.Last + 1
955 raise Constraint_Error with
956 "Before index is out of range (too large)";
964 Old_Last_As_Int : constant Int := Int (Container.Plain.Last);
967 if Old_Last_As_Int > Int'Last - N then
968 raise Constraint_Error with "new length is out of range";
971 New_Last_As_Int := Old_Last_As_Int + N;
973 if New_Last_As_Int > Int (Index_Type'Last) then
974 raise Constraint_Error with "new length is out of range";
977 New_Length := UInt (New_Last_As_Int - First + Int'(1));
979 if New_Length > Max_Length then
980 raise Constraint_Error with "new length is out of range";
983 New_Last := Index_Type (New_Last_As_Int);
985 -- Resolve issue of capacity vs. max index ???
988 if Container.Plain.Busy > 0 then
989 raise Program_Error with
990 "attempt to tamper with elements (vector is busy)";
994 EA : Elements_Array renames Container.Plain.Elements;
996 BB : constant Int'Base := Int (Before) - Int (No_Index);
997 B : constant Count_Type := Count_Type (BB);
999 LL : constant Int'Base := New_Last_As_Int - Int (No_Index);
1000 L : constant Count_Type := Count_Type (LL);
1003 if Before <= Container.Plain.Last then
1005 II : constant Int'Base := BB + N;
1006 I : constant Count_Type := Count_Type (II);
1009 EA (I .. L) := EA (B .. Length (Container));
1010 EA (B .. I - 1) := (others => New_Item);
1014 EA (B .. L) := (others => New_Item);
1018 Container.Plain.Last := New_Last;
1022 (Container : in out Vector;
1023 Before : Extended_Index;
1026 N : constant Count_Type := Length (New_Item);
1030 if Container.K /= Plain then
1031 raise Constraint_Error
1032 with "Can't modify part of container";
1035 if Before < Index_Type'First then
1036 raise Constraint_Error with
1037 "Before index is out of range (too small)";
1040 if Before > Container.Plain.Last
1041 and then Before > Container.Plain.Last + 1
1043 raise Constraint_Error with
1044 "Before index is out of range (too large)";
1051 Insert_Space (Container, Before, Count => N);
1054 Dst_Last_As_Int : constant Int'Base :=
1055 Int (Before) + Int (N) - 1 - Int (No_Index);
1057 Dst_Last : constant Count_Type := Count_Type (Dst_Last_As_Int);
1059 Src_Fst : Count_Type;
1060 Src_Lst : Count_Type;
1062 BB : constant Int'Base := Int (Before) - Int (No_Index);
1063 B : constant Count_Type := Count_Type (BB);
1067 if Container.K = Plain then
1071 Src_Fst := New_Item.First;
1072 Src_Lst := N + New_Item.First - 1;
1075 if Container'Address /= New_Item'Address then
1076 Container.Plain.Elements (B .. Dst_Last) :=
1077 New_Item.Plain.Elements (Src_Fst .. Src_Lst);
1083 Src : Elements_Array renames Container.Plain.Elements (1 .. B - 1);
1085 Index_As_Int : constant Int'Base := BB + Src'Length - 1;
1087 Index : constant Count_Type := Count_Type (Index_As_Int);
1089 Dst : Elements_Array renames Container.Plain.Elements (B .. Index);
1095 if Dst_Last = Length (Container) then
1100 Src : Elements_Array renames
1101 Container.Plain.Elements
1102 (Dst_Last + 1 .. Length (Container));
1104 Index_As_Int : constant Int'Base :=
1105 Dst_Last_As_Int - Src'Length + 1;
1107 Index : constant Count_Type := Count_Type (Index_As_Int);
1109 Dst : Elements_Array renames
1110 Container.Plain.Elements (Index .. Dst_Last);
1119 (Container : in out Vector;
1123 Index : Index_Type'Base;
1127 if Container.K /= Plain then
1128 raise Constraint_Error
1129 with "Can't modify part of container";
1132 if Is_Empty (New_Item) then
1137 or else Before.Index > Container.Plain.Last
1139 if Container.Plain.Last = Index_Type'Last then
1140 raise Constraint_Error with
1141 "vector is already at its maximum length";
1144 Index := Container.Plain.Last + 1;
1147 Index := Before.Index;
1150 Insert (Container, Index, New_Item);
1154 (Container : in out Vector;
1157 Position : out Cursor)
1159 Index : Index_Type'Base;
1163 if Container.K /= Plain then
1164 raise Constraint_Error
1165 with "Can't modify part of container";
1168 if Is_Empty (New_Item) then
1170 or else Before.Index > Container.Plain.Last
1172 Position := No_Element;
1174 Position := (True, Before.Index);
1181 or else Before.Index > Container.Plain.Last
1183 if Container.Plain.Last = Index_Type'Last then
1184 raise Constraint_Error with
1185 "vector is already at its maximum length";
1188 Index := Container.Plain.Last + 1;
1191 Index := Before.Index;
1194 Insert (Container, Index, New_Item);
1196 Position := Cursor'(True, Index);
1200 (Container : in out Vector;
1202 New_Item : Element_Type;
1203 Count : Count_Type := 1)
1205 Index : Index_Type'Base;
1209 if Container.K /= Plain then
1210 raise Constraint_Error
1211 with "Can't modify part of container";
1219 or else Before.Index > Container.Plain.Last
1221 if Container.Plain.Last = Index_Type'Last then
1222 raise Constraint_Error with
1223 "vector is already at its maximum length";
1226 Index := Container.Plain.Last + 1;
1229 Index := Before.Index;
1232 Insert (Container, Index, New_Item, Count);
1236 (Container : in out Vector;
1238 New_Item : Element_Type;
1239 Position : out Cursor;
1240 Count : Count_Type := 1)
1242 Index : Index_Type'Base;
1246 if Container.K /= Plain then
1247 raise Constraint_Error
1248 with "Can't modify part of container";
1253 or else Before.Index > Container.Plain.Last
1255 Position := No_Element;
1257 Position := (True, Before.Index);
1264 or else Before.Index > Container.Plain.Last
1266 if Container.Plain.Last = Index_Type'Last then
1267 raise Constraint_Error with
1268 "vector is already at its maximum length";
1271 Index := Container.Plain.Last + 1;
1274 Index := Before.Index;
1277 Insert (Container, Index, New_Item, Count);
1279 Position := Cursor'(True, Index);
1283 (Container : in out Vector;
1284 Before : Extended_Index;
1285 Count : Count_Type := 1)
1287 New_Item : Element_Type; -- Default-initialized value
1288 pragma Warnings (Off, New_Item);
1291 Insert (Container, Before, New_Item, Count);
1295 (Container : in out Vector;
1297 Position : out Cursor;
1298 Count : Count_Type := 1)
1300 New_Item : Element_Type; -- Default-initialized value
1301 pragma Warnings (Off, New_Item);
1304 Insert (Container, Before, New_Item, Position, Count);
1311 procedure Insert_Space
1312 (Container : in out Vector;
1313 Before : Extended_Index;
1314 Count : Count_Type := 1)
1316 N : constant Int := Count_Type'Pos (Count);
1318 First : constant Int := Int (Index_Type'First);
1319 New_Last_As_Int : Int'Base;
1320 New_Last : Index_Type;
1322 Max_Length : constant UInt := UInt (Count_Type'Last);
1326 if Container.K /= Plain then
1327 raise Constraint_Error
1328 with "Can't modify part of container";
1331 if Before < Index_Type'First then
1332 raise Constraint_Error with
1333 "Before index is out of range (too small)";
1336 if Before > Container.Plain.Last
1337 and then Before > Container.Plain.Last + 1
1339 raise Constraint_Error with
1340 "Before index is out of range (too large)";
1348 Old_Last_As_Int : constant Int := Int (Container.Plain.Last);
1351 if Old_Last_As_Int > Int'Last - N then
1352 raise Constraint_Error with "new length is out of range";
1355 New_Last_As_Int := Old_Last_As_Int + N;
1357 if New_Last_As_Int > Int (Index_Type'Last) then
1358 raise Constraint_Error with "new length is out of range";
1361 New_Length := UInt (New_Last_As_Int - First + Int'(1));
1363 if New_Length > Max_Length then
1364 raise Constraint_Error with "new length is out of range";
1367 New_Last := Index_Type (New_Last_As_Int);
1369 -- Resolve issue of capacity vs. max index ???
1372 if Container.Plain.Busy > 0 then
1373 raise Program_Error with
1374 "attempt to tamper with elements (vector is busy)";
1378 EA : Elements_Array renames Container.Plain.Elements;
1380 BB : constant Int'Base := Int (Before) - Int (No_Index);
1381 B : constant Count_Type := Count_Type (BB);
1383 LL : constant Int'Base := New_Last_As_Int - Int (No_Index);
1384 L : constant Count_Type := Count_Type (LL);
1387 if Before <= Container.Plain.Last then
1389 II : constant Int'Base := BB + N;
1390 I : constant Count_Type := Count_Type (II);
1393 EA (I .. L) := EA (B .. Length (Container));
1398 Container.Plain.Last := New_Last;
1401 procedure Insert_Space
1402 (Container : in out Vector;
1404 Position : out Cursor;
1405 Count : Count_Type := 1)
1407 Index : Index_Type'Base;
1411 if Container.K /= Plain then
1412 raise Constraint_Error
1413 with "Can't modify part of container";
1418 or else Before.Index > Container.Plain.Last
1420 Position := No_Element;
1422 Position := (True, Before.Index);
1429 or else Before.Index > Container.Plain.Last
1431 if Container.Plain.Last = Index_Type'Last then
1432 raise Constraint_Error with
1433 "vector is already at its maximum length";
1436 Index := Container.Plain.Last + 1;
1439 Index := Before.Index;
1442 Insert_Space (Container, Index, Count => Count);
1444 Position := Cursor'(True, Index);
1451 function Is_Empty (Container : Vector) return Boolean is
1453 return Last_Index (Container) < Index_Type'First;
1461 (Container : Vector;
1463 not null access procedure (Container : Vector; Position : Cursor))
1465 V : Vector renames Container'Unrestricted_Access.all;
1466 B : Natural renames V.Plain.Busy;
1472 for Indx in Index_Type'First .. Last_Index (Container) loop
1473 Process (Container, Cursor'(True, Indx));
1488 function Last (Container : Vector) return Cursor is
1490 if Is_Empty (Container) then
1494 return (True, Last_Index (Container));
1501 function Last_Element (Container : Vector) return Element_Type is
1503 if Is_Empty (Container) then
1504 raise Constraint_Error with "Container is empty";
1507 return Get_Element (Container, Length (Container));
1514 function Last_Index (Container : Vector) return Extended_Index is
1516 if Container.K = Plain then
1517 return Container.Plain.Last;
1519 return Container.Last;
1527 function Length (Container : Vector) return Capacity_Subtype is
1528 L : constant Int := Int (Last_Index (Container));
1529 F : constant Int := Int (Index_Type'First);
1530 N : constant Int'Base := L - F + 1;
1533 return Capacity_Subtype (N);
1540 function Left (Container : Vector; Position : Cursor) return Vector is
1543 if Container.K = Plain then
1546 Fst := Container.First;
1549 if not Position.Valid then
1550 return (Container.Capacity, Container.Plain, Part, Fst,
1551 Last_Index (Container));
1554 if Position.Index > Last_Index (Container) then
1555 raise Constraint_Error with
1556 "Before index is out of range (too large)";
1559 return (Container.Capacity, Container.Plain, Part, Fst,
1560 (Position.Index - 1));
1568 (Target : in out Vector;
1569 Source : in out Vector)
1571 N : constant Count_Type := Length (Source);
1575 if Target.K /= Plain or Source.K /= Plain then
1576 raise Constraint_Error
1577 with "Can't modify part of container";
1580 if Target'Address = Source'Address then
1584 if Target.Plain.Busy > 0 then
1585 raise Program_Error with
1586 "attempt to tamper with elements (Target is busy)";
1589 if Source.Plain.Busy > 0 then
1590 raise Program_Error with
1591 "attempt to tamper with elements (Source is busy)";
1594 if N > Target.Capacity then
1595 raise Constraint_Error with -- correct exception here???
1596 "length of Source is greater than capacity of Target";
1599 -- We could also write this as a loop, and incrementally
1600 -- copy elements from source to target.
1602 Target.Plain.Last := No_Index; -- in case array assignment files
1603 Target.Plain.Elements (1 .. N) := Source.Plain.Elements (1 .. N);
1605 Target.Plain.Last := Source.Plain.Last;
1606 Source.Plain.Last := No_Index;
1613 function Next (Container : Vector; Position : Cursor) return Cursor is
1615 if not Position.Valid then
1619 if Position.Index < Last_Index (Container) then
1620 return (True, Position.Index + 1);
1630 procedure Next (Container : Vector; Position : in out Cursor) is
1632 if not Position.Valid then
1636 if Position.Index < Last_Index (Container) then
1637 Position.Index := Position.Index + 1;
1639 Position := No_Element;
1647 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1649 Insert (Container, Index_Type'First, New_Item);
1653 (Container : in out Vector;
1654 New_Item : Element_Type;
1655 Count : Count_Type := 1)
1668 procedure Previous (Container : Vector; Position : in out Cursor) is
1670 if not Position.Valid then
1674 if Position.Index > Index_Type'First and
1675 Position.Index <= Last_Index (Container) then
1676 Position.Index := Position.Index - 1;
1678 Position := No_Element;
1682 function Previous (Container : Vector; Position : Cursor) return Cursor is
1684 if not Position.Valid then
1688 if Position.Index > Index_Type'First and
1689 Position.Index <= Last_Index (Container) then
1690 return (True, Position.Index - 1);
1700 procedure Query_Element
1701 (Container : Vector;
1703 Process : not null access procedure (Element : Element_Type))
1705 V : Vector renames Container'Unrestricted_Access.all;
1706 B : Natural renames V.Plain.Busy;
1707 L : Natural renames V.Plain.Lock;
1710 if Index > Last_Index (Container) then
1711 raise Constraint_Error with "Index is out of range";
1718 II : constant Int'Base := Int (Index) - Int (No_Index);
1719 I : constant Count_Type := Count_Type (II);
1722 Process (Get_Element (V, I));
1734 procedure Query_Element
1735 (Container : Vector;
1737 Process : not null access procedure (Element : Element_Type))
1740 if not Position.Valid then
1741 raise Constraint_Error with "Position cursor has no element";
1744 Query_Element (Container, Position.Index, Process);
1752 (Stream : not null access Root_Stream_Type'Class;
1753 Container : out Vector)
1755 Length : Count_Type'Base;
1756 Last : Index_Type'Base := No_Index;
1761 Count_Type'Base'Read (Stream, Length);
1764 raise Program_Error with "stream appears to be corrupt";
1767 if Length > Container.Capacity then
1768 raise Storage_Error with "not enough capacity"; -- ???
1771 for J in Count_Type range 1 .. Length loop
1773 Element_Type'Read (Stream, Container.Plain.Elements (J));
1774 Container.Plain.Last := Last;
1779 (Stream : not null access Root_Stream_Type'Class;
1780 Position : out Cursor)
1783 raise Program_Error with "attempt to stream vector cursor";
1786 ---------------------
1787 -- Replace_Element --
1788 ---------------------
1790 procedure Replace_Element
1791 (Container : in out Vector;
1793 New_Item : Element_Type)
1796 if Container.K /= Plain then
1797 raise Constraint_Error
1798 with "Can't modify part of container";
1801 if Index > Container.Plain.Last then
1802 raise Constraint_Error with "Index is out of range";
1805 if Container.Plain.Lock > 0 then
1806 raise Program_Error with
1807 "attempt to tamper with cursors (vector is locked)";
1811 II : constant Int'Base := Int (Index) - Int (No_Index);
1812 I : constant Count_Type := Count_Type (II);
1815 Container.Plain.Elements (I) := New_Item;
1817 end Replace_Element;
1819 procedure Replace_Element
1820 (Container : in out Vector;
1822 New_Item : Element_Type)
1825 if Container.K /= Plain then
1826 raise Constraint_Error
1827 with "Can't modify part of container";
1830 if not Position.Valid then
1831 raise Constraint_Error with "Position cursor has no element";
1834 if Position.Index > Container.Plain.Last then
1835 raise Constraint_Error with "Position cursor is out of range";
1838 if Container.Plain.Lock > 0 then
1839 raise Program_Error with
1840 "attempt to tamper with cursors (vector is locked)";
1844 II : constant Int'Base := Int (Position.Index) - Int (No_Index);
1845 I : constant Count_Type := Count_Type (II);
1848 Container.Plain.Elements (I) := New_Item;
1850 end Replace_Element;
1852 ----------------------
1853 -- Reserve_Capacity --
1854 ----------------------
1856 procedure Reserve_Capacity
1857 (Container : in out Vector;
1858 Capacity : Capacity_Subtype)
1861 if Container.K /= Plain then
1862 raise Constraint_Error
1863 with "Can't modify part of container";
1866 if Capacity > Container.Capacity then
1867 raise Constraint_Error; -- ???
1869 end Reserve_Capacity;
1871 ----------------------
1872 -- Reverse_Elements --
1873 ----------------------
1875 procedure Reverse_Elements (Container : in out Vector) is
1877 if Container.K /= Plain then
1878 raise Constraint_Error
1879 with "Can't modify part of container";
1882 if Length (Container) <= 1 then
1886 if Container.Plain.Lock > 0 then
1887 raise Program_Error with
1888 "attempt to tamper with cursors (vector is locked)";
1893 E : Elements_Array renames Container.Plain.Elements;
1897 J := Length (Container);
1900 EI : constant Element_Type := E (I);
1911 end Reverse_Elements;
1917 function Reverse_Find
1918 (Container : Vector;
1919 Item : Element_Type;
1920 Position : Cursor := No_Element) return Cursor
1922 Last : Index_Type'Base;
1927 if not Position.Valid
1928 or else Position.Index > Last_Index (Container)
1930 Last := Last_Index (Container);
1932 Last := Position.Index;
1935 K := Count_Type (Int (Last) - Int (No_Index));
1936 for Indx in reverse Index_Type'First .. Last loop
1937 if Get_Element (Container, K) = Item then
1938 return (True, Indx);
1946 ------------------------
1947 -- Reverse_Find_Index --
1948 ------------------------
1950 function Reverse_Find_Index
1951 (Container : Vector;
1952 Item : Element_Type;
1953 Index : Index_Type := Index_Type'Last) return Extended_Index
1955 Last : Index_Type'Base;
1959 if Index > Last_Index (Container) then
1960 Last := Last_Index (Container);
1965 K := Count_Type (Int (Last) - Int (No_Index));
1966 for Indx in reverse Index_Type'First .. Last loop
1967 if Get_Element (Container, K) = Item then
1974 end Reverse_Find_Index;
1976 ---------------------
1977 -- Reverse_Iterate --
1978 ---------------------
1980 procedure Reverse_Iterate
1981 (Container : Vector;
1983 not null access procedure (Container : Vector; Position : Cursor))
1985 V : Vector renames Container'Unrestricted_Access.all;
1986 B : Natural renames V.Plain.Busy;
1992 for Indx in reverse Index_Type'First .. Last_Index (Container) loop
1993 Process (Container, Cursor'(True, Indx));
2002 end Reverse_Iterate;
2008 function Right (Container : Vector; Position : Cursor) return Vector is
2011 if Container.K = Plain then
2014 Fst := Container.First;
2017 if not Position.Valid then
2018 return (Container.Capacity, Container.Plain, Part, Fst, No_Index);
2021 if Position.Index > Last_Index (Container) then
2022 raise Constraint_Error with
2023 "Position index is out of range (too large)";
2026 Fst := Fst + Count_Type (Int (Position.Index) - Int (No_Index)) - 1;
2028 return (Container.Capacity, Container.Plain, Part, Fst,
2029 (Last_Index (Container) - Position.Index + 1));
2036 procedure Set_Length
2037 (Container : in out Vector;
2038 Length : Capacity_Subtype)
2041 if Container.K /= Plain then
2042 raise Constraint_Error
2043 with "Can't modify part of container";
2046 if Length = Formal_Vectors.Length (Container) then
2050 if Container.Plain.Busy > 0 then
2051 raise Program_Error with
2052 "attempt to tamper with elements (vector is busy)";
2055 if Length > Container.Capacity then
2056 raise Constraint_Error; -- ???
2060 Last_As_Int : constant Int'Base :=
2061 Int (Index_Type'First) + Int (Length) - 1;
2063 Container.Plain.Last := Index_Type'Base (Last_As_Int);
2071 procedure Swap (Container : in out Vector; I, J : Index_Type) is
2073 if Container.K /= Plain then
2074 raise Constraint_Error
2075 with "Can't modify part of container";
2078 if I > Container.Plain.Last then
2079 raise Constraint_Error with "I index is out of range";
2082 if J > Container.Plain.Last then
2083 raise Constraint_Error with "J index is out of range";
2090 if Container.Plain.Lock > 0 then
2091 raise Program_Error with
2092 "attempt to tamper with cursors (vector is locked)";
2096 II : constant Int'Base := Int (I) - Int (No_Index);
2097 JJ : constant Int'Base := Int (J) - Int (No_Index);
2099 EI : Element_Type renames Container.Plain.Elements (Count_Type (II));
2100 EJ : Element_Type renames Container.Plain.Elements (Count_Type (JJ));
2102 EI_Copy : constant Element_Type := EI;
2110 procedure Swap (Container : in out Vector; I, J : Cursor) is
2112 if Container.K /= Plain then
2113 raise Constraint_Error
2114 with "Can't modify part of container";
2118 raise Constraint_Error with "I cursor has no element";
2122 raise Constraint_Error with "J cursor has no element";
2125 Swap (Container, I.Index, J.Index);
2133 (Container : Vector;
2134 Index : Extended_Index) return Cursor
2137 if Index not in Index_Type'First .. Last_Index (Container) then
2141 return Cursor'(True, Index);
2148 function To_Index (Position : Cursor) return Extended_Index is
2150 if not Position.Valid then
2154 return Position.Index;
2161 function To_Vector (Length : Capacity_Subtype) return Vector is
2164 return Empty_Vector;
2168 First : constant Int := Int (Index_Type'First);
2169 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2173 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2174 raise Constraint_Error with "Length is out of range"; -- ???
2177 Last := Index_Type (Last_As_Int);
2180 new Plain_Vector'(Length, (others => <>), Last => Last,
2187 (New_Item : Element_Type;
2188 Length : Capacity_Subtype) return Vector
2192 return Empty_Vector;
2196 First : constant Int := Int (Index_Type'First);
2197 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2201 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2202 raise Constraint_Error with "Length is out of range"; -- ???
2205 Last := Index_Type (Last_As_Int);
2208 new Plain_Vector'(Length, (others => New_Item), Last => Last,
2214 --------------------
2215 -- Update_Element --
2216 --------------------
2218 procedure Update_Element
2219 (Container : in out Vector;
2221 Process : not null access procedure (Element : in out Element_Type))
2223 B : Natural renames Container.Plain.Busy;
2224 L : Natural renames Container.Plain.Lock;
2227 if Container.K /= Plain then
2228 raise Constraint_Error
2229 with "Can't modify part of container";
2232 if Index > Container.Plain.Last then
2233 raise Constraint_Error with "Index is out of range";
2240 II : constant Int'Base := Int (Index) - Int (No_Index);
2241 I : constant Count_Type := Count_Type (II);
2244 Process (Container.Plain.Elements (I));
2256 procedure Update_Element
2257 (Container : in out Vector;
2259 Process : not null access procedure (Element : in out Element_Type))
2262 if not Position.Valid then
2263 raise Constraint_Error with "Position cursor has no element";
2266 Update_Element (Container, Position.Index, Process);
2274 (Stream : not null access Root_Stream_Type'Class;
2278 Count_Type'Base'Write (Stream, Length (Container));
2280 for J in 1 .. Length (Container) loop
2281 Element_Type'Write (Stream, Container.Plain.Elements (J));
2286 (Stream : not null access Root_Stream_Type'Class;
2290 raise Program_Error with "attempt to stream vector cursor";
2293 end Ada.Containers.Formal_Vectors;