1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . O R D E R E D _ M U L T I S E T S --
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.Unchecked_Deallocation;
32 with Ada.Containers.Red_Black_Trees.Generic_Operations;
33 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
35 with Ada.Containers.Red_Black_Trees.Generic_Keys;
36 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
38 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
39 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
41 with System; use type System.Address;
43 package body Ada.Containers.Ordered_Multisets is
45 -----------------------------
46 -- Node Access Subprograms --
47 -----------------------------
49 -- These subprograms provide a functional interface to access fields
50 -- of a node, and a procedural interface for modifying these values.
52 function Color (Node : Node_Access) return Color_Type;
53 pragma Inline (Color);
55 function Left (Node : Node_Access) return Node_Access;
58 function Parent (Node : Node_Access) return Node_Access;
59 pragma Inline (Parent);
61 function Right (Node : Node_Access) return Node_Access;
62 pragma Inline (Right);
64 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
65 pragma Inline (Set_Parent);
67 procedure Set_Left (Node : Node_Access; Left : Node_Access);
68 pragma Inline (Set_Left);
70 procedure Set_Right (Node : Node_Access; Right : Node_Access);
71 pragma Inline (Set_Right);
73 procedure Set_Color (Node : Node_Access; Color : Color_Type);
74 pragma Inline (Set_Color);
76 -----------------------
77 -- Local Subprograms --
78 -----------------------
80 function Copy_Node (Source : Node_Access) return Node_Access;
81 pragma Inline (Copy_Node);
83 procedure Free (X : in out Node_Access);
85 procedure Insert_Sans_Hint
86 (Tree : in out Tree_Type;
87 New_Item : Element_Type;
88 Node : out Node_Access);
90 procedure Insert_With_Hint
91 (Dst_Tree : in out Tree_Type;
92 Dst_Hint : Node_Access;
93 Src_Node : Node_Access;
94 Dst_Node : out Node_Access);
96 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
97 pragma Inline (Is_Equal_Node_Node);
99 function Is_Greater_Element_Node
100 (Left : Element_Type;
101 Right : Node_Access) return Boolean;
102 pragma Inline (Is_Greater_Element_Node);
104 function Is_Less_Element_Node
105 (Left : Element_Type;
106 Right : Node_Access) return Boolean;
107 pragma Inline (Is_Less_Element_Node);
109 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
110 pragma Inline (Is_Less_Node_Node);
112 procedure Replace_Element
113 (Tree : in out Tree_Type;
115 Item : Element_Type);
117 --------------------------
118 -- Local Instantiations --
119 --------------------------
121 package Tree_Operations is
122 new Red_Black_Trees.Generic_Operations (Tree_Types);
124 procedure Delete_Tree is
125 new Tree_Operations.Generic_Delete_Tree (Free);
127 function Copy_Tree is
128 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
133 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
135 package Element_Keys is
136 new Red_Black_Trees.Generic_Keys
137 (Tree_Operations => Tree_Operations,
138 Key_Type => Element_Type,
139 Is_Less_Key_Node => Is_Less_Element_Node,
140 Is_Greater_Key_Node => Is_Greater_Element_Node);
143 new Generic_Set_Operations
144 (Tree_Operations => Tree_Operations,
145 Insert_With_Hint => Insert_With_Hint,
146 Copy_Tree => Copy_Tree,
147 Delete_Tree => Delete_Tree,
148 Is_Less => Is_Less_Node_Node,
155 function "<" (Left, Right : Cursor) return Boolean is
157 if Left.Node = null then
158 raise Constraint_Error with "Left cursor equals No_Element";
161 if Right.Node = null then
162 raise Constraint_Error with "Right cursor equals No_Element";
165 pragma Assert (Vet (Left.Container.Tree, Left.Node),
166 "bad Left cursor in ""<""");
168 pragma Assert (Vet (Right.Container.Tree, Right.Node),
169 "bad Right cursor in ""<""");
171 return Left.Node.Element < Right.Node.Element;
174 function "<" (Left : Cursor; Right : Element_Type)
177 if Left.Node = null then
178 raise Constraint_Error with "Left cursor equals No_Element";
181 pragma Assert (Vet (Left.Container.Tree, Left.Node),
182 "bad Left cursor in ""<""");
184 return Left.Node.Element < Right;
187 function "<" (Left : Element_Type; Right : Cursor)
190 if Right.Node = null then
191 raise Constraint_Error with "Right cursor equals No_Element";
194 pragma Assert (Vet (Right.Container.Tree, Right.Node),
195 "bad Right cursor in ""<""");
197 return Left < Right.Node.Element;
204 function "=" (Left, Right : Set) return Boolean is
206 return Is_Equal (Left.Tree, Right.Tree);
213 function ">" (Left, Right : Cursor) return Boolean is
215 if Left.Node = null then
216 raise Constraint_Error with "Left cursor equals No_Element";
219 if Right.Node = null then
220 raise Constraint_Error with "Right cursor equals No_Element";
223 pragma Assert (Vet (Left.Container.Tree, Left.Node),
224 "bad Left cursor in "">""");
226 pragma Assert (Vet (Right.Container.Tree, Right.Node),
227 "bad Right cursor in "">""");
229 -- L > R same as R < L
231 return Right.Node.Element < Left.Node.Element;
234 function ">" (Left : Cursor; Right : Element_Type)
237 if Left.Node = null then
238 raise Constraint_Error with "Left cursor equals No_Element";
241 pragma Assert (Vet (Left.Container.Tree, Left.Node),
242 "bad Left cursor in "">""");
244 return Right < Left.Node.Element;
247 function ">" (Left : Element_Type; Right : Cursor)
250 if Right.Node = null then
251 raise Constraint_Error with "Right cursor equals No_Element";
254 pragma Assert (Vet (Right.Container.Tree, Right.Node),
255 "bad Right cursor in "">""");
257 return Right.Node.Element < Left;
264 procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
266 procedure Adjust (Container : in out Set) is
268 Adjust (Container.Tree);
275 procedure Assign (Target : in out Set; Source : Set) is
277 if Target'Address = Source'Address then
282 Target.Union (Source);
289 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
290 Node : constant Node_Access :=
291 Element_Keys.Ceiling (Container.Tree, Item);
298 return Cursor'(Container'Unrestricted_Access, Node);
306 new Tree_Operations.Generic_Clear (Delete_Tree);
308 procedure Clear (Container : in out Set) is
310 Clear (Container.Tree);
317 function Color (Node : Node_Access) return Color_Type is
326 function Contains (Container : Set; Item : Element_Type) return Boolean is
328 return Find (Container, Item) /= No_Element;
335 function Copy (Source : Set) return Set is
337 return Target : Set do
338 Target.Assign (Source);
346 function Copy_Node (Source : Node_Access) return Node_Access is
347 Target : constant Node_Access :=
348 new Node_Type'(Parent => null,
351 Color => Source.Color,
352 Element => Source.Element);
361 procedure Delete (Container : in out Set; Item : Element_Type) is
362 Tree : Tree_Type renames Container.Tree;
363 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
364 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
369 raise Constraint_Error with
370 "attempt to delete element not in set";
375 Node := Tree_Operations.Next (Node);
376 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
379 exit when Node = Done;
383 procedure Delete (Container : in out Set; Position : in out Cursor) is
385 if Position.Node = null then
386 raise Constraint_Error with "Position cursor equals No_Element";
389 if Position.Container /= Container'Unrestricted_Access then
390 raise Program_Error with "Position cursor designates wrong set";
393 pragma Assert (Vet (Container.Tree, Position.Node),
394 "bad cursor in Delete");
396 Delete_Node_Sans_Free (Container.Tree, Position.Node);
397 Free (Position.Node);
399 Position.Container := null;
406 procedure Delete_First (Container : in out Set) is
407 Tree : Tree_Type renames Container.Tree;
408 X : Node_Access := Tree.First;
415 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
423 procedure Delete_Last (Container : in out Set) is
424 Tree : Tree_Type renames Container.Tree;
425 X : Node_Access := Tree.Last;
432 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
440 procedure Difference (Target : in out Set; Source : Set) is
442 Set_Ops.Difference (Target.Tree, Source.Tree);
445 function Difference (Left, Right : Set) return Set is
446 Tree : constant Tree_Type :=
447 Set_Ops.Difference (Left.Tree, Right.Tree);
449 return Set'(Controlled with Tree);
456 function Element (Position : Cursor) return Element_Type is
458 if Position.Node = null then
459 raise Constraint_Error with "Position cursor equals No_Element";
462 pragma Assert (Vet (Position.Container.Tree, Position.Node),
463 "bad cursor in Element");
465 return Position.Node.Element;
468 -------------------------
469 -- Equivalent_Elements --
470 -------------------------
472 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
481 end Equivalent_Elements;
483 ---------------------
484 -- Equivalent_Sets --
485 ---------------------
487 function Equivalent_Sets (Left, Right : Set) return Boolean is
489 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
490 pragma Inline (Is_Equivalent_Node_Node);
492 function Is_Equivalent is
493 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
495 -----------------------------
496 -- Is_Equivalent_Node_Node --
497 -----------------------------
499 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
501 if L.Element < R.Element then
503 elsif R.Element < L.Element then
508 end Is_Equivalent_Node_Node;
510 -- Start of processing for Equivalent_Sets
513 return Is_Equivalent (Left.Tree, Right.Tree);
520 procedure Exclude (Container : in out Set; Item : Element_Type) is
521 Tree : Tree_Type renames Container.Tree;
522 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
523 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
526 while Node /= Done loop
528 Node := Tree_Operations.Next (Node);
529 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
538 function Find (Container : Set; Item : Element_Type) return Cursor is
539 Node : constant Node_Access :=
540 Element_Keys.Find (Container.Tree, Item);
547 return Cursor'(Container'Unrestricted_Access, Node);
554 function First (Container : Set) return Cursor is
556 if Container.Tree.First = null then
560 return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
567 function First_Element (Container : Set) return Element_Type is
569 if Container.Tree.First = null then
570 raise Constraint_Error with "set is empty";
573 return Container.Tree.First.Element;
580 function Floor (Container : Set; Item : Element_Type) return Cursor is
581 Node : constant Node_Access :=
582 Element_Keys.Floor (Container.Tree, Item);
589 return Cursor'(Container'Unrestricted_Access, Node);
596 procedure Free (X : in out Node_Access) is
597 procedure Deallocate is
598 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
614 package body Generic_Keys is
616 -----------------------
617 -- Local Subprograms --
618 -----------------------
620 function Is_Greater_Key_Node
622 Right : Node_Access) return Boolean;
623 pragma Inline (Is_Greater_Key_Node);
625 function Is_Less_Key_Node
627 Right : Node_Access) return Boolean;
628 pragma Inline (Is_Less_Key_Node);
630 --------------------------
631 -- Local_Instantiations --
632 --------------------------
635 new Red_Black_Trees.Generic_Keys
636 (Tree_Operations => Tree_Operations,
637 Key_Type => Key_Type,
638 Is_Less_Key_Node => Is_Less_Key_Node,
639 Is_Greater_Key_Node => Is_Greater_Key_Node);
645 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
646 Node : constant Node_Access :=
647 Key_Keys.Ceiling (Container.Tree, Key);
654 return Cursor'(Container'Unrestricted_Access, Node);
661 function Contains (Container : Set; Key : Key_Type) return Boolean is
663 return Find (Container, Key) /= No_Element;
670 procedure Delete (Container : in out Set; Key : Key_Type) is
671 Tree : Tree_Type renames Container.Tree;
672 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
673 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
678 raise Constraint_Error with "attempt to delete key not in set";
683 Node := Tree_Operations.Next (Node);
684 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
687 exit when Node = Done;
695 function Element (Container : Set; Key : Key_Type) return Element_Type is
696 Node : constant Node_Access :=
697 Key_Keys.Find (Container.Tree, Key);
700 raise Constraint_Error with "key not in set";
706 ---------------------
707 -- Equivalent_Keys --
708 ---------------------
710 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
725 procedure Exclude (Container : in out Set; Key : Key_Type) is
726 Tree : Tree_Type renames Container.Tree;
727 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
728 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
732 while Node /= Done loop
734 Node := Tree_Operations.Next (Node);
735 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
744 function Find (Container : Set; Key : Key_Type) return Cursor is
745 Node : constant Node_Access :=
746 Key_Keys.Find (Container.Tree, Key);
753 return 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);
769 return Cursor'(Container'Unrestricted_Access, Node);
772 -------------------------
773 -- Is_Greater_Key_Node --
774 -------------------------
776 function Is_Greater_Key_Node
778 Right : Node_Access) return Boolean is
780 return Key (Right.Element) < Left;
781 end Is_Greater_Key_Node;
783 ----------------------
784 -- Is_Less_Key_Node --
785 ----------------------
787 function Is_Less_Key_Node
789 Right : Node_Access) return Boolean is
791 return Left < Key (Right.Element);
792 end Is_Less_Key_Node;
801 Process : not null access procedure (Position : Cursor))
803 procedure Process_Node (Node : Node_Access);
804 pragma Inline (Process_Node);
806 procedure Local_Iterate is
807 new Key_Keys.Generic_Iteration (Process_Node);
813 procedure Process_Node (Node : Node_Access) is
815 Process (Cursor'(Container'Unrestricted_Access, Node));
818 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
819 B : Natural renames T.Busy;
821 -- Start of processing for Iterate
827 Local_Iterate (T, Key);
841 function Key (Position : Cursor) return Key_Type is
843 if Position.Node = null then
844 raise Constraint_Error with
845 "Position cursor equals No_Element";
848 pragma Assert (Vet (Position.Container.Tree, Position.Node),
849 "bad cursor in Key");
851 return Key (Position.Node.Element);
854 ---------------------
855 -- Reverse_Iterate --
856 ---------------------
858 procedure Reverse_Iterate
861 Process : not null access procedure (Position : Cursor))
863 procedure Process_Node (Node : Node_Access);
864 pragma Inline (Process_Node);
866 procedure Local_Reverse_Iterate is
867 new Key_Keys.Generic_Reverse_Iteration (Process_Node);
873 procedure Process_Node (Node : Node_Access) is
875 Process (Cursor'(Container'Unrestricted_Access, Node));
878 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
879 B : Natural renames T.Busy;
881 -- Start of processing for Reverse_Iterate
887 Local_Reverse_Iterate (T, Key);
901 procedure Update_Element
902 (Container : in out Set;
904 Process : not null access procedure (Element : in out Element_Type))
906 Tree : Tree_Type renames Container.Tree;
907 Node : constant Node_Access := Position.Node;
911 raise Constraint_Error with
912 "Position cursor equals No_Element";
915 if Position.Container /= Container'Unrestricted_Access then
916 raise Program_Error with
917 "Position cursor designates wrong set";
920 pragma Assert (Vet (Tree, Node),
921 "bad cursor in Update_Element");
924 E : Element_Type renames Node.Element;
925 K : constant Key_Type := Key (E);
927 B : Natural renames Tree.Busy;
928 L : Natural renames Tree.Lock;
946 if Equivalent_Keys (Left => K, Right => Key (E)) then
951 -- Delete_Node checks busy-bit
953 Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
955 Insert_New_Item : declare
956 function New_Node return Node_Access;
957 pragma Inline (New_Node);
959 procedure Insert_Post is
960 new Element_Keys.Generic_Insert_Post (New_Node);
962 procedure Unconditional_Insert is
963 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
969 function New_Node return Node_Access is
971 Node.Color := Red_Black_Trees.Red;
979 Result : Node_Access;
981 -- Start of processing for Insert_New_Item
989 pragma Assert (Result = Node);
999 function Has_Element (Position : Cursor) return Boolean is
1001 return Position /= No_Element;
1008 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1010 pragma Unreferenced (Position);
1012 Insert (Container, New_Item, Position);
1016 (Container : in out Set;
1017 New_Item : Element_Type;
1018 Position : out Cursor)
1021 Insert_Sans_Hint (Container.Tree, New_Item, Position.Node);
1022 Position.Container := Container'Unrestricted_Access;
1025 ----------------------
1026 -- Insert_Sans_Hint --
1027 ----------------------
1029 procedure Insert_Sans_Hint
1030 (Tree : in out Tree_Type;
1031 New_Item : Element_Type;
1032 Node : out Node_Access)
1034 function New_Node return Node_Access;
1035 pragma Inline (New_Node);
1037 procedure Insert_Post is
1038 new Element_Keys.Generic_Insert_Post (New_Node);
1040 procedure Unconditional_Insert is
1041 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1047 function New_Node return Node_Access is
1048 Node : constant Node_Access :=
1049 new Node_Type'(Parent => null,
1052 Color => Red_Black_Trees.Red,
1053 Element => New_Item);
1058 -- Start of processing for Insert_Sans_Hint
1061 Unconditional_Insert (Tree, New_Item, Node);
1062 end Insert_Sans_Hint;
1064 ----------------------
1065 -- Insert_With_Hint --
1066 ----------------------
1068 procedure Insert_With_Hint
1069 (Dst_Tree : in out Tree_Type;
1070 Dst_Hint : Node_Access;
1071 Src_Node : Node_Access;
1072 Dst_Node : out Node_Access)
1074 function New_Node return Node_Access;
1075 pragma Inline (New_Node);
1077 procedure Insert_Post is
1078 new Element_Keys.Generic_Insert_Post (New_Node);
1080 procedure Insert_Sans_Hint is
1081 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1083 procedure Local_Insert_With_Hint is
1084 new Element_Keys.Generic_Unconditional_Insert_With_Hint
1092 function New_Node return Node_Access is
1093 Node : constant Node_Access :=
1094 new Node_Type'(Parent => null,
1098 Element => Src_Node.Element);
1103 -- Start of processing for Insert_With_Hint
1106 Local_Insert_With_Hint
1111 end Insert_With_Hint;
1117 procedure Intersection (Target : in out Set; Source : Set) is
1119 Set_Ops.Intersection (Target.Tree, Source.Tree);
1122 function Intersection (Left, Right : Set) return Set is
1123 Tree : constant Tree_Type :=
1124 Set_Ops.Intersection (Left.Tree, Right.Tree);
1126 return Set'(Controlled with Tree);
1133 function Is_Empty (Container : Set) return Boolean is
1135 return Container.Tree.Length = 0;
1138 ------------------------
1139 -- Is_Equal_Node_Node --
1140 ------------------------
1142 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1144 return L.Element = R.Element;
1145 end Is_Equal_Node_Node;
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 < 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;
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 < R.Element;
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 Item : Element_Type;
1236 Process : not null access procedure (Position : Cursor))
1238 procedure Process_Node (Node : Node_Access);
1239 pragma Inline (Process_Node);
1241 procedure Local_Iterate is
1242 new Element_Keys.Generic_Iteration (Process_Node);
1248 procedure Process_Node (Node : Node_Access) is
1250 Process (Cursor'(Container'Unrestricted_Access, Node));
1253 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1254 B : Natural renames T.Busy;
1256 -- Start of processing for Iterate
1262 Local_Iterate (T, Item);
1276 function Last (Container : Set) return Cursor is
1278 if Container.Tree.Last = null then
1282 return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1289 function Last_Element (Container : Set) return Element_Type is
1291 if Container.Tree.Last = null then
1292 raise Constraint_Error with "set is empty";
1295 return Container.Tree.Last.Element;
1302 function Left (Node : Node_Access) return Node_Access is
1311 function Length (Container : Set) return Count_Type is
1313 return Container.Tree.Length;
1321 new Tree_Operations.Generic_Move (Clear);
1323 procedure Move (Target : in out Set; Source : in out Set) is
1325 Move (Target => Target.Tree, Source => Source.Tree);
1332 procedure Next (Position : in out Cursor)
1335 Position := Next (Position);
1338 function Next (Position : Cursor) return Cursor is
1340 if Position = No_Element then
1344 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1345 "bad cursor in Next");
1348 Node : constant Node_Access :=
1349 Tree_Operations.Next (Position.Node);
1355 return Cursor'(Position.Container, Node);
1363 function Overlap (Left, Right : Set) return Boolean is
1365 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1372 function Parent (Node : Node_Access) return Node_Access is
1381 procedure Previous (Position : in out Cursor)
1384 Position := Previous (Position);
1387 function Previous (Position : Cursor) return Cursor is
1389 if Position = No_Element then
1393 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1394 "bad cursor in Previous");
1397 Node : constant Node_Access :=
1398 Tree_Operations.Previous (Position.Node);
1404 return Cursor'(Position.Container, Node);
1412 procedure Query_Element
1414 Process : not null access procedure (Element : Element_Type))
1417 if Position.Node = null then
1418 raise Constraint_Error with "Position cursor equals No_Element";
1421 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1422 "bad cursor in Query_Element");
1425 T : Tree_Type renames Position.Container.Tree;
1427 B : Natural renames T.Busy;
1428 L : Natural renames T.Lock;
1435 Process (Position.Node.Element);
1453 (Stream : not null access Root_Stream_Type'Class;
1454 Container : out Set)
1457 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1458 pragma Inline (Read_Node);
1461 new Tree_Operations.Generic_Read (Clear, Read_Node);
1468 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1470 Node : Node_Access := new Node_Type;
1472 Element_Type'Read (Stream, Node.Element);
1476 Free (Node); -- Note that Free deallocates elem too
1480 -- Start of processing for Read
1483 Read (Stream, Container.Tree);
1487 (Stream : not null access Root_Stream_Type'Class;
1491 raise Program_Error with "attempt to stream set cursor";
1494 ---------------------
1495 -- Replace_Element --
1496 ---------------------
1498 procedure Replace_Element
1499 (Tree : in out Tree_Type;
1501 Item : Element_Type)
1504 if Item < Node.Element
1505 or else Node.Element < Item
1509 if Tree.Lock > 0 then
1510 raise Program_Error with
1511 "attempt to tamper with elements (set is locked)";
1514 Node.Element := Item;
1518 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1520 Insert_New_Item : declare
1521 function New_Node return Node_Access;
1522 pragma Inline (New_Node);
1524 procedure Insert_Post is
1525 new Element_Keys.Generic_Insert_Post (New_Node);
1527 procedure Unconditional_Insert is
1528 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1534 function New_Node return Node_Access is
1536 Node.Element := Item;
1537 Node.Color := Red_Black_Trees.Red;
1538 Node.Parent := null;
1545 Result : Node_Access;
1547 -- Start of processing for Insert_New_Item
1550 Unconditional_Insert
1555 pragma Assert (Result = Node);
1556 end Insert_New_Item;
1557 end Replace_Element;
1559 procedure Replace_Element
1560 (Container : in out Set;
1562 New_Item : Element_Type)
1565 if Position.Node = null then
1566 raise Constraint_Error with
1567 "Position cursor equals No_Element";
1570 if Position.Container /= Container'Unrestricted_Access then
1571 raise Program_Error with
1572 "Position cursor designates wrong set";
1575 pragma Assert (Vet (Container.Tree, Position.Node),
1576 "bad cursor in Replace_Element");
1578 Replace_Element (Container.Tree, Position.Node, New_Item);
1579 end Replace_Element;
1581 ---------------------
1582 -- Reverse_Iterate --
1583 ---------------------
1585 procedure Reverse_Iterate
1587 Process : not null access procedure (Position : Cursor))
1589 procedure Process_Node (Node : Node_Access);
1590 pragma Inline (Process_Node);
1592 procedure Local_Reverse_Iterate is
1593 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1599 procedure Process_Node (Node : Node_Access) is
1601 Process (Cursor'(Container'Unrestricted_Access, Node));
1604 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1605 B : Natural renames T.Busy;
1607 -- Start of processing for Reverse_Iterate
1613 Local_Reverse_Iterate (T);
1621 end Reverse_Iterate;
1623 procedure Reverse_Iterate
1625 Item : Element_Type;
1626 Process : not null access procedure (Position : Cursor))
1628 procedure Process_Node (Node : Node_Access);
1629 pragma Inline (Process_Node);
1631 procedure Local_Reverse_Iterate is
1632 new Element_Keys.Generic_Reverse_Iteration (Process_Node);
1638 procedure Process_Node (Node : Node_Access) is
1640 Process (Cursor'(Container'Unrestricted_Access, Node));
1643 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1644 B : Natural renames T.Busy;
1646 -- Start of processing for Reverse_Iterate
1652 Local_Reverse_Iterate (T, Item);
1660 end Reverse_Iterate;
1666 function Right (Node : Node_Access) return Node_Access is
1675 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1677 Node.Color := Color;
1684 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1693 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1695 Node.Parent := Parent;
1702 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1704 Node.Right := Right;
1707 --------------------------
1708 -- Symmetric_Difference --
1709 --------------------------
1711 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1713 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1714 end Symmetric_Difference;
1716 function Symmetric_Difference (Left, Right : Set) return Set is
1717 Tree : constant Tree_Type :=
1718 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1720 return Set'(Controlled with Tree);
1721 end Symmetric_Difference;
1727 function To_Set (New_Item : Element_Type) return Set is
1730 pragma Unreferenced (Node);
1732 Insert_Sans_Hint (Tree, New_Item, Node);
1733 return Set'(Controlled with Tree);
1740 procedure Union (Target : in out Set; Source : Set) is
1742 Set_Ops.Union (Target.Tree, Source.Tree);
1745 function Union (Left, Right : Set) return Set is
1746 Tree : constant Tree_Type :=
1747 Set_Ops.Union (Left.Tree, Right.Tree);
1749 return Set'(Controlled with Tree);
1757 (Stream : not null access Root_Stream_Type'Class;
1760 procedure Write_Node
1761 (Stream : not null access Root_Stream_Type'Class;
1762 Node : Node_Access);
1763 pragma Inline (Write_Node);
1766 new Tree_Operations.Generic_Write (Write_Node);
1772 procedure Write_Node
1773 (Stream : not null access Root_Stream_Type'Class;
1777 Element_Type'Write (Stream, Node.Element);
1780 -- Start of processing for Write
1783 Write (Stream, Container.Tree);
1787 (Stream : not null access Root_Stream_Type'Class;
1791 raise Program_Error with "attempt to stream set cursor";
1794 end Ada.Containers.Ordered_Multisets;