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
379 function Contains (Container : Set; Item : Element_Type) return Boolean is
381 return Find (Container, Item) /= No_Element;
388 function Copy (Source : Set) return Set is
390 return Target : Set do
391 Target.Assign (Source);
399 function Copy_Node (Source : Node_Access) return Node_Access is
400 Element : Element_Access := new Element_Type'(Source.Element.all);
403 return new Node_Type'(Parent => null,
406 Color => Source.Color,
410 Free_Element (Element);
418 procedure Delete (Container : in out Set; Position : in out Cursor) is
420 if Position.Node = null then
421 raise Constraint_Error with "Position cursor equals No_Element";
424 if Position.Node.Element = null then
425 raise Program_Error with "Position cursor is bad";
428 if Position.Container /= Container'Unrestricted_Access then
429 raise Program_Error with "Position cursor designates wrong set";
432 pragma Assert (Vet (Container.Tree, Position.Node),
433 "bad cursor in Delete");
435 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
436 Free (Position.Node);
437 Position.Container := null;
440 procedure Delete (Container : in out Set; Item : Element_Type) is
442 Element_Keys.Find (Container.Tree, Item);
446 raise Constraint_Error with "attempt to delete element not in set";
449 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
457 procedure Delete_First (Container : in out Set) is
458 Tree : Tree_Type renames Container.Tree;
459 X : Node_Access := Tree.First;
462 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
471 procedure Delete_Last (Container : in out Set) is
472 Tree : Tree_Type renames Container.Tree;
473 X : Node_Access := Tree.Last;
476 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
485 procedure Difference (Target : in out Set; Source : Set) is
487 Set_Ops.Difference (Target.Tree, Source.Tree);
490 function Difference (Left, Right : Set) return Set is
491 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
493 return Set'(Controlled with Tree);
500 function Element (Position : Cursor) return Element_Type is
502 if Position.Node = null then
503 raise Constraint_Error with "Position cursor equals No_Element";
506 if Position.Node.Element = null then
507 raise Program_Error with "Position cursor is bad";
510 pragma Assert (Vet (Position.Container.Tree, Position.Node),
511 "bad cursor in Element");
513 return Position.Node.Element.all;
516 -------------------------
517 -- Equivalent_Elements --
518 -------------------------
520 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
522 if Left < Right or else Right < Left then
527 end Equivalent_Elements;
529 ---------------------
530 -- Equivalent_Sets --
531 ---------------------
533 function Equivalent_Sets (Left, Right : Set) return Boolean is
535 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
536 pragma Inline (Is_Equivalent_Node_Node);
538 function Is_Equivalent is
539 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
541 -----------------------------
542 -- Is_Equivalent_Node_Node --
543 -----------------------------
545 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
547 if L.Element.all < R.Element.all then
549 elsif R.Element.all < L.Element.all then
554 end Is_Equivalent_Node_Node;
556 -- Start of processing for Equivalent_Sets
559 return Is_Equivalent (Left.Tree, Right.Tree);
566 procedure Exclude (Container : in out Set; Item : Element_Type) is
568 Element_Keys.Find (Container.Tree, Item);
571 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
580 procedure Finalize (Object : in out Iterator) is
582 if Object.Container /= null then
584 B : Natural renames Object.Container.all.Tree.Busy;
595 function Find (Container : Set; Item : Element_Type) return Cursor is
596 Node : constant Node_Access :=
597 Element_Keys.Find (Container.Tree, Item);
602 return Cursor'(Container'Unrestricted_Access, Node);
610 function First (Container : Set) return Cursor is
613 (if Container.Tree.First = null then No_Element
614 else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
617 function First (Object : Iterator) return Cursor is
619 -- The value of the iterator object's Node component influences the
620 -- behavior of the First (and Last) selector function.
622 -- When the Node component is null, this means the iterator object was
623 -- constructed without a start expression, in which case the (forward)
624 -- iteration starts from the (logical) beginning of the entire sequence
625 -- of items (corresponding to Container.First, for a forward iterator).
627 -- Otherwise, this is iteration over a partial sequence of items. When
628 -- the Node component is non-null, the iterator object was constructed
629 -- with a start expression, that specifies the position from which the
630 -- (forward) partial iteration begins.
632 if Object.Node = null then
633 return Object.Container.First;
635 return Cursor'(Object.Container, Object.Node);
643 function First_Element (Container : Set) return Element_Type is
645 if Container.Tree.First = null then
646 raise Constraint_Error with "set is empty";
648 return Container.Tree.First.Element.all;
656 function Floor (Container : Set; Item : Element_Type) return Cursor is
657 Node : constant Node_Access :=
658 Element_Keys.Floor (Container.Tree, Item);
660 return (if Node = null then No_Element
661 else Cursor'(Container'Unrestricted_Access, Node));
668 procedure Free (X : in out Node_Access) is
669 procedure Deallocate is
670 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
682 Free_Element (X.Element);
697 package body Generic_Keys is
699 -----------------------
700 -- Local Subprograms --
701 -----------------------
703 function Is_Greater_Key_Node
705 Right : Node_Access) return Boolean;
706 pragma Inline (Is_Greater_Key_Node);
708 function Is_Less_Key_Node
710 Right : Node_Access) return Boolean;
711 pragma Inline (Is_Less_Key_Node);
713 --------------------------
714 -- Local Instantiations --
715 --------------------------
718 new Red_Black_Trees.Generic_Keys
719 (Tree_Operations => Tree_Operations,
720 Key_Type => Key_Type,
721 Is_Less_Key_Node => Is_Less_Key_Node,
722 Is_Greater_Key_Node => Is_Greater_Key_Node);
728 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
729 Node : constant Node_Access :=
730 Key_Keys.Ceiling (Container.Tree, Key);
732 return (if Node = null then No_Element
733 else Cursor'(Container'Unrestricted_Access, Node));
740 function Contains (Container : Set; Key : Key_Type) return Boolean is
742 return Find (Container, Key) /= No_Element;
749 procedure Delete (Container : in out Set; Key : Key_Type) is
750 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
754 raise Constraint_Error with "attempt to delete key not in set";
757 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
765 function Element (Container : Set; Key : Key_Type) return Element_Type is
766 Node : constant Node_Access :=
767 Key_Keys.Find (Container.Tree, Key);
770 raise Constraint_Error with "key not in set";
772 return Node.Element.all;
776 ---------------------
777 -- Equivalent_Keys --
778 ---------------------
780 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
782 if Left < Right or else Right < Left then
793 procedure Exclude (Container : in out Set; Key : Key_Type) is
794 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
797 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
806 function Find (Container : Set; Key : Key_Type) return Cursor is
807 Node : constant Node_Access :=
808 Key_Keys.Find (Container.Tree, Key);
810 return (if Node = null then No_Element
811 else Cursor'(Container'Unrestricted_Access, Node));
818 function Floor (Container : Set; Key : Key_Type) return Cursor is
819 Node : constant Node_Access :=
820 Key_Keys.Floor (Container.Tree, Key);
822 return (if Node = null then No_Element
823 else Cursor'(Container'Unrestricted_Access, Node));
826 -------------------------
827 -- Is_Greater_Key_Node --
828 -------------------------
830 function Is_Greater_Key_Node
832 Right : Node_Access) return Boolean
835 return Key (Right.Element.all) < Left;
836 end Is_Greater_Key_Node;
838 ----------------------
839 -- Is_Less_Key_Node --
840 ----------------------
842 function Is_Less_Key_Node
844 Right : Node_Access) return Boolean
847 return Left < Key (Right.Element.all);
848 end Is_Less_Key_Node;
854 function Key (Position : Cursor) return Key_Type is
856 if Position.Node = null then
857 raise Constraint_Error with
858 "Position cursor equals No_Element";
861 if Position.Node.Element = null then
862 raise Program_Error with
863 "Position cursor is bad";
866 pragma Assert (Vet (Position.Container.Tree, Position.Node),
867 "bad cursor in Key");
869 return Key (Position.Node.Element.all);
877 (Container : in out Set;
879 New_Item : Element_Type)
881 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
885 raise Constraint_Error with
886 "attempt to replace key not in set";
889 Replace_Element (Container.Tree, Node, New_Item);
892 -----------------------------------
893 -- Update_Element_Preserving_Key --
894 -----------------------------------
896 procedure Update_Element_Preserving_Key
897 (Container : in out Set;
899 Process : not null access
900 procedure (Element : in out Element_Type))
902 Tree : Tree_Type renames Container.Tree;
905 if Position.Node = null then
906 raise Constraint_Error with "Position cursor equals No_Element";
909 if Position.Node.Element = null then
910 raise Program_Error with "Position cursor is bad";
913 if Position.Container /= Container'Unrestricted_Access then
914 raise Program_Error with "Position cursor designates wrong set";
917 pragma Assert (Vet (Container.Tree, Position.Node),
918 "bad cursor in Update_Element_Preserving_Key");
921 E : Element_Type renames Position.Node.Element.all;
922 K : constant Key_Type := Key (E);
924 B : Natural renames Tree.Busy;
925 L : Natural renames Tree.Lock;
943 if Equivalent_Keys (K, Key (E)) then
949 X : Node_Access := Position.Node;
951 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
955 raise Program_Error with "key was modified";
956 end Update_Element_Preserving_Key;
958 function Reference_Preserving_Key
959 (Container : aliased in out Set;
960 Key : Key_Type) return Constant_Reference_Type
962 Position : constant Cursor := Find (Container, Key);
965 if Position.Container = null then
966 raise Constraint_Error with "Position cursor has no element";
969 return (Element => Position.Node.Element);
970 end Reference_Preserving_Key;
972 function Reference_Preserving_Key
973 (Container : aliased in out Set;
974 Key : Key_Type) return Reference_Type
976 Position : constant Cursor := Find (Container, Key);
979 if Position.Container = null then
980 raise Constraint_Error with "Position cursor has no element";
983 return (Element => Position.Node.Element);
984 end Reference_Preserving_Key;
987 (Stream : not null access Root_Stream_Type'Class;
988 Item : out Reference_Type)
991 raise Program_Error with "attempt to stream reference";
995 (Stream : not null access Root_Stream_Type'Class;
996 Item : Reference_Type)
999 raise Program_Error with "attempt to stream reference";
1008 function Has_Element (Position : Cursor) return Boolean is
1010 return Position /= No_Element;
1017 procedure Include (Container : in out Set; New_Item : Element_Type) is
1024 Insert (Container, New_Item, Position, Inserted);
1026 if not Inserted then
1027 if Container.Tree.Lock > 0 then
1028 raise Program_Error with
1029 "attempt to tamper with elements (set is locked)";
1032 X := Position.Node.Element;
1033 Position.Node.Element := new Element_Type'(New_Item);
1043 (Container : in out Set;
1044 New_Item : Element_Type;
1045 Position : out Cursor;
1046 Inserted : out Boolean)
1055 Position.Container := Container'Unrestricted_Access;
1058 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1060 pragma Unreferenced (Position);
1065 Insert (Container, New_Item, Position, Inserted);
1067 if not Inserted then
1068 raise Constraint_Error with
1069 "attempt to insert element already in set";
1073 ----------------------
1074 -- Insert_Sans_Hint --
1075 ----------------------
1077 procedure Insert_Sans_Hint
1078 (Tree : in out Tree_Type;
1079 New_Item : Element_Type;
1080 Node : out Node_Access;
1081 Inserted : out Boolean)
1083 function New_Node return Node_Access;
1084 pragma Inline (New_Node);
1086 procedure Insert_Post is
1087 new Element_Keys.Generic_Insert_Post (New_Node);
1089 procedure Conditional_Insert_Sans_Hint is
1090 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1096 function New_Node return Node_Access is
1097 Element : Element_Access := new Element_Type'(New_Item);
1100 return new Node_Type'(Parent => null,
1103 Color => Red_Black_Trees.Red,
1104 Element => Element);
1107 Free_Element (Element);
1111 -- Start of processing for Insert_Sans_Hint
1114 Conditional_Insert_Sans_Hint
1119 end Insert_Sans_Hint;
1121 ----------------------
1122 -- Insert_With_Hint --
1123 ----------------------
1125 procedure Insert_With_Hint
1126 (Dst_Tree : in out Tree_Type;
1127 Dst_Hint : Node_Access;
1128 Src_Node : Node_Access;
1129 Dst_Node : out Node_Access)
1132 pragma Unreferenced (Success);
1134 function New_Node return Node_Access;
1136 procedure Insert_Post is
1137 new Element_Keys.Generic_Insert_Post (New_Node);
1139 procedure Insert_Sans_Hint is
1140 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1142 procedure Insert_With_Hint is
1143 new Element_Keys.Generic_Conditional_Insert_With_Hint
1151 function New_Node return Node_Access is
1152 Element : Element_Access :=
1153 new Element_Type'(Src_Node.Element.all);
1158 Node := new Node_Type;
1161 Free_Element (Element);
1165 Node.Element := Element;
1169 -- Start of processing for Insert_With_Hint
1175 Src_Node.Element.all,
1178 end Insert_With_Hint;
1184 procedure Intersection (Target : in out Set; Source : Set) is
1186 Set_Ops.Intersection (Target.Tree, Source.Tree);
1189 function Intersection (Left, Right : Set) return Set is
1190 Tree : constant Tree_Type :=
1191 Set_Ops.Intersection (Left.Tree, Right.Tree);
1193 return Set'(Controlled with Tree);
1200 function Is_Empty (Container : Set) return Boolean is
1202 return Container.Tree.Length = 0;
1205 -----------------------------
1206 -- Is_Greater_Element_Node --
1207 -----------------------------
1209 function Is_Greater_Element_Node
1210 (Left : Element_Type;
1211 Right : Node_Access) return Boolean
1214 -- e > node same as node < e
1216 return Right.Element.all < Left;
1217 end Is_Greater_Element_Node;
1219 --------------------------
1220 -- Is_Less_Element_Node --
1221 --------------------------
1223 function Is_Less_Element_Node
1224 (Left : Element_Type;
1225 Right : Node_Access) return Boolean
1228 return Left < Right.Element.all;
1229 end Is_Less_Element_Node;
1231 -----------------------
1232 -- Is_Less_Node_Node --
1233 -----------------------
1235 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1237 return L.Element.all < R.Element.all;
1238 end Is_Less_Node_Node;
1244 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1246 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1255 Process : not null access procedure (Position : Cursor))
1257 procedure Process_Node (Node : Node_Access);
1258 pragma Inline (Process_Node);
1260 procedure Local_Iterate is
1261 new Tree_Operations.Generic_Iteration (Process_Node);
1267 procedure Process_Node (Node : Node_Access) is
1269 Process (Cursor'(Container'Unrestricted_Access, Node));
1272 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
1273 B : Natural renames T.Busy;
1275 -- Start of processing for Iterate
1293 return Set_Iterator_Interfaces.Reversible_Iterator'class
1295 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1298 -- The value of the Node component influences the behavior of the First
1299 -- and Last selector functions of the iterator object. When the Node
1300 -- component is null (as is the case here), this means the iterator
1301 -- object was constructed without a start expression. This is a complete
1302 -- iterator, meaning that the iteration starts from the (logical)
1303 -- beginning of the sequence of items.
1305 -- Note: For a forward iterator, Container.First is the beginning, and
1306 -- for a reverse iterator, Container.Last is the beginning.
1308 return It : constant Iterator :=
1309 Iterator'(Limited_Controlled with
1310 Container => Container'Unrestricted_Access,
1320 return Set_Iterator_Interfaces.Reversible_Iterator'class
1322 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1325 -- It was formerly the case that when Start = No_Element, the partial
1326 -- iterator was defined to behave the same as for a complete iterator,
1327 -- and iterate over the entire sequence of items. However, those
1328 -- semantics were unintuitive and arguably error-prone (it is too easy
1329 -- to accidentally create an endless loop), and so they were changed,
1330 -- per the ARG meeting in Denver on 2011/11. However, there was no
1331 -- consensus about what positive meaning this corner case should have,
1332 -- and so it was decided to simply raise an exception. This does imply,
1333 -- however, that it is not possible to use a partial iterator to specify
1334 -- an empty sequence of items.
1336 if Start = No_Element then
1337 raise Constraint_Error with
1338 "Start position for iterator equals No_Element";
1341 if Start.Container /= Container'Unrestricted_Access then
1342 raise Program_Error with
1343 "Start cursor of Iterate designates wrong set";
1346 pragma Assert (Vet (Container.Tree, Start.Node),
1347 "Start cursor of Iterate is bad");
1349 -- The value of the Node component influences the behavior of the First
1350 -- and Last selector functions of the iterator object. When the Node
1351 -- component is non-null (as is the case here), it means that this is a
1352 -- partial iteration, over a subset of the complete sequence of
1353 -- items. The iterator object was constructed with a start expression,
1354 -- indicating the position from which the iteration begins. Note that
1355 -- the start position has the same value irrespective of whether this is
1356 -- a forward or reverse iteration.
1358 return It : constant Iterator :=
1359 (Limited_Controlled with
1360 Container => Container'Unrestricted_Access,
1371 function Last (Container : Set) return Cursor is
1374 (if Container.Tree.Last = null then No_Element
1375 else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
1378 function Last (Object : Iterator) return Cursor is
1380 -- The value of the iterator object's Node component influences the
1381 -- behavior of the Last (and First) selector function.
1383 -- When the Node component is null, this means the iterator object was
1384 -- constructed without a start expression, in which case the (reverse)
1385 -- iteration starts from the (logical) beginning of the entire sequence
1386 -- (corresponding to Container.Last, for a reverse iterator).
1388 -- Otherwise, this is iteration over a partial sequence of items. When
1389 -- the Node component is non-null, the iterator object was constructed
1390 -- with a start expression, that specifies the position from which the
1391 -- (reverse) partial iteration begins.
1393 if Object.Node = null then
1394 return Object.Container.Last;
1396 return Cursor'(Object.Container, Object.Node);
1404 function Last_Element (Container : Set) return Element_Type is
1406 if Container.Tree.Last = null then
1407 raise Constraint_Error with "set is empty";
1409 return Container.Tree.Last.Element.all;
1417 function Left (Node : Node_Access) return Node_Access is
1426 function Length (Container : Set) return Count_Type is
1428 return Container.Tree.Length;
1435 procedure Move is new Tree_Operations.Generic_Move (Clear);
1437 procedure Move (Target : in out Set; Source : in out Set) is
1439 Move (Target => Target.Tree, Source => Source.Tree);
1446 procedure Next (Position : in out Cursor) is
1448 Position := Next (Position);
1451 function Next (Position : Cursor) return Cursor is
1453 if Position = No_Element then
1457 if Position.Node.Element = null then
1458 raise Program_Error with "Position cursor is bad";
1461 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1462 "bad cursor in Next");
1465 Node : constant Node_Access :=
1466 Tree_Operations.Next (Position.Node);
1468 return (if Node = null then No_Element
1469 else Cursor'(Position.Container, Node));
1475 Position : Cursor) return Cursor
1478 if Position.Container = null then
1482 if Position.Container /= Object.Container then
1483 raise Program_Error with
1484 "Position cursor of Next designates wrong set";
1487 return Next (Position);
1494 function Overlap (Left, Right : Set) return Boolean is
1496 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1503 function Parent (Node : Node_Access) return Node_Access is
1512 procedure Previous (Position : in out Cursor) is
1514 Position := Previous (Position);
1517 function Previous (Position : Cursor) return Cursor is
1519 if Position = No_Element then
1523 if Position.Node.Element = null then
1524 raise Program_Error with "Position cursor is bad";
1527 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1528 "bad cursor in Previous");
1531 Node : constant Node_Access :=
1532 Tree_Operations.Previous (Position.Node);
1534 return (if Node = null then No_Element
1535 else Cursor'(Position.Container, Node));
1541 Position : Cursor) return Cursor
1544 if Position.Container = null then
1548 if Position.Container /= Object.Container then
1549 raise Program_Error with
1550 "Position cursor of Previous designates wrong set";
1553 return Previous (Position);
1560 procedure Query_Element
1562 Process : not null access procedure (Element : Element_Type))
1565 if Position.Node = null then
1566 raise Constraint_Error with "Position cursor equals No_Element";
1569 if Position.Node.Element = null then
1570 raise Program_Error with "Position cursor is bad";
1573 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1574 "bad cursor in Query_Element");
1577 T : Tree_Type renames Position.Container.Tree;
1579 B : Natural renames T.Busy;
1580 L : Natural renames T.Lock;
1587 Process (Position.Node.Element.all);
1605 (Stream : not null access Root_Stream_Type'Class;
1606 Container : out Set)
1609 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1610 pragma Inline (Read_Node);
1613 new Tree_Operations.Generic_Read (Clear, Read_Node);
1620 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1622 Node : Node_Access := new Node_Type;
1625 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1630 Free (Node); -- Note that Free deallocates elem too
1634 -- Start of processing for Read
1637 Read (Stream, Container.Tree);
1641 (Stream : not null access Root_Stream_Type'Class;
1645 raise Program_Error with "attempt to stream set cursor";
1649 (Stream : not null access Root_Stream_Type'Class;
1650 Item : out Constant_Reference_Type)
1653 raise Program_Error with "attempt to stream reference";
1660 function Constant_Reference (Container : Set; Position : Cursor)
1661 return Constant_Reference_Type
1663 pragma Unreferenced (Container);
1665 if Position.Container = null then
1666 raise Constraint_Error with "Position cursor has no element";
1669 return (Element => Position.Node.Element.all'Access);
1670 end Constant_Reference;
1676 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1677 Node : constant Node_Access :=
1678 Element_Keys.Find (Container.Tree, New_Item);
1681 pragma Warnings (Off, X);
1685 raise Constraint_Error with "attempt to replace element not in set";
1688 if Container.Tree.Lock > 0 then
1689 raise Program_Error with
1690 "attempt to tamper with elements (set is locked)";
1694 Node.Element := new Element_Type'(New_Item);
1698 ---------------------
1699 -- Replace_Element --
1700 ---------------------
1702 procedure Replace_Element
1703 (Tree : in out Tree_Type;
1705 Item : Element_Type)
1707 pragma Assert (Node /= null);
1708 pragma Assert (Node.Element /= null);
1710 function New_Node return Node_Access;
1711 pragma Inline (New_Node);
1713 procedure Local_Insert_Post is
1714 new Element_Keys.Generic_Insert_Post (New_Node);
1716 procedure Local_Insert_Sans_Hint is
1717 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1719 procedure Local_Insert_With_Hint is
1720 new Element_Keys.Generic_Conditional_Insert_With_Hint
1722 Local_Insert_Sans_Hint);
1728 function New_Node return Node_Access is
1730 Node.Element := new Element_Type'(Item); -- OK if fails
1732 Node.Parent := null;
1739 Result : Node_Access;
1742 X : Element_Access := Node.Element;
1744 -- Start of processing for Replace_Element
1747 if Item < Node.Element.all
1748 or else Node.Element.all < Item
1753 if Tree.Lock > 0 then
1754 raise Program_Error with
1755 "attempt to tamper with elements (set is locked)";
1758 Node.Element := new Element_Type'(Item);
1764 Hint := Element_Keys.Ceiling (Tree, Item);
1769 elsif Item < Hint.Element.all then
1771 if Tree.Lock > 0 then
1772 raise Program_Error with
1773 "attempt to tamper with elements (set is locked)";
1776 Node.Element := new Element_Type'(Item);
1783 pragma Assert (not (Hint.Element.all < Item));
1784 raise Program_Error with "attempt to replace existing element";
1787 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1789 Local_Insert_With_Hint
1794 Inserted => Inserted);
1796 pragma Assert (Inserted);
1797 pragma Assert (Result = Node);
1800 end Replace_Element;
1802 procedure Replace_Element
1803 (Container : in out Set;
1805 New_Item : Element_Type)
1808 if Position.Node = null then
1809 raise Constraint_Error with "Position cursor equals No_Element";
1812 if Position.Node.Element = null then
1813 raise Program_Error with "Position cursor is bad";
1816 if Position.Container /= Container'Unrestricted_Access then
1817 raise Program_Error with "Position cursor designates wrong set";
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
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);
1844 procedure Process_Node (Node : Node_Access) is
1846 Process (Cursor'(Container'Unrestricted_Access, Node));
1849 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1850 B : Natural renames T.Busy;
1852 -- Start of processing for Reverse_Iterate
1858 Local_Reverse_Iterate (T);
1866 end Reverse_Iterate;
1872 function Right (Node : Node_Access) return Node_Access is
1881 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1883 Node.Color := Color;
1890 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1899 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1901 Node.Parent := Parent;
1908 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1910 Node.Right := Right;
1913 --------------------------
1914 -- Symmetric_Difference --
1915 --------------------------
1917 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1919 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1920 end Symmetric_Difference;
1922 function Symmetric_Difference (Left, Right : Set) return Set is
1923 Tree : constant Tree_Type :=
1924 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1926 return Set'(Controlled with Tree);
1927 end Symmetric_Difference;
1933 function To_Set (New_Item : Element_Type) return Set is
1937 pragma Unreferenced (Node, Inserted);
1939 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1940 return Set'(Controlled with Tree);
1947 procedure Union (Target : in out Set; Source : Set) is
1949 Set_Ops.Union (Target.Tree, Source.Tree);
1952 function Union (Left, Right : Set) return Set is
1953 Tree : constant Tree_Type :=
1954 Set_Ops.Union (Left.Tree, Right.Tree);
1956 return Set'(Controlled with Tree);
1964 (Stream : not null access Root_Stream_Type'Class;
1967 procedure Write_Node
1968 (Stream : not null access Root_Stream_Type'Class;
1969 Node : Node_Access);
1970 pragma Inline (Write_Node);
1973 new Tree_Operations.Generic_Write (Write_Node);
1979 procedure Write_Node
1980 (Stream : not null access Root_Stream_Type'Class;
1984 Element_Type'Output (Stream, Node.Element.all);
1987 -- Start of processing for Write
1990 Write (Stream, Container.Tree);
1994 (Stream : not null access Root_Stream_Type'Class;
1998 raise Program_Error with "attempt to stream set cursor";
2002 (Stream : not null access Root_Stream_Type'Class;
2003 Item : Constant_Reference_Type)
2006 raise Program_Error with "attempt to stream reference";
2009 end Ada.Containers.Indefinite_Ordered_Sets;