PR rtl-optimization/82913
[official-gcc.git] / gcc / ada / libgnat / a-coorse.adb
blob428b9b93bd0e6c6fc430930f02c0bc751abceec8
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . O R D E R E D _ S E T S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2017, 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.Helpers; use Ada.Containers.Helpers;
34 with Ada.Containers.Red_Black_Trees.Generic_Operations;
35 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
37 with Ada.Containers.Red_Black_Trees.Generic_Keys;
38 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
40 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
41 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
43 with System; use type System.Address;
45 package body Ada.Containers.Ordered_Sets is
47 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
48 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
49 -- See comment in Ada.Containers.Helpers
51 ------------------------------
52 -- Access to Fields of Node --
53 ------------------------------
55 -- These subprograms provide functional notation for access to fields
56 -- of a node, and procedural notation for modifying these fields.
58 function Color (Node : Node_Access) return Color_Type;
59 pragma Inline (Color);
61 function Left (Node : Node_Access) return Node_Access;
62 pragma Inline (Left);
64 function Parent (Node : Node_Access) return Node_Access;
65 pragma Inline (Parent);
67 function Right (Node : Node_Access) return Node_Access;
68 pragma Inline (Right);
70 procedure Set_Color (Node : Node_Access; Color : Color_Type);
71 pragma Inline (Set_Color);
73 procedure Set_Left (Node : Node_Access; Left : Node_Access);
74 pragma Inline (Set_Left);
76 procedure Set_Right (Node : Node_Access; Right : Node_Access);
77 pragma Inline (Set_Right);
79 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
80 pragma Inline (Set_Parent);
82 -----------------------
83 -- Local Subprograms --
84 -----------------------
86 function Copy_Node (Source : Node_Access) return Node_Access;
87 pragma Inline (Copy_Node);
89 procedure Free (X : in out Node_Access);
91 procedure Insert_Sans_Hint
92 (Tree : in out Tree_Type;
93 New_Item : Element_Type;
94 Node : out Node_Access;
95 Inserted : out Boolean);
97 procedure Insert_With_Hint
98 (Dst_Tree : in out Tree_Type;
99 Dst_Hint : Node_Access;
100 Src_Node : Node_Access;
101 Dst_Node : out Node_Access);
103 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
104 pragma Inline (Is_Equal_Node_Node);
106 function Is_Greater_Element_Node
107 (Left : Element_Type;
108 Right : Node_Access) return Boolean;
109 pragma Inline (Is_Greater_Element_Node);
111 function Is_Less_Element_Node
112 (Left : Element_Type;
113 Right : Node_Access) return Boolean;
114 pragma Inline (Is_Less_Element_Node);
116 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
117 pragma Inline (Is_Less_Node_Node);
119 procedure Replace_Element
120 (Tree : in out Tree_Type;
121 Node : Node_Access;
122 Item : Element_Type);
124 --------------------------
125 -- Local Instantiations --
126 --------------------------
128 package Tree_Operations is
129 new Red_Black_Trees.Generic_Operations (Tree_Types);
131 procedure Delete_Tree is
132 new Tree_Operations.Generic_Delete_Tree (Free);
134 function Copy_Tree is
135 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
137 use Tree_Operations;
139 function Is_Equal is
140 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
142 package Element_Keys is
143 new Red_Black_Trees.Generic_Keys
144 (Tree_Operations => Tree_Operations,
145 Key_Type => Element_Type,
146 Is_Less_Key_Node => Is_Less_Element_Node,
147 Is_Greater_Key_Node => Is_Greater_Element_Node);
149 package Set_Ops is
150 new Generic_Set_Operations
151 (Tree_Operations => Tree_Operations,
152 Insert_With_Hint => Insert_With_Hint,
153 Copy_Tree => Copy_Tree,
154 Delete_Tree => Delete_Tree,
155 Is_Less => Is_Less_Node_Node,
156 Free => Free);
158 ---------
159 -- "<" --
160 ---------
162 function "<" (Left, Right : Cursor) return Boolean is
163 begin
164 if Checks and then Left.Node = null then
165 raise Constraint_Error with "Left cursor equals No_Element";
166 end if;
168 if Checks and then Right.Node = null then
169 raise Constraint_Error with "Right cursor equals No_Element";
170 end if;
172 pragma Assert (Vet (Left.Container.Tree, Left.Node),
173 "bad Left cursor in ""<""");
175 pragma Assert (Vet (Right.Container.Tree, Right.Node),
176 "bad Right cursor in ""<""");
178 return Left.Node.Element < Right.Node.Element;
179 end "<";
181 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
182 begin
183 if Checks and then Left.Node = null then
184 raise Constraint_Error with "Left cursor equals No_Element";
185 end if;
187 pragma Assert (Vet (Left.Container.Tree, Left.Node),
188 "bad Left cursor in ""<""");
190 return Left.Node.Element < Right;
191 end "<";
193 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
194 begin
195 if Checks and then Right.Node = null then
196 raise Constraint_Error with "Right cursor equals No_Element";
197 end if;
199 pragma Assert (Vet (Right.Container.Tree, Right.Node),
200 "bad Right cursor in ""<""");
202 return Left < Right.Node.Element;
203 end "<";
205 ---------
206 -- "=" --
207 ---------
209 function "=" (Left, Right : Set) return Boolean is
210 begin
211 return Is_Equal (Left.Tree, Right.Tree);
212 end "=";
214 ---------
215 -- ">" --
216 ---------
218 function ">" (Left, Right : Cursor) return Boolean is
219 begin
220 if Checks and then Left.Node = null then
221 raise Constraint_Error with "Left cursor equals No_Element";
222 end if;
224 if Checks and then Right.Node = null then
225 raise Constraint_Error with "Right cursor equals No_Element";
226 end if;
228 pragma Assert (Vet (Left.Container.Tree, Left.Node),
229 "bad Left cursor in "">""");
231 pragma Assert (Vet (Right.Container.Tree, Right.Node),
232 "bad Right cursor in "">""");
234 -- L > R same as R < L
236 return Right.Node.Element < Left.Node.Element;
237 end ">";
239 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
240 begin
241 if Checks and then Right.Node = null then
242 raise Constraint_Error with "Right cursor equals No_Element";
243 end if;
245 pragma Assert (Vet (Right.Container.Tree, Right.Node),
246 "bad Right cursor in "">""");
248 return Right.Node.Element < Left;
249 end ">";
251 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
252 begin
253 if Checks and then Left.Node = null then
254 raise Constraint_Error with "Left cursor equals No_Element";
255 end if;
257 pragma Assert (Vet (Left.Container.Tree, Left.Node),
258 "bad Left cursor in "">""");
260 return Right < Left.Node.Element;
261 end ">";
263 ------------
264 -- Adjust --
265 ------------
267 procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
269 procedure Adjust (Container : in out Set) is
270 begin
271 Adjust (Container.Tree);
272 end Adjust;
274 ------------
275 -- Assign --
276 ------------
278 procedure Assign (Target : in out Set; Source : Set) is
279 begin
280 if Target'Address = Source'Address then
281 return;
282 end if;
284 Target.Clear;
285 Target.Union (Source);
286 end Assign;
288 -------------
289 -- Ceiling --
290 -------------
292 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
293 Node : constant Node_Access :=
294 Element_Keys.Ceiling (Container.Tree, Item);
295 begin
296 return (if Node = null then No_Element
297 else Cursor'(Container'Unrestricted_Access, Node));
298 end Ceiling;
300 -----------
301 -- Clear --
302 -----------
304 procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
306 procedure Clear (Container : in out Set) is
307 begin
308 Clear (Container.Tree);
309 end Clear;
311 -----------
312 -- Color --
313 -----------
315 function Color (Node : Node_Access) return Color_Type is
316 begin
317 return Node.Color;
318 end Color;
320 ------------------------
321 -- Constant_Reference --
322 ------------------------
324 function Constant_Reference
325 (Container : aliased Set;
326 Position : Cursor) return Constant_Reference_Type
328 begin
329 if Checks and then Position.Container = null then
330 raise Constraint_Error with "Position cursor has no element";
331 end if;
333 if Checks and then Position.Container /= Container'Unrestricted_Access
334 then
335 raise Program_Error with
336 "Position cursor designates wrong container";
337 end if;
339 pragma Assert
340 (Vet (Container.Tree, Position.Node),
341 "bad cursor in Constant_Reference");
343 declare
344 Tree : Tree_Type renames Position.Container.all.Tree;
345 TC : constant Tamper_Counts_Access :=
346 Tree.TC'Unrestricted_Access;
347 begin
348 return R : constant Constant_Reference_Type :=
349 (Element => Position.Node.Element'Access,
350 Control => (Controlled with TC))
352 Lock (TC.all);
353 end return;
354 end;
355 end Constant_Reference;
357 --------------
358 -- Contains --
359 --------------
361 function Contains
362 (Container : Set;
363 Item : Element_Type) return Boolean
365 begin
366 return Find (Container, Item) /= No_Element;
367 end Contains;
369 ----------
370 -- Copy --
371 ----------
373 function Copy (Source : Set) return Set is
374 begin
375 return Target : Set do
376 Target.Assign (Source);
377 end return;
378 end Copy;
380 ---------------
381 -- Copy_Node --
382 ---------------
384 function Copy_Node (Source : Node_Access) return Node_Access is
385 Target : constant Node_Access :=
386 new Node_Type'(Parent => null,
387 Left => null,
388 Right => null,
389 Color => Source.Color,
390 Element => Source.Element);
391 begin
392 return Target;
393 end Copy_Node;
395 ------------
396 -- Delete --
397 ------------
399 procedure Delete (Container : in out Set; Position : in out Cursor) is
400 begin
401 if Checks and then Position.Node = null then
402 raise Constraint_Error with "Position cursor equals No_Element";
403 end if;
405 if Checks and then Position.Container /= Container'Unrestricted_Access
406 then
407 raise Program_Error with "Position cursor designates wrong set";
408 end if;
410 pragma Assert (Vet (Container.Tree, Position.Node),
411 "bad cursor in Delete");
413 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
414 Free (Position.Node);
415 Position.Container := null;
416 end Delete;
418 procedure Delete (Container : in out Set; Item : Element_Type) is
419 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
421 begin
422 if Checks and then X = null then
423 raise Constraint_Error with "attempt to delete element not in set";
424 end if;
426 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
427 Free (X);
428 end Delete;
430 ------------------
431 -- Delete_First --
432 ------------------
434 procedure Delete_First (Container : in out Set) is
435 Tree : Tree_Type renames Container.Tree;
436 X : Node_Access := Tree.First;
437 begin
438 if X /= null then
439 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
440 Free (X);
441 end if;
442 end Delete_First;
444 -----------------
445 -- Delete_Last --
446 -----------------
448 procedure Delete_Last (Container : in out Set) is
449 Tree : Tree_Type renames Container.Tree;
450 X : Node_Access := Tree.Last;
451 begin
452 if X /= null then
453 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
454 Free (X);
455 end if;
456 end Delete_Last;
458 ----------------
459 -- Difference --
460 ----------------
462 procedure Difference (Target : in out Set; Source : Set) is
463 begin
464 Set_Ops.Difference (Target.Tree, Source.Tree);
465 end Difference;
467 function Difference (Left, Right : Set) return Set is
468 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
469 begin
470 return Set'(Controlled with Tree);
471 end Difference;
473 -------------
474 -- Element --
475 -------------
477 function Element (Position : Cursor) return Element_Type is
478 begin
479 if Checks and then Position.Node = null then
480 raise Constraint_Error with "Position cursor equals No_Element";
481 end if;
483 pragma Assert (Vet (Position.Container.Tree, Position.Node),
484 "bad cursor in Element");
486 return Position.Node.Element;
487 end Element;
489 -------------------------
490 -- Equivalent_Elements --
491 -------------------------
493 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
494 begin
495 return (if Left < Right or else Right < Left then False else True);
496 end Equivalent_Elements;
498 ---------------------
499 -- Equivalent_Sets --
500 ---------------------
502 function Equivalent_Sets (Left, Right : Set) return Boolean is
503 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
504 pragma Inline (Is_Equivalent_Node_Node);
506 function Is_Equivalent is
507 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
509 -----------------------------
510 -- Is_Equivalent_Node_Node --
511 -----------------------------
513 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
514 begin
515 return (if L.Element < R.Element then False
516 elsif R.Element < L.Element then False
517 else True);
518 end Is_Equivalent_Node_Node;
520 -- Start of processing for Equivalent_Sets
522 begin
523 return Is_Equivalent (Left.Tree, Right.Tree);
524 end Equivalent_Sets;
526 -------------
527 -- Exclude --
528 -------------
530 procedure Exclude (Container : in out Set; Item : Element_Type) is
531 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
533 begin
534 if X /= null then
535 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
536 Free (X);
537 end if;
538 end Exclude;
540 --------------
541 -- Finalize --
542 --------------
544 procedure Finalize (Object : in out Iterator) is
545 begin
546 if Object.Container /= null then
547 Unbusy (Object.Container.Tree.TC);
548 end if;
549 end Finalize;
551 ----------
552 -- Find --
553 ----------
555 function Find (Container : Set; Item : Element_Type) return Cursor is
556 Node : constant Node_Access := Element_Keys.Find (Container.Tree, Item);
557 begin
558 return (if Node = null then No_Element
559 else Cursor'(Container'Unrestricted_Access, Node));
560 end Find;
562 -----------
563 -- First --
564 -----------
566 function First (Container : Set) return Cursor is
567 begin
568 return
569 (if Container.Tree.First = null then No_Element
570 else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
571 end First;
573 function First (Object : Iterator) return Cursor is
574 begin
575 -- The value of the iterator object's Node component influences the
576 -- behavior of the First (and Last) selector function.
578 -- When the Node component is null, this means the iterator object was
579 -- constructed without a start expression, in which case the (forward)
580 -- iteration starts from the (logical) beginning of the entire sequence
581 -- of items (corresponding to Container.First, for a forward iterator).
583 -- Otherwise, this is iteration over a partial sequence of items. When
584 -- the Node component is non-null, the iterator object was constructed
585 -- with a start expression, that specifies the position from which the
586 -- (forward) partial iteration begins.
588 if Object.Node = null then
589 return Object.Container.First;
590 else
591 return Cursor'(Object.Container, Object.Node);
592 end if;
593 end First;
595 -------------------
596 -- First_Element --
597 -------------------
599 function First_Element (Container : Set) return Element_Type is
600 begin
601 if Checks and then Container.Tree.First = null then
602 raise Constraint_Error with "set is empty";
603 end if;
605 return Container.Tree.First.Element;
606 end First_Element;
608 -----------
609 -- Floor --
610 -----------
612 function Floor (Container : Set; Item : Element_Type) return Cursor is
613 Node : constant Node_Access := Element_Keys.Floor (Container.Tree, Item);
614 begin
615 return (if Node = null then No_Element
616 else Cursor'(Container'Unrestricted_Access, Node));
617 end Floor;
619 ----------
620 -- Free --
621 ----------
623 procedure Free (X : in out Node_Access) is
624 procedure Deallocate is
625 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
626 begin
627 if X /= null then
628 X.Parent := X;
629 X.Left := X;
630 X.Right := X;
631 Deallocate (X);
632 end if;
633 end Free;
635 ------------------
636 -- Generic_Keys --
637 ------------------
639 package body Generic_Keys is
641 -----------------------
642 -- Local Subprograms --
643 -----------------------
645 function Is_Greater_Key_Node
646 (Left : Key_Type;
647 Right : Node_Access) return Boolean;
648 pragma Inline (Is_Greater_Key_Node);
650 function Is_Less_Key_Node
651 (Left : Key_Type;
652 Right : Node_Access) return Boolean;
653 pragma Inline (Is_Less_Key_Node);
655 --------------------------
656 -- Local Instantiations --
657 --------------------------
659 package Key_Keys is
660 new Red_Black_Trees.Generic_Keys
661 (Tree_Operations => Tree_Operations,
662 Key_Type => Key_Type,
663 Is_Less_Key_Node => Is_Less_Key_Node,
664 Is_Greater_Key_Node => Is_Greater_Key_Node);
666 -------------
667 -- Ceiling --
668 -------------
670 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
671 Node : constant Node_Access := Key_Keys.Ceiling (Container.Tree, Key);
672 begin
673 return (if Node = null then No_Element
674 else Cursor'(Container'Unrestricted_Access, Node));
675 end Ceiling;
677 ------------------------
678 -- Constant_Reference --
679 ------------------------
681 function Constant_Reference
682 (Container : aliased Set;
683 Key : Key_Type) return Constant_Reference_Type
685 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
687 begin
688 if Checks and then Node = null then
689 raise Constraint_Error with "key not in set";
690 end if;
692 declare
693 Tree : Tree_Type renames Container'Unrestricted_Access.all.Tree;
694 TC : constant Tamper_Counts_Access :=
695 Tree.TC'Unrestricted_Access;
696 begin
697 return R : constant Constant_Reference_Type :=
698 (Element => Node.Element'Access,
699 Control => (Controlled with TC))
701 Lock (TC.all);
702 end return;
703 end;
704 end Constant_Reference;
706 --------------
707 -- Contains --
708 --------------
710 function Contains (Container : Set; Key : Key_Type) return Boolean is
711 begin
712 return Find (Container, Key) /= No_Element;
713 end Contains;
715 ------------
716 -- Delete --
717 ------------
719 procedure Delete (Container : in out Set; Key : Key_Type) is
720 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
722 begin
723 if Checks and then X = null then
724 raise Constraint_Error with "attempt to delete key not in set";
725 end if;
727 Delete_Node_Sans_Free (Container.Tree, X);
728 Free (X);
729 end Delete;
731 -------------
732 -- Element --
733 -------------
735 function Element (Container : Set; Key : Key_Type) return Element_Type is
736 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
738 begin
739 if Checks and then Node = null then
740 raise Constraint_Error with "key not in set";
741 end if;
743 return Node.Element;
744 end Element;
746 ---------------------
747 -- Equivalent_Keys --
748 ---------------------
750 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
751 begin
752 return (if Left < Right or else Right < Left then False else True);
753 end Equivalent_Keys;
755 -------------
756 -- Exclude --
757 -------------
759 procedure Exclude (Container : in out Set; Key : Key_Type) is
760 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
761 begin
762 if X /= null then
763 Delete_Node_Sans_Free (Container.Tree, X);
764 Free (X);
765 end if;
766 end Exclude;
768 --------------
769 -- Finalize --
770 --------------
772 procedure Finalize (Control : in out Reference_Control_Type) is
773 begin
774 if Control.Container /= null then
775 Impl.Reference_Control_Type (Control).Finalize;
777 if Checks and then not (Key (Control.Pos) = Control.Old_Key.all)
778 then
779 Delete (Control.Container.all, Key (Control.Pos));
780 raise Program_Error;
781 end if;
783 Control.Container := null;
784 Control.Old_Key := null;
785 end if;
786 end Finalize;
788 ----------
789 -- Find --
790 ----------
792 function Find (Container : Set; Key : Key_Type) return Cursor is
793 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
794 begin
795 return (if Node = null then No_Element
796 else Cursor'(Container'Unrestricted_Access, Node));
797 end Find;
799 -----------
800 -- Floor --
801 -----------
803 function Floor (Container : Set; Key : Key_Type) return Cursor is
804 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
805 begin
806 return (if Node = null then No_Element
807 else Cursor'(Container'Unrestricted_Access, Node));
808 end Floor;
810 -------------------------
811 -- Is_Greater_Key_Node --
812 -------------------------
814 function Is_Greater_Key_Node
815 (Left : Key_Type;
816 Right : Node_Access) return Boolean
818 begin
819 return Key (Right.Element) < Left;
820 end Is_Greater_Key_Node;
822 ----------------------
823 -- Is_Less_Key_Node --
824 ----------------------
826 function Is_Less_Key_Node
827 (Left : Key_Type;
828 Right : Node_Access) return Boolean
830 begin
831 return Left < Key (Right.Element);
832 end Is_Less_Key_Node;
834 ---------
835 -- Key --
836 ---------
838 function Key (Position : Cursor) return Key_Type is
839 begin
840 if Checks and then Position.Node = null then
841 raise Constraint_Error with
842 "Position cursor equals No_Element";
843 end if;
845 pragma Assert (Vet (Position.Container.Tree, Position.Node),
846 "bad cursor in Key");
848 return Key (Position.Node.Element);
849 end Key;
851 ----------
852 -- Read --
853 ----------
855 procedure Read
856 (Stream : not null access Root_Stream_Type'Class;
857 Item : out Reference_Type)
859 begin
860 raise Program_Error with "attempt to stream reference";
861 end Read;
863 ------------------------------
864 -- Reference_Preserving_Key --
865 ------------------------------
867 function Reference_Preserving_Key
868 (Container : aliased in out Set;
869 Position : Cursor) return Reference_Type
871 begin
872 if Checks and then Position.Container = null then
873 raise Constraint_Error with "Position cursor has no element";
874 end if;
876 if Checks and then Position.Container /= Container'Unrestricted_Access
877 then
878 raise Program_Error with
879 "Position cursor designates wrong container";
880 end if;
882 pragma Assert
883 (Vet (Container.Tree, Position.Node),
884 "bad cursor in function Reference_Preserving_Key");
886 declare
887 Tree : Tree_Type renames Container.Tree;
888 begin
889 return R : constant Reference_Type :=
890 (Element => Position.Node.Element'Access,
891 Control =>
892 (Controlled with
893 Tree.TC'Unrestricted_Access,
894 Container => Container'Access,
895 Pos => Position,
896 Old_Key => new Key_Type'(Key (Position))))
898 Lock (Tree.TC);
899 end return;
900 end;
901 end Reference_Preserving_Key;
903 function Reference_Preserving_Key
904 (Container : aliased in out Set;
905 Key : Key_Type) return Reference_Type
907 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
909 begin
910 if Checks and then Node = null then
911 raise Constraint_Error with "Key not in set";
912 end if;
914 declare
915 Tree : Tree_Type renames Container.Tree;
916 begin
917 return R : constant Reference_Type :=
918 (Element => Node.Element'Access,
919 Control =>
920 (Controlled with
921 Tree.TC'Unrestricted_Access,
922 Container => Container'Access,
923 Pos => Find (Container, Key),
924 Old_Key => new Key_Type'(Key)))
926 Lock (Tree.TC);
927 end return;
928 end;
929 end Reference_Preserving_Key;
931 -------------
932 -- Replace --
933 -------------
935 procedure Replace
936 (Container : in out Set;
937 Key : Key_Type;
938 New_Item : Element_Type)
940 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
942 begin
943 if Checks and then Node = null then
944 raise Constraint_Error with
945 "attempt to replace key not in set";
946 end if;
948 Replace_Element (Container.Tree, Node, New_Item);
949 end Replace;
951 -----------------------------------
952 -- Update_Element_Preserving_Key --
953 -----------------------------------
955 procedure Update_Element_Preserving_Key
956 (Container : in out Set;
957 Position : Cursor;
958 Process : not null access procedure (Element : in out Element_Type))
960 Tree : Tree_Type renames Container.Tree;
962 begin
963 if Checks and then Position.Node = null then
964 raise Constraint_Error with
965 "Position cursor equals No_Element";
966 end if;
968 if Checks and then Position.Container /= Container'Unrestricted_Access
969 then
970 raise Program_Error with
971 "Position cursor designates wrong set";
972 end if;
974 pragma Assert (Vet (Container.Tree, Position.Node),
975 "bad cursor in Update_Element_Preserving_Key");
977 declare
978 E : Element_Type renames Position.Node.Element;
979 K : constant Key_Type := Key (E);
980 Lock : With_Lock (Tree.TC'Unrestricted_Access);
981 begin
982 Process (E);
983 if Equivalent_Keys (K, Key (E)) then
984 return;
985 end if;
986 end;
988 declare
989 X : Node_Access := Position.Node;
990 begin
991 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
992 Free (X);
993 end;
995 raise Program_Error with "key was modified";
996 end Update_Element_Preserving_Key;
998 -----------
999 -- Write --
1000 -----------
1002 procedure Write
1003 (Stream : not null access Root_Stream_Type'Class;
1004 Item : Reference_Type)
1006 begin
1007 raise Program_Error with "attempt to stream reference";
1008 end Write;
1010 end Generic_Keys;
1012 ------------------------
1013 -- Get_Element_Access --
1014 ------------------------
1016 function Get_Element_Access
1017 (Position : Cursor) return not null Element_Access is
1018 begin
1019 return Position.Node.Element'Access;
1020 end Get_Element_Access;
1022 -----------------
1023 -- Has_Element --
1024 -----------------
1026 function Has_Element (Position : Cursor) return Boolean is
1027 begin
1028 return Position /= No_Element;
1029 end Has_Element;
1031 -------------
1032 -- Include --
1033 -------------
1035 procedure Include (Container : in out Set; New_Item : Element_Type) is
1036 Position : Cursor;
1037 Inserted : Boolean;
1039 begin
1040 Insert (Container, New_Item, Position, Inserted);
1042 if not Inserted then
1043 TE_Check (Container.Tree.TC);
1045 Position.Node.Element := New_Item;
1046 end if;
1047 end Include;
1049 ------------
1050 -- Insert --
1051 ------------
1053 procedure Insert
1054 (Container : in out Set;
1055 New_Item : Element_Type;
1056 Position : out Cursor;
1057 Inserted : out Boolean)
1059 begin
1060 Insert_Sans_Hint
1061 (Container.Tree,
1062 New_Item,
1063 Position.Node,
1064 Inserted);
1066 Position.Container := Container'Unrestricted_Access;
1067 end Insert;
1069 procedure Insert
1070 (Container : in out Set;
1071 New_Item : Element_Type)
1073 Position : Cursor;
1074 pragma Unreferenced (Position);
1076 Inserted : Boolean;
1078 begin
1079 Insert (Container, New_Item, Position, Inserted);
1081 if Checks and then not Inserted then
1082 raise Constraint_Error with
1083 "attempt to insert element already in set";
1084 end if;
1085 end Insert;
1087 ----------------------
1088 -- Insert_Sans_Hint --
1089 ----------------------
1091 procedure Insert_Sans_Hint
1092 (Tree : in out Tree_Type;
1093 New_Item : Element_Type;
1094 Node : out Node_Access;
1095 Inserted : out Boolean)
1097 function New_Node return Node_Access;
1098 pragma Inline (New_Node);
1100 procedure Insert_Post is
1101 new Element_Keys.Generic_Insert_Post (New_Node);
1103 procedure Conditional_Insert_Sans_Hint is
1104 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1106 --------------
1107 -- New_Node --
1108 --------------
1110 function New_Node return Node_Access is
1111 begin
1112 return new Node_Type'(Parent => null,
1113 Left => null,
1114 Right => null,
1115 Color => Red_Black_Trees.Red,
1116 Element => New_Item);
1117 end New_Node;
1119 -- Start of processing for Insert_Sans_Hint
1121 begin
1122 Conditional_Insert_Sans_Hint
1123 (Tree,
1124 New_Item,
1125 Node,
1126 Inserted);
1127 end Insert_Sans_Hint;
1129 ----------------------
1130 -- Insert_With_Hint --
1131 ----------------------
1133 procedure Insert_With_Hint
1134 (Dst_Tree : in out Tree_Type;
1135 Dst_Hint : Node_Access;
1136 Src_Node : Node_Access;
1137 Dst_Node : out Node_Access)
1139 Success : Boolean;
1140 pragma Unreferenced (Success);
1142 function New_Node return Node_Access;
1143 pragma Inline (New_Node);
1145 procedure Insert_Post is
1146 new Element_Keys.Generic_Insert_Post (New_Node);
1148 procedure Insert_Sans_Hint is
1149 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1151 procedure Local_Insert_With_Hint is
1152 new Element_Keys.Generic_Conditional_Insert_With_Hint
1153 (Insert_Post,
1154 Insert_Sans_Hint);
1156 --------------
1157 -- New_Node --
1158 --------------
1160 function New_Node return Node_Access is
1161 Node : constant Node_Access :=
1162 new Node_Type'(Parent => null,
1163 Left => null,
1164 Right => null,
1165 Color => Red,
1166 Element => Src_Node.Element);
1167 begin
1168 return Node;
1169 end New_Node;
1171 -- Start of processing for Insert_With_Hint
1173 begin
1174 Local_Insert_With_Hint
1175 (Dst_Tree,
1176 Dst_Hint,
1177 Src_Node.Element,
1178 Dst_Node,
1179 Success);
1180 end Insert_With_Hint;
1182 ------------------
1183 -- Intersection --
1184 ------------------
1186 procedure Intersection (Target : in out Set; Source : Set) is
1187 begin
1188 Set_Ops.Intersection (Target.Tree, Source.Tree);
1189 end Intersection;
1191 function Intersection (Left, Right : Set) return Set is
1192 Tree : constant Tree_Type :=
1193 Set_Ops.Intersection (Left.Tree, Right.Tree);
1194 begin
1195 return Set'(Controlled with Tree);
1196 end Intersection;
1198 --------------
1199 -- Is_Empty --
1200 --------------
1202 function Is_Empty (Container : Set) return Boolean is
1203 begin
1204 return Container.Tree.Length = 0;
1205 end Is_Empty;
1207 ------------------------
1208 -- Is_Equal_Node_Node --
1209 ------------------------
1211 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1212 begin
1213 return L.Element = R.Element;
1214 end Is_Equal_Node_Node;
1216 -----------------------------
1217 -- Is_Greater_Element_Node --
1218 -----------------------------
1220 function Is_Greater_Element_Node
1221 (Left : Element_Type;
1222 Right : Node_Access) return Boolean
1224 begin
1225 -- Compute e > node same as node < e
1227 return Right.Element < Left;
1228 end Is_Greater_Element_Node;
1230 --------------------------
1231 -- Is_Less_Element_Node --
1232 --------------------------
1234 function Is_Less_Element_Node
1235 (Left : Element_Type;
1236 Right : Node_Access) return Boolean
1238 begin
1239 return Left < Right.Element;
1240 end Is_Less_Element_Node;
1242 -----------------------
1243 -- Is_Less_Node_Node --
1244 -----------------------
1246 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1247 begin
1248 return L.Element < R.Element;
1249 end Is_Less_Node_Node;
1251 ---------------
1252 -- Is_Subset --
1253 ---------------
1255 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1256 begin
1257 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1258 end Is_Subset;
1260 -------------
1261 -- Iterate --
1262 -------------
1264 procedure Iterate
1265 (Container : Set;
1266 Process : not null access procedure (Position : Cursor))
1268 procedure Process_Node (Node : Node_Access);
1269 pragma Inline (Process_Node);
1271 procedure Local_Iterate is
1272 new Tree_Operations.Generic_Iteration (Process_Node);
1274 ------------------
1275 -- Process_Node --
1276 ------------------
1278 procedure Process_Node (Node : Node_Access) is
1279 begin
1280 Process (Cursor'(Container'Unrestricted_Access, Node));
1281 end Process_Node;
1283 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
1284 Busy : With_Busy (T.TC'Unrestricted_Access);
1286 -- Start of processing for Iterate
1288 begin
1289 Local_Iterate (T);
1290 end Iterate;
1292 function Iterate (Container : Set)
1293 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1295 begin
1296 -- The value of the Node component influences the behavior of the First
1297 -- and Last selector functions of the iterator object. When the Node
1298 -- component is null (as is the case here), this means the iterator
1299 -- object was constructed without a start expression. This is a complete
1300 -- iterator, meaning that the iteration starts from the (logical)
1301 -- beginning of the sequence of items.
1303 -- Note: For a forward iterator, Container.First is the beginning, and
1304 -- for a reverse iterator, Container.Last is the beginning.
1306 Busy (Container.Tree.TC'Unrestricted_Access.all);
1308 return It : constant Iterator :=
1309 Iterator'(Limited_Controlled with
1310 Container => Container'Unrestricted_Access,
1311 Node => null);
1312 end Iterate;
1314 function Iterate (Container : Set; Start : Cursor)
1315 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1317 begin
1318 -- It was formerly the case that when Start = No_Element, the partial
1319 -- iterator was defined to behave the same as for a complete iterator,
1320 -- and iterate over the entire sequence of items. However, those
1321 -- semantics were unintuitive and arguably error-prone (it is too easy
1322 -- to accidentally create an endless loop), and so they were changed,
1323 -- per the ARG meeting in Denver on 2011/11. However, there was no
1324 -- consensus about what positive meaning this corner case should have,
1325 -- and so it was decided to simply raise an exception. This does imply,
1326 -- however, that it is not possible to use a partial iterator to specify
1327 -- an empty sequence of items.
1329 if Checks and then Start = No_Element then
1330 raise Constraint_Error with
1331 "Start position for iterator equals No_Element";
1332 end if;
1334 if Checks and then Start.Container /= Container'Unrestricted_Access then
1335 raise Program_Error with
1336 "Start cursor of Iterate designates wrong set";
1337 end if;
1339 pragma Assert (Vet (Container.Tree, Start.Node),
1340 "Start cursor of Iterate is bad");
1342 -- The value of the Node component influences the behavior of the First
1343 -- and Last selector functions of the iterator object. When the Node
1344 -- component is non-null (as is the case here), it means that this is a
1345 -- partial iteration, over a subset of the complete sequence of
1346 -- items. The iterator object was constructed with a start expression,
1347 -- indicating the position from which the iteration begins. Note that
1348 -- the start position has the same value irrespective of whether this is
1349 -- a forward or reverse iteration.
1351 Busy (Container.Tree.TC'Unrestricted_Access.all);
1353 return It : constant Iterator :=
1354 Iterator'(Limited_Controlled with
1355 Container => Container'Unrestricted_Access,
1356 Node => Start.Node);
1357 end Iterate;
1359 ----------
1360 -- Last --
1361 ----------
1363 function Last (Container : Set) return Cursor is
1364 begin
1365 return
1366 (if Container.Tree.Last = null then No_Element
1367 else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
1368 end Last;
1370 function Last (Object : Iterator) return Cursor is
1371 begin
1372 -- The value of the iterator object's Node component influences the
1373 -- behavior of the Last (and First) selector function.
1375 -- When the Node component is null, this means the iterator object was
1376 -- constructed without a start expression, in which case the (reverse)
1377 -- iteration starts from the (logical) beginning of the entire sequence
1378 -- (corresponding to Container.Last, for a reverse iterator).
1380 -- Otherwise, this is iteration over a partial sequence of items. When
1381 -- the Node component is non-null, the iterator object was constructed
1382 -- with a start expression, that specifies the position from which the
1383 -- (reverse) partial iteration begins.
1385 if Object.Node = null then
1386 return Object.Container.Last;
1387 else
1388 return Cursor'(Object.Container, Object.Node);
1389 end if;
1390 end Last;
1392 ------------------
1393 -- Last_Element --
1394 ------------------
1396 function Last_Element (Container : Set) return Element_Type is
1397 begin
1398 if Checks and then Container.Tree.Last = null then
1399 raise Constraint_Error with "set is empty";
1400 end if;
1402 return Container.Tree.Last.Element;
1403 end Last_Element;
1405 ----------
1406 -- Left --
1407 ----------
1409 function Left (Node : Node_Access) return Node_Access is
1410 begin
1411 return Node.Left;
1412 end Left;
1414 ------------
1415 -- Length --
1416 ------------
1418 function Length (Container : Set) return Count_Type is
1419 begin
1420 return Container.Tree.Length;
1421 end Length;
1423 ----------
1424 -- Move --
1425 ----------
1427 procedure Move is new Tree_Operations.Generic_Move (Clear);
1429 procedure Move (Target : in out Set; Source : in out Set) is
1430 begin
1431 Move (Target => Target.Tree, Source => Source.Tree);
1432 end Move;
1434 ----------
1435 -- Next --
1436 ----------
1438 function Next (Position : Cursor) return Cursor is
1439 begin
1440 if Position = No_Element then
1441 return No_Element;
1442 end if;
1444 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1445 "bad cursor in Next");
1447 declare
1448 Node : constant Node_Access :=
1449 Tree_Operations.Next (Position.Node);
1450 begin
1451 return (if Node = null then No_Element
1452 else Cursor'(Position.Container, Node));
1453 end;
1454 end Next;
1456 procedure Next (Position : in out Cursor) is
1457 begin
1458 Position := Next (Position);
1459 end Next;
1461 function Next (Object : Iterator; Position : Cursor) return Cursor is
1462 begin
1463 if Position.Container = null then
1464 return No_Element;
1465 end if;
1467 if Checks and then Position.Container /= Object.Container then
1468 raise Program_Error with
1469 "Position cursor of Next designates wrong set";
1470 end if;
1472 return Next (Position);
1473 end Next;
1475 -------------
1476 -- Overlap --
1477 -------------
1479 function Overlap (Left, Right : Set) return Boolean is
1480 begin
1481 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1482 end Overlap;
1484 ------------
1485 -- Parent --
1486 ------------
1488 function Parent (Node : Node_Access) return Node_Access is
1489 begin
1490 return Node.Parent;
1491 end Parent;
1493 --------------
1494 -- Previous --
1495 --------------
1497 function Previous (Position : Cursor) return Cursor is
1498 begin
1499 if Position = No_Element then
1500 return No_Element;
1501 end if;
1503 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1504 "bad cursor in Previous");
1506 declare
1507 Node : constant Node_Access :=
1508 Tree_Operations.Previous (Position.Node);
1509 begin
1510 return (if Node = null then No_Element
1511 else Cursor'(Position.Container, Node));
1512 end;
1513 end Previous;
1515 procedure Previous (Position : in out Cursor) is
1516 begin
1517 Position := Previous (Position);
1518 end Previous;
1520 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1521 begin
1522 if Position.Container = null then
1523 return No_Element;
1524 end if;
1526 if Checks and then Position.Container /= Object.Container then
1527 raise Program_Error with
1528 "Position cursor of Previous designates wrong set";
1529 end if;
1531 return Previous (Position);
1532 end Previous;
1534 ----------------------
1535 -- Pseudo_Reference --
1536 ----------------------
1538 function Pseudo_Reference
1539 (Container : aliased Set'Class) return Reference_Control_Type
1541 TC : constant Tamper_Counts_Access :=
1542 Container.Tree.TC'Unrestricted_Access;
1543 begin
1544 return R : constant Reference_Control_Type := (Controlled with TC) do
1545 Lock (TC.all);
1546 end return;
1547 end Pseudo_Reference;
1549 -------------------
1550 -- Query_Element --
1551 -------------------
1553 procedure Query_Element
1554 (Position : Cursor;
1555 Process : not null access procedure (Element : Element_Type))
1557 begin
1558 if Checks and then Position.Node = null then
1559 raise Constraint_Error with "Position cursor equals No_Element";
1560 end if;
1562 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1563 "bad cursor in Query_Element");
1565 declare
1566 T : Tree_Type renames Position.Container.Tree;
1567 Lock : With_Lock (T.TC'Unrestricted_Access);
1568 begin
1569 Process (Position.Node.Element);
1570 end;
1571 end Query_Element;
1573 ----------
1574 -- Read --
1575 ----------
1577 procedure Read
1578 (Stream : not null access Root_Stream_Type'Class;
1579 Container : out Set)
1581 function Read_Node
1582 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1583 pragma Inline (Read_Node);
1585 procedure Read is
1586 new Tree_Operations.Generic_Read (Clear, Read_Node);
1588 ---------------
1589 -- Read_Node --
1590 ---------------
1592 function Read_Node
1593 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1595 Node : Node_Access := new Node_Type;
1596 begin
1597 Element_Type'Read (Stream, Node.Element);
1598 return Node;
1599 exception
1600 when others =>
1601 Free (Node);
1602 raise;
1603 end Read_Node;
1605 -- Start of processing for Read
1607 begin
1608 Read (Stream, Container.Tree);
1609 end Read;
1611 procedure Read
1612 (Stream : not null access Root_Stream_Type'Class;
1613 Item : out Cursor)
1615 begin
1616 raise Program_Error with "attempt to stream set cursor";
1617 end Read;
1619 procedure Read
1620 (Stream : not null access Root_Stream_Type'Class;
1621 Item : out Constant_Reference_Type)
1623 begin
1624 raise Program_Error with "attempt to stream reference";
1625 end Read;
1627 -------------
1628 -- Replace --
1629 -------------
1631 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1632 Node : constant Node_Access :=
1633 Element_Keys.Find (Container.Tree, New_Item);
1635 begin
1636 if Checks and then Node = null then
1637 raise Constraint_Error with
1638 "attempt to replace element not in set";
1639 end if;
1641 TE_Check (Container.Tree.TC);
1643 Node.Element := New_Item;
1644 end Replace;
1646 ---------------------
1647 -- Replace_Element --
1648 ---------------------
1650 procedure Replace_Element
1651 (Tree : in out Tree_Type;
1652 Node : Node_Access;
1653 Item : Element_Type)
1655 pragma Assert (Node /= null);
1657 function New_Node return Node_Access;
1658 pragma Inline (New_Node);
1660 procedure Local_Insert_Post is
1661 new Element_Keys.Generic_Insert_Post (New_Node);
1663 procedure Local_Insert_Sans_Hint is
1664 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1666 procedure Local_Insert_With_Hint is
1667 new Element_Keys.Generic_Conditional_Insert_With_Hint
1668 (Local_Insert_Post,
1669 Local_Insert_Sans_Hint);
1671 --------------
1672 -- New_Node --
1673 --------------
1675 function New_Node return Node_Access is
1676 begin
1677 Node.Element := Item;
1678 Node.Color := Red;
1679 Node.Parent := null;
1680 Node.Right := null;
1681 Node.Left := null;
1682 return Node;
1683 end New_Node;
1685 Hint : Node_Access;
1686 Result : Node_Access;
1687 Inserted : Boolean;
1688 Compare : Boolean;
1690 -- Start of processing for Replace_Element
1692 begin
1693 -- Replace_Element assigns value Item to the element designated by Node,
1694 -- per certain semantic constraints.
1696 -- If Item is equivalent to the element, then element is replaced and
1697 -- there's nothing else to do. This is the easy case.
1699 -- If Item is not equivalent, then the node will (possibly) have to move
1700 -- to some other place in the tree. This is slighly more complicated,
1701 -- because we must ensure that Item is not equivalent to some other
1702 -- element in the tree (in which case, the replacement is not allowed).
1704 -- Determine whether Item is equivalent to element on the specified
1705 -- node.
1707 declare
1708 Lock : With_Lock (Tree.TC'Unrestricted_Access);
1709 begin
1710 Compare := (if Item < Node.Element then False
1711 elsif Node.Element < Item then False
1712 else True);
1713 end;
1715 if Compare then
1716 -- Item is equivalent to the node's element, so we will not have to
1717 -- move the node.
1719 TE_Check (Tree.TC);
1721 Node.Element := Item;
1722 return;
1723 end if;
1725 -- The replacement Item is not equivalent to the element on the
1726 -- specified node, which means that it will need to be re-inserted in a
1727 -- different position in the tree. We must now determine whether Item is
1728 -- equivalent to some other element in the tree (which would prohibit
1729 -- the assignment and hence the move).
1731 -- Ceiling returns the smallest element equivalent or greater than the
1732 -- specified Item; if there is no such element, then it returns null.
1734 Hint := Element_Keys.Ceiling (Tree, Item);
1736 if Hint /= null then
1737 declare
1738 Lock : With_Lock (Tree.TC'Unrestricted_Access);
1739 begin
1740 Compare := Item < Hint.Element;
1741 end;
1743 -- Item >= Hint.Element
1745 if Checks and then not Compare then
1747 -- Ceiling returns an element that is equivalent or greater
1748 -- than Item. If Item is "not less than" the element, then
1749 -- by elimination we know that Item is equivalent to the element.
1751 -- But this means that it is not possible to assign the value of
1752 -- Item to the specified element (on Node), because a different
1753 -- element (on Hint) equivalent to Item already exsits. (Were we
1754 -- to change Node's element value, we would have to move Node, but
1755 -- we would be unable to move the Node, because its new position
1756 -- in the tree is already occupied by an equivalent element.)
1758 raise Program_Error with "attempt to replace existing element";
1759 end if;
1761 -- Item is not equivalent to any other element in the tree, so it is
1762 -- safe to assign the value of Item to Node.Element. This means that
1763 -- the node will have to move to a different position in the tree
1764 -- (because its element will have a different value).
1766 -- The nearest (greater) neighbor of Item is Hint. This will be the
1767 -- insertion position of Node (because its element will have Item as
1768 -- its new value).
1770 -- If Node equals Hint, the relative position of Node does not
1771 -- change. This allows us to perform an optimization: we need not
1772 -- remove Node from the tree and then reinsert it with its new value,
1773 -- because it would only be placed in the exact same position.
1775 if Hint = Node then
1776 TE_Check (Tree.TC);
1778 Node.Element := Item;
1779 return;
1780 end if;
1781 end if;
1783 -- If we get here, it is because Item was greater than all elements in
1784 -- the tree (Hint = null), or because Item was less than some element at
1785 -- a different place in the tree (Item < Hint.Element). In either case,
1786 -- we remove Node from the tree (without actually deallocating it), and
1787 -- then insert Item into the tree, onto the same Node (so no new node is
1788 -- actually allocated).
1790 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1792 Local_Insert_With_Hint -- use unconditional insert here instead???
1793 (Tree => Tree,
1794 Position => Hint,
1795 Key => Item,
1796 Node => Result,
1797 Inserted => Inserted);
1799 pragma Assert (Inserted);
1800 pragma Assert (Result = Node);
1801 end Replace_Element;
1803 procedure Replace_Element
1804 (Container : in out Set;
1805 Position : Cursor;
1806 New_Item : Element_Type)
1808 begin
1809 if Checks and then Position.Node = null then
1810 raise Constraint_Error with
1811 "Position cursor equals No_Element";
1812 end if;
1814 if Checks and then Position.Container /= Container'Unrestricted_Access
1815 then
1816 raise Program_Error with
1817 "Position cursor designates wrong set";
1818 end if;
1820 pragma Assert (Vet (Container.Tree, Position.Node),
1821 "bad cursor in Replace_Element");
1823 Replace_Element (Container.Tree, Position.Node, New_Item);
1824 end Replace_Element;
1826 ---------------------
1827 -- Reverse_Iterate --
1828 ---------------------
1830 procedure Reverse_Iterate
1831 (Container : Set;
1832 Process : not null access procedure (Position : Cursor))
1834 procedure Process_Node (Node : Node_Access);
1835 pragma Inline (Process_Node);
1837 procedure Local_Reverse_Iterate is
1838 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1840 ------------------
1841 -- Process_Node --
1842 ------------------
1844 procedure Process_Node (Node : Node_Access) is
1845 begin
1846 Process (Cursor'(Container'Unrestricted_Access, Node));
1847 end Process_Node;
1849 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1850 Busy : With_Busy (T.TC'Unrestricted_Access);
1852 -- Start of processing for Reverse_Iterate
1854 begin
1855 Local_Reverse_Iterate (T);
1856 end Reverse_Iterate;
1858 -----------
1859 -- Right --
1860 -----------
1862 function Right (Node : Node_Access) return Node_Access is
1863 begin
1864 return Node.Right;
1865 end Right;
1867 ---------------
1868 -- Set_Color --
1869 ---------------
1871 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1872 begin
1873 Node.Color := Color;
1874 end Set_Color;
1876 --------------
1877 -- Set_Left --
1878 --------------
1880 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1881 begin
1882 Node.Left := Left;
1883 end Set_Left;
1885 ----------------
1886 -- Set_Parent --
1887 ----------------
1889 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1890 begin
1891 Node.Parent := Parent;
1892 end Set_Parent;
1894 ---------------
1895 -- Set_Right --
1896 ---------------
1898 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1899 begin
1900 Node.Right := Right;
1901 end Set_Right;
1903 --------------------------
1904 -- Symmetric_Difference --
1905 --------------------------
1907 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1908 begin
1909 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1910 end Symmetric_Difference;
1912 function Symmetric_Difference (Left, Right : Set) return Set is
1913 Tree : constant Tree_Type :=
1914 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1915 begin
1916 return Set'(Controlled with Tree);
1917 end Symmetric_Difference;
1919 ------------
1920 -- To_Set --
1921 ------------
1923 function To_Set (New_Item : Element_Type) return Set is
1924 Tree : Tree_Type;
1925 Node : Node_Access;
1926 Inserted : Boolean;
1927 pragma Unreferenced (Node, Inserted);
1928 begin
1929 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1930 return Set'(Controlled with Tree);
1931 end To_Set;
1933 -----------
1934 -- Union --
1935 -----------
1937 procedure Union (Target : in out Set; Source : Set) is
1938 begin
1939 Set_Ops.Union (Target.Tree, Source.Tree);
1940 end Union;
1942 function Union (Left, Right : Set) return Set is
1943 Tree : constant Tree_Type :=
1944 Set_Ops.Union (Left.Tree, Right.Tree);
1945 begin
1946 return Set'(Controlled with Tree);
1947 end Union;
1949 -----------
1950 -- Write --
1951 -----------
1953 procedure Write
1954 (Stream : not null access Root_Stream_Type'Class;
1955 Container : Set)
1957 procedure Write_Node
1958 (Stream : not null access Root_Stream_Type'Class;
1959 Node : Node_Access);
1960 pragma Inline (Write_Node);
1962 procedure Write is
1963 new Tree_Operations.Generic_Write (Write_Node);
1965 ----------------
1966 -- Write_Node --
1967 ----------------
1969 procedure Write_Node
1970 (Stream : not null access Root_Stream_Type'Class;
1971 Node : Node_Access)
1973 begin
1974 Element_Type'Write (Stream, Node.Element);
1975 end Write_Node;
1977 -- Start of processing for Write
1979 begin
1980 Write (Stream, Container.Tree);
1981 end Write;
1983 procedure Write
1984 (Stream : not null access Root_Stream_Type'Class;
1985 Item : Cursor)
1987 begin
1988 raise Program_Error with "attempt to stream set cursor";
1989 end Write;
1991 procedure Write
1992 (Stream : not null access Root_Stream_Type'Class;
1993 Item : Constant_Reference_Type)
1995 begin
1996 raise Program_Error with "attempt to stream reference";
1997 end Write;
1999 end Ada.Containers.Ordered_Sets;