* g++.dg/cpp0x/constexpr-53094-2.C: Ignore non-standard ABI
[official-gcc.git] / gcc / ada / a-ciormu.adb
blob4fce4754c7853172a8c5cd1261a8ece9323982a3
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_MULTISETS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2012, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada.Unchecked_Deallocation;
32 with Ada.Containers.Red_Black_Trees.Generic_Operations;
33 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
35 with Ada.Containers.Red_Black_Trees.Generic_Keys;
36 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
38 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
39 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
41 with System; use type System.Address;
43 package body Ada.Containers.Indefinite_Ordered_Multisets is
45 type Iterator is new Limited_Controlled and
46 Set_Iterator_Interfaces.Reversible_Iterator with
47 record
48 Container : Set_Access;
49 Node : Node_Access;
50 end record;
52 overriding procedure Finalize (Object : in out Iterator);
54 overriding function First (Object : Iterator) return Cursor;
55 overriding function Last (Object : Iterator) return Cursor;
57 overriding function Next
58 (Object : Iterator;
59 Position : Cursor) return Cursor;
61 overriding function Previous
62 (Object : Iterator;
63 Position : Cursor) return Cursor;
65 -----------------------------
66 -- Node Access Subprograms --
67 -----------------------------
69 -- These subprograms provide a functional interface to access fields
70 -- of a node, and a procedural interface for modifying these values.
72 function Color (Node : Node_Access) return Color_Type;
73 pragma Inline (Color);
75 function Left (Node : Node_Access) return Node_Access;
76 pragma Inline (Left);
78 function Parent (Node : Node_Access) return Node_Access;
79 pragma Inline (Parent);
81 function Right (Node : Node_Access) return Node_Access;
82 pragma Inline (Right);
84 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
85 pragma Inline (Set_Parent);
87 procedure Set_Left (Node : Node_Access; Left : Node_Access);
88 pragma Inline (Set_Left);
90 procedure Set_Right (Node : Node_Access; Right : Node_Access);
91 pragma Inline (Set_Right);
93 procedure Set_Color (Node : Node_Access; Color : Color_Type);
94 pragma Inline (Set_Color);
96 -----------------------
97 -- Local Subprograms --
98 -----------------------
100 function Copy_Node (Source : Node_Access) return Node_Access;
101 pragma Inline (Copy_Node);
103 procedure Free (X : in out Node_Access);
105 procedure Insert_Sans_Hint
106 (Tree : in out Tree_Type;
107 New_Item : Element_Type;
108 Node : out Node_Access);
110 procedure Insert_With_Hint
111 (Dst_Tree : in out Tree_Type;
112 Dst_Hint : Node_Access;
113 Src_Node : Node_Access;
114 Dst_Node : out Node_Access);
116 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
117 pragma Inline (Is_Equal_Node_Node);
119 function Is_Greater_Element_Node
120 (Left : Element_Type;
121 Right : Node_Access) return Boolean;
122 pragma Inline (Is_Greater_Element_Node);
124 function Is_Less_Element_Node
125 (Left : Element_Type;
126 Right : Node_Access) return Boolean;
127 pragma Inline (Is_Less_Element_Node);
129 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
130 pragma Inline (Is_Less_Node_Node);
132 procedure Replace_Element
133 (Tree : in out Tree_Type;
134 Node : Node_Access;
135 Item : Element_Type);
137 --------------------------
138 -- Local Instantiations --
139 --------------------------
141 package Tree_Operations is
142 new Red_Black_Trees.Generic_Operations (Tree_Types);
144 procedure Delete_Tree is
145 new Tree_Operations.Generic_Delete_Tree (Free);
147 function Copy_Tree is
148 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
150 use Tree_Operations;
152 procedure Free_Element is
153 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
155 function Is_Equal is
156 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
158 package Set_Ops is
159 new Generic_Set_Operations
160 (Tree_Operations => Tree_Operations,
161 Insert_With_Hint => Insert_With_Hint,
162 Copy_Tree => Copy_Tree,
163 Delete_Tree => Delete_Tree,
164 Is_Less => Is_Less_Node_Node,
165 Free => Free);
167 package Element_Keys is
168 new Red_Black_Trees.Generic_Keys
169 (Tree_Operations => Tree_Operations,
170 Key_Type => Element_Type,
171 Is_Less_Key_Node => Is_Less_Element_Node,
172 Is_Greater_Key_Node => Is_Greater_Element_Node);
174 ---------
175 -- "<" --
176 ---------
178 function "<" (Left, Right : Cursor) return Boolean is
179 begin
180 if Left.Node = null then
181 raise Constraint_Error with "Left cursor equals No_Element";
182 end if;
184 if Right.Node = null then
185 raise Constraint_Error with "Right cursor equals No_Element";
186 end if;
188 if Left.Node.Element = null then
189 raise Program_Error with "Left cursor is bad";
190 end if;
192 if Right.Node.Element = null then
193 raise Program_Error with "Right cursor is bad";
194 end if;
196 pragma Assert (Vet (Left.Container.Tree, Left.Node),
197 "bad Left cursor in ""<""");
199 pragma Assert (Vet (Right.Container.Tree, Right.Node),
200 "bad Right cursor in ""<""");
202 return Left.Node.Element.all < Right.Node.Element.all;
203 end "<";
205 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
206 begin
207 if Left.Node = null then
208 raise Constraint_Error with "Left cursor equals No_Element";
209 end if;
211 if Left.Node.Element = null then
212 raise Program_Error with "Left cursor is bad";
213 end if;
215 pragma Assert (Vet (Left.Container.Tree, Left.Node),
216 "bad Left cursor in ""<""");
218 return Left.Node.Element.all < Right;
219 end "<";
221 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
222 begin
223 if Right.Node = null then
224 raise Constraint_Error with "Right cursor equals No_Element";
225 end if;
227 if Right.Node.Element = null then
228 raise Program_Error with "Right cursor is bad";
229 end if;
231 pragma Assert (Vet (Right.Container.Tree, Right.Node),
232 "bad Right cursor in ""<""");
234 return Left < Right.Node.Element.all;
235 end "<";
237 ---------
238 -- "=" --
239 ---------
241 function "=" (Left, Right : Set) return Boolean is
242 begin
243 return Is_Equal (Left.Tree, Right.Tree);
244 end "=";
246 ---------
247 -- ">" --
248 ---------
250 function ">" (Left, Right : Cursor) return Boolean is
251 begin
252 if Left.Node = null then
253 raise Constraint_Error with "Left cursor equals No_Element";
254 end if;
256 if Right.Node = null then
257 raise Constraint_Error with "Right cursor equals No_Element";
258 end if;
260 if Left.Node.Element = null then
261 raise Program_Error with "Left cursor is bad";
262 end if;
264 if Right.Node.Element = null then
265 raise Program_Error with "Right cursor is bad";
266 end if;
268 pragma Assert (Vet (Left.Container.Tree, Left.Node),
269 "bad Left cursor in "">""");
271 pragma Assert (Vet (Right.Container.Tree, Right.Node),
272 "bad Right cursor in "">""");
274 -- L > R same as R < L
276 return Right.Node.Element.all < Left.Node.Element.all;
277 end ">";
279 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
280 begin
281 if Left.Node = null then
282 raise Constraint_Error with "Left cursor equals No_Element";
283 end if;
285 if Left.Node.Element = null then
286 raise Program_Error with "Left cursor is bad";
287 end if;
289 pragma Assert (Vet (Left.Container.Tree, Left.Node),
290 "bad Left cursor in "">""");
292 return Right < Left.Node.Element.all;
293 end ">";
295 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
296 begin
297 if Right.Node = null then
298 raise Constraint_Error with "Right cursor equals No_Element";
299 end if;
301 if Right.Node.Element = null then
302 raise Program_Error with "Right cursor is bad";
303 end if;
305 pragma Assert (Vet (Right.Container.Tree, Right.Node),
306 "bad Right cursor in "">""");
308 return Right.Node.Element.all < Left;
309 end ">";
311 ------------
312 -- Adjust --
313 ------------
315 procedure Adjust is
316 new Tree_Operations.Generic_Adjust (Copy_Tree);
318 procedure Adjust (Container : in out Set) is
319 begin
320 Adjust (Container.Tree);
321 end Adjust;
323 ------------
324 -- Assign --
325 ------------
327 procedure Assign (Target : in out Set; Source : Set) is
328 begin
329 if Target'Address = Source'Address then
330 return;
331 end if;
333 Target.Clear;
334 Target.Union (Source);
335 end Assign;
337 -------------
338 -- Ceiling --
339 -------------
341 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
342 Node : constant Node_Access :=
343 Element_Keys.Ceiling (Container.Tree, Item);
345 begin
346 if Node = null then
347 return No_Element;
348 end if;
350 return Cursor'(Container'Unrestricted_Access, Node);
351 end Ceiling;
353 -----------
354 -- Clear --
355 -----------
357 procedure Clear is
358 new Tree_Operations.Generic_Clear (Delete_Tree);
360 procedure Clear (Container : in out Set) is
361 begin
362 Clear (Container.Tree);
363 end Clear;
365 -----------
366 -- Color --
367 -----------
369 function Color (Node : Node_Access) return Color_Type is
370 begin
371 return Node.Color;
372 end Color;
374 --------------
375 -- Contains --
376 --------------
378 function Contains (Container : Set; Item : Element_Type) return Boolean is
379 begin
380 return Find (Container, Item) /= No_Element;
381 end Contains;
383 ----------
384 -- Copy --
385 ----------
387 function Copy (Source : Set) return Set is
388 begin
389 return Target : Set do
390 Target.Assign (Source);
391 end return;
392 end Copy;
394 ---------------
395 -- Copy_Node --
396 ---------------
398 function Copy_Node (Source : Node_Access) return Node_Access is
399 X : Element_Access := new Element_Type'(Source.Element.all);
401 begin
402 return new Node_Type'(Parent => null,
403 Left => null,
404 Right => null,
405 Color => Source.Color,
406 Element => X);
408 exception
409 when others =>
410 Free_Element (X);
411 raise;
412 end Copy_Node;
414 ------------
415 -- Delete --
416 ------------
418 procedure Delete (Container : in out Set; Item : Element_Type) is
419 Tree : Tree_Type renames Container.Tree;
420 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
421 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
422 X : Node_Access;
424 begin
425 if Node = Done then
426 raise Constraint_Error with "attempt to delete element not in set";
427 end if;
429 loop
430 X := Node;
431 Node := Tree_Operations.Next (Node);
432 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
433 Free (X);
435 exit when Node = Done;
436 end loop;
437 end Delete;
439 procedure Delete (Container : in out Set; Position : in out Cursor) is
440 begin
441 if Position.Node = null then
442 raise Constraint_Error with "Position cursor equals No_Element";
443 end if;
445 if Position.Node.Element = null then
446 raise Program_Error with "Position cursor is bad";
447 end if;
449 if Position.Container /= Container'Unrestricted_Access then
450 raise Program_Error with "Position cursor designates wrong set";
451 end if;
453 pragma Assert (Vet (Container.Tree, Position.Node),
454 "bad cursor in Delete");
456 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
457 Free (Position.Node);
459 Position.Container := null;
460 end Delete;
462 ------------------
463 -- Delete_First --
464 ------------------
466 procedure Delete_First (Container : in out Set) is
467 Tree : Tree_Type renames Container.Tree;
468 X : Node_Access := Tree.First;
470 begin
471 if X = null then
472 return;
473 end if;
475 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
476 Free (X);
477 end Delete_First;
479 -----------------
480 -- Delete_Last --
481 -----------------
483 procedure Delete_Last (Container : in out Set) is
484 Tree : Tree_Type renames Container.Tree;
485 X : Node_Access := Tree.Last;
487 begin
488 if X = null then
489 return;
490 end if;
492 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
493 Free (X);
494 end Delete_Last;
496 ----------------
497 -- Difference --
498 ----------------
500 procedure Difference (Target : in out Set; Source : Set) is
501 begin
502 Set_Ops.Difference (Target.Tree, Source.Tree);
503 end Difference;
505 function Difference (Left, Right : Set) return Set is
506 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
507 begin
508 return Set'(Controlled with Tree);
509 end Difference;
511 -------------
512 -- Element --
513 -------------
515 function Element (Position : Cursor) return Element_Type is
516 begin
517 if Position.Node = null then
518 raise Constraint_Error with "Position cursor equals No_Element";
519 end if;
521 if Position.Node.Element = null then
522 raise Program_Error with "Position cursor is bad";
523 end if;
525 pragma Assert (Vet (Position.Container.Tree, Position.Node),
526 "bad cursor in Element");
528 return Position.Node.Element.all;
529 end Element;
531 -------------------------
532 -- Equivalent_Elements --
533 -------------------------
535 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
536 begin
537 if Left < Right
538 or else Right < Left
539 then
540 return False;
541 else
542 return True;
543 end if;
544 end Equivalent_Elements;
546 ---------------------
547 -- Equivalent_Sets --
548 ---------------------
550 function Equivalent_Sets (Left, Right : Set) return Boolean is
552 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
553 pragma Inline (Is_Equivalent_Node_Node);
555 function Is_Equivalent is
556 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
558 -----------------------------
559 -- Is_Equivalent_Node_Node --
560 -----------------------------
562 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
563 begin
564 if L.Element.all < R.Element.all then
565 return False;
566 elsif R.Element.all < L.Element.all then
567 return False;
568 else
569 return True;
570 end if;
571 end Is_Equivalent_Node_Node;
573 -- Start of processing for Equivalent_Sets
575 begin
576 return Is_Equivalent (Left.Tree, Right.Tree);
577 end Equivalent_Sets;
579 -------------
580 -- Exclude --
581 -------------
583 procedure Exclude (Container : in out Set; Item : Element_Type) is
584 Tree : Tree_Type renames Container.Tree;
585 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
586 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
587 X : Node_Access;
589 begin
590 while Node /= Done loop
591 X := Node;
592 Node := Tree_Operations.Next (Node);
593 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
594 Free (X);
595 end loop;
596 end Exclude;
598 ----------
599 -- Find --
600 ----------
602 function Find (Container : Set; Item : Element_Type) return Cursor is
603 Node : constant Node_Access := Element_Keys.Find (Container.Tree, Item);
605 begin
606 if Node = null then
607 return No_Element;
608 end if;
610 return Cursor'(Container'Unrestricted_Access, Node);
611 end Find;
613 --------------
614 -- Finalize --
615 --------------
617 procedure Finalize (Object : in out Iterator) is
618 B : Natural renames Object.Container.Tree.Busy;
619 pragma Assert (B > 0);
620 begin
621 B := B - 1;
622 end Finalize;
624 -----------
625 -- First --
626 -----------
628 function First (Container : Set) return Cursor is
629 begin
630 if Container.Tree.First = null then
631 return No_Element;
632 end if;
634 return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
635 end First;
637 function First (Object : Iterator) return Cursor is
638 begin
639 -- The value of the iterator object's Node component influences the
640 -- behavior of the First (and Last) selector function.
642 -- When the Node component is null, this means the iterator object was
643 -- constructed without a start expression, in which case the (forward)
644 -- iteration starts from the (logical) beginning of the entire sequence
645 -- of items (corresponding to Container.First, for a forward iterator).
647 -- Otherwise, this is iteration over a partial sequence of items. When
648 -- the Node component is non-null, the iterator object was constructed
649 -- with a start expression, that specifies the position from which the
650 -- (forward) partial iteration begins.
652 if Object.Node = null then
653 return Object.Container.First;
654 else
655 return Cursor'(Object.Container, Object.Node);
656 end if;
657 end First;
659 -------------------
660 -- First_Element --
661 -------------------
663 function First_Element (Container : Set) return Element_Type is
664 begin
665 if Container.Tree.First = null then
666 raise Constraint_Error with "set is empty";
667 end if;
669 pragma Assert (Container.Tree.First.Element /= null);
670 return Container.Tree.First.Element.all;
671 end First_Element;
673 -----------
674 -- Floor --
675 -----------
677 function Floor (Container : Set; Item : Element_Type) return Cursor is
678 Node : constant Node_Access := Element_Keys.Floor (Container.Tree, Item);
680 begin
681 if Node = null then
682 return No_Element;
683 end if;
685 return Cursor'(Container'Unrestricted_Access, Node);
686 end Floor;
688 ----------
689 -- Free --
690 ----------
692 procedure Free (X : in out Node_Access) is
693 procedure Deallocate is
694 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
696 begin
697 if X = null then
698 return;
699 end if;
701 X.Parent := X;
702 X.Left := X;
703 X.Right := X;
705 begin
706 Free_Element (X.Element);
707 exception
708 when others =>
709 X.Element := null;
710 Deallocate (X);
711 raise;
712 end;
714 Deallocate (X);
715 end Free;
717 ------------------
718 -- Generic_Keys --
719 ------------------
721 package body Generic_Keys is
723 -----------------------
724 -- Local Subprograms --
725 -----------------------
727 function Is_Less_Key_Node
728 (Left : Key_Type;
729 Right : Node_Access) return Boolean;
730 pragma Inline (Is_Less_Key_Node);
732 function Is_Greater_Key_Node
733 (Left : Key_Type;
734 Right : Node_Access) return Boolean;
735 pragma Inline (Is_Greater_Key_Node);
737 --------------------------
738 -- Local Instantiations --
739 --------------------------
741 package Key_Keys is
742 new Red_Black_Trees.Generic_Keys
743 (Tree_Operations => Tree_Operations,
744 Key_Type => Key_Type,
745 Is_Less_Key_Node => Is_Less_Key_Node,
746 Is_Greater_Key_Node => Is_Greater_Key_Node);
748 -------------
749 -- Ceiling --
750 -------------
752 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
753 Node : constant Node_Access := Key_Keys.Ceiling (Container.Tree, Key);
755 begin
756 if Node = null then
757 return No_Element;
758 end if;
760 return Cursor'(Container'Unrestricted_Access, Node);
761 end Ceiling;
763 --------------
764 -- Contains --
765 --------------
767 function Contains (Container : Set; Key : Key_Type) return Boolean is
768 begin
769 return Find (Container, Key) /= No_Element;
770 end Contains;
772 ------------
773 -- Delete --
774 ------------
776 procedure Delete (Container : in out Set; Key : Key_Type) is
777 Tree : Tree_Type renames Container.Tree;
778 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
779 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
780 X : Node_Access;
782 begin
783 if Node = Done then
784 raise Constraint_Error with "attempt to delete key not in set";
785 end if;
787 loop
788 X := Node;
789 Node := Tree_Operations.Next (Node);
790 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
791 Free (X);
793 exit when Node = Done;
794 end loop;
795 end Delete;
797 -------------
798 -- Element --
799 -------------
801 function Element (Container : Set; Key : Key_Type) return Element_Type is
802 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
804 begin
805 if Node = null then
806 raise Constraint_Error with "key not in set";
807 end if;
809 return Node.Element.all;
810 end Element;
812 ---------------------
813 -- Equivalent_Keys --
814 ---------------------
816 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
817 begin
818 if Left < Right
819 or else Right < Left
820 then
821 return False;
822 else
823 return True;
824 end if;
825 end Equivalent_Keys;
827 -------------
828 -- Exclude --
829 -------------
831 procedure Exclude (Container : in out Set; Key : Key_Type) is
832 Tree : Tree_Type renames Container.Tree;
833 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
834 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
835 X : Node_Access;
837 begin
838 while Node /= Done loop
839 X := Node;
840 Node := Tree_Operations.Next (Node);
841 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
842 Free (X);
843 end loop;
844 end Exclude;
846 ----------
847 -- Find --
848 ----------
850 function Find (Container : Set; Key : Key_Type) return Cursor is
851 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
853 begin
854 if Node = null then
855 return No_Element;
856 end if;
858 return Cursor'(Container'Unrestricted_Access, Node);
859 end Find;
861 -----------
862 -- Floor --
863 -----------
865 function Floor (Container : Set; Key : Key_Type) return Cursor is
866 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
868 begin
869 if Node = null then
870 return No_Element;
871 end if;
873 return Cursor'(Container'Unrestricted_Access, Node);
874 end Floor;
876 -------------------------
877 -- Is_Greater_Key_Node --
878 -------------------------
880 function Is_Greater_Key_Node
881 (Left : Key_Type;
882 Right : Node_Access) return Boolean
884 begin
885 return Key (Right.Element.all) < Left;
886 end Is_Greater_Key_Node;
888 ----------------------
889 -- Is_Less_Key_Node --
890 ----------------------
892 function Is_Less_Key_Node
893 (Left : Key_Type;
894 Right : Node_Access) return Boolean
896 begin
897 return Left < Key (Right.Element.all);
898 end Is_Less_Key_Node;
900 -------------
901 -- Iterate --
902 -------------
904 procedure Iterate
905 (Container : Set;
906 Key : Key_Type;
907 Process : not null access procedure (Position : Cursor))
909 procedure Process_Node (Node : Node_Access);
910 pragma Inline (Process_Node);
912 procedure Local_Iterate is
913 new Key_Keys.Generic_Iteration (Process_Node);
915 ------------------
916 -- Process_Node --
917 ------------------
919 procedure Process_Node (Node : Node_Access) is
920 begin
921 Process (Cursor'(Container'Unrestricted_Access, Node));
922 end Process_Node;
924 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
925 B : Natural renames T.Busy;
927 -- Start of processing for Iterate
929 begin
930 B := B + 1;
932 begin
933 Local_Iterate (T, Key);
934 exception
935 when others =>
936 B := B - 1;
937 raise;
938 end;
940 B := B - 1;
941 end Iterate;
943 ---------
944 -- Key --
945 ---------
947 function Key (Position : Cursor) return Key_Type is
948 begin
949 if Position.Node = null then
950 raise Constraint_Error with
951 "Position cursor equals No_Element";
952 end if;
954 if Position.Node.Element = null then
955 raise Program_Error with
956 "Position cursor is bad";
957 end if;
959 pragma Assert (Vet (Position.Container.Tree, Position.Node),
960 "bad cursor in Key");
962 return Key (Position.Node.Element.all);
963 end Key;
965 ---------------------
966 -- Reverse_Iterate --
967 ---------------------
969 procedure Reverse_Iterate
970 (Container : Set;
971 Key : Key_Type;
972 Process : not null access procedure (Position : Cursor))
974 procedure Process_Node (Node : Node_Access);
975 pragma Inline (Process_Node);
977 -------------
978 -- Iterate --
979 -------------
981 procedure Local_Reverse_Iterate is
982 new Key_Keys.Generic_Reverse_Iteration (Process_Node);
984 ------------------
985 -- Process_Node --
986 ------------------
988 procedure Process_Node (Node : Node_Access) is
989 begin
990 Process (Cursor'(Container'Unrestricted_Access, Node));
991 end Process_Node;
993 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
994 B : Natural renames T.Busy;
996 -- Start of processing for Reverse_Iterate
998 begin
999 B := B + 1;
1001 begin
1002 Local_Reverse_Iterate (T, Key);
1003 exception
1004 when others =>
1005 B := B - 1;
1006 raise;
1007 end;
1009 B := B - 1;
1010 end Reverse_Iterate;
1012 --------------------
1013 -- Update_Element --
1014 --------------------
1016 procedure Update_Element
1017 (Container : in out Set;
1018 Position : Cursor;
1019 Process : not null access procedure (Element : in out Element_Type))
1021 Tree : Tree_Type renames Container.Tree;
1022 Node : constant Node_Access := Position.Node;
1024 begin
1025 if Node = null then
1026 raise Constraint_Error with "Position cursor equals No_Element";
1027 end if;
1029 if Node.Element = null then
1030 raise Program_Error with "Position cursor is bad";
1031 end if;
1033 if Position.Container /= Container'Unrestricted_Access then
1034 raise Program_Error with "Position cursor designates wrong set";
1035 end if;
1037 pragma Assert (Vet (Tree, Node),
1038 "bad cursor in Update_Element");
1040 declare
1041 E : Element_Type renames Node.Element.all;
1042 K : constant Key_Type := Key (E);
1044 B : Natural renames Tree.Busy;
1045 L : Natural renames Tree.Lock;
1047 begin
1048 B := B + 1;
1049 L := L + 1;
1051 begin
1052 Process (E);
1053 exception
1054 when others =>
1055 L := L - 1;
1056 B := B - 1;
1057 raise;
1058 end;
1060 L := L - 1;
1061 B := B - 1;
1063 if Equivalent_Keys (Left => K, Right => Key (E)) then
1064 return;
1065 end if;
1066 end;
1068 -- Delete_Node checks busy-bit
1070 Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
1072 Insert_New_Item : declare
1073 function New_Node return Node_Access;
1074 pragma Inline (New_Node);
1076 procedure Insert_Post is
1077 new Element_Keys.Generic_Insert_Post (New_Node);
1079 procedure Unconditional_Insert is
1080 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1082 --------------
1083 -- New_Node --
1084 --------------
1086 function New_Node return Node_Access is
1087 begin
1088 Node.Color := Red_Black_Trees.Red;
1089 Node.Parent := null;
1090 Node.Left := null;
1091 Node.Right := null;
1093 return Node;
1094 end New_Node;
1096 Result : Node_Access;
1098 -- Start of processing for Insert_New_Item
1100 begin
1101 Unconditional_Insert
1102 (Tree => Tree,
1103 Key => Node.Element.all,
1104 Node => Result);
1106 pragma Assert (Result = Node);
1107 end Insert_New_Item;
1108 end Update_Element;
1110 end Generic_Keys;
1112 -----------------
1113 -- Has_Element --
1114 -----------------
1116 function Has_Element (Position : Cursor) return Boolean is
1117 begin
1118 return Position /= No_Element;
1119 end Has_Element;
1121 ------------
1122 -- Insert --
1123 ------------
1125 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1126 Position : Cursor;
1127 pragma Unreferenced (Position);
1128 begin
1129 Insert (Container, New_Item, Position);
1130 end Insert;
1132 procedure Insert
1133 (Container : in out Set;
1134 New_Item : Element_Type;
1135 Position : out Cursor)
1137 begin
1138 Insert_Sans_Hint (Container.Tree, New_Item, Position.Node);
1139 Position.Container := Container'Unrestricted_Access;
1140 end Insert;
1142 ----------------------
1143 -- Insert_Sans_Hint --
1144 ----------------------
1146 procedure Insert_Sans_Hint
1147 (Tree : in out Tree_Type;
1148 New_Item : Element_Type;
1149 Node : out Node_Access)
1151 function New_Node return Node_Access;
1152 pragma Inline (New_Node);
1154 procedure Insert_Post is
1155 new Element_Keys.Generic_Insert_Post (New_Node);
1157 procedure Unconditional_Insert is
1158 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1160 --------------
1161 -- New_Node --
1162 --------------
1164 function New_Node return Node_Access is
1165 -- The element allocator may need an accessibility check in the case
1166 -- the actual type is class-wide or has access discriminants (see
1167 -- RM 4.8(10.1) and AI12-0035).
1169 pragma Unsuppress (Accessibility_Check);
1171 Element : Element_Access := new Element_Type'(New_Item);
1173 begin
1174 return new Node_Type'(Parent => null,
1175 Left => null,
1176 Right => null,
1177 Color => Red_Black_Trees.Red,
1178 Element => Element);
1180 exception
1181 when others =>
1182 Free_Element (Element);
1183 raise;
1184 end New_Node;
1186 -- Start of processing for Insert_Sans_Hint
1188 begin
1189 Unconditional_Insert (Tree, New_Item, Node);
1190 end Insert_Sans_Hint;
1192 ----------------------
1193 -- Insert_With_Hint --
1194 ----------------------
1196 procedure Insert_With_Hint
1197 (Dst_Tree : in out Tree_Type;
1198 Dst_Hint : Node_Access;
1199 Src_Node : Node_Access;
1200 Dst_Node : out Node_Access)
1202 function New_Node return Node_Access;
1203 pragma Inline (New_Node);
1205 procedure Insert_Post is
1206 new Element_Keys.Generic_Insert_Post (New_Node);
1208 procedure Insert_Sans_Hint is
1209 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1211 procedure Local_Insert_With_Hint is
1212 new Element_Keys.Generic_Unconditional_Insert_With_Hint
1213 (Insert_Post,
1214 Insert_Sans_Hint);
1216 --------------
1217 -- New_Node --
1218 --------------
1220 function New_Node return Node_Access is
1221 X : Element_Access := new Element_Type'(Src_Node.Element.all);
1223 begin
1224 return new Node_Type'(Parent => null,
1225 Left => null,
1226 Right => null,
1227 Color => Red,
1228 Element => X);
1230 exception
1231 when others =>
1232 Free_Element (X);
1233 raise;
1234 end New_Node;
1236 -- Start of processing for Insert_With_Hint
1238 begin
1239 Local_Insert_With_Hint
1240 (Dst_Tree,
1241 Dst_Hint,
1242 Src_Node.Element.all,
1243 Dst_Node);
1244 end Insert_With_Hint;
1246 ------------------
1247 -- Intersection --
1248 ------------------
1250 procedure Intersection (Target : in out Set; Source : Set) is
1251 begin
1252 Set_Ops.Intersection (Target.Tree, Source.Tree);
1253 end Intersection;
1255 function Intersection (Left, Right : Set) return Set is
1256 Tree : constant Tree_Type :=
1257 Set_Ops.Intersection (Left.Tree, Right.Tree);
1258 begin
1259 return Set'(Controlled with Tree);
1260 end Intersection;
1262 --------------
1263 -- Is_Empty --
1264 --------------
1266 function Is_Empty (Container : Set) return Boolean is
1267 begin
1268 return Container.Tree.Length = 0;
1269 end Is_Empty;
1271 ------------------------
1272 -- Is_Equal_Node_Node --
1273 ------------------------
1275 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1276 begin
1277 return L.Element.all = R.Element.all;
1278 end Is_Equal_Node_Node;
1280 -----------------------------
1281 -- Is_Greater_Element_Node --
1282 -----------------------------
1284 function Is_Greater_Element_Node
1285 (Left : Element_Type;
1286 Right : Node_Access) return Boolean
1288 begin
1289 -- e > node same as node < e
1291 return Right.Element.all < Left;
1292 end Is_Greater_Element_Node;
1294 --------------------------
1295 -- Is_Less_Element_Node --
1296 --------------------------
1298 function Is_Less_Element_Node
1299 (Left : Element_Type;
1300 Right : Node_Access) return Boolean
1302 begin
1303 return Left < Right.Element.all;
1304 end Is_Less_Element_Node;
1306 -----------------------
1307 -- Is_Less_Node_Node --
1308 -----------------------
1310 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1311 begin
1312 return L.Element.all < R.Element.all;
1313 end Is_Less_Node_Node;
1315 ---------------
1316 -- Is_Subset --
1317 ---------------
1319 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1320 begin
1321 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1322 end Is_Subset;
1324 -------------
1325 -- Iterate --
1326 -------------
1328 procedure Iterate
1329 (Container : Set;
1330 Item : Element_Type;
1331 Process : not null access procedure (Position : Cursor))
1333 procedure Process_Node (Node : Node_Access);
1334 pragma Inline (Process_Node);
1336 procedure Local_Iterate is
1337 new Element_Keys.Generic_Iteration (Process_Node);
1339 ------------------
1340 -- Process_Node --
1341 ------------------
1343 procedure Process_Node (Node : Node_Access) is
1344 begin
1345 Process (Cursor'(Container'Unrestricted_Access, Node));
1346 end Process_Node;
1348 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1349 B : Natural renames T.Busy;
1351 -- Start of processing for Iterate
1353 begin
1354 B := B + 1;
1356 begin
1357 Local_Iterate (T, Item);
1358 exception
1359 when others =>
1360 B := B - 1;
1361 raise;
1362 end;
1364 B := B - 1;
1365 end Iterate;
1367 procedure Iterate
1368 (Container : Set;
1369 Process : not null access procedure (Position : Cursor))
1371 procedure Process_Node (Node : Node_Access);
1372 pragma Inline (Process_Node);
1374 procedure Local_Iterate is
1375 new Tree_Operations.Generic_Iteration (Process_Node);
1377 ------------------
1378 -- Process_Node --
1379 ------------------
1381 procedure Process_Node (Node : Node_Access) is
1382 begin
1383 Process (Cursor'(Container'Unrestricted_Access, Node));
1384 end Process_Node;
1386 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1387 B : Natural renames T.Busy;
1389 -- Start of processing for Iterate
1391 begin
1392 B := B + 1;
1394 begin
1395 Local_Iterate (T);
1396 exception
1397 when others =>
1398 B := B - 1;
1399 raise;
1400 end;
1402 B := B - 1;
1403 end Iterate;
1405 function Iterate (Container : Set)
1406 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1408 S : constant Set_Access := Container'Unrestricted_Access;
1409 B : Natural renames S.Tree.Busy;
1411 begin
1412 -- The value of the Node component influences the behavior of the First
1413 -- and Last selector functions of the iterator object. When the Node
1414 -- component is null (as is the case here), this means the iterator
1415 -- object was constructed without a start expression. This is a complete
1416 -- iterator, meaning that the iteration starts from the (logical)
1417 -- beginning of the sequence of items.
1419 -- Note: For a forward iterator, Container.First is the beginning, and
1420 -- for a reverse iterator, Container.Last is the beginning.
1422 return It : constant Iterator := (Limited_Controlled with S, null) do
1423 B := B + 1;
1424 end return;
1425 end Iterate;
1427 function Iterate (Container : Set; Start : Cursor)
1428 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1430 S : constant Set_Access := Container'Unrestricted_Access;
1431 B : Natural renames S.Tree.Busy;
1433 begin
1434 -- It was formerly the case that when Start = No_Element, the partial
1435 -- iterator was defined to behave the same as for a complete iterator,
1436 -- and iterate over the entire sequence of items. However, those
1437 -- semantics were unintuitive and arguably error-prone (it is too easy
1438 -- to accidentally create an endless loop), and so they were changed,
1439 -- per the ARG meeting in Denver on 2011/11. However, there was no
1440 -- consensus about what positive meaning this corner case should have,
1441 -- and so it was decided to simply raise an exception. This does imply,
1442 -- however, that it is not possible to use a partial iterator to specify
1443 -- an empty sequence of items.
1445 if Start = No_Element then
1446 raise Constraint_Error with
1447 "Start position for iterator equals No_Element";
1448 end if;
1450 if Start.Container /= Container'Unrestricted_Access then
1451 raise Program_Error with
1452 "Start cursor of Iterate designates wrong set";
1453 end if;
1455 pragma Assert (Vet (Container.Tree, Start.Node),
1456 "Start cursor of Iterate is bad");
1458 -- The value of the Node component influences the behavior of the First
1459 -- and Last selector functions of the iterator object. When the Node
1460 -- component is non-null (as is the case here), it means that this is a
1461 -- partial iteration, over a subset of the complete sequence of
1462 -- items. The iterator object was constructed with a start expression,
1463 -- indicating the position from which the iteration begins. Note that
1464 -- the start position has the same value irrespective of whether this is
1465 -- a forward or reverse iteration.
1467 return It : constant Iterator :=
1468 (Limited_Controlled with S, Start.Node)
1470 B := B + 1;
1471 end return;
1472 end Iterate;
1474 ----------
1475 -- Last --
1476 ----------
1478 function Last (Container : Set) return Cursor is
1479 begin
1480 if Container.Tree.Last = null then
1481 return No_Element;
1482 end if;
1484 return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1485 end Last;
1487 function Last (Object : Iterator) return Cursor is
1488 begin
1489 -- The value of the iterator object's Node component influences the
1490 -- behavior of the Last (and First) selector function.
1492 -- When the Node component is null, this means the iterator object was
1493 -- constructed without a start expression, in which case the (reverse)
1494 -- iteration starts from the (logical) beginning of the entire sequence
1495 -- (corresponding to Container.Last, for a reverse iterator).
1497 -- Otherwise, this is iteration over a partial sequence of items. When
1498 -- the Node component is non-null, the iterator object was constructed
1499 -- with a start expression, that specifies the position from which the
1500 -- (reverse) partial iteration begins.
1502 if Object.Node = null then
1503 return Object.Container.Last;
1504 else
1505 return Cursor'(Object.Container, Object.Node);
1506 end if;
1507 end Last;
1509 ------------------
1510 -- Last_Element --
1511 ------------------
1513 function Last_Element (Container : Set) return Element_Type is
1514 begin
1515 if Container.Tree.Last = null then
1516 raise Constraint_Error with "set is empty";
1517 end if;
1519 pragma Assert (Container.Tree.Last.Element /= null);
1520 return Container.Tree.Last.Element.all;
1521 end Last_Element;
1523 ----------
1524 -- Left --
1525 ----------
1527 function Left (Node : Node_Access) return Node_Access is
1528 begin
1529 return Node.Left;
1530 end Left;
1532 ------------
1533 -- Length --
1534 ------------
1536 function Length (Container : Set) return Count_Type is
1537 begin
1538 return Container.Tree.Length;
1539 end Length;
1541 ----------
1542 -- Move --
1543 ----------
1545 procedure Move is
1546 new Tree_Operations.Generic_Move (Clear);
1548 procedure Move (Target : in out Set; Source : in out Set) is
1549 begin
1550 Move (Target => Target.Tree, Source => Source.Tree);
1551 end Move;
1553 ----------
1554 -- Next --
1555 ----------
1557 function Next (Position : Cursor) return Cursor is
1558 begin
1559 if Position = No_Element then
1560 return No_Element;
1561 end if;
1563 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1564 "bad cursor in Next");
1566 declare
1567 Node : constant Node_Access :=
1568 Tree_Operations.Next (Position.Node);
1570 begin
1571 if Node = null then
1572 return No_Element;
1573 end if;
1575 return Cursor'(Position.Container, Node);
1576 end;
1577 end Next;
1579 procedure Next (Position : in out Cursor) is
1580 begin
1581 Position := Next (Position);
1582 end Next;
1584 function Next (Object : Iterator; Position : Cursor) return Cursor is
1585 begin
1586 if Position.Container = null then
1587 return No_Element;
1588 end if;
1590 if Position.Container /= Object.Container then
1591 raise Program_Error with
1592 "Position cursor of Next designates wrong set";
1593 end if;
1595 return Next (Position);
1596 end Next;
1598 -------------
1599 -- Overlap --
1600 -------------
1602 function Overlap (Left, Right : Set) return Boolean is
1603 begin
1604 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1605 end Overlap;
1607 ------------
1608 -- Parent --
1609 ------------
1611 function Parent (Node : Node_Access) return Node_Access is
1612 begin
1613 return Node.Parent;
1614 end Parent;
1616 --------------
1617 -- Previous --
1618 --------------
1620 function Previous (Position : Cursor) return Cursor is
1621 begin
1622 if Position = No_Element then
1623 return No_Element;
1624 end if;
1626 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1627 "bad cursor in Previous");
1629 declare
1630 Node : constant Node_Access :=
1631 Tree_Operations.Previous (Position.Node);
1633 begin
1634 if Node = null then
1635 return No_Element;
1636 end if;
1638 return Cursor'(Position.Container, Node);
1639 end;
1640 end Previous;
1642 procedure Previous (Position : in out Cursor) is
1643 begin
1644 Position := Previous (Position);
1645 end Previous;
1647 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1648 begin
1649 if Position.Container = null then
1650 return No_Element;
1651 end if;
1653 if Position.Container /= Object.Container then
1654 raise Program_Error with
1655 "Position cursor of Previous designates wrong set";
1656 end if;
1658 return Previous (Position);
1659 end Previous;
1661 -------------------
1662 -- Query_Element --
1663 -------------------
1665 procedure Query_Element
1666 (Position : Cursor;
1667 Process : not null access procedure (Element : Element_Type))
1669 begin
1670 if Position.Node = null then
1671 raise Constraint_Error with "Position cursor equals No_Element";
1672 end if;
1674 if Position.Node.Element = null then
1675 raise Program_Error with "Position cursor is bad";
1676 end if;
1678 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1679 "bad cursor in Query_Element");
1681 declare
1682 T : Tree_Type renames Position.Container.Tree;
1684 B : Natural renames T.Busy;
1685 L : Natural renames T.Lock;
1687 begin
1688 B := B + 1;
1689 L := L + 1;
1691 begin
1692 Process (Position.Node.Element.all);
1693 exception
1694 when others =>
1695 L := L - 1;
1696 B := B - 1;
1697 raise;
1698 end;
1700 L := L - 1;
1701 B := B - 1;
1702 end;
1703 end Query_Element;
1705 ----------
1706 -- Read --
1707 ----------
1709 procedure Read
1710 (Stream : not null access Root_Stream_Type'Class;
1711 Container : out Set)
1713 function Read_Node
1714 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1715 pragma Inline (Read_Node);
1717 procedure Read is
1718 new Tree_Operations.Generic_Read (Clear, Read_Node);
1720 ---------------
1721 -- Read_Node --
1722 ---------------
1724 function Read_Node
1725 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1727 Node : Node_Access := new Node_Type;
1728 begin
1729 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1730 return Node;
1731 exception
1732 when others =>
1733 Free (Node); -- Note that Free deallocates elem too
1734 raise;
1735 end Read_Node;
1737 -- Start of processing for Read
1739 begin
1740 Read (Stream, Container.Tree);
1741 end Read;
1743 procedure Read
1744 (Stream : not null access Root_Stream_Type'Class;
1745 Item : out Cursor)
1747 begin
1748 raise Program_Error with "attempt to stream set cursor";
1749 end Read;
1751 ---------------------
1752 -- Replace_Element --
1753 ---------------------
1755 procedure Replace_Element
1756 (Tree : in out Tree_Type;
1757 Node : Node_Access;
1758 Item : Element_Type)
1760 begin
1761 if Item < Node.Element.all
1762 or else Node.Element.all < Item
1763 then
1764 null;
1765 else
1766 if Tree.Lock > 0 then
1767 raise Program_Error with
1768 "attempt to tamper with elements (set is locked)";
1769 end if;
1771 declare
1772 X : Element_Access := Node.Element;
1774 -- The element allocator may need an accessibility check in the
1775 -- case the actual type is class-wide or has access discriminants
1776 -- (see RM 4.8(10.1) and AI12-0035).
1778 pragma Unsuppress (Accessibility_Check);
1780 begin
1781 Node.Element := new Element_Type'(Item);
1782 Free_Element (X);
1783 end;
1785 return;
1786 end if;
1788 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1790 Insert_New_Item : declare
1791 function New_Node return Node_Access;
1792 pragma Inline (New_Node);
1794 procedure Insert_Post is
1795 new Element_Keys.Generic_Insert_Post (New_Node);
1797 procedure Unconditional_Insert is
1798 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1800 --------------
1801 -- New_Node --
1802 --------------
1804 function New_Node return Node_Access is
1806 -- The element allocator may need an accessibility check in the
1807 -- case the actual type is class-wide or has access discriminants
1808 -- (see RM 4.8(10.1) and AI12-0035).
1810 pragma Unsuppress (Accessibility_Check);
1812 begin
1813 Node.Element := new Element_Type'(Item); -- OK if fails
1814 Node.Color := Red_Black_Trees.Red;
1815 Node.Parent := null;
1816 Node.Left := null;
1817 Node.Right := null;
1819 return Node;
1820 end New_Node;
1822 Result : Node_Access;
1824 X : Element_Access := Node.Element;
1826 -- Start of processing for Insert_New_Item
1828 begin
1829 Unconditional_Insert
1830 (Tree => Tree,
1831 Key => Item,
1832 Node => Result);
1833 pragma Assert (Result = Node);
1835 Free_Element (X); -- OK if fails
1836 end Insert_New_Item;
1837 end Replace_Element;
1839 procedure Replace_Element
1840 (Container : in out Set;
1841 Position : Cursor;
1842 New_Item : Element_Type)
1844 begin
1845 if Position.Node = null then
1846 raise Constraint_Error with "Position cursor equals No_Element";
1847 end if;
1849 if Position.Node.Element = null then
1850 raise Program_Error with "Position cursor is bad";
1851 end if;
1853 if Position.Container /= Container'Unrestricted_Access then
1854 raise Program_Error with "Position cursor designates wrong set";
1855 end if;
1857 pragma Assert (Vet (Container.Tree, Position.Node),
1858 "bad cursor in Replace_Element");
1860 Replace_Element (Container.Tree, Position.Node, New_Item);
1861 end Replace_Element;
1863 ---------------------
1864 -- Reverse_Iterate --
1865 ---------------------
1867 procedure Reverse_Iterate
1868 (Container : Set;
1869 Item : Element_Type;
1870 Process : not null access procedure (Position : Cursor))
1872 procedure Process_Node (Node : Node_Access);
1873 pragma Inline (Process_Node);
1875 procedure Local_Reverse_Iterate is
1876 new Element_Keys.Generic_Reverse_Iteration (Process_Node);
1878 ------------------
1879 -- Process_Node --
1880 ------------------
1882 procedure Process_Node (Node : Node_Access) is
1883 begin
1884 Process (Cursor'(Container'Unrestricted_Access, Node));
1885 end Process_Node;
1887 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1888 B : Natural renames T.Busy;
1890 -- Start of processing for Reverse_Iterate
1892 begin
1893 B := B + 1;
1895 begin
1896 Local_Reverse_Iterate (T, Item);
1897 exception
1898 when others =>
1899 B := B - 1;
1900 raise;
1901 end;
1903 B := B - 1;
1904 end Reverse_Iterate;
1906 procedure Reverse_Iterate
1907 (Container : Set;
1908 Process : not null access procedure (Position : Cursor))
1910 procedure Process_Node (Node : Node_Access);
1911 pragma Inline (Process_Node);
1913 procedure Local_Reverse_Iterate is
1914 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1916 ------------------
1917 -- Process_Node --
1918 ------------------
1920 procedure Process_Node (Node : Node_Access) is
1921 begin
1922 Process (Cursor'(Container'Unrestricted_Access, Node));
1923 end Process_Node;
1925 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1926 B : Natural renames T.Busy;
1928 -- Start of processing for Reverse_Iterate
1930 begin
1931 B := B + 1;
1933 begin
1934 Local_Reverse_Iterate (T);
1935 exception
1936 when others =>
1937 B := B - 1;
1938 raise;
1939 end;
1941 B := B - 1;
1942 end Reverse_Iterate;
1944 -----------
1945 -- Right --
1946 -----------
1948 function Right (Node : Node_Access) return Node_Access is
1949 begin
1950 return Node.Right;
1951 end Right;
1953 ---------------
1954 -- Set_Color --
1955 ---------------
1957 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1958 begin
1959 Node.Color := Color;
1960 end Set_Color;
1962 --------------
1963 -- Set_Left --
1964 --------------
1966 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1967 begin
1968 Node.Left := Left;
1969 end Set_Left;
1971 ----------------
1972 -- Set_Parent --
1973 ----------------
1975 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1976 begin
1977 Node.Parent := Parent;
1978 end Set_Parent;
1980 ---------------
1981 -- Set_Right --
1982 ---------------
1984 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1985 begin
1986 Node.Right := Right;
1987 end Set_Right;
1989 --------------------------
1990 -- Symmetric_Difference --
1991 --------------------------
1993 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1994 begin
1995 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1996 end Symmetric_Difference;
1998 function Symmetric_Difference (Left, Right : Set) return Set is
1999 Tree : constant Tree_Type :=
2000 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
2001 begin
2002 return Set'(Controlled with Tree);
2003 end Symmetric_Difference;
2005 ------------
2006 -- To_Set --
2007 ------------
2009 function To_Set (New_Item : Element_Type) return Set is
2010 Tree : Tree_Type;
2011 Node : Node_Access;
2012 pragma Unreferenced (Node);
2013 begin
2014 Insert_Sans_Hint (Tree, New_Item, Node);
2015 return Set'(Controlled with Tree);
2016 end To_Set;
2018 -----------
2019 -- Union --
2020 -----------
2022 procedure Union (Target : in out Set; Source : Set) is
2023 begin
2024 Set_Ops.Union (Target.Tree, Source.Tree);
2025 end Union;
2027 function Union (Left, Right : Set) return Set is
2028 Tree : constant Tree_Type :=
2029 Set_Ops.Union (Left.Tree, Right.Tree);
2030 begin
2031 return Set'(Controlled with Tree);
2032 end Union;
2034 -----------
2035 -- Write --
2036 -----------
2038 procedure Write
2039 (Stream : not null access Root_Stream_Type'Class;
2040 Container : Set)
2042 procedure Write_Node
2043 (Stream : not null access Root_Stream_Type'Class;
2044 Node : Node_Access);
2045 pragma Inline (Write_Node);
2047 procedure Write is
2048 new Tree_Operations.Generic_Write (Write_Node);
2050 ----------------
2051 -- Write_Node --
2052 ----------------
2054 procedure Write_Node
2055 (Stream : not null access Root_Stream_Type'Class;
2056 Node : Node_Access)
2058 begin
2059 Element_Type'Output (Stream, Node.Element.all);
2060 end Write_Node;
2062 -- Start of processing for Write
2064 begin
2065 Write (Stream, Container.Tree);
2066 end Write;
2068 procedure Write
2069 (Stream : not null access Root_Stream_Type'Class;
2070 Item : Cursor)
2072 begin
2073 raise Program_Error with "attempt to stream set cursor";
2074 end Write;
2076 end Ada.Containers.Indefinite_Ordered_Multisets;