PR ada/18819
[official-gcc.git] / gcc / ada / a-convec.adb
blobf08b70416a7196dcdce187da90dfb82950247d84
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-2006 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- This unit was originally developed by Matthew J Heaney. --
30 ------------------------------------------------------------------------------
32 with Ada.Containers.Generic_Array_Sort;
33 with Ada.Unchecked_Deallocation;
35 with System; use type System.Address;
37 package body Ada.Containers.Vectors is
39 type Int is range System.Min_Int .. System.Max_Int;
40 type UInt is mod System.Max_Binary_Modulus;
42 procedure Free is
43 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
45 ---------
46 -- "&" --
47 ---------
49 function "&" (Left, Right : Vector) return Vector is
50 LN : constant Count_Type := Length (Left);
51 RN : constant Count_Type := Length (Right);
53 begin
54 if LN = 0 then
55 if RN = 0 then
56 return Empty_Vector;
57 end if;
59 declare
60 RE : Elements_Type renames
61 Right.Elements (Index_Type'First .. Right.Last);
63 Elements : constant Elements_Access :=
64 new Elements_Type'(RE);
66 begin
67 return (Controlled with Elements, Right.Last, 0, 0);
68 end;
69 end if;
71 if RN = 0 then
72 declare
73 LE : Elements_Type renames
74 Left.Elements (Index_Type'First .. Left.Last);
76 Elements : constant Elements_Access :=
77 new Elements_Type'(LE);
79 begin
80 return (Controlled with Elements, Left.Last, 0, 0);
81 end;
83 end if;
85 declare
86 N : constant Int'Base := Int (LN) + Int (RN);
87 Last_As_Int : Int'Base;
89 begin
90 if Int (No_Index) > Int'Last - N then
91 raise Constraint_Error with "new length is out of range";
92 end if;
94 Last_As_Int := Int (No_Index) + N;
96 if Last_As_Int > Int (Index_Type'Last) then
97 raise Constraint_Error with "new length is out of range";
98 end if;
100 declare
101 Last : constant Index_Type := Index_Type (Last_As_Int);
103 LE : Elements_Type renames
104 Left.Elements (Index_Type'First .. Left.Last);
106 RE : Elements_Type renames
107 Right.Elements (Index_Type'First .. Right.Last);
109 Elements : constant Elements_Access :=
110 new Elements_Type'(LE & RE);
112 begin
113 return (Controlled with Elements, Last, 0, 0);
114 end;
115 end;
116 end "&";
118 function "&" (Left : Vector; Right : Element_Type) return Vector is
119 LN : constant Count_Type := Length (Left);
121 begin
122 if LN = 0 then
123 declare
124 subtype Elements_Subtype is
125 Elements_Type (Index_Type'First .. Index_Type'First);
127 Elements : constant Elements_Access :=
128 new Elements_Subtype'(others => Right);
130 begin
131 return (Controlled with Elements, Index_Type'First, 0, 0);
132 end;
133 end if;
135 declare
136 Last_As_Int : Int'Base;
138 begin
139 if Int (Index_Type'First) > Int'Last - Int (LN) then
140 raise Constraint_Error with "new length is out of range";
141 end if;
143 Last_As_Int := Int (Index_Type'First) + Int (LN);
145 if Last_As_Int > Int (Index_Type'Last) then
146 raise Constraint_Error with "new length is out of range";
147 end if;
149 declare
150 Last : constant Index_Type := Index_Type (Last_As_Int);
152 LE : Elements_Type renames
153 Left.Elements (Index_Type'First .. Left.Last);
155 subtype ET is Elements_Type (Index_Type'First .. Last);
157 Elements : constant Elements_Access := new ET'(LE & Right);
159 begin
160 return (Controlled with Elements, Last, 0, 0);
161 end;
162 end;
163 end "&";
165 function "&" (Left : Element_Type; Right : Vector) return Vector is
166 RN : constant Count_Type := Length (Right);
168 begin
169 if RN = 0 then
170 declare
171 subtype Elements_Subtype is
172 Elements_Type (Index_Type'First .. Index_Type'First);
174 Elements : constant Elements_Access :=
175 new Elements_Subtype'(others => Left);
177 begin
178 return (Controlled with Elements, Index_Type'First, 0, 0);
179 end;
180 end if;
182 declare
183 Last_As_Int : Int'Base;
185 begin
186 if Int (Index_Type'First) > Int'Last - Int (RN) then
187 raise Constraint_Error with "new length is out of range";
188 end if;
190 Last_As_Int := Int (Index_Type'First) + Int (RN);
192 if Last_As_Int > Int (Index_Type'Last) then
193 raise Constraint_Error with "new length is out of range";
194 end if;
196 declare
197 Last : constant Index_Type := Index_Type (Last_As_Int);
199 RE : Elements_Type renames
200 Right.Elements (Index_Type'First .. Right.Last);
202 subtype ET is Elements_Type (Index_Type'First .. Last);
204 Elements : constant Elements_Access := new ET'(Left & RE);
206 begin
207 return (Controlled with Elements, Last, 0, 0);
208 end;
209 end;
210 end "&";
212 function "&" (Left, Right : Element_Type) return Vector is
213 begin
214 if Index_Type'First >= Index_Type'Last then
215 raise Constraint_Error with "new length is out of range";
216 end if;
218 declare
219 Last : constant Index_Type := Index_Type'First + 1;
221 subtype ET is Elements_Type (Index_Type'First .. Last);
223 Elements : constant Elements_Access := new ET'(Left, Right);
225 begin
226 return (Controlled with Elements, Last, 0, 0);
227 end;
228 end "&";
230 ---------
231 -- "=" --
232 ---------
234 function "=" (Left, Right : Vector) return Boolean is
235 begin
236 if Left'Address = Right'Address then
237 return True;
238 end if;
240 if Left.Last /= Right.Last then
241 return False;
242 end if;
244 for J in Index_Type range Index_Type'First .. Left.Last loop
245 if Left.Elements (J) /= Right.Elements (J) then
246 return False;
247 end if;
248 end loop;
250 return True;
251 end "=";
253 ------------
254 -- Adjust --
255 ------------
257 procedure Adjust (Container : in out Vector) is
258 begin
259 if Container.Last = No_Index then
260 Container.Elements := null;
261 return;
262 end if;
264 declare
265 E : constant Elements_Access := Container.Elements;
266 L : constant Index_Type := Container.Last;
268 begin
269 Container.Elements := null;
270 Container.Last := No_Index;
271 Container.Busy := 0;
272 Container.Lock := 0;
273 Container.Elements := new Elements_Type'(E (Index_Type'First .. L));
274 Container.Last := L;
275 end;
276 end Adjust;
278 ------------
279 -- Append --
280 ------------
282 procedure Append (Container : in out Vector; New_Item : Vector) is
283 begin
284 if Is_Empty (New_Item) then
285 return;
286 end if;
288 if Container.Last = Index_Type'Last then
289 raise Constraint_Error with "vector is already at its maximum length";
290 end if;
292 Insert
293 (Container,
294 Container.Last + 1,
295 New_Item);
296 end Append;
298 procedure Append
299 (Container : in out Vector;
300 New_Item : Element_Type;
301 Count : Count_Type := 1)
303 begin
304 if Count = 0 then
305 return;
306 end if;
308 if Container.Last = Index_Type'Last then
309 raise Constraint_Error with "vector is already at its maximum length";
310 end if;
312 Insert
313 (Container,
314 Container.Last + 1,
315 New_Item,
316 Count);
317 end Append;
319 --------------
320 -- Capacity --
321 --------------
323 function Capacity (Container : Vector) return Count_Type is
324 begin
325 if Container.Elements = null then
326 return 0;
327 end if;
329 return Container.Elements'Length;
330 end Capacity;
332 -----------
333 -- Clear --
334 -----------
336 procedure Clear (Container : in out Vector) is
337 begin
338 if Container.Busy > 0 then
339 raise Program_Error with
340 "attempt to tamper with elements (vector is busy)";
341 end if;
343 Container.Last := No_Index;
344 end Clear;
346 --------------
347 -- Contains --
348 --------------
350 function Contains
351 (Container : Vector;
352 Item : Element_Type) return Boolean
354 begin
355 return Find_Index (Container, Item) /= No_Index;
356 end Contains;
358 ------------
359 -- Delete --
360 ------------
362 procedure Delete
363 (Container : in out Vector;
364 Index : Extended_Index;
365 Count : Count_Type := 1)
367 begin
368 if Index < Index_Type'First then
369 raise Constraint_Error with "Index is out of range (too small)";
370 end if;
372 if Index > Container.Last then
373 if Index > Container.Last + 1 then
374 raise Constraint_Error with "Index is out of range (too large)";
375 end if;
377 return;
378 end if;
380 if Count = 0 then
381 return;
382 end if;
384 if Container.Busy > 0 then
385 raise Program_Error with
386 "attempt to tamper with elements (vector is busy)";
387 end if;
389 declare
390 I_As_Int : constant Int := Int (Index);
391 Old_Last_As_Int : constant Int := Index_Type'Pos (Container.Last);
393 Count1 : constant Int'Base := Count_Type'Pos (Count);
394 Count2 : constant Int'Base := Old_Last_As_Int - I_As_Int + 1;
395 N : constant Int'Base := Int'Min (Count1, Count2);
397 J_As_Int : constant Int'Base := I_As_Int + N;
399 begin
400 if J_As_Int > Old_Last_As_Int then
401 Container.Last := Index - 1;
403 else
404 declare
405 J : constant Index_Type := Index_Type (J_As_Int);
406 E : Elements_Type renames Container.Elements.all;
408 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
409 New_Last : constant Index_Type :=
410 Index_Type (New_Last_As_Int);
412 begin
413 E (Index .. New_Last) := E (J .. Container.Last);
414 Container.Last := New_Last;
415 end;
416 end if;
417 end;
418 end Delete;
420 procedure Delete
421 (Container : in out Vector;
422 Position : in out Cursor;
423 Count : Count_Type := 1)
425 begin
426 if Position.Container = null then
427 raise Constraint_Error with "Position cursor has no element";
428 end if;
430 if Position.Container /= Container'Unrestricted_Access then
431 raise Program_Error with "Position cursor denotes wrong container";
432 end if;
434 if Position.Index > Container.Last then
435 raise Program_Error with "Position index is out of range";
436 end if;
438 Delete (Container, Position.Index, Count);
440 -- This is the old behavior, prior to the York API (2005/06):
442 -- if Position.Index <= Container.Last then
443 -- Position := (Container'Unchecked_Access, Position.Index);
444 -- else
445 -- Position := No_Element;
446 -- end if;
448 -- This is the behavior specified by the York API:
450 Position := No_Element;
451 end Delete;
453 ------------------
454 -- Delete_First --
455 ------------------
457 procedure Delete_First
458 (Container : in out Vector;
459 Count : Count_Type := 1)
461 begin
462 if Count = 0 then
463 return;
464 end if;
466 if Count >= Length (Container) then
467 Clear (Container);
468 return;
469 end if;
471 Delete (Container, Index_Type'First, Count);
472 end Delete_First;
474 -----------------
475 -- Delete_Last --
476 -----------------
478 procedure Delete_Last
479 (Container : in out Vector;
480 Count : Count_Type := 1)
482 Index : Int'Base;
484 begin
485 if Count = 0 then
486 return;
487 end if;
489 if Container.Busy > 0 then
490 raise Program_Error with
491 "attempt to tamper with elements (vector is busy)";
492 end if;
494 Index := Int'Base (Container.Last) - Int'Base (Count);
496 if Index < Index_Type'Pos (Index_Type'First) then
497 Container.Last := No_Index;
498 else
499 Container.Last := Index_Type (Index);
500 end if;
501 end Delete_Last;
503 -------------
504 -- Element --
505 -------------
507 function Element
508 (Container : Vector;
509 Index : Index_Type) return Element_Type
511 begin
512 if Index > Container.Last then
513 raise Constraint_Error with "Index is out of range";
514 end if;
516 return Container.Elements (Index);
517 end Element;
519 function Element (Position : Cursor) return Element_Type is
520 begin
521 if Position.Container = null then
522 raise Constraint_Error with "Position cursor has no element";
523 end if;
525 return Element (Position.Container.all, 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 (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 (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 return Element (Container, Index_Type'First);
614 end First_Element;
616 -----------------
617 -- First_Index --
618 -----------------
620 function First_Index (Container : Vector) return Index_Type is
621 pragma Unreferenced (Container);
622 begin
623 return Index_Type'First;
624 end First_Index;
626 ---------------------
627 -- Generic_Sorting --
628 ---------------------
630 package body Generic_Sorting is
632 ---------------
633 -- Is_Sorted --
634 ---------------
636 function Is_Sorted (Container : Vector) return Boolean is
637 begin
638 if Container.Last <= Index_Type'First then
639 return True;
640 end if;
642 declare
643 E : Elements_Type renames Container.Elements.all;
644 begin
645 for I in Index_Type'First .. Container.Last - 1 loop
646 if E (I + 1) < E (I) then
647 return False;
648 end if;
649 end loop;
650 end;
652 return True;
653 end Is_Sorted;
655 -----------
656 -- Merge --
657 -----------
659 procedure Merge (Target, Source : in out Vector) is
660 I : Index_Type'Base := Target.Last;
661 J : Index_Type'Base;
663 begin
664 if Target.Last < Index_Type'First then
665 Move (Target => Target, Source => Source);
666 return;
667 end if;
669 if Target'Address = Source'Address then
670 return;
671 end if;
673 if Source.Last < Index_Type'First then
674 return;
675 end if;
677 if Source.Busy > 0 then
678 raise Program_Error with
679 "attempt to tamper with elements (vector is busy)";
680 end if;
682 Target.Set_Length (Length (Target) + Length (Source));
684 J := Target.Last;
685 while Source.Last >= Index_Type'First loop
686 pragma Assert (Source.Last <= Index_Type'First
687 or else not (Source.Elements (Source.Last) <
688 Source.Elements (Source.Last - 1)));
690 if I < Index_Type'First then
691 Target.Elements (Index_Type'First .. J) :=
692 Source.Elements (Index_Type'First .. Source.Last);
694 Source.Last := No_Index;
695 return;
696 end if;
698 pragma Assert (I <= Index_Type'First
699 or else not (Target.Elements (I) <
700 Target.Elements (I - 1)));
702 if Source.Elements (Source.Last) < Target.Elements (I) then
703 Target.Elements (J) := Target.Elements (I);
704 I := I - 1;
706 else
707 Target.Elements (J) := Source.Elements (Source.Last);
708 Source.Last := Source.Last - 1;
709 end if;
711 J := J - 1;
712 end loop;
713 end Merge;
715 ----------
716 -- Sort --
717 ----------
719 procedure Sort (Container : in out Vector)
721 procedure Sort is
722 new Generic_Array_Sort
723 (Index_Type => Index_Type,
724 Element_Type => Element_Type,
725 Array_Type => Elements_Type,
726 "<" => "<");
728 begin
729 if Container.Last <= Index_Type'First then
730 return;
731 end if;
733 if Container.Lock > 0 then
734 raise Program_Error with
735 "attempt to tamper with cursors (vector is locked)";
736 end if;
738 Sort (Container.Elements (Index_Type'First .. Container.Last));
739 end Sort;
741 end Generic_Sorting;
743 -----------------
744 -- Has_Element --
745 -----------------
747 function Has_Element (Position : Cursor) return Boolean is
748 begin
749 if Position.Container = null then
750 return False;
751 end if;
753 return Position.Index <= Position.Container.Last;
754 end Has_Element;
756 ------------
757 -- Insert --
758 ------------
760 procedure Insert
761 (Container : in out Vector;
762 Before : Extended_Index;
763 New_Item : Element_Type;
764 Count : Count_Type := 1)
766 N : constant Int := Count_Type'Pos (Count);
768 First : constant Int := Int (Index_Type'First);
769 New_Last_As_Int : Int'Base;
770 New_Last : Index_Type;
771 New_Length : UInt;
772 Max_Length : constant UInt := UInt (Count_Type'Last);
774 Dst : Elements_Access;
776 begin
777 if Before < Index_Type'First then
778 raise Constraint_Error with
779 "Before index is out of range (too small)";
780 end if;
782 if Before > Container.Last
783 and then Before > Container.Last + 1
784 then
785 raise Constraint_Error with
786 "Before index is out of range (too large)";
787 end if;
789 if Count = 0 then
790 return;
791 end if;
793 declare
794 Old_Last_As_Int : constant Int := Int (Container.Last);
796 begin
797 if Old_Last_As_Int > Int'Last - N then
798 raise Constraint_Error with "new length is out of range";
799 end if;
801 New_Last_As_Int := Old_Last_As_Int + N;
803 if New_Last_As_Int > Int (Index_Type'Last) then
804 raise Constraint_Error with "new length is out of range";
805 end if;
807 New_Length := UInt (New_Last_As_Int - First + Int'(1));
809 if New_Length > Max_Length then
810 raise Constraint_Error with "new length is out of range";
811 end if;
813 New_Last := Index_Type (New_Last_As_Int);
814 end;
816 if Container.Busy > 0 then
817 raise Program_Error with
818 "attempt to tamper with elements (vector is busy)";
819 end if;
821 if Container.Elements = null then
822 declare
823 subtype Elements_Subtype is
824 Elements_Type (Index_Type'First .. New_Last);
825 begin
826 Container.Elements := new Elements_Subtype'(others => New_Item);
827 end;
829 Container.Last := New_Last;
830 return;
831 end if;
833 if New_Last <= Container.Elements'Last then
834 declare
835 E : Elements_Type renames Container.Elements.all;
837 begin
838 if Before <= Container.Last then
839 declare
840 Index_As_Int : constant Int'Base :=
841 Index_Type'Pos (Before) + N;
843 Index : constant Index_Type := Index_Type (Index_As_Int);
845 begin
846 E (Index .. New_Last) := E (Before .. Container.Last);
848 E (Before .. Index_Type'Pred (Index)) :=
849 (others => New_Item);
850 end;
852 else
853 E (Before .. New_Last) := (others => New_Item);
854 end if;
855 end;
857 Container.Last := New_Last;
858 return;
859 end if;
861 declare
862 C, CC : UInt;
864 begin
865 C := UInt'Max (1, Container.Elements'Length);
866 while C < New_Length loop
867 if C > UInt'Last / 2 then
868 C := UInt'Last;
869 exit;
870 end if;
872 C := 2 * C;
873 end loop;
875 if C > Max_Length then
876 C := Max_Length;
877 end if;
879 if Index_Type'First <= 0
880 and then Index_Type'Last >= 0
881 then
882 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
884 else
885 CC := UInt (Int (Index_Type'Last) - First + 1);
886 end if;
888 if C > CC then
889 C := CC;
890 end if;
892 declare
893 Dst_Last : constant Index_Type :=
894 Index_Type (First + UInt'Pos (C) - 1);
896 begin
897 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
898 end;
899 end;
901 declare
902 Src : Elements_Type renames Container.Elements.all;
904 begin
905 Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
906 Src (Index_Type'First .. Index_Type'Pred (Before));
908 if Before <= Container.Last then
909 declare
910 Index_As_Int : constant Int'Base :=
911 Index_Type'Pos (Before) + N;
913 Index : constant Index_Type := Index_Type (Index_As_Int);
915 begin
916 Dst (Before .. Index_Type'Pred (Index)) := (others => New_Item);
917 Dst (Index .. New_Last) := Src (Before .. Container.Last);
918 end;
920 else
921 Dst (Before .. New_Last) := (others => New_Item);
922 end if;
923 exception
924 when others =>
925 Free (Dst);
926 raise;
927 end;
929 declare
930 X : Elements_Access := Container.Elements;
931 begin
932 Container.Elements := Dst;
933 Container.Last := New_Last;
934 Free (X);
935 end;
936 end Insert;
938 procedure Insert
939 (Container : in out Vector;
940 Before : Extended_Index;
941 New_Item : Vector)
943 N : constant Count_Type := Length (New_Item);
945 begin
946 if Before < Index_Type'First then
947 raise Constraint_Error with
948 "Before index is out of range (too small)";
949 end if;
951 if Before > Container.Last
952 and then Before > Container.Last + 1
953 then
954 raise Constraint_Error with
955 "Before index is out of range (too large)";
956 end if;
958 if N = 0 then
959 return;
960 end if;
962 Insert_Space (Container, Before, Count => N);
964 declare
965 Dst_Last_As_Int : constant Int'Base :=
966 Int'Base (Before) + Int'Base (N) - 1;
968 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
970 begin
971 if Container'Address /= New_Item'Address then
972 Container.Elements (Before .. Dst_Last) :=
973 New_Item.Elements (Index_Type'First .. New_Item.Last);
975 return;
976 end if;
978 declare
979 subtype Src_Index_Subtype is Index_Type'Base range
980 Index_Type'First .. Before - 1;
982 Src : Elements_Type renames
983 Container.Elements (Src_Index_Subtype);
985 Index_As_Int : constant Int'Base :=
986 Int (Before) + Src'Length - 1;
988 Index : constant Index_Type'Base :=
989 Index_Type'Base (Index_As_Int);
991 Dst : Elements_Type renames
992 Container.Elements (Before .. Index);
994 begin
995 Dst := Src;
996 end;
998 if Dst_Last = Container.Last then
999 return;
1000 end if;
1002 declare
1003 subtype Src_Index_Subtype is Index_Type'Base range
1004 Dst_Last + 1 .. Container.Last;
1006 Src : Elements_Type renames
1007 Container.Elements (Src_Index_Subtype);
1009 Index_As_Int : constant Int'Base :=
1010 Dst_Last_As_Int - Src'Length + 1;
1012 Index : constant Index_Type :=
1013 Index_Type (Index_As_Int);
1015 Dst : Elements_Type renames
1016 Container.Elements (Index .. Dst_Last);
1018 begin
1019 Dst := Src;
1020 end;
1021 end;
1022 end Insert;
1024 procedure Insert
1025 (Container : in out Vector;
1026 Before : Cursor;
1027 New_Item : Vector)
1029 Index : Index_Type'Base;
1031 begin
1032 if Before.Container /= null
1033 and then Before.Container /= Container'Unchecked_Access
1034 then
1035 raise Program_Error with "Before cursor denotes wrong container";
1036 end if;
1038 if Is_Empty (New_Item) then
1039 return;
1040 end if;
1042 if Before.Container = null
1043 or else Before.Index > Container.Last
1044 then
1045 if Container.Last = Index_Type'Last then
1046 raise Constraint_Error with
1047 "vector is already at its maximum length";
1048 end if;
1050 Index := Container.Last + 1;
1052 else
1053 Index := Before.Index;
1054 end if;
1056 Insert (Container, Index, New_Item);
1057 end Insert;
1059 procedure Insert
1060 (Container : in out Vector;
1061 Before : Cursor;
1062 New_Item : Vector;
1063 Position : out Cursor)
1065 Index : Index_Type'Base;
1067 begin
1068 if Before.Container /= null
1069 and then Before.Container /= Container'Unchecked_Access
1070 then
1071 raise Program_Error with "Before cursor denotes wrong container";
1072 end if;
1074 if Is_Empty (New_Item) then
1075 if Before.Container = null
1076 or else Before.Index > Container.Last
1077 then
1078 Position := No_Element;
1079 else
1080 Position := (Container'Unchecked_Access, Before.Index);
1081 end if;
1083 return;
1084 end if;
1086 if Before.Container = null
1087 or else Before.Index > Container.Last
1088 then
1089 if Container.Last = Index_Type'Last then
1090 raise Constraint_Error with
1091 "vector is already at its maximum length";
1092 end if;
1094 Index := Container.Last + 1;
1096 else
1097 Index := Before.Index;
1098 end if;
1100 Insert (Container, Index, New_Item);
1102 Position := Cursor'(Container'Unchecked_Access, Index);
1103 end Insert;
1105 procedure Insert
1106 (Container : in out Vector;
1107 Before : Cursor;
1108 New_Item : Element_Type;
1109 Count : Count_Type := 1)
1111 Index : Index_Type'Base;
1113 begin
1114 if Before.Container /= null
1115 and then Before.Container /= Container'Unchecked_Access
1116 then
1117 raise Program_Error with "Before cursor denotes wrong container";
1118 end if;
1120 if Count = 0 then
1121 return;
1122 end if;
1124 if Before.Container = null
1125 or else Before.Index > Container.Last
1126 then
1127 if Container.Last = Index_Type'Last then
1128 raise Constraint_Error with
1129 "vector is already at its maximum length";
1130 end if;
1132 Index := Container.Last + 1;
1134 else
1135 Index := Before.Index;
1136 end if;
1138 Insert (Container, Index, New_Item, Count);
1139 end Insert;
1141 procedure Insert
1142 (Container : in out Vector;
1143 Before : Cursor;
1144 New_Item : Element_Type;
1145 Position : out Cursor;
1146 Count : Count_Type := 1)
1148 Index : Index_Type'Base;
1150 begin
1151 if Before.Container /= null
1152 and then Before.Container /= Container'Unchecked_Access
1153 then
1154 raise Program_Error with "Before cursor denotes wrong container";
1155 end if;
1157 if Count = 0 then
1158 if Before.Container = null
1159 or else Before.Index > Container.Last
1160 then
1161 Position := No_Element;
1162 else
1163 Position := (Container'Unchecked_Access, Before.Index);
1164 end if;
1166 return;
1167 end if;
1169 if Before.Container = null
1170 or else Before.Index > Container.Last
1171 then
1172 if Container.Last = Index_Type'Last then
1173 raise Constraint_Error with
1174 "vector is already at its maximum length";
1175 end if;
1177 Index := Container.Last + 1;
1179 else
1180 Index := Before.Index;
1181 end if;
1183 Insert (Container, Index, New_Item, Count);
1185 Position := Cursor'(Container'Unchecked_Access, Index);
1186 end Insert;
1188 procedure Insert
1189 (Container : in out Vector;
1190 Before : Extended_Index;
1191 Count : Count_Type := 1)
1193 New_Item : Element_Type; -- Default-initialized value
1194 pragma Warnings (Off, New_Item);
1196 begin
1197 Insert (Container, Before, New_Item, Count);
1198 end Insert;
1200 procedure Insert
1201 (Container : in out Vector;
1202 Before : Cursor;
1203 Position : out Cursor;
1204 Count : Count_Type := 1)
1206 New_Item : Element_Type; -- Default-initialized value
1207 pragma Warnings (Off, New_Item);
1209 begin
1210 Insert (Container, Before, New_Item, Position, Count);
1211 end Insert;
1213 ------------------
1214 -- Insert_Space --
1215 ------------------
1217 procedure Insert_Space
1218 (Container : in out Vector;
1219 Before : Extended_Index;
1220 Count : Count_Type := 1)
1222 N : constant Int := Count_Type'Pos (Count);
1224 First : constant Int := Int (Index_Type'First);
1225 New_Last_As_Int : Int'Base;
1226 New_Last : Index_Type;
1227 New_Length : UInt;
1228 Max_Length : constant UInt := UInt (Count_Type'Last);
1230 Dst : Elements_Access;
1232 begin
1233 if Before < Index_Type'First then
1234 raise Constraint_Error with
1235 "Before index is out of range (too small)";
1236 end if;
1238 if Before > Container.Last
1239 and then Before > Container.Last + 1
1240 then
1241 raise Constraint_Error with
1242 "Before index is out of range (too large)";
1243 end if;
1245 if Count = 0 then
1246 return;
1247 end if;
1249 declare
1250 Old_Last_As_Int : constant Int := Int (Container.Last);
1252 begin
1253 if Old_Last_As_Int > Int'Last - N then
1254 raise Constraint_Error with "new length is out of range";
1255 end if;
1257 New_Last_As_Int := Old_Last_As_Int + N;
1259 if New_Last_As_Int > Int (Index_Type'Last) then
1260 raise Constraint_Error with "new length is out of range";
1261 end if;
1263 New_Length := UInt (New_Last_As_Int - First + Int'(1));
1265 if New_Length > Max_Length then
1266 raise Constraint_Error with "new length is out of range";
1267 end if;
1269 New_Last := Index_Type (New_Last_As_Int);
1270 end;
1272 if Container.Busy > 0 then
1273 raise Program_Error with
1274 "attempt to tamper with elements (vector is busy)";
1275 end if;
1277 if Container.Elements = null then
1278 Container.Elements :=
1279 new Elements_Type (Index_Type'First .. New_Last);
1281 Container.Last := New_Last;
1282 return;
1283 end if;
1285 if New_Last <= Container.Elements'Last then
1286 declare
1287 E : Elements_Type renames Container.Elements.all;
1288 begin
1289 if Before <= Container.Last then
1290 declare
1291 Index_As_Int : constant Int'Base :=
1292 Index_Type'Pos (Before) + N;
1294 Index : constant Index_Type := Index_Type (Index_As_Int);
1296 begin
1297 E (Index .. New_Last) := E (Before .. Container.Last);
1298 end;
1299 end if;
1300 end;
1302 Container.Last := New_Last;
1303 return;
1304 end if;
1306 declare
1307 C, CC : UInt;
1309 begin
1310 C := UInt'Max (1, Container.Elements'Length);
1311 while C < New_Length loop
1312 if C > UInt'Last / 2 then
1313 C := UInt'Last;
1314 exit;
1315 end if;
1317 C := 2 * C;
1318 end loop;
1320 if C > Max_Length then
1321 C := Max_Length;
1322 end if;
1324 if Index_Type'First <= 0
1325 and then Index_Type'Last >= 0
1326 then
1327 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1329 else
1330 CC := UInt (Int (Index_Type'Last) - First + 1);
1331 end if;
1333 if C > CC then
1334 C := CC;
1335 end if;
1337 declare
1338 Dst_Last : constant Index_Type :=
1339 Index_Type (First + UInt'Pos (C) - 1);
1341 begin
1342 Dst := new Elements_Type (Index_Type'First .. Dst_Last);
1343 end;
1344 end;
1346 declare
1347 Src : Elements_Type renames Container.Elements.all;
1349 begin
1350 Dst (Index_Type'First .. Index_Type'Pred (Before)) :=
1351 Src (Index_Type'First .. Index_Type'Pred (Before));
1353 if Before <= Container.Last then
1354 declare
1355 Index_As_Int : constant Int'Base :=
1356 Index_Type'Pos (Before) + N;
1358 Index : constant Index_Type := Index_Type (Index_As_Int);
1360 begin
1361 Dst (Index .. New_Last) := Src (Before .. Container.Last);
1362 end;
1363 end if;
1364 exception
1365 when others =>
1366 Free (Dst);
1367 raise;
1368 end;
1370 declare
1371 X : Elements_Access := Container.Elements;
1372 begin
1373 Container.Elements := Dst;
1374 Container.Last := New_Last;
1375 Free (X);
1376 end;
1377 end Insert_Space;
1379 procedure Insert_Space
1380 (Container : in out Vector;
1381 Before : Cursor;
1382 Position : out Cursor;
1383 Count : Count_Type := 1)
1385 Index : Index_Type'Base;
1387 begin
1388 if Before.Container /= null
1389 and then Before.Container /= Container'Unchecked_Access
1390 then
1391 raise Program_Error with "Before cursor denotes wrong container";
1392 end if;
1394 if Count = 0 then
1395 if Before.Container = null
1396 or else Before.Index > Container.Last
1397 then
1398 Position := No_Element;
1399 else
1400 Position := (Container'Unchecked_Access, Before.Index);
1401 end if;
1403 return;
1404 end if;
1406 if Before.Container = null
1407 or else Before.Index > Container.Last
1408 then
1409 if Container.Last = Index_Type'Last then
1410 raise Constraint_Error with
1411 "vector is already at its maximum length";
1412 end if;
1414 Index := Container.Last + 1;
1416 else
1417 Index := Before.Index;
1418 end if;
1420 Insert_Space (Container, Index, Count => Count);
1422 Position := Cursor'(Container'Unchecked_Access, Index);
1423 end Insert_Space;
1425 --------------
1426 -- Is_Empty --
1427 --------------
1429 function Is_Empty (Container : Vector) return Boolean is
1430 begin
1431 return Container.Last < Index_Type'First;
1432 end Is_Empty;
1434 -------------
1435 -- Iterate --
1436 -------------
1438 procedure Iterate
1439 (Container : Vector;
1440 Process : not null access procedure (Position : Cursor))
1442 V : Vector renames Container'Unrestricted_Access.all;
1443 B : Natural renames V.Busy;
1445 begin
1446 B := B + 1;
1448 begin
1449 for Indx in Index_Type'First .. Container.Last loop
1450 Process (Cursor'(Container'Unchecked_Access, Indx));
1451 end loop;
1452 exception
1453 when others =>
1454 B := B - 1;
1455 raise;
1456 end;
1458 B := B - 1;
1459 end Iterate;
1461 ----------
1462 -- Last --
1463 ----------
1465 function Last (Container : Vector) return Cursor is
1466 begin
1467 if Is_Empty (Container) then
1468 return No_Element;
1469 end if;
1471 return (Container'Unchecked_Access, Container.Last);
1472 end Last;
1474 ------------------
1475 -- Last_Element --
1476 ------------------
1478 function Last_Element (Container : Vector) return Element_Type is
1479 begin
1480 return Element (Container, Container.Last);
1481 end Last_Element;
1483 ----------------
1484 -- Last_Index --
1485 ----------------
1487 function Last_Index (Container : Vector) return Extended_Index is
1488 begin
1489 return Container.Last;
1490 end Last_Index;
1492 ------------
1493 -- Length --
1494 ------------
1496 function Length (Container : Vector) return Count_Type is
1497 L : constant Int := Int (Container.Last);
1498 F : constant Int := Int (Index_Type'First);
1499 N : constant Int'Base := L - F + 1;
1501 begin
1502 return Count_Type (N);
1503 end Length;
1505 ----------
1506 -- Move --
1507 ----------
1509 procedure Move
1510 (Target : in out Vector;
1511 Source : in out Vector)
1513 begin
1514 if Target'Address = Source'Address then
1515 return;
1516 end if;
1518 if Target.Busy > 0 then
1519 raise Program_Error with
1520 "attempt to tamper with elements (Target is busy)";
1521 end if;
1523 if Source.Busy > 0 then
1524 raise Program_Error with
1525 "attempt to tamper with elements (Source is busy)";
1526 end if;
1528 declare
1529 Target_Elements : constant Elements_Access := Target.Elements;
1530 begin
1531 Target.Elements := Source.Elements;
1532 Source.Elements := Target_Elements;
1533 end;
1535 Target.Last := Source.Last;
1536 Source.Last := No_Index;
1537 end Move;
1539 ----------
1540 -- Next --
1541 ----------
1543 function Next (Position : Cursor) return Cursor is
1544 begin
1545 if Position.Container = null then
1546 return No_Element;
1547 end if;
1549 if Position.Index < Position.Container.Last then
1550 return (Position.Container, Position.Index + 1);
1551 end if;
1553 return No_Element;
1554 end Next;
1556 ----------
1557 -- Next --
1558 ----------
1560 procedure Next (Position : in out Cursor) is
1561 begin
1562 if Position.Container = null then
1563 return;
1564 end if;
1566 if Position.Index < Position.Container.Last then
1567 Position.Index := Position.Index + 1;
1568 else
1569 Position := No_Element;
1570 end if;
1571 end Next;
1573 -------------
1574 -- Prepend --
1575 -------------
1577 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1578 begin
1579 Insert (Container, Index_Type'First, New_Item);
1580 end Prepend;
1582 procedure Prepend
1583 (Container : in out Vector;
1584 New_Item : Element_Type;
1585 Count : Count_Type := 1)
1587 begin
1588 Insert (Container,
1589 Index_Type'First,
1590 New_Item,
1591 Count);
1592 end Prepend;
1594 --------------
1595 -- Previous --
1596 --------------
1598 procedure Previous (Position : in out Cursor) is
1599 begin
1600 if Position.Container = null then
1601 return;
1602 end if;
1604 if Position.Index > Index_Type'First then
1605 Position.Index := Position.Index - 1;
1606 else
1607 Position := No_Element;
1608 end if;
1609 end Previous;
1611 function Previous (Position : Cursor) return Cursor is
1612 begin
1613 if Position.Container = null then
1614 return No_Element;
1615 end if;
1617 if Position.Index > Index_Type'First then
1618 return (Position.Container, Position.Index - 1);
1619 end if;
1621 return No_Element;
1622 end Previous;
1624 -------------------
1625 -- Query_Element --
1626 -------------------
1628 procedure Query_Element
1629 (Container : Vector;
1630 Index : Index_Type;
1631 Process : not null access procedure (Element : Element_Type))
1633 V : Vector renames Container'Unrestricted_Access.all;
1634 B : Natural renames V.Busy;
1635 L : Natural renames V.Lock;
1637 begin
1638 if Index > Container.Last then
1639 raise Constraint_Error with "Index is out of range";
1640 end if;
1642 B := B + 1;
1643 L := L + 1;
1645 begin
1646 Process (V.Elements (Index));
1647 exception
1648 when others =>
1649 L := L - 1;
1650 B := B - 1;
1651 raise;
1652 end;
1654 L := L - 1;
1655 B := B - 1;
1656 end Query_Element;
1658 procedure Query_Element
1659 (Position : Cursor;
1660 Process : not null access procedure (Element : Element_Type))
1662 begin
1663 if Position.Container = null then
1664 raise Constraint_Error with "Position cursor has no element";
1665 end if;
1667 Query_Element (Position.Container.all, Position.Index, Process);
1668 end Query_Element;
1670 ----------
1671 -- Read --
1672 ----------
1674 procedure Read
1675 (Stream : not null access Root_Stream_Type'Class;
1676 Container : out Vector)
1678 Length : Count_Type'Base;
1679 Last : Index_Type'Base := No_Index;
1681 begin
1682 Clear (Container);
1684 Count_Type'Base'Read (Stream, Length);
1686 if Length > Capacity (Container) then
1687 Reserve_Capacity (Container, Capacity => Length);
1688 end if;
1690 for J in Count_Type range 1 .. Length loop
1691 Last := Last + 1;
1692 Element_Type'Read (Stream, Container.Elements (Last));
1693 Container.Last := Last;
1694 end loop;
1695 end Read;
1697 procedure Read
1698 (Stream : not null access Root_Stream_Type'Class;
1699 Position : out Cursor)
1701 begin
1702 raise Program_Error with "attempt to stream vector cursor";
1703 end Read;
1705 ---------------------
1706 -- Replace_Element --
1707 ---------------------
1709 procedure Replace_Element
1710 (Container : in out Vector;
1711 Index : Index_Type;
1712 New_Item : Element_Type)
1714 begin
1715 if Index > Container.Last then
1716 raise Constraint_Error with "Index is out of range";
1717 end if;
1719 if Container.Lock > 0 then
1720 raise Program_Error with
1721 "attempt to tamper with cursors (vector is locked)";
1722 end if;
1724 Container.Elements (Index) := New_Item;
1725 end Replace_Element;
1727 procedure Replace_Element
1728 (Container : in out Vector;
1729 Position : Cursor;
1730 New_Item : Element_Type)
1732 begin
1733 if Position.Container = null then
1734 raise Constraint_Error with "Position cursor has no element";
1735 end if;
1737 if Position.Container /= Container'Unrestricted_Access then
1738 raise Program_Error with "Position cursor denotes wrong container";
1739 end if;
1741 Replace_Element (Container, Position.Index, New_Item);
1742 end Replace_Element;
1744 ----------------------
1745 -- Reserve_Capacity --
1746 ----------------------
1748 procedure Reserve_Capacity
1749 (Container : in out Vector;
1750 Capacity : Count_Type)
1752 N : constant Count_Type := Length (Container);
1754 begin
1755 if Capacity = 0 then
1756 if N = 0 then
1757 declare
1758 X : Elements_Access := Container.Elements;
1759 begin
1760 Container.Elements := null;
1761 Free (X);
1762 end;
1764 elsif N < Container.Elements'Length then
1765 if Container.Busy > 0 then
1766 raise Program_Error with
1767 "attempt to tamper with elements (vector is busy)";
1768 end if;
1770 declare
1771 subtype Array_Index_Subtype is Index_Type'Base range
1772 Index_Type'First .. Container.Last;
1774 Src : Elements_Type renames
1775 Container.Elements (Array_Index_Subtype);
1777 subtype Array_Subtype is
1778 Elements_Type (Array_Index_Subtype);
1780 X : Elements_Access := Container.Elements;
1782 begin
1783 Container.Elements := new Array_Subtype'(Src);
1784 Free (X);
1785 end;
1786 end if;
1788 return;
1789 end if;
1791 if Container.Elements = null then
1792 declare
1793 Last_As_Int : constant Int'Base :=
1794 Int (Index_Type'First) + Int (Capacity) - 1;
1796 begin
1797 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1798 raise Constraint_Error with "new length is out of range";
1799 end if;
1801 declare
1802 Last : constant Index_Type := Index_Type (Last_As_Int);
1804 subtype Array_Subtype is
1805 Elements_Type (Index_Type'First .. Last);
1807 begin
1808 Container.Elements := new Array_Subtype;
1809 end;
1810 end;
1812 return;
1813 end if;
1815 if Capacity <= N then
1816 if N < Container.Elements'Length then
1817 if Container.Busy > 0 then
1818 raise Program_Error with
1819 "attempt to tamper with elements (vector is busy)";
1820 end if;
1822 declare
1823 subtype Array_Index_Subtype is Index_Type'Base range
1824 Index_Type'First .. Container.Last;
1826 Src : Elements_Type renames
1827 Container.Elements (Array_Index_Subtype);
1829 subtype Array_Subtype is
1830 Elements_Type (Array_Index_Subtype);
1832 X : Elements_Access := Container.Elements;
1834 begin
1835 Container.Elements := new Array_Subtype'(Src);
1836 Free (X);
1837 end;
1839 end if;
1841 return;
1842 end if;
1844 if Capacity = Container.Elements'Length then
1845 return;
1846 end if;
1848 if Container.Busy > 0 then
1849 raise Program_Error with
1850 "attempt to tamper with elements (vector is busy)";
1851 end if;
1853 declare
1854 Last_As_Int : constant Int'Base :=
1855 Int (Index_Type'First) + Int (Capacity) - 1;
1857 begin
1858 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
1859 raise Constraint_Error with "new length is out of range";
1860 end if;
1862 declare
1863 Last : constant Index_Type := Index_Type (Last_As_Int);
1865 subtype Array_Subtype is
1866 Elements_Type (Index_Type'First .. Last);
1868 E : Elements_Access := new Array_Subtype;
1870 begin
1871 declare
1872 Src : Elements_Type renames
1873 Container.Elements (Index_Type'First .. Container.Last);
1875 Tgt : Elements_Type renames
1876 E (Index_Type'First .. Container.Last);
1878 begin
1879 Tgt := Src;
1881 exception
1882 when others =>
1883 Free (E);
1884 raise;
1885 end;
1887 declare
1888 X : Elements_Access := Container.Elements;
1889 begin
1890 Container.Elements := E;
1891 Free (X);
1892 end;
1893 end;
1894 end;
1895 end Reserve_Capacity;
1897 ----------------------
1898 -- Reverse_Elements --
1899 ----------------------
1901 procedure Reverse_Elements (Container : in out Vector) is
1902 begin
1903 if Container.Length <= 1 then
1904 return;
1905 end if;
1907 if Container.Lock > 0 then
1908 raise Program_Error with
1909 "attempt to tamper with cursors (vector is locked)";
1910 end if;
1912 declare
1913 I, J : Index_Type;
1914 E : Elements_Type renames Container.Elements.all;
1916 begin
1917 I := Index_Type'First;
1918 J := Container.Last;
1919 while I < J loop
1920 declare
1921 EI : constant Element_Type := E (I);
1923 begin
1924 E (I) := E (J);
1925 E (J) := EI;
1926 end;
1928 I := I + 1;
1929 J := J - 1;
1930 end loop;
1931 end;
1932 end Reverse_Elements;
1934 ------------------
1935 -- Reverse_Find --
1936 ------------------
1938 function Reverse_Find
1939 (Container : Vector;
1940 Item : Element_Type;
1941 Position : Cursor := No_Element) return Cursor
1943 Last : Index_Type'Base;
1945 begin
1946 if Position.Container /= null
1947 and then Position.Container /= Container'Unchecked_Access
1948 then
1949 raise Program_Error with "Position cursor denotes wrong container";
1950 end if;
1952 if Position.Container = null
1953 or else Position.Index > Container.Last
1954 then
1955 Last := Container.Last;
1956 else
1957 Last := Position.Index;
1958 end if;
1960 for Indx in reverse Index_Type'First .. Last loop
1961 if Container.Elements (Indx) = Item then
1962 return (Container'Unchecked_Access, Indx);
1963 end if;
1964 end loop;
1966 return No_Element;
1967 end Reverse_Find;
1969 ------------------------
1970 -- Reverse_Find_Index --
1971 ------------------------
1973 function Reverse_Find_Index
1974 (Container : Vector;
1975 Item : Element_Type;
1976 Index : Index_Type := Index_Type'Last) return Extended_Index
1978 Last : Index_Type'Base;
1980 begin
1981 if Index > Container.Last then
1982 Last := Container.Last;
1983 else
1984 Last := Index;
1985 end if;
1987 for Indx in reverse Index_Type'First .. Last loop
1988 if Container.Elements (Indx) = Item then
1989 return Indx;
1990 end if;
1991 end loop;
1993 return No_Index;
1994 end Reverse_Find_Index;
1996 ---------------------
1997 -- Reverse_Iterate --
1998 ---------------------
2000 procedure Reverse_Iterate
2001 (Container : Vector;
2002 Process : not null access procedure (Position : Cursor))
2004 V : Vector renames Container'Unrestricted_Access.all;
2005 B : Natural renames V.Busy;
2007 begin
2008 B := B + 1;
2010 begin
2011 for Indx in reverse Index_Type'First .. Container.Last loop
2012 Process (Cursor'(Container'Unchecked_Access, Indx));
2013 end loop;
2014 exception
2015 when others =>
2016 B := B - 1;
2017 raise;
2018 end;
2020 B := B - 1;
2021 end Reverse_Iterate;
2023 ----------------
2024 -- Set_Length --
2025 ----------------
2027 procedure Set_Length (Container : in out Vector; Length : Count_Type) is
2028 begin
2029 if Length = Vectors.Length (Container) then
2030 return;
2031 end if;
2033 if Container.Busy > 0 then
2034 raise Program_Error with
2035 "attempt to tamper with elements (vector is busy)";
2036 end if;
2038 if Length > Capacity (Container) then
2039 Reserve_Capacity (Container, Capacity => Length);
2040 end if;
2042 declare
2043 Last_As_Int : constant Int'Base :=
2044 Int (Index_Type'First) + Int (Length) - 1;
2045 begin
2046 Container.Last := Index_Type'Base (Last_As_Int);
2047 end;
2048 end Set_Length;
2050 ----------
2051 -- Swap --
2052 ----------
2054 procedure Swap (Container : in out Vector; I, J : Index_Type) is
2055 begin
2056 if I > Container.Last then
2057 raise Constraint_Error with "I index is out of range";
2058 end if;
2060 if J > Container.Last then
2061 raise Constraint_Error with "J index is out of range";
2062 end if;
2064 if I = J then
2065 return;
2066 end if;
2068 if Container.Lock > 0 then
2069 raise Program_Error with
2070 "attempt to tamper with cursors (vector is locked)";
2071 end if;
2073 declare
2074 EI : Element_Type renames Container.Elements (I);
2075 EJ : Element_Type renames Container.Elements (J);
2077 EI_Copy : constant Element_Type := EI;
2079 begin
2080 EI := EJ;
2081 EJ := EI_Copy;
2082 end;
2083 end Swap;
2085 procedure Swap (Container : in out Vector; I, J : Cursor) is
2086 begin
2087 if I.Container = null then
2088 raise Constraint_Error with "I cursor has no element";
2089 end if;
2091 if J.Container = null then
2092 raise Constraint_Error with "J cursor has no element";
2093 end if;
2095 if I.Container /= Container'Unrestricted_Access then
2096 raise Program_Error with "I cursor denotes wrong container";
2097 end if;
2099 if J.Container /= Container'Unrestricted_Access then
2100 raise Program_Error with "J cursor denotes wrong container";
2101 end if;
2103 Swap (Container, I.Index, J.Index);
2104 end Swap;
2106 ---------------
2107 -- To_Cursor --
2108 ---------------
2110 function To_Cursor
2111 (Container : Vector;
2112 Index : Extended_Index) return Cursor
2114 begin
2115 if Index not in Index_Type'First .. Container.Last then
2116 return No_Element;
2117 end if;
2119 return Cursor'(Container'Unchecked_Access, Index);
2120 end To_Cursor;
2122 --------------
2123 -- To_Index --
2124 --------------
2126 function To_Index (Position : Cursor) return Extended_Index is
2127 begin
2128 if Position.Container = null then
2129 return No_Index;
2130 end if;
2132 if Position.Index <= Position.Container.Last then
2133 return Position.Index;
2134 end if;
2136 return No_Index;
2137 end To_Index;
2139 ---------------
2140 -- To_Vector --
2141 ---------------
2143 function To_Vector (Length : Count_Type) return Vector is
2144 begin
2145 if Length = 0 then
2146 return Empty_Vector;
2147 end if;
2149 declare
2150 First : constant Int := Int (Index_Type'First);
2151 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2152 Last : Index_Type;
2153 Elements : Elements_Access;
2155 begin
2156 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2157 raise Constraint_Error with "Length is out of range";
2158 end if;
2160 Last := Index_Type (Last_As_Int);
2161 Elements := new Elements_Type (Index_Type'First .. Last);
2163 return Vector'(Controlled with Elements, Last, 0, 0);
2164 end;
2165 end To_Vector;
2167 function To_Vector
2168 (New_Item : Element_Type;
2169 Length : Count_Type) return Vector
2171 begin
2172 if Length = 0 then
2173 return Empty_Vector;
2174 end if;
2176 declare
2177 First : constant Int := Int (Index_Type'First);
2178 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2179 Last : Index_Type;
2180 Elements : Elements_Access;
2182 begin
2183 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2184 raise Constraint_Error with "Length is out of range";
2185 end if;
2187 Last := Index_Type (Last_As_Int);
2188 Elements := new Elements_Type'(Index_Type'First .. Last => New_Item);
2190 return Vector'(Controlled with Elements, Last, 0, 0);
2191 end;
2192 end To_Vector;
2194 --------------------
2195 -- Update_Element --
2196 --------------------
2198 procedure Update_Element
2199 (Container : in out Vector;
2200 Index : Index_Type;
2201 Process : not null access procedure (Element : in out Element_Type))
2203 B : Natural renames Container.Busy;
2204 L : Natural renames Container.Lock;
2206 begin
2207 if Index > Container.Last then
2208 raise Constraint_Error with "Index is out of range";
2209 end if;
2211 B := B + 1;
2212 L := L + 1;
2214 begin
2215 Process (Container.Elements (Index));
2216 exception
2217 when others =>
2218 L := L - 1;
2219 B := B - 1;
2220 raise;
2221 end;
2223 L := L - 1;
2224 B := B - 1;
2225 end Update_Element;
2227 procedure Update_Element
2228 (Container : in out Vector;
2229 Position : Cursor;
2230 Process : not null access procedure (Element : in out Element_Type))
2232 begin
2233 if Position.Container = null then
2234 raise Constraint_Error with "Position cursor has no element";
2235 end if;
2237 if Position.Container /= Container'Unrestricted_Access then
2238 raise Program_Error with "Position cursor denotes wrong container";
2239 end if;
2241 Update_Element (Container, Position.Index, Process);
2242 end Update_Element;
2244 -----------
2245 -- Write --
2246 -----------
2248 procedure Write
2249 (Stream : not null access Root_Stream_Type'Class;
2250 Container : Vector)
2252 begin
2253 Count_Type'Base'Write (Stream, Length (Container));
2255 for J in Index_Type'First .. Container.Last loop
2256 Element_Type'Write (Stream, Container.Elements (J));
2257 end loop;
2258 end Write;
2260 procedure Write
2261 (Stream : not null access Root_Stream_Type'Class;
2262 Position : Cursor)
2264 begin
2265 raise Program_Error with "attempt to stream vector cursor";
2266 end Write;
2268 end Ada.Containers.Vectors;