Merged with mainline at revision 128810.
[official-gcc.git] / gcc / ada / a-coinve.adb
blob8233a4e9b907303663387f7320621137abeb319d
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 begin
624 if Position.Container = null then
625 raise Constraint_Error with "Position cursor has no element";
626 end if;
628 if Position.Container /= Container'Unrestricted_Access then
629 raise Program_Error with "Position cursor denotes wrong container";
630 end if;
632 if Position.Index > Container.Last then
633 raise Program_Error with "Position index is out of range";
634 end if;
636 Delete (Container, Position.Index, Count);
638 Position := No_Element;
639 end Delete;
641 ------------------
642 -- Delete_First --
643 ------------------
645 procedure Delete_First
646 (Container : in out Vector;
647 Count : Count_Type := 1)
649 begin
650 if Count = 0 then
651 return;
652 end if;
654 if Count >= Length (Container) then
655 Clear (Container);
656 return;
657 end if;
659 Delete (Container, Index_Type'First, Count);
660 end Delete_First;
662 -----------------
663 -- Delete_Last --
664 -----------------
666 procedure Delete_Last
667 (Container : in out Vector;
668 Count : Count_Type := 1)
670 N : constant Count_Type := Length (Container);
672 begin
673 if Count = 0
674 or else N = 0
675 then
676 return;
677 end if;
679 if Container.Busy > 0 then
680 raise Program_Error with
681 "attempt to tamper with elements (vector is busy)";
682 end if;
684 declare
685 E : Elements_Array renames Container.Elements.EA;
687 begin
688 for Indx in 1 .. Count_Type'Min (Count, N) loop
689 declare
690 J : constant Index_Type := Container.Last;
691 X : Element_Access := E (J);
693 begin
694 E (J) := null;
695 Container.Last := J - 1;
696 Free (X);
697 end;
698 end loop;
699 end;
700 end Delete_Last;
702 -------------
703 -- Element --
704 -------------
706 function Element
707 (Container : Vector;
708 Index : Index_Type) return Element_Type
710 begin
711 if Index > Container.Last then
712 raise Constraint_Error with "Index is out of range";
713 end if;
715 declare
716 EA : constant Element_Access := Container.Elements.EA (Index);
718 begin
719 if EA = null then
720 raise Constraint_Error with "element is empty";
721 end if;
723 return EA.all;
724 end;
725 end Element;
727 function Element (Position : Cursor) return Element_Type is
728 begin
729 if Position.Container = null then
730 raise Constraint_Error with "Position cursor has no element";
731 end if;
733 if Position.Index > Position.Container.Last then
734 raise Constraint_Error with "Position cursor is out of range";
735 end if;
737 declare
738 EA : constant Element_Access :=
739 Position.Container.Elements.EA (Position.Index);
741 begin
742 if EA = null then
743 raise Constraint_Error with "element is empty";
744 end if;
746 return EA.all;
747 end;
748 end Element;
750 --------------
751 -- Finalize --
752 --------------
754 procedure Finalize (Container : in out Vector) is
755 begin
756 Clear (Container); -- Checks busy-bit
758 declare
759 X : Elements_Access := Container.Elements;
760 begin
761 Container.Elements := null;
762 Free (X);
763 end;
764 end Finalize;
766 ----------
767 -- Find --
768 ----------
770 function Find
771 (Container : Vector;
772 Item : Element_Type;
773 Position : Cursor := No_Element) return Cursor
775 begin
776 if Position.Container /= null then
777 if Position.Container /= Container'Unrestricted_Access then
778 raise Program_Error with "Position cursor denotes wrong container";
779 end if;
781 if Position.Index > Container.Last then
782 raise Program_Error with "Position index is out of range";
783 end if;
784 end if;
786 for J in Position.Index .. Container.Last loop
787 if Container.Elements.EA (J) /= null
788 and then Container.Elements.EA (J).all = Item
789 then
790 return (Container'Unchecked_Access, J);
791 end if;
792 end loop;
794 return No_Element;
795 end Find;
797 ----------------
798 -- Find_Index --
799 ----------------
801 function Find_Index
802 (Container : Vector;
803 Item : Element_Type;
804 Index : Index_Type := Index_Type'First) return Extended_Index
806 begin
807 for Indx in Index .. Container.Last loop
808 if Container.Elements.EA (Indx) /= null
809 and then Container.Elements.EA (Indx).all = Item
810 then
811 return Indx;
812 end if;
813 end loop;
815 return No_Index;
816 end Find_Index;
818 -----------
819 -- First --
820 -----------
822 function First (Container : Vector) return Cursor is
823 begin
824 if Is_Empty (Container) then
825 return No_Element;
826 end if;
828 return (Container'Unchecked_Access, Index_Type'First);
829 end First;
831 -------------------
832 -- First_Element --
833 -------------------
835 function First_Element (Container : Vector) return Element_Type is
836 begin
837 if Container.Last = No_Index then
838 raise Constraint_Error with "Container is empty";
839 end if;
841 declare
842 EA : constant Element_Access :=
843 Container.Elements.EA (Index_Type'First);
845 begin
846 if EA = null then
847 raise Constraint_Error with "first element is empty";
848 end if;
850 return EA.all;
851 end;
852 end First_Element;
854 -----------------
855 -- First_Index --
856 -----------------
858 function First_Index (Container : Vector) return Index_Type is
859 pragma Unreferenced (Container);
860 begin
861 return Index_Type'First;
862 end First_Index;
864 ---------------------
865 -- Generic_Sorting --
866 ---------------------
868 package body Generic_Sorting is
870 -----------------------
871 -- Local Subprograms --
872 -----------------------
874 function Is_Less (L, R : Element_Access) return Boolean;
875 pragma Inline (Is_Less);
877 -------------
878 -- Is_Less --
879 -------------
881 function Is_Less (L, R : Element_Access) return Boolean is
882 begin
883 if L = null then
884 return R /= null;
885 elsif R = null then
886 return False;
887 else
888 return L.all < R.all;
889 end if;
890 end Is_Less;
892 ---------------
893 -- Is_Sorted --
894 ---------------
896 function Is_Sorted (Container : Vector) return Boolean is
897 begin
898 if Container.Last <= Index_Type'First then
899 return True;
900 end if;
902 declare
903 E : Elements_Array renames Container.Elements.EA;
904 begin
905 for I in Index_Type'First .. Container.Last - 1 loop
906 if Is_Less (E (I + 1), E (I)) then
907 return False;
908 end if;
909 end loop;
910 end;
912 return True;
913 end Is_Sorted;
915 -----------
916 -- Merge --
917 -----------
919 procedure Merge (Target, Source : in out Vector) is
920 I, J : Index_Type'Base;
922 begin
923 if Target.Last < Index_Type'First then
924 Move (Target => Target, Source => Source);
925 return;
926 end if;
928 if Target'Address = Source'Address then
929 return;
930 end if;
932 if Source.Last < Index_Type'First then
933 return;
934 end if;
936 if Source.Busy > 0 then
937 raise Program_Error with
938 "attempt to tamper with elements (vector is busy)";
939 end if;
941 I := Target.Last; -- original value (before Set_Length)
942 Target.Set_Length (Length (Target) + Length (Source));
944 J := Target.Last; -- new value (after Set_Length)
945 while Source.Last >= Index_Type'First loop
946 pragma Assert
947 (Source.Last <= Index_Type'First
948 or else not (Is_Less
949 (Source.Elements.EA (Source.Last),
950 Source.Elements.EA (Source.Last - 1))));
952 if I < Index_Type'First then
953 declare
954 Src : Elements_Array renames
955 Source.Elements.EA (Index_Type'First .. Source.Last);
957 begin
958 Target.Elements.EA (Index_Type'First .. J) := Src;
959 Src := (others => null);
960 end;
962 Source.Last := No_Index;
963 return;
964 end if;
966 pragma Assert
967 (I <= Index_Type'First
968 or else not (Is_Less
969 (Target.Elements.EA (I),
970 Target.Elements.EA (I - 1))));
972 declare
973 Src : Element_Access renames Source.Elements.EA (Source.Last);
974 Tgt : Element_Access renames Target.Elements.EA (I);
976 begin
977 if Is_Less (Src, Tgt) then
978 Target.Elements.EA (J) := Tgt;
979 Tgt := null;
980 I := I - 1;
982 else
983 Target.Elements.EA (J) := Src;
984 Src := null;
985 Source.Last := Source.Last - 1;
986 end if;
987 end;
989 J := J - 1;
990 end loop;
991 end Merge;
993 ----------
994 -- Sort --
995 ----------
997 procedure Sort (Container : in out Vector)
999 procedure Sort is
1000 new Generic_Array_Sort
1001 (Index_Type => Index_Type,
1002 Element_Type => Element_Access,
1003 Array_Type => Elements_Array,
1004 "<" => Is_Less);
1006 -- Start of processing for Sort
1008 begin
1009 if Container.Last <= Index_Type'First then
1010 return;
1011 end if;
1013 if Container.Lock > 0 then
1014 raise Program_Error with
1015 "attempt to tamper with cursors (vector is locked)";
1016 end if;
1018 Sort (Container.Elements.EA (Index_Type'First .. Container.Last));
1019 end Sort;
1021 end Generic_Sorting;
1023 -----------------
1024 -- Has_Element --
1025 -----------------
1027 function Has_Element (Position : Cursor) return Boolean is
1028 begin
1029 if Position.Container = null then
1030 return False;
1031 end if;
1033 return Position.Index <= Position.Container.Last;
1034 end Has_Element;
1036 ------------
1037 -- Insert --
1038 ------------
1040 procedure Insert
1041 (Container : in out Vector;
1042 Before : Extended_Index;
1043 New_Item : Element_Type;
1044 Count : Count_Type := 1)
1046 N : constant Int := Int (Count);
1048 First : constant Int := Int (Index_Type'First);
1049 New_Last_As_Int : Int'Base;
1050 New_Last : Index_Type;
1051 New_Length : UInt;
1052 Max_Length : constant UInt := UInt (Count_Type'Last);
1054 Dst : Elements_Access;
1056 begin
1057 if Before < Index_Type'First then
1058 raise Constraint_Error with
1059 "Before index is out of range (too small)";
1060 end if;
1062 if Before > Container.Last
1063 and then Before > Container.Last + 1
1064 then
1065 raise Constraint_Error with
1066 "Before index is out of range (too large)";
1067 end if;
1069 if Count = 0 then
1070 return;
1071 end if;
1073 declare
1074 Old_Last_As_Int : constant Int := Int (Container.Last);
1076 begin
1077 if Old_Last_As_Int > Int'Last - N then
1078 raise Constraint_Error with "new length is out of range";
1079 end if;
1081 New_Last_As_Int := Old_Last_As_Int + N;
1083 if New_Last_As_Int > Int (Index_Type'Last) then
1084 raise Constraint_Error with "new length is out of range";
1085 end if;
1087 New_Length := UInt (New_Last_As_Int - First + 1);
1089 if New_Length > Max_Length then
1090 raise Constraint_Error with "new length is out of range";
1091 end if;
1093 New_Last := Index_Type (New_Last_As_Int);
1094 end;
1096 if Container.Busy > 0 then
1097 raise Program_Error with
1098 "attempt to tamper with elements (vector is busy)";
1099 end if;
1101 if Container.Elements = null then
1102 Container.Elements := new Elements_Type (New_Last);
1103 Container.Last := No_Index;
1105 for J in Container.Elements.EA'Range loop
1106 Container.Elements.EA (J) := new Element_Type'(New_Item);
1107 Container.Last := J;
1108 end loop;
1110 return;
1111 end if;
1113 if New_Last <= Container.Elements.Last then
1114 declare
1115 E : Elements_Array renames Container.Elements.EA;
1117 begin
1118 if Before <= Container.Last then
1119 declare
1120 Index_As_Int : constant Int'Base :=
1121 Index_Type'Pos (Before) + N;
1123 Index : constant Index_Type := Index_Type (Index_As_Int);
1125 J : Index_Type'Base;
1127 begin
1128 E (Index .. New_Last) := E (Before .. Container.Last);
1129 Container.Last := New_Last;
1131 J := Before;
1132 while J < Index loop
1133 E (J) := new Element_Type'(New_Item);
1134 J := J + 1;
1135 end loop;
1137 exception
1138 when others =>
1139 E (J .. Index - 1) := (others => null);
1140 raise;
1141 end;
1143 else
1144 for J in Before .. New_Last loop
1145 E (J) := new Element_Type'(New_Item);
1146 Container.Last := J;
1147 end loop;
1148 end if;
1149 end;
1151 return;
1152 end if;
1154 declare
1155 C, CC : UInt;
1157 begin
1158 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1159 while C < New_Length loop
1160 if C > UInt'Last / 2 then
1161 C := UInt'Last;
1162 exit;
1163 end if;
1165 C := 2 * C;
1166 end loop;
1168 if C > Max_Length then
1169 C := Max_Length;
1170 end if;
1172 if Index_Type'First <= 0
1173 and then Index_Type'Last >= 0
1174 then
1175 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1177 else
1178 CC := UInt (Int (Index_Type'Last) - First + 1);
1179 end if;
1181 if C > CC then
1182 C := CC;
1183 end if;
1185 declare
1186 Dst_Last : constant Index_Type :=
1187 Index_Type (First + UInt'Pos (C) - Int'(1));
1189 begin
1190 Dst := new Elements_Type (Dst_Last);
1191 end;
1192 end;
1194 if Before <= Container.Last then
1195 declare
1196 Index_As_Int : constant Int'Base :=
1197 Index_Type'Pos (Before) + N;
1199 Index : constant Index_Type := Index_Type (Index_As_Int);
1201 Src : Elements_Access := Container.Elements;
1203 begin
1204 Dst.EA (Index_Type'First .. Before - 1) :=
1205 Src.EA (Index_Type'First .. Before - 1);
1207 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1209 Container.Elements := Dst;
1210 Container.Last := New_Last;
1211 Free (Src);
1213 for J in Before .. Index - 1 loop
1214 Dst.EA (J) := new Element_Type'(New_Item);
1215 end loop;
1216 end;
1218 else
1219 declare
1220 Src : Elements_Access := Container.Elements;
1222 begin
1223 Dst.EA (Index_Type'First .. Container.Last) :=
1224 Src.EA (Index_Type'First .. Container.Last);
1226 Container.Elements := Dst;
1227 Free (Src);
1229 for J in Before .. New_Last loop
1230 Dst.EA (J) := new Element_Type'(New_Item);
1231 Container.Last := J;
1232 end loop;
1233 end;
1234 end if;
1235 end Insert;
1237 procedure Insert
1238 (Container : in out Vector;
1239 Before : Extended_Index;
1240 New_Item : Vector)
1242 N : constant Count_Type := Length (New_Item);
1244 begin
1245 if Before < Index_Type'First then
1246 raise Constraint_Error with
1247 "Before index is out of range (too small)";
1248 end if;
1250 if Before > Container.Last
1251 and then Before > Container.Last + 1
1252 then
1253 raise Constraint_Error with
1254 "Before index is out of range (too large)";
1255 end if;
1257 if N = 0 then
1258 return;
1259 end if;
1261 Insert_Space (Container, Before, Count => N);
1263 declare
1264 Dst_Last_As_Int : constant Int'Base :=
1265 Int'Base (Before) + Int'Base (N) - 1;
1267 Dst_Last : constant Index_Type := Index_Type (Dst_Last_As_Int);
1269 Dst : Elements_Array renames
1270 Container.Elements.EA (Before .. Dst_Last);
1272 Dst_Index : Index_Type'Base := Before - 1;
1274 begin
1275 if Container'Address /= New_Item'Address then
1276 declare
1277 subtype Src_Index_Subtype is Index_Type'Base range
1278 Index_Type'First .. New_Item.Last;
1280 Src : Elements_Array renames
1281 New_Item.Elements.EA (Src_Index_Subtype);
1283 begin
1284 for Src_Index in Src'Range loop
1285 Dst_Index := Dst_Index + 1;
1287 if Src (Src_Index) /= null then
1288 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1289 end if;
1290 end loop;
1291 end;
1293 return;
1294 end if;
1296 declare
1297 subtype Src_Index_Subtype is Index_Type'Base range
1298 Index_Type'First .. Before - 1;
1300 Src : Elements_Array renames
1301 Container.Elements.EA (Src_Index_Subtype);
1303 begin
1304 for Src_Index in Src'Range loop
1305 Dst_Index := Dst_Index + 1;
1307 if Src (Src_Index) /= null then
1308 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1309 end if;
1310 end loop;
1311 end;
1313 if Dst_Last = Container.Last then
1314 return;
1315 end if;
1317 declare
1318 subtype Src_Index_Subtype is Index_Type'Base range
1319 Dst_Last + 1 .. Container.Last;
1321 Src : Elements_Array renames
1322 Container.Elements.EA (Src_Index_Subtype);
1324 begin
1325 for Src_Index in Src'Range loop
1326 Dst_Index := Dst_Index + 1;
1328 if Src (Src_Index) /= null then
1329 Dst (Dst_Index) := new Element_Type'(Src (Src_Index).all);
1330 end if;
1331 end loop;
1332 end;
1333 end;
1334 end Insert;
1336 procedure Insert
1337 (Container : in out Vector;
1338 Before : Cursor;
1339 New_Item : Vector)
1341 Index : Index_Type'Base;
1343 begin
1344 if Before.Container /= null
1345 and then Before.Container /= Container'Unchecked_Access
1346 then
1347 raise Program_Error with "Before cursor denotes wrong container";
1348 end if;
1350 if Is_Empty (New_Item) then
1351 return;
1352 end if;
1354 if Before.Container = null
1355 or else Before.Index > Container.Last
1356 then
1357 if Container.Last = Index_Type'Last then
1358 raise Constraint_Error with
1359 "vector is already at its maximum length";
1360 end if;
1362 Index := Container.Last + 1;
1364 else
1365 Index := Before.Index;
1366 end if;
1368 Insert (Container, Index, New_Item);
1369 end Insert;
1371 procedure Insert
1372 (Container : in out Vector;
1373 Before : Cursor;
1374 New_Item : Vector;
1375 Position : out Cursor)
1377 Index : Index_Type'Base;
1379 begin
1380 if Before.Container /= null
1381 and then Before.Container /= Vector_Access'(Container'Unchecked_Access)
1382 then
1383 raise Program_Error with "Before cursor denotes wrong container";
1384 end if;
1386 if Is_Empty (New_Item) then
1387 if Before.Container = null
1388 or else Before.Index > Container.Last
1389 then
1390 Position := No_Element;
1391 else
1392 Position := (Container'Unchecked_Access, Before.Index);
1393 end if;
1395 return;
1396 end if;
1398 if Before.Container = null
1399 or else Before.Index > Container.Last
1400 then
1401 if Container.Last = Index_Type'Last then
1402 raise Constraint_Error with
1403 "vector is already at its maximum length";
1404 end if;
1406 Index := Container.Last + 1;
1408 else
1409 Index := Before.Index;
1410 end if;
1412 Insert (Container, Index, New_Item);
1414 Position := Cursor'(Container'Unchecked_Access, Index);
1415 end Insert;
1417 procedure Insert
1418 (Container : in out Vector;
1419 Before : Cursor;
1420 New_Item : Element_Type;
1421 Count : Count_Type := 1)
1423 Index : Index_Type'Base;
1425 begin
1426 if Before.Container /= null
1427 and then Before.Container /= Container'Unchecked_Access
1428 then
1429 raise Program_Error with "Before cursor denotes wrong container";
1430 end if;
1432 if Count = 0 then
1433 return;
1434 end if;
1436 if Before.Container = null
1437 or else Before.Index > Container.Last
1438 then
1439 if Container.Last = Index_Type'Last then
1440 raise Constraint_Error with
1441 "vector is already at its maximum length";
1442 end if;
1444 Index := Container.Last + 1;
1446 else
1447 Index := Before.Index;
1448 end if;
1450 Insert (Container, Index, New_Item, Count);
1451 end Insert;
1453 procedure Insert
1454 (Container : in out Vector;
1455 Before : Cursor;
1456 New_Item : Element_Type;
1457 Position : out Cursor;
1458 Count : Count_Type := 1)
1460 Index : Index_Type'Base;
1462 begin
1463 if Before.Container /= null
1464 and then Before.Container /= Container'Unchecked_Access
1465 then
1466 raise Program_Error with "Before cursor denotes wrong container";
1467 end if;
1469 if Count = 0 then
1470 if Before.Container = null
1471 or else Before.Index > Container.Last
1472 then
1473 Position := No_Element;
1474 else
1475 Position := (Container'Unchecked_Access, Before.Index);
1476 end if;
1478 return;
1479 end if;
1481 if Before.Container = null
1482 or else Before.Index > Container.Last
1483 then
1484 if Container.Last = Index_Type'Last then
1485 raise Constraint_Error with
1486 "vector is already at its maximum length";
1487 end if;
1489 Index := Container.Last + 1;
1491 else
1492 Index := Before.Index;
1493 end if;
1495 Insert (Container, Index, New_Item, Count);
1497 Position := (Container'Unchecked_Access, Index);
1498 end Insert;
1500 ------------------
1501 -- Insert_Space --
1502 ------------------
1504 procedure Insert_Space
1505 (Container : in out Vector;
1506 Before : Extended_Index;
1507 Count : Count_Type := 1)
1509 N : constant Int := Int (Count);
1511 First : constant Int := Int (Index_Type'First);
1512 New_Last_As_Int : Int'Base;
1513 New_Last : Index_Type;
1514 New_Length : UInt;
1515 Max_Length : constant UInt := UInt (Count_Type'Last);
1517 Dst : Elements_Access;
1519 begin
1520 if Before < Index_Type'First then
1521 raise Constraint_Error with
1522 "Before index is out of range (too small)";
1523 end if;
1525 if Before > Container.Last
1526 and then Before > Container.Last + 1
1527 then
1528 raise Constraint_Error with
1529 "Before index is out of range (too large)";
1530 end if;
1532 if Count = 0 then
1533 return;
1534 end if;
1536 declare
1537 Old_Last_As_Int : constant Int := Int (Container.Last);
1539 begin
1540 if Old_Last_As_Int > Int'Last - N then
1541 raise Constraint_Error with "new length is out of range";
1542 end if;
1544 New_Last_As_Int := Old_Last_As_Int + N;
1546 if New_Last_As_Int > Int (Index_Type'Last) then
1547 raise Constraint_Error with "new length is out of range";
1548 end if;
1550 New_Length := UInt (New_Last_As_Int - First + 1);
1552 if New_Length > Max_Length then
1553 raise Constraint_Error with "new length is out of range";
1554 end if;
1556 New_Last := Index_Type (New_Last_As_Int);
1557 end;
1559 if Container.Busy > 0 then
1560 raise Program_Error with
1561 "attempt to tamper with elements (vector is busy)";
1562 end if;
1564 if Container.Elements = null then
1565 Container.Elements := new Elements_Type (New_Last);
1566 Container.Last := New_Last;
1567 return;
1568 end if;
1570 if New_Last <= Container.Elements.Last then
1571 declare
1572 E : Elements_Array renames Container.Elements.EA;
1574 begin
1575 if Before <= Container.Last then
1576 declare
1577 Index_As_Int : constant Int'Base :=
1578 Index_Type'Pos (Before) + N;
1580 Index : constant Index_Type := Index_Type (Index_As_Int);
1582 begin
1583 E (Index .. New_Last) := E (Before .. Container.Last);
1584 E (Before .. Index - 1) := (others => null);
1585 end;
1586 end if;
1587 end;
1589 Container.Last := New_Last;
1590 return;
1591 end if;
1593 declare
1594 C, CC : UInt;
1596 begin
1597 C := UInt'Max (1, Container.Elements.EA'Length); -- ???
1598 while C < New_Length loop
1599 if C > UInt'Last / 2 then
1600 C := UInt'Last;
1601 exit;
1602 end if;
1604 C := 2 * C;
1605 end loop;
1607 if C > Max_Length then
1608 C := Max_Length;
1609 end if;
1611 if Index_Type'First <= 0
1612 and then Index_Type'Last >= 0
1613 then
1614 CC := UInt (Index_Type'Last) + UInt (-Index_Type'First) + 1;
1616 else
1617 CC := UInt (Int (Index_Type'Last) - First + 1);
1618 end if;
1620 if C > CC then
1621 C := CC;
1622 end if;
1624 declare
1625 Dst_Last : constant Index_Type :=
1626 Index_Type (First + UInt'Pos (C) - 1);
1628 begin
1629 Dst := new Elements_Type (Dst_Last);
1630 end;
1631 end;
1633 declare
1634 Src : Elements_Access := Container.Elements;
1636 begin
1637 if Before <= Container.Last then
1638 declare
1639 Index_As_Int : constant Int'Base :=
1640 Index_Type'Pos (Before) + N;
1642 Index : constant Index_Type := Index_Type (Index_As_Int);
1644 begin
1645 Dst.EA (Index_Type'First .. Before - 1) :=
1646 Src.EA (Index_Type'First .. Before - 1);
1648 Dst.EA (Index .. New_Last) := Src.EA (Before .. Container.Last);
1649 end;
1651 else
1652 Dst.EA (Index_Type'First .. Container.Last) :=
1653 Src.EA (Index_Type'First .. Container.Last);
1654 end if;
1656 Container.Elements := Dst;
1657 Container.Last := New_Last;
1658 Free (Src);
1659 end;
1660 end Insert_Space;
1662 procedure Insert_Space
1663 (Container : in out Vector;
1664 Before : Cursor;
1665 Position : out Cursor;
1666 Count : Count_Type := 1)
1668 Index : Index_Type'Base;
1670 begin
1671 if Before.Container /= null
1672 and then Before.Container /= Container'Unchecked_Access
1673 then
1674 raise Program_Error with "Before cursor denotes wrong container";
1675 end if;
1677 if Count = 0 then
1678 if Before.Container = null
1679 or else Before.Index > Container.Last
1680 then
1681 Position := No_Element;
1682 else
1683 Position := (Container'Unchecked_Access, Before.Index);
1684 end if;
1686 return;
1687 end if;
1689 if Before.Container = null
1690 or else Before.Index > Container.Last
1691 then
1692 if Container.Last = Index_Type'Last then
1693 raise Constraint_Error with
1694 "vector is already at its maximum length";
1695 end if;
1697 Index := Container.Last + 1;
1699 else
1700 Index := Before.Index;
1701 end if;
1703 Insert_Space (Container, Index, Count);
1705 Position := Cursor'(Container'Unchecked_Access, Index);
1706 end Insert_Space;
1708 --------------
1709 -- Is_Empty --
1710 --------------
1712 function Is_Empty (Container : Vector) return Boolean is
1713 begin
1714 return Container.Last < Index_Type'First;
1715 end Is_Empty;
1717 -------------
1718 -- Iterate --
1719 -------------
1721 procedure Iterate
1722 (Container : Vector;
1723 Process : not null access procedure (Position : Cursor))
1725 V : Vector renames Container'Unrestricted_Access.all;
1726 B : Natural renames V.Busy;
1728 begin
1729 B := B + 1;
1731 begin
1732 for Indx in Index_Type'First .. Container.Last loop
1733 Process (Cursor'(Container'Unchecked_Access, Indx));
1734 end loop;
1735 exception
1736 when others =>
1737 B := B - 1;
1738 raise;
1739 end;
1741 B := B - 1;
1742 end Iterate;
1744 ----------
1745 -- Last --
1746 ----------
1748 function Last (Container : Vector) return Cursor is
1749 begin
1750 if Is_Empty (Container) then
1751 return No_Element;
1752 end if;
1754 return (Container'Unchecked_Access, Container.Last);
1755 end Last;
1757 ------------------
1758 -- Last_Element --
1759 ------------------
1761 function Last_Element (Container : Vector) return Element_Type is
1762 begin
1763 if Container.Last = No_Index then
1764 raise Constraint_Error with "Container is empty";
1765 end if;
1767 declare
1768 EA : constant Element_Access :=
1769 Container.Elements.EA (Container.Last);
1771 begin
1772 if EA = null then
1773 raise Constraint_Error with "last element is empty";
1774 end if;
1776 return EA.all;
1777 end;
1778 end Last_Element;
1780 ----------------
1781 -- Last_Index --
1782 ----------------
1784 function Last_Index (Container : Vector) return Extended_Index is
1785 begin
1786 return Container.Last;
1787 end Last_Index;
1789 ------------
1790 -- Length --
1791 ------------
1793 function Length (Container : Vector) return Count_Type is
1794 L : constant Int := Int (Container.Last);
1795 F : constant Int := Int (Index_Type'First);
1796 N : constant Int'Base := L - F + 1;
1798 begin
1799 return Count_Type (N);
1800 end Length;
1802 ----------
1803 -- Move --
1804 ----------
1806 procedure Move
1807 (Target : in out Vector;
1808 Source : in out Vector)
1810 begin
1811 if Target'Address = Source'Address then
1812 return;
1813 end if;
1815 if Source.Busy > 0 then
1816 raise Program_Error with
1817 "attempt to tamper with elements (Source is busy)";
1818 end if;
1820 Clear (Target); -- Checks busy-bit
1822 declare
1823 Target_Elements : constant Elements_Access := Target.Elements;
1824 begin
1825 Target.Elements := Source.Elements;
1826 Source.Elements := Target_Elements;
1827 end;
1829 Target.Last := Source.Last;
1830 Source.Last := No_Index;
1831 end Move;
1833 ----------
1834 -- Next --
1835 ----------
1837 function Next (Position : Cursor) return Cursor is
1838 begin
1839 if Position.Container = null then
1840 return No_Element;
1841 end if;
1843 if Position.Index < Position.Container.Last then
1844 return (Position.Container, Position.Index + 1);
1845 end if;
1847 return No_Element;
1848 end Next;
1850 ----------
1851 -- Next --
1852 ----------
1854 procedure Next (Position : in out Cursor) is
1855 begin
1856 if Position.Container = null then
1857 return;
1858 end if;
1860 if Position.Index < Position.Container.Last then
1861 Position.Index := Position.Index + 1;
1862 else
1863 Position := No_Element;
1864 end if;
1865 end Next;
1867 -------------
1868 -- Prepend --
1869 -------------
1871 procedure Prepend (Container : in out Vector; New_Item : Vector) is
1872 begin
1873 Insert (Container, Index_Type'First, New_Item);
1874 end Prepend;
1876 procedure Prepend
1877 (Container : in out Vector;
1878 New_Item : Element_Type;
1879 Count : Count_Type := 1)
1881 begin
1882 Insert (Container,
1883 Index_Type'First,
1884 New_Item,
1885 Count);
1886 end Prepend;
1888 --------------
1889 -- Previous --
1890 --------------
1892 procedure Previous (Position : in out Cursor) is
1893 begin
1894 if Position.Container = null then
1895 return;
1896 end if;
1898 if Position.Index > Index_Type'First then
1899 Position.Index := Position.Index - 1;
1900 else
1901 Position := No_Element;
1902 end if;
1903 end Previous;
1905 function Previous (Position : Cursor) return Cursor is
1906 begin
1907 if Position.Container = null then
1908 return No_Element;
1909 end if;
1911 if Position.Index > Index_Type'First then
1912 return (Position.Container, Position.Index - 1);
1913 end if;
1915 return No_Element;
1916 end Previous;
1918 -------------------
1919 -- Query_Element --
1920 -------------------
1922 procedure Query_Element
1923 (Container : Vector;
1924 Index : Index_Type;
1925 Process : not null access procedure (Element : Element_Type))
1927 V : Vector renames Container'Unrestricted_Access.all;
1928 B : Natural renames V.Busy;
1929 L : Natural renames V.Lock;
1931 begin
1932 if Index > Container.Last then
1933 raise Constraint_Error with "Index is out of range";
1934 end if;
1936 if V.Elements.EA (Index) = null then
1937 raise Constraint_Error with "element is null";
1938 end if;
1940 B := B + 1;
1941 L := L + 1;
1943 begin
1944 Process (V.Elements.EA (Index).all);
1945 exception
1946 when others =>
1947 L := L - 1;
1948 B := B - 1;
1949 raise;
1950 end;
1952 L := L - 1;
1953 B := B - 1;
1954 end Query_Element;
1956 procedure Query_Element
1957 (Position : Cursor;
1958 Process : not null access procedure (Element : Element_Type))
1960 begin
1961 if Position.Container = null then
1962 raise Constraint_Error with "Position cursor has no element";
1963 end if;
1965 Query_Element (Position.Container.all, Position.Index, Process);
1966 end Query_Element;
1968 ----------
1969 -- Read --
1970 ----------
1972 procedure Read
1973 (Stream : not null access Root_Stream_Type'Class;
1974 Container : out Vector)
1976 Length : Count_Type'Base;
1977 Last : Index_Type'Base := Index_Type'Pred (Index_Type'First);
1979 B : Boolean;
1981 begin
1982 Clear (Container);
1984 Count_Type'Base'Read (Stream, Length);
1986 if Length > Capacity (Container) then
1987 Reserve_Capacity (Container, Capacity => Length);
1988 end if;
1990 for J in Count_Type range 1 .. Length loop
1991 Last := Last + 1;
1993 Boolean'Read (Stream, B);
1995 if B then
1996 Container.Elements.EA (Last) :=
1997 new Element_Type'(Element_Type'Input (Stream));
1998 end if;
2000 Container.Last := Last;
2001 end loop;
2002 end Read;
2004 procedure Read
2005 (Stream : not null access Root_Stream_Type'Class;
2006 Position : out Cursor)
2008 begin
2009 raise Program_Error with "attempt to stream vector cursor";
2010 end Read;
2012 ---------------------
2013 -- Replace_Element --
2014 ---------------------
2016 procedure Replace_Element
2017 (Container : in out Vector;
2018 Index : Index_Type;
2019 New_Item : Element_Type)
2021 begin
2022 if Index > Container.Last then
2023 raise Constraint_Error with "Index is out of range";
2024 end if;
2026 if Container.Lock > 0 then
2027 raise Program_Error with
2028 "attempt to tamper with cursors (vector is locked)";
2029 end if;
2031 declare
2032 X : Element_Access := Container.Elements.EA (Index);
2033 begin
2034 Container.Elements.EA (Index) := new Element_Type'(New_Item);
2035 Free (X);
2036 end;
2037 end Replace_Element;
2039 procedure Replace_Element
2040 (Container : in out Vector;
2041 Position : Cursor;
2042 New_Item : Element_Type)
2044 begin
2045 if Position.Container = null then
2046 raise Constraint_Error with "Position cursor has no element";
2047 end if;
2049 if Position.Container /= Container'Unrestricted_Access then
2050 raise Program_Error with "Position cursor denotes wrong container";
2051 end if;
2053 if Position.Index > Container.Last then
2054 raise Constraint_Error with "Position cursor is out of range";
2055 end if;
2057 if Container.Lock > 0 then
2058 raise Program_Error with
2059 "attempt to tamper with cursors (vector is locked)";
2060 end if;
2062 declare
2063 X : Element_Access := Container.Elements.EA (Position.Index);
2064 begin
2065 Container.Elements.EA (Position.Index) := new Element_Type'(New_Item);
2066 Free (X);
2067 end;
2068 end Replace_Element;
2070 ----------------------
2071 -- Reserve_Capacity --
2072 ----------------------
2074 procedure Reserve_Capacity
2075 (Container : in out Vector;
2076 Capacity : Count_Type)
2078 N : constant Count_Type := Length (Container);
2080 begin
2081 if Capacity = 0 then
2082 if N = 0 then
2083 declare
2084 X : Elements_Access := Container.Elements;
2085 begin
2086 Container.Elements := null;
2087 Free (X);
2088 end;
2090 elsif N < Container.Elements.EA'Length then
2091 if Container.Busy > 0 then
2092 raise Program_Error with
2093 "attempt to tamper with elements (vector is busy)";
2094 end if;
2096 declare
2097 subtype Array_Index_Subtype is Index_Type'Base range
2098 Index_Type'First .. Container.Last;
2100 Src : Elements_Array renames
2101 Container.Elements.EA (Array_Index_Subtype);
2103 X : Elements_Access := Container.Elements;
2105 begin
2106 Container.Elements := new Elements_Type'(Container.Last, Src);
2107 Free (X);
2108 end;
2109 end if;
2111 return;
2112 end if;
2114 if Container.Elements = null then
2115 declare
2116 Last_As_Int : constant Int'Base :=
2117 Int (Index_Type'First) + Int (Capacity) - 1;
2119 begin
2120 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2121 raise Constraint_Error with "new length is out of range";
2122 end if;
2124 declare
2125 Last : constant Index_Type := Index_Type (Last_As_Int);
2127 begin
2128 Container.Elements := new Elements_Type (Last);
2129 end;
2130 end;
2132 return;
2133 end if;
2135 if Capacity <= N then
2136 if N < Container.Elements.EA'Length then
2137 if Container.Busy > 0 then
2138 raise Program_Error with
2139 "attempt to tamper with elements (vector is busy)";
2140 end if;
2142 declare
2143 subtype Array_Index_Subtype is Index_Type'Base range
2144 Index_Type'First .. Container.Last;
2146 Src : Elements_Array renames
2147 Container.Elements.EA (Array_Index_Subtype);
2149 X : Elements_Access := Container.Elements;
2151 begin
2152 Container.Elements := new Elements_Type'(Container.Last, Src);
2153 Free (X);
2154 end;
2155 end if;
2157 return;
2158 end if;
2160 if Capacity = Container.Elements.EA'Length then
2161 return;
2162 end if;
2164 if Container.Busy > 0 then
2165 raise Program_Error with
2166 "attempt to tamper with elements (vector is busy)";
2167 end if;
2169 declare
2170 Last_As_Int : constant Int'Base :=
2171 Int (Index_Type'First) + Int (Capacity) - 1;
2173 begin
2174 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2175 raise Constraint_Error with "new length is out of range";
2176 end if;
2178 declare
2179 Last : constant Index_Type := Index_Type (Last_As_Int);
2180 X : Elements_Access := Container.Elements;
2182 subtype Index_Subtype is Index_Type'Base range
2183 Index_Type'First .. Container.Last;
2185 begin
2186 Container.Elements := new Elements_Type (Last);
2188 declare
2189 Src : Elements_Array renames
2190 X.EA (Index_Subtype);
2192 Tgt : Elements_Array renames
2193 Container.Elements.EA (Index_Subtype);
2195 begin
2196 Tgt := Src;
2197 end;
2199 Free (X);
2200 end;
2201 end;
2202 end Reserve_Capacity;
2204 ----------------------
2205 -- Reverse_Elements --
2206 ----------------------
2208 procedure Reverse_Elements (Container : in out Vector) is
2209 begin
2210 if Container.Length <= 1 then
2211 return;
2212 end if;
2214 if Container.Lock > 0 then
2215 raise Program_Error with
2216 "attempt to tamper with cursors (vector is locked)";
2217 end if;
2219 declare
2220 I : Index_Type;
2221 J : Index_Type;
2222 E : Elements_Array renames Container.Elements.EA;
2224 begin
2225 I := Index_Type'First;
2226 J := Container.Last;
2227 while I < J loop
2228 declare
2229 EI : constant Element_Access := E (I);
2231 begin
2232 E (I) := E (J);
2233 E (J) := EI;
2234 end;
2236 I := I + 1;
2237 J := J - 1;
2238 end loop;
2239 end;
2240 end Reverse_Elements;
2242 ------------------
2243 -- Reverse_Find --
2244 ------------------
2246 function Reverse_Find
2247 (Container : Vector;
2248 Item : Element_Type;
2249 Position : Cursor := No_Element) return Cursor
2251 Last : Index_Type'Base;
2253 begin
2254 if Position.Container /= null
2255 and then Position.Container /= Container'Unchecked_Access
2256 then
2257 raise Program_Error with "Position cursor denotes wrong container";
2258 end if;
2260 if Position.Container = null
2261 or else Position.Index > Container.Last
2262 then
2263 Last := Container.Last;
2264 else
2265 Last := Position.Index;
2266 end if;
2268 for Indx in reverse Index_Type'First .. Last loop
2269 if Container.Elements.EA (Indx) /= null
2270 and then Container.Elements.EA (Indx).all = Item
2271 then
2272 return (Container'Unchecked_Access, Indx);
2273 end if;
2274 end loop;
2276 return No_Element;
2277 end Reverse_Find;
2279 ------------------------
2280 -- Reverse_Find_Index --
2281 ------------------------
2283 function Reverse_Find_Index
2284 (Container : Vector;
2285 Item : Element_Type;
2286 Index : Index_Type := Index_Type'Last) return Extended_Index
2288 Last : Index_Type'Base;
2290 begin
2291 if Index > Container.Last then
2292 Last := Container.Last;
2293 else
2294 Last := Index;
2295 end if;
2297 for Indx in reverse Index_Type'First .. Last loop
2298 if Container.Elements.EA (Indx) /= null
2299 and then Container.Elements.EA (Indx).all = Item
2300 then
2301 return Indx;
2302 end if;
2303 end loop;
2305 return No_Index;
2306 end Reverse_Find_Index;
2308 ---------------------
2309 -- Reverse_Iterate --
2310 ---------------------
2312 procedure Reverse_Iterate
2313 (Container : Vector;
2314 Process : not null access procedure (Position : Cursor))
2316 V : Vector renames Container'Unrestricted_Access.all;
2317 B : Natural renames V.Busy;
2319 begin
2320 B := B + 1;
2322 begin
2323 for Indx in reverse Index_Type'First .. Container.Last loop
2324 Process (Cursor'(Container'Unchecked_Access, Indx));
2325 end loop;
2326 exception
2327 when others =>
2328 B := B - 1;
2329 raise;
2330 end;
2332 B := B - 1;
2333 end Reverse_Iterate;
2335 ----------------
2336 -- Set_Length --
2337 ----------------
2339 procedure Set_Length
2340 (Container : in out Vector;
2341 Length : Count_Type)
2343 N : constant Count_Type := Indefinite_Vectors.Length (Container);
2345 begin
2346 if Length = N then
2347 return;
2348 end if;
2350 if Container.Busy > 0 then
2351 raise Program_Error with
2352 "attempt to tamper with elements (vector is busy)";
2353 end if;
2355 if Length < N then
2356 for Index in 1 .. N - Length loop
2357 declare
2358 J : constant Index_Type := Container.Last;
2359 X : Element_Access := Container.Elements.EA (J);
2361 begin
2362 Container.Elements.EA (J) := null;
2363 Container.Last := J - 1;
2364 Free (X);
2365 end;
2366 end loop;
2368 return;
2369 end if;
2371 if Length > Capacity (Container) then
2372 Reserve_Capacity (Container, Capacity => Length);
2373 end if;
2375 declare
2376 Last_As_Int : constant Int'Base :=
2377 Int (Index_Type'First) + Int (Length) - 1;
2379 begin
2380 Container.Last := Index_Type (Last_As_Int);
2381 end;
2382 end Set_Length;
2384 ----------
2385 -- Swap --
2386 ----------
2388 procedure Swap
2389 (Container : in out Vector;
2390 I, J : Index_Type)
2392 begin
2393 if I > Container.Last then
2394 raise Constraint_Error with "I index is out of range";
2395 end if;
2397 if J > Container.Last then
2398 raise Constraint_Error with "J index is out of range";
2399 end if;
2401 if I = J then
2402 return;
2403 end if;
2405 if Container.Lock > 0 then
2406 raise Program_Error with
2407 "attempt to tamper with cursors (vector is locked)";
2408 end if;
2410 declare
2411 EI : Element_Access renames Container.Elements.EA (I);
2412 EJ : Element_Access renames Container.Elements.EA (J);
2414 EI_Copy : constant Element_Access := EI;
2416 begin
2417 EI := EJ;
2418 EJ := EI_Copy;
2419 end;
2420 end Swap;
2422 procedure Swap
2423 (Container : in out Vector;
2424 I, J : Cursor)
2426 begin
2427 if I.Container = null then
2428 raise Constraint_Error with "I cursor has no element";
2429 end if;
2431 if J.Container = null then
2432 raise Constraint_Error with "J cursor has no element";
2433 end if;
2435 if I.Container /= Container'Unrestricted_Access then
2436 raise Program_Error with "I cursor denotes wrong container";
2437 end if;
2439 if J.Container /= Container'Unrestricted_Access then
2440 raise Program_Error with "J cursor denotes wrong container";
2441 end if;
2443 Swap (Container, I.Index, J.Index);
2444 end Swap;
2446 ---------------
2447 -- To_Cursor --
2448 ---------------
2450 function To_Cursor
2451 (Container : Vector;
2452 Index : Extended_Index) return Cursor
2454 begin
2455 if Index not in Index_Type'First .. Container.Last then
2456 return No_Element;
2457 end if;
2459 return Cursor'(Container'Unchecked_Access, Index);
2460 end To_Cursor;
2462 --------------
2463 -- To_Index --
2464 --------------
2466 function To_Index (Position : Cursor) return Extended_Index is
2467 begin
2468 if Position.Container = null then
2469 return No_Index;
2470 end if;
2472 if Position.Index <= Position.Container.Last then
2473 return Position.Index;
2474 end if;
2476 return No_Index;
2477 end To_Index;
2479 ---------------
2480 -- To_Vector --
2481 ---------------
2483 function To_Vector (Length : Count_Type) return Vector is
2484 begin
2485 if Length = 0 then
2486 return Empty_Vector;
2487 end if;
2489 declare
2490 First : constant Int := Int (Index_Type'First);
2491 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2492 Last : Index_Type;
2493 Elements : Elements_Access;
2495 begin
2496 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2497 raise Constraint_Error with "Length is out of range";
2498 end if;
2500 Last := Index_Type (Last_As_Int);
2501 Elements := new Elements_Type (Last);
2503 return (Controlled with Elements, Last, 0, 0);
2504 end;
2505 end To_Vector;
2507 function To_Vector
2508 (New_Item : Element_Type;
2509 Length : Count_Type) return Vector
2511 begin
2512 if Length = 0 then
2513 return Empty_Vector;
2514 end if;
2516 declare
2517 First : constant Int := Int (Index_Type'First);
2518 Last_As_Int : constant Int'Base := First + Int (Length) - 1;
2519 Last : Index_Type'Base;
2520 Elements : Elements_Access;
2522 begin
2523 if Last_As_Int > Index_Type'Pos (Index_Type'Last) then
2524 raise Constraint_Error with "Length is out of range";
2525 end if;
2527 Last := Index_Type (Last_As_Int);
2528 Elements := new Elements_Type (Last);
2530 Last := Index_Type'First;
2532 begin
2533 loop
2534 Elements.EA (Last) := new Element_Type'(New_Item);
2535 exit when Last = Elements.Last;
2536 Last := Last + 1;
2537 end loop;
2539 exception
2540 when others =>
2541 for J in Index_Type'First .. Last - 1 loop
2542 Free (Elements.EA (J));
2543 end loop;
2545 Free (Elements);
2546 raise;
2547 end;
2549 return (Controlled with Elements, Last, 0, 0);
2550 end;
2551 end To_Vector;
2553 --------------------
2554 -- Update_Element --
2555 --------------------
2557 procedure Update_Element
2558 (Container : in out Vector;
2559 Index : Index_Type;
2560 Process : not null access procedure (Element : in out Element_Type))
2562 B : Natural renames Container.Busy;
2563 L : Natural renames Container.Lock;
2565 begin
2566 if Index > Container.Last then
2567 raise Constraint_Error with "Index is out of range";
2568 end if;
2570 if Container.Elements.EA (Index) = null then
2571 raise Constraint_Error with "element is null";
2572 end if;
2574 B := B + 1;
2575 L := L + 1;
2577 begin
2578 Process (Container.Elements.EA (Index).all);
2579 exception
2580 when others =>
2581 L := L - 1;
2582 B := B - 1;
2583 raise;
2584 end;
2586 L := L - 1;
2587 B := B - 1;
2588 end Update_Element;
2590 procedure Update_Element
2591 (Container : in out Vector;
2592 Position : Cursor;
2593 Process : not null access procedure (Element : in out Element_Type))
2595 begin
2596 if Position.Container = null then
2597 raise Constraint_Error with "Position cursor has no element";
2598 end if;
2600 if Position.Container /= Container'Unrestricted_Access then
2601 raise Program_Error with "Position cursor denotes wrong container";
2602 end if;
2604 Update_Element (Container, Position.Index, Process);
2605 end Update_Element;
2607 -----------
2608 -- Write --
2609 -----------
2611 procedure Write
2612 (Stream : not null access Root_Stream_Type'Class;
2613 Container : Vector)
2615 N : constant Count_Type := Length (Container);
2617 begin
2618 Count_Type'Base'Write (Stream, N);
2620 if N = 0 then
2621 return;
2622 end if;
2624 declare
2625 E : Elements_Array renames Container.Elements.EA;
2627 begin
2628 for Indx in Index_Type'First .. Container.Last loop
2629 if E (Indx) = null then
2630 Boolean'Write (Stream, False);
2631 else
2632 Boolean'Write (Stream, True);
2633 Element_Type'Output (Stream, E (Indx).all);
2634 end if;
2635 end loop;
2636 end;
2637 end Write;
2639 procedure Write
2640 (Stream : not null access Root_Stream_Type'Class;
2641 Position : Cursor)
2643 begin
2644 raise Program_Error with "attempt to stream vector cursor";
2645 end Write;
2647 end Ada.Containers.Indefinite_Vectors;