1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
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 --
9 -- Copyright (C) 2004-2012, Free Software Foundation, Inc. --
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. --
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. --
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/>. --
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.Ordered_Sets is
45 type Iterator is new Limited_Controlled and
46 Set_Iterator_Interfaces.Reversible_Iterator with
48 Container : Set_Access;
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
59 Position : Cursor) return Cursor;
61 overriding function Previous
63 Position : Cursor) return Cursor;
65 ------------------------------
66 -- Access to Fields of Node --
67 ------------------------------
69 -- These subprograms provide functional notation for access to fields
70 -- of a node, and procedural notation for modifying these fields.
72 function Color (Node : Node_Access) return Color_Type;
73 pragma Inline (Color);
75 function Left (Node : Node_Access) return Node_Access;
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_Color (Node : Node_Access; Color : Color_Type);
85 pragma Inline (Set_Color);
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_Parent (Node : Node_Access; Parent : Node_Access);
94 pragma Inline (Set_Parent);
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;
109 Inserted : out Boolean);
111 procedure Insert_With_Hint
112 (Dst_Tree : in out Tree_Type;
113 Dst_Hint : Node_Access;
114 Src_Node : Node_Access;
115 Dst_Node : out Node_Access);
117 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
118 pragma Inline (Is_Equal_Node_Node);
120 function Is_Greater_Element_Node
121 (Left : Element_Type;
122 Right : Node_Access) return Boolean;
123 pragma Inline (Is_Greater_Element_Node);
125 function Is_Less_Element_Node
126 (Left : Element_Type;
127 Right : Node_Access) return Boolean;
128 pragma Inline (Is_Less_Element_Node);
130 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
131 pragma Inline (Is_Less_Node_Node);
133 procedure Replace_Element
134 (Tree : in out Tree_Type;
136 Item : Element_Type);
138 --------------------------
139 -- Local Instantiations --
140 --------------------------
142 package Tree_Operations is
143 new Red_Black_Trees.Generic_Operations (Tree_Types);
145 procedure Delete_Tree is
146 new Tree_Operations.Generic_Delete_Tree (Free);
148 function Copy_Tree is
149 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
154 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
156 package Element_Keys is
157 new Red_Black_Trees.Generic_Keys
158 (Tree_Operations => Tree_Operations,
159 Key_Type => Element_Type,
160 Is_Less_Key_Node => Is_Less_Element_Node,
161 Is_Greater_Key_Node => Is_Greater_Element_Node);
164 new Generic_Set_Operations
165 (Tree_Operations => Tree_Operations,
166 Insert_With_Hint => Insert_With_Hint,
167 Copy_Tree => Copy_Tree,
168 Delete_Tree => Delete_Tree,
169 Is_Less => Is_Less_Node_Node,
176 function "<" (Left, Right : Cursor) return Boolean is
178 if Left.Node = null then
179 raise Constraint_Error with "Left cursor equals No_Element";
182 if Right.Node = null then
183 raise Constraint_Error with "Right cursor equals No_Element";
186 pragma Assert (Vet (Left.Container.Tree, Left.Node),
187 "bad Left cursor in ""<""");
189 pragma Assert (Vet (Right.Container.Tree, Right.Node),
190 "bad Right cursor in ""<""");
192 return Left.Node.Element < Right.Node.Element;
195 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
197 if Left.Node = null then
198 raise Constraint_Error with "Left cursor equals No_Element";
201 pragma Assert (Vet (Left.Container.Tree, Left.Node),
202 "bad Left cursor in ""<""");
204 return Left.Node.Element < Right;
207 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
209 if Right.Node = null then
210 raise Constraint_Error with "Right cursor equals No_Element";
213 pragma Assert (Vet (Right.Container.Tree, Right.Node),
214 "bad Right cursor in ""<""");
216 return Left < Right.Node.Element;
223 function "=" (Left, Right : Set) return Boolean is
225 return Is_Equal (Left.Tree, Right.Tree);
232 function ">" (Left, Right : Cursor) return Boolean is
234 if Left.Node = null then
235 raise Constraint_Error with "Left cursor equals No_Element";
238 if Right.Node = null then
239 raise Constraint_Error with "Right cursor equals No_Element";
242 pragma Assert (Vet (Left.Container.Tree, Left.Node),
243 "bad Left cursor in "">""");
245 pragma Assert (Vet (Right.Container.Tree, Right.Node),
246 "bad Right cursor in "">""");
248 -- L > R same as R < L
250 return Right.Node.Element < Left.Node.Element;
253 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
255 if Right.Node = null then
256 raise Constraint_Error with "Right cursor equals No_Element";
259 pragma Assert (Vet (Right.Container.Tree, Right.Node),
260 "bad Right cursor in "">""");
262 return Right.Node.Element < Left;
265 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
267 if Left.Node = null then
268 raise Constraint_Error with "Left cursor equals No_Element";
271 pragma Assert (Vet (Left.Container.Tree, Left.Node),
272 "bad Left cursor in "">""");
274 return Right < Left.Node.Element;
281 procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
283 procedure Adjust (Container : in out Set) is
285 Adjust (Container.Tree);
288 procedure Adjust (Control : in out Reference_Control_Type) is
290 if Control.Container /= null then
292 Tree : Tree_Type renames Control.Container.all.Tree;
293 B : Natural renames Tree.Busy;
294 L : Natural renames Tree.Lock;
306 procedure Assign (Target : in out Set; Source : Set) is
308 if Target'Address = Source'Address then
313 Target.Union (Source);
320 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
321 Node : constant Node_Access :=
322 Element_Keys.Ceiling (Container.Tree, Item);
324 return (if Node = null then No_Element
325 else Cursor'(Container'Unrestricted_Access, Node));
332 procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
334 procedure Clear (Container : in out Set) is
336 Clear (Container.Tree);
343 function Color (Node : Node_Access) return Color_Type is
348 ------------------------
349 -- Constant_Reference --
350 ------------------------
352 function Constant_Reference
353 (Container : aliased Set;
354 Position : Cursor) return Constant_Reference_Type
357 if Position.Container = null then
358 raise Constraint_Error with "Position cursor has no element";
361 if Position.Container /= Container'Unrestricted_Access then
362 raise Program_Error with
363 "Position cursor designates wrong container";
367 (Vet (Container.Tree, Position.Node),
368 "bad cursor in Constant_Reference");
371 Tree : Tree_Type renames Position.Container.all.Tree;
372 B : Natural renames Tree.Busy;
373 L : Natural renames Tree.Lock;
375 return R : constant Constant_Reference_Type :=
376 (Element => Position.Node.Element'Access,
378 (Controlled with Container'Unrestricted_Access))
384 end Constant_Reference;
392 Item : Element_Type) return Boolean
395 return Find (Container, Item) /= No_Element;
402 function Copy (Source : Set) return Set is
404 return Target : Set do
405 Target.Assign (Source);
413 function Copy_Node (Source : Node_Access) return Node_Access is
414 Target : constant Node_Access :=
415 new Node_Type'(Parent => null,
418 Color => Source.Color,
419 Element => Source.Element);
428 procedure Delete (Container : in out Set; Position : in out Cursor) is
430 if Position.Node = null then
431 raise Constraint_Error with "Position cursor equals No_Element";
434 if Position.Container /= Container'Unrestricted_Access then
435 raise Program_Error with "Position cursor designates wrong set";
438 pragma Assert (Vet (Container.Tree, Position.Node),
439 "bad cursor in Delete");
441 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
442 Free (Position.Node);
443 Position.Container := null;
446 procedure Delete (Container : in out Set; Item : Element_Type) is
447 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
451 raise Constraint_Error with "attempt to delete element not in set";
454 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
462 procedure Delete_First (Container : in out Set) is
463 Tree : Tree_Type renames Container.Tree;
464 X : Node_Access := Tree.First;
467 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
476 procedure Delete_Last (Container : in out Set) is
477 Tree : Tree_Type renames Container.Tree;
478 X : Node_Access := Tree.Last;
481 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
490 procedure Difference (Target : in out Set; Source : Set) is
492 Set_Ops.Difference (Target.Tree, Source.Tree);
495 function Difference (Left, Right : Set) return Set is
496 Tree : constant Tree_Type :=
497 Set_Ops.Difference (Left.Tree, Right.Tree);
499 return Set'(Controlled with Tree);
506 function Element (Position : Cursor) return Element_Type is
508 if Position.Node = null then
509 raise Constraint_Error with "Position cursor equals No_Element";
512 pragma Assert (Vet (Position.Container.Tree, Position.Node),
513 "bad cursor in Element");
515 return Position.Node.Element;
518 -------------------------
519 -- Equivalent_Elements --
520 -------------------------
522 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
524 return (if Left < Right or else Right < Left then False else True);
525 end Equivalent_Elements;
527 ---------------------
528 -- Equivalent_Sets --
529 ---------------------
531 function Equivalent_Sets (Left, Right : Set) return Boolean is
532 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
533 pragma Inline (Is_Equivalent_Node_Node);
535 function Is_Equivalent is
536 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
538 -----------------------------
539 -- Is_Equivalent_Node_Node --
540 -----------------------------
542 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
544 return (if L.Element < R.Element then False
545 elsif R.Element < L.Element then False
547 end Is_Equivalent_Node_Node;
549 -- Start of processing for Equivalent_Sets
552 return Is_Equivalent (Left.Tree, Right.Tree);
559 procedure Exclude (Container : in out Set; Item : Element_Type) is
560 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
564 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
573 procedure Finalize (Object : in out Iterator) is
575 if Object.Container /= null then
577 B : Natural renames Object.Container.all.Tree.Busy;
584 procedure Finalize (Control : in out Reference_Control_Type) is
586 if Control.Container /= null then
588 Tree : Tree_Type renames Control.Container.all.Tree;
589 B : Natural renames Tree.Busy;
590 L : Natural renames Tree.Lock;
596 Control.Container := null;
604 function Find (Container : Set; Item : Element_Type) return Cursor is
605 Node : constant Node_Access :=
606 Element_Keys.Find (Container.Tree, Item);
608 return (if Node = null then No_Element
609 else Cursor'(Container'Unrestricted_Access, Node));
616 function First (Container : Set) return Cursor is
619 (if Container.Tree.First = null then No_Element
620 else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
623 function First (Object : Iterator) return Cursor is
625 -- The value of the iterator object's Node component influences the
626 -- behavior of the First (and Last) selector function.
628 -- When the Node component is null, this means the iterator object was
629 -- constructed without a start expression, in which case the (forward)
630 -- iteration starts from the (logical) beginning of the entire sequence
631 -- of items (corresponding to Container.First, for a forward iterator).
633 -- Otherwise, this is iteration over a partial sequence of items. When
634 -- the Node component is non-null, the iterator object was constructed
635 -- with a start expression, that specifies the position from which the
636 -- (forward) partial iteration begins.
638 if Object.Node = null then
639 return Object.Container.First;
641 return Cursor'(Object.Container, Object.Node);
649 function First_Element (Container : Set) return Element_Type is
651 if Container.Tree.First = null then
652 raise Constraint_Error with "set is empty";
655 return Container.Tree.First.Element;
662 function Floor (Container : Set; Item : Element_Type) return Cursor is
663 Node : constant Node_Access :=
664 Element_Keys.Floor (Container.Tree, Item);
666 return (if Node = null then No_Element
667 else Cursor'(Container'Unrestricted_Access, Node));
674 procedure Free (X : in out Node_Access) is
675 procedure Deallocate is
676 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
690 package body Generic_Keys is
692 -----------------------
693 -- Local Subprograms --
694 -----------------------
696 function Is_Greater_Key_Node
698 Right : Node_Access) return Boolean;
699 pragma Inline (Is_Greater_Key_Node);
701 function Is_Less_Key_Node
703 Right : Node_Access) return Boolean;
704 pragma Inline (Is_Less_Key_Node);
706 --------------------------
707 -- Local Instantiations --
708 --------------------------
711 new Red_Black_Trees.Generic_Keys
712 (Tree_Operations => Tree_Operations,
713 Key_Type => Key_Type,
714 Is_Less_Key_Node => Is_Less_Key_Node,
715 Is_Greater_Key_Node => Is_Greater_Key_Node);
721 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
722 Node : constant Node_Access :=
723 Key_Keys.Ceiling (Container.Tree, Key);
725 return (if Node = null then No_Element
726 else Cursor'(Container'Unrestricted_Access, Node));
729 ------------------------
730 -- Constant_Reference --
731 ------------------------
733 function Constant_Reference
734 (Container : aliased Set;
735 Key : Key_Type) return Constant_Reference_Type
737 Node : constant Node_Access :=
738 Key_Keys.Find (Container.Tree, Key);
742 raise Constraint_Error with "key not in set";
746 Tree : Tree_Type renames Container'Unrestricted_Access.all.Tree;
747 B : Natural renames Tree.Busy;
748 L : Natural renames Tree.Lock;
750 return R : constant Constant_Reference_Type :=
751 (Element => Node.Element'Access,
753 (Controlled with Container'Unrestricted_Access))
759 end Constant_Reference;
765 function Contains (Container : Set; Key : Key_Type) return Boolean is
767 return Find (Container, Key) /= No_Element;
774 procedure Delete (Container : in out Set; Key : Key_Type) is
775 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
779 raise Constraint_Error with "attempt to delete key not in set";
782 Delete_Node_Sans_Free (Container.Tree, X);
790 function Element (Container : Set; Key : Key_Type) return Element_Type is
791 Node : constant Node_Access :=
792 Key_Keys.Find (Container.Tree, Key);
796 raise Constraint_Error with "key not in set";
802 ---------------------
803 -- Equivalent_Keys --
804 ---------------------
806 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
808 return (if Left < Right or else Right < Left then False else True);
815 procedure Exclude (Container : in out Set; Key : Key_Type) is
816 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
819 Delete_Node_Sans_Free (Container.Tree, X);
828 function Find (Container : Set; Key : Key_Type) return Cursor is
829 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
831 return (if Node = null then No_Element
832 else Cursor'(Container'Unrestricted_Access, Node));
839 function Floor (Container : Set; Key : Key_Type) return Cursor is
840 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
842 return (if Node = null then No_Element
843 else Cursor'(Container'Unrestricted_Access, Node));
846 -------------------------
847 -- Is_Greater_Key_Node --
848 -------------------------
850 function Is_Greater_Key_Node
852 Right : Node_Access) return Boolean
855 return Key (Right.Element) < Left;
856 end Is_Greater_Key_Node;
858 ----------------------
859 -- Is_Less_Key_Node --
860 ----------------------
862 function Is_Less_Key_Node
864 Right : Node_Access) return Boolean
867 return Left < Key (Right.Element);
868 end Is_Less_Key_Node;
874 function Key (Position : Cursor) return Key_Type is
876 if Position.Node = null then
877 raise Constraint_Error with
878 "Position cursor equals No_Element";
881 pragma Assert (Vet (Position.Container.Tree, Position.Node),
882 "bad cursor in Key");
884 return Key (Position.Node.Element);
892 (Stream : not null access Root_Stream_Type'Class;
893 Item : out Reference_Type)
896 raise Program_Error with "attempt to stream reference";
899 ------------------------------
900 -- Reference_Preserving_Key --
901 ------------------------------
903 function Reference_Preserving_Key
904 (Container : aliased in out Set;
905 Position : Cursor) return Reference_Type
908 if Position.Container = null then
909 raise Constraint_Error with "Position cursor has no element";
912 if Position.Container /= Container'Unrestricted_Access then
913 raise Program_Error with
914 "Position cursor designates wrong container";
918 (Vet (Container.Tree, Position.Node),
919 "bad cursor in function Reference_Preserving_Key");
921 -- Some form of finalization will be required in order to actually
922 -- check that the key-part of the element designated by Position has
925 return (Element => Position.Node.Element'Access);
926 end Reference_Preserving_Key;
928 function Reference_Preserving_Key
929 (Container : aliased in out Set;
930 Key : Key_Type) return Reference_Type
932 Node : constant Node_Access :=
933 Key_Keys.Find (Container.Tree, Key);
937 raise Constraint_Error with "key not in set";
940 -- Some form of finalization will be required in order to actually
941 -- check that the key-part of the element designated by Position has
944 return (Element => Node.Element'Access);
945 end Reference_Preserving_Key;
952 (Container : in out Set;
954 New_Item : Element_Type)
956 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
960 raise Constraint_Error with
961 "attempt to replace key not in set";
964 Replace_Element (Container.Tree, Node, New_Item);
967 -----------------------------------
968 -- Update_Element_Preserving_Key --
969 -----------------------------------
971 procedure Update_Element_Preserving_Key
972 (Container : in out Set;
974 Process : not null access procedure (Element : in out Element_Type))
976 Tree : Tree_Type renames Container.Tree;
979 if Position.Node = null then
980 raise Constraint_Error with
981 "Position cursor equals No_Element";
984 if Position.Container /= Container'Unrestricted_Access then
985 raise Program_Error with
986 "Position cursor designates wrong set";
989 pragma Assert (Vet (Container.Tree, Position.Node),
990 "bad cursor in Update_Element_Preserving_Key");
993 E : Element_Type renames Position.Node.Element;
994 K : constant Key_Type := Key (E);
996 B : Natural renames Tree.Busy;
997 L : Natural renames Tree.Lock;
1015 if Equivalent_Keys (K, Key (E)) then
1021 X : Node_Access := Position.Node;
1023 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
1027 raise Program_Error with "key was modified";
1028 end Update_Element_Preserving_Key;
1035 (Stream : not null access Root_Stream_Type'Class;
1036 Item : Reference_Type)
1039 raise Program_Error with "attempt to stream reference";
1048 function Has_Element (Position : Cursor) return Boolean is
1050 return Position /= No_Element;
1057 procedure Include (Container : in out Set; New_Item : Element_Type) is
1062 Insert (Container, New_Item, Position, Inserted);
1064 if not Inserted then
1065 if Container.Tree.Lock > 0 then
1066 raise Program_Error with
1067 "attempt to tamper with elements (set is locked)";
1070 Position.Node.Element := New_Item;
1079 (Container : in out Set;
1080 New_Item : Element_Type;
1081 Position : out Cursor;
1082 Inserted : out Boolean)
1091 Position.Container := Container'Unrestricted_Access;
1095 (Container : in out Set;
1096 New_Item : Element_Type)
1099 pragma Unreferenced (Position);
1104 Insert (Container, New_Item, Position, Inserted);
1106 if not Inserted then
1107 raise Constraint_Error with
1108 "attempt to insert element already in set";
1112 ----------------------
1113 -- Insert_Sans_Hint --
1114 ----------------------
1116 procedure Insert_Sans_Hint
1117 (Tree : in out Tree_Type;
1118 New_Item : Element_Type;
1119 Node : out Node_Access;
1120 Inserted : out Boolean)
1122 function New_Node return Node_Access;
1123 pragma Inline (New_Node);
1125 procedure Insert_Post is
1126 new Element_Keys.Generic_Insert_Post (New_Node);
1128 procedure Conditional_Insert_Sans_Hint is
1129 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1135 function New_Node return Node_Access is
1137 return new Node_Type'(Parent => null,
1140 Color => Red_Black_Trees.Red,
1141 Element => New_Item);
1144 -- Start of processing for Insert_Sans_Hint
1147 Conditional_Insert_Sans_Hint
1152 end Insert_Sans_Hint;
1154 ----------------------
1155 -- Insert_With_Hint --
1156 ----------------------
1158 procedure Insert_With_Hint
1159 (Dst_Tree : in out Tree_Type;
1160 Dst_Hint : Node_Access;
1161 Src_Node : Node_Access;
1162 Dst_Node : out Node_Access)
1165 pragma Unreferenced (Success);
1167 function New_Node return Node_Access;
1168 pragma Inline (New_Node);
1170 procedure Insert_Post is
1171 new Element_Keys.Generic_Insert_Post (New_Node);
1173 procedure Insert_Sans_Hint is
1174 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1176 procedure Local_Insert_With_Hint is
1177 new Element_Keys.Generic_Conditional_Insert_With_Hint
1185 function New_Node return Node_Access is
1186 Node : constant Node_Access :=
1187 new Node_Type'(Parent => null,
1191 Element => Src_Node.Element);
1196 -- Start of processing for Insert_With_Hint
1199 Local_Insert_With_Hint
1205 end Insert_With_Hint;
1211 procedure Intersection (Target : in out Set; Source : Set) is
1213 Set_Ops.Intersection (Target.Tree, Source.Tree);
1216 function Intersection (Left, Right : Set) return Set is
1217 Tree : constant Tree_Type :=
1218 Set_Ops.Intersection (Left.Tree, Right.Tree);
1220 return Set'(Controlled with Tree);
1227 function Is_Empty (Container : Set) return Boolean is
1229 return Container.Tree.Length = 0;
1232 ------------------------
1233 -- Is_Equal_Node_Node --
1234 ------------------------
1236 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1238 return L.Element = R.Element;
1239 end Is_Equal_Node_Node;
1241 -----------------------------
1242 -- Is_Greater_Element_Node --
1243 -----------------------------
1245 function Is_Greater_Element_Node
1246 (Left : Element_Type;
1247 Right : Node_Access) return Boolean
1250 -- Compute e > node same as node < e
1252 return Right.Element < Left;
1253 end Is_Greater_Element_Node;
1255 --------------------------
1256 -- Is_Less_Element_Node --
1257 --------------------------
1259 function Is_Less_Element_Node
1260 (Left : Element_Type;
1261 Right : Node_Access) return Boolean
1264 return Left < Right.Element;
1265 end Is_Less_Element_Node;
1267 -----------------------
1268 -- Is_Less_Node_Node --
1269 -----------------------
1271 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1273 return L.Element < R.Element;
1274 end Is_Less_Node_Node;
1280 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1282 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1291 Process : not null access procedure (Position : Cursor))
1293 procedure Process_Node (Node : Node_Access);
1294 pragma Inline (Process_Node);
1296 procedure Local_Iterate is
1297 new Tree_Operations.Generic_Iteration (Process_Node);
1303 procedure Process_Node (Node : Node_Access) is
1305 Process (Cursor'(Container'Unrestricted_Access, Node));
1308 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
1309 B : Natural renames T.Busy;
1311 -- Start of processing for Iterate
1327 function Iterate (Container : Set)
1328 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1330 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1333 -- The value of the Node component influences the behavior of the First
1334 -- and Last selector functions of the iterator object. When the Node
1335 -- component is null (as is the case here), this means the iterator
1336 -- object was constructed without a start expression. This is a complete
1337 -- iterator, meaning that the iteration starts from the (logical)
1338 -- beginning of the sequence of items.
1340 -- Note: For a forward iterator, Container.First is the beginning, and
1341 -- for a reverse iterator, Container.Last is the beginning.
1345 return It : constant Iterator :=
1346 Iterator'(Limited_Controlled with
1347 Container => Container'Unrestricted_Access,
1351 function Iterate (Container : Set; Start : Cursor)
1352 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1354 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1357 -- It was formerly the case that when Start = No_Element, the partial
1358 -- iterator was defined to behave the same as for a complete iterator,
1359 -- and iterate over the entire sequence of items. However, those
1360 -- semantics were unintuitive and arguably error-prone (it is too easy
1361 -- to accidentally create an endless loop), and so they were changed,
1362 -- per the ARG meeting in Denver on 2011/11. However, there was no
1363 -- consensus about what positive meaning this corner case should have,
1364 -- and so it was decided to simply raise an exception. This does imply,
1365 -- however, that it is not possible to use a partial iterator to specify
1366 -- an empty sequence of items.
1368 if Start = No_Element then
1369 raise Constraint_Error with
1370 "Start position for iterator equals No_Element";
1373 if Start.Container /= Container'Unrestricted_Access then
1374 raise Program_Error with
1375 "Start cursor of Iterate designates wrong set";
1378 pragma Assert (Vet (Container.Tree, Start.Node),
1379 "Start cursor of Iterate is bad");
1381 -- The value of the Node component influences the behavior of the First
1382 -- and Last selector functions of the iterator object. When the Node
1383 -- component is non-null (as is the case here), it means that this is a
1384 -- partial iteration, over a subset of the complete sequence of
1385 -- items. The iterator object was constructed with a start expression,
1386 -- indicating the position from which the iteration begins. Note that
1387 -- the start position has the same value irrespective of whether this is
1388 -- a forward or reverse iteration.
1392 return It : constant Iterator :=
1393 Iterator'(Limited_Controlled with
1394 Container => Container'Unrestricted_Access,
1395 Node => Start.Node);
1402 function Last (Container : Set) return Cursor is
1405 (if Container.Tree.Last = null then No_Element
1406 else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
1409 function Last (Object : Iterator) return Cursor is
1411 -- The value of the iterator object's Node component influences the
1412 -- behavior of the Last (and First) selector function.
1414 -- When the Node component is null, this means the iterator object was
1415 -- constructed without a start expression, in which case the (reverse)
1416 -- iteration starts from the (logical) beginning of the entire sequence
1417 -- (corresponding to Container.Last, for a reverse iterator).
1419 -- Otherwise, this is iteration over a partial sequence of items. When
1420 -- the Node component is non-null, the iterator object was constructed
1421 -- with a start expression, that specifies the position from which the
1422 -- (reverse) partial iteration begins.
1424 if Object.Node = null then
1425 return Object.Container.Last;
1427 return Cursor'(Object.Container, Object.Node);
1435 function Last_Element (Container : Set) return Element_Type is
1437 if Container.Tree.Last = null then
1438 raise Constraint_Error with "set is empty";
1440 return Container.Tree.Last.Element;
1448 function Left (Node : Node_Access) return Node_Access is
1457 function Length (Container : Set) return Count_Type is
1459 return Container.Tree.Length;
1466 procedure Move is new Tree_Operations.Generic_Move (Clear);
1468 procedure Move (Target : in out Set; Source : in out Set) is
1470 Move (Target => Target.Tree, Source => Source.Tree);
1477 function Next (Position : Cursor) return Cursor is
1479 if Position = No_Element then
1483 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1484 "bad cursor in Next");
1487 Node : constant Node_Access :=
1488 Tree_Operations.Next (Position.Node);
1490 return (if Node = null then No_Element
1491 else Cursor'(Position.Container, Node));
1495 procedure Next (Position : in out Cursor) is
1497 Position := Next (Position);
1500 function Next (Object : Iterator; Position : Cursor) return Cursor is
1502 if Position.Container = null then
1506 if Position.Container /= Object.Container then
1507 raise Program_Error with
1508 "Position cursor of Next designates wrong set";
1511 return Next (Position);
1518 function Overlap (Left, Right : Set) return Boolean is
1520 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1527 function Parent (Node : Node_Access) return Node_Access is
1536 function Previous (Position : Cursor) return Cursor is
1538 if Position = No_Element then
1542 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1543 "bad cursor in Previous");
1546 Node : constant Node_Access :=
1547 Tree_Operations.Previous (Position.Node);
1549 return (if Node = null then No_Element
1550 else Cursor'(Position.Container, Node));
1554 procedure Previous (Position : in out Cursor) is
1556 Position := Previous (Position);
1559 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1561 if Position.Container = null then
1565 if Position.Container /= Object.Container then
1566 raise Program_Error with
1567 "Position cursor of Previous designates wrong set";
1570 return Previous (Position);
1577 procedure Query_Element
1579 Process : not null access procedure (Element : Element_Type))
1582 if Position.Node = null then
1583 raise Constraint_Error with "Position cursor equals No_Element";
1586 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1587 "bad cursor in Query_Element");
1590 T : Tree_Type renames Position.Container.Tree;
1592 B : Natural renames T.Busy;
1593 L : Natural renames T.Lock;
1600 Process (Position.Node.Element);
1618 (Stream : not null access Root_Stream_Type'Class;
1619 Container : out Set)
1622 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1623 pragma Inline (Read_Node);
1626 new Tree_Operations.Generic_Read (Clear, Read_Node);
1633 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1635 Node : Node_Access := new Node_Type;
1637 Element_Type'Read (Stream, Node.Element);
1645 -- Start of processing for Read
1648 Read (Stream, Container.Tree);
1652 (Stream : not null access Root_Stream_Type'Class;
1656 raise Program_Error with "attempt to stream set cursor";
1660 (Stream : not null access Root_Stream_Type'Class;
1661 Item : out Constant_Reference_Type)
1664 raise Program_Error with "attempt to stream reference";
1671 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1672 Node : constant Node_Access :=
1673 Element_Keys.Find (Container.Tree, New_Item);
1677 raise Constraint_Error with
1678 "attempt to replace element not in set";
1681 if Container.Tree.Lock > 0 then
1682 raise Program_Error with
1683 "attempt to tamper with elements (set is locked)";
1686 Node.Element := New_Item;
1689 ---------------------
1690 -- Replace_Element --
1691 ---------------------
1693 procedure Replace_Element
1694 (Tree : in out Tree_Type;
1696 Item : Element_Type)
1698 pragma Assert (Node /= null);
1700 function New_Node return Node_Access;
1701 pragma Inline (New_Node);
1703 procedure Local_Insert_Post is
1704 new Element_Keys.Generic_Insert_Post (New_Node);
1706 procedure Local_Insert_Sans_Hint is
1707 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1709 procedure Local_Insert_With_Hint is
1710 new Element_Keys.Generic_Conditional_Insert_With_Hint
1712 Local_Insert_Sans_Hint);
1718 function New_Node return Node_Access is
1720 Node.Element := Item;
1722 Node.Parent := null;
1729 Result : Node_Access;
1732 -- Start of processing for Replace_Element
1735 if Item < Node.Element or else Node.Element < Item then
1739 if Tree.Lock > 0 then
1740 raise Program_Error with
1741 "attempt to tamper with elements (set is locked)";
1744 Node.Element := Item;
1748 Hint := Element_Keys.Ceiling (Tree, Item);
1753 elsif Item < Hint.Element then
1755 if Tree.Lock > 0 then
1756 raise Program_Error with
1757 "attempt to tamper with elements (set is locked)";
1760 Node.Element := Item;
1765 pragma Assert (not (Hint.Element < Item));
1766 raise Program_Error with "attempt to replace existing element";
1769 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1771 Local_Insert_With_Hint
1776 Inserted => Inserted);
1778 pragma Assert (Inserted);
1779 pragma Assert (Result = Node);
1780 end Replace_Element;
1782 procedure Replace_Element
1783 (Container : in out Set;
1785 New_Item : Element_Type)
1788 if Position.Node = null then
1789 raise Constraint_Error with
1790 "Position cursor equals No_Element";
1793 if Position.Container /= Container'Unrestricted_Access then
1794 raise Program_Error with
1795 "Position cursor designates wrong set";
1798 pragma Assert (Vet (Container.Tree, Position.Node),
1799 "bad cursor in Replace_Element");
1801 Replace_Element (Container.Tree, Position.Node, New_Item);
1802 end Replace_Element;
1804 ---------------------
1805 -- Reverse_Iterate --
1806 ---------------------
1808 procedure Reverse_Iterate
1810 Process : not null access procedure (Position : Cursor))
1812 procedure Process_Node (Node : Node_Access);
1813 pragma Inline (Process_Node);
1815 procedure Local_Reverse_Iterate is
1816 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1822 procedure Process_Node (Node : Node_Access) is
1824 Process (Cursor'(Container'Unrestricted_Access, Node));
1827 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1828 B : Natural renames T.Busy;
1830 -- Start of processing for Reverse_Iterate
1836 Local_Reverse_Iterate (T);
1844 end Reverse_Iterate;
1850 function Right (Node : Node_Access) return Node_Access is
1859 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1861 Node.Color := Color;
1868 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1877 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1879 Node.Parent := Parent;
1886 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1888 Node.Right := Right;
1891 --------------------------
1892 -- Symmetric_Difference --
1893 --------------------------
1895 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1897 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1898 end Symmetric_Difference;
1900 function Symmetric_Difference (Left, Right : Set) return Set is
1901 Tree : constant Tree_Type :=
1902 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1904 return Set'(Controlled with Tree);
1905 end Symmetric_Difference;
1911 function To_Set (New_Item : Element_Type) return Set is
1915 pragma Unreferenced (Node, Inserted);
1917 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1918 return Set'(Controlled with Tree);
1925 procedure Union (Target : in out Set; Source : Set) is
1927 Set_Ops.Union (Target.Tree, Source.Tree);
1930 function Union (Left, Right : Set) return Set is
1931 Tree : constant Tree_Type :=
1932 Set_Ops.Union (Left.Tree, Right.Tree);
1934 return Set'(Controlled with Tree);
1942 (Stream : not null access Root_Stream_Type'Class;
1945 procedure Write_Node
1946 (Stream : not null access Root_Stream_Type'Class;
1947 Node : Node_Access);
1948 pragma Inline (Write_Node);
1951 new Tree_Operations.Generic_Write (Write_Node);
1957 procedure Write_Node
1958 (Stream : not null access Root_Stream_Type'Class;
1962 Element_Type'Write (Stream, Node.Element);
1965 -- Start of processing for Write
1968 Write (Stream, Container.Tree);
1972 (Stream : not null access Root_Stream_Type'Class;
1976 raise Program_Error with "attempt to stream set cursor";
1980 (Stream : not null access Root_Stream_Type'Class;
1981 Item : Constant_Reference_Type)
1984 raise Program_Error with "attempt to stream reference";
1987 end Ada.Containers.Ordered_Sets;