1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . B O U N D E D _ V E C T O R S --
9 -- Copyright (C) 2004-2014, 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/>. --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada
.Containers
.Generic_Array_Sort
;
32 with System
; use type System
.Address
;
34 package body Ada
.Containers
.Bounded_Vectors
is
36 -----------------------
37 -- Local Subprograms --
38 -----------------------
40 function To_Array_Index
(Index
: Index_Type
'Base) return Count_Type
'Base;
46 function "&" (Left
, Right
: Vector
) return Vector
is
47 LN
: constant Count_Type
:= Length
(Left
);
48 RN
: constant Count_Type
:= Length
(Right
);
49 N
: Count_Type
'Base; -- length of result
50 J
: Count_Type
'Base; -- for computing intermediate index values
51 Last
: Index_Type
'Base; -- Last index of result
54 -- We decide that the capacity of the result is the sum of the lengths
55 -- of the vector parameters. We could decide to make it larger, but we
56 -- have no basis for knowing how much larger, so we just allocate the
57 -- minimum amount of storage.
59 -- Here we handle the easy cases first, when one of the vector
60 -- parameters is empty. (We say "easy" because there's nothing to
61 -- compute, that can potentially overflow.)
68 return Vector
'(Capacity => RN,
69 Elements => Right.Elements (1 .. RN),
75 return Vector'(Capacity
=> LN
,
76 Elements
=> Left
.Elements
(1 .. LN
),
81 -- Neither of the vector parameters is empty, so must compute the length
82 -- of the result vector and its last index. (This is the harder case,
83 -- because our computations must avoid overflow.)
85 -- There are two constraints we need to satisfy. The first constraint is
86 -- that a container cannot have more than Count_Type'Last elements, so
87 -- we must check the sum of the combined lengths. Note that we cannot
88 -- simply add the lengths, because of the possibility of overflow.
90 if LN
> Count_Type
'Last - RN
then
91 raise Constraint_Error
with "new length is out of range";
94 -- It is now safe to compute the length of the new vector, without fear
99 -- The second constraint is that the new Last index value cannot
100 -- exceed Index_Type'Last. We use the wider of Index_Type'Base and
101 -- Count_Type'Base as the type for intermediate values.
103 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
105 -- We perform a two-part test. First we determine whether the
106 -- computed Last value lies in the base range of the type, and then
107 -- determine whether it lies in the range of the index (sub)type.
109 -- Last must satisfy this relation:
110 -- First + Length - 1 <= Last
112 -- First - 1 <= Last - Length
113 -- Which can rewrite as:
114 -- No_Index <= Last - Length
116 if Index_Type'Base'Last
- Index_Type
'Base (N
) < No_Index
then
117 raise Constraint_Error
with "new length is out of range";
120 -- We now know that the computed value of Last is within the base
121 -- range of the type, so it is safe to compute its value:
123 Last
:= No_Index
+ Index_Type
'Base (N
);
125 -- Finally we test whether the value is within the range of the
126 -- generic actual index subtype:
128 if Last
> Index_Type
'Last then
129 raise Constraint_Error
with "new length is out of range";
132 elsif Index_Type
'First <= 0 then
134 -- Here we can compute Last directly, in the normal way. We know that
135 -- No_Index is less than 0, so there is no danger of overflow when
136 -- adding the (positive) value of length.
138 J
:= Count_Type
'Base (No_Index
) + N
; -- Last
140 if J
> Count_Type
'Base (Index_Type
'Last) then
141 raise Constraint_Error
with "new length is out of range";
144 -- We know that the computed value (having type Count_Type) of Last
145 -- is within the range of the generic actual index subtype, so it is
146 -- safe to convert to Index_Type:
148 Last
:= Index_Type
'Base (J
);
151 -- Here Index_Type'First (and Index_Type'Last) is positive, so we
152 -- must test the length indirectly (by working backwards from the
153 -- largest possible value of Last), in order to prevent overflow.
155 J
:= Count_Type
'Base (Index_Type
'Last) - N
; -- No_Index
157 if J
< Count_Type
'Base (No_Index
) then
158 raise Constraint_Error
with "new length is out of range";
161 -- We have determined that the result length would not create a Last
162 -- index value outside of the range of Index_Type, so we can now
163 -- safely compute its value.
165 Last
:= Index_Type
'Base (Count_Type
'Base (No_Index
) + N
);
169 LE
: Elements_Array
renames Left
.Elements
(1 .. LN
);
170 RE
: Elements_Array
renames Right
.Elements
(1 .. RN
);
173 return Vector
'(Capacity => N,
180 function "&" (Left : Vector; Right : Element_Type) return Vector is
181 LN : constant Count_Type := Length (Left);
184 -- We decide that the capacity of the result is the sum of the lengths
185 -- of the parameters. We could decide to make it larger, but we have no
186 -- basis for knowing how much larger, so we just allocate the minimum
187 -- amount of storage.
189 -- We must compute the length of the result vector and its last index,
190 -- but in such a way that overflow is avoided. We must satisfy two
191 -- constraints: the new length cannot exceed Count_Type'Last, and the
192 -- new Last index cannot exceed Index_Type'Last.
194 if LN = Count_Type'Last then
195 raise Constraint_Error with "new length is out of range";
198 if Left.Last >= Index_Type'Last then
199 raise Constraint_Error with "new length is out of range";
202 return Vector'(Capacity
=> LN
+ 1,
203 Elements
=> Left
.Elements
(1 .. LN
) & Right
,
204 Last
=> Left
.Last
+ 1,
208 function "&" (Left
: Element_Type
; Right
: Vector
) return Vector
is
209 RN
: constant Count_Type
:= Length
(Right
);
212 -- We decide that the capacity of the result is the sum of the lengths
213 -- of the parameters. We could decide to make it larger, but we have no
214 -- basis for knowing how much larger, so we just allocate the minimum
215 -- amount of storage.
217 -- We compute the length of the result vector and its last index, but in
218 -- such a way that overflow is avoided. We must satisfy two constraints:
219 -- the new length cannot exceed Count_Type'Last, and the new Last index
220 -- cannot exceed Index_Type'Last.
222 if RN
= Count_Type
'Last then
223 raise Constraint_Error
with "new length is out of range";
226 if Right
.Last
>= Index_Type
'Last then
227 raise Constraint_Error
with "new length is out of range";
230 return Vector
'(Capacity => 1 + RN,
231 Elements => Left & Right.Elements (1 .. RN),
232 Last => Right.Last + 1,
236 function "&" (Left, Right : Element_Type) return Vector is
238 -- We decide that the capacity of the result is the sum of the lengths
239 -- of the parameters. We could decide to make it larger, but we have no
240 -- basis for knowing how much larger, so we just allocate the minimum
241 -- amount of storage.
243 -- We must compute the length of the result vector and its last index,
244 -- but in such a way that overflow is avoided. We must satisfy two
245 -- constraints: the new length cannot exceed Count_Type'Last (here, we
246 -- know that that condition is satisfied), and the new Last index cannot
247 -- exceed Index_Type'Last.
249 if Index_Type'First >= Index_Type'Last then
250 raise Constraint_Error with "new length is out of range";
253 return Vector'(Capacity
=> 2,
254 Elements
=> (Left
, Right
),
255 Last
=> Index_Type
'First + 1,
263 overriding
function "=" (Left
, Right
: Vector
) return Boolean is
264 BL
: Natural renames Left
'Unrestricted_Access.Busy
;
265 LL
: Natural renames Left
'Unrestricted_Access.Lock
;
267 BR
: Natural renames Right
'Unrestricted_Access.Busy
;
268 LR
: Natural renames Right
'Unrestricted_Access.Lock
;
273 if Left
'Address = Right
'Address then
277 if Left
.Last
/= Right
.Last
then
281 -- Per AI05-0022, the container implementation is required to detect
282 -- element tampering by a generic actual subprogram.
291 for J
in Count_Type
range 1 .. Left
.Length
loop
292 if Left
.Elements
(J
) /= Right
.Elements
(J
) then
321 procedure Adjust
(Control
: in out Reference_Control_Type
) is
323 if Control
.Container
/= null then
325 C
: Vector
renames Control
.Container
.all;
326 B
: Natural renames C
.Busy
;
327 L
: Natural renames C
.Lock
;
339 procedure Assign
(Target
: in out Vector
; Source
: Vector
) is
341 if Target
'Address = Source
'Address then
345 if Target
.Capacity
< Source
.Length
then
346 raise Capacity_Error
-- ???
347 with "Target capacity is less than Source length";
352 Target
.Elements
(1 .. Source
.Length
) :=
353 Source
.Elements
(1 .. Source
.Length
);
355 Target
.Last
:= Source
.Last
;
362 procedure Append
(Container
: in out Vector
; New_Item
: Vector
) is
364 if New_Item
.Is_Empty
then
368 if Container
.Last
>= Index_Type
'Last then
369 raise Constraint_Error
with "vector is already at its maximum length";
372 Container
.Insert
(Container
.Last
+ 1, New_Item
);
376 (Container
: in out Vector
;
377 New_Item
: Element_Type
;
378 Count
: Count_Type
:= 1)
385 if Container
.Last
>= Index_Type
'Last then
386 raise Constraint_Error
with "vector is already at its maximum length";
389 Container
.Insert
(Container
.Last
+ 1, New_Item
, Count
);
396 function Capacity
(Container
: Vector
) return Count_Type
is
398 return Container
.Elements
'Length;
405 procedure Clear
(Container
: in out Vector
) is
407 if Container
.Busy
> 0 then
408 raise Program_Error
with
409 "attempt to tamper with cursors (vector is busy)";
412 Container
.Last
:= No_Index
;
415 ------------------------
416 -- Constant_Reference --
417 ------------------------
419 function Constant_Reference
420 (Container
: aliased Vector
;
421 Position
: Cursor
) return Constant_Reference_Type
424 if Position
.Container
= null then
425 raise Constraint_Error
with "Position cursor has no element";
428 if Position
.Container
/= Container
'Unrestricted_Access then
429 raise Program_Error
with "Position cursor denotes wrong container";
432 if Position
.Index
> Position
.Container
.Last
then
433 raise Constraint_Error
with "Position cursor is out of range";
437 A
: Elements_Array
renames Container
.Elements
;
438 I
: constant Count_Type
:= To_Array_Index
(Position
.Index
);
439 B
: Natural renames Position
.Container
.Busy
;
440 L
: Natural renames Position
.Container
.Lock
;
442 return R
: constant Constant_Reference_Type
:=
443 (Element
=> A
(I
)'Access,
444 Control
=> (Controlled
with Container
'Unrestricted_Access))
450 end Constant_Reference
;
452 function Constant_Reference
453 (Container
: aliased Vector
;
454 Index
: Index_Type
) return Constant_Reference_Type
457 if Index
> Container
.Last
then
458 raise Constraint_Error
with "Index is out of range";
462 A
: Elements_Array
renames Container
.Elements
;
463 I
: constant Count_Type
:= To_Array_Index
(Index
);
465 return R
: constant Constant_Reference_Type
:=
466 (Element
=> A
(I
)'Access,
467 Control
=> (Controlled
with Container
'Unrestricted_Access))
469 R
.Control
.Container
.Busy
:= R
.Control
.Container
.Busy
+ 1;
470 R
.Control
.Container
.Lock
:= R
.Control
.Container
.Lock
+ 1;
473 end Constant_Reference
;
481 Item
: Element_Type
) return Boolean
484 return Find_Index
(Container
, Item
) /= No_Index
;
493 Capacity
: Count_Type
:= 0) return Vector
501 elsif Capacity
>= Source
.Length
then
506 with "Requested capacity is less than Source length";
509 return Target
: Vector
(C
) do
510 Target
.Elements
(1 .. Source
.Length
) :=
511 Source
.Elements
(1 .. Source
.Length
);
513 Target
.Last
:= Source
.Last
;
522 (Container
: in out Vector
;
523 Index
: Extended_Index
;
524 Count
: Count_Type
:= 1)
526 Old_Last
: constant Index_Type
'Base := Container
.Last
;
527 Old_Len
: constant Count_Type
:= Container
.Length
;
528 New_Last
: Index_Type
'Base;
529 Count2
: Count_Type
'Base; -- count of items from Index to Old_Last
530 Off
: Count_Type
'Base; -- Index expressed as offset from IT'First
533 -- Delete removes items from the vector, the number of which is the
534 -- minimum of the specified Count and the items (if any) that exist from
535 -- Index to Container.Last. There are no constraints on the specified
536 -- value of Count (it can be larger than what's available at this
537 -- position in the vector, for example), but there are constraints on
538 -- the allowed values of the Index.
540 -- As a precondition on the generic actual Index_Type, the base type
541 -- must include Index_Type'Pred (Index_Type'First); this is the value
542 -- that Container.Last assumes when the vector is empty. However, we do
543 -- not allow that as the value for Index when specifying which items
544 -- should be deleted, so we must manually check. (That the user is
545 -- allowed to specify the value at all here is a consequence of the
546 -- declaration of the Extended_Index subtype, which includes the values
547 -- in the base range that immediately precede and immediately follow the
548 -- values in the Index_Type.)
550 if Index
< Index_Type
'First then
551 raise Constraint_Error
with "Index is out of range (too small)";
554 -- We do allow a value greater than Container.Last to be specified as
555 -- the Index, but only if it's immediately greater. This allows the
556 -- corner case of deleting no items from the back end of the vector to
557 -- be treated as a no-op. (It is assumed that specifying an index value
558 -- greater than Last + 1 indicates some deeper flaw in the caller's
559 -- algorithm, so that case is treated as a proper error.)
561 if Index
> Old_Last
then
562 if Index
> Old_Last
+ 1 then
563 raise Constraint_Error
with "Index is out of range (too large)";
569 -- Here and elsewhere we treat deleting 0 items from the container as a
570 -- no-op, even when the container is busy, so we simply return.
576 -- The tampering bits exist to prevent an item from being deleted (or
577 -- otherwise harmfully manipulated) while it is being visited. Query,
578 -- Update, and Iterate increment the busy count on entry, and decrement
579 -- the count on exit. Delete checks the count to determine whether it is
580 -- being called while the associated callback procedure is executing.
582 if Container
.Busy
> 0 then
583 raise Program_Error
with
584 "attempt to tamper with cursors (vector is busy)";
587 -- We first calculate what's available for deletion starting at
588 -- Index. Here and elsewhere we use the wider of Index_Type'Base and
589 -- Count_Type'Base as the type for intermediate values. (See function
590 -- Length for more information.)
592 if Count_Type
'Base'Last >= Index_Type'Pos (Index_Type'Base'Last
) then
593 Count2
:= Count_Type
'Base (Old_Last
) - Count_Type
'Base (Index
) + 1;
595 Count2
:= Count_Type
'Base (Old_Last
- Index
+ 1);
598 -- If more elements are requested (Count) for deletion than are
599 -- available (Count2) for deletion beginning at Index, then everything
600 -- from Index is deleted. There are no elements to slide down, and so
601 -- all we need to do is set the value of Container.Last.
603 if Count
>= Count2
then
604 Container
.Last
:= Index
- 1;
608 -- There are some elements aren't being deleted (the requested count was
609 -- less than the available count), so we must slide them down to
610 -- Index. We first calculate the index values of the respective array
611 -- slices, using the wider of Index_Type'Base and Count_Type'Base as the
612 -- type for intermediate calculations.
614 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
615 Off := Count_Type'Base (Index - Index_Type'First);
616 New_Last := Old_Last - Index_Type'Base (Count);
618 Off := Count_Type'Base (Index) - Count_Type'Base (Index_Type'First);
619 New_Last := Index_Type'Base (Count_Type'Base (Old_Last) - Count);
622 -- The array index values for each slice have already been determined,
623 -- so we just slide down to Index the elements that weren't deleted.
626 EA : Elements_Array renames Container.Elements;
627 Idx : constant Count_Type := EA'First + Off;
629 EA (Idx .. Old_Len - Count) := EA (Idx + Count .. Old_Len);
630 Container.Last := New_Last;
635 (Container : in out Vector;
636 Position : in out Cursor;
637 Count : Count_Type := 1)
639 pragma Warnings (Off, Position);
642 if Position.Container = null then
643 raise Constraint_Error with "Position cursor has no element";
646 if Position.Container /= Container'Unrestricted_Access then
647 raise Program_Error with "Position cursor denotes wrong container";
650 if Position.Index > Container.Last then
651 raise Program_Error with "Position index is out of range";
654 Delete (Container, Position.Index, Count);
655 Position := No_Element;
662 procedure Delete_First
663 (Container : in out Vector;
664 Count : Count_Type := 1)
670 elsif Count >= Length (Container) then
675 Delete (Container, Index_Type'First, Count);
683 procedure Delete_Last
684 (Container : in out Vector;
685 Count : Count_Type := 1)
688 -- It is not permitted to delete items while the container is busy (for
689 -- example, we're in the middle of a passive iteration). However, we
690 -- always treat deleting 0 items as a no-op, even when we're busy, so we
691 -- simply return without checking.
697 -- The tampering bits exist to prevent an item from being deleted (or
698 -- otherwise harmfully manipulated) while it is being visited. Query,
699 -- Update, and Iterate increment the busy count on entry, and decrement
700 -- the count on exit. Delete_Last checks the count to determine whether
701 -- it is being called while the associated callback procedure is
704 if Container.Busy > 0 then
705 raise Program_Error with
706 "attempt to tamper with cursors (vector is busy)";
709 -- There is no restriction on how large Count can be when deleting
710 -- items. If it is equal or greater than the current length, then this
711 -- is equivalent to clearing the vector. (In particular, there's no need
712 -- for us to actually calculate the new value for Last.)
714 -- If the requested count is less than the current length, then we must
715 -- calculate the new value for Last. For the type we use the widest of
716 -- Index_Type'Base and Count_Type'Base for the intermediate values of
717 -- our calculation. (See the comments in Length for more information.)
719 if Count >= Container.Length then
720 Container.Last := No_Index;
722 elsif Index_Type'Base'Last
>= Count_Type
'Pos (Count_Type
'Last) then
723 Container
.Last
:= Container
.Last
- Index_Type
'Base (Count
);
727 Index_Type
'Base (Count_Type
'Base (Container
.Last
) - Count
);
737 Index
: Index_Type
) return Element_Type
740 if Index
> Container
.Last
then
741 raise Constraint_Error
with "Index is out of range";
743 return Container
.Elements
(To_Array_Index
(Index
));
747 function Element
(Position
: Cursor
) return Element_Type
is
749 if Position
.Container
= null then
750 raise Constraint_Error
with "Position cursor has no element";
752 return Position
.Container
.Element
(Position
.Index
);
760 procedure Finalize
(Object
: in out Iterator
) is
761 B
: Natural renames Object
.Container
.Busy
;
766 procedure Finalize
(Control
: in out Reference_Control_Type
) is
768 if Control
.Container
/= null then
770 C
: Vector
renames Control
.Container
.all;
771 B
: Natural renames C
.Busy
;
772 L
: Natural renames C
.Lock
;
778 Control
.Container
:= null;
789 Position
: Cursor
:= No_Element
) return Cursor
792 if Position
.Container
/= null then
793 if Position
.Container
/= Container
'Unrestricted_Access then
794 raise Program_Error
with "Position cursor denotes wrong container";
797 if Position
.Index
> Container
.Last
then
798 raise Program_Error
with "Position index is out of range";
802 -- Per AI05-0022, the container implementation is required to detect
803 -- element tampering by a generic actual subprogram.
806 B
: Natural renames Container
'Unrestricted_Access.Busy
;
807 L
: Natural renames Container
'Unrestricted_Access.Lock
;
809 Result
: Index_Type
'Base;
816 for J
in Position
.Index
.. Container
.Last
loop
817 if Container
.Elements
(To_Array_Index
(J
)) = Item
then
826 if Result
= No_Index
then
829 return Cursor
'(Container'Unrestricted_Access, Result);
848 Index : Index_Type := Index_Type'First) return Extended_Index
850 B : Natural renames Container'Unrestricted_Access.Busy;
851 L : Natural renames Container'Unrestricted_Access.Lock;
853 Result : Index_Type'Base;
856 -- Per AI05-0022, the container implementation is required to detect
857 -- element tampering by a generic actual subprogram.
863 for Indx in Index .. Container.Last loop
864 if Container.Elements (To_Array_Index (Indx)) = Item then
887 function First (Container : Vector) return Cursor is
889 if Is_Empty (Container) then
892 return (Container'Unrestricted_Access, Index_Type'First);
896 function First (Object : Iterator) return Cursor is
898 -- The value of the iterator object's Index component influences the
899 -- behavior of the First (and Last) selector function.
901 -- When the Index component is No_Index, this means the iterator
902 -- object was constructed without a start expression, in which case the
903 -- (forward) iteration starts from the (logical) beginning of the entire
904 -- sequence of items (corresponding to Container.First, for a forward
907 -- Otherwise, this is iteration over a partial sequence of items.
908 -- When the Index component isn't No_Index, the iterator object was
909 -- constructed with a start expression, that specifies the position
910 -- from which the (forward) partial iteration begins.
912 if Object.Index = No_Index then
913 return First (Object.Container.all);
915 return Cursor'(Object
.Container
, Object
.Index
);
923 function First_Element
(Container
: Vector
) return Element_Type
is
925 if Container
.Last
= No_Index
then
926 raise Constraint_Error
with "Container is empty";
928 return Container
.Elements
(To_Array_Index
(Index_Type
'First));
936 function First_Index
(Container
: Vector
) return Index_Type
is
937 pragma Unreferenced
(Container
);
939 return Index_Type
'First;
942 ---------------------
943 -- Generic_Sorting --
944 ---------------------
946 package body Generic_Sorting
is
952 function Is_Sorted
(Container
: Vector
) return Boolean is
954 if Container
.Last
<= Index_Type
'First then
958 -- Per AI05-0022, the container implementation is required to detect
959 -- element tampering by a generic actual subprogram.
962 EA
: Elements_Array
renames Container
.Elements
;
964 B
: Natural renames Container
'Unrestricted_Access.Busy
;
965 L
: Natural renames Container
'Unrestricted_Access.Lock
;
974 for J
in 1 .. Container
.Length
- 1 loop
975 if EA
(J
+ 1) < EA
(J
) then
999 procedure Merge
(Target
, Source
: in out Vector
) is
1003 -- The semantics of Merge changed slightly per AI05-0021. It was
1004 -- originally the case that if Target and Source denoted the same
1005 -- container object, then the GNAT implementation of Merge did
1006 -- nothing. However, it was argued that RM05 did not precisely
1007 -- specify the semantics for this corner case. The decision of the
1008 -- ARG was that if Target and Source denote the same non-empty
1009 -- container object, then Program_Error is raised.
1011 if Source
.Is_Empty
then
1015 if Target
'Address = Source
'Address then
1016 raise Program_Error
with
1017 "Target and Source denote same non-empty container";
1020 if Target
.Is_Empty
then
1021 Move
(Target
=> Target
, Source
=> Source
);
1025 if Source
.Busy
> 0 then
1026 raise Program_Error
with
1027 "attempt to tamper with cursors (vector is busy)";
1031 Target
.Set_Length
(I
+ Source
.Length
);
1033 -- Per AI05-0022, the container implementation is required to detect
1034 -- element tampering by a generic actual subprogram.
1037 TA
: Elements_Array
renames Target
.Elements
;
1038 SA
: Elements_Array
renames Source
.Elements
;
1040 TB
: Natural renames Target
.Busy
;
1041 TL
: Natural renames Target
.Lock
;
1043 SB
: Natural renames Source
.Busy
;
1044 SL
: Natural renames Source
.Lock
;
1054 while not Source
.Is_Empty
loop
1055 pragma Assert
(Source
.Length
<= 1
1056 or else not (SA
(Source
.Length
) < SA
(Source
.Length
- 1)));
1059 TA
(1 .. J
) := SA
(1 .. Source
.Length
);
1060 Source
.Last
:= No_Index
;
1064 pragma Assert
(I
<= 1
1065 or else not (TA
(I
) < TA
(I
- 1)));
1067 if SA
(Source
.Length
) < TA
(I
) then
1072 TA
(J
) := SA
(Source
.Length
);
1073 Source
.Last
:= Source
.Last
- 1;
1101 procedure Sort
(Container
: in out Vector
) is
1103 new Generic_Array_Sort
1104 (Index_Type
=> Count_Type
,
1105 Element_Type
=> Element_Type
,
1106 Array_Type
=> Elements_Array
,
1110 if Container
.Last
<= Index_Type
'First then
1114 -- The exception behavior for the vector container must match that
1115 -- for the list container, so we check for cursor tampering here
1116 -- (which will catch more things) instead of for element tampering
1117 -- (which will catch fewer things). It's true that the elements of
1118 -- this vector container could be safely moved around while (say) an
1119 -- iteration is taking place (iteration only increments the busy
1120 -- counter), and so technically all we would need here is a test for
1121 -- element tampering (indicated by the lock counter), that's simply
1122 -- an artifact of our array-based implementation. Logically Sort
1123 -- requires a check for cursor tampering.
1125 if Container
.Busy
> 0 then
1126 raise Program_Error
with
1127 "attempt to tamper with cursors (vector is busy)";
1130 -- Per AI05-0022, the container implementation is required to detect
1131 -- element tampering by a generic actual subprogram.
1134 B
: Natural renames Container
.Busy
;
1135 L
: Natural renames Container
.Lock
;
1141 Sort
(Container
.Elements
(1 .. Container
.Length
));
1155 end Generic_Sorting
;
1161 function Has_Element
(Position
: Cursor
) return Boolean is
1163 if Position
.Container
= null then
1167 return Position
.Index
<= Position
.Container
.Last
;
1175 (Container
: in out Vector
;
1176 Before
: Extended_Index
;
1177 New_Item
: Element_Type
;
1178 Count
: Count_Type
:= 1)
1180 EA
: Elements_Array
renames Container
.Elements
;
1181 Old_Length
: constant Count_Type
:= Container
.Length
;
1183 Max_Length
: Count_Type
'Base; -- determined from range of Index_Type
1184 New_Length
: Count_Type
'Base; -- sum of current length and Count
1186 Index
: Index_Type
'Base; -- scratch for intermediate values
1187 J
: Count_Type
'Base; -- scratch
1190 -- As a precondition on the generic actual Index_Type, the base type
1191 -- must include Index_Type'Pred (Index_Type'First); this is the value
1192 -- that Container.Last assumes when the vector is empty. However, we do
1193 -- not allow that as the value for Index when specifying where the new
1194 -- items should be inserted, so we must manually check. (That the user
1195 -- is allowed to specify the value at all here is a consequence of the
1196 -- declaration of the Extended_Index subtype, which includes the values
1197 -- in the base range that immediately precede and immediately follow the
1198 -- values in the Index_Type.)
1200 if Before
< Index_Type
'First then
1201 raise Constraint_Error
with
1202 "Before index is out of range (too small)";
1205 -- We do allow a value greater than Container.Last to be specified as
1206 -- the Index, but only if it's immediately greater. This allows for the
1207 -- case of appending items to the back end of the vector. (It is assumed
1208 -- that specifying an index value greater than Last + 1 indicates some
1209 -- deeper flaw in the caller's algorithm, so that case is treated as a
1212 if Before
> Container
.Last
1213 and then Before
> Container
.Last
+ 1
1215 raise Constraint_Error
with
1216 "Before index is out of range (too large)";
1219 -- We treat inserting 0 items into the container as a no-op, even when
1220 -- the container is busy, so we simply return.
1226 -- There are two constraints we need to satisfy. The first constraint is
1227 -- that a container cannot have more than Count_Type'Last elements, so
1228 -- we must check the sum of the current length and the insertion
1229 -- count. Note that we cannot simply add these values, because of the
1230 -- possibility of overflow.
1232 if Old_Length
> Count_Type
'Last - Count
then
1233 raise Constraint_Error
with "Count is out of range";
1236 -- It is now safe compute the length of the new vector, without fear of
1239 New_Length
:= Old_Length
+ Count
;
1241 -- The second constraint is that the new Last index value cannot exceed
1242 -- Index_Type'Last. In each branch below, we calculate the maximum
1243 -- length (computed from the range of values in Index_Type), and then
1244 -- compare the new length to the maximum length. If the new length is
1245 -- acceptable, then we compute the new last index from that.
1247 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
1249 -- We have to handle the case when there might be more values in the
1250 -- range of Index_Type than in the range of Count_Type.
1252 if Index_Type'First <= 0 then
1254 -- We know that No_Index (the same as Index_Type'First - 1) is
1255 -- less than 0, so it is safe to compute the following sum without
1256 -- fear of overflow.
1258 Index := No_Index + Index_Type'Base (Count_Type'Last);
1260 if Index <= Index_Type'Last then
1262 -- We have determined that range of Index_Type has at least as
1263 -- many values as in Count_Type, so Count_Type'Last is the
1264 -- maximum number of items that are allowed.
1266 Max_Length := Count_Type'Last;
1269 -- The range of Index_Type has fewer values than in Count_Type,
1270 -- so the maximum number of items is computed from the range of
1273 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1277 -- No_Index is equal or greater than 0, so we can safely compute
1278 -- the difference without fear of overflow (which we would have to
1279 -- worry about if No_Index were less than 0, but that case is
1282 if Index_Type'Last - No_Index >=
1283 Count_Type'Pos (Count_Type'Last)
1285 -- We have determined that range of Index_Type has at least as
1286 -- many values as in Count_Type, so Count_Type'Last is the
1287 -- maximum number of items that are allowed.
1289 Max_Length := Count_Type'Last;
1292 -- The range of Index_Type has fewer values than in Count_Type,
1293 -- so the maximum number of items is computed from the range of
1296 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1300 elsif Index_Type'First <= 0 then
1302 -- We know that No_Index (the same as Index_Type'First - 1) is less
1303 -- than 0, so it is safe to compute the following sum without fear of
1306 J := Count_Type'Base (No_Index) + Count_Type'Last;
1308 if J <= Count_Type'Base (Index_Type'Last) then
1310 -- We have determined that range of Index_Type has at least as
1311 -- many values as in Count_Type, so Count_Type'Last is the maximum
1312 -- number of items that are allowed.
1314 Max_Length := Count_Type'Last;
1317 -- The range of Index_Type has fewer values than Count_Type does,
1318 -- so the maximum number of items is computed from the range of
1322 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
1326 -- No_Index is equal or greater than 0, so we can safely compute the
1327 -- difference without fear of overflow (which we would have to worry
1328 -- about if No_Index were less than 0, but that case is handled
1332 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
1335 -- We have just computed the maximum length (number of items). We must
1336 -- now compare the requested length to the maximum length, as we do not
1337 -- allow a vector expand beyond the maximum (because that would create
1338 -- an internal array with a last index value greater than
1339 -- Index_Type'Last, with no way to index those elements).
1341 if New_Length > Max_Length then
1342 raise Constraint_Error with "Count is out of range";
1345 -- The tampering bits exist to prevent an item from being harmfully
1346 -- manipulated while it is being visited. Query, Update, and Iterate
1347 -- increment the busy count on entry, and decrement the count on
1348 -- exit. Insert checks the count to determine whether it is being called
1349 -- while the associated callback procedure is executing.
1351 if Container.Busy > 0 then
1352 raise Program_Error with
1353 "attempt to tamper with cursors (vector is busy)";
1356 if New_Length > Container.Capacity then
1357 raise Capacity_Error with "New length is larger than capacity";
1360 J := To_Array_Index (Before);
1362 if Before > Container.Last then
1364 -- The new items are being appended to the vector, so no
1365 -- sliding of existing elements is required.
1367 EA (J .. New_Length) := (others => New_Item);
1370 -- The new items are being inserted before some existing
1371 -- elements, so we must slide the existing elements up to their
1374 EA (J + Count .. New_Length) := EA (J .. Old_Length);
1375 EA (J .. J + Count - 1) := (others => New_Item);
1378 if Index_Type'Base'Last
>= Count_Type
'Pos (Count_Type
'Last) then
1379 Container
.Last
:= No_Index
+ Index_Type
'Base (New_Length
);
1383 Index_Type
'Base (Count_Type
'Base (No_Index
) + New_Length
);
1388 (Container
: in out Vector
;
1389 Before
: Extended_Index
;
1392 N
: constant Count_Type
:= Length
(New_Item
);
1393 B
: Count_Type
; -- index Before converted to Count_Type
1396 -- Use Insert_Space to create the "hole" (the destination slice) into
1397 -- which we copy the source items.
1399 Insert_Space
(Container
, Before
, Count
=> N
);
1402 -- There's nothing else to do here (vetting of parameters was
1403 -- performed already in Insert_Space), so we simply return.
1408 B
:= To_Array_Index
(Before
);
1410 if Container
'Address /= New_Item
'Address then
1411 -- This is the simple case. New_Item denotes an object different
1412 -- from Container, so there's nothing special we need to do to copy
1413 -- the source items to their destination, because all of the source
1414 -- items are contiguous.
1416 Container
.Elements
(B
.. B
+ N
- 1) := New_Item
.Elements
(1 .. N
);
1420 -- We refer to array index value Before + N - 1 as J. This is the last
1421 -- index value of the destination slice.
1423 -- New_Item denotes the same object as Container, so an insertion has
1424 -- potentially split the source items. The destination is always the
1425 -- range [Before, J], but the source is [Index_Type'First, Before) and
1426 -- (J, Container.Last]. We perform the copy in two steps, using each of
1427 -- the two slices of the source items.
1430 subtype Src_Index_Subtype
is Count_Type
'Base range 1 .. B
- 1;
1432 Src
: Elements_Array
renames Container
.Elements
(Src_Index_Subtype
);
1435 -- We first copy the source items that precede the space we
1436 -- inserted. (If Before equals Index_Type'First, then this first
1437 -- source slice will be empty, which is harmless.)
1439 Container
.Elements
(B
.. B
+ Src
'Length - 1) := Src
;
1443 subtype Src_Index_Subtype
is Count_Type
'Base range
1444 B
+ N
.. Container
.Length
;
1446 Src
: Elements_Array
renames Container
.Elements
(Src_Index_Subtype
);
1449 -- We next copy the source items that follow the space we inserted.
1451 Container
.Elements
(B
+ N
- Src
'Length .. B
+ N
- 1) := Src
;
1456 (Container
: in out Vector
;
1460 Index
: Index_Type
'Base;
1463 if Before
.Container
/= null
1464 and then Before
.Container
/= Container
'Unchecked_Access
1466 raise Program_Error
with "Before cursor denotes wrong container";
1469 if Is_Empty
(New_Item
) then
1473 if Before
.Container
= null
1474 or else Before
.Index
> Container
.Last
1476 if Container
.Last
= Index_Type
'Last then
1477 raise Constraint_Error
with
1478 "vector is already at its maximum length";
1481 Index
:= Container
.Last
+ 1;
1484 Index
:= Before
.Index
;
1487 Insert
(Container
, Index
, New_Item
);
1491 (Container
: in out Vector
;
1494 Position
: out Cursor
)
1496 Index
: Index_Type
'Base;
1499 if Before
.Container
/= null
1500 and then Before
.Container
/= Container
'Unchecked_Access
1502 raise Program_Error
with "Before cursor denotes wrong container";
1505 if Is_Empty
(New_Item
) then
1506 if Before
.Container
= null
1507 or else Before
.Index
> Container
.Last
1509 Position
:= No_Element
;
1511 Position
:= (Container
'Unchecked_Access, Before
.Index
);
1517 if Before
.Container
= null
1518 or else Before
.Index
> Container
.Last
1520 if Container
.Last
= Index_Type
'Last then
1521 raise Constraint_Error
with
1522 "vector is already at its maximum length";
1525 Index
:= Container
.Last
+ 1;
1528 Index
:= Before
.Index
;
1531 Insert
(Container
, Index
, New_Item
);
1533 Position
:= Cursor
'(Container'Unchecked_Access, Index);
1537 (Container : in out Vector;
1539 New_Item : Element_Type;
1540 Count : Count_Type := 1)
1542 Index : Index_Type'Base;
1545 if Before.Container /= null
1546 and then Before.Container /= Container'Unchecked_Access
1548 raise Program_Error with "Before cursor denotes wrong container";
1555 if Before.Container = null
1556 or else Before.Index > Container.Last
1558 if Container.Last = Index_Type'Last then
1559 raise Constraint_Error with
1560 "vector is already at its maximum length";
1563 Index := Container.Last + 1;
1566 Index := Before.Index;
1569 Insert (Container, Index, New_Item, Count);
1573 (Container : in out Vector;
1575 New_Item : Element_Type;
1576 Position : out Cursor;
1577 Count : Count_Type := 1)
1579 Index : Index_Type'Base;
1582 if Before.Container /= null
1583 and then Before.Container /= Container'Unchecked_Access
1585 raise Program_Error with "Before cursor denotes wrong container";
1589 if Before.Container = null
1590 or else Before.Index > Container.Last
1592 Position := No_Element;
1594 Position := (Container'Unchecked_Access, Before.Index);
1600 if Before.Container = null
1601 or else Before.Index > Container.Last
1603 if Container.Last = Index_Type'Last then
1604 raise Constraint_Error with
1605 "vector is already at its maximum length";
1608 Index := Container.Last + 1;
1611 Index := Before.Index;
1614 Insert (Container, Index, New_Item, Count);
1616 Position := Cursor'(Container
'Unchecked_Access, Index
);
1620 (Container
: in out Vector
;
1621 Before
: Extended_Index
;
1622 Count
: Count_Type
:= 1)
1624 New_Item
: Element_Type
; -- Default-initialized value
1625 pragma Warnings
(Off
, New_Item
);
1628 Insert
(Container
, Before
, New_Item
, Count
);
1632 (Container
: in out Vector
;
1634 Position
: out Cursor
;
1635 Count
: Count_Type
:= 1)
1637 New_Item
: Element_Type
; -- Default-initialized value
1638 pragma Warnings
(Off
, New_Item
);
1641 Insert
(Container
, Before
, New_Item
, Position
, Count
);
1648 procedure Insert_Space
1649 (Container
: in out Vector
;
1650 Before
: Extended_Index
;
1651 Count
: Count_Type
:= 1)
1653 EA
: Elements_Array
renames Container
.Elements
;
1654 Old_Length
: constant Count_Type
:= Container
.Length
;
1656 Max_Length
: Count_Type
'Base; -- determined from range of Index_Type
1657 New_Length
: Count_Type
'Base; -- sum of current length and Count
1659 Index
: Index_Type
'Base; -- scratch for intermediate values
1660 J
: Count_Type
'Base; -- scratch
1663 -- As a precondition on the generic actual Index_Type, the base type
1664 -- must include Index_Type'Pred (Index_Type'First); this is the value
1665 -- that Container.Last assumes when the vector is empty. However, we do
1666 -- not allow that as the value for Index when specifying where the new
1667 -- items should be inserted, so we must manually check. (That the user
1668 -- is allowed to specify the value at all here is a consequence of the
1669 -- declaration of the Extended_Index subtype, which includes the values
1670 -- in the base range that immediately precede and immediately follow the
1671 -- values in the Index_Type.)
1673 if Before
< Index_Type
'First then
1674 raise Constraint_Error
with
1675 "Before index is out of range (too small)";
1678 -- We do allow a value greater than Container.Last to be specified as
1679 -- the Index, but only if it's immediately greater. This allows for the
1680 -- case of appending items to the back end of the vector. (It is assumed
1681 -- that specifying an index value greater than Last + 1 indicates some
1682 -- deeper flaw in the caller's algorithm, so that case is treated as a
1685 if Before
> Container
.Last
1686 and then Before
> Container
.Last
+ 1
1688 raise Constraint_Error
with
1689 "Before index is out of range (too large)";
1692 -- We treat inserting 0 items into the container as a no-op, even when
1693 -- the container is busy, so we simply return.
1699 -- There are two constraints we need to satisfy. The first constraint is
1700 -- that a container cannot have more than Count_Type'Last elements, so
1701 -- we must check the sum of the current length and the insertion count.
1702 -- Note that we cannot simply add these values, because of the
1703 -- possibility of overflow.
1705 if Old_Length
> Count_Type
'Last - Count
then
1706 raise Constraint_Error
with "Count is out of range";
1709 -- It is now safe compute the length of the new vector, without fear of
1712 New_Length
:= Old_Length
+ Count
;
1714 -- The second constraint is that the new Last index value cannot exceed
1715 -- Index_Type'Last. In each branch below, we calculate the maximum
1716 -- length (computed from the range of values in Index_Type), and then
1717 -- compare the new length to the maximum length. If the new length is
1718 -- acceptable, then we compute the new last index from that.
1720 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
1722 -- We have to handle the case when there might be more values in the
1723 -- range of Index_Type than in the range of Count_Type.
1725 if Index_Type'First <= 0 then
1727 -- We know that No_Index (the same as Index_Type'First - 1) is
1728 -- less than 0, so it is safe to compute the following sum without
1729 -- fear of overflow.
1731 Index := No_Index + Index_Type'Base (Count_Type'Last);
1733 if Index <= Index_Type'Last then
1735 -- We have determined that range of Index_Type has at least as
1736 -- many values as in Count_Type, so Count_Type'Last is the
1737 -- maximum number of items that are allowed.
1739 Max_Length := Count_Type'Last;
1742 -- The range of Index_Type has fewer values than in Count_Type,
1743 -- so the maximum number of items is computed from the range of
1746 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1750 -- No_Index is equal or greater than 0, so we can safely compute
1751 -- the difference without fear of overflow (which we would have to
1752 -- worry about if No_Index were less than 0, but that case is
1755 if Index_Type'Last - No_Index >=
1756 Count_Type'Pos (Count_Type'Last)
1758 -- We have determined that range of Index_Type has at least as
1759 -- many values as in Count_Type, so Count_Type'Last is the
1760 -- maximum number of items that are allowed.
1762 Max_Length := Count_Type'Last;
1765 -- The range of Index_Type has fewer values than in Count_Type,
1766 -- so the maximum number of items is computed from the range of
1769 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1773 elsif Index_Type'First <= 0 then
1775 -- We know that No_Index (the same as Index_Type'First - 1) is less
1776 -- than 0, so it is safe to compute the following sum without fear of
1779 J := Count_Type'Base (No_Index) + Count_Type'Last;
1781 if J <= Count_Type'Base (Index_Type'Last) then
1783 -- We have determined that range of Index_Type has at least as
1784 -- many values as in Count_Type, so Count_Type'Last is the maximum
1785 -- number of items that are allowed.
1787 Max_Length := Count_Type'Last;
1790 -- The range of Index_Type has fewer values than Count_Type does,
1791 -- so the maximum number of items is computed from the range of
1795 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
1799 -- No_Index is equal or greater than 0, so we can safely compute the
1800 -- difference without fear of overflow (which we would have to worry
1801 -- about if No_Index were less than 0, but that case is handled
1805 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
1808 -- We have just computed the maximum length (number of items). We must
1809 -- now compare the requested length to the maximum length, as we do not
1810 -- allow a vector expand beyond the maximum (because that would create
1811 -- an internal array with a last index value greater than
1812 -- Index_Type'Last, with no way to index those elements).
1814 if New_Length > Max_Length then
1815 raise Constraint_Error with "Count is out of range";
1818 -- The tampering bits exist to prevent an item from being harmfully
1819 -- manipulated while it is being visited. Query, Update, and Iterate
1820 -- increment the busy count on entry, and decrement the count on
1821 -- exit. Insert checks the count to determine whether it is being called
1822 -- while the associated callback procedure is executing.
1824 if Container.Busy > 0 then
1825 raise Program_Error with
1826 "attempt to tamper with cursors (vector is busy)";
1829 -- An internal array has already been allocated, so we need to check
1830 -- whether there is enough unused storage for the new items.
1832 if New_Length > Container.Capacity then
1833 raise Capacity_Error with "New length is larger than capacity";
1836 -- In this case, we're inserting space into a vector that has already
1837 -- allocated an internal array, and the existing array has enough
1838 -- unused storage for the new items.
1840 if Before <= Container.Last then
1842 -- The space is being inserted before some existing elements,
1843 -- so we must slide the existing elements up to their new home.
1845 J := To_Array_Index (Before);
1846 EA (J + Count .. New_Length) := EA (J .. Old_Length);
1849 -- New_Last is the last index value of the items in the container after
1850 -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to
1851 -- compute its value from the New_Length.
1853 if Index_Type'Base'Last
>= Count_Type
'Pos (Count_Type
'Last) then
1854 Container
.Last
:= No_Index
+ Index_Type
'Base (New_Length
);
1858 Index_Type
'Base (Count_Type
'Base (No_Index
) + New_Length
);
1862 procedure Insert_Space
1863 (Container
: in out Vector
;
1865 Position
: out Cursor
;
1866 Count
: Count_Type
:= 1)
1868 Index
: Index_Type
'Base;
1871 if Before
.Container
/= null
1872 and then Before
.Container
/= Container
'Unchecked_Access
1874 raise Program_Error
with "Before cursor denotes wrong container";
1878 if Before
.Container
= null
1879 or else Before
.Index
> Container
.Last
1881 Position
:= No_Element
;
1883 Position
:= (Container
'Unchecked_Access, Before
.Index
);
1889 if Before
.Container
= null
1890 or else Before
.Index
> Container
.Last
1892 if Container
.Last
= Index_Type
'Last then
1893 raise Constraint_Error
with
1894 "vector is already at its maximum length";
1897 Index
:= Container
.Last
+ 1;
1900 Index
:= Before
.Index
;
1903 Insert_Space
(Container
, Index
, Count
=> Count
);
1905 Position
:= Cursor
'(Container'Unchecked_Access, Index);
1912 function Is_Empty (Container : Vector) return Boolean is
1914 return Container.Last < Index_Type'First;
1922 (Container : Vector;
1923 Process : not null access procedure (Position : Cursor))
1925 B : Natural renames Container'Unrestricted_Access.all.Busy;
1931 for Indx in Index_Type'First .. Container.Last loop
1932 Process (Cursor'(Container
'Unrestricted_Access, Indx
));
1944 (Container
: Vector
)
1945 return Vector_Iterator_Interfaces
.Reversible_Iterator
'Class
1947 V
: constant Vector_Access
:= Container
'Unrestricted_Access;
1948 B
: Natural renames V
.Busy
;
1951 -- The value of its Index component influences the behavior of the First
1952 -- and Last selector functions of the iterator object. When the Index
1953 -- component is No_Index (as is the case here), this means the iterator
1954 -- object was constructed without a start expression. This is a complete
1955 -- iterator, meaning that the iteration starts from the (logical)
1956 -- beginning of the sequence of items.
1958 -- Note: For a forward iterator, Container.First is the beginning, and
1959 -- for a reverse iterator, Container.Last is the beginning.
1961 return It
: constant Iterator
:=
1962 (Limited_Controlled
with
1971 (Container
: Vector
;
1973 return Vector_Iterator_Interfaces
.Reversible_Iterator
'Class
1975 V
: constant Vector_Access
:= Container
'Unrestricted_Access;
1976 B
: Natural renames V
.Busy
;
1979 -- It was formerly the case that when Start = No_Element, the partial
1980 -- iterator was defined to behave the same as for a complete iterator,
1981 -- and iterate over the entire sequence of items. However, those
1982 -- semantics were unintuitive and arguably error-prone (it is too easy
1983 -- to accidentally create an endless loop), and so they were changed,
1984 -- per the ARG meeting in Denver on 2011/11. However, there was no
1985 -- consensus about what positive meaning this corner case should have,
1986 -- and so it was decided to simply raise an exception. This does imply,
1987 -- however, that it is not possible to use a partial iterator to specify
1988 -- an empty sequence of items.
1990 if Start
.Container
= null then
1991 raise Constraint_Error
with
1992 "Start position for iterator equals No_Element";
1995 if Start
.Container
/= V
then
1996 raise Program_Error
with
1997 "Start cursor of Iterate designates wrong vector";
2000 if Start
.Index
> V
.Last
then
2001 raise Constraint_Error
with
2002 "Start position for iterator equals No_Element";
2005 -- The value of its Index component influences the behavior of the First
2006 -- and Last selector functions of the iterator object. When the Index
2007 -- component is not No_Index (as is the case here), it means that this
2008 -- is a partial iteration, over a subset of the complete sequence of
2009 -- items. The iterator object was constructed with a start expression,
2010 -- indicating the position from which the iteration begins. Note that
2011 -- the start position has the same value irrespective of whether this is
2012 -- a forward or reverse iteration.
2014 return It
: constant Iterator
:=
2015 (Limited_Controlled
with
2017 Index
=> Start
.Index
)
2027 function Last
(Container
: Vector
) return Cursor
is
2029 if Is_Empty
(Container
) then
2032 return (Container
'Unrestricted_Access, Container
.Last
);
2036 function Last
(Object
: Iterator
) return Cursor
is
2038 -- The value of the iterator object's Index component influences the
2039 -- behavior of the Last (and First) selector function.
2041 -- When the Index component is No_Index, this means the iterator object
2042 -- was constructed without a start expression, in which case the
2043 -- (reverse) iteration starts from the (logical) beginning of the entire
2044 -- sequence (corresponding to Container.Last, for a reverse iterator).
2046 -- Otherwise, this is iteration over a partial sequence of items. When
2047 -- the Index component is not No_Index, the iterator object was
2048 -- constructed with a start expression, that specifies the position from
2049 -- which the (reverse) partial iteration begins.
2051 if Object
.Index
= No_Index
then
2052 return Last
(Object
.Container
.all);
2054 return Cursor
'(Object.Container, Object.Index);
2062 function Last_Element (Container : Vector) return Element_Type is
2064 if Container.Last = No_Index then
2065 raise Constraint_Error with "Container is empty";
2067 return Container.Elements (Container.Length);
2075 function Last_Index (Container : Vector) return Extended_Index is
2077 return Container.Last;
2084 function Length (Container : Vector) return Count_Type is
2085 L : constant Index_Type'Base := Container.Last;
2086 F : constant Index_Type := Index_Type'First;
2089 -- The base range of the index type (Index_Type'Base) might not include
2090 -- all values for length (Count_Type). Contrariwise, the index type
2091 -- might include values outside the range of length. Hence we use
2092 -- whatever type is wider for intermediate values when calculating
2093 -- length. Note that no matter what the index type is, the maximum
2094 -- length to which a vector is allowed to grow is always the minimum
2095 -- of Count_Type'Last and (IT'Last - IT'First + 1).
2097 -- For example, an Index_Type with range -127 .. 127 is only guaranteed
2098 -- to have a base range of -128 .. 127, but the corresponding vector
2099 -- would have lengths in the range 0 .. 255. In this case we would need
2100 -- to use Count_Type'Base for intermediate values.
2102 -- Another case would be the index range -2**63 + 1 .. -2**63 + 10. The
2103 -- vector would have a maximum length of 10, but the index values lie
2104 -- outside the range of Count_Type (which is only 32 bits). In this
2105 -- case we would need to use Index_Type'Base for intermediate values.
2107 if Count_Type'Base'Last
>= Index_Type
'Pos (Index_Type
'Base'Last) then
2108 return Count_Type'Base (L) - Count_Type'Base (F) + 1;
2110 return Count_Type (L - F + 1);
2119 (Target : in out Vector;
2120 Source : in out Vector)
2123 if Target'Address = Source'Address then
2127 if Target.Capacity < Source.Length then
2128 raise Capacity_Error -- ???
2129 with "Target capacity is less than Source length";
2132 if Target.Busy > 0 then
2133 raise Program_Error with
2134 "attempt to tamper with cursors (Target is busy)";
2137 if Source.Busy > 0 then
2138 raise Program_Error with
2139 "attempt to tamper with cursors (Source is busy)";
2142 -- Clear Target now, in case element assignment fails
2144 Target.Last := No_Index;
2146 Target.Elements (1 .. Source.Length) :=
2147 Source.Elements (1 .. Source.Length);
2149 Target.Last := Source.Last;
2150 Source.Last := No_Index;
2157 function Next (Position : Cursor) return Cursor is
2159 if Position.Container = null then
2161 elsif Position.Index < Position.Container.Last then
2162 return (Position.Container, Position.Index + 1);
2168 function Next (Object : Iterator; Position : Cursor) return Cursor is
2170 if Position.Container = null then
2172 elsif Position.Container /= Object.Container then
2173 raise Program_Error with
2174 "Position cursor of Next designates wrong vector";
2176 return Next (Position);
2180 procedure Next (Position : in out Cursor) is
2182 if Position.Container = null then
2184 elsif Position.Index < Position.Container.Last then
2185 Position.Index := Position.Index + 1;
2187 Position := No_Element;
2195 procedure Prepend (Container : in out Vector; New_Item : Vector) is
2197 Insert (Container, Index_Type'First, New_Item);
2201 (Container : in out Vector;
2202 New_Item : Element_Type;
2203 Count : Count_Type := 1)
2216 procedure Previous (Position : in out Cursor) is
2218 if Position.Container = null then
2220 elsif Position.Index > Index_Type'First then
2221 Position.Index := Position.Index - 1;
2223 Position := No_Element;
2227 function Previous (Position : Cursor) return Cursor is
2229 if Position.Container = null then
2231 elsif Position.Index > Index_Type'First then
2232 return (Position.Container, Position.Index - 1);
2238 function Previous (Object : Iterator; Position : Cursor) return Cursor is
2240 if Position.Container = null then
2242 elsif Position.Container /= Object.Container then
2243 raise Program_Error with
2244 "Position cursor of Previous designates wrong vector";
2246 return Previous (Position);
2254 procedure Query_Element
2255 (Container : Vector;
2257 Process : not null access procedure (Element : Element_Type))
2259 V : Vector renames Container'Unrestricted_Access.all;
2260 B : Natural renames V.Busy;
2261 L : Natural renames V.Lock;
2264 if Index > Container.Last then
2265 raise Constraint_Error with "Index is out of range";
2272 Process (V.Elements (To_Array_Index (Index)));
2284 procedure Query_Element
2286 Process : not null access procedure (Element : Element_Type))
2289 if Position.Container = null then
2290 raise Constraint_Error with "Position cursor has no element";
2292 Query_Element (Position.Container.all, Position.Index, Process);
2301 (Stream : not null access Root_Stream_Type'Class;
2302 Container : out Vector)
2304 Length : Count_Type'Base;
2305 Last : Index_Type'Base := No_Index;
2310 Count_Type'Base'Read
(Stream
, Length
);
2312 Reserve_Capacity
(Container
, Capacity
=> Length
);
2314 for Idx
in Count_Type
range 1 .. Length
loop
2316 Element_Type
'Read (Stream
, Container
.Elements
(Idx
));
2317 Container
.Last
:= Last
;
2322 (Stream
: not null access Root_Stream_Type
'Class;
2323 Position
: out Cursor
)
2326 raise Program_Error
with "attempt to stream vector cursor";
2330 (Stream
: not null access Root_Stream_Type
'Class;
2331 Item
: out Reference_Type
)
2334 raise Program_Error
with "attempt to stream reference";
2338 (Stream
: not null access Root_Stream_Type
'Class;
2339 Item
: out Constant_Reference_Type
)
2342 raise Program_Error
with "attempt to stream reference";
2350 (Container
: aliased in out Vector
;
2351 Position
: Cursor
) return Reference_Type
2354 if Position
.Container
= null then
2355 raise Constraint_Error
with "Position cursor has no element";
2358 if Position
.Container
/= Container
'Unrestricted_Access then
2359 raise Program_Error
with "Position cursor denotes wrong container";
2362 if Position
.Index
> Position
.Container
.Last
then
2363 raise Constraint_Error
with "Position cursor is out of range";
2367 A
: Elements_Array
renames Container
.Elements
;
2368 B
: Natural renames Container
.Busy
;
2369 L
: Natural renames Container
.Lock
;
2370 J
: constant Count_Type
:= To_Array_Index
(Position
.Index
);
2374 return (Element
=> A
(J
)'Access,
2375 Control
=> (Controlled
with Container
'Unrestricted_Access));
2380 (Container
: aliased in out Vector
;
2381 Index
: Index_Type
) return Reference_Type
2384 if Index
> Container
.Last
then
2385 raise Constraint_Error
with "Index is out of range";
2389 A
: Elements_Array
renames Container
.Elements
;
2390 B
: Natural renames Container
.Busy
;
2391 L
: Natural renames Container
.Lock
;
2392 J
: constant Count_Type
:= To_Array_Index
(Index
);
2396 return (Element
=> A
(J
)'Access,
2397 Control
=> (Controlled
with Container
'Unrestricted_Access));
2401 ---------------------
2402 -- Replace_Element --
2403 ---------------------
2405 procedure Replace_Element
2406 (Container
: in out Vector
;
2408 New_Item
: Element_Type
)
2411 if Index
> Container
.Last
then
2412 raise Constraint_Error
with "Index is out of range";
2413 elsif Container
.Lock
> 0 then
2414 raise Program_Error
with
2415 "attempt to tamper with elements (vector is locked)";
2417 Container
.Elements
(To_Array_Index
(Index
)) := New_Item
;
2419 end Replace_Element
;
2421 procedure Replace_Element
2422 (Container
: in out Vector
;
2424 New_Item
: Element_Type
)
2427 if Position
.Container
= null then
2428 raise Constraint_Error
with "Position cursor has no element";
2430 elsif Position
.Container
/= Container
'Unrestricted_Access then
2431 raise Program_Error
with "Position cursor denotes wrong container";
2433 elsif Position
.Index
> Container
.Last
then
2434 raise Constraint_Error
with "Position cursor is out of range";
2436 elsif Container
.Lock
> 0 then
2437 raise Program_Error
with
2438 "attempt to tamper with elements (vector is locked)";
2441 Container
.Elements
(To_Array_Index
(Position
.Index
)) := New_Item
;
2443 end Replace_Element
;
2445 ----------------------
2446 -- Reserve_Capacity --
2447 ----------------------
2449 procedure Reserve_Capacity
2450 (Container
: in out Vector
;
2451 Capacity
: Count_Type
)
2454 if Capacity
> Container
.Capacity
then
2455 raise Capacity_Error
with "Capacity is out of range";
2457 end Reserve_Capacity
;
2459 ----------------------
2460 -- Reverse_Elements --
2461 ----------------------
2463 procedure Reverse_Elements
(Container
: in out Vector
) is
2464 E
: Elements_Array
renames Container
.Elements
;
2469 if Container
.Length
<= 1 then
2473 -- The exception behavior for the vector container must match that for
2474 -- the list container, so we check for cursor tampering here (which will
2475 -- catch more things) instead of for element tampering (which will catch
2476 -- fewer things). It's true that the elements of this vector container
2477 -- could be safely moved around while (say) an iteration is taking place
2478 -- (iteration only increments the busy counter), and so technically
2479 -- all we would need here is a test for element tampering (indicated
2480 -- by the lock counter), that's simply an artifact of our array-based
2481 -- implementation. Logically Reverse_Elements requires a check for
2482 -- cursor tampering.
2484 if Container
.Busy
> 0 then
2485 raise Program_Error
with
2486 "attempt to tamper with cursors (vector is busy)";
2490 Jdx
:= Container
.Length
;
2491 while Idx
< Jdx
loop
2493 EI
: constant Element_Type
:= E
(Idx
);
2503 end Reverse_Elements
;
2509 function Reverse_Find
2510 (Container
: Vector
;
2511 Item
: Element_Type
;
2512 Position
: Cursor
:= No_Element
) return Cursor
2514 Last
: Index_Type
'Base;
2517 if Position
.Container
/= null
2518 and then Position
.Container
/= Container
'Unrestricted_Access
2520 raise Program_Error
with "Position cursor denotes wrong container";
2524 (if Position
.Container
= null or else Position
.Index
> Container
.Last
2526 else Position
.Index
);
2528 -- Per AI05-0022, the container implementation is required to detect
2529 -- element tampering by a generic actual subprogram.
2532 B
: Natural renames Container
'Unrestricted_Access.Busy
;
2533 L
: Natural renames Container
'Unrestricted_Access.Lock
;
2535 Result
: Index_Type
'Base;
2542 for Indx
in reverse Index_Type
'First .. Last
loop
2543 if Container
.Elements
(To_Array_Index
(Indx
)) = Item
then
2552 if Result
= No_Index
then
2555 return Cursor
'(Container'Unrestricted_Access, Result);
2567 ------------------------
2568 -- Reverse_Find_Index --
2569 ------------------------
2571 function Reverse_Find_Index
2572 (Container : Vector;
2573 Item : Element_Type;
2574 Index : Index_Type := Index_Type'Last) return Extended_Index
2576 B : Natural renames Container'Unrestricted_Access.Busy;
2577 L : Natural renames Container'Unrestricted_Access.Lock;
2579 Last : constant Index_Type'Base :=
2580 Index_Type'Min (Container.Last, Index);
2582 Result : Index_Type'Base;
2585 -- Per AI05-0022, the container implementation is required to detect
2586 -- element tampering by a generic actual subprogram.
2592 for Indx in reverse Index_Type'First .. Last loop
2593 if Container.Elements (To_Array_Index (Indx)) = Item then
2610 end Reverse_Find_Index;
2612 ---------------------
2613 -- Reverse_Iterate --
2614 ---------------------
2616 procedure Reverse_Iterate
2617 (Container : Vector;
2618 Process : not null access procedure (Position : Cursor))
2620 V : Vector renames Container'Unrestricted_Access.all;
2621 B : Natural renames V.Busy;
2627 for Indx in reverse Index_Type'First .. Container.Last loop
2628 Process (Cursor'(Container
'Unrestricted_Access, Indx
));
2637 end Reverse_Iterate
;
2643 procedure Set_Length
(Container
: in out Vector
; Length
: Count_Type
) is
2644 Count
: constant Count_Type
'Base := Container
.Length
- Length
;
2647 -- Set_Length allows the user to set the length explicitly, instead of
2648 -- implicitly as a side-effect of deletion or insertion. If the
2649 -- requested length is less than the current length, this is equivalent
2650 -- to deleting items from the back end of the vector. If the requested
2651 -- length is greater than the current length, then this is equivalent to
2652 -- inserting "space" (nonce items) at the end.
2655 Container
.Delete_Last
(Count
);
2656 elsif Container
.Last
>= Index_Type
'Last then
2657 raise Constraint_Error
with "vector is already at its maximum length";
2659 Container
.Insert_Space
(Container
.Last
+ 1, -Count
);
2667 procedure Swap
(Container
: in out Vector
; I
, J
: Index_Type
) is
2668 E
: Elements_Array
renames Container
.Elements
;
2671 if I
> Container
.Last
then
2672 raise Constraint_Error
with "I index is out of range";
2675 if J
> Container
.Last
then
2676 raise Constraint_Error
with "J index is out of range";
2683 if Container
.Lock
> 0 then
2684 raise Program_Error
with
2685 "attempt to tamper with elements (vector is locked)";
2689 EI_Copy
: constant Element_Type
:= E
(To_Array_Index
(I
));
2691 E
(To_Array_Index
(I
)) := E
(To_Array_Index
(J
));
2692 E
(To_Array_Index
(J
)) := EI_Copy
;
2696 procedure Swap
(Container
: in out Vector
; I
, J
: Cursor
) is
2698 if I
.Container
= null then
2699 raise Constraint_Error
with "I cursor has no element";
2702 if J
.Container
= null then
2703 raise Constraint_Error
with "J cursor has no element";
2706 if I
.Container
/= Container
'Unrestricted_Access then
2707 raise Program_Error
with "I cursor denotes wrong container";
2710 if J
.Container
/= Container
'Unrestricted_Access then
2711 raise Program_Error
with "J cursor denotes wrong container";
2714 Swap
(Container
, I
.Index
, J
.Index
);
2717 --------------------
2718 -- To_Array_Index --
2719 --------------------
2721 function To_Array_Index
(Index
: Index_Type
'Base) return Count_Type
'Base is
2722 Offset
: Count_Type
'Base;
2726 -- Index >= Index_Type'First
2727 -- hence we also know that
2728 -- Index - Index_Type'First >= 0
2730 -- The issue is that even though 0 is guaranteed to be a value in
2731 -- the type Index_Type'Base, there's no guarantee that the difference
2732 -- is a value in that type. To prevent overflow we use the wider
2733 -- of Count_Type'Base and Index_Type'Base to perform intermediate
2736 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
2737 Offset := Count_Type'Base (Index - Index_Type'First);
2740 Offset := Count_Type'Base (Index) -
2741 Count_Type'Base (Index_Type'First);
2744 -- The array index subtype for all container element arrays
2745 -- always starts with 1.
2755 (Container : Vector;
2756 Index : Extended_Index) return Cursor
2759 if Index not in Index_Type'First .. Container.Last then
2763 return Cursor'(Container
'Unrestricted_Access, Index
);
2770 function To_Index
(Position
: Cursor
) return Extended_Index
is
2772 if Position
.Container
= null then
2776 if Position
.Index
<= Position
.Container
.Last
then
2777 return Position
.Index
;
2787 function To_Vector
(Length
: Count_Type
) return Vector
is
2788 Index
: Count_Type
'Base;
2789 Last
: Index_Type
'Base;
2793 return Empty_Vector
;
2796 -- We create a vector object with a capacity that matches the specified
2797 -- Length, but we do not allow the vector capacity (the length of the
2798 -- internal array) to exceed the number of values in Index_Type'Range
2799 -- (otherwise, there would be no way to refer to those components via an
2800 -- index). We must therefore check whether the specified Length would
2801 -- create a Last index value greater than Index_Type'Last.
2803 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
2804 -- We perform a two-part test. First we determine whether the
2805 -- computed Last value lies in the base range of the type, and then
2806 -- determine whether it lies in the range of the index (sub)type.
2808 -- Last must satisfy this relation:
2809 -- First + Length - 1 <= Last
2810 -- We regroup terms:
2811 -- First - 1 <= Last - Length
2812 -- Which can rewrite as:
2813 -- No_Index <= Last - Length
2815 if Index_Type'Base'Last
- Index_Type
'Base (Length
) < No_Index
then
2816 raise Constraint_Error
with "Length is out of range";
2819 -- We now know that the computed value of Last is within the base
2820 -- range of the type, so it is safe to compute its value:
2822 Last
:= No_Index
+ Index_Type
'Base (Length
);
2824 -- Finally we test whether the value is within the range of the
2825 -- generic actual index subtype:
2827 if Last
> Index_Type
'Last then
2828 raise Constraint_Error
with "Length is out of range";
2831 elsif Index_Type
'First <= 0 then
2833 -- Here we can compute Last directly, in the normal way. We know that
2834 -- No_Index is less than 0, so there is no danger of overflow when
2835 -- adding the (positive) value of Length.
2837 Index
:= Count_Type
'Base (No_Index
) + Length
; -- Last
2839 if Index
> Count_Type
'Base (Index_Type
'Last) then
2840 raise Constraint_Error
with "Length is out of range";
2843 -- We know that the computed value (having type Count_Type) of Last
2844 -- is within the range of the generic actual index subtype, so it is
2845 -- safe to convert to Index_Type:
2847 Last
:= Index_Type
'Base (Index
);
2850 -- Here Index_Type'First (and Index_Type'Last) is positive, so we
2851 -- must test the length indirectly (by working backwards from the
2852 -- largest possible value of Last), in order to prevent overflow.
2854 Index
:= Count_Type
'Base (Index_Type
'Last) - Length
; -- No_Index
2856 if Index
< Count_Type
'Base (No_Index
) then
2857 raise Constraint_Error
with "Length is out of range";
2860 -- We have determined that the value of Length would not create a
2861 -- Last index value outside of the range of Index_Type, so we can now
2862 -- safely compute its value.
2864 Last
:= Index_Type
'Base (Count_Type
'Base (No_Index
) + Length
);
2867 return V
: Vector
(Capacity
=> Length
) do
2873 (New_Item
: Element_Type
;
2874 Length
: Count_Type
) return Vector
2876 Index
: Count_Type
'Base;
2877 Last
: Index_Type
'Base;
2881 return Empty_Vector
;
2884 -- We create a vector object with a capacity that matches the specified
2885 -- Length, but we do not allow the vector capacity (the length of the
2886 -- internal array) to exceed the number of values in Index_Type'Range
2887 -- (otherwise, there would be no way to refer to those components via an
2888 -- index). We must therefore check whether the specified Length would
2889 -- create a Last index value greater than Index_Type'Last.
2891 if Index_Type
'Base'Last >= Count_Type'Pos (Count_Type'Last) then
2893 -- We perform a two-part test. First we determine whether the
2894 -- computed Last value lies in the base range of the type, and then
2895 -- determine whether it lies in the range of the index (sub)type.
2897 -- Last must satisfy this relation:
2898 -- First + Length - 1 <= Last
2899 -- We regroup terms:
2900 -- First - 1 <= Last - Length
2901 -- Which can rewrite as:
2902 -- No_Index <= Last - Length
2904 if Index_Type'Base'Last
- Index_Type
'Base (Length
) < No_Index
then
2905 raise Constraint_Error
with "Length is out of range";
2908 -- We now know that the computed value of Last is within the base
2909 -- range of the type, so it is safe to compute its value:
2911 Last
:= No_Index
+ Index_Type
'Base (Length
);
2913 -- Finally we test whether the value is within the range of the
2914 -- generic actual index subtype:
2916 if Last
> Index_Type
'Last then
2917 raise Constraint_Error
with "Length is out of range";
2920 elsif Index_Type
'First <= 0 then
2922 -- Here we can compute Last directly, in the normal way. We know that
2923 -- No_Index is less than 0, so there is no danger of overflow when
2924 -- adding the (positive) value of Length.
2926 Index
:= Count_Type
'Base (No_Index
) + Length
; -- same value as V.Last
2928 if Index
> Count_Type
'Base (Index_Type
'Last) then
2929 raise Constraint_Error
with "Length is out of range";
2932 -- We know that the computed value (having type Count_Type) of Last
2933 -- is within the range of the generic actual index subtype, so it is
2934 -- safe to convert to Index_Type:
2936 Last
:= Index_Type
'Base (Index
);
2939 -- Here Index_Type'First (and Index_Type'Last) is positive, so we
2940 -- must test the length indirectly (by working backwards from the
2941 -- largest possible value of Last), in order to prevent overflow.
2943 Index
:= Count_Type
'Base (Index_Type
'Last) - Length
; -- No_Index
2945 if Index
< Count_Type
'Base (No_Index
) then
2946 raise Constraint_Error
with "Length is out of range";
2949 -- We have determined that the value of Length would not create a
2950 -- Last index value outside of the range of Index_Type, so we can now
2951 -- safely compute its value.
2953 Last
:= Index_Type
'Base (Count_Type
'Base (No_Index
) + Length
);
2956 return V
: Vector
(Capacity
=> Length
) do
2957 V
.Elements
:= (others => New_Item
);
2962 --------------------
2963 -- Update_Element --
2964 --------------------
2966 procedure Update_Element
2967 (Container
: in out Vector
;
2969 Process
: not null access procedure (Element
: in out Element_Type
))
2971 B
: Natural renames Container
.Busy
;
2972 L
: Natural renames Container
.Lock
;
2975 if Index
> Container
.Last
then
2976 raise Constraint_Error
with "Index is out of range";
2983 Process
(Container
.Elements
(To_Array_Index
(Index
)));
2995 procedure Update_Element
2996 (Container
: in out Vector
;
2998 Process
: not null access procedure (Element
: in out Element_Type
))
3001 if Position
.Container
= null then
3002 raise Constraint_Error
with "Position cursor has no element";
3005 if Position
.Container
/= Container
'Unrestricted_Access then
3006 raise Program_Error
with "Position cursor denotes wrong container";
3009 Update_Element
(Container
, Position
.Index
, Process
);
3017 (Stream
: not null access Root_Stream_Type
'Class;
3023 N
:= Container
.Length
;
3024 Count_Type
'Base'Write (Stream, N);
3026 for J in 1 .. N loop
3027 Element_Type'Write (Stream, Container.Elements (J));
3032 (Stream : not null access Root_Stream_Type'Class;
3036 raise Program_Error with "attempt to stream vector cursor";
3040 (Stream : not null access Root_Stream_Type'Class;
3041 Item : Reference_Type)
3044 raise Program_Error with "attempt to stream reference";
3048 (Stream : not null access Root_Stream_Type'Class;
3049 Item : Constant_Reference_Type)
3052 raise Program_Error with "attempt to stream reference";
3055 end Ada.Containers.Bounded_Vectors;