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-2017, 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 Ada
.Unchecked_Deallocation
;
31 with System
; use type System
.Address
;
33 package body Ada
.Containers
.Formal_Vectors
with
37 Growth_Factor
: constant := 2;
38 -- When growing a container, multiply current capacity by this. Doubling
39 -- leads to amortized linear-time copying.
41 type Int
is range System
.Min_Int
.. System
.Max_Int
;
44 new Ada
.Unchecked_Deallocation
(Elements_Array
, Elements_Array_Ptr
);
46 type Maximal_Array_Ptr
is access all Elements_Array
(Array_Index
)
47 with Storage_Size
=> 0;
48 type Maximal_Array_Ptr_Const
is access constant Elements_Array
(Array_Index
)
49 with Storage_Size
=> 0;
51 function Elems
(Container
: in out Vector
) return Maximal_Array_Ptr
;
53 (Container
: Vector
) return Maximal_Array_Ptr_Const
;
54 -- Returns a pointer to the Elements array currently in use -- either
55 -- Container.Elements_Ptr or a pointer to Container.Elements. We work with
56 -- pointers to a bogus array subtype that is constrained with the maximum
57 -- possible bounds. This means that the pointer is a thin pointer. This is
58 -- necessary because 'Unrestricted_Access doesn't work when it produces
59 -- access-to-unconstrained and is returned from a function.
61 -- Note that this is dangerous: make sure calls to this use an indexed
62 -- component or slice that is within the bounds 1 .. Length (Container).
66 Position
: Capacity_Range
) return Element_Type
;
68 function To_Array_Index
(Index
: Index_Type
'Base) return Count_Type
'Base;
70 function Current_Capacity
(Container
: Vector
) return Capacity_Range
;
72 procedure Insert_Space
73 (Container
: in out Vector
;
74 Before
: Extended_Index
;
75 Count
: Count_Type
:= 1);
81 function "=" (Left
: Vector
; Right
: Vector
) return Boolean is
83 if Left
'Address = Right
'Address then
87 if Length
(Left
) /= Length
(Right
) then
91 for J
in 1 .. Length
(Left
) loop
92 if Get_Element
(Left
, J
) /= Get_Element
(Right
, J
) then
104 procedure Append
(Container
: in out Vector
; New_Item
: Vector
) is
106 if Is_Empty
(New_Item
) then
110 if Container
.Last
>= Index_Type
'Last then
111 raise Constraint_Error
with "vector is already at its maximum length";
114 Insert
(Container
, Container
.Last
+ 1, New_Item
);
117 procedure Append
(Container
: in out Vector
; New_Item
: Element_Type
) is
119 Append
(Container
, New_Item
, 1);
123 (Container
: in out Vector
;
124 New_Item
: Element_Type
;
132 if Container
.Last
>= Index_Type
'Last then
133 raise Constraint_Error
with "vector is already at its maximum length";
136 Insert
(Container
, Container
.Last
+ 1, New_Item
, Count
);
143 procedure Assign
(Target
: in out Vector
; Source
: Vector
) is
144 LS
: constant Capacity_Range
:= Length
(Source
);
147 if Target
'Address = Source
'Address then
151 if Bounded
and then Target
.Capacity
< LS
then
152 raise Constraint_Error
;
156 Append
(Target
, Source
);
163 function Capacity
(Container
: Vector
) return Capacity_Range
is
169 Capacity_Range
'Last);
176 procedure Clear
(Container
: in out Vector
) is
178 Container
.Last
:= No_Index
;
180 -- Free element, note that this is OK if Elements_Ptr is null
182 Free
(Container
.Elements_Ptr
);
191 Item
: Element_Type
) return Boolean
194 return Find_Index
(Container
, Item
) /= No_Index
;
203 Capacity
: Capacity_Range
:= 0) return Vector
205 LS
: constant Capacity_Range
:= Length
(Source
);
211 elsif Capacity
>= LS
then
214 raise Capacity_Error
;
217 return Target
: Vector
(C
) do
218 Elems
(Target
) (1 .. LS
) := Elemsc
(Source
) (1 .. LS
);
219 Target
.Last
:= Source
.Last
;
223 ----------------------
224 -- Current_Capacity --
225 ----------------------
227 function Current_Capacity
(Container
: Vector
) return Capacity_Range
is
230 (if Container
.Elements_Ptr
= null then
231 Container
.Elements
'Length
233 Container
.Elements_Ptr
.all'Length);
234 end Current_Capacity
;
240 procedure Delete
(Container
: in out Vector
; Index
: Extended_Index
) is
242 Delete
(Container
, Index
, 1);
246 (Container
: in out Vector
;
247 Index
: Extended_Index
;
250 Old_Last
: constant Index_Type
'Base := Container
.Last
;
251 Old_Len
: constant Count_Type
:= Length
(Container
);
252 New_Last
: Index_Type
'Base;
253 Count2
: Count_Type
'Base; -- count of items from Index to Old_Last
254 Off
: Count_Type
'Base; -- Index expressed as offset from IT'First
257 -- Delete removes items from the vector, the number of which is the
258 -- minimum of the specified Count and the items (if any) that exist from
259 -- Index to Container.Last. There are no constraints on the specified
260 -- value of Count (it can be larger than what's available at this
261 -- position in the vector, for example), but there are constraints on
262 -- the allowed values of the Index.
264 -- As a precondition on the generic actual Index_Type, the base type
265 -- must include Index_Type'Pred (Index_Type'First); this is the value
266 -- that Container.Last assumes when the vector is empty. However, we do
267 -- not allow that as the value for Index when specifying which items
268 -- should be deleted, so we must manually check. (That the user is
269 -- allowed to specify the value at all here is a consequence of the
270 -- declaration of the Extended_Index subtype, which includes the values
271 -- in the base range that immediately precede and immediately follow the
272 -- values in the Index_Type.)
274 if Index
< Index_Type
'First then
275 raise Constraint_Error
with "Index is out of range (too small)";
278 -- We do allow a value greater than Container.Last to be specified as
279 -- the Index, but only if it's immediately greater. This allows the
280 -- corner case of deleting no items from the back end of the vector to
281 -- be treated as a no-op. (It is assumed that specifying an index value
282 -- greater than Last + 1 indicates some deeper flaw in the caller's
283 -- algorithm, so that case is treated as a proper error.)
285 if Index
> Old_Last
then
286 if Index
> Old_Last
+ 1 then
287 raise Constraint_Error
with "Index is out of range (too large)";
297 -- We first calculate what's available for deletion starting at
298 -- Index. Here and elsewhere we use the wider of Index_Type'Base and
299 -- Count_Type'Base as the type for intermediate values. (See function
300 -- Length for more information.)
302 if Count_Type
'Base'Last >= Index_Type'Pos (Index_Type'Base'Last
) then
303 Count2
:= Count_Type
'Base (Old_Last
) - Count_Type
'Base (Index
) + 1;
305 Count2
:= Count_Type
'Base (Old_Last
- Index
+ 1);
308 -- If more elements are requested (Count) for deletion than are
309 -- available (Count2) for deletion beginning at Index, then everything
310 -- from Index is deleted. There are no elements to slide down, and so
311 -- all we need to do is set the value of Container.Last.
313 if Count
>= Count2
then
314 Container
.Last
:= Index
- 1;
318 -- There are some elements aren't being deleted (the requested count was
319 -- less than the available count), so we must slide them down to Index.
320 -- We first calculate the index values of the respective array slices,
321 -- using the wider of Index_Type'Base and Count_Type'Base as the type
322 -- for intermediate calculations.
324 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
325 Off := Count_Type'Base (Index - Index_Type'First);
326 New_Last := Old_Last - Index_Type'Base (Count);
328 Off := Count_Type'Base (Index) - Count_Type'Base (Index_Type'First);
329 New_Last := Index_Type'Base (Count_Type'Base (Old_Last) - Count);
332 -- The array index values for each slice have already been determined,
333 -- so we just slide down to Index the elements that weren't deleted.
336 EA : Maximal_Array_Ptr renames Elems (Container);
337 Idx : constant Count_Type := EA'First + Off;
339 EA (Idx .. Old_Len - Count) := EA (Idx + Count .. Old_Len);
340 Container.Last := New_Last;
348 procedure Delete_First (Container : in out Vector) is
350 Delete_First (Container, 1);
353 procedure Delete_First (Container : in out Vector; Count : Count_Type) is
358 elsif Count >= Length (Container) then
363 Delete (Container, Index_Type'First, Count);
371 procedure Delete_Last (Container : in out Vector) is
373 Delete_Last (Container, 1);
376 procedure Delete_Last (Container : in out Vector; Count : Count_Type) is
382 -- There is no restriction on how large Count can be when deleting
383 -- items. If it is equal or greater than the current length, then this
384 -- is equivalent to clearing the vector. (In particular, there's no need
385 -- for us to actually calculate the new value for Last.)
387 -- If the requested count is less than the current length, then we must
388 -- calculate the new value for Last. For the type we use the widest of
389 -- Index_Type'Base and Count_Type'Base for the intermediate values of
390 -- our calculation. (See the comments in Length for more information.)
392 if Count >= Length (Container) then
393 Container.Last := No_Index;
395 elsif Index_Type'Base'Last
>= Count_Type
'Pos (Count_Type
'Last) then
396 Container
.Last
:= Container
.Last
- Index_Type
'Base (Count
);
400 Index_Type
'Base (Count_Type
'Base (Container
.Last
) - Count
);
410 Index
: Index_Type
) return Element_Type
413 if Index
> Container
.Last
then
414 raise Constraint_Error
with "Index is out of range";
418 II
: constant Int
'Base := Int
(Index
) - Int
(No_Index
);
419 I
: constant Capacity_Range
:= Capacity_Range
(II
);
421 return Get_Element
(Container
, I
);
429 function Elems
(Container
: in out Vector
) return Maximal_Array_Ptr
is
432 (if Container
.Elements_Ptr
= null then
433 Container
.Elements
'Unrestricted_Access
435 Container
.Elements_Ptr
.all'Unrestricted_Access);
438 function Elemsc
(Container
: Vector
) return Maximal_Array_Ptr_Const
is
441 (if Container
.Elements_Ptr
= null then
442 Container
.Elements
'Unrestricted_Access
444 Container
.Elements_Ptr
.all'Unrestricted_Access);
454 Index
: Index_Type
:= Index_Type
'First) return Extended_Index
457 Last
: constant Index_Type
:= Last_Index
(Container
);
460 K
:= Capacity_Range
(Int
(Index
) - Int
(No_Index
));
461 for Indx
in Index
.. Last
loop
462 if Get_Element
(Container
, K
) = Item
then
476 function First_Element
(Container
: Vector
) return Element_Type
is
478 if Is_Empty
(Container
) then
479 raise Constraint_Error
with "Container is empty";
481 return Get_Element
(Container
, 1);
489 function First_Index
(Container
: Vector
) return Index_Type
is
490 pragma Unreferenced
(Container
);
492 return Index_Type
'First;
499 package body Formal_Model
is
501 -------------------------
502 -- M_Elements_In_Union --
503 -------------------------
505 function M_Elements_In_Union
506 (Container
: M
.Sequence
;
508 Right
: M
.Sequence
) return Boolean
513 for Index
in Index_Type
'First .. M
.Last
(Container
) loop
514 Elem
:= Element
(Container
, Index
);
516 if not M
.Contains
(Left
, Index_Type
'First, M
.Last
(Left
), Elem
)
518 not M
.Contains
(Right
, Index_Type
'First, M
.Last
(Right
), Elem
)
525 end M_Elements_In_Union
;
527 -------------------------
528 -- M_Elements_Included --
529 -------------------------
531 function M_Elements_Included
533 L_Fst
: Index_Type
:= Index_Type
'First;
534 L_Lst
: Extended_Index
;
536 R_Fst
: Index_Type
:= Index_Type
'First;
537 R_Lst
: Extended_Index
) return Boolean
540 for I
in L_Fst
.. L_Lst
loop
542 Found
: Boolean := False;
543 J
: Extended_Index
:= R_Fst
- 1;
546 while not Found
and J
< R_Lst
loop
548 if Element
(Left
, I
) = Element
(Right
, J
) then
560 end M_Elements_Included
;
562 -------------------------
563 -- M_Elements_Reversed --
564 -------------------------
566 function M_Elements_Reversed
568 Right
: M
.Sequence
) return Boolean
570 L
: constant Index_Type
:= M
.Last
(Left
);
573 if L
/= M
.Last
(Right
) then
577 for I
in Index_Type
'First .. L
loop
578 if Element
(Left
, I
) /= Element
(Right
, L
- I
+ 1)
585 end M_Elements_Reversed
;
587 ------------------------
588 -- M_Elements_Swapted --
589 ------------------------
591 function M_Elements_Swapped
595 Y
: Index_Type
) return Boolean
598 if M
.Length
(Left
) /= M
.Length
(Right
)
599 or else Element
(Left
, X
) /= Element
(Right
, Y
)
600 or else Element
(Left
, Y
) /= Element
(Right
, X
)
605 for I
in Index_Type
'First .. M
.Last
(Left
) loop
606 if I
/= X
and then I
/= Y
607 and then Element
(Left
, I
) /= Element
(Right
, I
)
614 end M_Elements_Swapped
;
620 function Model
(Container
: Vector
) return M
.Sequence
is
624 for Position
in 1 .. Length
(Container
) loop
625 R
:= M
.Add
(R
, Elemsc
(Container
) (Position
));
633 ---------------------
634 -- Generic_Sorting --
635 ---------------------
637 package body Generic_Sorting
with SPARK_Mode
=> Off
is
643 package body Formal_Model
is
645 -----------------------
646 -- M_Elements_Sorted --
647 -----------------------
649 function M_Elements_Sorted
(Container
: M
.Sequence
) return Boolean is
651 if M
.Length
(Container
) = 0 then
656 E1
: Element_Type
:= Element
(Container
, Index_Type
'First);
659 for I
in Index_Type
'First + 1 .. M
.Last
(Container
) loop
661 E2
: constant Element_Type
:= Element
(Container
, I
);
674 end M_Elements_Sorted
;
682 function Is_Sorted
(Container
: Vector
) return Boolean is
683 L
: constant Capacity_Range
:= Length
(Container
);
686 for J
in 1 .. L
- 1 loop
687 if Get_Element
(Container
, J
+ 1) <
688 Get_Element
(Container
, J
)
701 procedure Sort
(Container
: in out Vector
) is
703 new Generic_Array_Sort
704 (Index_Type
=> Array_Index
,
705 Element_Type
=> Element_Type
,
706 Array_Type
=> Elements_Array
,
709 Len
: constant Capacity_Range
:= Length
(Container
);
712 if Container
.Last
<= Index_Type
'First then
715 Sort
(Elems
(Container
) (1 .. Len
));
723 procedure Merge
(Target
: in out Vector
; Source
: in out Vector
) is
728 if Target
'Address = Source
'Address then
729 raise Program_Error
with "Target and Source denote same container";
732 if Length
(Source
) = 0 then
736 if Length
(Target
) = 0 then
737 Move
(Target
=> Target
, Source
=> Source
);
741 I
:= Length
(Target
);
744 New_Length
: constant Count_Type
:= I
+ Length
(Source
);
748 and then Current_Capacity
(Target
) < Capacity_Range
(New_Length
)
753 (Current_Capacity
(Target
) * Growth_Factor
,
754 Capacity_Range
(New_Length
)));
757 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
758 Target.Last := No_Index + Index_Type'Base (New_Length);
762 Index_Type'Base (Count_Type'Base (No_Index) + New_Length);
767 TA : Maximal_Array_Ptr renames Elems (Target);
768 SA : Maximal_Array_Ptr renames Elems (Source);
771 J := Length (Target);
772 while Length (Source) /= 0 loop
774 TA (1 .. J) := SA (1 .. Length (Source));
775 Source.Last := No_Index;
779 if SA (Length (Source)) < TA (I) then
784 TA (J) := SA (Length (Source));
785 Source.Last := Source.Last - 1;
801 Position : Capacity_Range) return Element_Type
804 return Elemsc (Container) (Position);
813 Position : Extended_Index) return Boolean
816 return Position in First_Index (Container) .. Last_Index (Container);
824 (Container : in out Vector;
825 Before : Extended_Index;
826 New_Item : Element_Type)
829 Insert (Container, Before, New_Item, 1);
833 (Container : in out Vector;
834 Before : Extended_Index;
835 New_Item : Element_Type;
838 J : Count_Type'Base; -- scratch
841 -- Use Insert_Space to create the "hole" (the destination slice)
843 Insert_Space (Container, Before, Count);
845 J := To_Array_Index (Before);
847 Elems (Container) (J .. J - 1 + Count) := (others => New_Item);
851 (Container : in out Vector;
852 Before : Extended_Index;
855 N : constant Count_Type := Length (New_Item);
856 B : Count_Type; -- index Before converted to Count_Type
859 if Container'Address = New_Item'Address then
860 raise Program_Error with
861 "Container and New_Item denote same container";
864 -- Use Insert_Space to create the "hole" (the destination slice) into
865 -- which we copy the source items.
867 Insert_Space (Container, Before, Count => N);
871 -- There's nothing else to do here (vetting of parameters was
872 -- performed already in Insert_Space), so we simply return.
877 B := To_Array_Index (Before);
879 Elems (Container) (B .. B + N - 1) := Elemsc (New_Item) (1 .. N);
886 procedure Insert_Space
887 (Container : in out Vector;
888 Before : Extended_Index;
889 Count : Count_Type := 1)
891 Old_Length : constant Count_Type := Length (Container);
893 Max_Length : Count_Type'Base; -- determined from range of Index_Type
894 New_Length : Count_Type'Base; -- sum of current length and Count
896 Index : Index_Type'Base; -- scratch for intermediate values
897 J : Count_Type'Base; -- scratch
900 -- As a precondition on the generic actual Index_Type, the base type
901 -- must include Index_Type'Pred (Index_Type'First); this is the value
902 -- that Container.Last assumes when the vector is empty. However, we do
903 -- not allow that as the value for Index when specifying where the new
904 -- items should be inserted, so we must manually check. (That the user
905 -- is allowed to specify the value at all here is a consequence of the
906 -- declaration of the Extended_Index subtype, which includes the values
907 -- in the base range that immediately precede and immediately follow the
908 -- values in the Index_Type.)
910 if Before < Index_Type'First then
911 raise Constraint_Error with
912 "Before index is out of range (too small)";
915 -- We do allow a value greater than Container.Last to be specified as
916 -- the Index, but only if it's immediately greater. This allows for the
917 -- case of appending items to the back end of the vector. (It is assumed
918 -- that specifying an index value greater than Last + 1 indicates some
919 -- deeper flaw in the caller's algorithm, so that case is treated as a
922 if Before > Container.Last
923 and then Before - 1 > Container.Last
925 raise Constraint_Error with
926 "Before index is out of range (too large)";
929 -- We treat inserting 0 items into the container as a no-op, so we
936 -- There are two constraints we need to satisfy. The first constraint is
937 -- that a container cannot have more than Count_Type'Last elements, so
938 -- we must check the sum of the current length and the insertion count.
939 -- Note that the value cannot be simply added because the result may
942 if Old_Length > Count_Type'Last - Count then
943 raise Constraint_Error with "Count is out of range";
946 -- It is now safe compute the length of the new vector, without fear of
949 New_Length := Old_Length + Count;
951 -- The second constraint is that the new Last index value cannot exceed
952 -- Index_Type'Last. In each branch below, we calculate the maximum
953 -- length (computed from the range of values in Index_Type), and then
954 -- compare the new length to the maximum length. If the new length is
955 -- acceptable, then we compute the new last index from that.
957 if Index_Type'Base'Last
>= Count_Type
'Pos (Count_Type
'Last) then
959 -- We have to handle the case when there might be more values in the
960 -- range of Index_Type than in the range of Count_Type.
962 if Index_Type
'First <= 0 then
964 -- We know that No_Index (the same as Index_Type'First - 1) is
965 -- less than 0, so it is safe to compute the following sum without
968 Index
:= No_Index
+ Index_Type
'Base (Count_Type
'Last);
970 if Index
<= Index_Type
'Last then
972 -- We have determined that range of Index_Type has at least as
973 -- many values as in Count_Type, so Count_Type'Last is the
974 -- maximum number of items that are allowed.
976 Max_Length
:= Count_Type
'Last;
979 -- The range of Index_Type has fewer values than in Count_Type,
980 -- so the maximum number of items is computed from the range of
983 Max_Length
:= Count_Type
'Base (Index_Type
'Last - No_Index
);
987 -- No_Index is equal or greater than 0, so we can safely compute
988 -- the difference without fear of overflow (which we would have to
989 -- worry about if No_Index were less than 0, but that case is
992 if Index_Type
'Last - No_Index
>= Count_Type
'Pos (Count_Type
'Last)
994 -- We have determined that range of Index_Type has at least as
995 -- many values as in Count_Type, so Count_Type'Last is the
996 -- maximum number of items that are allowed.
998 Max_Length
:= Count_Type
'Last;
1001 -- The range of Index_Type has fewer values than in Count_Type,
1002 -- so the maximum number of items is computed from the range of
1005 Max_Length
:= Count_Type
'Base (Index_Type
'Last - No_Index
);
1009 elsif Index_Type
'First <= 0 then
1011 -- We know that No_Index (the same as Index_Type'First - 1) is less
1012 -- than 0, so it is safe to compute the following sum without fear of
1015 J
:= Count_Type
'Base (No_Index
) + Count_Type
'Last;
1017 if J
<= Count_Type
'Base (Index_Type
'Last) then
1019 -- We have determined that range of Index_Type has at least as
1020 -- many values as in Count_Type, so Count_Type'Last is the maximum
1021 -- number of items that are allowed.
1023 Max_Length
:= Count_Type
'Last;
1026 -- The range of Index_Type has fewer values than Count_Type does,
1027 -- so the maximum number of items is computed from the range of
1031 Count_Type
'Base (Index_Type
'Last) - Count_Type
'Base (No_Index
);
1035 -- No_Index is equal or greater than 0, so we can safely compute the
1036 -- difference without fear of overflow (which we would have to worry
1037 -- about if No_Index were less than 0, but that case is handled
1041 Count_Type
'Base (Index_Type
'Last) - Count_Type
'Base (No_Index
);
1044 -- We have just computed the maximum length (number of items). We must
1045 -- now compare the requested length to the maximum length, as we do not
1046 -- allow a vector expand beyond the maximum (because that would create
1047 -- an internal array with a last index value greater than
1048 -- Index_Type'Last, with no way to index those elements).
1050 if New_Length
> Max_Length
then
1051 raise Constraint_Error
with "Count is out of range";
1054 J
:= To_Array_Index
(Before
);
1056 -- Increase the capacity of container if needed
1059 and then Current_Capacity
(Container
) < Capacity_Range
(New_Length
)
1063 Capacity_Range
'Max (Current_Capacity
(Container
) * Growth_Factor
,
1064 Capacity_Range
(New_Length
)));
1068 EA
: Maximal_Array_Ptr
renames Elems
(Container
);
1071 if Before
<= Container
.Last
then
1073 -- The new items are being inserted before some existing
1074 -- elements, so we must slide the existing elements up to their
1077 EA
(J
+ Count
.. New_Length
) := EA
(J
.. Old_Length
);
1081 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
1082 Container.Last := No_Index + Index_Type'Base (New_Length);
1086 Index_Type'Base (Count_Type'Base (No_Index) + New_Length);
1094 function Is_Empty (Container : Vector) return Boolean is
1096 return Last_Index (Container) < Index_Type'First;
1103 function Last_Element (Container : Vector) return Element_Type is
1105 if Is_Empty (Container) then
1106 raise Constraint_Error with "Container is empty";
1108 return Get_Element (Container, Length (Container));
1116 function Last_Index (Container : Vector) return Extended_Index is
1118 return Container.Last;
1125 function Length (Container : Vector) return Capacity_Range is
1126 L : constant Int := Int (Container.Last);
1127 F : constant Int := Int (Index_Type'First);
1128 N : constant Int'Base := L - F + 1;
1131 return Capacity_Range (N);
1138 procedure Move (Target : in out Vector; Source : in out Vector) is
1139 LS : constant Capacity_Range := Length (Source);
1142 if Target'Address = Source'Address then
1146 if Bounded and then Target.Capacity < LS then
1147 raise Constraint_Error;
1151 Append (Target, Source);
1159 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1161 Insert (Container, Index_Type'First, New_Item);
1164 procedure Prepend (Container : in out Vector; New_Item : Element_Type) is
1166 Prepend (Container, New_Item, 1);
1170 (Container : in out Vector;
1171 New_Item : Element_Type;
1175 Insert (Container, Index_Type'First, New_Item, Count);
1178 ---------------------
1179 -- Replace_Element --
1180 ---------------------
1182 procedure Replace_Element
1183 (Container : in out Vector;
1185 New_Item : Element_Type)
1188 if Index > Container.Last then
1189 raise Constraint_Error with "Index is out of range";
1193 II : constant Int'Base := Int (Index) - Int (No_Index);
1194 I : constant Capacity_Range := Capacity_Range (II);
1197 Elems (Container) (I) := New_Item;
1199 end Replace_Element;
1201 ----------------------
1202 -- Reserve_Capacity --
1203 ----------------------
1205 procedure Reserve_Capacity
1206 (Container : in out Vector;
1207 Capacity : Capacity_Range)
1211 if Capacity > Container.Capacity then
1212 raise Constraint_Error with "Capacity is out of range";
1216 if Capacity > Formal_Vectors.Current_Capacity (Container) then
1218 New_Elements : constant Elements_Array_Ptr :=
1219 new Elements_Array (1 .. Capacity);
1220 L : constant Capacity_Range := Length (Container);
1223 New_Elements (1 .. L) := Elemsc (Container) (1 .. L);
1224 Free (Container.Elements_Ptr);
1225 Container.Elements_Ptr := New_Elements;
1229 end Reserve_Capacity;
1231 ----------------------
1232 -- Reverse_Elements --
1233 ----------------------
1235 procedure Reverse_Elements (Container : in out Vector) is
1237 if Length (Container) <= 1 then
1242 I, J : Capacity_Range;
1243 E : Elements_Array renames
1244 Elems (Container) (1 .. Length (Container));
1248 J := Length (Container);
1251 EI : constant Element_Type := E (I);
1262 end Reverse_Elements;
1264 ------------------------
1265 -- Reverse_Find_Index --
1266 ------------------------
1268 function Reverse_Find_Index
1269 (Container : Vector;
1270 Item : Element_Type;
1271 Index : Index_Type := Index_Type'Last) return Extended_Index
1273 Last : Index_Type'Base;
1277 if Index > Last_Index (Container) then
1278 Last := Last_Index (Container);
1283 K := Capacity_Range (Int (Last) - Int (No_Index));
1284 for Indx in reverse Index_Type'First .. Last loop
1285 if Get_Element (Container, K) = Item then
1293 end Reverse_Find_Index;
1300 (Container : in out Vector;
1305 if I > Container.Last then
1306 raise Constraint_Error with "I index is out of range";
1309 if J > Container.Last then
1310 raise Constraint_Error with "J index is out of range";
1318 II : constant Int'Base := Int (I) - Int (No_Index);
1319 JJ : constant Int'Base := Int (J) - Int (No_Index);
1321 EI : Element_Type renames Elems (Container) (Capacity_Range (II));
1322 EJ : Element_Type renames Elems (Container) (Capacity_Range (JJ));
1324 EI_Copy : constant Element_Type := EI;
1332 --------------------
1333 -- To_Array_Index --
1334 --------------------
1336 function To_Array_Index (Index : Index_Type'Base) return Count_Type'Base is
1337 Offset : Count_Type'Base;
1341 -- Index >= Index_Type'First
1342 -- hence we also know that
1343 -- Index - Index_Type'First >= 0
1345 -- The issue is that even though 0 is guaranteed to be a value in
1346 -- the type Index_Type'Base, there's no guarantee that the difference
1347 -- is a value in that type. To prevent overflow we use the wider
1348 -- of Count_Type'Base and Index_Type'Base to perform intermediate
1351 if Index_Type'Base'Last
>= Count_Type
'Pos (Count_Type
'Last) then
1352 Offset
:= Count_Type
'Base (Index
- Index_Type
'First);
1356 Count_Type
'Base (Index
) - Count_Type
'Base (Index_Type
'First);
1359 -- The array index subtype for all container element arrays always
1370 (New_Item
: Element_Type
;
1371 Length
: Capacity_Range
) return Vector
1375 return Empty_Vector
;
1379 First
: constant Int
:= Int
(Index_Type
'First);
1380 Last_As_Int
: constant Int
'Base := First
+ Int
(Length
) - 1;
1384 if Last_As_Int
> Index_Type
'Pos (Index_Type
'Last) then
1385 raise Constraint_Error
with "Length is out of range"; -- ???
1388 Last
:= Index_Type
(Last_As_Int
);
1391 (Capacity
=> Length
,
1394 Elements
=> (others => New_Item
));
1398 end Ada
.Containers
.Formal_Vectors
;