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
, Last
=> Right
.Last
, others => <>);
64 E
: constant Elements_Array
(1 .. Length
(Left
)) :=
65 Left
.Elements
(1 .. LN
);
67 return (Length
(Left
), E
, Last
=> Left
.Last
, others => <>);
72 N
: constant Int
'Base := Int
(LN
) + Int
(RN
);
73 Last_As_Int
: Int
'Base;
76 if Int
(No_Index
) > Int
'Last - N
then
77 raise Constraint_Error
with "new length is out of range";
80 Last_As_Int
:= Int
(No_Index
) + N
;
82 if Last_As_Int
> Int
(Index_Type
'Last) then
83 raise Constraint_Error
with "new length is out of range";
86 -- TODO: should check whether length > max capacity (cnt_t'last) ???
89 Last
: constant Index_Type
:= Index_Type
(Last_As_Int
);
91 LE
: constant Elements_Array
(1 .. LN
) := Left
.Elements
(1 .. LN
);
92 RE
: Elements_Array
renames Right
.Elements
(1 .. RN
);
94 Capacity
: constant Count_Type
:= Length
(Left
) + Length
(Right
);
97 return (Capacity
, LE
& RE
, Last
=> Last
, others => <>);
102 function "&" (Left
: Vector
; Right
: Element_Type
) return Vector
is
103 LN
: constant Count_Type
:= Length
(Left
);
104 Last_As_Int
: Int
'Base;
108 return (1, (1 .. 1 => Right
), Index_Type
'First, others => <>);
111 if Int
(Index_Type
'First) > Int
'Last - Int
(LN
) then
112 raise Constraint_Error
with "new length is out of range";
115 Last_As_Int
:= Int
(Index_Type
'First) + Int
(LN
);
117 if Last_As_Int
> Int
(Index_Type
'Last) then
118 raise Constraint_Error
with "new length is out of range";
122 Last
: constant Index_Type
:= Index_Type
(Last_As_Int
);
123 LE
: constant Elements_Array
(1 .. LN
) := Left
.Elements
(1 .. LN
);
125 Capacity
: constant Count_Type
:= Length
(Left
) + 1;
128 return (Capacity
, LE
& Right
, Last
=> Last
, others => <>);
132 function "&" (Left
: Element_Type
; Right
: Vector
) return Vector
is
133 RN
: constant Count_Type
:= Length
(Right
);
134 Last_As_Int
: Int
'Base;
138 return (1, (1 .. 1 => Left
),
139 Index_Type
'First, others => <>);
142 if Int
(Index_Type
'First) > Int
'Last - Int
(RN
) then
143 raise Constraint_Error
with "new length is out of range";
146 Last_As_Int
:= Int
(Index_Type
'First) + Int
(RN
);
148 if Last_As_Int
> Int
(Index_Type
'Last) then
149 raise Constraint_Error
with "new length is out of range";
153 Last
: constant Index_Type
:= Index_Type
(Last_As_Int
);
154 RE
: Elements_Array
renames Right
.Elements
(1 .. RN
);
155 Capacity
: constant Count_Type
:= 1 + Length
(Right
);
157 return (Capacity
, Left
& RE
, Last
=> Last
, others => <>);
161 function "&" (Left
, Right
: Element_Type
) return Vector
is
163 if Index_Type
'First >= Index_Type
'Last then
164 raise Constraint_Error
with "new length is out of range";
168 Last
: constant Index_Type
:= Index_Type
'First + 1;
170 return (2, (Left
, Right
), Last
=> Last
, others => <>);
178 function "=" (Left
, Right
: Vector
) return Boolean is
180 if Left
'Address = Right
'Address then
184 if Length
(Left
) /= Length
(Right
) then
188 for J
in Count_Type
range 1 .. Length
(Left
) loop
189 if Get_Element
(Left
, J
) /= Get_Element
(Right
, J
) then
201 procedure Append
(Container
: in out Vector
; New_Item
: Vector
) is
203 if Is_Empty
(New_Item
) then
207 if Container
.Last
= Index_Type
'Last then
208 raise Constraint_Error
with "vector is already at its maximum length";
211 Insert
(Container
, Container
.Last
+ 1, New_Item
);
215 (Container
: in out Vector
;
216 New_Item
: Element_Type
;
217 Count
: Count_Type
:= 1)
224 if Container
.Last
= Index_Type
'Last then
225 raise Constraint_Error
with "vector is already at its maximum length";
228 -- TODO: should check whether length > max capacity (cnt_t'last) ???
230 Insert
(Container
, Container
.Last
+ 1, New_Item
, Count
);
237 procedure Assign
(Target
: in out Vector
; Source
: Vector
) is
238 LS
: constant Count_Type
:= Length
(Source
);
241 if Target
'Address = Source
'Address then
245 if Target
.Capacity
< LS
then
246 raise Constraint_Error
;
251 Target
.Elements
(1 .. LS
) := Source
.Elements
(1 .. LS
);
252 Target
.Last
:= Source
.Last
;
259 function Capacity
(Container
: Vector
) return Capacity_Subtype
is
261 return Container
.Elements
'Length;
268 procedure Clear
(Container
: in out Vector
) is
270 if Container
.Busy
> 0 then
271 raise Program_Error
with
272 "attempt to tamper with elements (vector is busy)";
275 Container
.Last
:= No_Index
;
284 Item
: Element_Type
) return Boolean
287 return Find_Index
(Container
, Item
) /= No_Index
;
296 Capacity
: Capacity_Subtype
:= 0) return Vector
298 LS
: constant Count_Type
:= Length
(Source
);
299 C
: Capacity_Subtype
;
304 elsif Capacity
>= LS
then
307 raise Constraint_Error
;
310 return Target
: Vector
(C
) do
311 Target
.Elements
(1 .. LS
) := Source
.Elements
(1 .. LS
);
312 Target
.Last
:= Source
.Last
;
321 (Container
: in out Vector
;
322 Index
: Extended_Index
;
323 Count
: Count_Type
:= 1)
326 if Index
< Index_Type
'First then
327 raise Constraint_Error
with "Index is out of range (too small)";
330 if Index
> Container
.Last
then
331 if Index
> Container
.Last
+ 1 then
332 raise Constraint_Error
with "Index is out of range (too large)";
342 if Container
.Busy
> 0 then
343 raise Program_Error
with
344 "attempt to tamper with elements (vector is busy)";
348 I_As_Int
: constant Int
:= Int
(Index
);
349 Old_Last_As_Int
: constant Int
:= Index_Type
'Pos (Container
.Last
);
351 Count1
: constant Int
'Base := Count_Type
'Pos (Count
);
352 Count2
: constant Int
'Base := Old_Last_As_Int
- I_As_Int
+ 1;
353 N
: constant Int
'Base := Int
'Min (Count1
, Count2
);
355 J_As_Int
: constant Int
'Base := I_As_Int
+ N
;
358 if J_As_Int
> Old_Last_As_Int
then
359 Container
.Last
:= Index
- 1;
363 EA
: Elements_Array
renames Container
.Elements
;
365 II
: constant Int
'Base := I_As_Int
- Int
(No_Index
);
366 I
: constant Count_Type
:= Count_Type
(II
);
368 JJ
: constant Int
'Base := J_As_Int
- Int
(No_Index
);
369 J
: constant Count_Type
:= Count_Type
(JJ
);
371 New_Last_As_Int
: constant Int
'Base := Old_Last_As_Int
- N
;
372 New_Last
: constant Index_Type
:=
373 Index_Type
(New_Last_As_Int
);
375 KK
: constant Int
:= New_Last_As_Int
- Int
(No_Index
);
376 K
: constant Count_Type
:= Count_Type
(KK
);
379 EA
(I
.. K
) := EA
(J
.. Length
(Container
));
380 Container
.Last
:= New_Last
;
387 (Container
: in out Vector
;
388 Position
: in out Cursor
;
389 Count
: Count_Type
:= 1)
392 if not Position
.Valid
then
393 raise Constraint_Error
with "Position cursor has no element";
396 if Position
.Index
> Container
.Last
then
397 raise Program_Error
with "Position index is out of range";
400 Delete
(Container
, Position
.Index
, Count
);
401 Position
:= No_Element
;
408 procedure Delete_First
409 (Container
: in out Vector
;
410 Count
: Count_Type
:= 1)
417 if Count
>= Length
(Container
) then
422 Delete
(Container
, Index_Type
'First, Count
);
429 procedure Delete_Last
430 (Container
: in out Vector
;
431 Count
: Count_Type
:= 1)
440 if Container
.Busy
> 0 then
441 raise Program_Error
with
442 "attempt to tamper with elements (vector is busy)";
445 Index
:= Int
'Base (Container
.Last
) - Int
'Base (Count
);
447 if Index
< Index_Type
'Pos (Index_Type
'First) then
448 Container
.Last
:= No_Index
;
450 Container
.Last
:= Index_Type
(Index
);
460 Index
: Index_Type
) return Element_Type
463 if Index
> Container
.Last
then
464 raise Constraint_Error
with "Index is out of range";
468 II
: constant Int
'Base := Int
(Index
) - Int
(No_Index
);
469 I
: constant Count_Type
:= Count_Type
(II
);
471 return Get_Element
(Container
, I
);
477 Position
: Cursor
) return Element_Type
479 Lst
: constant Index_Type
:= Last_Index
(Container
);
482 if not Position
.Valid
then
483 raise Constraint_Error
with "Position cursor has no element";
486 if Position
.Index
> Lst
then
487 raise Constraint_Error
with "Position cursor is out of range";
491 II
: constant Int
'Base := Int
(Position
.Index
) - Int
(No_Index
);
492 I
: constant Count_Type
:= Count_Type
(II
);
494 return Get_Element
(Container
, I
);
505 Position
: Cursor
:= No_Element
) return Cursor
508 Last
: constant Index_Type
:= Last_Index
(Container
);
511 if Position
.Valid
then
512 if Position
.Index
> Last_Index
(Container
) then
513 raise Program_Error
with "Position index is out of range";
517 K
:= Count_Type
(Int
(Position
.Index
) - Int
(No_Index
));
519 for J
in Position
.Index
.. Last
loop
520 if Get_Element
(Container
, K
) = Item
then
521 return Cursor
'(Index => J, others => <>);
537 Index : Index_Type := Index_Type'First) return Extended_Index
540 Last : constant Index_Type := Last_Index (Container);
544 K := Count_Type (Int (Index) - Int (No_Index));
545 for Indx in Index .. Last loop
546 if Get_Element (Container, K) = Item then
560 function First (Container : Vector) return Cursor is
562 if Is_Empty (Container) then
566 return (True, Index_Type'First);
573 function First_Element (Container : Vector) return Element_Type is
575 if Is_Empty (Container) then
576 raise Constraint_Error with "Container is empty";
579 return Get_Element (Container, 1);
586 function First_Index (Container : Vector) return Index_Type is
587 pragma Unreferenced (Container);
589 return Index_Type'First;
592 ---------------------
593 -- Generic_Sorting --
594 ---------------------
596 package body Generic_Sorting is
602 function Is_Sorted (Container : Vector) return Boolean is
603 Last : constant Index_Type := Last_Index (Container);
606 if Container.Last <= Last then
611 L : constant Capacity_Subtype := Length (Container);
613 for J in Count_Type range 1 .. L - 1 loop
614 if Get_Element (Container, J + 1) <
615 Get_Element (Container, J)
629 procedure Merge (Target, Source : in out Vector) is
633 TA : Elements_Array renames Target.Elements;
634 SA : Elements_Array renames Source.Elements;
640 -- if Target.Last < Index_Type'First then
641 -- Move (Target => Target, Source => Source);
645 if Target'Address = Source'Address then
649 if Source.Last < Index_Type'First then
653 -- I think we're missing this check in a-convec.adb... ???
655 if Target.Busy > 0 then
656 raise Program_Error with
657 "attempt to tamper with elements (vector is busy)";
660 if Source.Busy > 0 then
661 raise Program_Error with
662 "attempt to tamper with elements (vector is busy)";
665 I := Length (Target);
666 Target.Set_Length (I + Length (Source));
668 J := Length (Target);
669 while not Source.Is_Empty loop
670 pragma Assert (Length (Source) <= 1
671 or else not (SA (Length (Source)) <
672 SA (Length (Source) - 1)));
675 TA (1 .. J) := SA (1 .. Length (Source));
676 Source.Last := No_Index;
680 pragma Assert (I <= 1 or else not (TA (I) < TA (I - 1)));
682 if SA (Length (Source)) < TA (I) then
687 TA (J) := SA (Length (Source));
688 Source.Last := Source.Last - 1;
700 procedure Sort (Container : in out Vector)
703 new Generic_Array_Sort
704 (Index_Type => Count_Type,
705 Element_Type => Element_Type,
706 Array_Type => Elements_Array,
710 if Container.Last <= Index_Type'First then
714 if Container.Lock > 0 then
715 raise Program_Error with
716 "attempt to tamper with cursors (vector is locked)";
719 Sort (Container.Elements (1 .. Length (Container)));
730 Position : Count_Type) return Element_Type
733 return Container.Elements (Position);
742 Position : Cursor) return Boolean
745 if not Position.Valid then
748 return Position.Index <= Last_Index (Container);
757 (Container : in out Vector;
758 Before : Extended_Index;
759 New_Item : Element_Type;
760 Count : Count_Type := 1)
762 N : constant Int := Count_Type'Pos (Count);
764 First : constant Int := Int (Index_Type'First);
765 New_Last_As_Int : Int'Base;
766 New_Last : Index_Type;
768 Max_Length : constant UInt := UInt (Container.Capacity);
771 if Before < Index_Type'First then
772 raise Constraint_Error with
773 "Before index is out of range (too small)";
776 if Before > Container.Last
777 and then Before > Container.Last + 1
779 raise Constraint_Error with
780 "Before index is out of range (too large)";
788 Old_Last_As_Int : constant Int := Int (Container.Last);
791 if Old_Last_As_Int > Int'Last - N then
792 raise Constraint_Error with "new length is out of range";
795 New_Last_As_Int := Old_Last_As_Int + N;
797 if New_Last_As_Int > Int (Index_Type'Last) then
798 raise Constraint_Error with "new length is out of range";
801 New_Length := UInt (New_Last_As_Int - First + Int'(1));
803 if New_Length
> Max_Length
then
804 raise Constraint_Error
with "new length is out of range";
807 New_Last
:= Index_Type
(New_Last_As_Int
);
809 -- Resolve issue of capacity vs. max index ???
812 if Container
.Busy
> 0 then
813 raise Program_Error
with
814 "attempt to tamper with elements (vector is busy)";
818 EA
: Elements_Array
renames Container
.Elements
;
820 BB
: constant Int
'Base := Int
(Before
) - Int
(No_Index
);
821 B
: constant Count_Type
:= Count_Type
(BB
);
823 LL
: constant Int
'Base := New_Last_As_Int
- Int
(No_Index
);
824 L
: constant Count_Type
:= Count_Type
(LL
);
827 if Before
<= Container
.Last
then
829 II
: constant Int
'Base := BB
+ N
;
830 I
: constant Count_Type
:= Count_Type
(II
);
832 EA
(I
.. L
) := EA
(B
.. Length
(Container
));
833 EA
(B
.. I
- 1) := (others => New_Item
);
837 EA
(B
.. L
) := (others => New_Item
);
841 Container
.Last
:= New_Last
;
845 (Container
: in out Vector
;
846 Before
: Extended_Index
;
849 N
: constant Count_Type
:= Length
(New_Item
);
852 if Before
< Index_Type
'First then
853 raise Constraint_Error
with
854 "Before index is out of range (too small)";
857 if Before
> Container
.Last
858 and then Before
> Container
.Last
+ 1
860 raise Constraint_Error
with
861 "Before index is out of range (too large)";
868 Insert_Space
(Container
, Before
, Count
=> N
);
871 Dst_Last_As_Int
: constant Int
'Base :=
872 Int
(Before
) + Int
(N
) - 1 - Int
(No_Index
);
874 Dst_Last
: constant Count_Type
:= Count_Type
(Dst_Last_As_Int
);
876 BB
: constant Int
'Base := Int
(Before
) - Int
(No_Index
);
877 B
: constant Count_Type
:= Count_Type
(BB
);
880 if Container
'Address /= New_Item
'Address then
881 Container
.Elements
(B
.. Dst_Last
) := New_Item
.Elements
(1 .. N
);
886 Src
: Elements_Array
renames Container
.Elements
(1 .. B
- 1);
888 Index_As_Int
: constant Int
'Base := BB
+ Src
'Length - 1;
890 Index
: constant Count_Type
:= Count_Type
(Index_As_Int
);
892 Dst
: Elements_Array
renames Container
.Elements
(B
.. Index
);
898 if Dst_Last
= Length
(Container
) then
903 Src
: Elements_Array
renames
904 Container
.Elements
(Dst_Last
+ 1 .. Length
(Container
));
906 Index_As_Int
: constant Int
'Base :=
907 Dst_Last_As_Int
- Src
'Length + 1;
909 Index
: constant Count_Type
:= Count_Type
(Index_As_Int
);
911 Dst
: Elements_Array
renames
912 Container
.Elements
(Index
.. Dst_Last
);
921 (Container
: in out Vector
;
925 Index
: Index_Type
'Base;
928 if Is_Empty
(New_Item
) then
933 or else Before
.Index
> Container
.Last
935 if Container
.Last
= Index_Type
'Last then
936 raise Constraint_Error
with
937 "vector is already at its maximum length";
940 Index
:= Container
.Last
+ 1;
943 Index
:= Before
.Index
;
946 Insert
(Container
, Index
, New_Item
);
950 (Container
: in out Vector
;
953 Position
: out Cursor
)
955 Index
: Index_Type
'Base;
958 if Is_Empty
(New_Item
) then
960 or else Before
.Index
> Container
.Last
962 Position
:= No_Element
;
964 Position
:= (True, Before
.Index
);
971 or else Before
.Index
> Container
.Last
973 if Container
.Last
= Index_Type
'Last then
974 raise Constraint_Error
with
975 "vector is already at its maximum length";
978 Index
:= Container
.Last
+ 1;
981 Index
:= Before
.Index
;
984 Insert
(Container
, Index
, New_Item
);
986 Position
:= Cursor
'(True, Index);
990 (Container : in out Vector;
992 New_Item : Element_Type;
993 Count : Count_Type := 1)
995 Index : Index_Type'Base;
1003 or else Before.Index > Container.Last
1005 if Container.Last = Index_Type'Last then
1006 raise Constraint_Error with
1007 "vector is already at its maximum length";
1010 Index := Container.Last + 1;
1013 Index := Before.Index;
1016 Insert (Container, Index, New_Item, Count);
1020 (Container : in out Vector;
1022 New_Item : Element_Type;
1023 Position : out Cursor;
1024 Count : Count_Type := 1)
1026 Index : Index_Type'Base;
1031 or else Before.Index > Container.Last
1033 Position := No_Element;
1035 Position := (True, Before.Index);
1042 or else Before.Index > Container.Last
1044 if Container.Last = Index_Type'Last then
1045 raise Constraint_Error with
1046 "vector is already at its maximum length";
1049 Index := Container.Last + 1;
1052 Index := Before.Index;
1055 Insert (Container, Index, New_Item, Count);
1057 Position := Cursor'(True, Index
);
1061 (Container
: in out Vector
;
1062 Before
: Extended_Index
;
1063 Count
: Count_Type
:= 1)
1065 New_Item
: Element_Type
; -- Default-initialized value
1066 pragma Warnings
(Off
, New_Item
);
1069 Insert
(Container
, Before
, New_Item
, Count
);
1073 (Container
: in out Vector
;
1075 Position
: out Cursor
;
1076 Count
: Count_Type
:= 1)
1078 New_Item
: Element_Type
; -- Default-initialized value
1079 pragma Warnings
(Off
, New_Item
);
1081 Insert
(Container
, Before
, New_Item
, Position
, Count
);
1088 procedure Insert_Space
1089 (Container
: in out Vector
;
1090 Before
: Extended_Index
;
1091 Count
: Count_Type
:= 1)
1093 N
: constant Int
:= Count_Type
'Pos (Count
);
1095 First
: constant Int
:= Int
(Index_Type
'First);
1096 New_Last_As_Int
: Int
'Base;
1097 New_Last
: Index_Type
;
1099 Max_Length
: constant UInt
:= UInt
(Count_Type
'Last);
1102 if Before
< Index_Type
'First then
1103 raise Constraint_Error
with
1104 "Before index is out of range (too small)";
1107 if Before
> Container
.Last
1108 and then Before
> Container
.Last
+ 1
1110 raise Constraint_Error
with
1111 "Before index is out of range (too large)";
1119 Old_Last_As_Int
: constant Int
:= Int
(Container
.Last
);
1122 if Old_Last_As_Int
> Int
'Last - N
then
1123 raise Constraint_Error
with "new length is out of range";
1126 New_Last_As_Int
:= Old_Last_As_Int
+ N
;
1128 if New_Last_As_Int
> Int
(Index_Type
'Last) then
1129 raise Constraint_Error
with "new length is out of range";
1132 New_Length
:= UInt
(New_Last_As_Int
- First
+ Int
'(1));
1134 if New_Length > Max_Length then
1135 raise Constraint_Error with "new length is out of range";
1138 New_Last := Index_Type (New_Last_As_Int);
1140 -- Resolve issue of capacity vs. max index ???
1143 if Container.Busy > 0 then
1144 raise Program_Error with
1145 "attempt to tamper with elements (vector is busy)";
1149 EA : Elements_Array renames Container.Elements;
1151 BB : constant Int'Base := Int (Before) - Int (No_Index);
1152 B : constant Count_Type := Count_Type (BB);
1154 LL : constant Int'Base := New_Last_As_Int - Int (No_Index);
1155 L : constant Count_Type := Count_Type (LL);
1158 if Before <= Container.Last then
1160 II : constant Int'Base := BB + N;
1161 I : constant Count_Type := Count_Type (II);
1163 EA (I .. L) := EA (B .. Length (Container));
1168 Container.Last := New_Last;
1171 procedure Insert_Space
1172 (Container : in out Vector;
1174 Position : out Cursor;
1175 Count : Count_Type := 1)
1177 Index : Index_Type'Base;
1182 or else Before.Index > Container.Last
1184 Position := No_Element;
1186 Position := (True, Before.Index);
1193 or else Before.Index > Container.Last
1195 if Container.Last = Index_Type'Last then
1196 raise Constraint_Error with
1197 "vector is already at its maximum length";
1200 Index := Container.Last + 1;
1203 Index := Before.Index;
1206 Insert_Space (Container, Index, Count => Count);
1208 Position := Cursor'(True, Index
);
1215 function Is_Empty
(Container
: Vector
) return Boolean is
1217 return Last_Index
(Container
) < Index_Type
'First;
1225 (Container
: Vector
;
1227 not null access procedure (Container
: Vector
; Position
: Cursor
))
1229 V
: Vector
renames Container
'Unrestricted_Access.all;
1230 B
: Natural renames V
.Busy
;
1236 for Indx
in Index_Type
'First .. Last_Index
(Container
) loop
1237 Process
(Container
, Cursor
'(True, Indx));
1252 function Last (Container : Vector) return Cursor is
1254 if Is_Empty (Container) then
1258 return (True, Last_Index (Container));
1265 function Last_Element (Container : Vector) return Element_Type is
1267 if Is_Empty (Container) then
1268 raise Constraint_Error with "Container is empty";
1271 return Get_Element (Container, Length (Container));
1278 function Last_Index (Container : Vector) return Extended_Index is
1280 return Container.Last;
1287 function Length (Container : Vector) return Capacity_Subtype is
1288 L : constant Int := Int (Last_Index (Container));
1289 F : constant Int := Int (Index_Type'First);
1290 N : constant Int'Base := L - F + 1;
1293 return Capacity_Subtype (N);
1300 function Left (Container : Vector; Position : Cursor) return Vector is
1301 C : Vector (Container.Capacity) := Copy (Container, Container.Capacity);
1304 if Position = No_Element then
1308 if not Has_Element (Container, Position) then
1309 raise Constraint_Error;
1312 while C.Last /= Position.Index - 1 loop
1323 (Target : in out Vector;
1324 Source : in out Vector)
1326 N : constant Count_Type := Length (Source);
1330 if Target'Address = Source'Address then
1334 if Target.Busy > 0 then
1335 raise Program_Error with
1336 "attempt to tamper with elements (Target is busy)";
1339 if Source.Busy > 0 then
1340 raise Program_Error with
1341 "attempt to tamper with elements (Source is busy)";
1344 if N > Target.Capacity then
1345 raise Constraint_Error with -- correct exception here???
1346 "length of Source is greater than capacity of Target";
1349 -- We could also write this as a loop, and incrementally
1350 -- copy elements from source to target.
1352 Target.Last := No_Index; -- in case array assignment files
1353 Target.Elements (1 .. N) := Source.Elements (1 .. N);
1355 Target.Last := Source.Last;
1356 Source.Last := No_Index;
1363 function Next (Container : Vector; Position : Cursor) return Cursor is
1365 if not Position.Valid then
1369 if Position.Index < Last_Index (Container) then
1370 return (True, Position.Index + 1);
1380 procedure Next (Container : Vector; Position : in out Cursor) is
1382 if not Position.Valid then
1386 if Position.Index < Last_Index (Container) then
1387 Position.Index := Position.Index + 1;
1389 Position := No_Element;
1397 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1399 Insert (Container, Index_Type'First, New_Item);
1403 (Container : in out Vector;
1404 New_Item : Element_Type;
1405 Count : Count_Type := 1)
1418 procedure Previous (Container : Vector; Position : in out Cursor) is
1420 if not Position.Valid then
1424 if Position.Index > Index_Type'First and
1425 Position.Index <= Last_Index (Container) then
1426 Position.Index := Position.Index - 1;
1428 Position := No_Element;
1432 function Previous (Container : Vector; Position : Cursor) return Cursor is
1434 if not Position.Valid then
1438 if Position.Index > Index_Type'First and
1439 Position.Index <= Last_Index (Container) then
1440 return (True, Position.Index - 1);
1450 procedure Query_Element
1451 (Container : Vector;
1453 Process : not null access procedure (Element : Element_Type))
1455 V : Vector renames Container'Unrestricted_Access.all;
1456 B : Natural renames V.Busy;
1457 L : Natural renames V.Lock;
1460 if Index > Last_Index (Container) then
1461 raise Constraint_Error with "Index is out of range";
1468 II : constant Int'Base := Int (Index) - Int (No_Index);
1469 I : constant Count_Type := Count_Type (II);
1472 Process (Get_Element (V, I));
1484 procedure Query_Element
1485 (Container : Vector;
1487 Process : not null access procedure (Element : Element_Type))
1490 if not Position.Valid then
1491 raise Constraint_Error with "Position cursor has no element";
1494 Query_Element (Container, Position.Index, Process);
1502 (Stream : not null access Root_Stream_Type'Class;
1503 Container : out Vector)
1505 Length : Count_Type'Base;
1506 Last : Index_Type'Base := No_Index;
1511 Count_Type'Base'Read
(Stream
, Length
);
1514 raise Program_Error
with "stream appears to be corrupt";
1517 if Length
> Container
.Capacity
then
1518 raise Storage_Error
with "not enough capacity"; -- ???
1521 for J
in Count_Type
range 1 .. Length
loop
1523 Element_Type
'Read (Stream
, Container
.Elements
(J
));
1524 Container
.Last
:= Last
;
1529 (Stream
: not null access Root_Stream_Type
'Class;
1530 Position
: out Cursor
)
1533 raise Program_Error
with "attempt to stream vector cursor";
1536 ---------------------
1537 -- Replace_Element --
1538 ---------------------
1540 procedure Replace_Element
1541 (Container
: in out Vector
;
1543 New_Item
: Element_Type
)
1547 if Index
> Container
.Last
then
1548 raise Constraint_Error
with "Index is out of range";
1551 if Container
.Lock
> 0 then
1552 raise Program_Error
with
1553 "attempt to tamper with cursors (vector is locked)";
1557 II
: constant Int
'Base := Int
(Index
) - Int
(No_Index
);
1558 I
: constant Count_Type
:= Count_Type
(II
);
1561 Container
.Elements
(I
) := New_Item
;
1563 end Replace_Element
;
1565 procedure Replace_Element
1566 (Container
: in out Vector
;
1568 New_Item
: Element_Type
)
1572 if not Position
.Valid
then
1573 raise Constraint_Error
with "Position cursor has no element";
1576 if Position
.Index
> Container
.Last
then
1577 raise Constraint_Error
with "Position cursor is out of range";
1580 if Container
.Lock
> 0 then
1581 raise Program_Error
with
1582 "attempt to tamper with cursors (vector is locked)";
1586 II
: constant Int
'Base := Int
(Position
.Index
) - Int
(No_Index
);
1587 I
: constant Count_Type
:= Count_Type
(II
);
1589 Container
.Elements
(I
) := New_Item
;
1591 end Replace_Element
;
1593 ----------------------
1594 -- Reserve_Capacity --
1595 ----------------------
1597 procedure Reserve_Capacity
1598 (Container
: in out Vector
;
1599 Capacity
: Capacity_Subtype
)
1602 if Capacity
> Container
.Capacity
then
1603 raise Constraint_Error
; -- ???
1605 end Reserve_Capacity
;
1607 ----------------------
1608 -- Reverse_Elements --
1609 ----------------------
1611 procedure Reverse_Elements
(Container
: in out Vector
) is
1613 if Length
(Container
) <= 1 then
1617 if Container
.Lock
> 0 then
1618 raise Program_Error
with
1619 "attempt to tamper with cursors (vector is locked)";
1624 E
: Elements_Array
renames Container
.Elements
;
1628 J
:= Length
(Container
);
1631 EI
: constant Element_Type
:= E
(I
);
1641 end Reverse_Elements
;
1647 function Reverse_Find
1648 (Container
: Vector
;
1649 Item
: Element_Type
;
1650 Position
: Cursor
:= No_Element
) return Cursor
1652 Last
: Index_Type
'Base;
1656 if not Position
.Valid
1657 or else Position
.Index
> Last_Index
(Container
)
1659 Last
:= Last_Index
(Container
);
1661 Last
:= Position
.Index
;
1664 K
:= Count_Type
(Int
(Last
) - Int
(No_Index
));
1665 for Indx
in reverse Index_Type
'First .. Last
loop
1666 if Get_Element
(Container
, K
) = Item
then
1667 return (True, Indx
);
1676 ------------------------
1677 -- Reverse_Find_Index --
1678 ------------------------
1680 function Reverse_Find_Index
1681 (Container
: Vector
;
1682 Item
: Element_Type
;
1683 Index
: Index_Type
:= Index_Type
'Last) return Extended_Index
1685 Last
: Index_Type
'Base;
1689 if Index
> Last_Index
(Container
) then
1690 Last
:= Last_Index
(Container
);
1695 K
:= Count_Type
(Int
(Last
) - Int
(No_Index
));
1696 for Indx
in reverse Index_Type
'First .. Last
loop
1697 if Get_Element
(Container
, K
) = Item
then
1705 end Reverse_Find_Index
;
1707 ---------------------
1708 -- Reverse_Iterate --
1709 ---------------------
1711 procedure Reverse_Iterate
1712 (Container
: Vector
;
1713 Process
: not null access procedure (Container
: Vector
;
1716 V
: Vector
renames Container
'Unrestricted_Access.all;
1717 B
: Natural renames V
.Busy
;
1723 for Indx
in reverse Index_Type
'First .. Last_Index
(Container
) loop
1724 Process
(Container
, Cursor
'(True, Indx));
1733 end Reverse_Iterate;
1739 function Right (Container : Vector; Position : Cursor) return Vector is
1740 C : Vector (Container.Capacity) := Copy (Container, Container.Capacity);
1743 if Position = No_Element then
1748 if not Has_Element (Container, Position) then
1749 raise Constraint_Error;
1752 while C.Last /= Container.Last - Position.Index + 1 loop
1763 procedure Set_Length
1764 (Container : in out Vector;
1765 Length : Capacity_Subtype)
1768 if Length = Formal_Vectors.Length (Container) then
1772 if Container.Busy > 0 then
1773 raise Program_Error with
1774 "attempt to tamper with elements (vector is busy)";
1777 if Length > Container.Capacity then
1778 raise Constraint_Error; -- ???
1782 Last_As_Int : constant Int'Base :=
1783 Int (Index_Type'First) + Int (Length) - 1;
1785 Container.Last := Index_Type'Base (Last_As_Int);
1793 procedure Swap (Container : in out Vector; I, J : Index_Type) is
1795 if I > Container.Last then
1796 raise Constraint_Error with "I index is out of range";
1799 if J > Container.Last then
1800 raise Constraint_Error with "J index is out of range";
1807 if Container.Lock > 0 then
1808 raise Program_Error with
1809 "attempt to tamper with cursors (vector is locked)";
1813 II : constant Int'Base := Int (I) - Int (No_Index);
1814 JJ : constant Int'Base := Int (J) - Int (No_Index);
1816 EI : Element_Type renames Container.Elements (Count_Type (II));
1817 EJ : Element_Type renames Container.Elements (Count_Type (JJ));
1819 EI_Copy : constant Element_Type := EI;
1827 procedure Swap (Container : in out Vector; I, J : Cursor) is
1830 raise Constraint_Error with "I cursor has no element";
1834 raise Constraint_Error with "J cursor has no element";
1837 Swap (Container, I.Index, J.Index);
1845 (Container : Vector;
1846 Index : Extended_Index) return Cursor
1849 if Index not in Index_Type'First .. Last_Index (Container) then
1853 return Cursor'(True, Index
);
1860 function To_Index
(Position
: Cursor
) return Extended_Index
is
1862 if not Position
.Valid
then
1866 return Position
.Index
;
1873 function To_Vector
(Length
: Capacity_Subtype
) return Vector
is
1876 return Empty_Vector
;
1880 First
: constant Int
:= Int
(Index_Type
'First);
1881 Last_As_Int
: constant Int
'Base := First
+ Int
(Length
) - 1;
1885 if Last_As_Int
> Index_Type
'Pos (Index_Type
'Last) then
1886 raise Constraint_Error
with "Length is out of range"; -- ???
1889 Last
:= Index_Type
(Last_As_Int
);
1891 return (Length
, (others => <>), Last
=> Last
,
1897 (New_Item
: Element_Type
;
1898 Length
: Capacity_Subtype
) return Vector
1902 return Empty_Vector
;
1906 First
: constant Int
:= Int
(Index_Type
'First);
1907 Last_As_Int
: constant Int
'Base := First
+ Int
(Length
) - 1;
1911 if Last_As_Int
> Index_Type
'Pos (Index_Type
'Last) then
1912 raise Constraint_Error
with "Length is out of range"; -- ???
1915 Last
:= Index_Type
(Last_As_Int
);
1917 return (Length
, (others => New_Item
), Last
=> Last
,
1922 --------------------
1923 -- Update_Element --
1924 --------------------
1926 procedure Update_Element
1927 (Container
: in out Vector
;
1929 Process
: not null access procedure (Element
: in out Element_Type
))
1931 B
: Natural renames Container
.Busy
;
1932 L
: Natural renames Container
.Lock
;
1936 if Index
> Container
.Last
then
1937 raise Constraint_Error
with "Index is out of range";
1944 II
: constant Int
'Base := Int
(Index
) - Int
(No_Index
);
1945 I
: constant Count_Type
:= Count_Type
(II
);
1948 Process
(Container
.Elements
(I
));
1960 procedure Update_Element
1961 (Container
: in out Vector
;
1963 Process
: not null access procedure (Element
: in out Element_Type
))
1966 if not Position
.Valid
then
1967 raise Constraint_Error
with "Position cursor has no element";
1970 Update_Element
(Container
, Position
.Index
, Process
);
1978 (Stream
: not null access Root_Stream_Type
'Class;
1982 Count_Type
'Base'Write (Stream, Length (Container));
1984 for J in 1 .. Length (Container) loop
1985 Element_Type'Write (Stream, Container.Elements (J));
1990 (Stream : not null access Root_Stream_Type'Class;
1994 raise Program_Error with "attempt to stream vector cursor";
1997 end Ada.Containers.Formal_Vectors;