1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_SETS --
9 -- Copyright (C) 2004-2011, 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.Containers.Red_Black_Trees.Generic_Operations;
31 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
33 with Ada.Containers.Red_Black_Trees.Generic_Keys;
34 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
36 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
37 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
39 with Ada.Unchecked_Deallocation;
41 with System; use type System.Address;
43 package body Ada.Containers.Indefinite_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 -- Local Subprograms --
67 -----------------------
69 function Color (Node : Node_Access) return Color_Type;
70 pragma Inline (Color);
72 function Copy_Node (Source : Node_Access) return Node_Access;
73 pragma Inline (Copy_Node);
75 procedure Free (X : in out Node_Access);
77 procedure Insert_Sans_Hint
78 (Tree : in out Tree_Type;
79 New_Item : Element_Type;
80 Node : out Node_Access;
81 Inserted : out Boolean);
83 procedure Insert_With_Hint
84 (Dst_Tree : in out Tree_Type;
85 Dst_Hint : Node_Access;
86 Src_Node : Node_Access;
87 Dst_Node : out Node_Access);
89 function Is_Greater_Element_Node
91 Right : Node_Access) return Boolean;
92 pragma Inline (Is_Greater_Element_Node);
94 function Is_Less_Element_Node
96 Right : Node_Access) return Boolean;
97 pragma Inline (Is_Less_Element_Node);
99 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
100 pragma Inline (Is_Less_Node_Node);
102 function Left (Node : Node_Access) return Node_Access;
103 pragma Inline (Left);
105 function Parent (Node : Node_Access) return Node_Access;
106 pragma Inline (Parent);
108 procedure Replace_Element
109 (Tree : in out Tree_Type;
111 Item : Element_Type);
113 function Right (Node : Node_Access) return Node_Access;
114 pragma Inline (Right);
116 procedure Set_Color (Node : Node_Access; Color : Color_Type);
117 pragma Inline (Set_Color);
119 procedure Set_Left (Node : Node_Access; Left : Node_Access);
120 pragma Inline (Set_Left);
122 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
123 pragma Inline (Set_Parent);
125 procedure Set_Right (Node : Node_Access; Right : Node_Access);
126 pragma Inline (Set_Right);
128 --------------------------
129 -- Local Instantiations --
130 --------------------------
132 procedure Free_Element is
133 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
135 package Tree_Operations is
136 new Red_Black_Trees.Generic_Operations (Tree_Types);
138 procedure Delete_Tree is
139 new Tree_Operations.Generic_Delete_Tree (Free);
141 function Copy_Tree is
142 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
146 package Element_Keys is
147 new Red_Black_Trees.Generic_Keys
148 (Tree_Operations => Tree_Operations,
149 Key_Type => Element_Type,
150 Is_Less_Key_Node => Is_Less_Element_Node,
151 Is_Greater_Key_Node => Is_Greater_Element_Node);
154 new Generic_Set_Operations
155 (Tree_Operations => Tree_Operations,
156 Insert_With_Hint => Insert_With_Hint,
157 Copy_Tree => Copy_Tree,
158 Delete_Tree => Delete_Tree,
159 Is_Less => Is_Less_Node_Node,
166 function "<" (Left, Right : Cursor) return Boolean is
168 if Left.Node = null then
169 raise Constraint_Error with "Left cursor equals No_Element";
172 if Right.Node = null then
173 raise Constraint_Error with "Right cursor equals No_Element";
176 if Left.Node.Element = null then
177 raise Program_Error with "Left cursor is bad";
180 if Right.Node.Element = null then
181 raise Program_Error with "Right cursor is bad";
184 pragma Assert (Vet (Left.Container.Tree, Left.Node),
185 "bad Left cursor in ""<""");
187 pragma Assert (Vet (Right.Container.Tree, Right.Node),
188 "bad Right cursor in ""<""");
190 return Left.Node.Element.all < Right.Node.Element.all;
193 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
195 if Left.Node = null then
196 raise Constraint_Error with "Left cursor equals No_Element";
199 if Left.Node.Element = null then
200 raise Program_Error with "Left cursor is bad";
203 pragma Assert (Vet (Left.Container.Tree, Left.Node),
204 "bad Left cursor in ""<""");
206 return Left.Node.Element.all < Right;
209 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
211 if Right.Node = null then
212 raise Constraint_Error with "Right cursor equals No_Element";
215 if Right.Node.Element = null then
216 raise Program_Error with "Right cursor is bad";
219 pragma Assert (Vet (Right.Container.Tree, Right.Node),
220 "bad Right cursor in ""<""");
222 return Left < Right.Node.Element.all;
229 function "=" (Left, Right : Set) return Boolean is
231 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
232 pragma Inline (Is_Equal_Node_Node);
235 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
237 ------------------------
238 -- Is_Equal_Node_Node --
239 ------------------------
241 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
243 return L.Element.all = R.Element.all;
244 end Is_Equal_Node_Node;
246 -- Start of processing for "="
249 return Is_Equal (Left.Tree, Right.Tree);
256 function ">" (Left, Right : Cursor) return Boolean is
258 if Left.Node = null then
259 raise Constraint_Error with "Left cursor equals No_Element";
262 if Right.Node = null then
263 raise Constraint_Error with "Right cursor equals No_Element";
266 if Left.Node.Element = null then
267 raise Program_Error with "Left cursor is bad";
270 if Right.Node.Element = null then
271 raise Program_Error with "Right cursor is bad";
274 pragma Assert (Vet (Left.Container.Tree, Left.Node),
275 "bad Left cursor in "">""");
277 pragma Assert (Vet (Right.Container.Tree, Right.Node),
278 "bad Right cursor in "">""");
280 -- L > R same as R < L
282 return Right.Node.Element.all < Left.Node.Element.all;
285 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
287 if Left.Node = null then
288 raise Constraint_Error with "Left cursor equals No_Element";
291 if Left.Node.Element = null then
292 raise Program_Error with "Left cursor is bad";
295 pragma Assert (Vet (Left.Container.Tree, Left.Node),
296 "bad Left cursor in "">""");
298 return Right < Left.Node.Element.all;
301 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
303 if Right.Node = null then
304 raise Constraint_Error with "Right cursor equals No_Element";
307 if Right.Node.Element = null then
308 raise Program_Error with "Right cursor is bad";
311 pragma Assert (Vet (Right.Container.Tree, Right.Node),
312 "bad Right cursor in "">""");
314 return Right.Node.Element.all < Left;
321 procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
323 procedure Adjust (Container : in out Set) is
325 Adjust (Container.Tree);
332 procedure Assign (Target : in out Set; Source : Set) is
334 if Target'Address = Source'Address then
339 Target.Union (Source);
346 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
347 Node : constant Node_Access :=
348 Element_Keys.Ceiling (Container.Tree, Item);
350 return (if Node = null then No_Element
351 else Cursor'(Container'Unrestricted_Access, Node));
359 new Tree_Operations.Generic_Clear (Delete_Tree);
361 procedure Clear (Container : in out Set) is
363 Clear (Container.Tree);
370 function Color (Node : Node_Access) return Color_Type is
375 ------------------------
376 -- Constant_Reference --
377 ------------------------
379 function Constant_Reference
380 (Container : aliased Set;
381 Position : Cursor) return Constant_Reference_Type
384 if Position.Container = null then
385 raise Constraint_Error with "Position cursor has no element";
388 if Position.Container /= Container'Unrestricted_Access then
389 raise Program_Error with
390 "Position cursor designates wrong container";
393 if Position.Node.Element = null then
394 raise Program_Error with "Node has no element";
398 (Vet (Container.Tree, Position.Node),
399 "bad cursor in Constant_Reference");
401 return (Element => Position.Node.Element.all'Access);
402 end Constant_Reference;
408 function Contains (Container : Set; Item : Element_Type) return Boolean is
410 return Find (Container, Item) /= No_Element;
417 function Copy (Source : Set) return Set is
419 return Target : Set do
420 Target.Assign (Source);
428 function Copy_Node (Source : Node_Access) return Node_Access is
429 Element : Element_Access := new Element_Type'(Source.Element.all);
432 return new Node_Type'(Parent => null,
435 Color => Source.Color,
439 Free_Element (Element);
447 procedure Delete (Container : in out Set; Position : in out Cursor) is
449 if Position.Node = null then
450 raise Constraint_Error with "Position cursor equals No_Element";
453 if Position.Node.Element = null then
454 raise Program_Error with "Position cursor is bad";
457 if Position.Container /= Container'Unrestricted_Access then
458 raise Program_Error with "Position cursor designates wrong set";
461 pragma Assert (Vet (Container.Tree, Position.Node),
462 "bad cursor in Delete");
464 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
465 Free (Position.Node);
466 Position.Container := null;
469 procedure Delete (Container : in out Set; Item : Element_Type) is
471 Element_Keys.Find (Container.Tree, Item);
475 raise Constraint_Error with "attempt to delete element not in set";
478 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
486 procedure Delete_First (Container : in out Set) is
487 Tree : Tree_Type renames Container.Tree;
488 X : Node_Access := Tree.First;
491 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
500 procedure Delete_Last (Container : in out Set) is
501 Tree : Tree_Type renames Container.Tree;
502 X : Node_Access := Tree.Last;
505 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
514 procedure Difference (Target : in out Set; Source : Set) is
516 Set_Ops.Difference (Target.Tree, Source.Tree);
519 function Difference (Left, Right : Set) return Set is
520 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
522 return Set'(Controlled with Tree);
529 function Element (Position : Cursor) return Element_Type is
531 if Position.Node = null then
532 raise Constraint_Error with "Position cursor equals No_Element";
535 if Position.Node.Element = null then
536 raise Program_Error with "Position cursor is bad";
539 pragma Assert (Vet (Position.Container.Tree, Position.Node),
540 "bad cursor in Element");
542 return Position.Node.Element.all;
545 -------------------------
546 -- Equivalent_Elements --
547 -------------------------
549 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
551 if Left < Right or else Right < Left then
556 end Equivalent_Elements;
558 ---------------------
559 -- Equivalent_Sets --
560 ---------------------
562 function Equivalent_Sets (Left, Right : Set) return Boolean is
564 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
565 pragma Inline (Is_Equivalent_Node_Node);
567 function Is_Equivalent is
568 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
570 -----------------------------
571 -- Is_Equivalent_Node_Node --
572 -----------------------------
574 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
576 if L.Element.all < R.Element.all then
578 elsif R.Element.all < L.Element.all then
583 end Is_Equivalent_Node_Node;
585 -- Start of processing for Equivalent_Sets
588 return Is_Equivalent (Left.Tree, Right.Tree);
595 procedure Exclude (Container : in out Set; Item : Element_Type) is
597 Element_Keys.Find (Container.Tree, Item);
600 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
609 procedure Finalize (Object : in out Iterator) is
611 if Object.Container /= null then
613 B : Natural renames Object.Container.all.Tree.Busy;
624 function Find (Container : Set; Item : Element_Type) return Cursor is
625 Node : constant Node_Access :=
626 Element_Keys.Find (Container.Tree, Item);
631 return Cursor'(Container'Unrestricted_Access, Node);
639 function First (Container : Set) return Cursor is
642 (if Container.Tree.First = null then No_Element
643 else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
646 function First (Object : Iterator) return Cursor is
648 -- The value of the iterator object's Node component influences the
649 -- behavior of the First (and Last) selector function.
651 -- When the Node component is null, this means the iterator object was
652 -- constructed without a start expression, in which case the (forward)
653 -- iteration starts from the (logical) beginning of the entire sequence
654 -- of items (corresponding to Container.First, for a forward iterator).
656 -- Otherwise, this is iteration over a partial sequence of items. When
657 -- the Node component is non-null, the iterator object was constructed
658 -- with a start expression, that specifies the position from which the
659 -- (forward) partial iteration begins.
661 if Object.Node = null then
662 return Object.Container.First;
664 return Cursor'(Object.Container, Object.Node);
672 function First_Element (Container : Set) return Element_Type is
674 if Container.Tree.First = null then
675 raise Constraint_Error with "set is empty";
677 return Container.Tree.First.Element.all;
685 function Floor (Container : Set; Item : Element_Type) return Cursor is
686 Node : constant Node_Access :=
687 Element_Keys.Floor (Container.Tree, Item);
689 return (if Node = null then No_Element
690 else Cursor'(Container'Unrestricted_Access, Node));
697 procedure Free (X : in out Node_Access) is
698 procedure Deallocate is
699 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
711 Free_Element (X.Element);
726 package body Generic_Keys is
728 -----------------------
729 -- Local Subprograms --
730 -----------------------
732 function Is_Greater_Key_Node
734 Right : Node_Access) return Boolean;
735 pragma Inline (Is_Greater_Key_Node);
737 function Is_Less_Key_Node
739 Right : Node_Access) return Boolean;
740 pragma Inline (Is_Less_Key_Node);
742 --------------------------
743 -- Local Instantiations --
744 --------------------------
747 new Red_Black_Trees.Generic_Keys
748 (Tree_Operations => Tree_Operations,
749 Key_Type => Key_Type,
750 Is_Less_Key_Node => Is_Less_Key_Node,
751 Is_Greater_Key_Node => Is_Greater_Key_Node);
757 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
758 Node : constant Node_Access :=
759 Key_Keys.Ceiling (Container.Tree, Key);
761 return (if Node = null then No_Element
762 else Cursor'(Container'Unrestricted_Access, Node));
765 ------------------------
766 -- Constant_Reference --
767 ------------------------
769 function Constant_Reference
770 (Container : aliased Set;
771 Key : Key_Type) return Constant_Reference_Type
773 Node : constant Node_Access :=
774 Key_Keys.Find (Container.Tree, Key);
778 raise Constraint_Error with "Key not in set";
781 if Node.Element = null then
782 raise Program_Error with "Node has no element";
785 return (Element => Node.Element.all'Access);
786 end Constant_Reference;
792 function Contains (Container : Set; Key : Key_Type) return Boolean is
794 return Find (Container, Key) /= No_Element;
801 procedure Delete (Container : in out Set; Key : Key_Type) is
802 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
806 raise Constraint_Error with "attempt to delete key not in set";
809 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
817 function Element (Container : Set; Key : Key_Type) return Element_Type is
818 Node : constant Node_Access :=
819 Key_Keys.Find (Container.Tree, Key);
822 raise Constraint_Error with "key not in set";
824 return Node.Element.all;
828 ---------------------
829 -- Equivalent_Keys --
830 ---------------------
832 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
834 if Left < Right or else Right < Left then
845 procedure Exclude (Container : in out Set; Key : Key_Type) is
846 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
849 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
858 function Find (Container : Set; Key : Key_Type) return Cursor is
859 Node : constant Node_Access :=
860 Key_Keys.Find (Container.Tree, Key);
862 return (if Node = null then No_Element
863 else Cursor'(Container'Unrestricted_Access, Node));
870 function Floor (Container : Set; Key : Key_Type) return Cursor is
871 Node : constant Node_Access :=
872 Key_Keys.Floor (Container.Tree, Key);
874 return (if Node = null then No_Element
875 else Cursor'(Container'Unrestricted_Access, Node));
878 -------------------------
879 -- Is_Greater_Key_Node --
880 -------------------------
882 function Is_Greater_Key_Node
884 Right : Node_Access) return Boolean
887 return Key (Right.Element.all) < Left;
888 end Is_Greater_Key_Node;
890 ----------------------
891 -- Is_Less_Key_Node --
892 ----------------------
894 function Is_Less_Key_Node
896 Right : Node_Access) return Boolean
899 return Left < Key (Right.Element.all);
900 end Is_Less_Key_Node;
906 function Key (Position : Cursor) return Key_Type is
908 if Position.Node = null then
909 raise Constraint_Error with
910 "Position cursor equals No_Element";
913 if Position.Node.Element = null then
914 raise Program_Error with
915 "Position cursor is bad";
918 pragma Assert (Vet (Position.Container.Tree, Position.Node),
919 "bad cursor in Key");
921 return Key (Position.Node.Element.all);
929 (Container : in out Set;
931 New_Item : Element_Type)
933 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
937 raise Constraint_Error with
938 "attempt to replace key not in set";
941 Replace_Element (Container.Tree, Node, New_Item);
949 (Stream : not null access Root_Stream_Type'Class;
950 Item : out Reference_Type)
953 raise Program_Error with "attempt to stream reference";
956 ------------------------------
957 -- Reference_Preserving_Key --
958 ------------------------------
960 function Reference_Preserving_Key
961 (Container : aliased in out Set;
962 Position : Cursor) return Reference_Type
965 if Position.Container = null then
966 raise Constraint_Error with "Position cursor has no element";
969 if Position.Container /= Container'Unrestricted_Access then
970 raise Program_Error with
971 "Position cursor designates wrong container";
974 if Position.Node.Element = null then
975 raise Program_Error with "Node has no element";
979 (Vet (Container.Tree, Position.Node),
980 "bad cursor in function Reference_Preserving_Key");
982 -- Some form of finalization will be required in order to actually
983 -- check that the key-part of the element designated by Position has
986 return (Element => Position.Node.Element.all'Access);
987 end Reference_Preserving_Key;
989 function Reference_Preserving_Key
990 (Container : aliased in out Set;
991 Key : Key_Type) return Reference_Type
993 Node : constant Node_Access :=
994 Key_Keys.Find (Container.Tree, Key);
998 raise Constraint_Error with "Key not in set";
1001 if Node.Element = null then
1002 raise Program_Error with "Node has no element";
1005 -- Some form of finalization will be required in order to actually
1006 -- check that the key-part of the element designated by Key has not
1009 return (Element => Node.Element.all'Access);
1010 end Reference_Preserving_Key;
1012 -----------------------------------
1013 -- Update_Element_Preserving_Key --
1014 -----------------------------------
1016 procedure Update_Element_Preserving_Key
1017 (Container : in out Set;
1019 Process : not null access
1020 procedure (Element : in out Element_Type))
1022 Tree : Tree_Type renames Container.Tree;
1025 if Position.Node = null then
1026 raise Constraint_Error with "Position cursor equals No_Element";
1029 if Position.Node.Element = null then
1030 raise Program_Error with "Position cursor is bad";
1033 if Position.Container /= Container'Unrestricted_Access then
1034 raise Program_Error with "Position cursor designates wrong set";
1037 pragma Assert (Vet (Container.Tree, Position.Node),
1038 "bad cursor in Update_Element_Preserving_Key");
1041 E : Element_Type renames Position.Node.Element.all;
1042 K : constant Key_Type := Key (E);
1044 B : Natural renames Tree.Busy;
1045 L : Natural renames Tree.Lock;
1063 if Equivalent_Keys (K, Key (E)) then
1069 X : Node_Access := Position.Node;
1071 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
1075 raise Program_Error with "key was modified";
1076 end Update_Element_Preserving_Key;
1083 (Stream : not null access Root_Stream_Type'Class;
1084 Item : Reference_Type)
1087 raise Program_Error with "attempt to stream reference";
1096 function Has_Element (Position : Cursor) return Boolean is
1098 return Position /= No_Element;
1105 procedure Include (Container : in out Set; New_Item : Element_Type) is
1112 Insert (Container, New_Item, Position, Inserted);
1114 if not Inserted then
1115 if Container.Tree.Lock > 0 then
1116 raise Program_Error with
1117 "attempt to tamper with elements (set is locked)";
1120 X := Position.Node.Element;
1121 Position.Node.Element := new Element_Type'(New_Item);
1131 (Container : in out Set;
1132 New_Item : Element_Type;
1133 Position : out Cursor;
1134 Inserted : out Boolean)
1143 Position.Container := Container'Unrestricted_Access;
1146 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1148 pragma Unreferenced (Position);
1153 Insert (Container, New_Item, Position, Inserted);
1155 if not Inserted then
1156 raise Constraint_Error with
1157 "attempt to insert element already in set";
1161 ----------------------
1162 -- Insert_Sans_Hint --
1163 ----------------------
1165 procedure Insert_Sans_Hint
1166 (Tree : in out Tree_Type;
1167 New_Item : Element_Type;
1168 Node : out Node_Access;
1169 Inserted : out Boolean)
1171 function New_Node return Node_Access;
1172 pragma Inline (New_Node);
1174 procedure Insert_Post is
1175 new Element_Keys.Generic_Insert_Post (New_Node);
1177 procedure Conditional_Insert_Sans_Hint is
1178 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1184 function New_Node return Node_Access is
1185 Element : Element_Access := new Element_Type'(New_Item);
1188 return new Node_Type'(Parent => null,
1191 Color => Red_Black_Trees.Red,
1192 Element => Element);
1195 Free_Element (Element);
1199 -- Start of processing for Insert_Sans_Hint
1202 Conditional_Insert_Sans_Hint
1207 end Insert_Sans_Hint;
1209 ----------------------
1210 -- Insert_With_Hint --
1211 ----------------------
1213 procedure Insert_With_Hint
1214 (Dst_Tree : in out Tree_Type;
1215 Dst_Hint : Node_Access;
1216 Src_Node : Node_Access;
1217 Dst_Node : out Node_Access)
1220 pragma Unreferenced (Success);
1222 function New_Node return Node_Access;
1224 procedure Insert_Post is
1225 new Element_Keys.Generic_Insert_Post (New_Node);
1227 procedure Insert_Sans_Hint is
1228 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1230 procedure Insert_With_Hint is
1231 new Element_Keys.Generic_Conditional_Insert_With_Hint
1239 function New_Node return Node_Access is
1240 Element : Element_Access :=
1241 new Element_Type'(Src_Node.Element.all);
1246 Node := new Node_Type;
1249 Free_Element (Element);
1253 Node.Element := Element;
1257 -- Start of processing for Insert_With_Hint
1263 Src_Node.Element.all,
1266 end Insert_With_Hint;
1272 procedure Intersection (Target : in out Set; Source : Set) is
1274 Set_Ops.Intersection (Target.Tree, Source.Tree);
1277 function Intersection (Left, Right : Set) return Set is
1278 Tree : constant Tree_Type :=
1279 Set_Ops.Intersection (Left.Tree, Right.Tree);
1281 return Set'(Controlled with Tree);
1288 function Is_Empty (Container : Set) return Boolean is
1290 return Container.Tree.Length = 0;
1293 -----------------------------
1294 -- Is_Greater_Element_Node --
1295 -----------------------------
1297 function Is_Greater_Element_Node
1298 (Left : Element_Type;
1299 Right : Node_Access) return Boolean
1302 -- e > node same as node < e
1304 return Right.Element.all < Left;
1305 end Is_Greater_Element_Node;
1307 --------------------------
1308 -- Is_Less_Element_Node --
1309 --------------------------
1311 function Is_Less_Element_Node
1312 (Left : Element_Type;
1313 Right : Node_Access) return Boolean
1316 return Left < Right.Element.all;
1317 end Is_Less_Element_Node;
1319 -----------------------
1320 -- Is_Less_Node_Node --
1321 -----------------------
1323 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1325 return L.Element.all < R.Element.all;
1326 end Is_Less_Node_Node;
1332 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1334 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1343 Process : not null access procedure (Position : Cursor))
1345 procedure Process_Node (Node : Node_Access);
1346 pragma Inline (Process_Node);
1348 procedure Local_Iterate is
1349 new Tree_Operations.Generic_Iteration (Process_Node);
1355 procedure Process_Node (Node : Node_Access) is
1357 Process (Cursor'(Container'Unrestricted_Access, Node));
1360 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
1361 B : Natural renames T.Busy;
1363 -- Start of processing for Iterate
1381 return Set_Iterator_Interfaces.Reversible_Iterator'class
1383 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1386 -- The value of the Node component influences the behavior of the First
1387 -- and Last selector functions of the iterator object. When the Node
1388 -- component is null (as is the case here), this means the iterator
1389 -- object was constructed without a start expression. This is a complete
1390 -- iterator, meaning that the iteration starts from the (logical)
1391 -- beginning of the sequence of items.
1393 -- Note: For a forward iterator, Container.First is the beginning, and
1394 -- for a reverse iterator, Container.Last is the beginning.
1396 return It : constant Iterator :=
1397 Iterator'(Limited_Controlled with
1398 Container => Container'Unrestricted_Access,
1408 return Set_Iterator_Interfaces.Reversible_Iterator'class
1410 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1413 -- It was formerly the case that when Start = No_Element, the partial
1414 -- iterator was defined to behave the same as for a complete iterator,
1415 -- and iterate over the entire sequence of items. However, those
1416 -- semantics were unintuitive and arguably error-prone (it is too easy
1417 -- to accidentally create an endless loop), and so they were changed,
1418 -- per the ARG meeting in Denver on 2011/11. However, there was no
1419 -- consensus about what positive meaning this corner case should have,
1420 -- and so it was decided to simply raise an exception. This does imply,
1421 -- however, that it is not possible to use a partial iterator to specify
1422 -- an empty sequence of items.
1424 if Start = No_Element then
1425 raise Constraint_Error with
1426 "Start position for iterator equals No_Element";
1429 if Start.Container /= Container'Unrestricted_Access then
1430 raise Program_Error with
1431 "Start cursor of Iterate designates wrong set";
1434 pragma Assert (Vet (Container.Tree, Start.Node),
1435 "Start cursor of Iterate is bad");
1437 -- The value of the Node component influences the behavior of the First
1438 -- and Last selector functions of the iterator object. When the Node
1439 -- component is non-null (as is the case here), it means that this is a
1440 -- partial iteration, over a subset of the complete sequence of
1441 -- items. The iterator object was constructed with a start expression,
1442 -- indicating the position from which the iteration begins. Note that
1443 -- the start position has the same value irrespective of whether this is
1444 -- a forward or reverse iteration.
1446 return It : constant Iterator :=
1447 (Limited_Controlled with
1448 Container => Container'Unrestricted_Access,
1459 function Last (Container : Set) return Cursor is
1462 (if Container.Tree.Last = null then No_Element
1463 else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
1466 function Last (Object : Iterator) return Cursor is
1468 -- The value of the iterator object's Node component influences the
1469 -- behavior of the Last (and First) selector function.
1471 -- When the Node component is null, this means the iterator object was
1472 -- constructed without a start expression, in which case the (reverse)
1473 -- iteration starts from the (logical) beginning of the entire sequence
1474 -- (corresponding to Container.Last, for a reverse iterator).
1476 -- Otherwise, this is iteration over a partial sequence of items. When
1477 -- the Node component is non-null, the iterator object was constructed
1478 -- with a start expression, that specifies the position from which the
1479 -- (reverse) partial iteration begins.
1481 if Object.Node = null then
1482 return Object.Container.Last;
1484 return Cursor'(Object.Container, Object.Node);
1492 function Last_Element (Container : Set) return Element_Type is
1494 if Container.Tree.Last = null then
1495 raise Constraint_Error with "set is empty";
1497 return Container.Tree.Last.Element.all;
1505 function Left (Node : Node_Access) return Node_Access is
1514 function Length (Container : Set) return Count_Type is
1516 return Container.Tree.Length;
1523 procedure Move is new Tree_Operations.Generic_Move (Clear);
1525 procedure Move (Target : in out Set; Source : in out Set) is
1527 Move (Target => Target.Tree, Source => Source.Tree);
1534 procedure Next (Position : in out Cursor) is
1536 Position := Next (Position);
1539 function Next (Position : Cursor) return Cursor is
1541 if Position = No_Element then
1545 if Position.Node.Element = null then
1546 raise Program_Error with "Position cursor is bad";
1549 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1550 "bad cursor in Next");
1553 Node : constant Node_Access :=
1554 Tree_Operations.Next (Position.Node);
1556 return (if Node = null then No_Element
1557 else Cursor'(Position.Container, Node));
1563 Position : Cursor) return Cursor
1566 if Position.Container = null then
1570 if Position.Container /= Object.Container then
1571 raise Program_Error with
1572 "Position cursor of Next designates wrong set";
1575 return Next (Position);
1582 function Overlap (Left, Right : Set) return Boolean is
1584 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1591 function Parent (Node : Node_Access) return Node_Access is
1600 procedure Previous (Position : in out Cursor) is
1602 Position := Previous (Position);
1605 function Previous (Position : Cursor) return Cursor is
1607 if Position = No_Element then
1611 if Position.Node.Element = null then
1612 raise Program_Error with "Position cursor is bad";
1615 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1616 "bad cursor in Previous");
1619 Node : constant Node_Access :=
1620 Tree_Operations.Previous (Position.Node);
1622 return (if Node = null then No_Element
1623 else Cursor'(Position.Container, Node));
1629 Position : Cursor) return Cursor
1632 if Position.Container = null then
1636 if Position.Container /= Object.Container then
1637 raise Program_Error with
1638 "Position cursor of Previous designates wrong set";
1641 return Previous (Position);
1648 procedure Query_Element
1650 Process : not null access procedure (Element : Element_Type))
1653 if Position.Node = null then
1654 raise Constraint_Error with "Position cursor equals No_Element";
1657 if Position.Node.Element = null then
1658 raise Program_Error with "Position cursor is bad";
1661 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1662 "bad cursor in Query_Element");
1665 T : Tree_Type renames Position.Container.Tree;
1667 B : Natural renames T.Busy;
1668 L : Natural renames T.Lock;
1675 Process (Position.Node.Element.all);
1693 (Stream : not null access Root_Stream_Type'Class;
1694 Container : out Set)
1697 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1698 pragma Inline (Read_Node);
1701 new Tree_Operations.Generic_Read (Clear, Read_Node);
1708 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1710 Node : Node_Access := new Node_Type;
1713 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1718 Free (Node); -- Note that Free deallocates elem too
1722 -- Start of processing for Read
1725 Read (Stream, Container.Tree);
1729 (Stream : not null access Root_Stream_Type'Class;
1733 raise Program_Error with "attempt to stream set cursor";
1737 (Stream : not null access Root_Stream_Type'Class;
1738 Item : out Constant_Reference_Type)
1741 raise Program_Error with "attempt to stream reference";
1748 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1749 Node : constant Node_Access :=
1750 Element_Keys.Find (Container.Tree, New_Item);
1753 pragma Warnings (Off, X);
1757 raise Constraint_Error with "attempt to replace element not in set";
1760 if Container.Tree.Lock > 0 then
1761 raise Program_Error with
1762 "attempt to tamper with elements (set is locked)";
1766 Node.Element := new Element_Type'(New_Item);
1770 ---------------------
1771 -- Replace_Element --
1772 ---------------------
1774 procedure Replace_Element
1775 (Tree : in out Tree_Type;
1777 Item : Element_Type)
1779 pragma Assert (Node /= null);
1780 pragma Assert (Node.Element /= null);
1782 function New_Node return Node_Access;
1783 pragma Inline (New_Node);
1785 procedure Local_Insert_Post is
1786 new Element_Keys.Generic_Insert_Post (New_Node);
1788 procedure Local_Insert_Sans_Hint is
1789 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1791 procedure Local_Insert_With_Hint is
1792 new Element_Keys.Generic_Conditional_Insert_With_Hint
1794 Local_Insert_Sans_Hint);
1800 function New_Node return Node_Access is
1802 Node.Element := new Element_Type'(Item); -- OK if fails
1804 Node.Parent := null;
1811 Result : Node_Access;
1814 X : Element_Access := Node.Element;
1816 -- Start of processing for Replace_Element
1819 if Item < Node.Element.all
1820 or else Node.Element.all < Item
1825 if Tree.Lock > 0 then
1826 raise Program_Error with
1827 "attempt to tamper with elements (set is locked)";
1830 Node.Element := new Element_Type'(Item);
1836 Hint := Element_Keys.Ceiling (Tree, Item);
1841 elsif Item < Hint.Element.all then
1843 if Tree.Lock > 0 then
1844 raise Program_Error with
1845 "attempt to tamper with elements (set is locked)";
1848 Node.Element := new Element_Type'(Item);
1855 pragma Assert (not (Hint.Element.all < Item));
1856 raise Program_Error with "attempt to replace existing element";
1859 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1861 Local_Insert_With_Hint
1866 Inserted => Inserted);
1868 pragma Assert (Inserted);
1869 pragma Assert (Result = Node);
1872 end Replace_Element;
1874 procedure Replace_Element
1875 (Container : in out Set;
1877 New_Item : Element_Type)
1880 if Position.Node = null then
1881 raise Constraint_Error with "Position cursor equals No_Element";
1884 if Position.Node.Element = null then
1885 raise Program_Error with "Position cursor is bad";
1888 if Position.Container /= Container'Unrestricted_Access then
1889 raise Program_Error with "Position cursor designates wrong set";
1892 pragma Assert (Vet (Container.Tree, Position.Node),
1893 "bad cursor in Replace_Element");
1895 Replace_Element (Container.Tree, Position.Node, New_Item);
1896 end Replace_Element;
1898 ---------------------
1899 -- Reverse_Iterate --
1900 ---------------------
1902 procedure Reverse_Iterate
1904 Process : not null access procedure (Position : Cursor))
1906 procedure Process_Node (Node : Node_Access);
1907 pragma Inline (Process_Node);
1909 procedure Local_Reverse_Iterate is
1910 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1916 procedure Process_Node (Node : Node_Access) is
1918 Process (Cursor'(Container'Unrestricted_Access, Node));
1921 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1922 B : Natural renames T.Busy;
1924 -- Start of processing for Reverse_Iterate
1930 Local_Reverse_Iterate (T);
1938 end Reverse_Iterate;
1944 function Right (Node : Node_Access) return Node_Access is
1953 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1955 Node.Color := Color;
1962 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1971 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1973 Node.Parent := Parent;
1980 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1982 Node.Right := Right;
1985 --------------------------
1986 -- Symmetric_Difference --
1987 --------------------------
1989 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1991 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1992 end Symmetric_Difference;
1994 function Symmetric_Difference (Left, Right : Set) return Set is
1995 Tree : constant Tree_Type :=
1996 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1998 return Set'(Controlled with Tree);
1999 end Symmetric_Difference;
2005 function To_Set (New_Item : Element_Type) return Set is
2009 pragma Unreferenced (Node, Inserted);
2011 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
2012 return Set'(Controlled with Tree);
2019 procedure Union (Target : in out Set; Source : Set) is
2021 Set_Ops.Union (Target.Tree, Source.Tree);
2024 function Union (Left, Right : Set) return Set is
2025 Tree : constant Tree_Type :=
2026 Set_Ops.Union (Left.Tree, Right.Tree);
2028 return Set'(Controlled with Tree);
2036 (Stream : not null access Root_Stream_Type'Class;
2039 procedure Write_Node
2040 (Stream : not null access Root_Stream_Type'Class;
2041 Node : Node_Access);
2042 pragma Inline (Write_Node);
2045 new Tree_Operations.Generic_Write (Write_Node);
2051 procedure Write_Node
2052 (Stream : not null access Root_Stream_Type'Class;
2056 Element_Type'Output (Stream, Node.Element.all);
2059 -- Start of processing for Write
2062 Write (Stream, Container.Tree);
2066 (Stream : not null access Root_Stream_Type'Class;
2070 raise Program_Error with "attempt to stream set cursor";
2074 (Stream : not null access Root_Stream_Type'Class;
2075 Item : Constant_Reference_Type)
2078 raise Program_Error with "attempt to stream reference";
2081 end Ada.Containers.Indefinite_Ordered_Sets;