* configure.tgt: Add sh* case.
[official-gcc.git] / gcc / ada / a-ciormu.adb
blob928ba9924c44e2a3c7ba4caa63fa026f9932186a
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_MULTISETS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2011, 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 :=
507 Set_Ops.Difference (Left.Tree, Right.Tree);
508 begin
509 return Set'(Controlled with Tree);
510 end Difference;
512 -------------
513 -- Element --
514 -------------
516 function Element (Position : Cursor) return Element_Type is
517 begin
518 if Position.Node = null then
519 raise Constraint_Error with "Position cursor equals No_Element";
520 end if;
522 if Position.Node.Element = null then
523 raise Program_Error with "Position cursor is bad";
524 end if;
526 pragma Assert (Vet (Position.Container.Tree, Position.Node),
527 "bad cursor in Element");
529 return Position.Node.Element.all;
530 end Element;
532 -------------------------
533 -- Equivalent_Elements --
534 -------------------------
536 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
537 begin
538 if Left < Right
539 or else Right < Left
540 then
541 return False;
542 else
543 return True;
544 end if;
545 end Equivalent_Elements;
547 ---------------------
548 -- Equivalent_Sets --
549 ---------------------
551 function Equivalent_Sets (Left, Right : Set) return Boolean is
553 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
554 pragma Inline (Is_Equivalent_Node_Node);
556 function Is_Equivalent is
557 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
559 -----------------------------
560 -- Is_Equivalent_Node_Node --
561 -----------------------------
563 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
564 begin
565 if L.Element.all < R.Element.all then
566 return False;
567 elsif R.Element.all < L.Element.all then
568 return False;
569 else
570 return True;
571 end if;
572 end Is_Equivalent_Node_Node;
574 -- Start of processing for Equivalent_Sets
576 begin
577 return Is_Equivalent (Left.Tree, Right.Tree);
578 end Equivalent_Sets;
580 -------------
581 -- Exclude --
582 -------------
584 procedure Exclude (Container : in out Set; Item : Element_Type) is
585 Tree : Tree_Type renames Container.Tree;
586 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
587 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
588 X : Node_Access;
590 begin
591 while Node /= Done loop
592 X := Node;
593 Node := Tree_Operations.Next (Node);
594 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
595 Free (X);
596 end loop;
597 end Exclude;
599 ----------
600 -- Find --
601 ----------
603 function Find (Container : Set; Item : Element_Type) return Cursor is
604 Node : constant Node_Access :=
605 Element_Keys.Find (Container.Tree, Item);
607 begin
608 if Node = null then
609 return No_Element;
610 end if;
612 return Cursor'(Container'Unrestricted_Access, Node);
613 end Find;
615 --------------
616 -- Finalize --
617 --------------
619 procedure Finalize (Object : in out Iterator) is
620 B : Natural renames Object.Container.Tree.Busy;
621 pragma Assert (B > 0);
622 begin
623 B := B - 1;
624 end Finalize;
626 -----------
627 -- First --
628 -----------
630 function First (Container : Set) return Cursor is
631 begin
632 if Container.Tree.First = null then
633 return No_Element;
634 end if;
636 return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
637 end First;
639 function First (Object : Iterator) return Cursor is
640 begin
641 -- The value of the iterator object's Node component influences the
642 -- behavior of the First (and Last) selector function.
644 -- When the Node component is null, this means the iterator object was
645 -- constructed without a start expression, in which case the (forward)
646 -- iteration starts from the (logical) beginning of the entire sequence
647 -- of items (corresponding to Container.First, for a forward iterator).
649 -- Otherwise, this is iteration over a partial sequence of items. When
650 -- the Node component is non-null, the iterator object was constructed
651 -- with a start expression, that specifies the position from which the
652 -- (forward) partial iteration begins.
654 if Object.Node = null then
655 return Object.Container.First;
656 else
657 return Cursor'(Object.Container, Object.Node);
658 end if;
659 end First;
661 -------------------
662 -- First_Element --
663 -------------------
665 function First_Element (Container : Set) return Element_Type is
666 begin
667 if Container.Tree.First = null then
668 raise Constraint_Error with "set is empty";
669 end if;
671 pragma Assert (Container.Tree.First.Element /= null);
672 return Container.Tree.First.Element.all;
673 end First_Element;
675 -----------
676 -- Floor --
677 -----------
679 function Floor (Container : Set; Item : Element_Type) return Cursor is
680 Node : constant Node_Access :=
681 Element_Keys.Floor (Container.Tree, Item);
683 begin
684 if Node = null then
685 return No_Element;
686 end if;
688 return Cursor'(Container'Unrestricted_Access, Node);
689 end Floor;
691 ----------
692 -- Free --
693 ----------
695 procedure Free (X : in out Node_Access) is
696 procedure Deallocate is
697 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
699 begin
700 if X = null then
701 return;
702 end if;
704 X.Parent := X;
705 X.Left := X;
706 X.Right := X;
708 begin
709 Free_Element (X.Element);
710 exception
711 when others =>
712 X.Element := null;
713 Deallocate (X);
714 raise;
715 end;
717 Deallocate (X);
718 end Free;
720 ------------------
721 -- Generic_Keys --
722 ------------------
724 package body Generic_Keys is
726 -----------------------
727 -- Local Subprograms --
728 -----------------------
730 function Is_Less_Key_Node
731 (Left : Key_Type;
732 Right : Node_Access) return Boolean;
733 pragma Inline (Is_Less_Key_Node);
735 function Is_Greater_Key_Node
736 (Left : Key_Type;
737 Right : Node_Access) return Boolean;
738 pragma Inline (Is_Greater_Key_Node);
740 --------------------------
741 -- Local Instantiations --
742 --------------------------
744 package Key_Keys is
745 new Red_Black_Trees.Generic_Keys
746 (Tree_Operations => Tree_Operations,
747 Key_Type => Key_Type,
748 Is_Less_Key_Node => Is_Less_Key_Node,
749 Is_Greater_Key_Node => Is_Greater_Key_Node);
751 -------------
752 -- Ceiling --
753 -------------
755 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
756 Node : constant Node_Access :=
757 Key_Keys.Ceiling (Container.Tree, Key);
759 begin
760 if Node = null then
761 return No_Element;
762 end if;
764 return Cursor'(Container'Unrestricted_Access, Node);
765 end Ceiling;
767 --------------
768 -- Contains --
769 --------------
771 function Contains (Container : Set; Key : Key_Type) return Boolean is
772 begin
773 return Find (Container, Key) /= No_Element;
774 end Contains;
776 ------------
777 -- Delete --
778 ------------
780 procedure Delete (Container : in out Set; Key : Key_Type) is
781 Tree : Tree_Type renames Container.Tree;
782 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
783 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
784 X : Node_Access;
786 begin
787 if Node = Done then
788 raise Constraint_Error with "attempt to delete key not in set";
789 end if;
791 loop
792 X := Node;
793 Node := Tree_Operations.Next (Node);
794 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
795 Free (X);
797 exit when Node = Done;
798 end loop;
799 end Delete;
801 -------------
802 -- Element --
803 -------------
805 function Element (Container : Set; Key : Key_Type) return Element_Type is
806 Node : constant Node_Access :=
807 Key_Keys.Find (Container.Tree, Key);
809 begin
810 if Node = null then
811 raise Constraint_Error with "key not in set";
812 end if;
814 return Node.Element.all;
815 end Element;
817 ---------------------
818 -- Equivalent_Keys --
819 ---------------------
821 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
822 begin
823 if Left < Right
824 or else Right < Left
825 then
826 return False;
827 else
828 return True;
829 end if;
830 end Equivalent_Keys;
832 -------------
833 -- Exclude --
834 -------------
836 procedure Exclude (Container : in out Set; Key : Key_Type) is
837 Tree : Tree_Type renames Container.Tree;
838 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
839 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
840 X : Node_Access;
842 begin
843 while Node /= Done loop
844 X := Node;
845 Node := Tree_Operations.Next (Node);
846 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
847 Free (X);
848 end loop;
849 end Exclude;
851 ----------
852 -- Find --
853 ----------
855 function Find (Container : Set; Key : Key_Type) return Cursor is
856 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
858 begin
859 if Node = null then
860 return No_Element;
861 end if;
863 return Cursor'(Container'Unrestricted_Access, Node);
864 end Find;
866 -----------
867 -- Floor --
868 -----------
870 function Floor (Container : Set; Key : Key_Type) return Cursor is
871 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
873 begin
874 if Node = null then
875 return No_Element;
876 end if;
878 return Cursor'(Container'Unrestricted_Access, Node);
879 end Floor;
881 -------------------------
882 -- Is_Greater_Key_Node --
883 -------------------------
885 function Is_Greater_Key_Node
886 (Left : Key_Type;
887 Right : Node_Access) return Boolean
889 begin
890 return Key (Right.Element.all) < Left;
891 end Is_Greater_Key_Node;
893 ----------------------
894 -- Is_Less_Key_Node --
895 ----------------------
897 function Is_Less_Key_Node
898 (Left : Key_Type;
899 Right : Node_Access) return Boolean
901 begin
902 return Left < Key (Right.Element.all);
903 end Is_Less_Key_Node;
905 -------------
906 -- Iterate --
907 -------------
909 procedure Iterate
910 (Container : Set;
911 Key : Key_Type;
912 Process : not null access procedure (Position : Cursor))
914 procedure Process_Node (Node : Node_Access);
915 pragma Inline (Process_Node);
917 procedure Local_Iterate is
918 new Key_Keys.Generic_Iteration (Process_Node);
920 ------------------
921 -- Process_Node --
922 ------------------
924 procedure Process_Node (Node : Node_Access) is
925 begin
926 Process (Cursor'(Container'Unrestricted_Access, Node));
927 end Process_Node;
929 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
930 B : Natural renames T.Busy;
932 -- Start of processing for Iterate
934 begin
935 B := B + 1;
937 begin
938 Local_Iterate (T, Key);
939 exception
940 when others =>
941 B := B - 1;
942 raise;
943 end;
945 B := B - 1;
946 end Iterate;
948 ---------
949 -- Key --
950 ---------
952 function Key (Position : Cursor) return Key_Type is
953 begin
954 if Position.Node = null then
955 raise Constraint_Error with
956 "Position cursor equals No_Element";
957 end if;
959 if Position.Node.Element = null then
960 raise Program_Error with
961 "Position cursor is bad";
962 end if;
964 pragma Assert (Vet (Position.Container.Tree, Position.Node),
965 "bad cursor in Key");
967 return Key (Position.Node.Element.all);
968 end Key;
970 ---------------------
971 -- Reverse_Iterate --
972 ---------------------
974 procedure Reverse_Iterate
975 (Container : Set;
976 Key : Key_Type;
977 Process : not null access procedure (Position : Cursor))
979 procedure Process_Node (Node : Node_Access);
980 pragma Inline (Process_Node);
982 -------------
983 -- Iterate --
984 -------------
986 procedure Local_Reverse_Iterate is
987 new Key_Keys.Generic_Reverse_Iteration (Process_Node);
989 ------------------
990 -- Process_Node --
991 ------------------
993 procedure Process_Node (Node : Node_Access) is
994 begin
995 Process (Cursor'(Container'Unrestricted_Access, Node));
996 end Process_Node;
998 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
999 B : Natural renames T.Busy;
1001 -- Start of processing for Reverse_Iterate
1003 begin
1004 B := B + 1;
1006 begin
1007 Local_Reverse_Iterate (T, Key);
1008 exception
1009 when others =>
1010 B := B - 1;
1011 raise;
1012 end;
1014 B := B - 1;
1015 end Reverse_Iterate;
1017 --------------------
1018 -- Update_Element --
1019 --------------------
1021 procedure Update_Element
1022 (Container : in out Set;
1023 Position : Cursor;
1024 Process : not null access procedure (Element : in out Element_Type))
1026 Tree : Tree_Type renames Container.Tree;
1027 Node : constant Node_Access := Position.Node;
1029 begin
1030 if Node = null then
1031 raise Constraint_Error with "Position cursor equals No_Element";
1032 end if;
1034 if Node.Element = null then
1035 raise Program_Error with "Position cursor is bad";
1036 end if;
1038 if Position.Container /= Container'Unrestricted_Access then
1039 raise Program_Error with "Position cursor designates wrong set";
1040 end if;
1042 pragma Assert (Vet (Tree, Node),
1043 "bad cursor in Update_Element");
1045 declare
1046 E : Element_Type renames Node.Element.all;
1047 K : constant Key_Type := Key (E);
1049 B : Natural renames Tree.Busy;
1050 L : Natural renames Tree.Lock;
1052 begin
1053 B := B + 1;
1054 L := L + 1;
1056 begin
1057 Process (E);
1058 exception
1059 when others =>
1060 L := L - 1;
1061 B := B - 1;
1062 raise;
1063 end;
1065 L := L - 1;
1066 B := B - 1;
1068 if Equivalent_Keys (Left => K, Right => Key (E)) then
1069 return;
1070 end if;
1071 end;
1073 -- Delete_Node checks busy-bit
1075 Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
1077 Insert_New_Item : declare
1078 function New_Node return Node_Access;
1079 pragma Inline (New_Node);
1081 procedure Insert_Post is
1082 new Element_Keys.Generic_Insert_Post (New_Node);
1084 procedure Unconditional_Insert is
1085 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1087 --------------
1088 -- New_Node --
1089 --------------
1091 function New_Node return Node_Access is
1092 begin
1093 Node.Color := Red_Black_Trees.Red;
1094 Node.Parent := null;
1095 Node.Left := null;
1096 Node.Right := null;
1098 return Node;
1099 end New_Node;
1101 Result : Node_Access;
1103 -- Start of processing for Insert_New_Item
1105 begin
1106 Unconditional_Insert
1107 (Tree => Tree,
1108 Key => Node.Element.all,
1109 Node => Result);
1111 pragma Assert (Result = Node);
1112 end Insert_New_Item;
1113 end Update_Element;
1115 end Generic_Keys;
1117 -----------------
1118 -- Has_Element --
1119 -----------------
1121 function Has_Element (Position : Cursor) return Boolean is
1122 begin
1123 return Position /= No_Element;
1124 end Has_Element;
1126 ------------
1127 -- Insert --
1128 ------------
1130 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1131 Position : Cursor;
1132 pragma Unreferenced (Position);
1133 begin
1134 Insert (Container, New_Item, Position);
1135 end Insert;
1137 procedure Insert
1138 (Container : in out Set;
1139 New_Item : Element_Type;
1140 Position : out Cursor)
1142 begin
1143 Insert_Sans_Hint (Container.Tree, New_Item, Position.Node);
1144 Position.Container := Container'Unrestricted_Access;
1145 end Insert;
1147 ----------------------
1148 -- Insert_Sans_Hint --
1149 ----------------------
1151 procedure Insert_Sans_Hint
1152 (Tree : in out Tree_Type;
1153 New_Item : Element_Type;
1154 Node : out Node_Access)
1156 function New_Node return Node_Access;
1157 pragma Inline (New_Node);
1159 procedure Insert_Post is
1160 new Element_Keys.Generic_Insert_Post (New_Node);
1162 procedure Unconditional_Insert is
1163 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1165 --------------
1166 -- New_Node --
1167 --------------
1169 function New_Node return Node_Access is
1170 Element : Element_Access := new Element_Type'(New_Item);
1172 begin
1173 return new Node_Type'(Parent => null,
1174 Left => null,
1175 Right => null,
1176 Color => Red_Black_Trees.Red,
1177 Element => Element);
1178 exception
1179 when others =>
1180 Free_Element (Element);
1181 raise;
1182 end New_Node;
1184 -- Start of processing for Insert_Sans_Hint
1186 begin
1187 Unconditional_Insert (Tree, New_Item, Node);
1188 end Insert_Sans_Hint;
1190 ----------------------
1191 -- Insert_With_Hint --
1192 ----------------------
1194 procedure Insert_With_Hint
1195 (Dst_Tree : in out Tree_Type;
1196 Dst_Hint : Node_Access;
1197 Src_Node : Node_Access;
1198 Dst_Node : out Node_Access)
1200 function New_Node return Node_Access;
1201 pragma Inline (New_Node);
1203 procedure Insert_Post is
1204 new Element_Keys.Generic_Insert_Post (New_Node);
1206 procedure Insert_Sans_Hint is
1207 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1209 procedure Local_Insert_With_Hint is
1210 new Element_Keys.Generic_Unconditional_Insert_With_Hint
1211 (Insert_Post,
1212 Insert_Sans_Hint);
1214 --------------
1215 -- New_Node --
1216 --------------
1218 function New_Node return Node_Access is
1219 X : Element_Access := new Element_Type'(Src_Node.Element.all);
1221 begin
1222 return new Node_Type'(Parent => null,
1223 Left => null,
1224 Right => null,
1225 Color => Red,
1226 Element => X);
1228 exception
1229 when others =>
1230 Free_Element (X);
1231 raise;
1232 end New_Node;
1234 -- Start of processing for Insert_With_Hint
1236 begin
1237 Local_Insert_With_Hint
1238 (Dst_Tree,
1239 Dst_Hint,
1240 Src_Node.Element.all,
1241 Dst_Node);
1242 end Insert_With_Hint;
1244 ------------------
1245 -- Intersection --
1246 ------------------
1248 procedure Intersection (Target : in out Set; Source : Set) is
1249 begin
1250 Set_Ops.Intersection (Target.Tree, Source.Tree);
1251 end Intersection;
1253 function Intersection (Left, Right : Set) return Set is
1254 Tree : constant Tree_Type :=
1255 Set_Ops.Intersection (Left.Tree, Right.Tree);
1256 begin
1257 return Set'(Controlled with Tree);
1258 end Intersection;
1260 --------------
1261 -- Is_Empty --
1262 --------------
1264 function Is_Empty (Container : Set) return Boolean is
1265 begin
1266 return Container.Tree.Length = 0;
1267 end Is_Empty;
1269 ------------------------
1270 -- Is_Equal_Node_Node --
1271 ------------------------
1273 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1274 begin
1275 return L.Element.all = R.Element.all;
1276 end Is_Equal_Node_Node;
1278 -----------------------------
1279 -- Is_Greater_Element_Node --
1280 -----------------------------
1282 function Is_Greater_Element_Node
1283 (Left : Element_Type;
1284 Right : Node_Access) return Boolean
1286 begin
1287 -- e > node same as node < e
1289 return Right.Element.all < Left;
1290 end Is_Greater_Element_Node;
1292 --------------------------
1293 -- Is_Less_Element_Node --
1294 --------------------------
1296 function Is_Less_Element_Node
1297 (Left : Element_Type;
1298 Right : Node_Access) return Boolean
1300 begin
1301 return Left < Right.Element.all;
1302 end Is_Less_Element_Node;
1304 -----------------------
1305 -- Is_Less_Node_Node --
1306 -----------------------
1308 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1309 begin
1310 return L.Element.all < R.Element.all;
1311 end Is_Less_Node_Node;
1313 ---------------
1314 -- Is_Subset --
1315 ---------------
1317 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1318 begin
1319 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1320 end Is_Subset;
1322 -------------
1323 -- Iterate --
1324 -------------
1326 procedure Iterate
1327 (Container : Set;
1328 Item : Element_Type;
1329 Process : not null access procedure (Position : Cursor))
1331 procedure Process_Node (Node : Node_Access);
1332 pragma Inline (Process_Node);
1334 procedure Local_Iterate is
1335 new Element_Keys.Generic_Iteration (Process_Node);
1337 ------------------
1338 -- Process_Node --
1339 ------------------
1341 procedure Process_Node (Node : Node_Access) is
1342 begin
1343 Process (Cursor'(Container'Unrestricted_Access, Node));
1344 end Process_Node;
1346 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1347 B : Natural renames T.Busy;
1349 -- Start of processing for Iterate
1351 begin
1352 B := B + 1;
1354 begin
1355 Local_Iterate (T, Item);
1356 exception
1357 when others =>
1358 B := B - 1;
1359 raise;
1360 end;
1362 B := B - 1;
1363 end Iterate;
1365 procedure Iterate
1366 (Container : Set;
1367 Process : not null access procedure (Position : Cursor))
1369 procedure Process_Node (Node : Node_Access);
1370 pragma Inline (Process_Node);
1372 procedure Local_Iterate is
1373 new Tree_Operations.Generic_Iteration (Process_Node);
1375 ------------------
1376 -- Process_Node --
1377 ------------------
1379 procedure Process_Node (Node : Node_Access) is
1380 begin
1381 Process (Cursor'(Container'Unrestricted_Access, Node));
1382 end Process_Node;
1384 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1385 B : Natural renames T.Busy;
1387 -- Start of processing for Iterate
1389 begin
1390 B := B + 1;
1392 begin
1393 Local_Iterate (T);
1394 exception
1395 when others =>
1396 B := B - 1;
1397 raise;
1398 end;
1400 B := B - 1;
1401 end Iterate;
1403 function Iterate (Container : Set)
1404 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1406 S : constant Set_Access := Container'Unrestricted_Access;
1407 B : Natural renames S.Tree.Busy;
1409 begin
1410 -- The value of the Node component influences the behavior of the First
1411 -- and Last selector functions of the iterator object. When the Node
1412 -- component is null (as is the case here), this means the iterator
1413 -- object was constructed without a start expression. This is a complete
1414 -- iterator, meaning that the iteration starts from the (logical)
1415 -- beginning of the sequence of items.
1417 -- Note: For a forward iterator, Container.First is the beginning, and
1418 -- for a reverse iterator, Container.Last is the beginning.
1420 return It : constant Iterator := (Limited_Controlled with S, null) do
1421 B := B + 1;
1422 end return;
1423 end Iterate;
1425 function Iterate (Container : Set; Start : Cursor)
1426 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1428 S : constant Set_Access := Container'Unrestricted_Access;
1429 B : Natural renames S.Tree.Busy;
1431 begin
1432 -- It was formerly the case that when Start = No_Element, the partial
1433 -- iterator was defined to behave the same as for a complete iterator,
1434 -- and iterate over the entire sequence of items. However, those
1435 -- semantics were unintuitive and arguably error-prone (it is too easy
1436 -- to accidentally create an endless loop), and so they were changed,
1437 -- per the ARG meeting in Denver on 2011/11. However, there was no
1438 -- consensus about what positive meaning this corner case should have,
1439 -- and so it was decided to simply raise an exception. This does imply,
1440 -- however, that it is not possible to use a partial iterator to specify
1441 -- an empty sequence of items.
1443 if Start = No_Element then
1444 raise Constraint_Error with
1445 "Start position for iterator equals No_Element";
1446 end if;
1448 if Start.Container /= Container'Unrestricted_Access then
1449 raise Program_Error with
1450 "Start cursor of Iterate designates wrong set";
1451 end if;
1453 pragma Assert (Vet (Container.Tree, Start.Node),
1454 "Start cursor of Iterate is bad");
1456 -- The value of the Node component influences the behavior of the First
1457 -- and Last selector functions of the iterator object. When the Node
1458 -- component is non-null (as is the case here), it means that this is a
1459 -- partial iteration, over a subset of the complete sequence of
1460 -- items. The iterator object was constructed with a start expression,
1461 -- indicating the position from which the iteration begins. Note that
1462 -- the start position has the same value irrespective of whether this is
1463 -- a forward or reverse iteration.
1465 return It : constant Iterator :=
1466 (Limited_Controlled with S, Start.Node)
1468 B := B + 1;
1469 end return;
1470 end Iterate;
1472 ----------
1473 -- Last --
1474 ----------
1476 function Last (Container : Set) return Cursor is
1477 begin
1478 if Container.Tree.Last = null then
1479 return No_Element;
1480 end if;
1482 return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1483 end Last;
1485 function Last (Object : Iterator) return Cursor is
1486 begin
1487 -- The value of the iterator object's Node component influences the
1488 -- behavior of the Last (and First) selector function.
1490 -- When the Node component is null, this means the iterator object was
1491 -- constructed without a start expression, in which case the (reverse)
1492 -- iteration starts from the (logical) beginning of the entire sequence
1493 -- (corresponding to Container.Last, for a reverse iterator).
1495 -- Otherwise, this is iteration over a partial sequence of items. When
1496 -- the Node component is non-null, the iterator object was constructed
1497 -- with a start expression, that specifies the position from which the
1498 -- (reverse) partial iteration begins.
1500 if Object.Node = null then
1501 return Object.Container.Last;
1502 else
1503 return Cursor'(Object.Container, Object.Node);
1504 end if;
1505 end Last;
1507 ------------------
1508 -- Last_Element --
1509 ------------------
1511 function Last_Element (Container : Set) return Element_Type is
1512 begin
1513 if Container.Tree.Last = null then
1514 raise Constraint_Error with "set is empty";
1515 end if;
1517 pragma Assert (Container.Tree.Last.Element /= null);
1518 return Container.Tree.Last.Element.all;
1519 end Last_Element;
1521 ----------
1522 -- Left --
1523 ----------
1525 function Left (Node : Node_Access) return Node_Access is
1526 begin
1527 return Node.Left;
1528 end Left;
1530 ------------
1531 -- Length --
1532 ------------
1534 function Length (Container : Set) return Count_Type is
1535 begin
1536 return Container.Tree.Length;
1537 end Length;
1539 ----------
1540 -- Move --
1541 ----------
1543 procedure Move is
1544 new Tree_Operations.Generic_Move (Clear);
1546 procedure Move (Target : in out Set; Source : in out Set) is
1547 begin
1548 Move (Target => Target.Tree, Source => Source.Tree);
1549 end Move;
1551 ----------
1552 -- Next --
1553 ----------
1555 function Next (Position : Cursor) return Cursor is
1556 begin
1557 if Position = No_Element then
1558 return No_Element;
1559 end if;
1561 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1562 "bad cursor in Next");
1564 declare
1565 Node : constant Node_Access :=
1566 Tree_Operations.Next (Position.Node);
1568 begin
1569 if Node = null then
1570 return No_Element;
1571 end if;
1573 return Cursor'(Position.Container, Node);
1574 end;
1575 end Next;
1577 procedure Next (Position : in out Cursor) is
1578 begin
1579 Position := Next (Position);
1580 end Next;
1582 function Next (Object : Iterator; Position : Cursor) return Cursor is
1583 begin
1584 if Position.Container = null then
1585 return No_Element;
1586 end if;
1588 if Position.Container /= Object.Container then
1589 raise Program_Error with
1590 "Position cursor of Next designates wrong set";
1591 end if;
1593 return Next (Position);
1594 end Next;
1596 -------------
1597 -- Overlap --
1598 -------------
1600 function Overlap (Left, Right : Set) return Boolean is
1601 begin
1602 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1603 end Overlap;
1605 ------------
1606 -- Parent --
1607 ------------
1609 function Parent (Node : Node_Access) return Node_Access is
1610 begin
1611 return Node.Parent;
1612 end Parent;
1614 --------------
1615 -- Previous --
1616 --------------
1618 function Previous (Position : Cursor) return Cursor is
1619 begin
1620 if Position = No_Element then
1621 return No_Element;
1622 end if;
1624 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1625 "bad cursor in Previous");
1627 declare
1628 Node : constant Node_Access :=
1629 Tree_Operations.Previous (Position.Node);
1631 begin
1632 if Node = null then
1633 return No_Element;
1634 end if;
1636 return Cursor'(Position.Container, Node);
1637 end;
1638 end Previous;
1640 procedure Previous (Position : in out Cursor) is
1641 begin
1642 Position := Previous (Position);
1643 end Previous;
1645 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1646 begin
1647 if Position.Container = null then
1648 return No_Element;
1649 end if;
1651 if Position.Container /= Object.Container then
1652 raise Program_Error with
1653 "Position cursor of Previous designates wrong set";
1654 end if;
1656 return Previous (Position);
1657 end Previous;
1659 -------------------
1660 -- Query_Element --
1661 -------------------
1663 procedure Query_Element
1664 (Position : Cursor;
1665 Process : not null access procedure (Element : Element_Type))
1667 begin
1668 if Position.Node = null then
1669 raise Constraint_Error with "Position cursor equals No_Element";
1670 end if;
1672 if Position.Node.Element = null then
1673 raise Program_Error with "Position cursor is bad";
1674 end if;
1676 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1677 "bad cursor in Query_Element");
1679 declare
1680 T : Tree_Type renames Position.Container.Tree;
1682 B : Natural renames T.Busy;
1683 L : Natural renames T.Lock;
1685 begin
1686 B := B + 1;
1687 L := L + 1;
1689 begin
1690 Process (Position.Node.Element.all);
1691 exception
1692 when others =>
1693 L := L - 1;
1694 B := B - 1;
1695 raise;
1696 end;
1698 L := L - 1;
1699 B := B - 1;
1700 end;
1701 end Query_Element;
1703 ----------
1704 -- Read --
1705 ----------
1707 procedure Read
1708 (Stream : not null access Root_Stream_Type'Class;
1709 Container : out Set)
1711 function Read_Node
1712 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1713 pragma Inline (Read_Node);
1715 procedure Read is
1716 new Tree_Operations.Generic_Read (Clear, Read_Node);
1718 ---------------
1719 -- Read_Node --
1720 ---------------
1722 function Read_Node
1723 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1725 Node : Node_Access := new Node_Type;
1726 begin
1727 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1728 return Node;
1729 exception
1730 when others =>
1731 Free (Node); -- Note that Free deallocates elem too
1732 raise;
1733 end Read_Node;
1735 -- Start of processing for Read
1737 begin
1738 Read (Stream, Container.Tree);
1739 end Read;
1741 procedure Read
1742 (Stream : not null access Root_Stream_Type'Class;
1743 Item : out Cursor)
1745 begin
1746 raise Program_Error with "attempt to stream set cursor";
1747 end Read;
1749 ---------------------
1750 -- Replace_Element --
1751 ---------------------
1753 procedure Replace_Element
1754 (Tree : in out Tree_Type;
1755 Node : Node_Access;
1756 Item : Element_Type)
1758 begin
1759 if Item < Node.Element.all
1760 or else Node.Element.all < Item
1761 then
1762 null;
1763 else
1764 if Tree.Lock > 0 then
1765 raise Program_Error with
1766 "attempt to tamper with elements (set is locked)";
1767 end if;
1769 declare
1770 X : Element_Access := Node.Element;
1771 begin
1772 Node.Element := new Element_Type'(Item);
1773 Free_Element (X);
1774 end;
1776 return;
1777 end if;
1779 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1781 Insert_New_Item : declare
1782 function New_Node return Node_Access;
1783 pragma Inline (New_Node);
1785 procedure Insert_Post is
1786 new Element_Keys.Generic_Insert_Post (New_Node);
1788 procedure Unconditional_Insert is
1789 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1791 --------------
1792 -- New_Node --
1793 --------------
1795 function New_Node return Node_Access is
1796 begin
1797 Node.Element := new Element_Type'(Item); -- OK if fails
1798 Node.Color := Red_Black_Trees.Red;
1799 Node.Parent := null;
1800 Node.Left := null;
1801 Node.Right := null;
1803 return Node;
1804 end New_Node;
1806 Result : Node_Access;
1808 X : Element_Access := Node.Element;
1810 -- Start of processing for Insert_New_Item
1812 begin
1813 Unconditional_Insert
1814 (Tree => Tree,
1815 Key => Item,
1816 Node => Result);
1817 pragma Assert (Result = Node);
1819 Free_Element (X); -- OK if fails
1820 end Insert_New_Item;
1821 end Replace_Element;
1823 procedure Replace_Element
1824 (Container : in out Set;
1825 Position : Cursor;
1826 New_Item : Element_Type)
1828 begin
1829 if Position.Node = null then
1830 raise Constraint_Error with "Position cursor equals No_Element";
1831 end if;
1833 if Position.Node.Element = null then
1834 raise Program_Error with "Position cursor is bad";
1835 end if;
1837 if Position.Container /= Container'Unrestricted_Access then
1838 raise Program_Error with "Position cursor designates wrong set";
1839 end if;
1841 pragma Assert (Vet (Container.Tree, Position.Node),
1842 "bad cursor in Replace_Element");
1844 Replace_Element (Container.Tree, Position.Node, New_Item);
1845 end Replace_Element;
1847 ---------------------
1848 -- Reverse_Iterate --
1849 ---------------------
1851 procedure Reverse_Iterate
1852 (Container : Set;
1853 Item : Element_Type;
1854 Process : not null access procedure (Position : Cursor))
1856 procedure Process_Node (Node : Node_Access);
1857 pragma Inline (Process_Node);
1859 procedure Local_Reverse_Iterate is
1860 new Element_Keys.Generic_Reverse_Iteration (Process_Node);
1862 ------------------
1863 -- Process_Node --
1864 ------------------
1866 procedure Process_Node (Node : Node_Access) is
1867 begin
1868 Process (Cursor'(Container'Unrestricted_Access, Node));
1869 end Process_Node;
1871 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1872 B : Natural renames T.Busy;
1874 -- Start of processing for Reverse_Iterate
1876 begin
1877 B := B + 1;
1879 begin
1880 Local_Reverse_Iterate (T, Item);
1881 exception
1882 when others =>
1883 B := B - 1;
1884 raise;
1885 end;
1887 B := B - 1;
1888 end Reverse_Iterate;
1890 procedure Reverse_Iterate
1891 (Container : Set;
1892 Process : not null access procedure (Position : Cursor))
1894 procedure Process_Node (Node : Node_Access);
1895 pragma Inline (Process_Node);
1897 procedure Local_Reverse_Iterate is
1898 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1900 ------------------
1901 -- Process_Node --
1902 ------------------
1904 procedure Process_Node (Node : Node_Access) is
1905 begin
1906 Process (Cursor'(Container'Unrestricted_Access, Node));
1907 end Process_Node;
1909 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1910 B : Natural renames T.Busy;
1912 -- Start of processing for Reverse_Iterate
1914 begin
1915 B := B + 1;
1917 begin
1918 Local_Reverse_Iterate (T);
1919 exception
1920 when others =>
1921 B := B - 1;
1922 raise;
1923 end;
1925 B := B - 1;
1926 end Reverse_Iterate;
1928 -----------
1929 -- Right --
1930 -----------
1932 function Right (Node : Node_Access) return Node_Access is
1933 begin
1934 return Node.Right;
1935 end Right;
1937 ---------------
1938 -- Set_Color --
1939 ---------------
1941 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1942 begin
1943 Node.Color := Color;
1944 end Set_Color;
1946 --------------
1947 -- Set_Left --
1948 --------------
1950 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1951 begin
1952 Node.Left := Left;
1953 end Set_Left;
1955 ----------------
1956 -- Set_Parent --
1957 ----------------
1959 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1960 begin
1961 Node.Parent := Parent;
1962 end Set_Parent;
1964 ---------------
1965 -- Set_Right --
1966 ---------------
1968 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1969 begin
1970 Node.Right := Right;
1971 end Set_Right;
1973 --------------------------
1974 -- Symmetric_Difference --
1975 --------------------------
1977 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1978 begin
1979 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1980 end Symmetric_Difference;
1982 function Symmetric_Difference (Left, Right : Set) return Set is
1983 Tree : constant Tree_Type :=
1984 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1985 begin
1986 return Set'(Controlled with Tree);
1987 end Symmetric_Difference;
1989 ------------
1990 -- To_Set --
1991 ------------
1993 function To_Set (New_Item : Element_Type) return Set is
1994 Tree : Tree_Type;
1995 Node : Node_Access;
1996 pragma Unreferenced (Node);
1997 begin
1998 Insert_Sans_Hint (Tree, New_Item, Node);
1999 return Set'(Controlled with Tree);
2000 end To_Set;
2002 -----------
2003 -- Union --
2004 -----------
2006 procedure Union (Target : in out Set; Source : Set) is
2007 begin
2008 Set_Ops.Union (Target.Tree, Source.Tree);
2009 end Union;
2011 function Union (Left, Right : Set) return Set is
2012 Tree : constant Tree_Type :=
2013 Set_Ops.Union (Left.Tree, Right.Tree);
2014 begin
2015 return Set'(Controlled with Tree);
2016 end Union;
2018 -----------
2019 -- Write --
2020 -----------
2022 procedure Write
2023 (Stream : not null access Root_Stream_Type'Class;
2024 Container : Set)
2026 procedure Write_Node
2027 (Stream : not null access Root_Stream_Type'Class;
2028 Node : Node_Access);
2029 pragma Inline (Write_Node);
2031 procedure Write is
2032 new Tree_Operations.Generic_Write (Write_Node);
2034 ----------------
2035 -- Write_Node --
2036 ----------------
2038 procedure Write_Node
2039 (Stream : not null access Root_Stream_Type'Class;
2040 Node : Node_Access)
2042 begin
2043 Element_Type'Output (Stream, Node.Element.all);
2044 end Write_Node;
2046 -- Start of processing for Write
2048 begin
2049 Write (Stream, Container.Tree);
2050 end Write;
2052 procedure Write
2053 (Stream : not null access Root_Stream_Type'Class;
2054 Item : Cursor)
2056 begin
2057 raise Program_Error with "attempt to stream set cursor";
2058 end Write;
2060 end Ada.Containers.Indefinite_Ordered_Multisets;