objc-act.c (synth_module_prologue): Use TREE_NO_WARNING instead of DECL_IN_SYSTEM_HEADER.
[official-gcc.git] / gcc / ada / a-coinve.adb
blobc97f4eb2406c6d276c6a7207391e8685b40392be
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . I N D E F I N I T E _ V E C T O R S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2007, 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 has originally being developed by Matthew J Heaney. --
30 ------------------------------------------------------------------------------
32 with Ada.Containers.Generic_Array_Sort;
33 with Ada.Unchecked_Deallocation;
34 with System; use type System.Address;
36 package body Ada.Containers.Indefinite_Vectors is
38 type Int is range System.Min_Int .. System.Max_Int;
39 type UInt is mod System.Max_Binary_Modulus;
41 procedure Free is
42 new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access);
44 procedure Free is
45 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
47 ---------
48 -- "&" --
49 ---------
51 function "&" (Left, Right : Vector) return Vector is
52 LN : constant Count_Type := Length (Left);
53 RN : constant Count_Type := Length (Right);
55 begin
56 if LN = 0 then
57 if RN = 0 then
58 return Empty_Vector;
59 end if;
61 declare
62 RE : Elements_Array renames
63 Right.Elements.EA (Index_Type'First .. Right.Last);
65 Elements : Elements_Access :=
66 new Elements_Type (Right.Last);
68 begin
69 for I in Elements.EA'Range loop
70 begin
71 if RE (I) /= null then
72 Elements.EA (I) := new Element_Type'(RE (I).all);
73 end if;
75 exception
76 when others =>
77 for J in Index_Type'First .. I - 1 loop
78 Free (Elements.EA (J));
79 end loop;
81 Free (Elements);
82 raise;
83 end;
84 end loop;
86 return (Controlled with Elements, Right.Last, 0, 0);
87 end;
89 end if;
91 if RN = 0 then
92 declare
93 LE : Elements_Array renames
94 Left.Elements.EA (Index_Type'First .. Left.Last);
96 Elements : Elements_Access :=
97 new Elements_Type (Left.Last);
99 begin
100 for I in Elements.EA'Range loop
101 begin
102 if LE (I) /= null then
103 Elements.EA (I) := new Element_Type'(LE (I).all);
104 end if;
106 exception
107 when others =>
108 for J in Index_Type'First .. I - 1 loop
109 Free (Elements.EA (J));
110 end loop;
112 Free (Elements);
113 raise;
114 end;
115 end loop;
117 return (Controlled with Elements, Left.Last, 0, 0);
118 end;
119 end if;
121 declare
122 N : constant Int'Base := Int (LN) + Int (RN);
123 Last_As_Int : Int'Base;
125 begin
126 if Int (No_Index) > Int'Last - N then
127 raise Constraint_Error with "new length is out of range";
128 end if;
130 Last_As_Int := Int (No_Index) + N;
132 if Last_As_Int > Int (Index_Type'Last) then
133 raise Constraint_Error with "new length is out of range";
134 end if;
136 declare
137 Last : constant Index_Type := Index_Type (Last_As_Int);
139 LE : Elements_Array renames
140 Left.Elements.EA (Index_Type'First .. Left.Last);
142 RE : Elements_Array renames
143 Right.Elements.EA (Index_Type'First .. Right.Last);
145 Elements : Elements_Access := new Elements_Type (Last);
147 I : Index_Type'Base := No_Index;
149 begin
150 for LI in LE'Range loop
151 I := I + 1;
153 begin
154 if LE (LI) /= null then
155 Elements.EA (I) := new Element_Type'(LE (LI).all);
156 end if;
158 exception
159 when others =>
160 for J in Index_Type'First .. I - 1 loop
161 Free (Elements.EA (J));
162 end loop;
164 Free (Elements);
165 raise;
166 end;
167 end loop;
169 for RI in RE'Range loop
170 I := I + 1;
172 begin
173 if RE (RI) /= null then
174 Elements.EA (I) := new Element_Type'(RE (RI).all);
175 end if;
177 exception
178 when others =>
179 for J in Index_Type'First .. I - 1 loop
180 Free (Elements.EA (J));
181 end loop;
183 Free (Elements);
184 raise;
185 end;
186 end loop;
188 return (Controlled with Elements, Last, 0, 0);
189 end;
190 end;
191 end "&";
193 function "&" (Left : Vector; Right : Element_Type) return Vector is
194 LN : constant Count_Type := Length (Left);
196 begin
197 if LN = 0 then
198 declare
199 Elements : Elements_Access := new Elements_Type (Index_Type'First);
201 begin
202 begin
203 Elements.EA (Index_Type'First) := new Element_Type'(Right);
204 exception
205 when others =>
206 Free (Elements);
207 raise;
208 end;
210 return (Controlled with Elements, Index_Type'First, 0, 0);
211 end;
212 end if;
214 declare
215 Last_As_Int : Int'Base;
217 begin
218 if Int (Index_Type'First) > Int'Last - Int (LN) then
219 raise Constraint_Error with "new length is out of range";
220 end if;
222 Last_As_Int := Int (Index_Type'First) + Int (LN);
224 if Last_As_Int > Int (Index_Type'Last) then
225 raise Constraint_Error with "new length is out of range";
226 end if;
228 declare
229 Last : constant Index_Type := Index_Type (Last_As_Int);
231 LE : Elements_Array renames
232 Left.Elements.EA (Index_Type'First .. Left.Last);
234 Elements : Elements_Access :=
235 new Elements_Type (Last);
237 begin
238 for I in LE'Range loop
239 begin
240 if LE (I) /= null then
241 Elements.EA (I) := new Element_Type'(LE (I).all);
242 end if;
244 exception
245 when others =>
246 for J in Index_Type'First .. I - 1 loop
247 Free (Elements.EA (J));
248 end loop;
250 Free (Elements);
251 raise;
252 end;
253 end loop;
255 begin
256 Elements.EA (Last) := new Element_Type'(Right);
258 exception
259 when others =>
260 for J in Index_Type'First .. Last - 1 loop
261 Free (Elements.EA (J));
262 end loop;
264 Free (Elements);
265 raise;
266 end;
268 return (Controlled with Elements, Last, 0, 0);
269 end;
270 end;
271 end "&";
273 function "&" (Left : Element_Type; Right : Vector) return Vector is
274 RN : constant Count_Type := Length (Right);
276 begin
277 if RN = 0 then
278 declare
279 Elements : Elements_Access := new Elements_Type (Index_Type'First);
281 begin
282 begin
283 Elements.EA (Index_Type'First) := new Element_Type'(Left);
284 exception
285 when others =>
286 Free (Elements);
287 raise;
288 end;
290 return (Controlled with Elements, Index_Type'First, 0, 0);
291 end;
292 end if;
294 declare
295 Last_As_Int : Int'Base;
297 begin
298 if Int (Index_Type'First) > Int'Last - Int (RN) then
299 raise Constraint_Error with "new length is out of range";
300 end if;
302 Last_As_Int := Int (Index_Type'First) + Int (RN);
304 if Last_As_Int > Int (Index_Type'Last) then
305 raise Constraint_Error with "new length is out of range";
306 end if;
308 declare
309 Last : constant Index_Type := Index_Type (Last_As_Int);
311 RE : Elements_Array renames
312 Right.Elements.EA (Index_Type'First .. Right.Last);
314 Elements : Elements_Access :=
315 new Elements_Type (Last);
317 I : Index_Type'Base := Index_Type'First;
319 begin
320 begin
321 Elements.EA (I) := new Element_Type'(Left);
322 exception
323 when others =>
324 Free (Elements);
325 raise;
326 end;
328 for RI in RE'Range loop
329 I := I + 1;
331 begin
332 if RE (RI) /= null then
333 Elements.EA (I) := new Element_Type'(RE (RI).all);
334 end if;
336 exception
337 when others =>
338 for J in Index_Type'First .. I - 1 loop
339 Free (Elements.EA (J));
340 end loop;
342 Free (Elements);
343 raise;
344 end;
345 end loop;
347 return (Controlled with Elements, Last, 0, 0);
348 end;
349 end;
350 end "&";
352 function "&" (Left, Right : Element_Type) return Vector is
353 begin
354 if Index_Type'First >= Index_Type'Last then
355 raise Constraint_Error with "new length is out of range";
356 end if;
358 declare
359 Last : constant Index_Type := Index_Type'First + 1;
360 Elements : Elements_Access := new Elements_Type (Last);
362 begin
363 begin
364 Elements.EA (Index_Type'First) := new Element_Type'(Left);
365 exception
366 when others =>
367 Free (Elements);
368 raise;
369 end;
371 begin
372 Elements.EA (Last) := new Element_Type'(Right);
373 exception
374 when others =>
375 Free (Elements.EA (Index_Type'First));
376 Free (Elements);
377 raise;
378 end;
380 return (Controlled with Elements, Last, 0, 0);
381 end;
382 end "&";
384 ---------
385 -- "=" --
386 ---------
388 function "=" (Left, Right : Vector) return Boolean is
389 begin
390 if Left'Address = Right'Address then
391 return True;
392 end if;
394 if Left.Last /= Right.Last then
395 return False;
396 end if;
398 for J in Index_Type'First .. Left.Last loop
399 if Left.Elements.EA (J) = null then
400 if Right.Elements.EA (J) /= null then
401 return False;
402 end if;
404 elsif Right.Elements.EA (J) = null then
405 return False;
407 elsif Left.Elements.EA (J).all /= Right.Elements.EA (J).all then
408 return False;
409 end if;
410 end loop;
412 return True;
413 end "=";
415 ------------
416 -- Adjust --
417 ------------
419 procedure Adjust (Container : in out Vector) is
420 begin
421 if Container.Last = No_Index then
422 Container.Elements := null;
423 return;
424 end if;
426 declare
427 L : constant Index_Type := Container.Last;
428 E : Elements_Array renames
429 Container.Elements.EA (Index_Type'First .. L);
431 begin
432 Container.Elements := null;
433 Container.Last := No_Index;
434 Container.Busy := 0;
435 Container.Lock := 0;
437 Container.Elements := new Elements_Type (L);
439 for I in E'Range loop
440 if E (I) /= null then
441 Container.Elements.EA (I) := new Element_Type'(E (I).all);
442 end if;
444 Container.Last := I;
445 end loop;
446 end;
447 end Adjust;
449 ------------
450 -- Append --
451 ------------
453 procedure Append (Container : in out Vector; New_Item : Vector) is
454 begin
455 if Is_Empty (New_Item) then
456 return;
457 end if;
459 if Container.Last = Index_Type'Last then
460 raise Constraint_Error with "vector is already at its maximum length";
461 end if;
463 Insert
464 (Container,
465 Container.Last + 1,
466 New_Item);
467 end Append;
469 procedure Append
470 (Container : in out Vector;
471 New_Item : Element_Type;
472 Count : Count_Type := 1)
474 begin
475 if Count = 0 then
476 return;
477 end if;
479 if Container.Last = Index_Type'Last then
480 raise Constraint_Error with "vector is already at its maximum length";
481 end if;
483 Insert
484 (Container,
485 Container.Last + 1,
486 New_Item,
487 Count);
488 end Append;
490 --------------
491 -- Capacity --
492 --------------
494 function Capacity (Container : Vector) return Count_Type is
495 begin
496 if Container.Elements = null then
497 return 0;
498 end if;
500 return Container.Elements.EA'Length;
501 end Capacity;
503 -----------
504 -- Clear --
505 -----------
507 procedure Clear (Container : in out Vector) is
508 begin
509 if Container.Busy > 0 then
510 raise Program_Error with
511 "attempt to tamper with elements (vector is busy)";
512 end if;
514 while Container.Last >= Index_Type'First loop
515 declare
516 X : Element_Access := Container.Elements.EA (Container.Last);
517 begin
518 Container.Elements.EA (Container.Last) := null;
519 Container.Last := Container.Last - 1;
520 Free (X);
521 end;
522 end loop;
523 end Clear;
525 --------------
526 -- Contains --
527 --------------
529 function Contains
530 (Container : Vector;
531 Item : Element_Type) return Boolean
533 begin
534 return Find_Index (Container, Item) /= No_Index;
535 end Contains;
537 ------------
538 -- Delete --
539 ------------
541 procedure Delete
542 (Container : in out Vector;
543 Index : Extended_Index;
544 Count : Count_Type := 1)
546 begin
547 if Index < Index_Type'First then
548 raise Constraint_Error with "Index is out of range (too small)";
549 end if;
551 if Index > Container.Last then
552 if Index > Container.Last + 1 then
553 raise Constraint_Error with "Index is out of range (too large)";
554 end if;
556 return;
557 end if;
559 if Count = 0 then
560 return;
561 end if;
563 if Container.Busy > 0 then
564 raise Program_Error with
565 "attempt to tamper with elements (vector is busy)";
566 end if;
568 declare
569 Index_As_Int : constant Int := Int (Index);
570 Old_Last_As_Int : constant Int := Int (Container.Last);
572 Count1 : constant Int'Base := Int (Count);
573 Count2 : constant Int'Base := Old_Last_As_Int - Index_As_Int + 1;
574 N : constant Int'Base := Int'Min (Count1, Count2);
576 J_As_Int : constant Int'Base := Index_As_Int + N;
577 E : Elements_Array renames Container.Elements.EA;
579 begin
580 if J_As_Int > Old_Last_As_Int then
581 while Container.Last >= Index loop
582 declare
583 K : constant Index_Type := Container.Last;
584 X : Element_Access := E (K);
586 begin
587 E (K) := null;
588 Container.Last := K - 1;
589 Free (X);
590 end;
591 end loop;
593 else
594 declare
595 J : constant Index_Type := Index_Type (J_As_Int);
597 New_Last_As_Int : constant Int'Base := Old_Last_As_Int - N;
598 New_Last : constant Index_Type :=
599 Index_Type (New_Last_As_Int);
601 begin
602 for K in Index .. J - 1 loop
603 declare
604 X : Element_Access := E (K);
605 begin
606 E (K) := null;
607 Free (X);
608 end;
609 end loop;
611 E (Index .. New_Last) := E (J .. Container.Last);
612 Container.Last := New_Last;
613 end;
614 end if;
615 end;
616 end Delete;
618 procedure Delete
619 (Container : in out Vector;
620 Position : in out Cursor;
621 Count : Count_Type := 1)
623 pragma Warnings (Off, Position);
625 begin
626 if Position.Container = null then
627 raise Constraint_Error with "Position cursor has no element";
628 end if;
630 if Position.Container /= Container'Unrestricted_Access then
631 raise Program_Error with "Position cursor denotes wrong container";
632 end if;
634 if Position.Index > Container.Last then
635 raise Program_Error with "Position index is out of range";
636 end if;
638 Delete (Container, Position.Index, Count);
640 Position := No_Element;
641 end Delete;
643 ------------------
644 -- Delete_First --
645 ------------------
647 procedure Delete_First
648 (Container : in out Vector;
649 Count : Count_Type := 1)
651 begin
652 if Count = 0 then
653 return;
654 end if;
656 if Count >= Length (Container) then
657 Clear (Container);
658 return;
659 end if;
661 Delete (Container, Index_Type'First, Count);
662 end Delete_First;
664 -----------------
665 -- Delete_Last --
666 -----------------
668 procedure Delete_Last
669 (Container : in out Vector;
670 Count : Count_Type := 1)
672 N : constant Count_Type := Length (Container);
674 begin
675 if Count = 0
676 or else N = 0
677 then
678 return;
679 end if;
681 if Container.Busy > 0 then
682 raise Program_Error with
683 "attempt to tamper with elements (vector is busy)";
684 end if;
686 declare
687 E : Elements_Array renames Container.Elements.EA;
689 begin
690 for Indx in 1 .. Count_Type'Min (Count, N) loop
691 declare
692 J : constant Index_Type := Container.Last;
693 X : Element_Access := E (J);
695 begin
696 E (J) := null;
697 Container.Last := J - 1;
698 Free (X);
699 end;
700 end loop;
701 end;
702 end Delete_Last;
704 -------------
705 -- Element --
706 -------------
708 function Element
709 (Container : Vector;
710 Index : Index_Type) return Element_Type
712 begin
713 if Index > Container.Last then
714 raise Constraint_Error with "Index is out of range";
715 end if;
717 declare
718 EA : constant Element_Access := Container.Elements.EA (Index);
720 begin
721 if EA = null then
722 raise Constraint_Error with "element is empty";
723 end if;
725 return EA.all;
726 end;
727 end Element;
729 function Element (Position : Cursor) return Element_Type is
730 begin
731 if Position.Container = null then
732 raise Constraint_Error with "Position cursor has no element";
733 end if;
735 if Position.Index > Position.Container.Last then
736 raise Constraint_Error with "Position cursor is out of range";
737 end if;
739 declare
740 EA : constant Element_Access :=
741 Position.Container.Elements.EA (Position.Index);
743 begin
744 if EA = null then
745 raise Constraint_Error with "element is empty";
746 end if;
748 return EA.all;
749 end;
750 end Element;
752 --------------
753 -- Finalize --
754 --------------
756 procedure Finalize (Container : in out Vector) is
757 begin
758 Clear (Container); -- Checks busy-bit
760 declare
761 X : Elements_Access := Container.Elements;
762 begin
763 Container.Elements := null;
764 Free (X);
765 end;
766 end Finalize;
768 ----------
769 -- Find --
770 ----------
772 function Find
773 (Container : Vector;
774 Item : Element_Type;
775 Position : Cursor := No_Element) return Cursor
777 begin
778 if Position.Container /= null then
779 if Position.Container /= Container'Unrestricted_Access then
780 raise Program_Error with "Position cursor denotes wrong container";
781 end if;
783 if Position.Index > Container.Last then
784 raise Program_Error with "Position index is out of range";
785 end if;
786 end if;
788 for J in Position.Index .. Container.Last loop
789 if Container.Elements.EA (J) /= null
790 and then Container.Elements.EA (J).all = Item
791 then
792 return (Container'Unchecked_Access, J);
793 end if;
794 end loop;
796 return No_Element;
797 end Find;
799 ----------------
800 -- Find_Index --
801 ----------------
803 function Find_Index
804 (Container : Vector;
805 Item : Element_Type;
806 Index : Index_Type := Index_Type'First) return Extended_Index
808 begin
809 for Indx in Index .. Container.Last loop
810 if Container.Elements.EA (Indx) /= null
811 and then Container.Elements.EA (Indx).all = Item
812 then
813 return Indx;
814 end if;
815 end loop;
817 return No_Index;
818 end Find_Index;
820 -----------
821 -- First --
822 -----------
824 function First (Container : Vector) return Cursor is
825 begin
826 if Is_Empty (Container) then
827 return No_Element;
828 end if;
830 return (Container'Unchecked_Access, Index_Type'First);
831 end First;
833 -------------------
834 -- First_Element --
835 -------------------
837 function First_Element (Container : Vector) return Element_Type is
838 begin
839 if Container.Last = No_Index then
840 raise Constraint_Error with "Container is empty";
841 end if;
843 declare
844 EA : constant Element_Access :=
845 Container.Elements.EA (Index_Type'First);
847 begin
848 if EA = null then
849 raise Constraint_Error with "first element is empty";
850 end if;
852 return EA.all;
853 end;
854 end First_Element;
856 -----------------
857 -- First_Index --
858 -----------------
860 function First_Index (Container : Vector) return Index_Type is
861 pragma Unreferenced (Container);
862 begin
863 return Index_Type'First;
864 end First_Index;
866 ---------------------
867 -- Generic_Sorting --
868 ---------------------
870 package body Generic_Sorting is
872 -----------------------
873 -- Local Subprograms --
874 -----------------------
876 function Is_Less (L, R : Element_Access) return Boolean;
877 pragma Inline (Is_Less);
879 -------------
880 -- Is_Less --
881 -------------
883 function Is_Less (L, R : Element_Access) return Boolean is
884 begin
885 if L = null then
886 return R /= null;
887 elsif R = null then
888 return False;
889 else
890 return L.all < R.all;
891 end if;
892 end Is_Less;
894 ---------------
895 -- Is_Sorted --
896 ---------------
898 function Is_Sorted (Container : Vector) return Boolean is
899 begin
900 if Container.Last <= Index_Type'First then
901 return True;
902 end if;
904 declare
905 E : Elements_Array renames Container.Elements.EA;
906 begin
907 for I in Index_Type'First .. Container.Last - 1 loop
908 if Is_Less (E (I + 1), E (I)) then
909 return False;
910 end if;
911 end loop;
912 end;
914 return True;
915 end Is_Sorted;
917 -----------
918 -- Merge --
919 -----------
921 procedure Merge (Target, Source : in out Vector) is
922 I, J : Index_Type'Base;
924 begin
925 if Target.Last < Index_Type'First then
926 Move (Target => Target, Source => Source);
927 return;
928 end if;
930 if Target'Address = Source'Address then
931 return;
932 end if;
934 if Source.Last < Index_Type'First then
935 return;
936 end if;
938 if Source.Busy > 0 then
939 raise Program_Error with
940 "attempt to tamper with elements (vector is busy)";
941 end if;
943 I := Target.Last; -- original value (before Set_Length)
944 Target.Set_Length (Length (Target) + Length (Source));
946 J := Target.Last; -- new value (after Set_Length)
947 while Source.Last >= Index_Type'First loop
948 pragma Assert
949 (Source.Last <= Index_Type'First
950 or else not (Is_Less
951 (Source.Elements.EA (Source.Last),
952 Source.Elements.EA (Source.Last - 1))));
954 if I < Index_Type'First then
955 declare
956 Src : Elements_Array renames
957 Source.Elements.EA (Index_Type'First .. Source.Last);
959 begin
960 Target.Elements.EA (Index_Type'First .. J) := Src;
961 Src := (others => null);
962 end;
964 Source.Last := No_Index;
965 return;
966 end if;
968 pragma Assert
969 (I <= Index_Type'First
970 or else not (Is_Less
971 (Target.Elements.EA (I),
972 Target.Elements.EA (I - 1))));
974 declare
975 Src : Element_Access renames Source.Elements.EA (Source.Last);
976 Tgt : Element_Access renames Target.Elements.EA (I);
978 begin
979 if Is_Less (Src, Tgt) then
980 Target.Elements.EA (J) := Tgt;
981 Tgt := null;
982 I := I - 1;
984 else
985 Target.Elements.EA (J) := Src;
986 Src := null;
987 Source.Last := Source.Last - 1;
988 end if;
989 end;
991 J := J - 1;
992 end loop;
993 end Merge;
995 ----------
996 -- Sort --
997 ----------
999 procedure Sort (Container : in out Vector)
1001 procedure Sort is
1002 new Generic_Array_Sort
1003 (Index_Type => Index_Type,
1004 Element_Type => Element_Access,
1005 Array_Type => Elements_Array,
1006 "<" => Is_Less);
1008 -- Start of processing for Sort
1010 begin
1011 if Container.Last <= Index_Type'First then
1012 return;
1013 end if;
1015 if Container.Lock > 0 then
1016 raise Program_Error with
1017 "attempt to tamper with cursors (vector is locked)";
1018 end if;
1020 Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
1021 end Sort;
1023 end Generic_Sorting;
1025 -----------------
1026 -- Has_Element --
1027 -----------------
1029 function Has_Element (Position : Cursor) return Boolean is
1030 begin
1031 if Position.Container = null then
1032 return False;
1033 end if;
1035 return Position.Index <= Position.Container.Last;
1036 end Has_Element;
1038 ------------
1039 -- Insert --
1040 ------------
1042 procedure Insert
1043 (Container : in out Vector;
1044 Before : Extended_Index;
1045 New_Item : Element_Type;
1046 Count : Count_Type := 1)
1048 N : constant Int := Int (Count);
1050 First : constant Int := Int (Index_Type'First);
1051 New_Last_As_Int : Int'Base;
1052 New_Last : Index_Type;
1053 New_Length : UInt;
1054 Max_Length : constant UInt := UInt (Count_Type'Last);
1056 Dst : Elements_Access;
1058 begin
1059 if Before < Index_Type'First then
1060 raise Constraint_Error with
1061 "Before index is out of range (too small)";
1062 end if;
1064 if Before > Container.Last
1065 and then Before > Container.Last + 1
1066 then
1067 raise Constraint_Error with
1068 "Before index is out of range (too large)";
1069 end if;
1071 if Count = 0 then
1072 return;
1073 end if;
1075 declare
1076 Old_Last_As_Int : constant Int := Int (Container.Last);
1078 begin
1079 if Old_Last_As_Int > Int'Last - N then
1080 raise Constraint_Error with "new length is out of range";
1081 end if;
1083 New_Last_As_Int := Old_Last_As_Int + N;
1085 if New_Last_As_Int > Int (Index_Type'Last) then
1086 raise Constraint_Error with "new length is out of range";
1087 end if;
1089 New_Length := UInt (New_Last_As_Int - First + 1);
1091 if New_Length > Max_Length then
1092 raise Constraint_Error with "new length is out of range";
1093 end if;
1095 New_Last := Index_Type (New_Last_As_Int);
1096 end;
1098 if Container.Busy > 0 then
1099 raise Program_Error with
1100 "attempt to tamper with elements (vector is busy)";
1101 end if;
1103 if Container.Elements = null then
1104 Container.Elements := new Elements_Type (New_Last);
1105 Container.Last := No_Index;
1107 for J in Container.Elements.EA'Range loop
1108 Container.Elements.EA (J) := new Element_Type'(New_Item);
1109 Container.Last := J;
1110 end loop;
1112 return;
1113 end if;
1115 if New_Last <= Container.Elements.Last then
1116 declare
1117 E : Elements_Array renames Container.Elements.EA;
1119 begin
1120 if Before <= Container.Last then
1121 declare
1122 Index_As_Int : constant Int'Base :=
1123 Index_Type'Pos (Before) + N;
1125 Index : constant Index_Type := Index_Type (Index_As_Int);
1127 J : Index_Type'Base;
1129 begin
1130 E (Index .. New_Last) := E (Before .. Container.Last);
1131 Container.Last := New_Last;
1133 J := Before;
1134 while J < Index loop
1135 E (J) := new Element_Type'(New_Item);
1136 J := J + 1;
1137 end loop;
1139 exception
1140 when others =>
1141 E (J .. Index - 1) := (others => null);
1142 raise;
1143 end;
1145 else
1146 for J in Before .. New_Last loop
1147 E (J) := new Element_Type'(New_Item);
1148 Container.Last := J;
1149 end loop;
1150 end if;
1151 end;
1153 return;
1154 end if;
1156 declare
1157 C, CC : UInt;
1159 begin
1160 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1161 while C < New_Length loop
1162 if C > UInt'Last / 2 then
1163 C := UInt'Last;
1164 exit;
1165 end if;
1167 C := 2 * C;
1168 end loop;
1170 if C > Max_Length then
1171 C := Max_Length;
1172 end if;
1174 if Index_Type'First <= 0
1175 and then Index_Type'Last >= 0
1176 then
1177 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1179 else
1180 CC := UInt (Int (Index_Type'Last) - First + 1);
1181 end if;
1183 if C > CC then
1184 C := CC;
1185 end if;
1187 declare
1188 Dst_Last : constant Index_Type :=
1189 Index_Type (First + UInt'Pos (C) - Int'(1));
1191 begin
1192 Dst := new Elements_Type (Dst_Last);
1193 end;
1194 end;
1196 if Before <= Container.Last then
1197 declare
1198 Index_As_Int : constant Int'Base :=
1199 Index_Type'Pos (Before) + N;
1201 Index : constant Index_Type := Index_Type (Index_As_Int);
1203 Src : Elements_Access := Container.Elements;
1205 begin
1206 Dst.EA (Index_Type'First .. Before - 1) :=
1207 Src.EA (Index_Type'First .. Before - 1);
1209 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1211 Container.Elements := Dst;
1212 Container.Last := New_Last;
1213 Free (Src);
1215 for J in Before .. Index - 1 loop
1216 Dst.EA (J) := new Element_Type'(New_Item);
1217 end loop;
1218 end;
1220 else
1221 declare
1222 Src : Elements_Access := Container.Elements;
1224 begin
1225 Dst.EA (Index_Type'First .. Container.Last) :=
1226 Src.EA (Index_Type'First .. Container.Last);
1228 Container.Elements := Dst;
1229 Free (Src);
1231 for J in Before .. New_Last loop
1232 Dst.EA (J) := new Element_Type'(New_Item);
1233 Container.Last := J;
1234 end loop;
1235 end;
1236 end if;
1237 end Insert;
1239 procedure Insert
1240 (Container : in out Vector;
1241 Before : Extended_Index;
1242 New_Item : Vector)
1244 N : constant Count_Type := Length (New_Item);
1246 begin
1247 if Before < Index_Type'First then
1248 raise Constraint_Error with
1249 "Before index is out of range (too small)";
1250 end if;
1252 if Before > Container.Last
1253 and then Before > Container.Last + 1
1254 then
1255 raise Constraint_Error with
1256 "Before index is out of range (too large)";
1257 end if;
1259 if N = 0 then
1260 return;
1261 end if;
1263 Insert_Space (Container, Before, Count => N);
1265 declare
1266 Dst_Last_As_Int : constant Int'Base :=
1267 Int'Base (Before) + Int'Base (N) - 1;
1269 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1271 Dst : Elements_Array renames
1272 Container.Elements.EA (Before .. Dst_Last);
1274 Dst_Index : Index_Type'Base := Before - 1;
1276 begin
1277 if Container'Address /= New_Item'Address then
1278 declare
1279 subtype Src_Index_Subtype is Index_Type'Base range
1280 Index_Type'First .. New_Item.Last;
1282 Src : Elements_Array renames
1283 New_Item.Elements.EA (Src_Index_Subtype);
1285 begin
1286 for Src_Index in Src'Range loop
1287 Dst_Index := Dst_Index + 1;
1289 if Src (Src_Index) /= null then
1290 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1291 end if;
1292 end loop;
1293 end;
1295 return;
1296 end if;
1298 declare
1299 subtype Src_Index_Subtype is Index_Type'Base range
1300 Index_Type'First .. Before - 1;
1302 Src : Elements_Array renames
1303 Container.Elements.EA (Src_Index_Subtype);
1305 begin
1306 for Src_Index in Src'Range loop
1307 Dst_Index := Dst_Index + 1;
1309 if Src (Src_Index) /= null then
1310 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1311 end if;
1312 end loop;
1313 end;
1315 if Dst_Last = Container.Last then
1316 return;
1317 end if;
1319 declare
1320 subtype Src_Index_Subtype is Index_Type'Base range
1321 Dst_Last + 1 .. Container.Last;
1323 Src : Elements_Array renames
1324 Container.Elements.EA (Src_Index_Subtype);
1326 begin
1327 for Src_Index in Src'Range loop
1328 Dst_Index := Dst_Index + 1;
1330 if Src (Src_Index) /= null then
1331 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1332 end if;
1333 end loop;
1334 end;
1335 end;
1336 end Insert;
1338 procedure Insert
1339 (Container : in out Vector;
1340 Before : Cursor;
1341 New_Item : Vector)
1343 Index : Index_Type'Base;
1345 begin
1346 if Before.Container /= null
1347 and then Before.Container /= Container'Unchecked_Access
1348 then
1349 raise Program_Error with "Before cursor denotes wrong container";
1350 end if;
1352 if Is_Empty (New_Item) then
1353 return;
1354 end if;
1356 if Before.Container = null
1357 or else Before.Index > Container.Last
1358 then
1359 if Container.Last = Index_Type'Last then
1360 raise Constraint_Error with
1361 "vector is already at its maximum length";
1362 end if;
1364 Index := Container.Last + 1;
1366 else
1367 Index := Before.Index;
1368 end if;
1370 Insert (Container, Index, New_Item);
1371 end Insert;
1373 procedure Insert
1374 (Container : in out Vector;
1375 Before : Cursor;
1376 New_Item : Vector;
1377 Position : out Cursor)
1379 Index : Index_Type'Base;
1381 begin
1382 if Before.Container /= null
1383 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1384 then
1385 raise Program_Error with "Before cursor denotes wrong container";
1386 end if;
1388 if Is_Empty (New_Item) then
1389 if Before.Container = null
1390 or else Before.Index > Container.Last
1391 then
1392 Position := No_Element;
1393 else
1394 Position := (Container'Unchecked_Access, Before.Index);
1395 end if;
1397 return;
1398 end if;
1400 if Before.Container = null
1401 or else Before.Index > Container.Last
1402 then
1403 if Container.Last = Index_Type'Last then
1404 raise Constraint_Error with
1405 "vector is already at its maximum length";
1406 end if;
1408 Index := Container.Last + 1;
1410 else
1411 Index := Before.Index;
1412 end if;
1414 Insert (Container, Index, New_Item);
1416 Position := Cursor'(Container'Unchecked_Access, Index);
1417 end Insert;
1419 procedure Insert
1420 (Container : in out Vector;
1421 Before : Cursor;
1422 New_Item : Element_Type;
1423 Count : Count_Type := 1)
1425 Index : Index_Type'Base;
1427 begin
1428 if Before.Container /= null
1429 and then Before.Container /= Container'Unchecked_Access
1430 then
1431 raise Program_Error with "Before cursor denotes wrong container";
1432 end if;
1434 if Count = 0 then
1435 return;
1436 end if;
1438 if Before.Container = null
1439 or else Before.Index > Container.Last
1440 then
1441 if Container.Last = Index_Type'Last then
1442 raise Constraint_Error with
1443 "vector is already at its maximum length";
1444 end if;
1446 Index := Container.Last + 1;
1448 else
1449 Index := Before.Index;
1450 end if;
1452 Insert (Container, Index, New_Item, Count);
1453 end Insert;
1455 procedure Insert
1456 (Container : in out Vector;
1457 Before : Cursor;
1458 New_Item : Element_Type;
1459 Position : out Cursor;
1460 Count : Count_Type := 1)
1462 Index : Index_Type'Base;
1464 begin
1465 if Before.Container /= null
1466 and then Before.Container /= Container'Unchecked_Access
1467 then
1468 raise Program_Error with "Before cursor denotes wrong container";
1469 end if;
1471 if Count = 0 then
1472 if Before.Container = null
1473 or else Before.Index > Container.Last
1474 then
1475 Position := No_Element;
1476 else
1477 Position := (Container'Unchecked_Access, Before.Index);
1478 end if;
1480 return;
1481 end if;
1483 if Before.Container = null
1484 or else Before.Index > Container.Last
1485 then
1486 if Container.Last = Index_Type'Last then
1487 raise Constraint_Error with
1488 "vector is already at its maximum length";
1489 end if;
1491 Index := Container.Last + 1;
1493 else
1494 Index := Before.Index;
1495 end if;
1497 Insert (Container, Index, New_Item, Count);
1499 Position := (Container'Unchecked_Access, Index);
1500 end Insert;
1502 ------------------
1503 -- Insert_Space --
1504 ------------------
1506 procedure Insert_Space
1507 (Container : in out Vector;
1508 Before : Extended_Index;
1509 Count : Count_Type := 1)
1511 N : constant Int := Int (Count);
1513 First : constant Int := Int (Index_Type'First);
1514 New_Last_As_Int : Int'Base;
1515 New_Last : Index_Type;
1516 New_Length : UInt;
1517 Max_Length : constant UInt := UInt (Count_Type'Last);
1519 Dst : Elements_Access;
1521 begin
1522 if Before < Index_Type'First then
1523 raise Constraint_Error with
1524 "Before index is out of range (too small)";
1525 end if;
1527 if Before > Container.Last
1528 and then Before > Container.Last + 1
1529 then
1530 raise Constraint_Error with
1531 "Before index is out of range (too large)";
1532 end if;
1534 if Count = 0 then
1535 return;
1536 end if;
1538 declare
1539 Old_Last_As_Int : constant Int := Int (Container.Last);
1541 begin
1542 if Old_Last_As_Int > Int'Last - N then
1543 raise Constraint_Error with "new length is out of range";
1544 end if;
1546 New_Last_As_Int := Old_Last_As_Int + N;
1548 if New_Last_As_Int > Int (Index_Type'Last) then
1549 raise Constraint_Error with "new length is out of range";
1550 end if;
1552 New_Length := UInt (New_Last_As_Int - First + 1);
1554 if New_Length > Max_Length then
1555 raise Constraint_Error with "new length is out of range";
1556 end if;
1558 New_Last := Index_Type (New_Last_As_Int);
1559 end;
1561 if Container.Busy > 0 then
1562 raise Program_Error with
1563 "attempt to tamper with elements (vector is busy)";
1564 end if;
1566 if Container.Elements = null then
1567 Container.Elements := new Elements_Type (New_Last);
1568 Container.Last := New_Last;
1569 return;
1570 end if;
1572 if New_Last <= Container.Elements.Last then
1573 declare
1574 E : Elements_Array renames Container.Elements.EA;
1576 begin
1577 if Before <= Container.Last then
1578 declare
1579 Index_As_Int : constant Int'Base :=
1580 Index_Type'Pos (Before) + N;
1582 Index : constant Index_Type := Index_Type (Index_As_Int);
1584 begin
1585 E (Index .. New_Last) := E (Before .. Container.Last);
1586 E (Before .. Index - 1) := (others => null);
1587 end;
1588 end if;
1589 end;
1591 Container.Last := New_Last;
1592 return;
1593 end if;
1595 declare
1596 C, CC : UInt;
1598 begin
1599 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1600 while C < New_Length loop
1601 if C > UInt'Last / 2 then
1602 C := UInt'Last;
1603 exit;
1604 end if;
1606 C := 2 * C;
1607 end loop;
1609 if C > Max_Length then
1610 C := Max_Length;
1611 end if;
1613 if Index_Type'First <= 0
1614 and then Index_Type'Last >= 0
1615 then
1616 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1618 else
1619 CC := UInt (Int (Index_Type'Last) - First + 1);
1620 end if;
1622 if C > CC then
1623 C := CC;
1624 end if;
1626 declare
1627 Dst_Last : constant Index_Type :=
1628 Index_Type (First + UInt'Pos (C) - 1);
1630 begin
1631 Dst := new Elements_Type (Dst_Last);
1632 end;
1633 end;
1635 declare
1636 Src : Elements_Access := Container.Elements;
1638 begin
1639 if Before <= Container.Last then
1640 declare
1641 Index_As_Int : constant Int'Base :=
1642 Index_Type'Pos (Before) + N;
1644 Index : constant Index_Type := Index_Type (Index_As_Int);
1646 begin
1647 Dst.EA (Index_Type'First .. Before - 1) :=
1648 Src.EA (Index_Type'First .. Before - 1);
1650 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1651 end;
1653 else
1654 Dst.EA (Index_Type'First .. Container.Last) :=
1655 Src.EA (Index_Type'First .. Container.Last);
1656 end if;
1658 Container.Elements := Dst;
1659 Container.Last := New_Last;
1660 Free (Src);
1661 end;
1662 end Insert_Space;
1664 procedure Insert_Space
1665 (Container : in out Vector;
1666 Before : Cursor;
1667 Position : out Cursor;
1668 Count : Count_Type := 1)
1670 Index : Index_Type'Base;
1672 begin
1673 if Before.Container /= null
1674 and then Before.Container /= Container'Unchecked_Access
1675 then
1676 raise Program_Error with "Before cursor denotes wrong container";
1677 end if;
1679 if Count = 0 then
1680 if Before.Container = null
1681 or else Before.Index > Container.Last
1682 then
1683 Position := No_Element;
1684 else
1685 Position := (Container'Unchecked_Access, Before.Index);
1686 end if;
1688 return;
1689 end if;
1691 if Before.Container = null
1692 or else Before.Index > Container.Last
1693 then
1694 if Container.Last = Index_Type'Last then
1695 raise Constraint_Error with
1696 "vector is already at its maximum length";
1697 end if;
1699 Index := Container.Last + 1;
1701 else
1702 Index := Before.Index;
1703 end if;
1705 Insert_Space (Container, Index, Count);
1707 Position := Cursor'(Container'Unchecked_Access, Index);
1708 end Insert_Space;
1710 --------------
1711 -- Is_Empty --
1712 --------------
1714 function Is_Empty (Container : Vector) return Boolean is
1715 begin
1716 return Container.Last < Index_Type'First;
1717 end Is_Empty;
1719 -------------
1720 -- Iterate --
1721 -------------
1723 procedure Iterate
1724 (Container : Vector;
1725 Process : not null access procedure (Position : Cursor))
1727 V : Vector renames Container'Unrestricted_Access.all;
1728 B : Natural renames V.Busy;
1730 begin
1731 B := B + 1;
1733 begin
1734 for Indx in Index_Type'First .. Container.Last loop
1735 Process (Cursor'(Container'Unchecked_Access, Indx));
1736 end loop;
1737 exception
1738 when others =>
1739 B := B - 1;
1740 raise;
1741 end;
1743 B := B - 1;
1744 end Iterate;
1746 ----------
1747 -- Last --
1748 ----------
1750 function Last (Container : Vector) return Cursor is
1751 begin
1752 if Is_Empty (Container) then
1753 return No_Element;
1754 end if;
1756 return (Container'Unchecked_Access, Container.Last);
1757 end Last;
1759 ------------------
1760 -- Last_Element --
1761 ------------------
1763 function Last_Element (Container : Vector) return Element_Type is
1764 begin
1765 if Container.Last = No_Index then
1766 raise Constraint_Error with "Container is empty";
1767 end if;
1769 declare
1770 EA : constant Element_Access :=
1771 Container.Elements.EA (Container.Last);
1773 begin
1774 if EA = null then
1775 raise Constraint_Error with "last element is empty";
1776 end if;
1778 return EA.all;
1779 end;
1780 end Last_Element;
1782 ----------------
1783 -- Last_Index --
1784 ----------------
1786 function Last_Index (Container : Vector) return Extended_Index is
1787 begin
1788 return Container.Last;
1789 end Last_Index;
1791 ------------
1792 -- Length --
1793 ------------
1795 function Length (Container : Vector) return Count_Type is
1796 L : constant Int := Int (Container.Last);
1797 F : constant Int := Int (Index_Type'First);
1798 N : constant Int'Base := L - F + 1;
1800 begin
1801 return Count_Type (N);
1802 end Length;
1804 ----------
1805 -- Move --
1806 ----------
1808 procedure Move
1809 (Target : in out Vector;
1810 Source : in out Vector)
1812 begin
1813 if Target'Address = Source'Address then
1814 return;
1815 end if;
1817 if Source.Busy > 0 then
1818 raise Program_Error with
1819 "attempt to tamper with elements (Source is busy)";
1820 end if;
1822 Clear (Target); -- Checks busy-bit
1824 declare
1825 Target_Elements : constant Elements_Access := Target.Elements;
1826 begin
1827 Target.Elements := Source.Elements;
1828 Source.Elements := Target_Elements;
1829 end;
1831 Target.Last := Source.Last;
1832 Source.Last := No_Index;
1833 end Move;
1835 ----------
1836 -- Next --
1837 ----------
1839 function Next (Position : Cursor) return Cursor is
1840 begin
1841 if Position.Container = null then
1842 return No_Element;
1843 end if;
1845 if Position.Index < Position.Container.Last then
1846 return (Position.Container, Position.Index + 1);
1847 end if;
1849 return No_Element;
1850 end Next;
1852 ----------
1853 -- Next --
1854 ----------
1856 procedure Next (Position : in out Cursor) is
1857 begin
1858 if Position.Container = null then
1859 return;
1860 end if;
1862 if Position.Index < Position.Container.Last then
1863 Position.Index := Position.Index + 1;
1864 else
1865 Position := No_Element;
1866 end if;
1867 end Next;
1869 -------------
1870 -- Prepend --
1871 -------------
1873 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1874 begin
1875 Insert (Container, Index_Type'First, New_Item);
1876 end Prepend;
1878 procedure Prepend
1879 (Container : in out Vector;
1880 New_Item : Element_Type;
1881 Count : Count_Type := 1)
1883 begin
1884 Insert (Container,
1885 Index_Type'First,
1886 New_Item,
1887 Count);
1888 end Prepend;
1890 --------------
1891 -- Previous --
1892 --------------
1894 procedure Previous (Position : in out Cursor) is
1895 begin
1896 if Position.Container = null then
1897 return;
1898 end if;
1900 if Position.Index > Index_Type'First then
1901 Position.Index := Position.Index - 1;
1902 else
1903 Position := No_Element;
1904 end if;
1905 end Previous;
1907 function Previous (Position : Cursor) return Cursor is
1908 begin
1909 if Position.Container = null then
1910 return No_Element;
1911 end if;
1913 if Position.Index > Index_Type'First then
1914 return (Position.Container, Position.Index - 1);
1915 end if;
1917 return No_Element;
1918 end Previous;
1920 -------------------
1921 -- Query_Element --
1922 -------------------
1924 procedure Query_Element
1925 (Container : Vector;
1926 Index : Index_Type;
1927 Process : not null access procedure (Element : Element_Type))
1929 V : Vector renames Container'Unrestricted_Access.all;
1930 B : Natural renames V.Busy;
1931 L : Natural renames V.Lock;
1933 begin
1934 if Index > Container.Last then
1935 raise Constraint_Error with "Index is out of range";
1936 end if;
1938 if V.Elements.EA (Index) = null then
1939 raise Constraint_Error with "element is null";
1940 end if;
1942 B := B + 1;
1943 L := L + 1;
1945 begin
1946 Process (V.Elements.EA (Index).all);
1947 exception
1948 when others =>
1949 L := L - 1;
1950 B := B - 1;
1951 raise;
1952 end;
1954 L := L - 1;
1955 B := B - 1;
1956 end Query_Element;
1958 procedure Query_Element
1959 (Position : Cursor;
1960 Process : not null access procedure (Element : Element_Type))
1962 begin
1963 if Position.Container = null then
1964 raise Constraint_Error with "Position cursor has no element";
1965 end if;
1967 Query_Element (Position.Container.all, Position.Index, Process);
1968 end Query_Element;
1970 ----------
1971 -- Read --
1972 ----------
1974 procedure Read
1975 (Stream : not null access Root_Stream_Type'Class;
1976 Container : out Vector)
1978 Length : Count_Type'Base;
1979 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1981 B : Boolean;
1983 begin
1984 Clear (Container);
1986 Count_Type'Base'Read (Stream, Length);
1988 if Length > Capacity (Container) then
1989 Reserve_Capacity (Container, Capacity => Length);
1990 end if;
1992 for J in Count_Type range 1 .. Length loop
1993 Last := Last + 1;
1995 Boolean'Read (Stream, B);
1997 if B then
1998 Container.Elements.EA (Last) :=
1999 new Element_Type'(Element_Type'Input (Stream));
2000 end if;
2002 Container.Last := Last;
2003 end loop;
2004 end Read;
2006 procedure Read
2007 (Stream : not null access Root_Stream_Type'Class;
2008 Position : out Cursor)
2010 begin
2011 raise Program_Error with "attempt to stream vector cursor";
2012 end Read;
2014 ---------------------
2015 -- Replace_Element --
2016 ---------------------
2018 procedure Replace_Element
2019 (Container : in out Vector;
2020 Index : Index_Type;
2021 New_Item : Element_Type)
2023 begin
2024 if Index > Container.Last then
2025 raise Constraint_Error with "Index is out of range";
2026 end if;
2028 if Container.Lock > 0 then
2029 raise Program_Error with
2030 "attempt to tamper with cursors (vector is locked)";
2031 end if;
2033 declare
2034 X : Element_Access := Container.Elements.EA (Index);
2035 begin
2036 Container.Elements.EA (Index) := new Element_Type'(New_Item);
2037 Free (X);
2038 end;
2039 end Replace_Element;
2041 procedure Replace_Element
2042 (Container : in out Vector;
2043 Position : Cursor;
2044 New_Item : Element_Type)
2046 begin
2047 if Position.Container = null then
2048 raise Constraint_Error with "Position cursor has no element";
2049 end if;
2051 if Position.Container /= Container'Unrestricted_Access then
2052 raise Program_Error with "Position cursor denotes wrong container";
2053 end if;
2055 if Position.Index > Container.Last then
2056 raise Constraint_Error with "Position cursor is out of range";
2057 end if;
2059 if Container.Lock > 0 then
2060 raise Program_Error with
2061 "attempt to tamper with cursors (vector is locked)";
2062 end if;
2064 declare
2065 X : Element_Access := Container.Elements.EA (Position.Index);
2066 begin
2067 Container.Elements.EA (Position.Index) := new Element_Type'(New_Item);
2068 Free (X);
2069 end;
2070 end Replace_Element;
2072 ----------------------
2073 -- Reserve_Capacity --
2074 ----------------------
2076 procedure Reserve_Capacity
2077 (Container : in out Vector;
2078 Capacity : Count_Type)
2080 N : constant Count_Type := Length (Container);
2082 begin
2083 if Capacity = 0 then
2084 if N = 0 then
2085 declare
2086 X : Elements_Access := Container.Elements;
2087 begin
2088 Container.Elements := null;
2089 Free (X);
2090 end;
2092 elsif N < Container.Elements.EA'Length then
2093 if Container.Busy > 0 then
2094 raise Program_Error with
2095 "attempt to tamper with elements (vector is busy)";
2096 end if;
2098 declare
2099 subtype Array_Index_Subtype is Index_Type'Base range
2100 Index_Type'First .. Container.Last;
2102 Src : Elements_Array renames
2103 Container.Elements.EA (Array_Index_Subtype);
2105 X : Elements_Access := Container.Elements;
2107 begin
2108 Container.Elements := new Elements_Type'(Container.Last, Src);
2109 Free (X);
2110 end;
2111 end if;
2113 return;
2114 end if;
2116 if Container.Elements = null then
2117 declare
2118 Last_As_Int : constant Int'Base :=
2119 Int (Index_Type'First) + Int (Capacity) - 1;
2121 begin
2122 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2123 raise Constraint_Error with "new length is out of range";
2124 end if;
2126 declare
2127 Last : constant Index_Type := Index_Type (Last_As_Int);
2129 begin
2130 Container.Elements := new Elements_Type (Last);
2131 end;
2132 end;
2134 return;
2135 end if;
2137 if Capacity <= N then
2138 if N < Container.Elements.EA'Length then
2139 if Container.Busy > 0 then
2140 raise Program_Error with
2141 "attempt to tamper with elements (vector is busy)";
2142 end if;
2144 declare
2145 subtype Array_Index_Subtype is Index_Type'Base range
2146 Index_Type'First .. Container.Last;
2148 Src : Elements_Array renames
2149 Container.Elements.EA (Array_Index_Subtype);
2151 X : Elements_Access := Container.Elements;
2153 begin
2154 Container.Elements := new Elements_Type'(Container.Last, Src);
2155 Free (X);
2156 end;
2157 end if;
2159 return;
2160 end if;
2162 if Capacity = Container.Elements.EA'Length then
2163 return;
2164 end if;
2166 if Container.Busy > 0 then
2167 raise Program_Error with
2168 "attempt to tamper with elements (vector is busy)";
2169 end if;
2171 declare
2172 Last_As_Int : constant Int'Base :=
2173 Int (Index_Type'First) + Int (Capacity) - 1;
2175 begin
2176 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2177 raise Constraint_Error with "new length is out of range";
2178 end if;
2180 declare
2181 Last : constant Index_Type := Index_Type (Last_As_Int);
2182 X : Elements_Access := Container.Elements;
2184 subtype Index_Subtype is Index_Type'Base range
2185 Index_Type'First .. Container.Last;
2187 begin
2188 Container.Elements := new Elements_Type (Last);
2190 declare
2191 Src : Elements_Array renames
2192 X.EA (Index_Subtype);
2194 Tgt : Elements_Array renames
2195 Container.Elements.EA (Index_Subtype);
2197 begin
2198 Tgt := Src;
2199 end;
2201 Free (X);
2202 end;
2203 end;
2204 end Reserve_Capacity;
2206 ----------------------
2207 -- Reverse_Elements --
2208 ----------------------
2210 procedure Reverse_Elements (Container : in out Vector) is
2211 begin
2212 if Container.Length <= 1 then
2213 return;
2214 end if;
2216 if Container.Lock > 0 then
2217 raise Program_Error with
2218 "attempt to tamper with cursors (vector is locked)";
2219 end if;
2221 declare
2222 I : Index_Type;
2223 J : Index_Type;
2224 E : Elements_Array renames Container.Elements.EA;
2226 begin
2227 I := Index_Type'First;
2228 J := Container.Last;
2229 while I < J loop
2230 declare
2231 EI : constant Element_Access := E (I);
2233 begin
2234 E (I) := E (J);
2235 E (J) := EI;
2236 end;
2238 I := I + 1;
2239 J := J - 1;
2240 end loop;
2241 end;
2242 end Reverse_Elements;
2244 ------------------
2245 -- Reverse_Find --
2246 ------------------
2248 function Reverse_Find
2249 (Container : Vector;
2250 Item : Element_Type;
2251 Position : Cursor := No_Element) return Cursor
2253 Last : Index_Type'Base;
2255 begin
2256 if Position.Container /= null
2257 and then Position.Container /= Container'Unchecked_Access
2258 then
2259 raise Program_Error with "Position cursor denotes wrong container";
2260 end if;
2262 if Position.Container = null
2263 or else Position.Index > Container.Last
2264 then
2265 Last := Container.Last;
2266 else
2267 Last := Position.Index;
2268 end if;
2270 for Indx in reverse Index_Type'First .. Last loop
2271 if Container.Elements.EA (Indx) /= null
2272 and then Container.Elements.EA (Indx).all = Item
2273 then
2274 return (Container'Unchecked_Access, Indx);
2275 end if;
2276 end loop;
2278 return No_Element;
2279 end Reverse_Find;
2281 ------------------------
2282 -- Reverse_Find_Index --
2283 ------------------------
2285 function Reverse_Find_Index
2286 (Container : Vector;
2287 Item : Element_Type;
2288 Index : Index_Type := Index_Type'Last) return Extended_Index
2290 Last : Index_Type'Base;
2292 begin
2293 if Index > Container.Last then
2294 Last := Container.Last;
2295 else
2296 Last := Index;
2297 end if;
2299 for Indx in reverse Index_Type'First .. Last loop
2300 if Container.Elements.EA (Indx) /= null
2301 and then Container.Elements.EA (Indx).all = Item
2302 then
2303 return Indx;
2304 end if;
2305 end loop;
2307 return No_Index;
2308 end Reverse_Find_Index;
2310 ---------------------
2311 -- Reverse_Iterate --
2312 ---------------------
2314 procedure Reverse_Iterate
2315 (Container : Vector;
2316 Process : not null access procedure (Position : Cursor))
2318 V : Vector renames Container'Unrestricted_Access.all;
2319 B : Natural renames V.Busy;
2321 begin
2322 B := B + 1;
2324 begin
2325 for Indx in reverse Index_Type'First .. Container.Last loop
2326 Process (Cursor'(Container'Unchecked_Access, Indx));
2327 end loop;
2328 exception
2329 when others =>
2330 B := B - 1;
2331 raise;
2332 end;
2334 B := B - 1;
2335 end Reverse_Iterate;
2337 ----------------
2338 -- Set_Length --
2339 ----------------
2341 procedure Set_Length
2342 (Container : in out Vector;
2343 Length : Count_Type)
2345 N : constant Count_Type := Indefinite_Vectors.Length (Container);
2347 begin
2348 if Length = N then
2349 return;
2350 end if;
2352 if Container.Busy > 0 then
2353 raise Program_Error with
2354 "attempt to tamper with elements (vector is busy)";
2355 end if;
2357 if Length < N then
2358 for Index in 1 .. N - Length loop
2359 declare
2360 J : constant Index_Type := Container.Last;
2361 X : Element_Access := Container.Elements.EA (J);
2363 begin
2364 Container.Elements.EA (J) := null;
2365 Container.Last := J - 1;
2366 Free (X);
2367 end;
2368 end loop;
2370 return;
2371 end if;
2373 if Length > Capacity (Container) then
2374 Reserve_Capacity (Container, Capacity => Length);
2375 end if;
2377 declare
2378 Last_As_Int : constant Int'Base :=
2379 Int (Index_Type'First) + Int (Length) - 1;
2381 begin
2382 Container.Last := Index_Type (Last_As_Int);
2383 end;
2384 end Set_Length;
2386 ----------
2387 -- Swap --
2388 ----------
2390 procedure Swap
2391 (Container : in out Vector;
2392 I, J : Index_Type)
2394 begin
2395 if I > Container.Last then
2396 raise Constraint_Error with "I index is out of range";
2397 end if;
2399 if J > Container.Last then
2400 raise Constraint_Error with "J index is out of range";
2401 end if;
2403 if I = J then
2404 return;
2405 end if;
2407 if Container.Lock > 0 then
2408 raise Program_Error with
2409 "attempt to tamper with cursors (vector is locked)";
2410 end if;
2412 declare
2413 EI : Element_Access renames Container.Elements.EA (I);
2414 EJ : Element_Access renames Container.Elements.EA (J);
2416 EI_Copy : constant Element_Access := EI;
2418 begin
2419 EI := EJ;
2420 EJ := EI_Copy;
2421 end;
2422 end Swap;
2424 procedure Swap
2425 (Container : in out Vector;
2426 I, J : Cursor)
2428 begin
2429 if I.Container = null then
2430 raise Constraint_Error with "I cursor has no element";
2431 end if;
2433 if J.Container = null then
2434 raise Constraint_Error with "J cursor has no element";
2435 end if;
2437 if I.Container /= Container'Unrestricted_Access then
2438 raise Program_Error with "I cursor denotes wrong container";
2439 end if;
2441 if J.Container /= Container'Unrestricted_Access then
2442 raise Program_Error with "J cursor denotes wrong container";
2443 end if;
2445 Swap (Container, I.Index, J.Index);
2446 end Swap;
2448 ---------------
2449 -- To_Cursor --
2450 ---------------
2452 function To_Cursor
2453 (Container : Vector;
2454 Index : Extended_Index) return Cursor
2456 begin
2457 if Index not in Index_Type'First .. Container.Last then
2458 return No_Element;
2459 end if;
2461 return Cursor'(Container'Unchecked_Access, Index);
2462 end To_Cursor;
2464 --------------
2465 -- To_Index --
2466 --------------
2468 function To_Index (Position : Cursor) return Extended_Index is
2469 begin
2470 if Position.Container = null then
2471 return No_Index;
2472 end if;
2474 if Position.Index <= Position.Container.Last then
2475 return Position.Index;
2476 end if;
2478 return No_Index;
2479 end To_Index;
2481 ---------------
2482 -- To_Vector --
2483 ---------------
2485 function To_Vector (Length : Count_Type) return Vector is
2486 begin
2487 if Length = 0 then
2488 return Empty_Vector;
2489 end if;
2491 declare
2492 First : constant Int := Int (Index_Type'First);
2493 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2494 Last : Index_Type;
2495 Elements : Elements_Access;
2497 begin
2498 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2499 raise Constraint_Error with "Length is out of range";
2500 end if;
2502 Last := Index_Type (Last_As_Int);
2503 Elements := new Elements_Type (Last);
2505 return (Controlled with Elements, Last, 0, 0);
2506 end;
2507 end To_Vector;
2509 function To_Vector
2510 (New_Item : Element_Type;
2511 Length : Count_Type) return Vector
2513 begin
2514 if Length = 0 then
2515 return Empty_Vector;
2516 end if;
2518 declare
2519 First : constant Int := Int (Index_Type'First);
2520 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2521 Last : Index_Type'Base;
2522 Elements : Elements_Access;
2524 begin
2525 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2526 raise Constraint_Error with "Length is out of range";
2527 end if;
2529 Last := Index_Type (Last_As_Int);
2530 Elements := new Elements_Type (Last);
2532 Last := Index_Type'First;
2534 begin
2535 loop
2536 Elements.EA (Last) := new Element_Type'(New_Item);
2537 exit when Last = Elements.Last;
2538 Last := Last + 1;
2539 end loop;
2541 exception
2542 when others =>
2543 for J in Index_Type'First .. Last - 1 loop
2544 Free (Elements.EA (J));
2545 end loop;
2547 Free (Elements);
2548 raise;
2549 end;
2551 return (Controlled with Elements, Last, 0, 0);
2552 end;
2553 end To_Vector;
2555 --------------------
2556 -- Update_Element --
2557 --------------------
2559 procedure Update_Element
2560 (Container : in out Vector;
2561 Index : Index_Type;
2562 Process : not null access procedure (Element : in out Element_Type))
2564 B : Natural renames Container.Busy;
2565 L : Natural renames Container.Lock;
2567 begin
2568 if Index > Container.Last then
2569 raise Constraint_Error with "Index is out of range";
2570 end if;
2572 if Container.Elements.EA (Index) = null then
2573 raise Constraint_Error with "element is null";
2574 end if;
2576 B := B + 1;
2577 L := L + 1;
2579 begin
2580 Process (Container.Elements.EA (Index).all);
2581 exception
2582 when others =>
2583 L := L - 1;
2584 B := B - 1;
2585 raise;
2586 end;
2588 L := L - 1;
2589 B := B - 1;
2590 end Update_Element;
2592 procedure Update_Element
2593 (Container : in out Vector;
2594 Position : Cursor;
2595 Process : not null access procedure (Element : in out Element_Type))
2597 begin
2598 if Position.Container = null then
2599 raise Constraint_Error with "Position cursor has no element";
2600 end if;
2602 if Position.Container /= Container'Unrestricted_Access then
2603 raise Program_Error with "Position cursor denotes wrong container";
2604 end if;
2606 Update_Element (Container, Position.Index, Process);
2607 end Update_Element;
2609 -----------
2610 -- Write --
2611 -----------
2613 procedure Write
2614 (Stream : not null access Root_Stream_Type'Class;
2615 Container : Vector)
2617 N : constant Count_Type := Length (Container);
2619 begin
2620 Count_Type'Base'Write (Stream, N);
2622 if N = 0 then
2623 return;
2624 end if;
2626 declare
2627 E : Elements_Array renames Container.Elements.EA;
2629 begin
2630 for Indx in Index_Type'First .. Container.Last loop
2631 if E (Indx) = null then
2632 Boolean'Write (Stream, False);
2633 else
2634 Boolean'Write (Stream, True);
2635 Element_Type'Output (Stream, E (Indx).all);
2636 end if;
2637 end loop;
2638 end;
2639 end Write;
2641 procedure Write
2642 (Stream : not null access Root_Stream_Type'Class;
2643 Position : Cursor)
2645 begin
2646 raise Program_Error with "attempt to stream vector cursor";
2647 end Write;
2649 end Ada.Containers.Indefinite_Vectors;