PR tree-optimization/19853
[official-gcc.git] / gcc / ada / a-convec.adb
blobc98c58a3b21896dd4057a4e3598c569487c0bd16
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.VECTORS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004 Free Software Foundation, Inc. --
10 -- --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
14 -- --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 2, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21 -- for more details. You should have received a copy of the GNU General --
22 -- Public License distributed with GNAT; see file COPYING. If not, write --
23 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
24 -- MA 02111-1307, USA. --
25 -- --
26 -- As a special exception, if other files instantiate generics from this --
27 -- unit, or you link this unit with other files to produce an executable, --
28 -- this unit does not by itself cause the resulting executable to be --
29 -- covered by the GNU General Public License. This exception does not --
30 -- however invalidate any other reasons why the executable file might be --
31 -- covered by the GNU Public License. --
32 -- --
33 -- This unit was originally developed by Matthew J Heaney. --
34 ------------------------------------------------------------------------------
36 with Ada.Containers.Generic_Array_Sort;
37 with Ada.Unchecked_Deallocation;
39 with System; use type System.Address;
41 package body Ada.Containers.Vectors is
43 type Int is range System.Min_Int .. System.Max_Int;
45 procedure Free is
46 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
48 ---------
49 -- "&" --
50 ---------
52 function "&" (Left, Right : Vector) return Vector is
53 LN : constant Count_Type := Length (Left);
54 RN : constant Count_Type := Length (Right);
56 begin
57 if LN = 0 then
58 if RN = 0 then
59 return Empty_Vector;
60 end if;
62 declare
63 RE : Elements_Type renames
64 Right.Elements (Index_Type'First .. Right.Last);
66 Elements : constant Elements_Access :=
67 new Elements_Type'(RE);
69 begin
70 return (Controlled with Elements, Right.Last);
71 end;
72 end if;
74 if RN = 0 then
75 declare
76 LE : Elements_Type renames
77 Left.Elements (Index_Type'First .. Left.Last);
79 Elements : constant Elements_Access :=
80 new Elements_Type'(LE);
82 begin
83 return (Controlled with Elements, Left.Last);
84 end;
86 end if;
88 declare
89 Last_As_Int : constant Int'Base :=
90 Int (Index_Type'First) + Int (LN) + Int (RN) - 1;
92 Last : constant Index_Type := Index_Type (Last_As_Int);
94 LE : Elements_Type renames
95 Left.Elements (Index_Type'First .. Left.Last);
97 RE : Elements_Type renames
98 Right.Elements (Index_Type'First .. Right.Last);
100 Elements : constant Elements_Access :=
101 new Elements_Type'(LE & RE);
103 begin
104 return (Controlled with Elements, Last);
105 end;
106 end "&";
108 function "&" (Left : Vector; Right : Element_Type) return Vector is
109 LN : constant Count_Type := Length (Left);
111 begin
112 if LN = 0 then
113 declare
114 subtype Elements_Subtype is
115 Elements_Type (Index_Type'First .. Index_Type'First);
117 Elements : constant Elements_Access :=
118 new Elements_Subtype'(others => Right);
120 begin
121 return (Controlled with Elements, Index_Type'First);
122 end;
123 end if;
125 declare
126 Last_As_Int : constant Int'Base :=
127 Int (Index_Type'First) + Int (LN);
129 Last : constant Index_Type := Index_Type (Last_As_Int);
131 LE : Elements_Type renames
132 Left.Elements (Index_Type'First .. Left.Last);
134 subtype ET is Elements_Type (Index_Type'First .. Last);
136 Elements : constant Elements_Access := new ET'(LE & Right);
138 begin
139 return (Controlled with Elements, Last);
140 end;
141 end "&";
143 function "&" (Left : Element_Type; Right : Vector) return Vector is
144 RN : constant Count_Type := Length (Right);
146 begin
147 if RN = 0 then
148 declare
149 subtype Elements_Subtype is
150 Elements_Type (Index_Type'First .. Index_Type'First);
152 Elements : constant Elements_Access :=
153 new Elements_Subtype'(others => Left);
155 begin
156 return (Controlled with Elements, Index_Type'First);
157 end;
158 end if;
160 declare
161 Last_As_Int : constant Int'Base :=
162 Int (Index_Type'First) + Int (RN);
164 Last : constant Index_Type := Index_Type (Last_As_Int);
166 RE : Elements_Type renames
167 Right.Elements (Index_Type'First .. Right.Last);
169 subtype ET is Elements_Type (Index_Type'First .. Last);
171 Elements : constant Elements_Access := new ET'(Left & RE);
173 begin
174 return (Controlled with Elements, Last);
175 end;
176 end "&";
178 function "&" (Left, Right : Element_Type) return Vector is
179 subtype IT is Index_Type'Base range
180 Index_Type'First .. Index_Type'Succ (Index_Type'First);
182 subtype ET is Elements_Type (IT);
184 Elements : constant Elements_Access := new ET'(Left, Right);
186 begin
187 return Vector'(Controlled with Elements, Elements'Last);
188 end "&";
190 ---------
191 -- "=" --
192 ---------
194 function "=" (Left, Right : Vector) return Boolean is
195 begin
196 if Left'Address = Right'Address then
197 return True;
198 end if;
200 if Left.Last /= Right.Last then
201 return False;
202 end if;
204 for J in Index_Type range Index_Type'First .. Left.Last loop
205 if Left.Elements (J) /= Right.Elements (J) then
206 return False;
207 end if;
208 end loop;
210 return True;
211 end "=";
213 ------------
214 -- Adjust --
215 ------------
217 procedure Adjust (Container : in out Vector) is
218 begin
219 if Container.Elements = null then
220 return;
221 end if;
223 if Container.Elements'Length = 0
224 or else Container.Last < Index_Type'First
225 then
226 Container.Elements := null;
227 return;
228 end if;
230 declare
231 X : constant Elements_Access := Container.Elements;
232 L : constant Index_Type'Base := Container.Last;
233 E : Elements_Type renames X (Index_Type'First .. L);
234 begin
235 Container.Elements := null;
236 Container.Last := Index_Type'Pred (Index_Type'First);
237 Container.Elements := new Elements_Type'(E);
238 Container.Last := L;
239 end;
240 end Adjust;
242 ------------
243 -- Append --
244 ------------
246 procedure Append (Container : in out Vector; New_Item : Vector) is
247 begin
248 if Is_Empty (New_Item) then
249 return;
250 end if;
252 Insert
253 (Container,
254 Index_Type'Succ (Container.Last),
255 New_Item);
256 end Append;
258 procedure Append
259 (Container : in out Vector;
260 New_Item : Element_Type;
261 Count : Count_Type := 1)
263 begin
264 if Count = 0 then
265 return;
266 end if;
268 Insert
269 (Container,
270 Index_Type'Succ (Container.Last),
271 New_Item,
272 Count);
273 end Append;
275 ------------
276 -- Assign --
277 ------------
279 procedure Assign
280 (Target : in out Vector;
281 Source : Vector)
283 N : constant Count_Type := Length (Source);
285 begin
286 if Target'Address = Source'Address then
287 return;
288 end if;
290 Clear (Target);
292 if N = 0 then
293 return;
294 end if;
296 if N > Capacity (Target) then
297 Reserve_Capacity (Target, Capacity => N);
298 end if;
300 Target.Elements (Index_Type'First .. Source.Last) :=
301 Source.Elements (Index_Type'First .. Source.Last);
303 Target.Last := Source.Last;
304 end Assign;
306 --------------
307 -- Capacity --
308 --------------
310 function Capacity (Container : Vector) return Count_Type is
311 begin
312 if Container.Elements = null then
313 return 0;
314 end if;
316 return Container.Elements'Length;
317 end Capacity;
319 -----------
320 -- Clear --
321 -----------
323 procedure Clear (Container : in out Vector) is
324 begin
325 Container.Last := Index_Type'Pred (Index_Type'First);
326 end Clear;
328 --------------
329 -- Contains --
330 --------------
332 function Contains
333 (Container : Vector;
334 Item : Element_Type) return Boolean
336 begin
337 return Find_Index (Container, Item) /= No_Index;
338 end Contains;
340 ------------
341 -- Delete --
342 ------------
344 procedure Delete
345 (Container : in out Vector;
346 Index : Extended_Index;
347 Count : Count_Type := 1)
349 begin
350 if Count = 0 then
351 return;
352 end if;
354 declare
355 subtype I_Subtype is Index_Type'Base range
356 Index_Type'First .. Container.Last;
358 I : constant I_Subtype := Index;
359 -- TODO: not sure whether to relax this check ???
361 I_As_Int : constant Int := Int (I);
363 Old_Last_As_Int : constant Int := Index_Type'Pos (Container.Last);
365 Count1 : constant Int'Base := Count_Type'Pos (Count);
366 Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
368 N : constant Int'Base := Int'Min (Count1, Count2);
370 J_As_Int : constant Int'Base := I_As_Int + N;
371 J : constant Index_Type'Base := Index_Type'Base (J_As_Int);
373 E : Elements_Type renames Container.Elements.all;
375 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
377 New_Last : constant Extended_Index :=
378 Extended_Index (New_Last_As_Int);
380 begin
381 E (I .. New_Last) := E (J .. Container.Last);
382 Container.Last := New_Last;
383 end;
384 end Delete;
386 procedure Delete
387 (Container : in out Vector;
388 Position : in out Cursor;
389 Count : Count_Type := 1)
391 begin
393 if Position.Container /= null
394 and then Position.Container /=
395 Vector_Access'(Container'Unchecked_Access)
396 then
397 raise Program_Error;
398 end if;
400 if Position.Container = null
401 or else Position.Index > Container.Last
402 then
403 Position := No_Element;
404 return;
405 end if;
407 Delete (Container, Position.Index, Count);
409 if Position.Index <= Container.Last then
410 Position := (Container'Unchecked_Access, Position.Index);
411 else
412 Position := No_Element;
413 end if;
414 end Delete;
416 ------------------
417 -- Delete_First --
418 ------------------
420 procedure Delete_First
421 (Container : in out Vector;
422 Count : Count_Type := 1)
424 begin
425 if Count = 0 then
426 return;
427 end if;
429 if Count >= Length (Container) then
430 Clear (Container);
431 return;
432 end if;
434 Delete (Container, Index_Type'First, Count);
435 end Delete_First;
437 -----------------
438 -- Delete_Last --
439 -----------------
441 procedure Delete_Last
442 (Container : in out Vector;
443 Count : Count_Type := 1)
445 Index : Int'Base;
447 begin
448 if Count = 0 then
449 return;
450 end if;
452 if Count >= Length (Container) then
453 Clear (Container);
454 return;
455 end if;
457 Index := Int'Base (Container.Last) - Int'Base (Count) + 1;
459 Delete (Container, Index_Type'Base (Index), Count);
460 end Delete_Last;
462 -------------
463 -- Element --
464 -------------
466 function Element
467 (Container : Vector;
468 Index : Index_Type) return Element_Type
470 subtype T is Index_Type'Base range
471 Index_Type'First .. Container.Last;
472 begin
473 return Container.Elements (T'(Index));
474 end Element;
476 function Element (Position : Cursor) return Element_Type is
477 begin
478 return Element (Position.Container.all, Position.Index);
479 end Element;
481 --------------
482 -- Finalize --
483 --------------
485 procedure Finalize (Container : in out Vector) is
486 X : Elements_Access := Container.Elements;
487 begin
488 Container.Elements := null;
489 Container.Last := Index_Type'Pred (Index_Type'First);
490 Free (X);
491 end Finalize;
493 ----------
494 -- Find --
495 ----------
497 function Find
498 (Container : Vector;
499 Item : Element_Type;
500 Position : Cursor := No_Element) return Cursor is
502 begin
503 if Position.Container /= null
504 and then Position.Container /=
505 Vector_Access'(Container'Unchecked_Access)
506 then
507 raise Program_Error;
508 end if;
510 for J in Position.Index .. Container.Last loop
511 if Container.Elements (J) = Item then
512 return (Container'Unchecked_Access, J);
513 end if;
514 end loop;
516 return No_Element;
517 end Find;
519 ----------------
520 -- Find_Index --
521 ----------------
523 function Find_Index
524 (Container : Vector;
525 Item : Element_Type;
526 Index : Index_Type := Index_Type'First) return Extended_Index is
527 begin
528 for Indx in Index .. Container.Last loop
529 if Container.Elements (Indx) = Item then
530 return Indx;
531 end if;
532 end loop;
534 return No_Index;
535 end Find_Index;
537 -----------
538 -- First --
539 -----------
541 function First (Container : Vector) return Cursor is
542 begin
543 if Is_Empty (Container) then
544 return No_Element;
545 end if;
547 return (Container'Unchecked_Access, Index_Type'First);
548 end First;
550 -------------------
551 -- First_Element --
552 -------------------
554 function First_Element (Container : Vector) return Element_Type is
555 begin
556 return Element (Container, Index_Type'First);
557 end First_Element;
559 -----------------
560 -- First_Index --
561 -----------------
563 function First_Index (Container : Vector) return Index_Type is
564 pragma Unreferenced (Container);
565 begin
566 return Index_Type'First;
567 end First_Index;
569 ------------------
570 -- Generic_Sort --
571 ------------------
573 procedure Generic_Sort (Container : Vector)
575 procedure Sort is
576 new Generic_Array_Sort
577 (Index_Type => Index_Type,
578 Element_Type => Element_Type,
579 Array_Type => Elements_Type,
580 "<" => "<");
582 begin
583 if Container.Elements = null then
584 return;
585 end if;
587 Sort (Container.Elements (Index_Type'First .. Container.Last));
588 end Generic_Sort;
590 -----------------
591 -- Has_Element --
592 -----------------
594 function Has_Element (Position : Cursor) return Boolean is
595 begin
596 if Position.Container = null then
597 return False;
598 end if;
600 return Position.Index <= Position.Container.Last;
601 end Has_Element;
603 ------------
604 -- Insert --
605 ------------
607 procedure Insert
608 (Container : in out Vector;
609 Before : Extended_Index;
610 New_Item : Element_Type;
611 Count : Count_Type := 1)
613 Old_Last : constant Extended_Index := Container.Last;
615 Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
617 N : constant Int := Count_Type'Pos (Count);
619 New_Last_As_Int : constant Int'Base := Old_Last_As_Int + N;
621 New_Last : constant Extended_Index := Extended_Index (New_Last_As_Int);
623 Index : Index_Type;
625 Dst_Last : Index_Type;
626 Dst : Elements_Access;
628 begin
629 if Count = 0 then
630 return;
631 end if;
633 declare
634 subtype Before_Subtype is Index_Type'Base range
635 Index_Type'First .. Index_Type'Succ (Container.Last);
637 Old_First : constant Before_Subtype := Before;
639 Old_First_As_Int : constant Int := Index_Type'Pos (Old_First);
641 New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
643 begin
644 Index := Index_Type (New_First_As_Int);
645 end;
647 if Container.Elements = null then
648 declare
649 subtype Elements_Subtype is
650 Elements_Type (Index_Type'First .. New_Last);
651 begin
652 Container.Elements := new Elements_Subtype'(others => New_Item);
653 end;
655 Container.Last := New_Last;
656 return;
657 end if;
659 if New_Last <= Container.Elements'Last then
660 declare
661 E : Elements_Type renames Container.Elements.all;
662 begin
663 E (Index .. New_Last) := E (Before .. Container.Last);
664 E (Before .. Index_Type'Pred (Index)) := (others => New_Item);
665 end;
667 Container.Last := New_Last;
668 return;
669 end if;
671 declare
672 First : constant Int := Int (Index_Type'First);
674 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
675 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
677 Size, Dst_Last_As_Int : Int'Base;
679 begin
680 if New_Size >= Max_Size / 2 then
681 Dst_Last := Index_Type'Last;
683 else
684 Size := Container.Elements'Length;
686 if Size = 0 then
687 Size := 1;
688 end if;
690 while Size < New_Size loop
691 Size := 2 * Size;
692 end loop;
694 Dst_Last_As_Int := First + Size - 1;
695 Dst_Last := Index_Type (Dst_Last_As_Int);
696 end if;
697 end;
699 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
701 declare
702 Src : Elements_Type renames Container.Elements.all;
704 begin
705 Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
706 Src (Index_Type'First .. Index_Type'Pred (Before));
708 Dst (Before .. Index_Type'Pred (Index)) :=
709 (others => New_Item);
711 Dst (Index .. New_Last) :=
712 Src (Before .. Container.Last);
714 exception
715 when others =>
716 Free (Dst);
717 raise;
718 end;
720 declare
721 X : Elements_Access := Container.Elements;
722 begin
723 Container.Elements := Dst;
724 Container.Last := New_Last;
725 Free (X);
726 end;
727 end Insert;
729 procedure Insert
730 (Container : in out Vector;
731 Before : Extended_Index;
732 New_Item : Vector)
734 N : constant Count_Type := Length (New_Item);
736 begin
737 if N = 0 then
738 return;
739 end if;
741 Insert_Space (Container, Before, Count => N);
743 declare
744 Dst_Last_As_Int : constant Int'Base :=
745 Int'Base (Before) + Int'Base (N) - 1;
747 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
749 begin
750 if Container'Address = New_Item'Address then
751 declare
752 subtype Src_Index_Subtype is Index_Type'Base range
753 Index_Type'First .. Index_Type'Pred (Before);
755 Src : Elements_Type renames
756 Container.Elements (Src_Index_Subtype);
758 Index_As_Int : constant Int'Base :=
759 Int (Before) + Src'Length - 1;
761 Index : constant Index_Type'Base :=
762 Index_Type'Base (Index_As_Int);
764 Dst : Elements_Type renames
765 Container.Elements (Before .. Index);
767 begin
768 Dst := Src;
769 end;
771 declare
772 subtype Src_Index_Subtype is Index_Type'Base range
773 Index_Type'Succ (Dst_Last) .. Container.Last;
775 Src : Elements_Type renames
776 Container.Elements (Src_Index_Subtype);
778 Index_As_Int : constant Int'Base :=
779 Dst_Last_As_Int - Src'Length + 1;
781 Index : constant Index_Type'Base :=
782 Index_Type'Base (Index_As_Int);
784 Dst : Elements_Type renames
785 Container.Elements (Index .. Dst_Last);
787 begin
788 Dst := Src;
789 end;
791 else
792 Container.Elements (Before .. Dst_Last) :=
793 New_Item.Elements (Index_Type'First .. New_Item.Last);
794 end if;
795 end;
796 end Insert;
798 procedure Insert
799 (Container : in out Vector;
800 Before : Cursor;
801 New_Item : Vector)
803 Index : Index_Type'Base;
805 begin
806 if Before.Container /= null
807 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
808 then
809 raise Program_Error;
810 end if;
812 if Is_Empty (New_Item) then
813 return;
814 end if;
816 if Before.Container = null
817 or else Before.Index > Container.Last
818 then
819 Index := Index_Type'Succ (Container.Last);
820 else
821 Index := Before.Index;
822 end if;
824 Insert (Container, Index, New_Item);
825 end Insert;
827 procedure Insert
828 (Container : in out Vector;
829 Before : Cursor;
830 New_Item : Vector;
831 Position : out Cursor)
833 Index : Index_Type'Base;
835 begin
836 if Before.Container /= null
837 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
838 then
839 raise Program_Error;
840 end if;
842 if Is_Empty (New_Item) then
843 if Before.Container = null
844 or else Before.Index > Container.Last
845 then
846 Position := No_Element;
847 else
848 Position := (Container'Unchecked_Access, Before.Index);
849 end if;
851 return;
852 end if;
854 if Before.Container = null
855 or else Before.Index > Container.Last
856 then
857 Index := Index_Type'Succ (Container.Last);
858 else
859 Index := Before.Index;
860 end if;
862 Insert (Container, Index, New_Item);
864 Position := Cursor'(Container'Unchecked_Access, Index);
865 end Insert;
867 procedure Insert
868 (Container : in out Vector;
869 Before : Cursor;
870 New_Item : Element_Type;
871 Count : Count_Type := 1)
873 Index : Index_Type'Base;
875 begin
876 if Before.Container /= null
877 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
878 then
879 raise Program_Error;
880 end if;
882 if Count = 0 then
883 return;
884 end if;
886 if Before.Container = null
887 or else Before.Index > Container.Last
888 then
889 Index := Index_Type'Succ (Container.Last);
890 else
891 Index := Before.Index;
892 end if;
894 Insert (Container, Index, New_Item, Count);
895 end Insert;
897 procedure Insert
898 (Container : in out Vector;
899 Before : Cursor;
900 New_Item : Element_Type;
901 Position : out Cursor;
902 Count : Count_Type := 1)
904 Index : Index_Type'Base;
906 begin
907 if Before.Container /= null
908 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
909 then
910 raise Program_Error;
911 end if;
913 if Count = 0 then
914 if Before.Container = null
915 or else Before.Index > Container.Last
916 then
917 Position := No_Element;
918 else
919 Position := (Container'Unchecked_Access, Before.Index);
920 end if;
922 return;
923 end if;
925 if Before.Container = null
926 or else Before.Index > Container.Last
927 then
928 Index := Index_Type'Succ (Container.Last);
929 else
930 Index := Before.Index;
931 end if;
933 Insert (Container, Index, New_Item, Count);
935 Position := Cursor'(Container'Unchecked_Access, Index);
936 end Insert;
938 ------------------
939 -- Insert_Space --
940 ------------------
942 procedure Insert_Space
943 (Container : in out Vector;
944 Before : Extended_Index;
945 Count : Count_Type := 1)
947 Old_Last : constant Extended_Index := Container.Last;
949 Old_Last_As_Int : constant Int := Index_Type'Pos (Old_Last);
951 N : constant Int := Count_Type'Pos (Count);
953 New_Last_As_Int : constant Int'Base := Old_Last_As_Int + N;
955 New_Last : constant Extended_Index := Extended_Index (New_Last_As_Int);
957 Index : Index_Type;
959 Dst_Last : Index_Type;
960 Dst : Elements_Access;
962 begin
963 if Count = 0 then
964 return;
965 end if;
967 declare
968 subtype Before_Subtype is Index_Type'Base range
969 Index_Type'First .. Index_Type'Succ (Container.Last);
971 Old_First : constant Before_Subtype := Before;
973 Old_First_As_Int : constant Int := Index_Type'Pos (Old_First);
975 New_First_As_Int : constant Int'Base := Old_First_As_Int + N;
977 begin
978 Index := Index_Type (New_First_As_Int);
979 end;
981 if Container.Elements = null then
982 Container.Elements :=
983 new Elements_Type (Index_Type'First .. New_Last);
985 Container.Last := New_Last;
986 return;
987 end if;
989 if New_Last <= Container.Elements'Last then
990 declare
991 E : Elements_Type renames Container.Elements.all;
992 begin
993 E (Index .. New_Last) := E (Before .. Container.Last);
994 end;
996 Container.Last := New_Last;
997 return;
998 end if;
1000 declare
1001 First : constant Int := Int (Index_Type'First);
1003 New_Size : constant Int'Base := New_Last_As_Int - First + 1;
1004 Max_Size : constant Int'Base := Int (Index_Type'Last) - First + 1;
1006 Size, Dst_Last_As_Int : Int'Base;
1008 begin
1009 if New_Size >= Max_Size / 2 then
1010 Dst_Last := Index_Type'Last;
1012 else
1013 Size := Container.Elements'Length;
1015 if Size = 0 then
1016 Size := 1;
1017 end if;
1019 while Size < New_Size loop
1020 Size := 2 * Size;
1021 end loop;
1023 Dst_Last_As_Int := First + Size - 1;
1024 Dst_Last := Index_Type (Dst_Last_As_Int);
1025 end if;
1026 end;
1028 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1030 declare
1031 Src : Elements_Type renames Container.Elements.all;
1033 begin
1034 Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
1035 Src (Index_Type'First .. Index_Type'Pred (Before));
1037 Dst (Index .. New_Last) :=
1038 Src (Before .. Container.Last);
1040 exception
1041 when others =>
1042 Free (Dst);
1043 raise;
1044 end;
1046 declare
1047 X : Elements_Access := Container.Elements;
1048 begin
1049 Container.Elements := Dst;
1050 Container.Last := New_Last;
1052 Free (X);
1053 end;
1054 end Insert_Space;
1056 procedure Insert_Space
1057 (Container : in out Vector;
1058 Before : Cursor;
1059 Position : out Cursor;
1060 Count : Count_Type := 1)
1062 Index : Index_Type'Base;
1064 begin
1065 if Before.Container /= null
1066 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1067 then
1068 raise Program_Error;
1069 end if;
1071 if Count = 0 then
1072 if Before.Container = null
1073 or else Before.Index > Container.Last
1074 then
1075 Position := No_Element;
1076 else
1077 Position := (Container'Unchecked_Access, Before.Index);
1078 end if;
1080 return;
1081 end if;
1083 if Before.Container = null
1084 or else Before.Index > Container.Last
1085 then
1086 Index := Index_Type'Succ (Container.Last);
1087 else
1088 Index := Before.Index;
1089 end if;
1091 Insert_Space (Container, Index, Count);
1093 Position := Cursor'(Container'Unchecked_Access, Index);
1094 end Insert_Space;
1096 --------------
1097 -- Is_Empty --
1098 --------------
1100 function Is_Empty (Container : Vector) return Boolean is
1101 begin
1102 return Container.Last < Index_Type'First;
1103 end Is_Empty;
1105 -------------
1106 -- Iterate --
1107 -------------
1109 procedure Iterate
1110 (Container : Vector;
1111 Process : not null access procedure (Position : Cursor))
1113 begin
1114 for Indx in Index_Type'First .. Container.Last loop
1115 Process (Cursor'(Container'Unchecked_Access, Indx));
1116 end loop;
1117 end Iterate;
1119 ----------
1120 -- Last --
1121 ----------
1123 function Last (Container : Vector) return Cursor is
1124 begin
1125 if Is_Empty (Container) then
1126 return No_Element;
1127 end if;
1129 return (Container'Unchecked_Access, Container.Last);
1130 end Last;
1132 ------------------
1133 -- Last_Element --
1134 ------------------
1136 function Last_Element (Container : Vector) return Element_Type is
1137 begin
1138 return Element (Container, Container.Last);
1139 end Last_Element;
1141 ----------------
1142 -- Last_Index --
1143 ----------------
1145 function Last_Index (Container : Vector) return Extended_Index is
1146 begin
1147 return Container.Last;
1148 end Last_Index;
1150 ------------
1151 -- Length --
1152 ------------
1154 function Length (Container : Vector) return Count_Type is
1155 L : constant Int := Int (Container.Last);
1156 F : constant Int := Int (Index_Type'First);
1157 N : constant Int'Base := L - F + 1;
1158 begin
1159 return Count_Type (N);
1160 end Length;
1162 ----------
1163 -- Move --
1164 ----------
1166 procedure Move
1167 (Target : in out Vector;
1168 Source : in out Vector)
1170 X : Elements_Access := Target.Elements;
1172 begin
1173 if Target'Address = Source'Address then
1174 return;
1175 end if;
1177 if Target.Last >= Index_Type'First then
1178 raise Constraint_Error;
1179 end if;
1181 Target.Elements := null;
1182 Free (X);
1184 Target.Elements := Source.Elements;
1185 Target.Last := Source.Last;
1187 Source.Elements := null;
1188 Source.Last := Index_Type'Pred (Index_Type'First);
1189 end Move;
1191 ----------
1192 -- Next --
1193 ----------
1195 function Next (Position : Cursor) return Cursor is
1196 begin
1197 if Position.Container = null then
1198 return No_Element;
1199 end if;
1201 if Position.Index < Position.Container.Last then
1202 return (Position.Container, Index_Type'Succ (Position.Index));
1203 end if;
1205 return No_Element;
1206 end Next;
1208 ----------
1209 -- Next --
1210 ----------
1212 procedure Next (Position : in out Cursor) is
1213 begin
1214 if Position.Container = null then
1215 return;
1216 end if;
1218 if Position.Index < Position.Container.Last then
1219 Position.Index := Index_Type'Succ (Position.Index);
1220 else
1221 Position := No_Element;
1222 end if;
1223 end Next;
1225 -------------
1226 -- Prepend --
1227 -------------
1229 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1230 begin
1231 Insert (Container, Index_Type'First, New_Item);
1232 end Prepend;
1234 procedure Prepend
1235 (Container : in out Vector;
1236 New_Item : Element_Type;
1237 Count : Count_Type := 1)
1239 begin
1240 Insert (Container,
1241 Index_Type'First,
1242 New_Item,
1243 Count);
1244 end Prepend;
1246 --------------
1247 -- Previous --
1248 --------------
1250 procedure Previous (Position : in out Cursor) is
1251 begin
1252 if Position.Container = null then
1253 return;
1254 end if;
1256 if Position.Index > Index_Type'First then
1257 Position.Index := Index_Type'Pred (Position.Index);
1258 else
1259 Position := No_Element;
1260 end if;
1261 end Previous;
1263 function Previous (Position : Cursor) return Cursor is
1264 begin
1265 if Position.Container = null then
1266 return No_Element;
1267 end if;
1269 if Position.Index > Index_Type'First then
1270 return (Position.Container, Index_Type'Pred (Position.Index));
1271 end if;
1273 return No_Element;
1274 end Previous;
1276 -------------------
1277 -- Query_Element --
1278 -------------------
1280 procedure Query_Element
1281 (Container : Vector;
1282 Index : Index_Type;
1283 Process : not null access procedure (Element : Element_Type))
1285 subtype T is Index_Type'Base range
1286 Index_Type'First .. Container.Last;
1287 begin
1288 Process (Container.Elements (T'(Index)));
1289 end Query_Element;
1291 procedure Query_Element
1292 (Position : Cursor;
1293 Process : not null access procedure (Element : Element_Type))
1295 Container : Vector renames Position.Container.all;
1297 subtype T is Index_Type'Base range
1298 Index_Type'First .. Container.Last;
1300 begin
1301 Process (Container.Elements (T'(Position.Index)));
1302 end Query_Element;
1304 ----------
1305 -- Read --
1306 ----------
1308 procedure Read
1309 (Stream : access Root_Stream_Type'Class;
1310 Container : out Vector)
1312 Length : Count_Type'Base;
1313 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1315 begin
1316 Clear (Container);
1318 Count_Type'Base'Read (Stream, Length);
1320 if Length > Capacity (Container) then
1321 Reserve_Capacity (Container, Capacity => Length);
1322 end if;
1324 for J in Count_Type range 1 .. Length loop
1325 Last := Index_Type'Succ (Last);
1326 Element_Type'Read (Stream, Container.Elements (Last));
1327 Container.Last := Last;
1328 end loop;
1329 end Read;
1331 ---------------------
1332 -- Replace_Element --
1333 ---------------------
1335 procedure Replace_Element
1336 (Container : Vector;
1337 Index : Index_Type;
1338 By : Element_Type)
1340 subtype T is Index_Type'Base range
1341 Index_Type'First .. Container.Last;
1342 begin
1343 Container.Elements (T'(Index)) := By;
1344 end Replace_Element;
1346 procedure Replace_Element (Position : Cursor; By : Element_Type) is
1347 subtype T is Index_Type'Base range
1348 Index_Type'First .. Position.Container.Last;
1349 begin
1350 Position.Container.Elements (T'(Position.Index)) := By;
1351 end Replace_Element;
1353 ----------------------
1354 -- Reserve_Capacity --
1355 ----------------------
1357 procedure Reserve_Capacity
1358 (Container : in out Vector;
1359 Capacity : Count_Type)
1361 N : constant Count_Type := Length (Container);
1363 begin
1364 if Capacity = 0 then
1365 if N = 0 then
1366 declare
1367 X : Elements_Access := Container.Elements;
1368 begin
1369 Container.Elements := null;
1370 Free (X);
1371 end;
1373 elsif N < Container.Elements'Length then
1374 declare
1375 subtype Array_Index_Subtype is Index_Type'Base range
1376 Index_Type'First .. Container.Last;
1378 Src : Elements_Type renames
1379 Container.Elements (Array_Index_Subtype);
1381 subtype Array_Subtype is
1382 Elements_Type (Array_Index_Subtype);
1384 X : Elements_Access := Container.Elements;
1386 begin
1387 Container.Elements := new Array_Subtype'(Src);
1388 Free (X);
1389 end;
1390 end if;
1392 return;
1393 end if;
1395 if Container.Elements = null then
1396 declare
1397 Last_As_Int : constant Int'Base :=
1398 Int (Index_Type'First) + Int (Capacity) - 1;
1400 Last : constant Index_Type := Index_Type (Last_As_Int);
1402 subtype Array_Subtype is
1403 Elements_Type (Index_Type'First .. Last);
1405 begin
1406 Container.Elements := new Array_Subtype;
1407 end;
1409 return;
1410 end if;
1412 if Capacity <= N then
1413 if N < Container.Elements'Length then
1414 declare
1415 subtype Array_Index_Subtype is Index_Type'Base range
1416 Index_Type'First .. Container.Last;
1418 Src : Elements_Type renames
1419 Container.Elements (Array_Index_Subtype);
1421 subtype Array_Subtype is
1422 Elements_Type (Array_Index_Subtype);
1424 X : Elements_Access := Container.Elements;
1426 begin
1427 Container.Elements := new Array_Subtype'(Src);
1428 Free (X);
1429 end;
1431 end if;
1433 return;
1434 end if;
1436 if Capacity = Container.Elements'Length then
1437 return;
1438 end if;
1440 declare
1441 Last_As_Int : constant Int'Base :=
1442 Int (Index_Type'First) + Int (Capacity) - 1;
1444 Last : constant Index_Type := Index_Type (Last_As_Int);
1446 subtype Array_Subtype is
1447 Elements_Type (Index_Type'First .. Last);
1449 E : Elements_Access := new Array_Subtype;
1451 begin
1452 declare
1453 Src : Elements_Type renames
1454 Container.Elements (Index_Type'First .. Container.Last);
1456 Tgt : Elements_Type renames
1457 E (Index_Type'First .. Container.Last);
1459 begin
1460 Tgt := Src;
1462 exception
1463 when others =>
1464 Free (E);
1465 raise;
1466 end;
1468 declare
1469 X : Elements_Access := Container.Elements;
1470 begin
1471 Container.Elements := E;
1472 Free (X);
1473 end;
1474 end;
1475 end Reserve_Capacity;
1477 ------------------
1478 -- Reverse_Find --
1479 ------------------
1481 function Reverse_Find
1482 (Container : Vector;
1483 Item : Element_Type;
1484 Position : Cursor := No_Element) return Cursor
1486 Last : Index_Type'Base;
1488 begin
1489 if Position.Container /= null
1490 and then Position.Container /=
1491 Vector_Access'(Container'Unchecked_Access)
1492 then
1493 raise Program_Error;
1494 end if;
1496 if Position.Container = null
1497 or else Position.Index > Container.Last
1498 then
1499 Last := Container.Last;
1500 else
1501 Last := Position.Index;
1502 end if;
1504 for Indx in reverse Index_Type'First .. Last loop
1505 if Container.Elements (Indx) = Item then
1506 return (Container'Unchecked_Access, Indx);
1507 end if;
1508 end loop;
1510 return No_Element;
1511 end Reverse_Find;
1513 ------------------------
1514 -- Reverse_Find_Index --
1515 ------------------------
1517 function Reverse_Find_Index
1518 (Container : Vector;
1519 Item : Element_Type;
1520 Index : Index_Type := Index_Type'Last) return Extended_Index
1522 Last : Index_Type'Base;
1524 begin
1525 if Index > Container.Last then
1526 Last := Container.Last;
1527 else
1528 Last := Index;
1529 end if;
1531 for Indx in reverse Index_Type'First .. Last loop
1532 if Container.Elements (Indx) = Item then
1533 return Indx;
1534 end if;
1535 end loop;
1537 return No_Index;
1538 end Reverse_Find_Index;
1540 ---------------------
1541 -- Reverse_Iterate --
1542 ---------------------
1544 procedure Reverse_Iterate
1545 (Container : Vector;
1546 Process : not null access procedure (Position : Cursor))
1548 begin
1549 for Indx in reverse Index_Type'First .. Container.Last loop
1550 Process (Cursor'(Container'Unchecked_Access, Indx));
1551 end loop;
1552 end Reverse_Iterate;
1554 ----------------
1555 -- Set_Length --
1556 ----------------
1558 procedure Set_Length (Container : in out Vector; Length : Count_Type) is
1559 begin
1560 if Length = 0 then
1561 Clear (Container);
1562 return;
1563 end if;
1565 declare
1566 Last_As_Int : constant Int'Base :=
1567 Int (Index_Type'First) + Int (Length) - 1;
1569 Last : constant Index_Type := Index_Type (Last_As_Int);
1571 begin
1572 if Length > Capacity (Container) then
1573 Reserve_Capacity (Container, Capacity => Length);
1574 end if;
1576 Container.Last := Last;
1577 end;
1578 end Set_Length;
1580 ----------
1581 -- Swap --
1582 ----------
1584 procedure Swap
1585 (Container : Vector;
1586 I, J : Index_Type)
1589 subtype T is Index_Type'Base range
1590 Index_Type'First .. Container.Last;
1592 EI : constant Element_Type := Container.Elements (T'(I));
1594 begin
1596 Container.Elements (T'(I)) := Container.Elements (T'(J));
1597 Container.Elements (T'(J)) := EI;
1599 end Swap;
1601 procedure Swap (I, J : Cursor) is
1603 -- NOTE: The behavior has been liberalized here to
1604 -- allow I and J to designate different containers.
1605 -- TODO: Probably this is supposed to raise P_E ???
1607 subtype TI is Index_Type'Base range
1608 Index_Type'First .. I.Container.Last;
1610 EI : Element_Type renames I.Container.Elements (TI'(I.Index));
1612 EI_Copy : constant Element_Type := EI;
1614 subtype TJ is Index_Type'Base range
1615 Index_Type'First .. J.Container.Last;
1617 EJ : Element_Type renames J.Container.Elements (TJ'(J.Index));
1619 begin
1620 EI := EJ;
1621 EJ := EI_Copy;
1622 end Swap;
1624 ---------------
1625 -- To_Cursor --
1626 ---------------
1628 function To_Cursor
1629 (Container : Vector;
1630 Index : Extended_Index) return Cursor
1632 begin
1633 if Index not in Index_Type'First .. Container.Last then
1634 return No_Element;
1635 end if;
1637 return Cursor'(Container'Unchecked_Access, Index);
1638 end To_Cursor;
1640 --------------
1641 -- To_Index --
1642 --------------
1644 function To_Index (Position : Cursor) return Extended_Index is
1645 begin
1646 if Position.Container = null then
1647 return No_Index;
1648 end if;
1650 if Position.Index <= Position.Container.Last then
1651 return Position.Index;
1652 end if;
1654 return No_Index;
1655 end To_Index;
1657 ---------------
1658 -- To_Vector --
1659 ---------------
1661 function To_Vector (Length : Count_Type) return Vector is
1662 begin
1663 if Length = 0 then
1664 return Empty_Vector;
1665 end if;
1667 declare
1668 First : constant Int := Int (Index_Type'First);
1669 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
1670 Last : constant Index_Type := Index_Type (Last_As_Int);
1671 Elements : constant Elements_Access :=
1672 new Elements_Type (Index_Type'First .. Last);
1673 begin
1674 return (Controlled with Elements, Last);
1675 end;
1676 end To_Vector;
1678 function To_Vector
1679 (New_Item : Element_Type;
1680 Length : Count_Type) return Vector
1682 begin
1683 if Length = 0 then
1684 return Empty_Vector;
1685 end if;
1687 declare
1688 First : constant Int := Int (Index_Type'First);
1689 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
1690 Last : constant Index_Type := Index_Type (Last_As_Int);
1691 Elements : constant Elements_Access :=
1692 new Elements_Type'
1693 (Index_Type'First .. Last => New_Item);
1694 begin
1695 return (Controlled with Elements, Last);
1696 end;
1697 end To_Vector;
1699 --------------------
1700 -- Update_Element --
1701 --------------------
1703 procedure Update_Element
1704 (Container : Vector;
1705 Index : Index_Type;
1706 Process : not null access procedure (Element : in out Element_Type))
1708 subtype T is Index_Type'Base range
1709 Index_Type'First .. Container.Last;
1710 begin
1711 Process (Container.Elements (T'(Index)));
1712 end Update_Element;
1714 procedure Update_Element
1715 (Position : Cursor;
1716 Process : not null access procedure (Element : in out Element_Type))
1718 subtype T is Index_Type'Base range
1719 Index_Type'First .. Position.Container.Last;
1720 begin
1721 Process (Position.Container.Elements (T'(Position.Index)));
1722 end Update_Element;
1724 -----------
1725 -- Write --
1726 -----------
1728 procedure Write
1729 (Stream : access Root_Stream_Type'Class;
1730 Container : Vector)
1732 begin
1733 Count_Type'Base'Write (Stream, Length (Container));
1735 for J in Index_Type'First .. Container.Last loop
1736 Element_Type'Write (Stream, Container.Elements (J));
1737 end loop;
1738 end Write;
1740 end Ada.Containers.Vectors;