fixing pr42337
[official-gcc.git] / gcc / ada / a-convec.adb
blob64b1b07d9273e88dbafaa33713d34bac581407a5
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . V E C T O R S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2009, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
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/>. --
26 -- --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada.Containers.Generic_Array_Sort;
31 with Ada.Unchecked_Deallocation;
33 with System; use type System.Address;
35 package body Ada.Containers.Vectors is
37 type Int is range System.Min_Int .. System.Max_Int;
38 type UInt is mod System.Max_Binary_Modulus;
40 procedure Free is
41 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
43 ---------
44 -- "&" --
45 ---------
47 function "&" (Left, Right : Vector) return Vector is
48 LN : constant Count_Type := Length (Left);
49 RN : constant Count_Type := Length (Right);
51 begin
52 if LN = 0 then
53 if RN = 0 then
54 return Empty_Vector;
55 end if;
57 declare
58 RE : Elements_Array renames
59 Right.Elements.EA (Index_Type'First .. Right.Last);
61 Elements : constant Elements_Access :=
62 new Elements_Type'(Right.Last, RE);
64 begin
65 return (Controlled with Elements, Right.Last, 0, 0);
66 end;
67 end if;
69 if RN = 0 then
70 declare
71 LE : Elements_Array renames
72 Left.Elements.EA (Index_Type'First .. Left.Last);
74 Elements : constant Elements_Access :=
75 new Elements_Type'(Left.Last, LE);
77 begin
78 return (Controlled with Elements, Left.Last, 0, 0);
79 end;
81 end if;
83 declare
84 N : constant Int'Base := Int (LN) + Int (RN);
85 Last_As_Int : Int'Base;
87 begin
88 if Int (No_Index) > Int'Last - N then
89 raise Constraint_Error with "new length is out of range";
90 end if;
92 Last_As_Int := Int (No_Index) + N;
94 if Last_As_Int > Int (Index_Type'Last) then
95 raise Constraint_Error with "new length is out of range";
96 end if;
98 declare
99 Last : constant Index_Type := Index_Type (Last_As_Int);
101 LE : Elements_Array renames
102 Left.Elements.EA (Index_Type'First .. Left.Last);
104 RE : Elements_Array renames
105 Right.Elements.EA (Index_Type'First .. Right.Last);
107 Elements : constant Elements_Access :=
108 new Elements_Type'(Last, LE & RE);
110 begin
111 return (Controlled with Elements, Last, 0, 0);
112 end;
113 end;
114 end "&";
116 function "&" (Left : Vector; Right : Element_Type) return Vector is
117 LN : constant Count_Type := Length (Left);
119 begin
120 if LN = 0 then
121 declare
122 Elements : constant Elements_Access :=
123 new Elements_Type'
124 (Last => Index_Type'First,
125 EA => (others => Right));
127 begin
128 return (Controlled with Elements, Index_Type'First, 0, 0);
129 end;
130 end if;
132 declare
133 Last_As_Int : Int'Base;
135 begin
136 if Int (Index_Type'First) > Int'Last - Int (LN) then
137 raise Constraint_Error with "new length is out of range";
138 end if;
140 Last_As_Int := Int (Index_Type'First) + Int (LN);
142 if Last_As_Int > Int (Index_Type'Last) then
143 raise Constraint_Error with "new length is out of range";
144 end if;
146 declare
147 Last : constant Index_Type := Index_Type (Last_As_Int);
149 LE : Elements_Array renames
150 Left.Elements.EA (Index_Type'First .. Left.Last);
152 Elements : constant Elements_Access :=
153 new Elements_Type'
154 (Last => Last,
155 EA => LE & Right);
157 begin
158 return (Controlled with Elements, Last, 0, 0);
159 end;
160 end;
161 end "&";
163 function "&" (Left : Element_Type; Right : Vector) return Vector is
164 RN : constant Count_Type := Length (Right);
166 begin
167 if RN = 0 then
168 declare
169 Elements : constant Elements_Access :=
170 new Elements_Type'
171 (Last => Index_Type'First,
172 EA => (others => Left));
174 begin
175 return (Controlled with Elements, Index_Type'First, 0, 0);
176 end;
177 end if;
179 declare
180 Last_As_Int : Int'Base;
182 begin
183 if Int (Index_Type'First) > Int'Last - Int (RN) then
184 raise Constraint_Error with "new length is out of range";
185 end if;
187 Last_As_Int := Int (Index_Type'First) + Int (RN);
189 if Last_As_Int > Int (Index_Type'Last) then
190 raise Constraint_Error with "new length is out of range";
191 end if;
193 declare
194 Last : constant Index_Type := Index_Type (Last_As_Int);
196 RE : Elements_Array renames
197 Right.Elements.EA (Index_Type'First .. Right.Last);
199 Elements : constant Elements_Access :=
200 new Elements_Type'
201 (Last => Last,
202 EA => Left & RE);
204 begin
205 return (Controlled with Elements, Last, 0, 0);
206 end;
207 end;
208 end "&";
210 function "&" (Left, Right : Element_Type) return Vector is
211 begin
212 if Index_Type'First >= Index_Type'Last then
213 raise Constraint_Error with "new length is out of range";
214 end if;
216 declare
217 Last : constant Index_Type := Index_Type'First + 1;
219 Elements : constant Elements_Access :=
220 new Elements_Type'
221 (Last => Last,
222 EA => (Left, Right));
224 begin
225 return (Controlled with Elements, Last, 0, 0);
226 end;
227 end "&";
229 ---------
230 -- "=" --
231 ---------
233 overriding function "=" (Left, Right : Vector) return Boolean is
234 begin
235 if Left'Address = Right'Address then
236 return True;
237 end if;
239 if Left.Last /= Right.Last then
240 return False;
241 end if;
243 for J in Index_Type range Index_Type'First .. Left.Last loop
244 if Left.Elements.EA (J) /= Right.Elements.EA (J) then
245 return False;
246 end if;
247 end loop;
249 return True;
250 end "=";
252 ------------
253 -- Adjust --
254 ------------
256 procedure Adjust (Container : in out Vector) is
257 begin
258 if Container.Last = No_Index then
259 Container.Elements := null;
260 return;
261 end if;
263 declare
264 L : constant Index_Type := Container.Last;
265 EA : Elements_Array renames
266 Container.Elements.EA (Index_Type'First .. L);
268 begin
269 Container.Elements := null;
270 Container.Busy := 0;
271 Container.Lock := 0;
273 -- Note: it may seem that the following assignment to Container.Last
274 -- is useless, since we assign it to L below. However this code is
275 -- used in case 'new Elements_Type' below raises an exception, to
276 -- keep Container in a consistent state.
278 Container.Last := No_Index;
279 Container.Elements := new Elements_Type'(L, EA);
280 Container.Last := L;
281 end;
282 end Adjust;
284 ------------
285 -- Append --
286 ------------
288 procedure Append (Container : in out Vector; New_Item : Vector) is
289 begin
290 if Is_Empty (New_Item) then
291 return;
292 end if;
294 if Container.Last = Index_Type'Last then
295 raise Constraint_Error with "vector is already at its maximum length";
296 end if;
298 Insert
299 (Container,
300 Container.Last + 1,
301 New_Item);
302 end Append;
304 procedure Append
305 (Container : in out Vector;
306 New_Item : Element_Type;
307 Count : Count_Type := 1)
309 begin
310 if Count = 0 then
311 return;
312 end if;
314 if Container.Last = Index_Type'Last then
315 raise Constraint_Error with "vector is already at its maximum length";
316 end if;
318 Insert
319 (Container,
320 Container.Last + 1,
321 New_Item,
322 Count);
323 end Append;
325 --------------
326 -- Capacity --
327 --------------
329 function Capacity (Container : Vector) return Count_Type is
330 begin
331 if Container.Elements = null then
332 return 0;
333 end if;
335 return Container.Elements.EA'Length;
336 end Capacity;
338 -----------
339 -- Clear --
340 -----------
342 procedure Clear (Container : in out Vector) is
343 begin
344 if Container.Busy > 0 then
345 raise Program_Error with
346 "attempt to tamper with elements (vector is busy)";
347 end if;
349 Container.Last := No_Index;
350 end Clear;
352 --------------
353 -- Contains --
354 --------------
356 function Contains
357 (Container : Vector;
358 Item : Element_Type) return Boolean
360 begin
361 return Find_Index (Container, Item) /= No_Index;
362 end Contains;
364 ------------
365 -- Delete --
366 ------------
368 procedure Delete
369 (Container : in out Vector;
370 Index : Extended_Index;
371 Count : Count_Type := 1)
373 begin
374 if Index < Index_Type'First then
375 raise Constraint_Error with "Index is out of range (too small)";
376 end if;
378 if Index > Container.Last then
379 if Index > Container.Last + 1 then
380 raise Constraint_Error with "Index is out of range (too large)";
381 end if;
383 return;
384 end if;
386 if Count = 0 then
387 return;
388 end if;
390 if Container.Busy > 0 then
391 raise Program_Error with
392 "attempt to tamper with elements (vector is busy)";
393 end if;
395 declare
396 I_As_Int : constant Int := Int (Index);
397 Old_Last_As_Int : constant Int := Index_Type'Pos (Container.Last);
399 Count1 : constant Int'Base := Count_Type'Pos (Count);
400 Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
401 N : constant Int'Base := Int'Min (Count1, Count2);
403 J_As_Int : constant Int'Base := I_As_Int + N;
405 begin
406 if J_As_Int > Old_Last_As_Int then
407 Container.Last := Index - 1;
409 else
410 declare
411 J : constant Index_Type := Index_Type (J_As_Int);
412 EA : Elements_Array renames Container.Elements.EA;
414 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
415 New_Last : constant Index_Type :=
416 Index_Type (New_Last_As_Int);
418 begin
419 EA (Index .. New_Last) := EA (J .. Container.Last);
420 Container.Last := New_Last;
421 end;
422 end if;
423 end;
424 end Delete;
426 procedure Delete
427 (Container : in out Vector;
428 Position : in out Cursor;
429 Count : Count_Type := 1)
431 pragma Warnings (Off, Position);
433 begin
434 if Position.Container = null then
435 raise Constraint_Error with "Position cursor has no element";
436 end if;
438 if Position.Container /= Container'Unrestricted_Access then
439 raise Program_Error with "Position cursor denotes wrong container";
440 end if;
442 if Position.Index > Container.Last then
443 raise Program_Error with "Position index is out of range";
444 end if;
446 Delete (Container, Position.Index, Count);
447 Position := No_Element;
448 end Delete;
450 ------------------
451 -- Delete_First --
452 ------------------
454 procedure Delete_First
455 (Container : in out Vector;
456 Count : Count_Type := 1)
458 begin
459 if Count = 0 then
460 return;
461 end if;
463 if Count >= Length (Container) then
464 Clear (Container);
465 return;
466 end if;
468 Delete (Container, Index_Type'First, Count);
469 end Delete_First;
471 -----------------
472 -- Delete_Last --
473 -----------------
475 procedure Delete_Last
476 (Container : in out Vector;
477 Count : Count_Type := 1)
479 Index : Int'Base;
481 begin
482 if Count = 0 then
483 return;
484 end if;
486 if Container.Busy > 0 then
487 raise Program_Error with
488 "attempt to tamper with elements (vector is busy)";
489 end if;
491 Index := Int'Base (Container.Last) - Int'Base (Count);
493 Container.Last :=
494 (if Index < Index_Type'Pos (Index_Type'First)
495 then No_Index
496 else Index_Type (Index));
497 end Delete_Last;
499 -------------
500 -- Element --
501 -------------
503 function Element
504 (Container : Vector;
505 Index : Index_Type) return Element_Type
507 begin
508 if Index > Container.Last then
509 raise Constraint_Error with "Index is out of range";
510 end if;
512 return Container.Elements.EA (Index);
513 end Element;
515 function Element (Position : Cursor) return Element_Type is
516 begin
517 if Position.Container = null then
518 raise Constraint_Error with "Position cursor has no element";
519 end if;
521 if Position.Index > Position.Container.Last then
522 raise Constraint_Error with "Position cursor is out of range";
523 end if;
525 return Position.Container.Elements.EA (Position.Index);
526 end Element;
528 --------------
529 -- Finalize --
530 --------------
532 procedure Finalize (Container : in out Vector) is
533 X : Elements_Access := Container.Elements;
535 begin
536 if Container.Busy > 0 then
537 raise Program_Error with
538 "attempt to tamper with elements (vector is busy)";
539 end if;
541 Container.Elements := null;
542 Container.Last := No_Index;
543 Free (X);
544 end Finalize;
546 ----------
547 -- Find --
548 ----------
550 function Find
551 (Container : Vector;
552 Item : Element_Type;
553 Position : Cursor := No_Element) return Cursor
555 begin
556 if Position.Container /= null then
557 if Position.Container /= Container'Unrestricted_Access then
558 raise Program_Error with "Position cursor denotes wrong container";
559 end if;
561 if Position.Index > Container.Last then
562 raise Program_Error with "Position index is out of range";
563 end if;
564 end if;
566 for J in Position.Index .. Container.Last loop
567 if Container.Elements.EA (J) = Item then
568 return (Container'Unchecked_Access, J);
569 end if;
570 end loop;
572 return No_Element;
573 end Find;
575 ----------------
576 -- Find_Index --
577 ----------------
579 function Find_Index
580 (Container : Vector;
581 Item : Element_Type;
582 Index : Index_Type := Index_Type'First) return Extended_Index
584 begin
585 for Indx in Index .. Container.Last loop
586 if Container.Elements.EA (Indx) = Item then
587 return Indx;
588 end if;
589 end loop;
591 return No_Index;
592 end Find_Index;
594 -----------
595 -- First --
596 -----------
598 function First (Container : Vector) return Cursor is
599 begin
600 if Is_Empty (Container) then
601 return No_Element;
602 end if;
604 return (Container'Unchecked_Access, Index_Type'First);
605 end First;
607 -------------------
608 -- First_Element --
609 -------------------
611 function First_Element (Container : Vector) return Element_Type is
612 begin
613 if Container.Last = No_Index then
614 raise Constraint_Error with "Container is empty";
615 end if;
617 return Container.Elements.EA (Index_Type'First);
618 end First_Element;
620 -----------------
621 -- First_Index --
622 -----------------
624 function First_Index (Container : Vector) return Index_Type is
625 pragma Unreferenced (Container);
626 begin
627 return Index_Type'First;
628 end First_Index;
630 ---------------------
631 -- Generic_Sorting --
632 ---------------------
634 package body Generic_Sorting is
636 ---------------
637 -- Is_Sorted --
638 ---------------
640 function Is_Sorted (Container : Vector) return Boolean is
641 begin
642 if Container.Last <= Index_Type'First then
643 return True;
644 end if;
646 declare
647 EA : Elements_Array renames Container.Elements.EA;
648 begin
649 for I in Index_Type'First .. Container.Last - 1 loop
650 if EA (I + 1) < EA (I) then
651 return False;
652 end if;
653 end loop;
654 end;
656 return True;
657 end Is_Sorted;
659 -----------
660 -- Merge --
661 -----------
663 procedure Merge (Target, Source : in out Vector) is
664 I : Index_Type'Base := Target.Last;
665 J : Index_Type'Base;
667 begin
668 if Target.Last < Index_Type'First then
669 Move (Target => Target, Source => Source);
670 return;
671 end if;
673 if Target'Address = Source'Address then
674 return;
675 end if;
677 if Source.Last < Index_Type'First then
678 return;
679 end if;
681 if Source.Busy > 0 then
682 raise Program_Error with
683 "attempt to tamper with elements (vector is busy)";
684 end if;
686 Target.Set_Length (Length (Target) + Length (Source));
688 declare
689 TA : Elements_Array renames Target.Elements.EA;
690 SA : Elements_Array renames Source.Elements.EA;
692 begin
693 J := Target.Last;
694 while Source.Last >= Index_Type'First loop
695 pragma Assert (Source.Last <= Index_Type'First
696 or else not (SA (Source.Last) <
697 SA (Source.Last - 1)));
699 if I < Index_Type'First then
700 TA (Index_Type'First .. J) :=
701 SA (Index_Type'First .. Source.Last);
703 Source.Last := No_Index;
704 return;
705 end if;
707 pragma Assert (I <= Index_Type'First
708 or else not (TA (I) < TA (I - 1)));
710 if SA (Source.Last) < TA (I) then
711 TA (J) := TA (I);
712 I := I - 1;
714 else
715 TA (J) := SA (Source.Last);
716 Source.Last := Source.Last - 1;
717 end if;
719 J := J - 1;
720 end loop;
721 end;
722 end Merge;
724 ----------
725 -- Sort --
726 ----------
728 procedure Sort (Container : in out Vector)
730 procedure Sort is
731 new Generic_Array_Sort
732 (Index_Type => Index_Type,
733 Element_Type => Element_Type,
734 Array_Type => Elements_Array,
735 "<" => "<");
737 begin
738 if Container.Last <= Index_Type'First then
739 return;
740 end if;
742 if Container.Lock > 0 then
743 raise Program_Error with
744 "attempt to tamper with cursors (vector is locked)";
745 end if;
747 Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
748 end Sort;
750 end Generic_Sorting;
752 -----------------
753 -- Has_Element --
754 -----------------
756 function Has_Element (Position : Cursor) return Boolean is
757 begin
758 if Position.Container = null then
759 return False;
760 end if;
762 return Position.Index <= Position.Container.Last;
763 end Has_Element;
765 ------------
766 -- Insert --
767 ------------
769 procedure Insert
770 (Container : in out Vector;
771 Before : Extended_Index;
772 New_Item : Element_Type;
773 Count : Count_Type := 1)
775 N : constant Int := Count_Type'Pos (Count);
777 First : constant Int := Int (Index_Type'First);
778 New_Last_As_Int : Int'Base;
779 New_Last : Index_Type;
780 New_Length : UInt;
781 Max_Length : constant UInt := UInt (Count_Type'Last);
783 Dst : Elements_Access;
785 begin
786 if Before < Index_Type'First then
787 raise Constraint_Error with
788 "Before index is out of range (too small)";
789 end if;
791 if Before > Container.Last
792 and then Before > Container.Last + 1
793 then
794 raise Constraint_Error with
795 "Before index is out of range (too large)";
796 end if;
798 if Count = 0 then
799 return;
800 end if;
802 declare
803 Old_Last_As_Int : constant Int := Int (Container.Last);
805 begin
806 if Old_Last_As_Int > Int'Last - N then
807 raise Constraint_Error with "new length is out of range";
808 end if;
810 New_Last_As_Int := Old_Last_As_Int + N;
812 if New_Last_As_Int > Int (Index_Type'Last) then
813 raise Constraint_Error with "new length is out of range";
814 end if;
816 New_Length := UInt (New_Last_As_Int - First + Int'(1));
818 if New_Length > Max_Length then
819 raise Constraint_Error with "new length is out of range";
820 end if;
822 New_Last := Index_Type (New_Last_As_Int);
823 end;
825 if Container.Busy > 0 then
826 raise Program_Error with
827 "attempt to tamper with elements (vector is busy)";
828 end if;
830 if Container.Elements = null then
831 Container.Elements := new Elements_Type'
832 (Last => New_Last,
833 EA => (others => New_Item));
834 Container.Last := New_Last;
835 return;
836 end if;
838 if New_Last <= Container.Elements.Last then
839 declare
840 EA : Elements_Array renames Container.Elements.EA;
842 begin
843 if Before <= Container.Last then
844 declare
845 Index_As_Int : constant Int'Base :=
846 Index_Type'Pos (Before) + N;
848 Index : constant Index_Type := Index_Type (Index_As_Int);
850 begin
851 EA (Index .. New_Last) := EA (Before .. Container.Last);
853 EA (Before .. Index_Type'Pred (Index)) :=
854 (others => New_Item);
855 end;
857 else
858 EA (Before .. New_Last) := (others => New_Item);
859 end if;
860 end;
862 Container.Last := New_Last;
863 return;
864 end if;
866 declare
867 C, CC : UInt;
869 begin
870 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
871 while C < New_Length loop
872 if C > UInt'Last / 2 then
873 C := UInt'Last;
874 exit;
875 end if;
877 C := 2 * C;
878 end loop;
880 if C > Max_Length then
881 C := Max_Length;
882 end if;
884 if Index_Type'First <= 0
885 and then Index_Type'Last >= 0
886 then
887 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
888 else
889 CC := UInt (Int (Index_Type'Last) - First + 1);
890 end if;
892 if C > CC then
893 C := CC;
894 end if;
896 declare
897 Dst_Last : constant Index_Type :=
898 Index_Type (First + UInt'Pos (C) - 1);
900 begin
901 Dst := new Elements_Type (Dst_Last);
902 end;
903 end;
905 declare
906 SA : Elements_Array renames Container.Elements.EA;
907 DA : Elements_Array renames Dst.EA;
909 begin
910 DA (Index_Type'First .. Index_Type'Pred (Before)) :=
911 SA (Index_Type'First .. Index_Type'Pred (Before));
913 if Before <= Container.Last then
914 declare
915 Index_As_Int : constant Int'Base :=
916 Index_Type'Pos (Before) + N;
918 Index : constant Index_Type := Index_Type (Index_As_Int);
920 begin
921 DA (Before .. Index_Type'Pred (Index)) := (others => New_Item);
922 DA (Index .. New_Last) := SA (Before .. Container.Last);
923 end;
925 else
926 DA (Before .. New_Last) := (others => New_Item);
927 end if;
928 exception
929 when others =>
930 Free (Dst);
931 raise;
932 end;
934 declare
935 X : Elements_Access := Container.Elements;
936 begin
937 Container.Elements := Dst;
938 Container.Last := New_Last;
939 Free (X);
940 end;
941 end Insert;
943 procedure Insert
944 (Container : in out Vector;
945 Before : Extended_Index;
946 New_Item : Vector)
948 N : constant Count_Type := Length (New_Item);
950 begin
951 if Before < Index_Type'First then
952 raise Constraint_Error with
953 "Before index is out of range (too small)";
954 end if;
956 if Before > Container.Last
957 and then Before > Container.Last + 1
958 then
959 raise Constraint_Error with
960 "Before index is out of range (too large)";
961 end if;
963 if N = 0 then
964 return;
965 end if;
967 Insert_Space (Container, Before, Count => N);
969 declare
970 Dst_Last_As_Int : constant Int'Base :=
971 Int'Base (Before) + Int'Base (N) - 1;
973 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
975 begin
976 if Container'Address /= New_Item'Address then
977 Container.Elements.EA (Before .. Dst_Last) :=
978 New_Item.Elements.EA (Index_Type'First .. New_Item.Last);
980 return;
981 end if;
983 declare
984 subtype Src_Index_Subtype is Index_Type'Base range
985 Index_Type'First .. Before - 1;
987 Src : Elements_Array renames
988 Container.Elements.EA (Src_Index_Subtype);
990 Index_As_Int : constant Int'Base :=
991 Int (Before) + Src'Length - 1;
993 Index : constant Index_Type'Base :=
994 Index_Type'Base (Index_As_Int);
996 Dst : Elements_Array renames
997 Container.Elements.EA (Before .. Index);
999 begin
1000 Dst := Src;
1001 end;
1003 if Dst_Last = Container.Last then
1004 return;
1005 end if;
1007 declare
1008 subtype Src_Index_Subtype is Index_Type'Base range
1009 Dst_Last + 1 .. Container.Last;
1011 Src : Elements_Array renames
1012 Container.Elements.EA (Src_Index_Subtype);
1014 Index_As_Int : constant Int'Base :=
1015 Dst_Last_As_Int - Src'Length + 1;
1017 Index : constant Index_Type :=
1018 Index_Type (Index_As_Int);
1020 Dst : Elements_Array renames
1021 Container.Elements.EA (Index .. Dst_Last);
1023 begin
1024 Dst := Src;
1025 end;
1026 end;
1027 end Insert;
1029 procedure Insert
1030 (Container : in out Vector;
1031 Before : Cursor;
1032 New_Item : Vector)
1034 Index : Index_Type'Base;
1036 begin
1037 if Before.Container /= null
1038 and then Before.Container /= Container'Unchecked_Access
1039 then
1040 raise Program_Error with "Before cursor denotes wrong container";
1041 end if;
1043 if Is_Empty (New_Item) then
1044 return;
1045 end if;
1047 if Before.Container = null
1048 or else Before.Index > Container.Last
1049 then
1050 if Container.Last = Index_Type'Last then
1051 raise Constraint_Error with
1052 "vector is already at its maximum length";
1053 end if;
1055 Index := Container.Last + 1;
1057 else
1058 Index := Before.Index;
1059 end if;
1061 Insert (Container, Index, New_Item);
1062 end Insert;
1064 procedure Insert
1065 (Container : in out Vector;
1066 Before : Cursor;
1067 New_Item : Vector;
1068 Position : out Cursor)
1070 Index : Index_Type'Base;
1072 begin
1073 if Before.Container /= null
1074 and then Before.Container /= Container'Unchecked_Access
1075 then
1076 raise Program_Error with "Before cursor denotes wrong container";
1077 end if;
1079 if Is_Empty (New_Item) then
1080 if Before.Container = null
1081 or else Before.Index > Container.Last
1082 then
1083 Position := No_Element;
1084 else
1085 Position := (Container'Unchecked_Access, Before.Index);
1086 end if;
1088 return;
1089 end if;
1091 if Before.Container = null
1092 or else Before.Index > Container.Last
1093 then
1094 if Container.Last = Index_Type'Last then
1095 raise Constraint_Error with
1096 "vector is already at its maximum length";
1097 end if;
1099 Index := Container.Last + 1;
1101 else
1102 Index := Before.Index;
1103 end if;
1105 Insert (Container, Index, New_Item);
1107 Position := Cursor'(Container'Unchecked_Access, Index);
1108 end Insert;
1110 procedure Insert
1111 (Container : in out Vector;
1112 Before : Cursor;
1113 New_Item : Element_Type;
1114 Count : Count_Type := 1)
1116 Index : Index_Type'Base;
1118 begin
1119 if Before.Container /= null
1120 and then Before.Container /= Container'Unchecked_Access
1121 then
1122 raise Program_Error with "Before cursor denotes wrong container";
1123 end if;
1125 if Count = 0 then
1126 return;
1127 end if;
1129 if Before.Container = null
1130 or else Before.Index > Container.Last
1131 then
1132 if Container.Last = Index_Type'Last then
1133 raise Constraint_Error with
1134 "vector is already at its maximum length";
1135 end if;
1137 Index := Container.Last + 1;
1139 else
1140 Index := Before.Index;
1141 end if;
1143 Insert (Container, Index, New_Item, Count);
1144 end Insert;
1146 procedure Insert
1147 (Container : in out Vector;
1148 Before : Cursor;
1149 New_Item : Element_Type;
1150 Position : out Cursor;
1151 Count : Count_Type := 1)
1153 Index : Index_Type'Base;
1155 begin
1156 if Before.Container /= null
1157 and then Before.Container /= Container'Unchecked_Access
1158 then
1159 raise Program_Error with "Before cursor denotes wrong container";
1160 end if;
1162 if Count = 0 then
1163 if Before.Container = null
1164 or else Before.Index > Container.Last
1165 then
1166 Position := No_Element;
1167 else
1168 Position := (Container'Unchecked_Access, Before.Index);
1169 end if;
1171 return;
1172 end if;
1174 if Before.Container = null
1175 or else Before.Index > Container.Last
1176 then
1177 if Container.Last = Index_Type'Last then
1178 raise Constraint_Error with
1179 "vector is already at its maximum length";
1180 end if;
1182 Index := Container.Last + 1;
1184 else
1185 Index := Before.Index;
1186 end if;
1188 Insert (Container, Index, New_Item, Count);
1190 Position := Cursor'(Container'Unchecked_Access, Index);
1191 end Insert;
1193 procedure Insert
1194 (Container : in out Vector;
1195 Before : Extended_Index;
1196 Count : Count_Type := 1)
1198 New_Item : Element_Type; -- Default-initialized value
1199 pragma Warnings (Off, New_Item);
1201 begin
1202 Insert (Container, Before, New_Item, Count);
1203 end Insert;
1205 procedure Insert
1206 (Container : in out Vector;
1207 Before : Cursor;
1208 Position : out Cursor;
1209 Count : Count_Type := 1)
1211 New_Item : Element_Type; -- Default-initialized value
1212 pragma Warnings (Off, New_Item);
1214 begin
1215 Insert (Container, Before, New_Item, Position, Count);
1216 end Insert;
1218 ------------------
1219 -- Insert_Space --
1220 ------------------
1222 procedure Insert_Space
1223 (Container : in out Vector;
1224 Before : Extended_Index;
1225 Count : Count_Type := 1)
1227 N : constant Int := Count_Type'Pos (Count);
1229 First : constant Int := Int (Index_Type'First);
1230 New_Last_As_Int : Int'Base;
1231 New_Last : Index_Type;
1232 New_Length : UInt;
1233 Max_Length : constant UInt := UInt (Count_Type'Last);
1235 Dst : Elements_Access;
1237 begin
1238 if Before < Index_Type'First then
1239 raise Constraint_Error with
1240 "Before index is out of range (too small)";
1241 end if;
1243 if Before > Container.Last
1244 and then Before > Container.Last + 1
1245 then
1246 raise Constraint_Error with
1247 "Before index is out of range (too large)";
1248 end if;
1250 if Count = 0 then
1251 return;
1252 end if;
1254 declare
1255 Old_Last_As_Int : constant Int := Int (Container.Last);
1257 begin
1258 if Old_Last_As_Int > Int'Last - N then
1259 raise Constraint_Error with "new length is out of range";
1260 end if;
1262 New_Last_As_Int := Old_Last_As_Int + N;
1264 if New_Last_As_Int > Int (Index_Type'Last) then
1265 raise Constraint_Error with "new length is out of range";
1266 end if;
1268 New_Length := UInt (New_Last_As_Int - First + Int'(1));
1270 if New_Length > Max_Length then
1271 raise Constraint_Error with "new length is out of range";
1272 end if;
1274 New_Last := Index_Type (New_Last_As_Int);
1275 end;
1277 if Container.Busy > 0 then
1278 raise Program_Error with
1279 "attempt to tamper with elements (vector is busy)";
1280 end if;
1282 if Container.Elements = null then
1283 Container.Elements := new Elements_Type (New_Last);
1284 Container.Last := New_Last;
1285 return;
1286 end if;
1288 if New_Last <= Container.Elements.Last then
1289 declare
1290 EA : Elements_Array renames Container.Elements.EA;
1291 begin
1292 if Before <= Container.Last then
1293 declare
1294 Index_As_Int : constant Int'Base :=
1295 Index_Type'Pos (Before) + N;
1297 Index : constant Index_Type := Index_Type (Index_As_Int);
1299 begin
1300 EA (Index .. New_Last) := EA (Before .. Container.Last);
1301 end;
1302 end if;
1303 end;
1305 Container.Last := New_Last;
1306 return;
1307 end if;
1309 declare
1310 C, CC : UInt;
1312 begin
1313 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1314 while C < New_Length loop
1315 if C > UInt'Last / 2 then
1316 C := UInt'Last;
1317 exit;
1318 end if;
1320 C := 2 * C;
1321 end loop;
1323 if C > Max_Length then
1324 C := Max_Length;
1325 end if;
1327 if Index_Type'First <= 0
1328 and then Index_Type'Last >= 0
1329 then
1330 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1331 else
1332 CC := UInt (Int (Index_Type'Last) - First + 1);
1333 end if;
1335 if C > CC then
1336 C := CC;
1337 end if;
1339 declare
1340 Dst_Last : constant Index_Type :=
1341 Index_Type (First + UInt'Pos (C) - 1);
1343 begin
1344 Dst := new Elements_Type (Dst_Last);
1345 end;
1346 end;
1348 declare
1349 SA : Elements_Array renames Container.Elements.EA;
1350 DA : Elements_Array renames Dst.EA;
1352 begin
1353 DA (Index_Type'First .. Index_Type'Pred (Before)) :=
1354 SA (Index_Type'First .. Index_Type'Pred (Before));
1356 if Before <= Container.Last then
1357 declare
1358 Index_As_Int : constant Int'Base :=
1359 Index_Type'Pos (Before) + N;
1361 Index : constant Index_Type := Index_Type (Index_As_Int);
1363 begin
1364 DA (Index .. New_Last) := SA (Before .. Container.Last);
1365 end;
1366 end if;
1367 exception
1368 when others =>
1369 Free (Dst);
1370 raise;
1371 end;
1373 declare
1374 X : Elements_Access := Container.Elements;
1375 begin
1376 Container.Elements := Dst;
1377 Container.Last := New_Last;
1378 Free (X);
1379 end;
1380 end Insert_Space;
1382 procedure Insert_Space
1383 (Container : in out Vector;
1384 Before : Cursor;
1385 Position : out Cursor;
1386 Count : Count_Type := 1)
1388 Index : Index_Type'Base;
1390 begin
1391 if Before.Container /= null
1392 and then Before.Container /= Container'Unchecked_Access
1393 then
1394 raise Program_Error with "Before cursor denotes wrong container";
1395 end if;
1397 if Count = 0 then
1398 if Before.Container = null
1399 or else Before.Index > Container.Last
1400 then
1401 Position := No_Element;
1402 else
1403 Position := (Container'Unchecked_Access, Before.Index);
1404 end if;
1406 return;
1407 end if;
1409 if Before.Container = null
1410 or else Before.Index > Container.Last
1411 then
1412 if Container.Last = Index_Type'Last then
1413 raise Constraint_Error with
1414 "vector is already at its maximum length";
1415 end if;
1417 Index := Container.Last + 1;
1419 else
1420 Index := Before.Index;
1421 end if;
1423 Insert_Space (Container, Index, Count => Count);
1425 Position := Cursor'(Container'Unchecked_Access, Index);
1426 end Insert_Space;
1428 --------------
1429 -- Is_Empty --
1430 --------------
1432 function Is_Empty (Container : Vector) return Boolean is
1433 begin
1434 return Container.Last < Index_Type'First;
1435 end Is_Empty;
1437 -------------
1438 -- Iterate --
1439 -------------
1441 procedure Iterate
1442 (Container : Vector;
1443 Process : not null access procedure (Position : Cursor))
1445 V : Vector renames Container'Unrestricted_Access.all;
1446 B : Natural renames V.Busy;
1448 begin
1449 B := B + 1;
1451 begin
1452 for Indx in Index_Type'First .. Container.Last loop
1453 Process (Cursor'(Container'Unchecked_Access, Indx));
1454 end loop;
1455 exception
1456 when others =>
1457 B := B - 1;
1458 raise;
1459 end;
1461 B := B - 1;
1462 end Iterate;
1464 ----------
1465 -- Last --
1466 ----------
1468 function Last (Container : Vector) return Cursor is
1469 begin
1470 if Is_Empty (Container) then
1471 return No_Element;
1472 end if;
1474 return (Container'Unchecked_Access, Container.Last);
1475 end Last;
1477 ------------------
1478 -- Last_Element --
1479 ------------------
1481 function Last_Element (Container : Vector) return Element_Type is
1482 begin
1483 if Container.Last = No_Index then
1484 raise Constraint_Error with "Container is empty";
1485 end if;
1487 return Container.Elements.EA (Container.Last);
1488 end Last_Element;
1490 ----------------
1491 -- Last_Index --
1492 ----------------
1494 function Last_Index (Container : Vector) return Extended_Index is
1495 begin
1496 return Container.Last;
1497 end Last_Index;
1499 ------------
1500 -- Length --
1501 ------------
1503 function Length (Container : Vector) return Count_Type is
1504 L : constant Int := Int (Container.Last);
1505 F : constant Int := Int (Index_Type'First);
1506 N : constant Int'Base := L - F + 1;
1508 begin
1509 return Count_Type (N);
1510 end Length;
1512 ----------
1513 -- Move --
1514 ----------
1516 procedure Move
1517 (Target : in out Vector;
1518 Source : in out Vector)
1520 begin
1521 if Target'Address = Source'Address then
1522 return;
1523 end if;
1525 if Target.Busy > 0 then
1526 raise Program_Error with
1527 "attempt to tamper with elements (Target is busy)";
1528 end if;
1530 if Source.Busy > 0 then
1531 raise Program_Error with
1532 "attempt to tamper with elements (Source is busy)";
1533 end if;
1535 declare
1536 Target_Elements : constant Elements_Access := Target.Elements;
1537 begin
1538 Target.Elements := Source.Elements;
1539 Source.Elements := Target_Elements;
1540 end;
1542 Target.Last := Source.Last;
1543 Source.Last := No_Index;
1544 end Move;
1546 ----------
1547 -- Next --
1548 ----------
1550 function Next (Position : Cursor) return Cursor is
1551 begin
1552 if Position.Container = null then
1553 return No_Element;
1554 end if;
1556 if Position.Index < Position.Container.Last then
1557 return (Position.Container, Position.Index + 1);
1558 end if;
1560 return No_Element;
1561 end Next;
1563 ----------
1564 -- Next --
1565 ----------
1567 procedure Next (Position : in out Cursor) is
1568 begin
1569 if Position.Container = null then
1570 return;
1571 end if;
1573 if Position.Index < Position.Container.Last then
1574 Position.Index := Position.Index + 1;
1575 else
1576 Position := No_Element;
1577 end if;
1578 end Next;
1580 -------------
1581 -- Prepend --
1582 -------------
1584 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1585 begin
1586 Insert (Container, Index_Type'First, New_Item);
1587 end Prepend;
1589 procedure Prepend
1590 (Container : in out Vector;
1591 New_Item : Element_Type;
1592 Count : Count_Type := 1)
1594 begin
1595 Insert (Container,
1596 Index_Type'First,
1597 New_Item,
1598 Count);
1599 end Prepend;
1601 --------------
1602 -- Previous --
1603 --------------
1605 procedure Previous (Position : in out Cursor) is
1606 begin
1607 if Position.Container = null then
1608 return;
1609 end if;
1611 if Position.Index > Index_Type'First then
1612 Position.Index := Position.Index - 1;
1613 else
1614 Position := No_Element;
1615 end if;
1616 end Previous;
1618 function Previous (Position : Cursor) return Cursor is
1619 begin
1620 if Position.Container = null then
1621 return No_Element;
1622 end if;
1624 if Position.Index > Index_Type'First then
1625 return (Position.Container, Position.Index - 1);
1626 end if;
1628 return No_Element;
1629 end Previous;
1631 -------------------
1632 -- Query_Element --
1633 -------------------
1635 procedure Query_Element
1636 (Container : Vector;
1637 Index : Index_Type;
1638 Process : not null access procedure (Element : Element_Type))
1640 V : Vector renames Container'Unrestricted_Access.all;
1641 B : Natural renames V.Busy;
1642 L : Natural renames V.Lock;
1644 begin
1645 if Index > Container.Last then
1646 raise Constraint_Error with "Index is out of range";
1647 end if;
1649 B := B + 1;
1650 L := L + 1;
1652 begin
1653 Process (V.Elements.EA (Index));
1654 exception
1655 when others =>
1656 L := L - 1;
1657 B := B - 1;
1658 raise;
1659 end;
1661 L := L - 1;
1662 B := B - 1;
1663 end Query_Element;
1665 procedure Query_Element
1666 (Position : Cursor;
1667 Process : not null access procedure (Element : Element_Type))
1669 begin
1670 if Position.Container = null then
1671 raise Constraint_Error with "Position cursor has no element";
1672 end if;
1674 Query_Element (Position.Container.all, Position.Index, Process);
1675 end Query_Element;
1677 ----------
1678 -- Read --
1679 ----------
1681 procedure Read
1682 (Stream : not null access Root_Stream_Type'Class;
1683 Container : out Vector)
1685 Length : Count_Type'Base;
1686 Last : Index_Type'Base := No_Index;
1688 begin
1689 Clear (Container);
1691 Count_Type'Base'Read (Stream, Length);
1693 if Length > Capacity (Container) then
1694 Reserve_Capacity (Container, Capacity => Length);
1695 end if;
1697 for J in Count_Type range 1 .. Length loop
1698 Last := Last + 1;
1699 Element_Type'Read (Stream, Container.Elements.EA (Last));
1700 Container.Last := Last;
1701 end loop;
1702 end Read;
1704 procedure Read
1705 (Stream : not null access Root_Stream_Type'Class;
1706 Position : out Cursor)
1708 begin
1709 raise Program_Error with "attempt to stream vector cursor";
1710 end Read;
1712 ---------------------
1713 -- Replace_Element --
1714 ---------------------
1716 procedure Replace_Element
1717 (Container : in out Vector;
1718 Index : Index_Type;
1719 New_Item : Element_Type)
1721 begin
1722 if Index > Container.Last then
1723 raise Constraint_Error with "Index is out of range";
1724 end if;
1726 if Container.Lock > 0 then
1727 raise Program_Error with
1728 "attempt to tamper with cursors (vector is locked)";
1729 end if;
1731 Container.Elements.EA (Index) := New_Item;
1732 end Replace_Element;
1734 procedure Replace_Element
1735 (Container : in out Vector;
1736 Position : Cursor;
1737 New_Item : Element_Type)
1739 begin
1740 if Position.Container = null then
1741 raise Constraint_Error with "Position cursor has no element";
1742 end if;
1744 if Position.Container /= Container'Unrestricted_Access then
1745 raise Program_Error with "Position cursor denotes wrong container";
1746 end if;
1748 if Position.Index > Container.Last then
1749 raise Constraint_Error with "Position cursor is out of range";
1750 end if;
1752 if Container.Lock > 0 then
1753 raise Program_Error with
1754 "attempt to tamper with cursors (vector is locked)";
1755 end if;
1757 Container.Elements.EA (Position.Index) := New_Item;
1758 end Replace_Element;
1760 ----------------------
1761 -- Reserve_Capacity --
1762 ----------------------
1764 procedure Reserve_Capacity
1765 (Container : in out Vector;
1766 Capacity : Count_Type)
1768 N : constant Count_Type := Length (Container);
1770 begin
1771 if Capacity = 0 then
1772 if N = 0 then
1773 declare
1774 X : Elements_Access := Container.Elements;
1775 begin
1776 Container.Elements := null;
1777 Free (X);
1778 end;
1780 elsif N < Container.Elements.EA'Length then
1781 if Container.Busy > 0 then
1782 raise Program_Error with
1783 "attempt to tamper with elements (vector is busy)";
1784 end if;
1786 declare
1787 subtype Src_Index_Subtype is Index_Type'Base range
1788 Index_Type'First .. Container.Last;
1790 Src : Elements_Array renames
1791 Container.Elements.EA (Src_Index_Subtype);
1793 X : Elements_Access := Container.Elements;
1795 begin
1796 Container.Elements := new Elements_Type'(Container.Last, Src);
1797 Free (X);
1798 end;
1799 end if;
1801 return;
1802 end if;
1804 if Container.Elements = null then
1805 declare
1806 Last_As_Int : constant Int'Base :=
1807 Int (Index_Type'First) + Int (Capacity) - 1;
1809 begin
1810 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1811 raise Constraint_Error with "new length is out of range";
1812 end if;
1814 declare
1815 Last : constant Index_Type := Index_Type (Last_As_Int);
1817 begin
1818 Container.Elements := new Elements_Type (Last);
1819 end;
1820 end;
1822 return;
1823 end if;
1825 if Capacity <= N then
1826 if N < Container.Elements.EA'Length then
1827 if Container.Busy > 0 then
1828 raise Program_Error with
1829 "attempt to tamper with elements (vector is busy)";
1830 end if;
1832 declare
1833 subtype Src_Index_Subtype is Index_Type'Base range
1834 Index_Type'First .. Container.Last;
1836 Src : Elements_Array renames
1837 Container.Elements.EA (Src_Index_Subtype);
1839 X : Elements_Access := Container.Elements;
1841 begin
1842 Container.Elements := new Elements_Type'(Container.Last, Src);
1843 Free (X);
1844 end;
1846 end if;
1848 return;
1849 end if;
1851 if Capacity = Container.Elements.EA'Length then
1852 return;
1853 end if;
1855 if Container.Busy > 0 then
1856 raise Program_Error with
1857 "attempt to tamper with elements (vector is busy)";
1858 end if;
1860 declare
1861 Last_As_Int : constant Int'Base :=
1862 Int (Index_Type'First) + Int (Capacity) - 1;
1864 begin
1865 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1866 raise Constraint_Error with "new length is out of range";
1867 end if;
1869 declare
1870 Last : constant Index_Type := Index_Type (Last_As_Int);
1872 E : Elements_Access := new Elements_Type (Last);
1874 begin
1875 declare
1876 subtype Index_Subtype is Index_Type'Base range
1877 Index_Type'First .. Container.Last;
1879 Src : Elements_Array renames
1880 Container.Elements.EA (Index_Subtype);
1882 Tgt : Elements_Array renames E.EA (Index_Subtype);
1884 begin
1885 Tgt := Src;
1887 exception
1888 when others =>
1889 Free (E);
1890 raise;
1891 end;
1893 declare
1894 X : Elements_Access := Container.Elements;
1895 begin
1896 Container.Elements := E;
1897 Free (X);
1898 end;
1899 end;
1900 end;
1901 end Reserve_Capacity;
1903 ----------------------
1904 -- Reverse_Elements --
1905 ----------------------
1907 procedure Reverse_Elements (Container : in out Vector) is
1908 begin
1909 if Container.Length <= 1 then
1910 return;
1911 end if;
1913 if Container.Lock > 0 then
1914 raise Program_Error with
1915 "attempt to tamper with cursors (vector is locked)";
1916 end if;
1918 declare
1919 I, J : Index_Type;
1920 E : Elements_Type renames Container.Elements.all;
1922 begin
1923 I := Index_Type'First;
1924 J := Container.Last;
1925 while I < J loop
1926 declare
1927 EI : constant Element_Type := E.EA (I);
1929 begin
1930 E.EA (I) := E.EA (J);
1931 E.EA (J) := EI;
1932 end;
1934 I := I + 1;
1935 J := J - 1;
1936 end loop;
1937 end;
1938 end Reverse_Elements;
1940 ------------------
1941 -- Reverse_Find --
1942 ------------------
1944 function Reverse_Find
1945 (Container : Vector;
1946 Item : Element_Type;
1947 Position : Cursor := No_Element) return Cursor
1949 Last : Index_Type'Base;
1951 begin
1952 if Position.Container /= null
1953 and then Position.Container /= Container'Unchecked_Access
1954 then
1955 raise Program_Error with "Position cursor denotes wrong container";
1956 end if;
1958 Last :=
1959 (if Position.Container = null or else Position.Index > Container.Last
1960 then Container.Last
1961 else Position.Index);
1963 for Indx in reverse Index_Type'First .. Last loop
1964 if Container.Elements.EA (Indx) = Item then
1965 return (Container'Unchecked_Access, Indx);
1966 end if;
1967 end loop;
1969 return No_Element;
1970 end Reverse_Find;
1972 ------------------------
1973 -- Reverse_Find_Index --
1974 ------------------------
1976 function Reverse_Find_Index
1977 (Container : Vector;
1978 Item : Element_Type;
1979 Index : Index_Type := Index_Type'Last) return Extended_Index
1981 Last : constant Index_Type'Base :=
1982 Index_Type'Min (Container.Last, Index);
1984 begin
1985 for Indx in reverse Index_Type'First .. Last loop
1986 if Container.Elements.EA (Indx) = Item then
1987 return Indx;
1988 end if;
1989 end loop;
1991 return No_Index;
1992 end Reverse_Find_Index;
1994 ---------------------
1995 -- Reverse_Iterate --
1996 ---------------------
1998 procedure Reverse_Iterate
1999 (Container : Vector;
2000 Process : not null access procedure (Position : Cursor))
2002 V : Vector renames Container'Unrestricted_Access.all;
2003 B : Natural renames V.Busy;
2005 begin
2006 B := B + 1;
2008 begin
2009 for Indx in reverse Index_Type'First .. Container.Last loop
2010 Process (Cursor'(Container'Unchecked_Access, Indx));
2011 end loop;
2012 exception
2013 when others =>
2014 B := B - 1;
2015 raise;
2016 end;
2018 B := B - 1;
2019 end Reverse_Iterate;
2021 ----------------
2022 -- Set_Length --
2023 ----------------
2025 procedure Set_Length (Container : in out Vector; Length : Count_Type) is
2026 begin
2027 if Length = Vectors.Length (Container) then
2028 return;
2029 end if;
2031 if Container.Busy > 0 then
2032 raise Program_Error with
2033 "attempt to tamper with elements (vector is busy)";
2034 end if;
2036 if Length > Capacity (Container) then
2037 Reserve_Capacity (Container, Capacity => Length);
2038 end if;
2040 declare
2041 Last_As_Int : constant Int'Base :=
2042 Int (Index_Type'First) + Int (Length) - 1;
2043 begin
2044 Container.Last := Index_Type'Base (Last_As_Int);
2045 end;
2046 end Set_Length;
2048 ----------
2049 -- Swap --
2050 ----------
2052 procedure Swap (Container : in out Vector; I, J : Index_Type) is
2053 begin
2054 if I > Container.Last then
2055 raise Constraint_Error with "I index is out of range";
2056 end if;
2058 if J > Container.Last then
2059 raise Constraint_Error with "J index is out of range";
2060 end if;
2062 if I = J then
2063 return;
2064 end if;
2066 if Container.Lock > 0 then
2067 raise Program_Error with
2068 "attempt to tamper with cursors (vector is locked)";
2069 end if;
2071 declare
2072 EI_Copy : constant Element_Type := Container.Elements.EA (I);
2073 begin
2074 Container.Elements.EA (I) := Container.Elements.EA (J);
2075 Container.Elements.EA (J) := EI_Copy;
2076 end;
2077 end Swap;
2079 procedure Swap (Container : in out Vector; I, J : Cursor) is
2080 begin
2081 if I.Container = null then
2082 raise Constraint_Error with "I cursor has no element";
2083 end if;
2085 if J.Container = null then
2086 raise Constraint_Error with "J cursor has no element";
2087 end if;
2089 if I.Container /= Container'Unrestricted_Access then
2090 raise Program_Error with "I cursor denotes wrong container";
2091 end if;
2093 if J.Container /= Container'Unrestricted_Access then
2094 raise Program_Error with "J cursor denotes wrong container";
2095 end if;
2097 Swap (Container, I.Index, J.Index);
2098 end Swap;
2100 ---------------
2101 -- To_Cursor --
2102 ---------------
2104 function To_Cursor
2105 (Container : Vector;
2106 Index : Extended_Index) return Cursor
2108 begin
2109 if Index not in Index_Type'First .. Container.Last then
2110 return No_Element;
2111 end if;
2113 return Cursor'(Container'Unchecked_Access, Index);
2114 end To_Cursor;
2116 --------------
2117 -- To_Index --
2118 --------------
2120 function To_Index (Position : Cursor) return Extended_Index is
2121 begin
2122 if Position.Container = null then
2123 return No_Index;
2124 end if;
2126 if Position.Index <= Position.Container.Last then
2127 return Position.Index;
2128 end if;
2130 return No_Index;
2131 end To_Index;
2133 ---------------
2134 -- To_Vector --
2135 ---------------
2137 function To_Vector (Length : Count_Type) return Vector is
2138 begin
2139 if Length = 0 then
2140 return Empty_Vector;
2141 end if;
2143 declare
2144 First : constant Int := Int (Index_Type'First);
2145 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2146 Last : Index_Type;
2147 Elements : Elements_Access;
2149 begin
2150 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2151 raise Constraint_Error with "Length is out of range";
2152 end if;
2154 Last := Index_Type (Last_As_Int);
2155 Elements := new Elements_Type (Last);
2157 return Vector'(Controlled with Elements, Last, 0, 0);
2158 end;
2159 end To_Vector;
2161 function To_Vector
2162 (New_Item : Element_Type;
2163 Length : Count_Type) return Vector
2165 begin
2166 if Length = 0 then
2167 return Empty_Vector;
2168 end if;
2170 declare
2171 First : constant Int := Int (Index_Type'First);
2172 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2173 Last : Index_Type;
2174 Elements : Elements_Access;
2176 begin
2177 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2178 raise Constraint_Error with "Length is out of range";
2179 end if;
2181 Last := Index_Type (Last_As_Int);
2182 Elements := new Elements_Type'(Last, EA => (others => New_Item));
2184 return Vector'(Controlled with Elements, Last, 0, 0);
2185 end;
2186 end To_Vector;
2188 --------------------
2189 -- Update_Element --
2190 --------------------
2192 procedure Update_Element
2193 (Container : in out Vector;
2194 Index : Index_Type;
2195 Process : not null access procedure (Element : in out Element_Type))
2197 B : Natural renames Container.Busy;
2198 L : Natural renames Container.Lock;
2200 begin
2201 if Index > Container.Last then
2202 raise Constraint_Error with "Index is out of range";
2203 end if;
2205 B := B + 1;
2206 L := L + 1;
2208 begin
2209 Process (Container.Elements.EA (Index));
2210 exception
2211 when others =>
2212 L := L - 1;
2213 B := B - 1;
2214 raise;
2215 end;
2217 L := L - 1;
2218 B := B - 1;
2219 end Update_Element;
2221 procedure Update_Element
2222 (Container : in out Vector;
2223 Position : Cursor;
2224 Process : not null access procedure (Element : in out Element_Type))
2226 begin
2227 if Position.Container = null then
2228 raise Constraint_Error with "Position cursor has no element";
2229 end if;
2231 if Position.Container /= Container'Unrestricted_Access then
2232 raise Program_Error with "Position cursor denotes wrong container";
2233 end if;
2235 Update_Element (Container, Position.Index, Process);
2236 end Update_Element;
2238 -----------
2239 -- Write --
2240 -----------
2242 procedure Write
2243 (Stream : not null access Root_Stream_Type'Class;
2244 Container : Vector)
2246 begin
2247 Count_Type'Base'Write (Stream, Length (Container));
2249 for J in Index_Type'First .. Container.Last loop
2250 Element_Type'Write (Stream, Container.Elements.EA (J));
2251 end loop;
2252 end Write;
2254 procedure Write
2255 (Stream : not null access Root_Stream_Type'Class;
2256 Position : Cursor)
2258 begin
2259 raise Program_Error with "attempt to stream vector cursor";
2260 end Write;
2262 end Ada.Containers.Vectors;