]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/libgnat/a-coinve.adb
[Ada] Bump copyright year
[thirdparty/gcc.git] / gcc / ada / libgnat / a-coinve.adb
CommitLineData
4c2d6a70
AC
1------------------------------------------------------------------------------
2-- --
3-- GNAT LIBRARY COMPONENTS --
4-- --
8704d4b3 5-- A D A . C O N T A I N E R S . I N D E F I N I T E _ V E C T O R S --
4c2d6a70
AC
6-- --
7-- B o d y --
8-- --
4b490c1e 9-- Copyright (C) 2004-2020, Free Software Foundation, Inc. --
4c2d6a70 10-- --
4c2d6a70
AC
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- --
748086b7 13-- ware Foundation; either version 3, or (at your option) any later ver- --
4c2d6a70
AC
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 --
748086b7
JJ
16-- or FITNESS FOR A PARTICULAR PURPOSE. --
17-- --
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. --
21-- --
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/>. --
4c2d6a70 26-- --
3c25856a 27-- This unit was originally developed by Matthew J Heaney. --
4c2d6a70
AC
28------------------------------------------------------------------------------
29
30with Ada.Containers.Generic_Array_Sort;
31with Ada.Unchecked_Deallocation;
35fae080 32
ef992452 33with System; use type System.Address;
4c2d6a70
AC
34
35package body Ada.Containers.Indefinite_Vectors is
36
e9f97e79
AC
37 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
38 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
14f73211 39 -- See comment in Ada.Containers.Helpers
e9f97e79 40
4c2d6a70 41 procedure Free is
8704d4b3 42 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
4c2d6a70
AC
43
44 procedure Free is
8704d4b3 45 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
4c2d6a70 46
e9f97e79
AC
47 procedure Append_Slow_Path
48 (Container : in out Vector;
49 New_Item : Element_Type;
50 Count : Count_Type);
51 -- This is the slow path for Append. This is split out to minimize the size
52 -- of Append, because we have Inline (Append).
53
8704d4b3
MH
54 ---------
55 -- "&" --
56 ---------
4c2d6a70 57
e9f97e79
AC
58 -- We decide that the capacity of the result of "&" is the minimum needed
59 -- -- the sum of the lengths of the vector parameters. We could decide to
60 -- make it larger, but we have no basis for knowing how much larger, so we
61 -- just allocate the minimum amount of storage.
4c2d6a70 62
e9f97e79 63 function "&" (Left, Right : Vector) return Vector is
4c2d6a70 64 begin
e9f97e79
AC
65 return Result : Vector do
66 Reserve_Capacity (Result, Length (Left) + Length (Right));
67 Append (Result, Left);
68 Append (Result, Right);
69 end return;
8704d4b3 70 end "&";
4c2d6a70 71
e9f97e79 72 function "&" (Left : Vector; Right : Element_Type) return Vector is
8704d4b3 73 begin
e9f97e79
AC
74 return Result : Vector do
75 Reserve_Capacity (Result, Length (Left) + 1);
76 Append (Result, Left);
77 Append (Result, Right);
78 end return;
8704d4b3 79 end "&";
4c2d6a70 80
e9f97e79 81 function "&" (Left : Element_Type; Right : Vector) return Vector is
4c2d6a70 82 begin
e9f97e79
AC
83 return Result : Vector do
84 Reserve_Capacity (Result, 1 + Length (Right));
85 Append (Result, Left);
86 Append (Result, Right);
87 end return;
8704d4b3
MH
88 end "&";
89
90 function "&" (Left, Right : Element_Type) return Vector is
d43d5ef7 91 begin
e9f97e79
AC
92 return Result : Vector do
93 Reserve_Capacity (Result, 1 + 1);
94 Append (Result, Left);
95 Append (Result, Right);
96 end return;
8704d4b3
MH
97 end "&";
98
99 ---------
100 -- "=" --
101 ---------
102
fa969310 103 overriding function "=" (Left, Right : Vector) return Boolean is
8704d4b3 104 begin
4c2d6a70
AC
105 if Left.Last /= Right.Last then
106 return False;
107 end if;
108
a015ef67
AC
109 if Left.Length = 0 then
110 return True;
111 end if;
4c2d6a70 112
a015ef67
AC
113 declare
114 -- Per AI05-0022, the container implementation is required to detect
115 -- element tampering by a generic actual subprogram.
116
117 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
118 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
119 begin
120 for J in Index_Type range Index_Type'First .. Left.Last loop
121 if Left.Elements.EA (J) = null then
122 if Right.Elements.EA (J) /= null then
123 return False;
124 end if;
4c2d6a70 125
a015ef67
AC
126 elsif Right.Elements.EA (J) = null then
127 return False;
128
129 elsif Left.Elements.EA (J).all /= Right.Elements.EA (J).all then
130 return False;
131 end if;
132 end loop;
133 end;
4c2d6a70 134
e9f97e79 135 return True;
4c2d6a70
AC
136 end "=";
137
8704d4b3
MH
138 ------------
139 -- Adjust --
140 ------------
4c2d6a70 141
8704d4b3 142 procedure Adjust (Container : in out Vector) is
4c2d6a70 143 begin
a015ef67
AC
144 -- If the counts are nonzero, execution is technically erroneous, but
145 -- it seems friendly to allow things like concurrent "=" on shared
146 -- constants.
147
148 Zero_Counts (Container.TC);
149
d43d5ef7 150 if Container.Last = No_Index then
8704d4b3 151 Container.Elements := null;
4c2d6a70
AC
152 return;
153 end if;
154
155 declare
8704d4b3 156 L : constant Index_Type := Container.Last;
f97ccb3a
BD
157 E : Elements_Array renames
158 Container.Elements.EA (Index_Type'First .. L);
d43d5ef7 159
4c2d6a70 160 begin
8704d4b3
MH
161 Container.Elements := null;
162 Container.Last := No_Index;
4c2d6a70 163
f97ccb3a 164 Container.Elements := new Elements_Type (L);
4c2d6a70 165
2602b64e
AC
166 for J in E'Range loop
167 if E (J) /= null then
168 Container.Elements.EA (J) := new Element_Type'(E (J).all);
4c2d6a70
AC
169 end if;
170
2602b64e 171 Container.Last := J;
4c2d6a70 172 end loop;
4c2d6a70 173 end;
8704d4b3 174 end Adjust;
4c2d6a70 175
8704d4b3
MH
176 ------------
177 -- Append --
178 ------------
4c2d6a70 179
8704d4b3 180 procedure Append (Container : in out Vector; New_Item : Vector) is
4c2d6a70 181 begin
8704d4b3
MH
182 if Is_Empty (New_Item) then
183 return;
e9f97e79 184 elsif Checks and then Container.Last = Index_Type'Last then
dc6b9ba2 185 raise Constraint_Error with "vector is already at its maximum length";
2602b64e
AC
186 else
187 Insert (Container, Container.Last + 1, New_Item);
d43d5ef7 188 end if;
8704d4b3 189 end Append;
4c2d6a70 190
8704d4b3
MH
191 procedure Append
192 (Container : in out Vector;
193 New_Item : Element_Type;
194 Count : Count_Type := 1)
195 is
e9f97e79
AC
196 begin
197 -- In the general case, we pass the buck to Insert, but for efficiency,
198 -- we check for the usual case where Count = 1 and the vector has enough
199 -- room for at least one more element.
200
201 if Count = 1
202 and then Container.Elements /= null
203 and then Container.Last /= Container.Elements.Last
204 then
205 TC_Check (Container.TC);
206
207 -- Increment Container.Last after assigning the New_Item, so we
208 -- leave the Container unmodified in case Finalize/Adjust raises
209 -- an exception.
210
211 declare
212 New_Last : constant Index_Type := Container.Last + 1;
213
214 -- The element allocator may need an accessibility check in the
215 -- case actual type is class-wide or has access discriminants
216 -- (see RM 4.8(10.1) and AI12-0035).
217
218 pragma Unsuppress (Accessibility_Check);
219 begin
220 Container.Elements.EA (New_Last) := new Element_Type'(New_Item);
221 Container.Last := New_Last;
222 end;
223
224 else
225 Append_Slow_Path (Container, New_Item, Count);
226 end if;
227 end Append;
228
229 ----------------------
230 -- Append_Slow_Path --
231 ----------------------
232
233 procedure Append_Slow_Path
234 (Container : in out Vector;
235 New_Item : Element_Type;
236 Count : Count_Type)
237 is
4c2d6a70
AC
238 begin
239 if Count = 0 then
240 return;
e9f97e79 241 elsif Checks and then Container.Last = Index_Type'Last then
dc6b9ba2 242 raise Constraint_Error with "vector is already at its maximum length";
2602b64e
AC
243 else
244 Insert (Container, Container.Last + 1, New_Item, Count);
d43d5ef7 245 end if;
e9f97e79 246 end Append_Slow_Path;
4c2d6a70 247
a31945d7
AC
248 ------------
249 -- Assign --
250 ------------
251
252 procedure Assign (Target : in out Vector; Source : Vector) is
253 begin
254 if Target'Address = Source'Address then
255 return;
2602b64e
AC
256 else
257 Target.Clear;
258 Target.Append (Source);
a31945d7 259 end if;
a31945d7
AC
260 end Assign;
261
8704d4b3
MH
262 --------------
263 -- Capacity --
264 --------------
4c2d6a70 265
8704d4b3 266 function Capacity (Container : Vector) return Count_Type is
4c2d6a70 267 begin
8704d4b3
MH
268 if Container.Elements = null then
269 return 0;
2602b64e
AC
270 else
271 return Container.Elements.EA'Length;
8704d4b3 272 end if;
8704d4b3
MH
273 end Capacity;
274
275 -----------
276 -- Clear --
277 -----------
278
279 procedure Clear (Container : in out Vector) is
280 begin
e9f97e79 281 TC_Check (Container.TC);
4c2d6a70 282
e9f97e79
AC
283 while Container.Last >= Index_Type'First loop
284 declare
285 X : Element_Access := Container.Elements.EA (Container.Last);
286 begin
287 Container.Elements.EA (Container.Last) := null;
288 Container.Last := Container.Last - 1;
289 Free (X);
290 end;
291 end loop;
8704d4b3 292 end Clear;
4c2d6a70 293
0b5b2bbc
AC
294 ------------------------
295 -- Constant_Reference --
296 ------------------------
297
298 function Constant_Reference
c9423ca3 299 (Container : aliased Vector;
0b5b2bbc
AC
300 Position : Cursor) return Constant_Reference_Type
301 is
c9423ca3 302 begin
e9f97e79
AC
303 if Checks then
304 if Position.Container = null then
305 raise Constraint_Error with "Position cursor has no element";
306 end if;
0b5b2bbc 307
e9f97e79
AC
308 if Position.Container /= Container'Unrestricted_Access then
309 raise Program_Error with "Position cursor denotes wrong container";
310 end if;
c9423ca3 311
e9f97e79
AC
312 if Position.Index > Position.Container.Last then
313 raise Constraint_Error with "Position cursor is out of range";
314 end if;
c9423ca3
AC
315 end if;
316
14f73211
BD
317 declare
318 TC : constant Tamper_Counts_Access :=
319 Container.TC'Unrestricted_Access;
320 begin
321 -- The following will raise Constraint_Error if Element is null
322
794b9b72 323 return R : constant Constant_Reference_Type :=
e9f97e79 324 (Element => Container.Elements.EA (Position.Index),
14f73211
BD
325 Control => (Controlled with TC))
326 do
2f26abcc 327 Busy (TC.all);
14f73211
BD
328 end return;
329 end;
0b5b2bbc
AC
330 end Constant_Reference;
331
332 function Constant_Reference
c9423ca3
AC
333 (Container : aliased Vector;
334 Index : Index_Type) return Constant_Reference_Type
0b5b2bbc
AC
335 is
336 begin
e9f97e79 337 if Checks and then Index > Container.Last then
0b5b2bbc
AC
338 raise Constraint_Error with "Index is out of range";
339 end if;
340
14f73211
BD
341 declare
342 TC : constant Tamper_Counts_Access :=
343 Container.TC'Unrestricted_Access;
344 begin
345 -- The following will raise Constraint_Error if Element is null
346
794b9b72 347 return R : constant Constant_Reference_Type :=
e9f97e79 348 (Element => Container.Elements.EA (Index),
14f73211
BD
349 Control => (Controlled with TC))
350 do
2f26abcc 351 Busy (TC.all);
14f73211
BD
352 end return;
353 end;
0b5b2bbc
AC
354 end Constant_Reference;
355
8704d4b3
MH
356 --------------
357 -- Contains --
358 --------------
4c2d6a70 359
8704d4b3
MH
360 function Contains
361 (Container : Vector;
2368f04e
MH
362 Item : Element_Type) return Boolean
363 is
8704d4b3
MH
364 begin
365 return Find_Index (Container, Item) /= No_Index;
366 end Contains;
4c2d6a70 367
a31945d7
AC
368 ----------
369 -- Copy --
370 ----------
371
372 function Copy
373 (Source : Vector;
374 Capacity : Count_Type := 0) return Vector
375 is
376 C : Count_Type;
377
378 begin
06f6c43f
AC
379 if Capacity < Source.Length then
380 if Checks and then Capacity /= 0 then
381 raise Capacity_Error
382 with "Requested capacity is less than Source length";
383 end if;
a31945d7 384
06f6c43f
AC
385 C := Source.Length;
386 else
a31945d7 387 C := Capacity;
a31945d7
AC
388 end if;
389
390 return Target : Vector do
391 Target.Reserve_Capacity (C);
392 Target.Assign (Source);
393 end return;
394 end Copy;
395
8704d4b3
MH
396 ------------
397 -- Delete --
398 ------------
4c2d6a70 399
8704d4b3
MH
400 procedure Delete
401 (Container : in out Vector;
402 Index : Extended_Index;
403 Count : Count_Type := 1)
404 is
5bec9717
AC
405 Old_Last : constant Index_Type'Base := Container.Last;
406 New_Last : Index_Type'Base;
407 Count2 : Count_Type'Base; -- count of items from Index to Old_Last
408 J : Index_Type'Base; -- first index of items that slide down
409
8704d4b3 410 begin
5bec9717
AC
411 -- Delete removes items from the vector, the number of which is the
412 -- minimum of the specified Count and the items (if any) that exist from
413 -- Index to Container.Last. There are no constraints on the specified
414 -- value of Count (it can be larger than what's available at this
415 -- position in the vector, for example), but there are constraints on
416 -- the allowed values of the Index.
417
418 -- As a precondition on the generic actual Index_Type, the base type
419 -- must include Index_Type'Pred (Index_Type'First); this is the value
420 -- that Container.Last assumes when the vector is empty. However, we do
421 -- not allow that as the value for Index when specifying which items
422 -- should be deleted, so we must manually check. (That the user is
423 -- allowed to specify the value at all here is a consequence of the
424 -- declaration of the Extended_Index subtype, which includes the values
425 -- in the base range that immediately precede and immediately follow the
426 -- values in the Index_Type.)
427
e9f97e79 428 if Checks and then Index < Index_Type'First then
dc6b9ba2 429 raise Constraint_Error with "Index is out of range (too small)";
8704d4b3 430 end if;
4c2d6a70 431
5bec9717
AC
432 -- We do allow a value greater than Container.Last to be specified as
433 -- the Index, but only if it's immediately greater. This allows the
434 -- corner case of deleting no items from the back end of the vector to
435 -- be treated as a no-op. (It is assumed that specifying an index value
436 -- greater than Last + 1 indicates some deeper flaw in the caller's
437 -- algorithm, so that case is treated as a proper error.)
438
439 if Index > Old_Last then
e9f97e79 440 if Checks and then Index > Old_Last + 1 then
dc6b9ba2 441 raise Constraint_Error with "Index is out of range (too large)";
2602b64e
AC
442 else
443 return;
8704d4b3 444 end if;
8704d4b3 445 end if;
4c2d6a70 446
5bec9717
AC
447 -- Here and elsewhere we treat deleting 0 items from the container as a
448 -- no-op, even when the container is busy, so we simply return.
449
8704d4b3 450 if Count = 0 then
4c2d6a70 451 return;
8704d4b3 452 end if;
4c2d6a70 453
5bec9717
AC
454 -- The internal elements array isn't guaranteed to exist unless we have
455 -- elements, so we handle that case here in order to avoid having to
456 -- check it later. (Note that an empty vector can never be busy, so
457 -- there's no semantic harm in returning early.)
458
459 if Container.Is_Empty then
460 return;
461 end if;
462
463 -- The tampering bits exist to prevent an item from being deleted (or
464 -- otherwise harmfully manipulated) while it is being visited. Query,
465 -- Update, and Iterate increment the busy count on entry, and decrement
466 -- the count on exit. Delete checks the count to determine whether it is
467 -- being called while the associated callback procedure is executing.
468
e9f97e79 469 TC_Check (Container.TC);
4c2d6a70 470
5bec9717
AC
471 -- We first calculate what's available for deletion starting at
472 -- Index. Here and elsewhere we use the wider of Index_Type'Base and
473 -- Count_Type'Base as the type for intermediate values. (See function
474 -- Length for more information.)
475
476 if Count_Type'Base'Last >= Index_Type'Pos (Index_Type'Base'Last) then
477 Count2 := Count_Type'Base (Old_Last) - Count_Type'Base (Index) + 1;
5bec9717
AC
478 else
479 Count2 := Count_Type'Base (Old_Last - Index + 1);
480 end if;
4c2d6a70 481
5bec9717
AC
482 -- If the number of elements requested (Count) for deletion is equal to
483 -- (or greater than) the number of elements available (Count2) for
484 -- deletion beginning at Index, then everything from Index to
485 -- Container.Last is deleted (this is equivalent to Delete_Last).
4c2d6a70 486
5bec9717
AC
487 if Count >= Count2 then
488 -- Elements in an indefinite vector are allocated, so we must iterate
489 -- over the loop and deallocate elements one-at-a-time. We work from
490 -- back to front, deleting the last element during each pass, in
491 -- order to gracefully handle deallocation failures.
492
493 declare
494 EA : Elements_Array renames Container.Elements.EA;
495
496 begin
d43d5ef7
MH
497 while Container.Last >= Index loop
498 declare
499 K : constant Index_Type := Container.Last;
5bec9717 500 X : Element_Access := EA (K);
4c2d6a70 501
d43d5ef7 502 begin
5bec9717
AC
503 -- We first isolate the element we're deleting, removing it
504 -- from the vector before we attempt to deallocate it, in
505 -- case the deallocation fails.
506
507 EA (K) := null;
d43d5ef7 508 Container.Last := K - 1;
5bec9717
AC
509
510 -- Container invariants have been restored, so it is now
511 -- safe to attempt to deallocate the element.
512
d43d5ef7
MH
513 Free (X);
514 end;
515 end loop;
5bec9717 516 end;
4c2d6a70 517
5bec9717
AC
518 return;
519 end if;
520
521 -- There are some elements that aren't being deleted (the requested
522 -- count was less than the available count), so we must slide them down
523 -- to Index. We first calculate the index values of the respective array
524 -- slices, using the wider of Index_Type'Base and Count_Type'Base as the
525 -- type for intermediate calculations. For the elements that slide down,
526 -- index value New_Last is the last index value of their new home, and
527 -- index value J is the first index of their old home.
4c2d6a70 528
e9f97e79 529 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717
AC
530 New_Last := Old_Last - Index_Type'Base (Count);
531 J := Index + Index_Type'Base (Count);
5bec9717
AC
532 else
533 New_Last := Index_Type'Base (Count_Type'Base (Old_Last) - Count);
534 J := Index_Type'Base (Count_Type'Base (Index) + Count);
535 end if;
536
537 -- The internal elements array isn't guaranteed to exist unless we have
538 -- elements, but we have that guarantee here because we know we have
539 -- elements to slide. The array index values for each slice have
540 -- already been determined, so what remains to be done is to first
541 -- deallocate the elements that are being deleted, and then slide down
542 -- to Index the elements that aren't being deleted.
543
544 declare
545 EA : Elements_Array renames Container.Elements.EA;
546
547 begin
548 -- Before we can slide down the elements that aren't being deleted,
549 -- we need to deallocate the elements that are being deleted.
550
551 for K in Index .. J - 1 loop
552 declare
553 X : Element_Access := EA (K);
8704d4b3 554
8704d4b3 555 begin
5bec9717
AC
556 -- First we remove the element we're about to deallocate from
557 -- the vector, in case the deallocation fails, in order to
558 -- preserve representation invariants.
8704d4b3 559
5bec9717
AC
560 EA (K) := null;
561
562 -- The element has been removed from the vector, so it is now
563 -- safe to attempt to deallocate it.
564
565 Free (X);
d43d5ef7 566 end;
5bec9717
AC
567 end loop;
568
569 EA (Index .. New_Last) := EA (J .. Old_Last);
570 Container.Last := New_Last;
8704d4b3
MH
571 end;
572 end Delete;
4c2d6a70 573
8704d4b3
MH
574 procedure Delete
575 (Container : in out Vector;
576 Position : in out Cursor;
577 Count : Count_Type := 1)
578 is
579 begin
e9f97e79
AC
580 if Checks then
581 if Position.Container = null then
582 raise Constraint_Error with "Position cursor has no element";
dc6b9ba2 583
e9f97e79
AC
584 elsif Position.Container /= Container'Unrestricted_Access then
585 raise Program_Error with "Position cursor denotes wrong container";
4c2d6a70 586
e9f97e79
AC
587 elsif Position.Index > Container.Last then
588 raise Program_Error with "Position index is out of range";
589 end if;
2602b64e 590 end if;
e9f97e79
AC
591
592 Delete (Container, Position.Index, Count);
593 Position := No_Element;
8704d4b3 594 end Delete;
4c2d6a70 595
8704d4b3
MH
596 ------------------
597 -- Delete_First --
598 ------------------
4c2d6a70 599
8704d4b3
MH
600 procedure Delete_First
601 (Container : in out Vector;
602 Count : Count_Type := 1)
603 is
604 begin
605 if Count = 0 then
606 return;
4c2d6a70 607
2602b64e 608 elsif Count >= Length (Container) then
8704d4b3
MH
609 Clear (Container);
610 return;
4c2d6a70 611
2602b64e
AC
612 else
613 Delete (Container, Index_Type'First, Count);
614 end if;
8704d4b3 615 end Delete_First;
4c2d6a70 616
8704d4b3
MH
617 -----------------
618 -- Delete_Last --
619 -----------------
4c2d6a70 620
8704d4b3
MH
621 procedure Delete_Last
622 (Container : in out Vector;
623 Count : Count_Type := 1)
624 is
8704d4b3 625 begin
5bec9717
AC
626 -- It is not permitted to delete items while the container is busy (for
627 -- example, we're in the middle of a passive iteration). However, we
628 -- always treat deleting 0 items as a no-op, even when we're busy, so we
629 -- simply return without checking.
630
631 if Count = 0 then
632 return;
633 end if;
634
635 -- We cannot simply subsume the empty case into the loop below (the loop
636 -- would iterate 0 times), because we rename the internal array object
637 -- (which is allocated), but an empty vector isn't guaranteed to have
638 -- actually allocated an array. (Note that an empty vector can never be
639 -- busy, so there's no semantic harm in returning early here.)
640
641 if Container.Is_Empty then
8704d4b3
MH
642 return;
643 end if;
4c2d6a70 644
5bec9717
AC
645 -- The tampering bits exist to prevent an item from being deleted (or
646 -- otherwise harmfully manipulated) while it is being visited. Query,
647 -- Update, and Iterate increment the busy count on entry, and decrement
648 -- the count on exit. Delete_Last checks the count to determine whether
649 -- it is being called while the associated callback procedure is
650 -- executing.
651
e9f97e79 652 TC_Check (Container.TC);
4c2d6a70 653
5bec9717
AC
654 -- Elements in an indefinite vector are allocated, so we must iterate
655 -- over the loop and deallocate elements one-at-a-time. We work from
656 -- back to front, deleting the last element during each pass, in order
657 -- to gracefully handle deallocation failures.
658
d43d5ef7 659 declare
f97ccb3a 660 E : Elements_Array renames Container.Elements.EA;
4c2d6a70 661
d43d5ef7 662 begin
5bec9717 663 for Indx in 1 .. Count_Type'Min (Count, Container.Length) loop
d43d5ef7
MH
664 declare
665 J : constant Index_Type := Container.Last;
666 X : Element_Access := E (J);
667
668 begin
5bec9717
AC
669 -- Note that we first isolate the element we're deleting,
670 -- removing it from the vector, before we actually deallocate
671 -- it, in order to preserve representation invariants even if
672 -- the deallocation fails.
673
d43d5ef7
MH
674 E (J) := null;
675 Container.Last := J - 1;
5bec9717
AC
676
677 -- Container invariants have been restored, so it is now safe
678 -- to deallocate the element.
679
d43d5ef7
MH
680 Free (X);
681 end;
682 end loop;
683 end;
8704d4b3 684 end Delete_Last;
4c2d6a70 685
8704d4b3
MH
686 -------------
687 -- Element --
688 -------------
4c2d6a70 689
8704d4b3
MH
690 function Element
691 (Container : Vector;
692 Index : Index_Type) return Element_Type
693 is
8704d4b3 694 begin
e9f97e79 695 if Checks and then Index > Container.Last then
dc6b9ba2 696 raise Constraint_Error with "Index is out of range";
d43d5ef7
MH
697 end if;
698
2368f04e 699 declare
f97ccb3a 700 EA : constant Element_Access := Container.Elements.EA (Index);
2368f04e 701 begin
e9f97e79 702 if Checks and then EA = null then
dc6b9ba2 703 raise Constraint_Error with "element is empty";
2602b64e
AC
704 else
705 return EA.all;
2368f04e 706 end if;
2368f04e 707 end;
8704d4b3 708 end Element;
4c2d6a70 709
8704d4b3
MH
710 function Element (Position : Cursor) return Element_Type is
711 begin
e9f97e79
AC
712 if Checks then
713 if Position.Container = null then
714 raise Constraint_Error with "Position cursor has no element";
715 end if;
d43d5ef7 716
e9f97e79
AC
717 if Position.Index > Position.Container.Last then
718 raise Constraint_Error with "Position cursor is out of range";
719 end if;
f97ccb3a
BD
720 end if;
721
722 declare
723 EA : constant Element_Access :=
2602b64e 724 Position.Container.Elements.EA (Position.Index);
f97ccb3a 725 begin
e9f97e79 726 if Checks and then EA = null then
f97ccb3a 727 raise Constraint_Error with "element is empty";
2602b64e
AC
728 else
729 return EA.all;
f97ccb3a 730 end if;
f97ccb3a 731 end;
8704d4b3 732 end Element;
4c2d6a70 733
8704d4b3
MH
734 --------------
735 -- Finalize --
736 --------------
4c2d6a70 737
8704d4b3
MH
738 procedure Finalize (Container : in out Vector) is
739 begin
dc6b9ba2 740 Clear (Container); -- Checks busy-bit
4c2d6a70
AC
741
742 declare
743 X : Elements_Access := Container.Elements;
744 begin
8704d4b3 745 Container.Elements := null;
4c2d6a70
AC
746 Free (X);
747 end;
8704d4b3 748 end Finalize;
4c2d6a70 749
ef992452
AC
750 procedure Finalize (Object : in out Iterator) is
751 begin
e9f97e79 752 Unbusy (Object.Container.TC);
794b9b72
AC
753 end Finalize;
754
8704d4b3
MH
755 ----------
756 -- Find --
757 ----------
4c2d6a70 758
8704d4b3
MH
759 function Find
760 (Container : Vector;
761 Item : Element_Type;
2368f04e
MH
762 Position : Cursor := No_Element) return Cursor
763 is
8704d4b3 764 begin
e9f97e79 765 if Checks and then Position.Container /= null then
dc6b9ba2
MH
766 if Position.Container /= Container'Unrestricted_Access then
767 raise Program_Error with "Position cursor denotes wrong container";
768 end if;
769
770 if Position.Index > Container.Last then
771 raise Program_Error with "Position index is out of range";
772 end if;
8704d4b3 773 end if;
4c2d6a70 774
2602b64e
AC
775 -- Per AI05-0022, the container implementation is required to detect
776 -- element tampering by a generic actual subprogram.
777
778 declare
e9f97e79 779 Lock : With_Lock (Container.TC'Unrestricted_Access);
2602b64e 780 begin
2602b64e 781 for J in Position.Index .. Container.Last loop
e9f97e79
AC
782 if Container.Elements.EA (J).all = Item then
783 return Cursor'(Container'Unrestricted_Access, J);
2602b64e
AC
784 end if;
785 end loop;
786
e9f97e79 787 return No_Element;
2602b64e 788 end;
8704d4b3 789 end Find;
4c2d6a70 790
8704d4b3
MH
791 ----------------
792 -- Find_Index --
793 ----------------
4c2d6a70 794
8704d4b3
MH
795 function Find_Index
796 (Container : Vector;
797 Item : Element_Type;
2368f04e
MH
798 Index : Index_Type := Index_Type'First) return Extended_Index
799 is
2602b64e
AC
800 -- Per AI05-0022, the container implementation is required to detect
801 -- element tampering by a generic actual subprogram.
802
e9f97e79
AC
803 Lock : With_Lock (Container.TC'Unrestricted_Access);
804 begin
8704d4b3 805 for Indx in Index .. Container.Last loop
e9f97e79
AC
806 if Container.Elements.EA (Indx).all = Item then
807 return Indx;
8704d4b3
MH
808 end if;
809 end loop;
810
e9f97e79 811 return No_Index;
8704d4b3 812 end Find_Index;
4c2d6a70 813
8704d4b3
MH
814 -----------
815 -- First --
816 -----------
4c2d6a70 817
8704d4b3
MH
818 function First (Container : Vector) return Cursor is
819 begin
820 if Is_Empty (Container) then
821 return No_Element;
822 end if;
4c2d6a70 823
ef992452 824 return (Container'Unrestricted_Access, Index_Type'First);
8704d4b3 825 end First;
4c2d6a70 826
3e24afaa 827 function First (Object : Iterator) return Cursor is
3e24afaa 828 begin
e8bd500e
AC
829 -- The value of the iterator object's Index component influences the
830 -- behavior of the First (and Last) selector function.
831
fe58fea7
AC
832 -- When the Index component is No_Index, this means the iterator
833 -- object was constructed without a start expression, in which case the
e8bd500e
AC
834 -- (forward) iteration starts from the (logical) beginning of the entire
835 -- sequence of items (corresponding to Container.First, for a forward
836 -- iterator).
837
fe58fea7
AC
838 -- Otherwise, this is iteration over a partial sequence of items.
839 -- When the Index component isn't No_Index, the iterator object was
840 -- constructed with a start expression, that specifies the position
841 -- from which the (forward) partial iteration begins.
e8bd500e
AC
842
843 if Object.Index = No_Index then
844 return First (Object.Container.all);
845 else
846 return Cursor'(Object.Container, Object.Index);
847 end if;
3e24afaa
AC
848 end First;
849
8704d4b3
MH
850 -------------------
851 -- First_Element --
852 -------------------
4c2d6a70 853
8704d4b3 854 function First_Element (Container : Vector) return Element_Type is
4c2d6a70 855 begin
e9f97e79 856 if Checks and then Container.Last = No_Index then
f97ccb3a
BD
857 raise Constraint_Error with "Container is empty";
858 end if;
859
860 declare
861 EA : constant Element_Access :=
2602b64e 862 Container.Elements.EA (Index_Type'First);
f97ccb3a 863 begin
e9f97e79 864 if Checks and then EA = null then
f97ccb3a 865 raise Constraint_Error with "first element is empty";
2602b64e
AC
866 else
867 return EA.all;
f97ccb3a 868 end if;
f97ccb3a 869 end;
8704d4b3 870 end First_Element;
4c2d6a70 871
8704d4b3
MH
872 -----------------
873 -- First_Index --
874 -----------------
4c2d6a70 875
8704d4b3
MH
876 function First_Index (Container : Vector) return Index_Type is
877 pragma Unreferenced (Container);
878 begin
879 return Index_Type'First;
880 end First_Index;
4c2d6a70 881
8704d4b3
MH
882 ---------------------
883 -- Generic_Sorting --
884 ---------------------
4c2d6a70 885
8704d4b3 886 package body Generic_Sorting is
4c2d6a70 887
8704d4b3
MH
888 -----------------------
889 -- Local Subprograms --
890 -----------------------
4c2d6a70 891
8704d4b3
MH
892 function Is_Less (L, R : Element_Access) return Boolean;
893 pragma Inline (Is_Less);
4c2d6a70 894
8704d4b3
MH
895 -------------
896 -- Is_Less --
897 -------------
4c2d6a70 898
8704d4b3
MH
899 function Is_Less (L, R : Element_Access) return Boolean is
900 begin
901 if L = null then
902 return R /= null;
903 elsif R = null then
904 return False;
905 else
906 return L.all < R.all;
907 end if;
908 end Is_Less;
4c2d6a70 909
8704d4b3
MH
910 ---------------
911 -- Is_Sorted --
912 ---------------
4c2d6a70 913
8704d4b3
MH
914 function Is_Sorted (Container : Vector) return Boolean is
915 begin
916 if Container.Last <= Index_Type'First then
917 return True;
918 end if;
4c2d6a70 919
2602b64e
AC
920 -- Per AI05-0022, the container implementation is required to detect
921 -- element tampering by a generic actual subprogram.
922
4c2d6a70 923 declare
e9f97e79 924 Lock : With_Lock (Container.TC'Unrestricted_Access);
f97ccb3a 925 E : Elements_Array renames Container.Elements.EA;
4c2d6a70 926 begin
e9f97e79
AC
927 for J in Index_Type'First .. Container.Last - 1 loop
928 if Is_Less (E (J + 1), E (J)) then
929 return False;
8704d4b3
MH
930 end if;
931 end loop;
4c2d6a70 932
e9f97e79 933 return True;
2602b64e 934 end;
8704d4b3 935 end Is_Sorted;
4c2d6a70 936
8704d4b3
MH
937 -----------
938 -- Merge --
939 -----------
4c2d6a70 940
8704d4b3 941 procedure Merge (Target, Source : in out Vector) is
f97ccb3a 942 I, J : Index_Type'Base;
4c2d6a70 943
8704d4b3 944 begin
4c9fe6c7
AC
945 -- The semantics of Merge changed slightly per AI05-0021. It was
946 -- originally the case that if Target and Source denoted the same
947 -- container object, then the GNAT implementation of Merge did
948 -- nothing. However, it was argued that RM05 did not precisely
949 -- specify the semantics for this corner case. The decision of the
950 -- ARG was that if Target and Source denote the same non-empty
951 -- container object, then Program_Error is raised.
952
953 if Source.Last < Index_Type'First then -- Source is empty
8704d4b3
MH
954 return;
955 end if;
4c2d6a70 956
e9f97e79 957 if Checks and then Target'Address = Source'Address then
4c9fe6c7
AC
958 raise Program_Error with
959 "Target and Source denote same non-empty container";
8704d4b3 960 end if;
4c2d6a70 961
4c9fe6c7
AC
962 if Target.Last < Index_Type'First then -- Target is empty
963 Move (Target => Target, Source => Source);
8704d4b3
MH
964 return;
965 end if;
4c2d6a70 966
e9f97e79 967 TC_Check (Source.TC);
4c2d6a70 968
f97ccb3a 969 I := Target.Last; -- original value (before Set_Length)
8704d4b3 970 Target.Set_Length (Length (Target) + Length (Source));
4c2d6a70 971
2602b64e
AC
972 -- Per AI05-0022, the container implementation is required to detect
973 -- element tampering by a generic actual subprogram.
974
975 declare
976 TA : Elements_Array renames Target.Elements.EA;
977 SA : Elements_Array renames Source.Elements.EA;
978
e9f97e79
AC
979 Lock_Target : With_Lock (Target.TC'Unchecked_Access);
980 Lock_Source : With_Lock (Source.TC'Unchecked_Access);
2602b64e 981 begin
2602b64e
AC
982 J := Target.Last; -- new value (after Set_Length)
983 while Source.Last >= Index_Type'First loop
984 pragma Assert
985 (Source.Last <= Index_Type'First
986 or else not (Is_Less (SA (Source.Last),
987 SA (Source.Last - 1))));
988
989 if I < Index_Type'First then
990 declare
991 Src : Elements_Array renames
992 SA (Index_Type'First .. Source.Last);
993 begin
994 TA (Index_Type'First .. J) := Src;
995 Src := (others => null);
996 end;
997
998 Source.Last := No_Index;
999 exit;
1000 end if;
1001
1002 pragma Assert
1003 (I <= Index_Type'First
1004 or else not (Is_Less (TA (I), TA (I - 1))));
7cdc672b 1005
8704d4b3 1006 declare
2602b64e
AC
1007 Src : Element_Access renames SA (Source.Last);
1008 Tgt : Element_Access renames TA (I);
4c2d6a70 1009
8704d4b3 1010 begin
2602b64e
AC
1011 if Is_Less (Src, Tgt) then
1012 Target.Elements.EA (J) := Tgt;
1013 Tgt := null;
1014 I := I - 1;
1015
1016 else
1017 Target.Elements.EA (J) := Src;
1018 Src := null;
1019 Source.Last := Source.Last - 1;
1020 end if;
8704d4b3 1021 end;
4c2d6a70 1022
2602b64e
AC
1023 J := J - 1;
1024 end loop;
2602b64e 1025 end;
8704d4b3 1026 end Merge;
4c2d6a70 1027
8704d4b3
MH
1028 ----------
1029 -- Sort --
1030 ----------
4c2d6a70 1031
3c25856a 1032 procedure Sort (Container : in out Vector) is
3c25856a
AC
1033 procedure Sort is new Generic_Array_Sort
1034 (Index_Type => Index_Type,
1035 Element_Type => Element_Access,
1036 Array_Type => Elements_Array,
1037 "<" => Is_Less);
4c2d6a70 1038
794b9b72
AC
1039 -- Start of processing for Sort
1040
4c2d6a70 1041 begin
8704d4b3
MH
1042 if Container.Last <= Index_Type'First then
1043 return;
1044 end if;
4c2d6a70 1045
b727a82b
AC
1046 -- The exception behavior for the vector container must match that
1047 -- for the list container, so we check for cursor tampering here
1048 -- (which will catch more things) instead of for element tampering
1049 -- (which will catch fewer things). It's true that the elements of
1050 -- this vector container could be safely moved around while (say) an
1051 -- iteration is taking place (iteration only increments the busy
1052 -- counter), and so technically all we would need here is a test for
1053 -- element tampering (indicated by the lock counter), that's simply
1054 -- an artifact of our array-based implementation. Logically Sort
1055 -- requires a check for cursor tampering.
1056
e9f97e79 1057 TC_Check (Container.TC);
4c2d6a70 1058
2602b64e
AC
1059 -- Per AI05-0022, the container implementation is required to detect
1060 -- element tampering by a generic actual subprogram.
1061
1062 declare
e9f97e79 1063 Lock : With_Lock (Container.TC'Unchecked_Access);
2602b64e 1064 begin
2602b64e 1065 Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
2602b64e 1066 end;
8704d4b3 1067 end Sort;
4c2d6a70 1068
8704d4b3 1069 end Generic_Sorting;
4c2d6a70 1070
e9f97e79
AC
1071 ------------------------
1072 -- Get_Element_Access --
1073 ------------------------
1074
1075 function Get_Element_Access
72d5c70b
AC
1076 (Position : Cursor) return not null Element_Access
1077 is
1078 Ptr : constant Element_Access :=
1079 Position.Container.Elements.EA (Position.Index);
1080
e9f97e79 1081 begin
72d5c70b
AC
1082 -- An indefinite vector may contain spaces that hold no elements.
1083 -- Any iteration over an indefinite vector with spaces will raise
1084 -- Constraint_Error.
1085
1086 if Ptr = null then
1087 raise Constraint_Error;
1088
1089 else
1090 return Ptr;
1091 end if;
e9f97e79
AC
1092 end Get_Element_Access;
1093
8704d4b3
MH
1094 -----------------
1095 -- Has_Element --
1096 -----------------
4c2d6a70 1097
8704d4b3 1098 function Has_Element (Position : Cursor) return Boolean is
4c2d6a70 1099 begin
8704d4b3
MH
1100 if Position.Container = null then
1101 return False;
2602b64e
AC
1102 else
1103 return Position.Index <= Position.Container.Last;
4c2d6a70 1104 end if;
8704d4b3 1105 end Has_Element;
4c2d6a70 1106
8704d4b3
MH
1107 ------------
1108 -- Insert --
1109 ------------
4c2d6a70 1110
8704d4b3
MH
1111 procedure Insert
1112 (Container : in out Vector;
1113 Before : Extended_Index;
1114 New_Item : Element_Type;
1115 Count : Count_Type := 1)
1116 is
5bec9717 1117 Old_Length : constant Count_Type := Container.Length;
4c2d6a70 1118
5bec9717
AC
1119 Max_Length : Count_Type'Base; -- determined from range of Index_Type
1120 New_Length : Count_Type'Base; -- sum of current length and Count
1121 New_Last : Index_Type'Base; -- last index of vector after insertion
4c2d6a70 1122
5bec9717
AC
1123 Index : Index_Type'Base; -- scratch for intermediate values
1124 J : Count_Type'Base; -- scratch
1125
1126 New_Capacity : Count_Type'Base; -- length of new, expanded array
1127 Dst_Last : Index_Type'Base; -- last index of new, expanded array
1128 Dst : Elements_Access; -- new, expanded internal array
4c2d6a70
AC
1129
1130 begin
e9f97e79
AC
1131 if Checks then
1132 -- As a precondition on the generic actual Index_Type, the base type
1133 -- must include Index_Type'Pred (Index_Type'First); this is the value
1134 -- that Container.Last assumes when the vector is empty. However, we
1135 -- do not allow that as the value for Index when specifying where the
1136 -- new items should be inserted, so we must manually check. (That the
1137 -- user is allowed to specify the value at all here is a consequence
1138 -- of the declaration of the Extended_Index subtype, which includes
1139 -- the values in the base range that immediately precede and
1140 -- immediately follow the values in the Index_Type.)
5bec9717 1141
e9f97e79
AC
1142 if Before < Index_Type'First then
1143 raise Constraint_Error with
1144 "Before index is out of range (too small)";
1145 end if;
8704d4b3 1146
e9f97e79
AC
1147 -- We do allow a value greater than Container.Last to be specified as
1148 -- the Index, but only if it's immediately greater. This allows for
1149 -- the case of appending items to the back end of the vector. (It is
1150 -- assumed that specifying an index value greater than Last + 1
1151 -- indicates some deeper flaw in the caller's algorithm, so that case
1152 -- is treated as a proper error.)
1153
1154 if Before > Container.Last + 1 then
1155 raise Constraint_Error with
1156 "Before index is out of range (too large)";
1157 end if;
8704d4b3 1158 end if;
4c2d6a70 1159
5bec9717
AC
1160 -- We treat inserting 0 items into the container as a no-op, even when
1161 -- the container is busy, so we simply return.
1162
4c2d6a70
AC
1163 if Count = 0 then
1164 return;
1165 end if;
1166
5bec9717
AC
1167 -- There are two constraints we need to satisfy. The first constraint is
1168 -- that a container cannot have more than Count_Type'Last elements, so
0b5b2bbc 1169 -- we must check the sum of the current length and the insertion count.
e9f97e79
AC
1170 -- Note: we cannot simply add these values, because of the possibility
1171 -- of overflow.
8704d4b3 1172
e9f97e79 1173 if Checks and then Old_Length > Count_Type'Last - Count then
5bec9717
AC
1174 raise Constraint_Error with "Count is out of range";
1175 end if;
dc6b9ba2 1176
5bec9717
AC
1177 -- It is now safe compute the length of the new vector, without fear of
1178 -- overflow.
d43d5ef7 1179
5bec9717
AC
1180 New_Length := Old_Length + Count;
1181
1182 -- The second constraint is that the new Last index value cannot exceed
1183 -- Index_Type'Last. In each branch below, we calculate the maximum
1184 -- length (computed from the range of values in Index_Type), and then
1185 -- compare the new length to the maximum length. If the new length is
1186 -- acceptable, then we compute the new last index from that.
1187
e9f97e79 1188 if Index_Type'Base'Last >= Count_Type_Last then
0b5b2bbc 1189
5bec9717
AC
1190 -- We have to handle the case when there might be more values in the
1191 -- range of Index_Type than in the range of Count_Type.
1192
1193 if Index_Type'First <= 0 then
0b5b2bbc 1194
5bec9717
AC
1195 -- We know that No_Index (the same as Index_Type'First - 1) is
1196 -- less than 0, so it is safe to compute the following sum without
1197 -- fear of overflow.
1198
1199 Index := No_Index + Index_Type'Base (Count_Type'Last);
1200
1201 if Index <= Index_Type'Last then
0b5b2bbc 1202
5bec9717
AC
1203 -- We have determined that range of Index_Type has at least as
1204 -- many values as in Count_Type, so Count_Type'Last is the
1205 -- maximum number of items that are allowed.
1206
1207 Max_Length := Count_Type'Last;
1208
1209 else
1210 -- The range of Index_Type has fewer values than in Count_Type,
1211 -- so the maximum number of items is computed from the range of
1212 -- the Index_Type.
1213
1214 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1215 end if;
1216
1217 else
1218 -- No_Index is equal or greater than 0, so we can safely compute
1219 -- the difference without fear of overflow (which we would have to
1220 -- worry about if No_Index were less than 0, but that case is
1221 -- handled above).
1222
e9f97e79 1223 if Index_Type'Last - No_Index >= Count_Type_Last then
7b56a91b
AC
1224 -- We have determined that range of Index_Type has at least as
1225 -- many values as in Count_Type, so Count_Type'Last is the
1226 -- maximum number of items that are allowed.
1227
1228 Max_Length := Count_Type'Last;
1229
1230 else
1231 -- The range of Index_Type has fewer values than in Count_Type,
1232 -- so the maximum number of items is computed from the range of
1233 -- the Index_Type.
1234
1235 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1236 end if;
dc6b9ba2
MH
1237 end if;
1238
5bec9717 1239 elsif Index_Type'First <= 0 then
0b5b2bbc 1240
5bec9717
AC
1241 -- We know that No_Index (the same as Index_Type'First - 1) is less
1242 -- than 0, so it is safe to compute the following sum without fear of
1243 -- overflow.
dc6b9ba2 1244
5bec9717
AC
1245 J := Count_Type'Base (No_Index) + Count_Type'Last;
1246
1247 if J <= Count_Type'Base (Index_Type'Last) then
0b5b2bbc 1248
5bec9717
AC
1249 -- We have determined that range of Index_Type has at least as
1250 -- many values as in Count_Type, so Count_Type'Last is the maximum
1251 -- number of items that are allowed.
1252
1253 Max_Length := Count_Type'Last;
1254
1255 else
1256 -- The range of Index_Type has fewer values than Count_Type does,
1257 -- so the maximum number of items is computed from the range of
1258 -- the Index_Type.
1259
1260 Max_Length :=
1261 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
d43d5ef7
MH
1262 end if;
1263
5bec9717
AC
1264 else
1265 -- No_Index is equal or greater than 0, so we can safely compute the
1266 -- difference without fear of overflow (which we would have to worry
1267 -- about if No_Index were less than 0, but that case is handled
1268 -- above).
8704d4b3 1269
5bec9717
AC
1270 Max_Length :=
1271 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
1272 end if;
1273
1274 -- We have just computed the maximum length (number of items). We must
1275 -- now compare the requested length to the maximum length, as we do not
1276 -- allow a vector expand beyond the maximum (because that would create
1277 -- an internal array with a last index value greater than
1278 -- Index_Type'Last, with no way to index those elements).
1279
e9f97e79 1280 if Checks and then New_Length > Max_Length then
5bec9717
AC
1281 raise Constraint_Error with "Count is out of range";
1282 end if;
1283
1284 -- New_Last is the last index value of the items in the container after
1285 -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to
1286 -- compute its value from the New_Length.
1287
e9f97e79 1288 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 1289 New_Last := No_Index + Index_Type'Base (New_Length);
5bec9717
AC
1290 else
1291 New_Last := Index_Type'Base (Count_Type'Base (No_Index) + New_Length);
4c2d6a70
AC
1292 end if;
1293
8704d4b3 1294 if Container.Elements = null then
5bec9717
AC
1295 pragma Assert (Container.Last = No_Index);
1296
1297 -- This is the simplest case, with which we must always begin: we're
1298 -- inserting items into an empty vector that hasn't allocated an
1299 -- internal array yet. Note that we don't need to check the busy bit
1300 -- here, because an empty container cannot be busy.
1301
1302 -- In an indefinite vector, elements are allocated individually, and
1303 -- stored as access values on the internal array (the length of which
1304 -- represents the vector "capacity"), which is separately allocated.
1305
f97ccb3a 1306 Container.Elements := new Elements_Type (New_Last);
d43d5ef7 1307
5bec9717
AC
1308 -- The element backbone has been successfully allocated, so now we
1309 -- allocate the elements.
1310
1311 for Idx in Container.Elements.EA'Range loop
0b5b2bbc 1312
5bec9717
AC
1313 -- In order to preserve container invariants, we always attempt
1314 -- the element allocation first, before setting the Last index
1315 -- value, in case the allocation fails (either because there is no
1316 -- storage available, or because element initialization fails).
1317
50878404 1318 declare
50878404
AC
1319 -- The element allocator may need an accessibility check in the
1320 -- case actual type is class-wide or has access discriminants
1321 -- (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
1322
1323 pragma Unsuppress (Accessibility_Check);
1324
50878404
AC
1325 begin
1326 Container.Elements.EA (Idx) := new Element_Type'(New_Item);
1327 end;
5bec9717
AC
1328
1329 -- The allocation of the element succeeded, so it is now safe to
1330 -- update the Last index, restoring container invariants.
1331
1332 Container.Last := Idx;
d43d5ef7 1333 end loop;
4c2d6a70 1334
8704d4b3
MH
1335 return;
1336 end if;
1337
5bec9717
AC
1338 -- The tampering bits exist to prevent an item from being harmfully
1339 -- manipulated while it is being visited. Query, Update, and Iterate
1340 -- increment the busy count on entry, and decrement the count on
1341 -- exit. Insert checks the count to determine whether it is being called
1342 -- while the associated callback procedure is executing.
1343
e9f97e79 1344 TC_Check (Container.TC);
5bec9717
AC
1345
1346 if New_Length <= Container.Elements.EA'Length then
0b5b2bbc 1347
5bec9717
AC
1348 -- In this case, we're inserting elements into a vector that has
1349 -- already allocated an internal array, and the existing array has
1350 -- enough unused storage for the new items.
1351
8704d4b3 1352 declare
f97ccb3a 1353 E : Elements_Array renames Container.Elements.EA;
5bec9717 1354 K : Index_Type'Base;
dc6b9ba2 1355
8704d4b3 1356 begin
5bec9717 1357 if Before > Container.Last then
0b5b2bbc 1358
5bec9717
AC
1359 -- The new items are being appended to the vector, so no
1360 -- sliding of existing elements is required.
d43d5ef7 1361
5bec9717 1362 for Idx in Before .. New_Last loop
0b5b2bbc 1363
5bec9717
AC
1364 -- In order to preserve container invariants, we always
1365 -- attempt the element allocation first, before setting the
1366 -- Last index value, in case the allocation fails (either
1367 -- because there is no storage available, or because element
1368 -- initialization fails).
d43d5ef7 1369
50878404 1370 declare
50878404
AC
1371 -- The element allocator may need an accessibility check
1372 -- in case the actual type is class-wide or has access
1373 -- discriminants (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
1374
1375 pragma Unsuppress (Accessibility_Check);
1376
50878404
AC
1377 begin
1378 E (Idx) := new Element_Type'(New_Item);
1379 end;
5bec9717
AC
1380
1381 -- The allocation of the element succeeded, so it is now
1382 -- safe to update the Last index, restoring container
1383 -- invariants.
1384
1385 Container.Last := Idx;
1386 end loop;
1387
1388 else
1389 -- The new items are being inserted before some existing
1390 -- elements, so we must slide the existing elements up to their
1391 -- new home. We use the wider of Index_Type'Base and
1392 -- Count_Type'Base as the type for intermediate index values.
8704d4b3 1393
e9f97e79 1394 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 1395 Index := Before + Index_Type'Base (Count);
5bec9717
AC
1396 else
1397 Index := Index_Type'Base (Count_Type'Base (Before) + Count);
1398 end if;
1399
1400 -- The new items are being inserted in the middle of the array,
1401 -- in the range [Before, Index). Copy the existing elements to
1402 -- the end of the array, to make room for the new items.
1403
1404 E (Index .. New_Last) := E (Before .. Container.Last);
1405 Container.Last := New_Last;
1406
1407 -- We have copied the existing items up to the end of the
1408 -- array, to make room for the new items in the middle of
1409 -- the array. Now we actually allocate the new items.
1410
1411 -- Note: initialize K outside loop to make it clear that
1412 -- K always has a value if the exception handler triggers.
1413
1414 K := Before;
29ba9f52 1415
50878404 1416 declare
50878404
AC
1417 -- The element allocator may need an accessibility check in
1418 -- the case the actual type is class-wide or has access
1419 -- discriminants (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
1420
1421 pragma Unsuppress (Accessibility_Check);
1422
8704d4b3 1423 begin
5bec9717
AC
1424 while K < Index loop
1425 E (K) := new Element_Type'(New_Item);
1426 K := K + 1;
1427 end loop;
3acdda2d 1428
5bec9717
AC
1429 exception
1430 when others =>
3acdda2d 1431
5bec9717
AC
1432 -- Values in the range [Before, K) were successfully
1433 -- allocated, but values in the range [K, Index) are
1434 -- stale (these array positions contain copies of the
1435 -- old items, that did not get assigned a new item,
1436 -- because the allocation failed). We must finish what
1437 -- we started by clearing out all of the stale values,
1438 -- leaving a "hole" in the middle of the array.
3acdda2d 1439
5bec9717
AC
1440 E (K .. Index - 1) := (others => null);
1441 raise;
8704d4b3 1442 end;
d43d5ef7 1443 end if;
8704d4b3 1444 end;
4c2d6a70 1445
4c2d6a70
AC
1446 return;
1447 end if;
1448
5bec9717
AC
1449 -- In this case, we're inserting elements into a vector that has already
1450 -- allocated an internal array, but the existing array does not have
1451 -- enough storage, so we must allocate a new, longer array. In order to
1452 -- guarantee that the amortized insertion cost is O(1), we always
1453 -- allocate an array whose length is some power-of-two factor of the
1454 -- current array length. (The new array cannot have a length less than
1455 -- the New_Length of the container, but its last index value cannot be
1456 -- greater than Index_Type'Last.)
1457
1458 New_Capacity := Count_Type'Max (1, Container.Elements.EA'Length);
1459 while New_Capacity < New_Length loop
1460 if New_Capacity > Count_Type'Last / 2 then
1461 New_Capacity := Count_Type'Last;
1462 exit;
1463 end if;
3acdda2d 1464
5bec9717
AC
1465 New_Capacity := 2 * New_Capacity;
1466 end loop;
4c2d6a70 1467
5bec9717 1468 if New_Capacity > Max_Length then
0b5b2bbc 1469
5bec9717
AC
1470 -- We have reached the limit of capacity, so no further expansion
1471 -- will occur. (This is not a problem, as there is never a need to
1472 -- have more capacity than the maximum container length.)
4c2d6a70 1473
5bec9717
AC
1474 New_Capacity := Max_Length;
1475 end if;
4c2d6a70 1476
5bec9717
AC
1477 -- We have computed the length of the new internal array (and this is
1478 -- what "vector capacity" means), so use that to compute its last index.
4c2d6a70 1479
e9f97e79 1480 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 1481 Dst_Last := No_Index + Index_Type'Base (New_Capacity);
5bec9717
AC
1482 else
1483 Dst_Last :=
1484 Index_Type'Base (Count_Type'Base (No_Index) + New_Capacity);
1485 end if;
4c2d6a70 1486
5bec9717
AC
1487 -- Now we allocate the new, longer internal array. If the allocation
1488 -- fails, we have not changed any container state, so no side-effect
1489 -- will occur as a result of propagating the exception.
dc6b9ba2 1490
5bec9717 1491 Dst := new Elements_Type (Dst_Last);
4c2d6a70 1492
5bec9717
AC
1493 -- We have our new internal array. All that needs to be done now is to
1494 -- copy the existing items (if any) from the old array (the "source"
1495 -- array) to the new array (the "destination" array), and then
1496 -- deallocate the old array.
4c2d6a70 1497
5bec9717
AC
1498 declare
1499 Src : Elements_Access := Container.Elements;
4c2d6a70 1500
5bec9717
AC
1501 begin
1502 Dst.EA (Index_Type'First .. Before - 1) :=
1503 Src.EA (Index_Type'First .. Before - 1);
4c2d6a70 1504
5bec9717 1505 if Before > Container.Last then
0b5b2bbc 1506
5bec9717
AC
1507 -- The new items are being appended to the vector, so no
1508 -- sliding of existing elements is required.
4c2d6a70 1509
2602b64e
AC
1510 -- We have copied the elements from to the old source array to the
1511 -- new destination array, so we can now deallocate the old array.
4c2d6a70 1512
d43d5ef7 1513 Container.Elements := Dst;
d43d5ef7
MH
1514 Free (Src);
1515
5bec9717
AC
1516 -- Now we append the new items.
1517
1518 for Idx in Before .. New_Last loop
0b5b2bbc 1519
2602b64e
AC
1520 -- In order to preserve container invariants, we always attempt
1521 -- the element allocation first, before setting the Last index
1522 -- value, in case the allocation fails (either because there
1523 -- is no storage available, or because element initialization
1524 -- fails).
5bec9717 1525
50878404 1526 declare
50878404
AC
1527 -- The element allocator may need an accessibility check in
1528 -- the case the actual type is class-wide or has access
1529 -- discriminants (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
1530
1531 pragma Unsuppress (Accessibility_Check);
1532
50878404
AC
1533 begin
1534 Dst.EA (Idx) := new Element_Type'(New_Item);
1535 end;
5bec9717
AC
1536
1537 -- The allocation of the element succeeded, so it is now safe
1538 -- to update the Last index, restoring container invariants.
1539
1540 Container.Last := Idx;
d43d5ef7 1541 end loop;
4c2d6a70 1542
5bec9717
AC
1543 else
1544 -- The new items are being inserted before some existing elements,
1545 -- so we must slide the existing elements up to their new home.
4c2d6a70 1546
e9f97e79 1547 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 1548 Index := Before + Index_Type'Base (Count);
5bec9717
AC
1549 else
1550 Index := Index_Type'Base (Count_Type'Base (Before) + Count);
1551 end if;
1552
1553 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1554
2602b64e
AC
1555 -- We have copied the elements from to the old source array to the
1556 -- new destination array, so we can now deallocate the old array.
d43d5ef7
MH
1557
1558 Container.Elements := Dst;
5bec9717 1559 Container.Last := New_Last;
d43d5ef7
MH
1560 Free (Src);
1561
5bec9717 1562 -- The new array has a range in the middle containing null access
2602b64e 1563 -- values. Fill in that partition of the array with the new items.
5bec9717
AC
1564
1565 for Idx in Before .. Index - 1 loop
0b5b2bbc 1566
5bec9717
AC
1567 -- Note that container invariants have already been satisfied
1568 -- (in particular, the Last index value of the vector has
1569 -- already been updated), so if this allocation fails we simply
1570 -- let it propagate.
1571
50878404 1572 declare
50878404
AC
1573 -- The element allocator may need an accessibility check in
1574 -- the case the actual type is class-wide or has access
1575 -- discriminants (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
1576
1577 pragma Unsuppress (Accessibility_Check);
1578
50878404
AC
1579 begin
1580 Dst.EA (Idx) := new Element_Type'(New_Item);
1581 end;
d43d5ef7 1582 end loop;
5bec9717
AC
1583 end if;
1584 end;
8704d4b3
MH
1585 end Insert;
1586
1587 procedure Insert
1588 (Container : in out Vector;
1589 Before : Extended_Index;
1590 New_Item : Vector)
1591 is
1592 N : constant Count_Type := Length (New_Item);
5bec9717 1593 J : Index_Type'Base;
4c2d6a70 1594
4c2d6a70 1595 begin
5bec9717
AC
1596 -- Use Insert_Space to create the "hole" (the destination slice) into
1597 -- which we copy the source items.
4c2d6a70 1598
5bec9717 1599 Insert_Space (Container, Before, Count => N);
4c2d6a70 1600
8704d4b3 1601 if N = 0 then
0b5b2bbc 1602
5bec9717
AC
1603 -- There's nothing else to do here (vetting of parameters was
1604 -- performed already in Insert_Space), so we simply return.
1605
8704d4b3
MH
1606 return;
1607 end if;
4c2d6a70 1608
5bec9717 1609 if Container'Address /= New_Item'Address then
0b5b2bbc 1610
5bec9717
AC
1611 -- This is the simple case. New_Item denotes an object different
1612 -- from Container, so there's nothing special we need to do to copy
1613 -- the source items to their destination, because all of the source
1614 -- items are contiguous.
1615
1616 declare
1617 subtype Src_Index_Subtype is Index_Type'Base range
1618 Index_Type'First .. New_Item.Last;
1619
1620 Src : Elements_Array renames
1621 New_Item.Elements.EA (Src_Index_Subtype);
1622
1623 Dst : Elements_Array renames Container.Elements.EA;
1624
1625 Dst_Index : Index_Type'Base;
1626
1627 begin
1628 Dst_Index := Before - 1;
1629 for Src_Index in Src'Range loop
1630 Dst_Index := Dst_Index + 1;
1631
1632 if Src (Src_Index) /= null then
1633 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1634 end if;
1635 end loop;
1636 end;
1637
1638 return;
1639 end if;
1640
1641 -- New_Item denotes the same object as Container, so an insertion has
1642 -- potentially split the source items. The first source slice is
1643 -- [Index_Type'First, Before), and the second source slice is
1644 -- [J, Container.Last], where index value J is the first index of the
1645 -- second slice. (J gets computed below, but only after we have
1646 -- determined that the second source slice is non-empty.) The
1647 -- destination slice is always the range [Before, J). We perform the
1648 -- copy in two steps, using each of the two slices of the source items.
4c2d6a70 1649
d43d5ef7 1650 declare
5bec9717
AC
1651 L : constant Index_Type'Base := Before - 1;
1652
1653 subtype Src_Index_Subtype is Index_Type'Base range
1654 Index_Type'First .. L;
4c2d6a70 1655
5bec9717
AC
1656 Src : Elements_Array renames
1657 Container.Elements.EA (Src_Index_Subtype);
4c2d6a70 1658
5bec9717 1659 Dst : Elements_Array renames Container.Elements.EA;
4c2d6a70 1660
5bec9717 1661 Dst_Index : Index_Type'Base;
4c2d6a70 1662
d43d5ef7 1663 begin
5bec9717
AC
1664 -- We first copy the source items that precede the space we
1665 -- inserted. (If Before equals Index_Type'First, then this first
1666 -- source slice will be empty, which is harmless.)
f97ccb3a 1667
5bec9717
AC
1668 Dst_Index := Before - 1;
1669 for Src_Index in Src'Range loop
1670 Dst_Index := Dst_Index + 1;
8704d4b3 1671
5bec9717
AC
1672 if Src (Src_Index) /= null then
1673 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1674 end if;
1675 end loop;
4c2d6a70 1676
5bec9717 1677 if Src'Length = N then
0b5b2bbc 1678
5bec9717
AC
1679 -- The new items were effectively appended to the container, so we
1680 -- have already copied all of the items that need to be copied.
1681 -- We return early here, even though the source slice below is
1682 -- empty (so the assignment would be harmless), because we want to
1683 -- avoid computing J, which will overflow if J is greater than
1684 -- Index_Type'Base'Last.
4c2d6a70 1685
d43d5ef7
MH
1686 return;
1687 end if;
5bec9717 1688 end;
4c2d6a70 1689
5bec9717 1690 -- Index value J is the first index of the second source slice. (It is
0b5b2bbc
AC
1691 -- also 1 greater than the last index of the destination slice.) Note:
1692 -- avoid computing J if J is greater than Index_Type'Base'Last, in order
1693 -- to avoid overflow. Prevent that by returning early above, immediately
1694 -- after copying the first slice of the source, and determining that
1695 -- this second slice of the source is empty.
4c2d6a70 1696
e9f97e79 1697 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 1698 J := Before + Index_Type'Base (N);
5bec9717
AC
1699 else
1700 J := Index_Type'Base (Count_Type'Base (Before) + N);
1701 end if;
4c2d6a70 1702
5bec9717
AC
1703 declare
1704 subtype Src_Index_Subtype is Index_Type'Base range
1705 J .. Container.Last;
4c2d6a70 1706
5bec9717
AC
1707 Src : Elements_Array renames
1708 Container.Elements.EA (Src_Index_Subtype);
4c2d6a70 1709
5bec9717 1710 Dst : Elements_Array renames Container.Elements.EA;
4c2d6a70 1711
5bec9717 1712 Dst_Index : Index_Type'Base;
4c2d6a70 1713
5bec9717 1714 begin
0b5b2bbc
AC
1715 -- We next copy the source items that follow the space we inserted.
1716 -- Index value Dst_Index is the first index of that portion of the
1717 -- destination that receives this slice of the source. (For the
1718 -- reasons given above, this slice is guaranteed to be non-empty.)
4c2d6a70 1719
e9f97e79 1720 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 1721 Dst_Index := J - Index_Type'Base (Src'Length);
5bec9717
AC
1722 else
1723 Dst_Index := Index_Type'Base (Count_Type'Base (J) - Src'Length);
1724 end if;
1725
1726 for Src_Index in Src'Range loop
1727 if Src (Src_Index) /= null then
1728 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1729 end if;
1730
1731 Dst_Index := Dst_Index + 1;
1732 end loop;
d43d5ef7 1733 end;
8704d4b3 1734 end Insert;
4c2d6a70 1735
8704d4b3
MH
1736 procedure Insert
1737 (Container : in out Vector;
1738 Before : Cursor;
1739 New_Item : Vector)
1740 is
1741 Index : Index_Type'Base;
4c2d6a70 1742
8704d4b3 1743 begin
e9f97e79 1744 if Checks and then Before.Container /= null
ef992452 1745 and then Before.Container /= Container'Unrestricted_Access
8704d4b3 1746 then
dc6b9ba2 1747 raise Program_Error with "Before cursor denotes wrong container";
4c2d6a70
AC
1748 end if;
1749
8704d4b3 1750 if Is_Empty (New_Item) then
4c2d6a70
AC
1751 return;
1752 end if;
1753
2602b64e 1754 if Before.Container = null or else Before.Index > Container.Last then
e9f97e79 1755 if Checks and then Container.Last = Index_Type'Last then
dc6b9ba2
MH
1756 raise Constraint_Error with
1757 "vector is already at its maximum length";
d43d5ef7
MH
1758 end if;
1759
1760 Index := Container.Last + 1;
1761
8704d4b3
MH
1762 else
1763 Index := Before.Index;
1764 end if;
4c2d6a70 1765
8704d4b3
MH
1766 Insert (Container, Index, New_Item);
1767 end Insert;
4c2d6a70 1768
8704d4b3
MH
1769 procedure Insert
1770 (Container : in out Vector;
1771 Before : Cursor;
1772 New_Item : Vector;
1773 Position : out Cursor)
1774 is
1775 Index : Index_Type'Base;
4c2d6a70 1776
4c2d6a70 1777 begin
e9f97e79
AC
1778 if Checks and then Before.Container /= null
1779 and then Before.Container /= Container'Unrestricted_Access
8704d4b3 1780 then
dc6b9ba2 1781 raise Program_Error with "Before cursor denotes wrong container";
8704d4b3 1782 end if;
4c2d6a70 1783
8704d4b3 1784 if Is_Empty (New_Item) then
2602b64e 1785 if Before.Container = null or else Before.Index > Container.Last then
8704d4b3 1786 Position := No_Element;
4c2d6a70 1787 else
ef992452 1788 Position := (Container'Unrestricted_Access, Before.Index);
4c2d6a70 1789 end if;
4c2d6a70 1790
4c2d6a70
AC
1791 return;
1792 end if;
1793
2602b64e 1794 if Before.Container = null or else Before.Index > Container.Last then
e9f97e79 1795 if Checks and then Container.Last = Index_Type'Last then
dc6b9ba2
MH
1796 raise Constraint_Error with
1797 "vector is already at its maximum length";
d43d5ef7
MH
1798 end if;
1799
1800 Index := Container.Last + 1;
1801
4c2d6a70 1802 else
8704d4b3 1803 Index := Before.Index;
4c2d6a70
AC
1804 end if;
1805
8704d4b3 1806 Insert (Container, Index, New_Item);
4c2d6a70 1807
e9f97e79 1808 Position := (Container'Unrestricted_Access, Index);
8704d4b3 1809 end Insert;
4c2d6a70 1810
8704d4b3
MH
1811 procedure Insert
1812 (Container : in out Vector;
1813 Before : Cursor;
1814 New_Item : Element_Type;
1815 Count : Count_Type := 1)
1816 is
1817 Index : Index_Type'Base;
4c2d6a70
AC
1818
1819 begin
e9f97e79 1820 if Checks and then Before.Container /= null
ef992452 1821 and then Before.Container /= Container'Unrestricted_Access
8704d4b3 1822 then
dc6b9ba2 1823 raise Program_Error with "Before cursor denotes wrong container";
4c2d6a70
AC
1824 end if;
1825
8704d4b3 1826 if Count = 0 then
4c2d6a70
AC
1827 return;
1828 end if;
1829
2602b64e 1830 if Before.Container = null or else Before.Index > Container.Last then
e9f97e79 1831 if Checks and then Container.Last = Index_Type'Last then
dc6b9ba2
MH
1832 raise Constraint_Error with
1833 "vector is already at its maximum length";
d43d5ef7
MH
1834 end if;
1835
1836 Index := Container.Last + 1;
1837
8704d4b3
MH
1838 else
1839 Index := Before.Index;
4c2d6a70
AC
1840 end if;
1841
8704d4b3
MH
1842 Insert (Container, Index, New_Item, Count);
1843 end Insert;
4c2d6a70 1844
8704d4b3
MH
1845 procedure Insert
1846 (Container : in out Vector;
1847 Before : Cursor;
1848 New_Item : Element_Type;
1849 Position : out Cursor;
1850 Count : Count_Type := 1)
1851 is
1852 Index : Index_Type'Base;
4c2d6a70
AC
1853
1854 begin
e9f97e79 1855 if Checks and then Before.Container /= null
ef992452 1856 and then Before.Container /= Container'Unrestricted_Access
8704d4b3 1857 then
dc6b9ba2 1858 raise Program_Error with "Before cursor denotes wrong container";
8704d4b3
MH
1859 end if;
1860
1861 if Count = 0 then
e9f97e79 1862 if Before.Container = null or else Before.Index > Container.Last then
8704d4b3
MH
1863 Position := No_Element;
1864 else
ef992452 1865 Position := (Container'Unrestricted_Access, Before.Index);
8704d4b3 1866 end if;
4c2d6a70 1867
4c2d6a70
AC
1868 return;
1869 end if;
1870
2602b64e 1871 if Before.Container = null or else Before.Index > Container.Last then
e9f97e79 1872 if Checks and then Container.Last = Index_Type'Last then
dc6b9ba2
MH
1873 raise Constraint_Error with
1874 "vector is already at its maximum length";
d43d5ef7
MH
1875 end if;
1876
1877 Index := Container.Last + 1;
1878
8704d4b3
MH
1879 else
1880 Index := Before.Index;
4c2d6a70
AC
1881 end if;
1882
8704d4b3 1883 Insert (Container, Index, New_Item, Count);
4c2d6a70 1884
ef992452 1885 Position := (Container'Unrestricted_Access, Index);
8704d4b3 1886 end Insert;
4c2d6a70 1887
8704d4b3
MH
1888 ------------------
1889 -- Insert_Space --
1890 ------------------
4c2d6a70 1891
8704d4b3
MH
1892 procedure Insert_Space
1893 (Container : in out Vector;
1894 Before : Extended_Index;
1895 Count : Count_Type := 1)
1896 is
5bec9717
AC
1897 Old_Length : constant Count_Type := Container.Length;
1898
1899 Max_Length : Count_Type'Base; -- determined from range of Index_Type
1900 New_Length : Count_Type'Base; -- sum of current length and Count
1901 New_Last : Index_Type'Base; -- last index of vector after insertion
4c2d6a70 1902
5bec9717
AC
1903 Index : Index_Type'Base; -- scratch for intermediate values
1904 J : Count_Type'Base; -- scratch
4c2d6a70 1905
5bec9717
AC
1906 New_Capacity : Count_Type'Base; -- length of new, expanded array
1907 Dst_Last : Index_Type'Base; -- last index of new, expanded array
1908 Dst : Elements_Access; -- new, expanded internal array
4c2d6a70
AC
1909
1910 begin
e9f97e79
AC
1911 if Checks then
1912 -- As a precondition on the generic actual Index_Type, the base type
1913 -- must include Index_Type'Pred (Index_Type'First); this is the value
1914 -- that Container.Last assumes when the vector is empty. However, we
1915 -- do not allow that as the value for Index when specifying where the
1916 -- new items should be inserted, so we must manually check. (That the
1917 -- user is allowed to specify the value at all here is a consequence
1918 -- of the declaration of the Extended_Index subtype, which includes
1919 -- the values in the base range that immediately precede and
1920 -- immediately follow the values in the Index_Type.)
5bec9717 1921
e9f97e79
AC
1922 if Before < Index_Type'First then
1923 raise Constraint_Error with
1924 "Before index is out of range (too small)";
1925 end if;
4c2d6a70 1926
e9f97e79
AC
1927 -- We do allow a value greater than Container.Last to be specified as
1928 -- the Index, but only if it's immediately greater. This allows for
1929 -- the case of appending items to the back end of the vector. (It is
1930 -- assumed that specifying an index value greater than Last + 1
1931 -- indicates some deeper flaw in the caller's algorithm, so that case
1932 -- is treated as a proper error.)
1933
1934 if Before > Container.Last + 1 then
1935 raise Constraint_Error with
1936 "Before index is out of range (too large)";
1937 end if;
8704d4b3 1938 end if;
4c2d6a70 1939
5bec9717
AC
1940 -- We treat inserting 0 items into the container as a no-op, even when
1941 -- the container is busy, so we simply return.
1942
8704d4b3
MH
1943 if Count = 0 then
1944 return;
4c2d6a70
AC
1945 end if;
1946
5bec9717
AC
1947 -- There are two constraints we need to satisfy. The first constraint is
1948 -- that a container cannot have more than Count_Type'Last elements, so
e9f97e79
AC
1949 -- we must check the sum of the current length and the insertion count.
1950 -- Note: we cannot simply add these values, because of the possibility
1951 -- of overflow.
4c2d6a70 1952
e9f97e79 1953 if Checks and then Old_Length > Count_Type'Last - Count then
5bec9717
AC
1954 raise Constraint_Error with "Count is out of range";
1955 end if;
dc6b9ba2 1956
5bec9717
AC
1957 -- It is now safe compute the length of the new vector, without fear of
1958 -- overflow.
d43d5ef7 1959
5bec9717
AC
1960 New_Length := Old_Length + Count;
1961
1962 -- The second constraint is that the new Last index value cannot exceed
1963 -- Index_Type'Last. In each branch below, we calculate the maximum
1964 -- length (computed from the range of values in Index_Type), and then
1965 -- compare the new length to the maximum length. If the new length is
1966 -- acceptable, then we compute the new last index from that.
1967
e9f97e79 1968 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717
AC
1969 -- We have to handle the case when there might be more values in the
1970 -- range of Index_Type than in the range of Count_Type.
1971
1972 if Index_Type'First <= 0 then
0b5b2bbc 1973
5bec9717
AC
1974 -- We know that No_Index (the same as Index_Type'First - 1) is
1975 -- less than 0, so it is safe to compute the following sum without
1976 -- fear of overflow.
1977
1978 Index := No_Index + Index_Type'Base (Count_Type'Last);
1979
1980 if Index <= Index_Type'Last then
0b5b2bbc 1981
5bec9717
AC
1982 -- We have determined that range of Index_Type has at least as
1983 -- many values as in Count_Type, so Count_Type'Last is the
1984 -- maximum number of items that are allowed.
1985
1986 Max_Length := Count_Type'Last;
1987
1988 else
1989 -- The range of Index_Type has fewer values than in Count_Type,
1990 -- so the maximum number of items is computed from the range of
1991 -- the Index_Type.
1992
1993 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
1994 end if;
1995
1996 else
1997 -- No_Index is equal or greater than 0, so we can safely compute
1998 -- the difference without fear of overflow (which we would have to
1999 -- worry about if No_Index were less than 0, but that case is
2000 -- handled above).
2001
e9f97e79 2002 if Index_Type'Last - No_Index >= Count_Type_Last then
7b56a91b
AC
2003 -- We have determined that range of Index_Type has at least as
2004 -- many values as in Count_Type, so Count_Type'Last is the
2005 -- maximum number of items that are allowed.
2006
2007 Max_Length := Count_Type'Last;
2008
2009 else
2010 -- The range of Index_Type has fewer values than in Count_Type,
2011 -- so the maximum number of items is computed from the range of
2012 -- the Index_Type.
2013
2014 Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
2015 end if;
dc6b9ba2
MH
2016 end if;
2017
5bec9717 2018 elsif Index_Type'First <= 0 then
0b5b2bbc 2019
5bec9717
AC
2020 -- We know that No_Index (the same as Index_Type'First - 1) is less
2021 -- than 0, so it is safe to compute the following sum without fear of
2022 -- overflow.
dc6b9ba2 2023
5bec9717
AC
2024 J := Count_Type'Base (No_Index) + Count_Type'Last;
2025
2026 if J <= Count_Type'Base (Index_Type'Last) then
0b5b2bbc 2027
5bec9717
AC
2028 -- We have determined that range of Index_Type has at least as
2029 -- many values as in Count_Type, so Count_Type'Last is the maximum
2030 -- number of items that are allowed.
2031
2032 Max_Length := Count_Type'Last;
2033
2034 else
2035 -- The range of Index_Type has fewer values than Count_Type does,
2036 -- so the maximum number of items is computed from the range of
2037 -- the Index_Type.
2038
2039 Max_Length :=
2040 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
d43d5ef7
MH
2041 end if;
2042
5bec9717
AC
2043 else
2044 -- No_Index is equal or greater than 0, so we can safely compute the
2045 -- difference without fear of overflow (which we would have to worry
2046 -- about if No_Index were less than 0, but that case is handled
2047 -- above).
4c2d6a70 2048
5bec9717
AC
2049 Max_Length :=
2050 Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index);
2051 end if;
2052
2053 -- We have just computed the maximum length (number of items). We must
2054 -- now compare the requested length to the maximum length, as we do not
2055 -- allow a vector expand beyond the maximum (because that would create
2056 -- an internal array with a last index value greater than
2057 -- Index_Type'Last, with no way to index those elements).
2058
e9f97e79 2059 if Checks and then New_Length > Max_Length then
5bec9717
AC
2060 raise Constraint_Error with "Count is out of range";
2061 end if;
2062
2063 -- New_Last is the last index value of the items in the container after
2064 -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to
2065 -- compute its value from the New_Length.
2066
e9f97e79 2067 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 2068 New_Last := No_Index + Index_Type'Base (New_Length);
5bec9717
AC
2069 else
2070 New_Last := Index_Type'Base (Count_Type'Base (No_Index) + New_Length);
4c2d6a70
AC
2071 end if;
2072
8704d4b3 2073 if Container.Elements = null then
5bec9717
AC
2074 pragma Assert (Container.Last = No_Index);
2075
2076 -- This is the simplest case, with which we must always begin: we're
2077 -- inserting items into an empty vector that hasn't allocated an
2078 -- internal array yet. Note that we don't need to check the busy bit
2079 -- here, because an empty container cannot be busy.
2080
2081 -- In an indefinite vector, elements are allocated individually, and
2082 -- stored as access values on the internal array (the length of which
0b5b2bbc
AC
2083 -- represents the vector "capacity"), which is separately allocated.
2084 -- We have no elements here (because we're inserting "space"), so all
2085 -- we need to do is allocate the backbone.
5bec9717 2086
f97ccb3a 2087 Container.Elements := new Elements_Type (New_Last);
d43d5ef7 2088 Container.Last := New_Last;
5bec9717 2089
8704d4b3
MH
2090 return;
2091 end if;
4c2d6a70 2092
5bec9717
AC
2093 -- The tampering bits exist to prevent an item from being harmfully
2094 -- manipulated while it is being visited. Query, Update, and Iterate
0b5b2bbc
AC
2095 -- increment the busy count on entry, and decrement the count on exit.
2096 -- Insert checks the count to determine whether it is being called while
2097 -- the associated callback procedure is executing.
5bec9717 2098
e9f97e79 2099 TC_Check (Container.TC);
5bec9717
AC
2100
2101 if New_Length <= Container.Elements.EA'Length then
2602b64e
AC
2102
2103 -- In this case, we are inserting elements into a vector that has
5bec9717
AC
2104 -- already allocated an internal array, and the existing array has
2105 -- enough unused storage for the new items.
2106
8704d4b3 2107 declare
f97ccb3a 2108 E : Elements_Array renames Container.Elements.EA;
d43d5ef7 2109
8704d4b3 2110 begin
d43d5ef7 2111 if Before <= Container.Last then
0b5b2bbc 2112
5bec9717 2113 -- The new space is being inserted before some existing
2602b64e
AC
2114 -- elements, so we must slide the existing elements up to
2115 -- their new home. We use the wider of Index_Type'Base and
5bec9717 2116 -- Count_Type'Base as the type for intermediate index values.
4c2d6a70 2117
e9f97e79 2118 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 2119 Index := Before + Index_Type'Base (Count);
5bec9717
AC
2120 else
2121 Index := Index_Type'Base (Count_Type'Base (Before) + Count);
2122 end if;
2123
2124 E (Index .. New_Last) := E (Before .. Container.Last);
2125 E (Before .. Index - 1) := (others => null);
d43d5ef7 2126 end if;
4c2d6a70
AC
2127 end;
2128
d43d5ef7 2129 Container.Last := New_Last;
8704d4b3 2130 return;
4c2d6a70
AC
2131 end if;
2132
5bec9717
AC
2133 -- In this case, we're inserting elements into a vector that has already
2134 -- allocated an internal array, but the existing array does not have
2135 -- enough storage, so we must allocate a new, longer array. In order to
2136 -- guarantee that the amortized insertion cost is O(1), we always
2137 -- allocate an array whose length is some power-of-two factor of the
2138 -- current array length. (The new array cannot have a length less than
2139 -- the New_Length of the container, but its last index value cannot be
2140 -- greater than Index_Type'Last.)
2141
2142 New_Capacity := Count_Type'Max (1, Container.Elements.EA'Length);
2143 while New_Capacity < New_Length loop
2144 if New_Capacity > Count_Type'Last / 2 then
2145 New_Capacity := Count_Type'Last;
2146 exit;
2147 end if;
4c2d6a70 2148
5bec9717
AC
2149 New_Capacity := 2 * New_Capacity;
2150 end loop;
4c2d6a70 2151
5bec9717 2152 if New_Capacity > Max_Length then
0b5b2bbc 2153
5bec9717
AC
2154 -- We have reached the limit of capacity, so no further expansion
2155 -- will occur. (This is not a problem, as there is never a need to
2156 -- have more capacity than the maximum container length.)
4c2d6a70 2157
5bec9717
AC
2158 New_Capacity := Max_Length;
2159 end if;
4c2d6a70 2160
5bec9717
AC
2161 -- We have computed the length of the new internal array (and this is
2162 -- what "vector capacity" means), so use that to compute its last index.
dc6b9ba2 2163
e9f97e79 2164 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 2165 Dst_Last := No_Index + Index_Type'Base (New_Capacity);
5bec9717
AC
2166 else
2167 Dst_Last :=
2168 Index_Type'Base (Count_Type'Base (No_Index) + New_Capacity);
2169 end if;
dc6b9ba2 2170
5bec9717
AC
2171 -- Now we allocate the new, longer internal array. If the allocation
2172 -- fails, we have not changed any container state, so no side-effect
2173 -- will occur as a result of propagating the exception.
2174
2175 Dst := new Elements_Type (Dst_Last);
2176
2177 -- We have our new internal array. All that needs to be done now is to
2178 -- copy the existing items (if any) from the old array (the "source"
2179 -- array) to the new array (the "destination" array), and then
2180 -- deallocate the old array.
4c2d6a70 2181
8704d4b3 2182 declare
d43d5ef7 2183 Src : Elements_Access := Container.Elements;
4c2d6a70 2184
8704d4b3 2185 begin
5bec9717
AC
2186 Dst.EA (Index_Type'First .. Before - 1) :=
2187 Src.EA (Index_Type'First .. Before - 1);
4c2d6a70 2188
5bec9717 2189 if Before <= Container.Last then
0b5b2bbc 2190
5bec9717
AC
2191 -- The new items are being inserted before some existing elements,
2192 -- so we must slide the existing elements up to their new home.
d43d5ef7 2193
e9f97e79 2194 if Index_Type'Base'Last >= Count_Type_Last then
5bec9717 2195 Index := Before + Index_Type'Base (Count);
5bec9717
AC
2196 else
2197 Index := Index_Type'Base (Count_Type'Base (Before) + Count);
2198 end if;
d43d5ef7 2199
5bec9717 2200 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
d43d5ef7 2201 end if;
4c2d6a70 2202
5bec9717
AC
2203 -- We have copied the elements from to the old, source array to the
2204 -- new, destination array, so we can now restore invariants, and
2205 -- deallocate the old array.
2206
8704d4b3
MH
2207 Container.Elements := Dst;
2208 Container.Last := New_Last;
d43d5ef7 2209 Free (Src);
4c2d6a70 2210 end;
8704d4b3 2211 end Insert_Space;
4c2d6a70 2212
8704d4b3
MH
2213 procedure Insert_Space
2214 (Container : in out Vector;
2215 Before : Cursor;
2216 Position : out Cursor;
2217 Count : Count_Type := 1)
2218 is
2219 Index : Index_Type'Base;
2220
2221 begin
e9f97e79 2222 if Checks and then Before.Container /= null
ef992452 2223 and then Before.Container /= Container'Unrestricted_Access
8704d4b3 2224 then
dc6b9ba2 2225 raise Program_Error with "Before cursor denotes wrong container";
8704d4b3 2226 end if;
4c2d6a70 2227
8704d4b3 2228 if Count = 0 then
2602b64e 2229 if Before.Container = null or else Before.Index > Container.Last then
8704d4b3
MH
2230 Position := No_Element;
2231 else
ef992452 2232 Position := (Container'Unrestricted_Access, Before.Index);
8704d4b3 2233 end if;
4c2d6a70 2234
8704d4b3
MH
2235 return;
2236 end if;
4c2d6a70 2237
e9f97e79
AC
2238 if Before.Container = null or else Before.Index > Container.Last then
2239 if Checks and then Container.Last = Index_Type'Last then
dc6b9ba2
MH
2240 raise Constraint_Error with
2241 "vector is already at its maximum length";
d43d5ef7
MH
2242 end if;
2243
2244 Index := Container.Last + 1;
2245
8704d4b3
MH
2246 else
2247 Index := Before.Index;
2248 end if;
4c2d6a70 2249
8704d4b3 2250 Insert_Space (Container, Index, Count);
4c2d6a70 2251
e9f97e79 2252 Position := (Container'Unrestricted_Access, Index);
8704d4b3
MH
2253 end Insert_Space;
2254
2255 --------------
2256 -- Is_Empty --
2257 --------------
2258
2259 function Is_Empty (Container : Vector) return Boolean is
4c2d6a70 2260 begin
8704d4b3
MH
2261 return Container.Last < Index_Type'First;
2262 end Is_Empty;
4c2d6a70 2263
8704d4b3
MH
2264 -------------
2265 -- Iterate --
2266 -------------
2267
2268 procedure Iterate
2269 (Container : Vector;
0ae9f22f 2270 Process : not null access procedure (Position : Cursor))
8704d4b3 2271 is
e9f97e79 2272 Busy : With_Busy (Container.TC'Unrestricted_Access);
8704d4b3 2273 begin
e9f97e79
AC
2274 for Indx in Index_Type'First .. Container.Last loop
2275 Process (Cursor'(Container'Unrestricted_Access, Indx));
2276 end loop;
8704d4b3 2277 end Iterate;
4c2d6a70 2278
e9f97e79
AC
2279 function Iterate
2280 (Container : Vector)
e8bd500e 2281 return Vector_Iterator_Interfaces.Reversible_Iterator'Class
3e24afaa 2282 is
e8bd500e 2283 V : constant Vector_Access := Container'Unrestricted_Access;
3e24afaa 2284 begin
e8bd500e
AC
2285 -- The value of its Index component influences the behavior of the First
2286 -- and Last selector functions of the iterator object. When the Index
2287 -- component is No_Index (as is the case here), this means the iterator
2288 -- object was constructed without a start expression. This is a complete
2289 -- iterator, meaning that the iteration starts from the (logical)
2290 -- beginning of the sequence of items.
2291
2292 -- Note: For a forward iterator, Container.First is the beginning, and
2293 -- for a reverse iterator, Container.Last is the beginning.
2294
ef992452 2295 return It : constant Iterator :=
15f0f591
AC
2296 (Limited_Controlled with
2297 Container => V,
2298 Index => No_Index)
ef992452 2299 do
e9f97e79 2300 Busy (Container.TC'Unrestricted_Access.all);
ef992452 2301 end return;
3e24afaa
AC
2302 end Iterate;
2303
690943fc
RD
2304 function Iterate
2305 (Container : Vector;
2306 Start : Cursor)
e8bd500e 2307 return Vector_Iterator_Interfaces.Reversible_Iterator'Class
3e24afaa 2308 is
e8bd500e 2309 V : constant Vector_Access := Container'Unrestricted_Access;
3e24afaa 2310 begin
e8bd500e
AC
2311 -- It was formerly the case that when Start = No_Element, the partial
2312 -- iterator was defined to behave the same as for a complete iterator,
2313 -- and iterate over the entire sequence of items. However, those
2314 -- semantics were unintuitive and arguably error-prone (it is too easy
2315 -- to accidentally create an endless loop), and so they were changed,
2316 -- per the ARG meeting in Denver on 2011/11. However, there was no
2317 -- consensus about what positive meaning this corner case should have,
2318 -- and so it was decided to simply raise an exception. This does imply,
2319 -- however, that it is not possible to use a partial iterator to specify
2320 -- an empty sequence of items.
2321
e9f97e79
AC
2322 if Checks then
2323 if Start.Container = null then
2324 raise Constraint_Error with
2325 "Start position for iterator equals No_Element";
2326 end if;
e8bd500e 2327
e9f97e79
AC
2328 if Start.Container /= V then
2329 raise Program_Error with
2330 "Start cursor of Iterate designates wrong vector";
2331 end if;
e8bd500e 2332
e9f97e79
AC
2333 if Start.Index > V.Last then
2334 raise Constraint_Error with
2335 "Start position for iterator equals No_Element";
2336 end if;
e8bd500e
AC
2337 end if;
2338
2339 -- The value of its Index component influences the behavior of the First
2340 -- and Last selector functions of the iterator object. When the Index
2341 -- component is not No_Index (as is the case here), it means that this
2342 -- is a partial iteration, over a subset of the complete sequence of
2343 -- items. The iterator object was constructed with a start expression,
2344 -- indicating the position from which the iteration begins. Note that
fe58fea7
AC
2345 -- the start position has the same value irrespective of whether this
2346 -- is a forward or reverse iteration.
e8bd500e 2347
ef992452 2348 return It : constant Iterator :=
15f0f591
AC
2349 (Limited_Controlled with
2350 Container => V,
2351 Index => Start.Index)
ef992452 2352 do
e9f97e79 2353 Busy (Container.TC'Unrestricted_Access.all);
ef992452 2354 end return;
3e24afaa
AC
2355 end Iterate;
2356
8704d4b3
MH
2357 ----------
2358 -- Last --
2359 ----------
4c2d6a70 2360
8704d4b3 2361 function Last (Container : Vector) return Cursor is
4c2d6a70 2362 begin
8704d4b3 2363 if Is_Empty (Container) then
4c2d6a70
AC
2364 return No_Element;
2365 end if;
2366
ef992452 2367 return (Container'Unrestricted_Access, Container.Last);
8704d4b3 2368 end Last;
4c2d6a70 2369
3e24afaa 2370 function Last (Object : Iterator) return Cursor is
3e24afaa 2371 begin
e8bd500e
AC
2372 -- The value of the iterator object's Index component influences the
2373 -- behavior of the Last (and First) selector function.
2374
fe58fea7
AC
2375 -- When the Index component is No_Index, this means the iterator
2376 -- object was constructed without a start expression, in which case the
e8bd500e
AC
2377 -- (reverse) iteration starts from the (logical) beginning of the entire
2378 -- sequence (corresponding to Container.Last, for a reverse iterator).
2379
fe58fea7
AC
2380 -- Otherwise, this is iteration over a partial sequence of items.
2381 -- When the Index component is not No_Index, the iterator object was
2382 -- constructed with a start expression, that specifies the position
2383 -- from which the (reverse) partial iteration begins.
e8bd500e
AC
2384
2385 if Object.Index = No_Index then
2386 return Last (Object.Container.all);
2387 else
2388 return Cursor'(Object.Container, Object.Index);
2389 end if;
3e24afaa
AC
2390 end Last;
2391
e9f97e79 2392 ------------------
8704d4b3
MH
2393 -- Last_Element --
2394 ------------------
4c2d6a70 2395
8704d4b3 2396 function Last_Element (Container : Vector) return Element_Type is
4c2d6a70 2397 begin
e9f97e79 2398 if Checks and then Container.Last = No_Index then
f97ccb3a
BD
2399 raise Constraint_Error with "Container is empty";
2400 end if;
2401
2402 declare
2403 EA : constant Element_Access :=
2602b64e 2404 Container.Elements.EA (Container.Last);
f97ccb3a 2405 begin
e9f97e79 2406 if Checks and then EA = null then
f97ccb3a 2407 raise Constraint_Error with "last element is empty";
2602b64e
AC
2408 else
2409 return EA.all;
f97ccb3a 2410 end if;
f97ccb3a 2411 end;
8704d4b3 2412 end Last_Element;
4c2d6a70 2413
8704d4b3
MH
2414 ----------------
2415 -- Last_Index --
2416 ----------------
4c2d6a70 2417
8704d4b3
MH
2418 function Last_Index (Container : Vector) return Extended_Index is
2419 begin
2420 return Container.Last;
2421 end Last_Index;
4c2d6a70 2422
8704d4b3
MH
2423 ------------
2424 -- Length --
2425 ------------
4c2d6a70 2426
8704d4b3 2427 function Length (Container : Vector) return Count_Type is
5bec9717
AC
2428 L : constant Index_Type'Base := Container.Last;
2429 F : constant Index_Type := Index_Type'First;
d43d5ef7 2430
4c2d6a70 2431 begin
5bec9717
AC
2432 -- The base range of the index type (Index_Type'Base) might not include
2433 -- all values for length (Count_Type). Contrariwise, the index type
2434 -- might include values outside the range of length. Hence we use
2435 -- whatever type is wider for intermediate values when calculating
2436 -- length. Note that no matter what the index type is, the maximum
2437 -- length to which a vector is allowed to grow is always the minimum
2438 -- of Count_Type'Last and (IT'Last - IT'First + 1).
2439
2440 -- For example, an Index_Type with range -127 .. 127 is only guaranteed
2441 -- to have a base range of -128 .. 127, but the corresponding vector
2442 -- would have lengths in the range 0 .. 255. In this case we would need
2443 -- to use Count_Type'Base for intermediate values.
2444
2445 -- Another case would be the index range -2**63 + 1 .. -2**63 + 10. The
2446 -- vector would have a maximum length of 10, but the index values lie
2447 -- outside the range of Count_Type (which is only 32 bits). In this
2448 -- case we would need to use Index_Type'Base for intermediate values.
2449
2450 if Count_Type'Base'Last >= Index_Type'Pos (Index_Type'Base'Last) then
2451 return Count_Type'Base (L) - Count_Type'Base (F) + 1;
2452 else
2453 return Count_Type (L - F + 1);
2454 end if;
8704d4b3 2455 end Length;
4c2d6a70 2456
8704d4b3
MH
2457 ----------
2458 -- Move --
2459 ----------
4c2d6a70 2460
8704d4b3
MH
2461 procedure Move
2462 (Target : in out Vector;
2463 Source : in out Vector)
2464 is
4c2d6a70 2465 begin
8704d4b3
MH
2466 if Target'Address = Source'Address then
2467 return;
4c2d6a70
AC
2468 end if;
2469
e9f97e79 2470 TC_Check (Source.TC);
4c2d6a70 2471
dc6b9ba2 2472 Clear (Target); -- Checks busy-bit
4c2d6a70 2473
8704d4b3 2474 declare
d43d5ef7 2475 Target_Elements : constant Elements_Access := Target.Elements;
8704d4b3 2476 begin
d43d5ef7
MH
2477 Target.Elements := Source.Elements;
2478 Source.Elements := Target_Elements;
8704d4b3 2479 end;
4c2d6a70 2480
8704d4b3 2481 Target.Last := Source.Last;
8704d4b3
MH
2482 Source.Last := No_Index;
2483 end Move;
2484
2485 ----------
2486 -- Next --
2487 ----------
4c2d6a70 2488
8704d4b3
MH
2489 function Next (Position : Cursor) return Cursor is
2490 begin
4c2d6a70
AC
2491 if Position.Container = null then
2492 return No_Element;
2602b64e 2493 elsif Position.Index < Position.Container.Last then
d43d5ef7 2494 return (Position.Container, Position.Index + 1);
2602b64e
AC
2495 else
2496 return No_Element;
4c2d6a70 2497 end if;
8704d4b3 2498 end Next;
4c2d6a70 2499
3e24afaa
AC
2500 function Next (Object : Iterator; Position : Cursor) return Cursor is
2501 begin
e8bd500e
AC
2502 if Position.Container = null then
2503 return No_Element;
e9f97e79 2504 elsif Checks and then Position.Container /= Object.Container then
e8bd500e
AC
2505 raise Program_Error with
2506 "Position cursor of Next designates wrong vector";
2602b64e
AC
2507 else
2508 return Next (Position);
e8bd500e 2509 end if;
3e24afaa
AC
2510 end Next;
2511
4c2d6a70
AC
2512 procedure Next (Position : in out Cursor) is
2513 begin
4c2d6a70
AC
2514 if Position.Container = null then
2515 return;
2602b64e 2516 elsif Position.Index < Position.Container.Last then
d43d5ef7 2517 Position.Index := Position.Index + 1;
4c2d6a70
AC
2518 else
2519 Position := No_Element;
2520 end if;
4c2d6a70
AC
2521 end Next;
2522
8704d4b3
MH
2523 -------------
2524 -- Prepend --
2525 -------------
4c2d6a70 2526
8704d4b3
MH
2527 procedure Prepend (Container : in out Vector; New_Item : Vector) is
2528 begin
2529 Insert (Container, Index_Type'First, New_Item);
2530 end Prepend;
2531
2532 procedure Prepend
2533 (Container : in out Vector;
2534 New_Item : Element_Type;
2535 Count : Count_Type := 1)
2536 is
4c2d6a70 2537 begin
2602b64e 2538 Insert (Container, Index_Type'First, New_Item, Count);
8704d4b3 2539 end Prepend;
4c2d6a70 2540
8704d4b3
MH
2541 --------------
2542 -- Previous --
2543 --------------
2544
8704d4b3 2545 function Previous (Position : Cursor) return Cursor is
4c2d6a70 2546 begin
4c2d6a70 2547 if Position.Container = null then
8704d4b3 2548 return No_Element;
2602b64e 2549 elsif Position.Index > Index_Type'First then
d43d5ef7 2550 return (Position.Container, Position.Index - 1);
2602b64e
AC
2551 else
2552 return No_Element;
8704d4b3 2553 end if;
8704d4b3 2554 end Previous;
4c2d6a70 2555
3e24afaa
AC
2556 function Previous (Object : Iterator; Position : Cursor) return Cursor is
2557 begin
e8bd500e 2558 if Position.Container = null then
3e24afaa 2559 return No_Element;
e9f97e79 2560 elsif Checks and then Position.Container /= Object.Container then
e8bd500e
AC
2561 raise Program_Error with
2562 "Position cursor of Previous designates wrong vector";
2602b64e
AC
2563 else
2564 return Previous (Position);
e8bd500e 2565 end if;
3e24afaa
AC
2566 end Previous;
2567
e9f97e79
AC
2568 procedure Previous (Position : in out Cursor) is
2569 begin
2570 if Position.Container = null then
2571 return;
2572 elsif Position.Index > Index_Type'First then
2573 Position.Index := Position.Index - 1;
2574 else
2575 Position := No_Element;
2576 end if;
2577 end Previous;
2578
2579 ----------------------
2580 -- Pseudo_Reference --
2581 ----------------------
2582
2583 function Pseudo_Reference
2584 (Container : aliased Vector'Class) return Reference_Control_Type
2585 is
2586 TC : constant Tamper_Counts_Access := Container.TC'Unrestricted_Access;
2587 begin
2588 return R : constant Reference_Control_Type := (Controlled with TC) do
2f26abcc 2589 Busy (TC.all);
e9f97e79
AC
2590 end return;
2591 end Pseudo_Reference;
2592
8704d4b3
MH
2593 -------------------
2594 -- Query_Element --
2595 -------------------
4c2d6a70 2596
8704d4b3
MH
2597 procedure Query_Element
2598 (Container : Vector;
2599 Index : Index_Type;
0ae9f22f 2600 Process : not null access procedure (Element : Element_Type))
8704d4b3 2601 is
e9f97e79 2602 Lock : With_Lock (Container.TC'Unrestricted_Access);
8704d4b3 2603 V : Vector renames Container'Unrestricted_Access.all;
4c2d6a70 2604
4c2d6a70 2605 begin
e9f97e79 2606 if Checks and then Index > Container.Last then
dc6b9ba2 2607 raise Constraint_Error with "Index is out of range";
d43d5ef7
MH
2608 end if;
2609
e9f97e79 2610 if Checks and then V.Elements.EA (Index) = null then
dc6b9ba2 2611 raise Constraint_Error with "element is null";
2368f04e
MH
2612 end if;
2613
e9f97e79 2614 Process (V.Elements.EA (Index).all);
8704d4b3 2615 end Query_Element;
4c2d6a70
AC
2616
2617 procedure Query_Element
8704d4b3 2618 (Position : Cursor;
0ae9f22f 2619 Process : not null access procedure (Element : Element_Type))
8704d4b3 2620 is
4c2d6a70 2621 begin
e9f97e79 2622 if Checks and then Position.Container = null then
dc6b9ba2 2623 raise Constraint_Error with "Position cursor has no element";
2602b64e
AC
2624 else
2625 Query_Element (Position.Container.all, Position.Index, Process);
d43d5ef7 2626 end if;
4c2d6a70
AC
2627 end Query_Element;
2628
8704d4b3
MH
2629 ----------
2630 -- Read --
2631 ----------
4c2d6a70 2632
8704d4b3 2633 procedure Read
dc6b9ba2 2634 (Stream : not null access Root_Stream_Type'Class;
8704d4b3
MH
2635 Container : out Vector)
2636 is
2637 Length : Count_Type'Base;
2638 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
2602b64e 2639 B : Boolean;
4c2d6a70 2640
4c2d6a70 2641 begin
8704d4b3 2642 Clear (Container);
4c2d6a70 2643
8704d4b3 2644 Count_Type'Base'Read (Stream, Length);
4c2d6a70 2645
8704d4b3
MH
2646 if Length > Capacity (Container) then
2647 Reserve_Capacity (Container, Capacity => Length);
2648 end if;
4c2d6a70 2649
8704d4b3 2650 for J in Count_Type range 1 .. Length loop
d43d5ef7 2651 Last := Last + 1;
4c2d6a70 2652
8704d4b3 2653 Boolean'Read (Stream, B);
4c2d6a70 2654
8704d4b3 2655 if B then
f97ccb3a 2656 Container.Elements.EA (Last) :=
8704d4b3
MH
2657 new Element_Type'(Element_Type'Input (Stream));
2658 end if;
2659
2660 Container.Last := Last;
2661 end loop;
2662 end Read;
4c2d6a70 2663
2368f04e 2664 procedure Read
dc6b9ba2 2665 (Stream : not null access Root_Stream_Type'Class;
2368f04e
MH
2666 Position : out Cursor)
2667 is
2668 begin
dc6b9ba2 2669 raise Program_Error with "attempt to stream vector cursor";
2368f04e
MH
2670 end Read;
2671
3e24afaa
AC
2672 procedure Read
2673 (Stream : not null access Root_Stream_Type'Class;
2674 Item : out Reference_Type)
2675 is
2676 begin
2677 raise Program_Error with "attempt to stream reference";
2678 end Read;
2679
2680 procedure Read
2681 (Stream : not null access Root_Stream_Type'Class;
2682 Item : out Constant_Reference_Type)
2683 is
2684 begin
2685 raise Program_Error with "attempt to stream reference";
2686 end Read;
2687
2688 ---------------
2689 -- Reference --
2690 ---------------
2691
0b5b2bbc 2692 function Reference
c9423ca3 2693 (Container : aliased in out Vector;
0b5b2bbc
AC
2694 Position : Cursor) return Reference_Type
2695 is
c9423ca3 2696 begin
e9f97e79
AC
2697 if Checks then
2698 if Position.Container = null then
2699 raise Constraint_Error with "Position cursor has no element";
2700 end if;
3e24afaa 2701
e9f97e79
AC
2702 if Position.Container /= Container'Unrestricted_Access then
2703 raise Program_Error with "Position cursor denotes wrong container";
2704 end if;
c9423ca3 2705
e9f97e79
AC
2706 if Position.Index > Position.Container.Last then
2707 raise Constraint_Error with "Position cursor is out of range";
2708 end if;
c9423ca3
AC
2709 end if;
2710
14f73211
BD
2711 declare
2712 TC : constant Tamper_Counts_Access :=
2713 Container.TC'Unrestricted_Access;
2714 begin
2715 -- The following will raise Constraint_Error if Element is null
2716
794b9b72 2717 return R : constant Reference_Type :=
e9f97e79 2718 (Element => Container.Elements.EA (Position.Index),
14f73211
BD
2719 Control => (Controlled with TC))
2720 do
2f26abcc 2721 Busy (TC.all);
14f73211
BD
2722 end return;
2723 end;
3e24afaa
AC
2724 end Reference;
2725
0b5b2bbc 2726 function Reference
c9423ca3
AC
2727 (Container : aliased in out Vector;
2728 Index : Index_Type) return Reference_Type
0b5b2bbc 2729 is
3e24afaa 2730 begin
e9f97e79 2731 if Checks and then Index > Container.Last then
3e24afaa
AC
2732 raise Constraint_Error with "Index is out of range";
2733 end if;
2734
14f73211
BD
2735 declare
2736 TC : constant Tamper_Counts_Access :=
2737 Container.TC'Unrestricted_Access;
2738 begin
2739 -- The following will raise Constraint_Error if Element is null
2740
794b9b72 2741 return R : constant Reference_Type :=
e9f97e79 2742 (Element => Container.Elements.EA (Index),
14f73211
BD
2743 Control => (Controlled with TC))
2744 do
2f26abcc 2745 Busy (TC.all);
14f73211
BD
2746 end return;
2747 end;
3e24afaa
AC
2748 end Reference;
2749
8704d4b3
MH
2750 ---------------------
2751 -- Replace_Element --
2752 ---------------------
4c2d6a70 2753
8704d4b3 2754 procedure Replace_Element
2368f04e 2755 (Container : in out Vector;
8704d4b3 2756 Index : Index_Type;
2368f04e 2757 New_Item : Element_Type)
8704d4b3 2758 is
4c2d6a70 2759 begin
e9f97e79 2760 if Checks and then Index > Container.Last then
dc6b9ba2 2761 raise Constraint_Error with "Index is out of range";
d43d5ef7
MH
2762 end if;
2763
e9f97e79 2764 TE_Check (Container.TC);
4c2d6a70 2765
d43d5ef7 2766 declare
f97ccb3a 2767 X : Element_Access := Container.Elements.EA (Index);
50878404 2768
50878404
AC
2769 -- The element allocator may need an accessibility check in the case
2770 -- where the actual type is class-wide or has access discriminants
2771 -- (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
2772
2773 pragma Unsuppress (Accessibility_Check);
2774
d43d5ef7 2775 begin
f97ccb3a 2776 Container.Elements.EA (Index) := new Element_Type'(New_Item);
d43d5ef7
MH
2777 Free (X);
2778 end;
8704d4b3 2779 end Replace_Element;
4c2d6a70 2780
2368f04e
MH
2781 procedure Replace_Element
2782 (Container : in out Vector;
2783 Position : Cursor;
2784 New_Item : Element_Type)
2785 is
8704d4b3 2786 begin
e9f97e79
AC
2787 if Checks then
2788 if Position.Container = null then
2789 raise Constraint_Error with "Position cursor has no element";
2790 end if;
d43d5ef7 2791
e9f97e79
AC
2792 if Position.Container /= Container'Unrestricted_Access then
2793 raise Program_Error with "Position cursor denotes wrong container";
2794 end if;
2368f04e 2795
e9f97e79
AC
2796 if Position.Index > Container.Last then
2797 raise Constraint_Error with "Position cursor is out of range";
2798 end if;
f97ccb3a
BD
2799 end if;
2800
e9f97e79 2801 TE_Check (Container.TC);
f97ccb3a
BD
2802
2803 declare
2804 X : Element_Access := Container.Elements.EA (Position.Index);
50878404 2805
50878404
AC
2806 -- The element allocator may need an accessibility check in the case
2807 -- where the actual type is class-wide or has access discriminants
2808 -- (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
2809
2810 pragma Unsuppress (Accessibility_Check);
2811
f97ccb3a
BD
2812 begin
2813 Container.Elements.EA (Position.Index) := new Element_Type'(New_Item);
2814 Free (X);
2815 end;
8704d4b3 2816 end Replace_Element;
4c2d6a70 2817
8704d4b3
MH
2818 ----------------------
2819 -- Reserve_Capacity --
2820 ----------------------
4c2d6a70 2821
8704d4b3
MH
2822 procedure Reserve_Capacity
2823 (Container : in out Vector;
2824 Capacity : Count_Type)
2825 is
2826 N : constant Count_Type := Length (Container);
4c2d6a70 2827
5bec9717
AC
2828 Index : Count_Type'Base;
2829 Last : Index_Type'Base;
2830
8704d4b3 2831 begin
5bec9717
AC
2832 -- Reserve_Capacity can be used to either expand the storage available
2833 -- for elements (this would be its typical use, in anticipation of
2834 -- future insertion), or to trim back storage. In the latter case,
2835 -- storage can only be trimmed back to the limit of the container
2836 -- length. Note that Reserve_Capacity neither deletes (active) elements
2837 -- nor inserts elements; it only affects container capacity, never
2838 -- container length.
2839
8704d4b3 2840 if Capacity = 0 then
0b5b2bbc 2841
5bec9717
AC
2842 -- This is a request to trim back storage, to the minimum amount
2843 -- possible given the current state of the container.
2844
8704d4b3 2845 if N = 0 then
0b5b2bbc 2846
5bec9717
AC
2847 -- The container is empty, so in this unique case we can
2848 -- deallocate the entire internal array. Note that an empty
2849 -- container can never be busy, so there's no need to check the
2850 -- tampering bits.
2851
4c2d6a70 2852 declare
8704d4b3 2853 X : Elements_Access := Container.Elements;
0b5b2bbc 2854
4c2d6a70 2855 begin
5bec9717
AC
2856 -- First we remove the internal array from the container, to
2857 -- handle the case when the deallocation raises an exception
2858 -- (although that's unlikely, since this is simply an array of
2859 -- access values, all of which are null).
2860
8704d4b3 2861 Container.Elements := null;
5bec9717
AC
2862
2863 -- Container invariants have been restored, so it is now safe
2864 -- to attempt to deallocate the internal array.
2865
8704d4b3 2866 Free (X);
4c2d6a70
AC
2867 end;
2868
f97ccb3a 2869 elsif N < Container.Elements.EA'Length then
0b5b2bbc 2870
5bec9717
AC
2871 -- The container is not empty, and the current length is less than
2872 -- the current capacity, so there's storage available to trim. In
2873 -- this case, we allocate a new internal array having a length
2874 -- that exactly matches the number of items in the
2875 -- container. (Reserve_Capacity does not delete active elements,
2876 -- so this is the best we can do with respect to minimizing
2877 -- storage).
2878
e9f97e79 2879 TC_Check (Container.TC);
8704d4b3 2880
4c2d6a70 2881 declare
8704d4b3
MH
2882 subtype Array_Index_Subtype is Index_Type'Base range
2883 Index_Type'First .. Container.Last;
4c2d6a70 2884
f97ccb3a
BD
2885 Src : Elements_Array renames
2886 Container.Elements.EA (Array_Index_Subtype);
8704d4b3
MH
2887
2888 X : Elements_Access := Container.Elements;
d43d5ef7 2889
8704d4b3 2890 begin
5bec9717
AC
2891 -- Although we have isolated the old internal array that we're
2892 -- going to deallocate, we don't deallocate it until we have
2893 -- successfully allocated a new one. If there is an exception
2894 -- during allocation (because there is not enough storage), we
2895 -- let it propagate without causing any side-effect.
2896
f97ccb3a 2897 Container.Elements := new Elements_Type'(Container.Last, Src);
5bec9717 2898
308e6f3a 2899 -- We have successfully allocated a new internal array (with a
5bec9717
AC
2900 -- smaller length than the old one, and containing a copy of
2901 -- just the active elements in the container), so we can
2902 -- deallocate the old array.
2903
8704d4b3 2904 Free (X);
4c2d6a70 2905 end;
8704d4b3 2906 end if;
4c2d6a70 2907
8704d4b3
MH
2908 return;
2909 end if;
4c2d6a70 2910
5bec9717
AC
2911 -- Reserve_Capacity can be used to expand the storage available for
2912 -- elements, but we do not let the capacity grow beyond the number of
2913 -- values in Index_Type'Range. (Were it otherwise, there would be no way
2914 -- to refer to the elements with index values greater than
2915 -- Index_Type'Last, so that storage would be wasted.) Here we compute
2916 -- the Last index value of the new internal array, in a way that avoids
2917 -- any possibility of overflow.
2918
e9f97e79 2919 if Index_Type'Base'Last >= Count_Type_Last then
0b5b2bbc 2920
5bec9717
AC
2921 -- We perform a two-part test. First we determine whether the
2922 -- computed Last value lies in the base range of the type, and then
2923 -- determine whether it lies in the range of the index (sub)type.
2924
2925 -- Last must satisfy this relation:
2926 -- First + Length - 1 <= Last
2927 -- We regroup terms:
2928 -- First - 1 <= Last - Length
2929 -- Which can rewrite as:
2930 -- No_Index <= Last - Length
2931
e9f97e79
AC
2932 if Checks and then
2933 Index_Type'Base'Last - Index_Type'Base (Capacity) < No_Index
2934 then
5bec9717
AC
2935 raise Constraint_Error with "Capacity is out of range";
2936 end if;
4c2d6a70 2937
5bec9717
AC
2938 -- We now know that the computed value of Last is within the base
2939 -- range of the type, so it is safe to compute its value:
4c2d6a70 2940
5bec9717 2941 Last := No_Index + Index_Type'Base (Capacity);
4c2d6a70 2942
5bec9717
AC
2943 -- Finally we test whether the value is within the range of the
2944 -- generic actual index subtype:
2945
e9f97e79 2946 if Checks and then Last > Index_Type'Last then
5bec9717
AC
2947 raise Constraint_Error with "Capacity is out of range";
2948 end if;
2949
2950 elsif Index_Type'First <= 0 then
0b5b2bbc 2951
5bec9717
AC
2952 -- Here we can compute Last directly, in the normal way. We know that
2953 -- No_Index is less than 0, so there is no danger of overflow when
2954 -- adding the (positive) value of Capacity.
2955
2956 Index := Count_Type'Base (No_Index) + Capacity; -- Last
2957
e9f97e79 2958 if Checks and then Index > Count_Type'Base (Index_Type'Last) then
5bec9717
AC
2959 raise Constraint_Error with "Capacity is out of range";
2960 end if;
2961
2962 -- We know that the computed value (having type Count_Type) of Last
2963 -- is within the range of the generic actual index subtype, so it is
2964 -- safe to convert to Index_Type:
2965
2966 Last := Index_Type'Base (Index);
2967
2968 else
2969 -- Here Index_Type'First (and Index_Type'Last) is positive, so we
2970 -- must test the length indirectly (by working backwards from the
2971 -- largest possible value of Last), in order to prevent overflow.
2972
2973 Index := Count_Type'Base (Index_Type'Last) - Capacity; -- No_Index
2974
e9f97e79 2975 if Checks and then Index < Count_Type'Base (No_Index) then
5bec9717
AC
2976 raise Constraint_Error with "Capacity is out of range";
2977 end if;
4c2d6a70 2978
5bec9717
AC
2979 -- We have determined that the value of Capacity would not create a
2980 -- Last index value outside of the range of Index_Type, so we can now
2981 -- safely compute its value.
2982
2983 Last := Index_Type'Base (Count_Type'Base (No_Index) + Capacity);
2984 end if;
2985
2986 -- The requested capacity is non-zero, but we don't know yet whether
2987 -- this is a request for expansion or contraction of storage.
2988
2989 if Container.Elements = null then
0b5b2bbc 2990
5bec9717
AC
2991 -- The container is empty (it doesn't even have an internal array),
2992 -- so this represents a request to allocate storage having the given
2993 -- capacity.
2994
2995 Container.Elements := new Elements_Type (Last);
4c2d6a70
AC
2996 return;
2997 end if;
2998
8704d4b3 2999 if Capacity <= N then
0b5b2bbc 3000
5bec9717
AC
3001 -- This is a request to trim back storage, but only to the limit of
3002 -- what's already in the container. (Reserve_Capacity never deletes
3003 -- active elements, it only reclaims excess storage.)
3004
f97ccb3a 3005 if N < Container.Elements.EA'Length then
0b5b2bbc 3006
5bec9717
AC
3007 -- The container is not empty (because the requested capacity is
3008 -- positive, and less than or equal to the container length), and
0b5b2bbc
AC
3009 -- the current length is less than the current capacity, so there
3010 -- is storage available to trim. In this case, we allocate a new
3011 -- internal array having a length that exactly matches the number
3012 -- of items in the container.
5bec9717 3013
e9f97e79 3014 TC_Check (Container.TC);
4c2d6a70 3015
8704d4b3
MH
3016 declare
3017 subtype Array_Index_Subtype is Index_Type'Base range
3018 Index_Type'First .. Container.Last;
4c2d6a70 3019
f97ccb3a
BD
3020 Src : Elements_Array renames
3021 Container.Elements.EA (Array_Index_Subtype);
4c2d6a70 3022
8704d4b3 3023 X : Elements_Access := Container.Elements;
4c2d6a70 3024
8704d4b3 3025 begin
5bec9717
AC
3026 -- Although we have isolated the old internal array that we're
3027 -- going to deallocate, we don't deallocate it until we have
3028 -- successfully allocated a new one. If there is an exception
3029 -- during allocation (because there is not enough storage), we
3030 -- let it propagate without causing any side-effect.
3031
f97ccb3a 3032 Container.Elements := new Elements_Type'(Container.Last, Src);
5bec9717 3033
308e6f3a 3034 -- We have successfully allocated a new internal array (with a
5bec9717
AC
3035 -- smaller length than the old one, and containing a copy of
3036 -- just the active elements in the container), so it is now
3037 -- safe to deallocate the old array.
3038
8704d4b3
MH
3039 Free (X);
3040 end;
4c2d6a70
AC
3041 end if;
3042
3043 return;
4c2d6a70
AC
3044 end if;
3045
5bec9717
AC
3046 -- The requested capacity is larger than the container length (the
3047 -- number of active elements). Whether this represents a request for
3048 -- expansion or contraction of the current capacity depends on what the
3049 -- current capacity is.
3050
f97ccb3a 3051 if Capacity = Container.Elements.EA'Length then
0b5b2bbc 3052
5bec9717
AC
3053 -- The requested capacity matches the existing capacity, so there's
3054 -- nothing to do here. We treat this case as a no-op, and simply
3055 -- return without checking the busy bit.
3056
8704d4b3 3057 return;
4c2d6a70
AC
3058 end if;
3059
5bec9717
AC
3060 -- There is a change in the capacity of a non-empty container, so a new
3061 -- internal array will be allocated. (The length of the new internal
3062 -- array could be less or greater than the old internal array. We know
3063 -- only that the length of the new internal array is greater than the
3064 -- number of active elements in the container.) We must check whether
3065 -- the container is busy before doing anything else.
3066
e9f97e79 3067 TC_Check (Container.TC);
4c2d6a70 3068
5bec9717
AC
3069 -- We now allocate a new internal array, having a length different from
3070 -- its current value.
4c2d6a70 3071
5bec9717
AC
3072 declare
3073 X : Elements_Access := Container.Elements;
4c2d6a70 3074
5bec9717
AC
3075 subtype Index_Subtype is Index_Type'Base range
3076 Index_Type'First .. Container.Last;
4c2d6a70 3077
5bec9717
AC
3078 begin
3079 -- We now allocate a new internal array, having a length different
3080 -- from its current value.
4c2d6a70 3081
5bec9717 3082 Container.Elements := new Elements_Type (Last);
4c2d6a70 3083
5bec9717
AC
3084 -- We have successfully allocated the new internal array, so now we
3085 -- move the existing elements from the existing the old internal
3086 -- array onto the new one. Note that we're just copying access
3087 -- values, to this should not raise any exceptions.
d43d5ef7 3088
5bec9717 3089 Container.Elements.EA (Index_Subtype) := X.EA (Index_Subtype);
d43d5ef7 3090
308e6f3a 3091 -- We have moved the elements from the old internal array, so now we
5bec9717 3092 -- can deallocate it.
d43d5ef7 3093
5bec9717 3094 Free (X);
8704d4b3
MH
3095 end;
3096 end Reserve_Capacity;
4c2d6a70 3097
2368f04e
MH
3098 ----------------------
3099 -- Reverse_Elements --
3100 ----------------------
3101
3102 procedure Reverse_Elements (Container : in out Vector) is
3103 begin
3104 if Container.Length <= 1 then
3105 return;
3106 end if;
3107
b727a82b
AC
3108 -- The exception behavior for the vector container must match that for
3109 -- the list container, so we check for cursor tampering here (which will
3110 -- catch more things) instead of for element tampering (which will catch
3111 -- fewer things). It's true that the elements of this vector container
3112 -- could be safely moved around while (say) an iteration is taking place
794b9b72
AC
3113 -- (iteration only increments the busy counter), and so technically all
3114 -- we would need here is a test for element tampering (indicated by the
3115 -- lock counter), that's simply an artifact of our array-based
b727a82b
AC
3116 -- implementation. Logically Reverse_Elements requires a check for
3117 -- cursor tampering.
3118
e9f97e79 3119 TC_Check (Container.TC);
2368f04e
MH
3120
3121 declare
dc6b9ba2
MH
3122 I : Index_Type;
3123 J : Index_Type;
f97ccb3a 3124 E : Elements_Array renames Container.Elements.EA;
2368f04e
MH
3125
3126 begin
dc6b9ba2
MH
3127 I := Index_Type'First;
3128 J := Container.Last;
2368f04e
MH
3129 while I < J loop
3130 declare
3131 EI : constant Element_Access := E (I);
3132
3133 begin
3134 E (I) := E (J);
3135 E (J) := EI;
3136 end;
3137
3138 I := I + 1;
3139 J := J - 1;
3140 end loop;
3141 end;
3142 end Reverse_Elements;
3143
8704d4b3
MH
3144 ------------------
3145 -- Reverse_Find --
3146 ------------------
4c2d6a70 3147
8704d4b3
MH
3148 function Reverse_Find
3149 (Container : Vector;
3150 Item : Element_Type;
3151 Position : Cursor := No_Element) return Cursor
3152 is
3153 Last : Index_Type'Base;
4c2d6a70 3154
8704d4b3 3155 begin
e9f97e79 3156 if Checks and then Position.Container /= null
ef992452 3157 and then Position.Container /= Container'Unrestricted_Access
8704d4b3 3158 then
dc6b9ba2 3159 raise Program_Error with "Position cursor denotes wrong container";
4c2d6a70
AC
3160 end if;
3161
e9f97e79
AC
3162 Last :=
3163 (if Position.Container = null or else Position.Index > Container.Last
3164 then Container.Last
3165 else Position.Index);
4c2d6a70 3166
2602b64e
AC
3167 -- Per AI05-0022, the container implementation is required to detect
3168 -- element tampering by a generic actual subprogram.
3169
3170 declare
e9f97e79 3171 Lock : With_Lock (Container.TC'Unrestricted_Access);
2602b64e 3172 begin
2602b64e
AC
3173 for Indx in reverse Index_Type'First .. Last loop
3174 if Container.Elements.EA (Indx) /= null
3175 and then Container.Elements.EA (Indx).all = Item
3176 then
e9f97e79 3177 return Cursor'(Container'Unrestricted_Access, Indx);
2602b64e
AC
3178 end if;
3179 end loop;
3180
e9f97e79 3181 return No_Element;
2602b64e 3182 end;
8704d4b3 3183 end Reverse_Find;
4c2d6a70 3184
8704d4b3
MH
3185 ------------------------
3186 -- Reverse_Find_Index --
3187 ------------------------
4c2d6a70 3188
8704d4b3
MH
3189 function Reverse_Find_Index
3190 (Container : Vector;
3191 Item : Element_Type;
3192 Index : Index_Type := Index_Type'Last) return Extended_Index
3193 is
2602b64e
AC
3194 -- Per AI05-0022, the container implementation is required to detect
3195 -- element tampering by a generic actual subprogram.
3196
e9f97e79
AC
3197 Lock : With_Lock (Container.TC'Unrestricted_Access);
3198
3199 Last : constant Index_Type'Base :=
3200 Index_Type'Min (Container.Last, Index);
2602b64e 3201
e9f97e79 3202 begin
8704d4b3 3203 for Indx in reverse Index_Type'First .. Last loop
f97ccb3a
BD
3204 if Container.Elements.EA (Indx) /= null
3205 and then Container.Elements.EA (Indx).all = Item
8704d4b3 3206 then
e9f97e79 3207 return Indx;
8704d4b3
MH
3208 end if;
3209 end loop;
4c2d6a70 3210
e9f97e79 3211 return No_Index;
8704d4b3 3212 end Reverse_Find_Index;
4c2d6a70 3213
8704d4b3
MH
3214 ---------------------
3215 -- Reverse_Iterate --
3216 ---------------------
4c2d6a70 3217
8704d4b3
MH
3218 procedure Reverse_Iterate
3219 (Container : Vector;
0ae9f22f 3220 Process : not null access procedure (Position : Cursor))
8704d4b3 3221 is
e9f97e79 3222 Busy : With_Busy (Container.TC'Unrestricted_Access);
8704d4b3 3223 begin
e9f97e79
AC
3224 for Indx in reverse Index_Type'First .. Container.Last loop
3225 Process (Cursor'(Container'Unrestricted_Access, Indx));
3226 end loop;
8704d4b3 3227 end Reverse_Iterate;
4c2d6a70 3228
8704d4b3
MH
3229 ----------------
3230 -- Set_Length --
3231 ----------------
4c2d6a70 3232
e9f97e79 3233 procedure Set_Length (Container : in out Vector; Length : Count_Type) is
5bec9717 3234 Count : constant Count_Type'Base := Container.Length - Length;
4c2d6a70
AC
3235
3236 begin
5bec9717
AC
3237 -- Set_Length allows the user to set the length explicitly, instead of
3238 -- implicitly as a side-effect of deletion or insertion. If the
3239 -- requested length is less than the current length, this is equivalent
3240 -- to deleting items from the back end of the vector. If the requested
3241 -- length is greater than the current length, then this is equivalent to
3242 -- inserting "space" (nonce items) at the end.
4c2d6a70 3243
5bec9717
AC
3244 if Count >= 0 then
3245 Container.Delete_Last (Count);
d43d5ef7 3246
e9f97e79 3247 elsif Checks and then Container.Last >= Index_Type'Last then
5bec9717 3248 raise Constraint_Error with "vector is already at its maximum length";
d43d5ef7 3249
5bec9717
AC
3250 else
3251 Container.Insert_Space (Container.Last + 1, -Count);
d43d5ef7 3252 end if;
8704d4b3 3253 end Set_Length;
4c2d6a70 3254
8704d4b3
MH
3255 ----------
3256 -- Swap --
3257 ----------
4c2d6a70 3258
e9f97e79 3259 procedure Swap (Container : in out Vector; I, J : Index_Type) is
d43d5ef7 3260 begin
e9f97e79
AC
3261 if Checks then
3262 if I > Container.Last then
3263 raise Constraint_Error with "I index is out of range";
3264 end if;
dc6b9ba2 3265
e9f97e79
AC
3266 if J > Container.Last then
3267 raise Constraint_Error with "J index is out of range";
3268 end if;
d43d5ef7 3269 end if;
4c2d6a70 3270
d43d5ef7
MH
3271 if I = J then
3272 return;
3273 end if;
4c2d6a70 3274
e9f97e79 3275 TE_Check (Container.TC);
4c2d6a70 3276
8704d4b3 3277 declare
f97ccb3a
BD
3278 EI : Element_Access renames Container.Elements.EA (I);
3279 EJ : Element_Access renames Container.Elements.EA (J);
d43d5ef7
MH
3280
3281 EI_Copy : constant Element_Access := EI;
3282
8704d4b3
MH
3283 begin
3284 EI := EJ;
3285 EJ := EI_Copy;
3286 end;
3287 end Swap;
3288
2368f04e
MH
3289 procedure Swap
3290 (Container : in out Vector;
3291 I, J : Cursor)
8704d4b3
MH
3292 is
3293 begin
e9f97e79
AC
3294 if Checks then
3295 if I.Container = null then
3296 raise Constraint_Error with "I cursor has no element";
3297 end if;
4c2d6a70 3298
e9f97e79
AC
3299 if J.Container = null then
3300 raise Constraint_Error with "J cursor has no element";
3301 end if;
dc6b9ba2 3302
e9f97e79
AC
3303 if I.Container /= Container'Unrestricted_Access then
3304 raise Program_Error with "I cursor denotes wrong container";
3305 end if;
dc6b9ba2 3306
e9f97e79
AC
3307 if J.Container /= Container'Unrestricted_Access then
3308 raise Program_Error with "J cursor denotes wrong container";
3309 end if;
4c2d6a70
AC
3310 end if;
3311
2368f04e 3312 Swap (Container, I.Index, J.Index);
8704d4b3 3313 end Swap;
4c2d6a70 3314
8704d4b3
MH
3315 ---------------
3316 -- To_Cursor --
3317 ---------------
4c2d6a70 3318
8704d4b3
MH
3319 function To_Cursor
3320 (Container : Vector;
3321 Index : Extended_Index) return Cursor
3322 is
4c2d6a70 3323 begin
8704d4b3 3324 if Index not in Index_Type'First .. Container.Last then
4c2d6a70
AC
3325 return No_Element;
3326 end if;
3327
ef992452 3328 return Cursor'(Container'Unrestricted_Access, Index);
8704d4b3 3329 end To_Cursor;
4c2d6a70 3330
8704d4b3
MH
3331 --------------
3332 -- To_Index --
3333 --------------
4c2d6a70 3334
8704d4b3 3335 function To_Index (Position : Cursor) return Extended_Index is
4c2d6a70 3336 begin
8704d4b3
MH
3337 if Position.Container = null then
3338 return No_Index;
2602b64e 3339 elsif Position.Index <= Position.Container.Last then
8704d4b3 3340 return Position.Index;
2602b64e
AC
3341 else
3342 return No_Index;
8704d4b3 3343 end if;
8704d4b3 3344 end To_Index;
4c2d6a70 3345
8704d4b3
MH
3346 ---------------
3347 -- To_Vector --
3348 ---------------
4c2d6a70 3349
8704d4b3 3350 function To_Vector (Length : Count_Type) return Vector is
5bec9717
AC
3351 Index : Count_Type'Base;
3352 Last : Index_Type'Base;
8255bc9d
AC
3353 Elements : Elements_Access;
3354
8704d4b3
MH
3355 begin
3356 if Length = 0 then
3357 return Empty_Vector;
3358 end if;
4c2d6a70 3359
8255bc9d 3360 -- We create a vector object with a capacity that matches the specified
5bec9717 3361 -- Length, but we do not allow the vector capacity (the length of the
8255bc9d
AC
3362 -- internal array) to exceed the number of values in Index_Type'Range
3363 -- (otherwise, there would be no way to refer to those components via an
5bec9717
AC
3364 -- index). We must therefore check whether the specified Length would
3365 -- create a Last index value greater than Index_Type'Last.
3366
e9f97e79 3367 if Index_Type'Base'Last >= Count_Type_Last then
0b5b2bbc 3368
5bec9717
AC
3369 -- We perform a two-part test. First we determine whether the
3370 -- computed Last value lies in the base range of the type, and then
3371 -- determine whether it lies in the range of the index (sub)type.
3372
3373 -- Last must satisfy this relation:
3374 -- First + Length - 1 <= Last
3375 -- We regroup terms:
3376 -- First - 1 <= Last - Length
3377 -- Which can rewrite as:
3378 -- No_Index <= Last - Length
3379
e9f97e79
AC
3380 if Checks and then
3381 Index_Type'Base'Last - Index_Type'Base (Length) < No_Index
3382 then
dc6b9ba2 3383 raise Constraint_Error with "Length is out of range";
d43d5ef7
MH
3384 end if;
3385
5bec9717
AC
3386 -- We now know that the computed value of Last is within the base
3387 -- range of the type, so it is safe to compute its value:
3388
3389 Last := No_Index + Index_Type'Base (Length);
3390
3391 -- Finally we test whether the value is within the range of the
3392 -- generic actual index subtype:
3393
e9f97e79 3394 if Checks and then Last > Index_Type'Last then
5bec9717
AC
3395 raise Constraint_Error with "Length is out of range";
3396 end if;
3397
3398 elsif Index_Type'First <= 0 then
0b5b2bbc 3399
5bec9717
AC
3400 -- Here we can compute Last directly, in the normal way. We know that
3401 -- No_Index is less than 0, so there is no danger of overflow when
3402 -- adding the (positive) value of Length.
3403
3404 Index := Count_Type'Base (No_Index) + Length; -- Last
3405
e9f97e79 3406 if Checks and then Index > Count_Type'Base (Index_Type'Last) then
5bec9717
AC
3407 raise Constraint_Error with "Length is out of range";
3408 end if;
3409
3410 -- We know that the computed value (having type Count_Type) of Last
3411 -- is within the range of the generic actual index subtype, so it is
3412 -- safe to convert to Index_Type:
3413
3414 Last := Index_Type'Base (Index);
3415
8255bc9d 3416 else
5bec9717
AC
3417 -- Here Index_Type'First (and Index_Type'Last) is positive, so we
3418 -- must test the length indirectly (by working backwards from the
3419 -- largest possible value of Last), in order to prevent overflow.
3420
3421 Index := Count_Type'Base (Index_Type'Last) - Length; -- No_Index
3422
e9f97e79 3423 if Checks and then Index < Count_Type'Base (No_Index) then
8255bc9d
AC
3424 raise Constraint_Error with "Length is out of range";
3425 end if;
d43d5ef7 3426
5bec9717
AC
3427 -- We have determined that the value of Length would not create a
3428 -- Last index value outside of the range of Index_Type, so we can now
3429 -- safely compute its value.
3430
3431 Last := Index_Type'Base (Count_Type'Base (No_Index) + Length);
8255bc9d
AC
3432 end if;
3433
8255bc9d
AC
3434 Elements := new Elements_Type (Last);
3435
e9f97e79 3436 return Vector'(Controlled with Elements, Last, TC => <>);
8704d4b3 3437 end To_Vector;
4c2d6a70 3438
8704d4b3
MH
3439 function To_Vector
3440 (New_Item : Element_Type;
3441 Length : Count_Type) return Vector
3442 is
5bec9717
AC
3443 Index : Count_Type'Base;
3444 Last : Index_Type'Base;
8255bc9d
AC
3445 Elements : Elements_Access;
3446
8704d4b3
MH
3447 begin
3448 if Length = 0 then
3449 return Empty_Vector;
3450 end if;
4c2d6a70 3451
8255bc9d 3452 -- We create a vector object with a capacity that matches the specified
5bec9717 3453 -- Length, but we do not allow the vector capacity (the length of the
8255bc9d
AC
3454 -- internal array) to exceed the number of values in Index_Type'Range
3455 -- (otherwise, there would be no way to refer to those components via an
5bec9717
AC
3456 -- index). We must therefore check whether the specified Length would
3457 -- create a Last index value greater than Index_Type'Last.
3458
e9f97e79 3459 if Index_Type'Base'Last >= Count_Type_Last then
0b5b2bbc 3460
5bec9717
AC
3461 -- We perform a two-part test. First we determine whether the
3462 -- computed Last value lies in the base range of the type, and then
3463 -- determine whether it lies in the range of the index (sub)type.
3464
3465 -- Last must satisfy this relation:
3466 -- First + Length - 1 <= Last
3467 -- We regroup terms:
3468 -- First - 1 <= Last - Length
3469 -- Which can rewrite as:
3470 -- No_Index <= Last - Length
3471
e9f97e79
AC
3472 if Checks and then
3473 Index_Type'Base'Last - Index_Type'Base (Length) < No_Index
3474 then
dc6b9ba2 3475 raise Constraint_Error with "Length is out of range";
d43d5ef7 3476 end if;
4c2d6a70 3477
5bec9717
AC
3478 -- We now know that the computed value of Last is within the base
3479 -- range of the type, so it is safe to compute its value:
3480
3481 Last := No_Index + Index_Type'Base (Length);
3482
3483 -- Finally we test whether the value is within the range of the
3484 -- generic actual index subtype:
3485
e9f97e79 3486 if Checks and then Last > Index_Type'Last then
5bec9717
AC
3487 raise Constraint_Error with "Length is out of range";
3488 end if;
3489
3490 elsif Index_Type'First <= 0 then
0b5b2bbc 3491
5bec9717
AC
3492 -- Here we can compute Last directly, in the normal way. We know that
3493 -- No_Index is less than 0, so there is no danger of overflow when
3494 -- adding the (positive) value of Length.
3495
3496 Index := Count_Type'Base (No_Index) + Length; -- Last
3497
e9f97e79 3498 if Checks and then Index > Count_Type'Base (Index_Type'Last) then
5bec9717
AC
3499 raise Constraint_Error with "Length is out of range";
3500 end if;
3501
3502 -- We know that the computed value (having type Count_Type) of Last
3503 -- is within the range of the generic actual index subtype, so it is
3504 -- safe to convert to Index_Type:
3505
3506 Last := Index_Type'Base (Index);
3507
8255bc9d 3508 else
5bec9717
AC
3509 -- Here Index_Type'First (and Index_Type'Last) is positive, so we
3510 -- must test the length indirectly (by working backwards from the
3511 -- largest possible value of Last), in order to prevent overflow.
3512
3513 Index := Count_Type'Base (Index_Type'Last) - Length; -- No_Index
3514
e9f97e79 3515 if Checks and then Index < Count_Type'Base (No_Index) then
8255bc9d
AC
3516 raise Constraint_Error with "Length is out of range";
3517 end if;
4c2d6a70 3518
5bec9717
AC
3519 -- We have determined that the value of Length would not create a
3520 -- Last index value outside of the range of Index_Type, so we can now
3521 -- safely compute its value.
3522
3523 Last := Index_Type'Base (Count_Type'Base (No_Index) + Length);
8255bc9d 3524 end if;
d43d5ef7 3525
8255bc9d 3526 Elements := new Elements_Type (Last);
f97ccb3a 3527
8255bc9d
AC
3528 -- We use Last as the index of the loop used to populate the internal
3529 -- array with items. In general, we prefer to initialize the loop index
3530 -- immediately prior to entering the loop. However, Last is also used in
5bec9717 3531 -- the exception handler (to reclaim elements that have been allocated,
8255bc9d
AC
3532 -- before propagating the exception), and the initialization of Last
3533 -- after entering the block containing the handler confuses some static
3534 -- analysis tools, with respect to whether Last has been properly
3535 -- initialized when the handler executes. So here we initialize our loop
3536 -- variable earlier than we prefer, before entering the block, so there
3537 -- is no ambiguity.
0b5b2bbc 3538
8255bc9d 3539 Last := Index_Type'First;
d43d5ef7 3540
50878404 3541 declare
50878404
AC
3542 -- The element allocator may need an accessibility check in the case
3543 -- where the actual type is class-wide or has access discriminants
3544 -- (see RM 4.8(10.1) and AI12-0035).
29ba9f52
RD
3545
3546 pragma Unsuppress (Accessibility_Check);
3547
8255bc9d
AC
3548 begin
3549 loop
3550 Elements.EA (Last) := new Element_Type'(New_Item);
3551 exit when Last = Elements.Last;
3552 Last := Last + 1;
3553 end loop;
4c2d6a70 3554
8255bc9d
AC
3555 exception
3556 when others =>
3557 for J in Index_Type'First .. Last - 1 loop
3558 Free (Elements.EA (J));
3559 end loop;
3560
3561 Free (Elements);
3562 raise;
8704d4b3 3563 end;
8255bc9d 3564
e9f97e79 3565 return (Controlled with Elements, Last, TC => <>);
8704d4b3 3566 end To_Vector;
4c2d6a70 3567
8704d4b3
MH
3568 --------------------
3569 -- Update_Element --
3570 --------------------
4c2d6a70 3571
8704d4b3 3572 procedure Update_Element
2368f04e 3573 (Container : in out Vector;
8704d4b3
MH
3574 Index : Index_Type;
3575 Process : not null access procedure (Element : in out Element_Type))
3576 is
e9f97e79 3577 Lock : With_Lock (Container.TC'Unchecked_Access);
4c2d6a70 3578 begin
e9f97e79 3579 if Checks and then Index > Container.Last then
dc6b9ba2 3580 raise Constraint_Error with "Index is out of range";
d43d5ef7
MH
3581 end if;
3582
e9f97e79 3583 if Checks and then Container.Elements.EA (Index) = null then
dc6b9ba2 3584 raise Constraint_Error with "element is null";
2368f04e
MH
3585 end if;
3586
e9f97e79 3587 Process (Container.Elements.EA (Index).all);
8704d4b3 3588 end Update_Element;
4c2d6a70 3589
8704d4b3 3590 procedure Update_Element
2368f04e
MH
3591 (Container : in out Vector;
3592 Position : Cursor;
3593 Process : not null access procedure (Element : in out Element_Type))
8704d4b3
MH
3594 is
3595 begin
e9f97e79
AC
3596 if Checks then
3597 if Position.Container = null then
3598 raise Constraint_Error with "Position cursor has no element";
3599 elsif Position.Container /= Container'Unrestricted_Access then
3600 raise Program_Error with "Position cursor denotes wrong container";
3601 end if;
2602b64e 3602 end if;
e9f97e79
AC
3603
3604 Update_Element (Container, Position.Index, Process);
8704d4b3 3605 end Update_Element;
4c2d6a70 3606
8704d4b3
MH
3607 -----------
3608 -- Write --
3609 -----------
4c2d6a70 3610
8704d4b3 3611 procedure Write
dc6b9ba2 3612 (Stream : not null access Root_Stream_Type'Class;
8704d4b3
MH
3613 Container : Vector)
3614 is
3615 N : constant Count_Type := Length (Container);
4c2d6a70
AC
3616
3617 begin
8704d4b3 3618 Count_Type'Base'Write (Stream, N);
4c2d6a70 3619
8704d4b3
MH
3620 if N = 0 then
3621 return;
4c2d6a70
AC
3622 end if;
3623
8704d4b3 3624 declare
f97ccb3a 3625 E : Elements_Array renames Container.Elements.EA;
4c2d6a70 3626
8704d4b3
MH
3627 begin
3628 for Indx in Index_Type'First .. Container.Last loop
8704d4b3
MH
3629 if E (Indx) = null then
3630 Boolean'Write (Stream, False);
3631 else
3632 Boolean'Write (Stream, True);
3633 Element_Type'Output (Stream, E (Indx).all);
3634 end if;
3635 end loop;
3636 end;
3637 end Write;
4c2d6a70 3638
2368f04e 3639 procedure Write
dc6b9ba2 3640 (Stream : not null access Root_Stream_Type'Class;
2368f04e
MH
3641 Position : Cursor)
3642 is
3643 begin
dc6b9ba2 3644 raise Program_Error with "attempt to stream vector cursor";
2368f04e
MH
3645 end Write;
3646
3e24afaa
AC
3647 procedure Write
3648 (Stream : not null access Root_Stream_Type'Class;
3649 Item : Reference_Type)
3650 is
3651 begin
3652 raise Program_Error with "attempt to stream reference";
3653 end Write;
3654
3655 procedure Write
3656 (Stream : not null access Root_Stream_Type'Class;
3657 Item : Constant_Reference_Type)
3658 is
3659 begin
3660 raise Program_Error with "attempt to stream reference";
3661 end Write;
3662
4c2d6a70 3663end Ada.Containers.Indefinite_Vectors;