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 package body Ada.Containers.Indefinite_Ordered_Sets is
44 Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
45 Container : access constant Set;
49 overriding function First (Object : Iterator) return Cursor;
51 overriding function Last (Object : Iterator) return Cursor;
53 overriding function Next
55 Position : Cursor) return Cursor;
57 overriding function Previous
59 Position : Cursor) return Cursor;
61 -----------------------
62 -- Local Subprograms --
63 -----------------------
65 function Color (Node : Node_Access) return Color_Type;
66 pragma Inline (Color);
68 function Copy_Node (Source : Node_Access) return Node_Access;
69 pragma Inline (Copy_Node);
71 procedure Free (X : in out Node_Access);
73 procedure Insert_Sans_Hint
74 (Tree : in out Tree_Type;
75 New_Item : Element_Type;
76 Node : out Node_Access;
77 Inserted : out Boolean);
79 procedure Insert_With_Hint
80 (Dst_Tree : in out Tree_Type;
81 Dst_Hint : Node_Access;
82 Src_Node : Node_Access;
83 Dst_Node : out Node_Access);
85 function Is_Greater_Element_Node
87 Right : Node_Access) return Boolean;
88 pragma Inline (Is_Greater_Element_Node);
90 function Is_Less_Element_Node
92 Right : Node_Access) return Boolean;
93 pragma Inline (Is_Less_Element_Node);
95 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
96 pragma Inline (Is_Less_Node_Node);
98 function Left (Node : Node_Access) return Node_Access;
101 function Parent (Node : Node_Access) return Node_Access;
102 pragma Inline (Parent);
104 procedure Replace_Element
105 (Tree : in out Tree_Type;
107 Item : Element_Type);
109 function Right (Node : Node_Access) return Node_Access;
110 pragma Inline (Right);
112 procedure Set_Color (Node : Node_Access; Color : Color_Type);
113 pragma Inline (Set_Color);
115 procedure Set_Left (Node : Node_Access; Left : Node_Access);
116 pragma Inline (Set_Left);
118 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
119 pragma Inline (Set_Parent);
121 procedure Set_Right (Node : Node_Access; Right : Node_Access);
122 pragma Inline (Set_Right);
124 --------------------------
125 -- Local Instantiations --
126 --------------------------
128 procedure Free_Element is
129 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
131 package Tree_Operations is
132 new Red_Black_Trees.Generic_Operations (Tree_Types);
134 procedure Delete_Tree is
135 new Tree_Operations.Generic_Delete_Tree (Free);
137 function Copy_Tree is
138 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
142 package Element_Keys is
143 new Red_Black_Trees.Generic_Keys
144 (Tree_Operations => Tree_Operations,
145 Key_Type => Element_Type,
146 Is_Less_Key_Node => Is_Less_Element_Node,
147 Is_Greater_Key_Node => Is_Greater_Element_Node);
150 new Generic_Set_Operations
151 (Tree_Operations => Tree_Operations,
152 Insert_With_Hint => Insert_With_Hint,
153 Copy_Tree => Copy_Tree,
154 Delete_Tree => Delete_Tree,
155 Is_Less => Is_Less_Node_Node,
162 function "<" (Left, Right : Cursor) return Boolean is
164 if Left.Node = null then
165 raise Constraint_Error with "Left cursor equals No_Element";
168 if Right.Node = null then
169 raise Constraint_Error with "Right cursor equals No_Element";
172 if Left.Node.Element = null then
173 raise Program_Error with "Left cursor is bad";
176 if Right.Node.Element = null then
177 raise Program_Error with "Right cursor is bad";
180 pragma Assert (Vet (Left.Container.Tree, Left.Node),
181 "bad Left cursor in ""<""");
183 pragma Assert (Vet (Right.Container.Tree, Right.Node),
184 "bad Right cursor in ""<""");
186 return Left.Node.Element.all < Right.Node.Element.all;
189 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
191 if Left.Node = null then
192 raise Constraint_Error with "Left cursor equals No_Element";
195 if Left.Node.Element = null then
196 raise Program_Error with "Left cursor is bad";
199 pragma Assert (Vet (Left.Container.Tree, Left.Node),
200 "bad Left cursor in ""<""");
202 return Left.Node.Element.all < Right;
205 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
207 if Right.Node = null then
208 raise Constraint_Error with "Right cursor equals No_Element";
211 if Right.Node.Element = null then
212 raise Program_Error with "Right cursor is bad";
215 pragma Assert (Vet (Right.Container.Tree, Right.Node),
216 "bad Right cursor in ""<""");
218 return Left < Right.Node.Element.all;
225 function "=" (Left, Right : Set) return Boolean is
227 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
228 pragma Inline (Is_Equal_Node_Node);
231 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
233 ------------------------
234 -- Is_Equal_Node_Node --
235 ------------------------
237 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
239 return L.Element.all = R.Element.all;
240 end Is_Equal_Node_Node;
242 -- Start of processing for "="
245 return Is_Equal (Left.Tree, Right.Tree);
252 function ">" (Left, Right : Cursor) return Boolean is
254 if Left.Node = null then
255 raise Constraint_Error with "Left cursor equals No_Element";
258 if Right.Node = null then
259 raise Constraint_Error with "Right cursor equals No_Element";
262 if Left.Node.Element = null then
263 raise Program_Error with "Left cursor is bad";
266 if Right.Node.Element = null then
267 raise Program_Error with "Right cursor is bad";
270 pragma Assert (Vet (Left.Container.Tree, Left.Node),
271 "bad Left cursor in "">""");
273 pragma Assert (Vet (Right.Container.Tree, Right.Node),
274 "bad Right cursor in "">""");
276 -- L > R same as R < L
278 return Right.Node.Element.all < Left.Node.Element.all;
281 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
283 if Left.Node = null then
284 raise Constraint_Error with "Left cursor equals No_Element";
287 if Left.Node.Element = null then
288 raise Program_Error with "Left cursor is bad";
291 pragma Assert (Vet (Left.Container.Tree, Left.Node),
292 "bad Left cursor in "">""");
294 return Right < Left.Node.Element.all;
297 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
299 if Right.Node = null then
300 raise Constraint_Error with "Right cursor equals No_Element";
303 if Right.Node.Element = null then
304 raise Program_Error with "Right cursor is bad";
307 pragma Assert (Vet (Right.Container.Tree, Right.Node),
308 "bad Right cursor in "">""");
310 return Right.Node.Element.all < Left;
317 procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
319 procedure Adjust (Container : in out Set) is
321 Adjust (Container.Tree);
328 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
329 Node : constant Node_Access :=
330 Element_Keys.Ceiling (Container.Tree, Item);
332 return (if Node = null then No_Element
333 else Cursor'(Container'Unrestricted_Access, Node));
341 new Tree_Operations.Generic_Clear (Delete_Tree);
343 procedure Clear (Container : in out Set) is
345 Clear (Container.Tree);
352 function Color (Node : Node_Access) return Color_Type is
361 function Contains (Container : Set; Item : Element_Type) return Boolean is
363 return Find (Container, Item) /= No_Element;
370 function Copy_Node (Source : Node_Access) return Node_Access is
371 Element : Element_Access := new Element_Type'(Source.Element.all);
374 return new Node_Type'(Parent => null,
377 Color => Source.Color,
381 Free_Element (Element);
389 procedure Delete (Container : in out Set; Position : in out Cursor) is
391 if Position.Node = null then
392 raise Constraint_Error with "Position cursor equals No_Element";
395 if Position.Node.Element = null then
396 raise Program_Error with "Position cursor is bad";
399 if Position.Container /= Container'Unrestricted_Access then
400 raise Program_Error with "Position cursor designates wrong set";
403 pragma Assert (Vet (Container.Tree, Position.Node),
404 "bad cursor in Delete");
406 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
407 Free (Position.Node);
408 Position.Container := null;
411 procedure Delete (Container : in out Set; Item : Element_Type) is
413 Element_Keys.Find (Container.Tree, Item);
417 raise Constraint_Error with "attempt to delete element not in set";
420 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
428 procedure Delete_First (Container : in out Set) is
429 Tree : Tree_Type renames Container.Tree;
430 X : Node_Access := Tree.First;
433 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
442 procedure Delete_Last (Container : in out Set) is
443 Tree : Tree_Type renames Container.Tree;
444 X : Node_Access := Tree.Last;
447 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
456 procedure Difference (Target : in out Set; Source : Set) is
458 Set_Ops.Difference (Target.Tree, Source.Tree);
461 function Difference (Left, Right : Set) return Set is
462 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
464 return Set'(Controlled with Tree);
471 function Element (Position : Cursor) return Element_Type is
473 if Position.Node = null then
474 raise Constraint_Error with "Position cursor equals No_Element";
477 if Position.Node.Element = null then
478 raise Program_Error with "Position cursor is bad";
481 pragma Assert (Vet (Position.Container.Tree, Position.Node),
482 "bad cursor in Element");
484 return Position.Node.Element.all;
487 -------------------------
488 -- Equivalent_Elements --
489 -------------------------
491 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
493 if Left < Right or else Right < Left then
498 end Equivalent_Elements;
500 ---------------------
501 -- Equivalent_Sets --
502 ---------------------
504 function Equivalent_Sets (Left, Right : Set) return Boolean is
506 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
507 pragma Inline (Is_Equivalent_Node_Node);
509 function Is_Equivalent is
510 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
512 -----------------------------
513 -- Is_Equivalent_Node_Node --
514 -----------------------------
516 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
518 if L.Element.all < R.Element.all then
520 elsif R.Element.all < L.Element.all then
525 end Is_Equivalent_Node_Node;
527 -- Start of processing for Equivalent_Sets
530 return Is_Equivalent (Left.Tree, Right.Tree);
537 procedure Exclude (Container : in out Set; Item : Element_Type) is
539 Element_Keys.Find (Container.Tree, Item);
542 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
551 function Find (Container : Set; Item : Element_Type) return Cursor is
552 Node : constant Node_Access :=
553 Element_Keys.Find (Container.Tree, Item);
560 return Cursor'(Container'Unrestricted_Access, Node);
567 function First (Container : Set) return Cursor is
570 (if Container.Tree.First = null then No_Element
571 else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
574 function First (Object : Iterator) return Cursor is
577 Object.Container.all'Unrestricted_Access, Object.Container.Tree.First);
584 function First_Element (Container : Set) return Element_Type is
586 if Container.Tree.First = null then
587 raise Constraint_Error with "set is empty";
589 return Container.Tree.First.Element.all;
597 function Floor (Container : Set; Item : Element_Type) return Cursor is
598 Node : constant Node_Access :=
599 Element_Keys.Floor (Container.Tree, Item);
601 return (if Node = null then No_Element
602 else Cursor'(Container'Unrestricted_Access, Node));
609 procedure Free (X : in out Node_Access) is
610 procedure Deallocate is
611 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
623 Free_Element (X.Element);
638 package body Generic_Keys is
640 -----------------------
641 -- Local Subprograms --
642 -----------------------
644 function Is_Greater_Key_Node
646 Right : Node_Access) return Boolean;
647 pragma Inline (Is_Greater_Key_Node);
649 function Is_Less_Key_Node
651 Right : Node_Access) return Boolean;
652 pragma Inline (Is_Less_Key_Node);
654 --------------------------
655 -- Local Instantiations --
656 --------------------------
659 new Red_Black_Trees.Generic_Keys
660 (Tree_Operations => Tree_Operations,
661 Key_Type => Key_Type,
662 Is_Less_Key_Node => Is_Less_Key_Node,
663 Is_Greater_Key_Node => Is_Greater_Key_Node);
669 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
670 Node : constant Node_Access :=
671 Key_Keys.Ceiling (Container.Tree, Key);
673 return (if Node = null then No_Element
674 else Cursor'(Container'Unrestricted_Access, Node));
681 function Contains (Container : Set; Key : Key_Type) return Boolean is
683 return Find (Container, Key) /= No_Element;
690 procedure Delete (Container : in out Set; Key : Key_Type) is
691 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
695 raise Constraint_Error with "attempt to delete key not in set";
698 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
706 function Element (Container : Set; Key : Key_Type) return Element_Type is
707 Node : constant Node_Access :=
708 Key_Keys.Find (Container.Tree, Key);
712 raise Constraint_Error with "key not in set";
715 return Node.Element.all;
718 ---------------------
719 -- Equivalent_Keys --
720 ---------------------
722 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
724 if Left < Right or else Right < Left then
735 procedure Exclude (Container : in out Set; Key : Key_Type) is
736 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
739 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
748 function Find (Container : Set; Key : Key_Type) return Cursor is
749 Node : constant Node_Access :=
750 Key_Keys.Find (Container.Tree, Key);
752 return (if Node = null then No_Element
753 else Cursor'(Container'Unrestricted_Access, Node));
760 function Floor (Container : Set; Key : Key_Type) return Cursor is
761 Node : constant Node_Access :=
762 Key_Keys.Floor (Container.Tree, Key);
764 return (if Node = null then No_Element
765 else Cursor'(Container'Unrestricted_Access, Node));
768 -------------------------
769 -- Is_Greater_Key_Node --
770 -------------------------
772 function Is_Greater_Key_Node
774 Right : Node_Access) return Boolean
777 return Key (Right.Element.all) < Left;
778 end Is_Greater_Key_Node;
780 ----------------------
781 -- Is_Less_Key_Node --
782 ----------------------
784 function Is_Less_Key_Node
786 Right : Node_Access) return Boolean
789 return Left < Key (Right.Element.all);
790 end Is_Less_Key_Node;
796 function Key (Position : Cursor) return Key_Type is
798 if Position.Node = null then
799 raise Constraint_Error with
800 "Position cursor equals No_Element";
803 if Position.Node.Element = null then
804 raise Program_Error with
805 "Position cursor is bad";
808 pragma Assert (Vet (Position.Container.Tree, Position.Node),
809 "bad cursor in Key");
811 return Key (Position.Node.Element.all);
819 (Container : in out Set;
821 New_Item : Element_Type)
823 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
827 raise Constraint_Error with
828 "attempt to replace key not in set";
831 Replace_Element (Container.Tree, Node, New_Item);
834 -----------------------------------
835 -- Update_Element_Preserving_Key --
836 -----------------------------------
838 procedure Update_Element_Preserving_Key
839 (Container : in out Set;
841 Process : not null access
842 procedure (Element : in out Element_Type))
844 Tree : Tree_Type renames Container.Tree;
847 if Position.Node = null then
848 raise Constraint_Error with "Position cursor equals No_Element";
851 if Position.Node.Element = null then
852 raise Program_Error with "Position cursor is bad";
855 if Position.Container /= Container'Unrestricted_Access then
856 raise Program_Error with "Position cursor designates wrong set";
859 pragma Assert (Vet (Container.Tree, Position.Node),
860 "bad cursor in Update_Element_Preserving_Key");
863 E : Element_Type renames Position.Node.Element.all;
864 K : constant Key_Type := Key (E);
866 B : Natural renames Tree.Busy;
867 L : Natural renames Tree.Lock;
885 if Equivalent_Keys (K, Key (E)) then
891 X : Node_Access := Position.Node;
893 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
897 raise Program_Error with "key was modified";
898 end Update_Element_Preserving_Key;
900 function Reference_Preserving_Key
901 (Container : aliased in out Set;
902 Key : Key_Type) return Constant_Reference_Type
904 Position : constant Cursor := Find (Container, Key);
907 if Position.Container = null then
908 raise Constraint_Error with "Position cursor has no element";
911 return (Element => Position.Node.Element);
912 end Reference_Preserving_Key;
914 function Reference_Preserving_Key
915 (Container : aliased in out Set;
916 Key : Key_Type) return Reference_Type
918 Position : constant Cursor := Find (Container, Key);
921 if Position.Container = null then
922 raise Constraint_Error with "Position cursor has no element";
925 return (Element => Position.Node.Element);
926 end Reference_Preserving_Key;
929 (Stream : not null access Root_Stream_Type'Class;
930 Item : out Reference_Type)
933 raise Program_Error with "attempt to stream reference";
937 (Stream : not null access Root_Stream_Type'Class;
938 Item : Reference_Type)
941 raise Program_Error with "attempt to stream reference";
950 function Has_Element (Position : Cursor) return Boolean is
952 return Position /= No_Element;
959 procedure Include (Container : in out Set; New_Item : Element_Type) is
966 Insert (Container, New_Item, Position, Inserted);
969 if Container.Tree.Lock > 0 then
970 raise Program_Error with
971 "attempt to tamper with elements (set is locked)";
974 X := Position.Node.Element;
975 Position.Node.Element := new Element_Type'(New_Item);
985 (Container : in out Set;
986 New_Item : Element_Type;
987 Position : out Cursor;
988 Inserted : out Boolean)
997 Position.Container := Container'Unrestricted_Access;
1000 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1002 pragma Unreferenced (Position);
1007 Insert (Container, New_Item, Position, Inserted);
1009 if not Inserted then
1010 raise Constraint_Error with
1011 "attempt to insert element already in set";
1015 ----------------------
1016 -- Insert_Sans_Hint --
1017 ----------------------
1019 procedure Insert_Sans_Hint
1020 (Tree : in out Tree_Type;
1021 New_Item : Element_Type;
1022 Node : out Node_Access;
1023 Inserted : out Boolean)
1025 function New_Node return Node_Access;
1026 pragma Inline (New_Node);
1028 procedure Insert_Post is
1029 new Element_Keys.Generic_Insert_Post (New_Node);
1031 procedure Conditional_Insert_Sans_Hint is
1032 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1038 function New_Node return Node_Access is
1039 Element : Element_Access := new Element_Type'(New_Item);
1042 return new Node_Type'(Parent => null,
1045 Color => Red_Black_Trees.Red,
1046 Element => Element);
1049 Free_Element (Element);
1053 -- Start of processing for Insert_Sans_Hint
1056 Conditional_Insert_Sans_Hint
1061 end Insert_Sans_Hint;
1063 ----------------------
1064 -- Insert_With_Hint --
1065 ----------------------
1067 procedure Insert_With_Hint
1068 (Dst_Tree : in out Tree_Type;
1069 Dst_Hint : Node_Access;
1070 Src_Node : Node_Access;
1071 Dst_Node : out Node_Access)
1074 pragma Unreferenced (Success);
1076 function New_Node return Node_Access;
1078 procedure Insert_Post is
1079 new Element_Keys.Generic_Insert_Post (New_Node);
1081 procedure Insert_Sans_Hint is
1082 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1084 procedure Insert_With_Hint is
1085 new Element_Keys.Generic_Conditional_Insert_With_Hint
1093 function New_Node return Node_Access is
1094 Element : Element_Access :=
1095 new Element_Type'(Src_Node.Element.all);
1100 Node := new Node_Type;
1103 Free_Element (Element);
1107 Node.Element := Element;
1111 -- Start of processing for Insert_With_Hint
1117 Src_Node.Element.all,
1120 end Insert_With_Hint;
1126 procedure Intersection (Target : in out Set; Source : Set) is
1128 Set_Ops.Intersection (Target.Tree, Source.Tree);
1131 function Intersection (Left, Right : Set) return Set is
1132 Tree : constant Tree_Type :=
1133 Set_Ops.Intersection (Left.Tree, Right.Tree);
1135 return Set'(Controlled with Tree);
1142 function Is_Empty (Container : Set) return Boolean is
1144 return Container.Tree.Length = 0;
1147 -----------------------------
1148 -- Is_Greater_Element_Node --
1149 -----------------------------
1151 function Is_Greater_Element_Node
1152 (Left : Element_Type;
1153 Right : Node_Access) return Boolean
1156 -- e > node same as node < e
1158 return Right.Element.all < Left;
1159 end Is_Greater_Element_Node;
1161 --------------------------
1162 -- Is_Less_Element_Node --
1163 --------------------------
1165 function Is_Less_Element_Node
1166 (Left : Element_Type;
1167 Right : Node_Access) return Boolean
1170 return Left < Right.Element.all;
1171 end Is_Less_Element_Node;
1173 -----------------------
1174 -- Is_Less_Node_Node --
1175 -----------------------
1177 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1179 return L.Element.all < R.Element.all;
1180 end Is_Less_Node_Node;
1186 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1188 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1197 Process : not null access procedure (Position : Cursor))
1199 procedure Process_Node (Node : Node_Access);
1200 pragma Inline (Process_Node);
1202 procedure Local_Iterate is
1203 new Tree_Operations.Generic_Iteration (Process_Node);
1209 procedure Process_Node (Node : Node_Access) is
1211 Process (Cursor'(Container'Unrestricted_Access, Node));
1214 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1215 B : Natural renames T.Busy;
1217 -- Start of processing for Iterate
1235 return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1237 It : constant Iterator :=
1238 (Container'Unchecked_Access, Container.Tree.First);
1246 return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1248 It : constant Iterator := (Container'Unchecked_Access, Start.Node);
1257 function Last (Container : Set) return Cursor is
1260 (if Container.Tree.Last = null then No_Element
1261 else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
1264 function Last (Object : Iterator) return Cursor is
1266 return (if Object.Container.Tree.Last = null then No_Element
1267 else Cursor'(Object.Container.all'Unrestricted_Access,
1268 Object.Container.Tree.Last));
1275 function Last_Element (Container : Set) return Element_Type is
1277 if Container.Tree.Last = null then
1278 raise Constraint_Error with "set is empty";
1280 return Container.Tree.Last.Element.all;
1288 function Left (Node : Node_Access) return Node_Access is
1297 function Length (Container : Set) return Count_Type is
1299 return Container.Tree.Length;
1306 procedure Move is new Tree_Operations.Generic_Move (Clear);
1308 procedure Move (Target : in out Set; Source : in out Set) is
1310 Move (Target => Target.Tree, Source => Source.Tree);
1317 procedure Next (Position : in out Cursor) is
1319 Position := Next (Position);
1322 function Next (Position : Cursor) return Cursor is
1324 if Position = No_Element then
1328 if Position.Node.Element = null then
1329 raise Program_Error with "Position cursor is bad";
1332 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1333 "bad cursor in Next");
1336 Node : constant Node_Access :=
1337 Tree_Operations.Next (Position.Node);
1339 return (if Node = null then No_Element
1340 else Cursor'(Position.Container, Node));
1346 Position : Cursor) return Cursor
1348 pragma Unreferenced (Object);
1350 return Next (Position);
1357 function Overlap (Left, Right : Set) return Boolean is
1359 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1366 function Parent (Node : Node_Access) return Node_Access is
1375 procedure Previous (Position : in out Cursor) is
1377 Position := Previous (Position);
1380 function Previous (Position : Cursor) return Cursor is
1382 if Position = No_Element then
1386 if Position.Node.Element = null then
1387 raise Program_Error with "Position cursor is bad";
1390 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1391 "bad cursor in Previous");
1394 Node : constant Node_Access :=
1395 Tree_Operations.Previous (Position.Node);
1397 return (if Node = null then No_Element
1398 else Cursor'(Position.Container, Node));
1404 Position : Cursor) return Cursor
1406 pragma Unreferenced (Object);
1408 return Previous (Position);
1415 procedure Query_Element
1417 Process : not null access procedure (Element : Element_Type))
1420 if Position.Node = null then
1421 raise Constraint_Error with "Position cursor equals No_Element";
1424 if Position.Node.Element = null then
1425 raise Program_Error with "Position cursor is bad";
1428 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1429 "bad cursor in Query_Element");
1432 T : Tree_Type renames Position.Container.Tree;
1434 B : Natural renames T.Busy;
1435 L : Natural renames T.Lock;
1442 Process (Position.Node.Element.all);
1460 (Stream : not null access Root_Stream_Type'Class;
1461 Container : out Set)
1464 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1465 pragma Inline (Read_Node);
1468 new Tree_Operations.Generic_Read (Clear, Read_Node);
1475 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1477 Node : Node_Access := new Node_Type;
1480 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1485 Free (Node); -- Note that Free deallocates elem too
1489 -- Start of processing for Read
1492 Read (Stream, Container.Tree);
1496 (Stream : not null access Root_Stream_Type'Class;
1500 raise Program_Error with "attempt to stream set cursor";
1504 (Stream : not null access Root_Stream_Type'Class;
1505 Item : out Constant_Reference_Type)
1508 raise Program_Error with "attempt to stream reference";
1515 function Constant_Reference (Container : Set; Position : Cursor)
1516 return Constant_Reference_Type
1518 pragma Unreferenced (Container);
1520 if Position.Container = null then
1521 raise Constraint_Error with "Position cursor has no element";
1524 return (Element => Position.Node.Element.all'Access);
1525 end Constant_Reference;
1531 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1532 Node : constant Node_Access :=
1533 Element_Keys.Find (Container.Tree, New_Item);
1536 pragma Warnings (Off, X);
1540 raise Constraint_Error with "attempt to replace element not in set";
1543 if Container.Tree.Lock > 0 then
1544 raise Program_Error with
1545 "attempt to tamper with elements (set is locked)";
1549 Node.Element := new Element_Type'(New_Item);
1553 ---------------------
1554 -- Replace_Element --
1555 ---------------------
1557 procedure Replace_Element
1558 (Tree : in out Tree_Type;
1560 Item : Element_Type)
1562 pragma Assert (Node /= null);
1563 pragma Assert (Node.Element /= null);
1565 function New_Node return Node_Access;
1566 pragma Inline (New_Node);
1568 procedure Local_Insert_Post is
1569 new Element_Keys.Generic_Insert_Post (New_Node);
1571 procedure Local_Insert_Sans_Hint is
1572 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1574 procedure Local_Insert_With_Hint is
1575 new Element_Keys.Generic_Conditional_Insert_With_Hint
1577 Local_Insert_Sans_Hint);
1583 function New_Node return Node_Access is
1585 Node.Element := new Element_Type'(Item); -- OK if fails
1587 Node.Parent := null;
1594 Result : Node_Access;
1597 X : Element_Access := Node.Element;
1599 -- Start of processing for Replace_Element
1602 if Item < Node.Element.all
1603 or else Node.Element.all < Item
1608 if Tree.Lock > 0 then
1609 raise Program_Error with
1610 "attempt to tamper with elements (set is locked)";
1613 Node.Element := new Element_Type'(Item);
1619 Hint := Element_Keys.Ceiling (Tree, Item);
1624 elsif Item < Hint.Element.all then
1626 if Tree.Lock > 0 then
1627 raise Program_Error with
1628 "attempt to tamper with elements (set is locked)";
1631 Node.Element := new Element_Type'(Item);
1638 pragma Assert (not (Hint.Element.all < Item));
1639 raise Program_Error with "attempt to replace existing element";
1642 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1644 Local_Insert_With_Hint
1649 Inserted => Inserted);
1651 pragma Assert (Inserted);
1652 pragma Assert (Result = Node);
1655 end Replace_Element;
1657 procedure Replace_Element
1658 (Container : in out Set;
1660 New_Item : Element_Type)
1663 if Position.Node = null then
1664 raise Constraint_Error with "Position cursor equals No_Element";
1667 if Position.Node.Element = null then
1668 raise Program_Error with "Position cursor is bad";
1671 if Position.Container /= Container'Unrestricted_Access then
1672 raise Program_Error with "Position cursor designates wrong set";
1675 pragma Assert (Vet (Container.Tree, Position.Node),
1676 "bad cursor in Replace_Element");
1678 Replace_Element (Container.Tree, Position.Node, New_Item);
1679 end Replace_Element;
1681 ---------------------
1682 -- Reverse_Iterate --
1683 ---------------------
1685 procedure Reverse_Iterate
1687 Process : not null access procedure (Position : Cursor))
1689 procedure Process_Node (Node : Node_Access);
1690 pragma Inline (Process_Node);
1692 procedure Local_Reverse_Iterate is
1693 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1699 procedure Process_Node (Node : Node_Access) is
1701 Process (Cursor'(Container'Unrestricted_Access, Node));
1704 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1705 B : Natural renames T.Busy;
1707 -- Start of processing for Reverse_Iterate
1713 Local_Reverse_Iterate (T);
1721 end Reverse_Iterate;
1727 function Right (Node : Node_Access) return Node_Access is
1736 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1738 Node.Color := Color;
1745 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1754 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1756 Node.Parent := Parent;
1763 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1765 Node.Right := Right;
1768 --------------------------
1769 -- Symmetric_Difference --
1770 --------------------------
1772 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1774 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1775 end Symmetric_Difference;
1777 function Symmetric_Difference (Left, Right : Set) return Set is
1778 Tree : constant Tree_Type :=
1779 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1781 return Set'(Controlled with Tree);
1782 end Symmetric_Difference;
1788 function To_Set (New_Item : Element_Type) return Set is
1792 pragma Unreferenced (Node, Inserted);
1794 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1795 return Set'(Controlled with Tree);
1802 procedure Union (Target : in out Set; Source : Set) is
1804 Set_Ops.Union (Target.Tree, Source.Tree);
1807 function Union (Left, Right : Set) return Set is
1808 Tree : constant Tree_Type :=
1809 Set_Ops.Union (Left.Tree, Right.Tree);
1811 return Set'(Controlled with Tree);
1819 (Stream : not null access Root_Stream_Type'Class;
1822 procedure Write_Node
1823 (Stream : not null access Root_Stream_Type'Class;
1824 Node : Node_Access);
1825 pragma Inline (Write_Node);
1828 new Tree_Operations.Generic_Write (Write_Node);
1834 procedure Write_Node
1835 (Stream : not null access Root_Stream_Type'Class;
1839 Element_Type'Output (Stream, Node.Element.all);
1842 -- Start of processing for Write
1845 Write (Stream, Container.Tree);
1849 (Stream : not null access Root_Stream_Type'Class;
1853 raise Program_Error with "attempt to stream set cursor";
1857 (Stream : not null access Root_Stream_Type'Class;
1858 Item : Constant_Reference_Type)
1861 raise Program_Error with "attempt to stream reference";
1864 end Ada.Containers.Indefinite_Ordered_Sets;