1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . B O U N D E D _ O R D E R E D _ 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.Containers.Red_Black_Trees.Generic_Bounded_Operations;
32 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations);
34 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
35 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
37 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations;
39 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Set_Operations);
41 with Ada.Finalization; use Ada.Finalization;
43 with System; use type System.Address;
45 package body Ada.Containers.Bounded_Ordered_Sets is
47 type Iterator is new Limited_Controlled and
48 Set_Iterator_Interfaces.Reversible_Iterator with
50 Container : Set_Access;
54 overriding procedure Finalize (Object : in out Iterator);
56 overriding function First (Object : Iterator) return Cursor;
57 overriding function Last (Object : Iterator) return Cursor;
59 overriding function Next
61 Position : Cursor) return Cursor;
63 overriding function Previous
65 Position : Cursor) return Cursor;
67 ------------------------------
68 -- Access to Fields of Node --
69 ------------------------------
71 -- These subprograms provide functional notation for access to fields
72 -- of a node, and procedural notation for modifying these fields.
74 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type;
75 pragma Inline (Color);
77 function Left (Node : Node_Type) return Count_Type;
80 function Parent (Node : Node_Type) return Count_Type;
81 pragma Inline (Parent);
83 function Right (Node : Node_Type) return Count_Type;
84 pragma Inline (Right);
87 (Node : in out Node_Type;
88 Color : Red_Black_Trees.Color_Type);
89 pragma Inline (Set_Color);
91 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
92 pragma Inline (Set_Left);
94 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
95 pragma Inline (Set_Right);
97 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
98 pragma Inline (Set_Parent);
100 -----------------------
101 -- Local Subprograms --
102 -----------------------
104 procedure Insert_Sans_Hint
105 (Container : in out Set;
106 New_Item : Element_Type;
107 Node : out Count_Type;
108 Inserted : out Boolean);
110 procedure Insert_With_Hint
111 (Dst_Set : in out Set;
112 Dst_Hint : Count_Type;
113 Src_Node : Node_Type;
114 Dst_Node : out Count_Type);
116 function Is_Greater_Element_Node
117 (Left : Element_Type;
118 Right : Node_Type) return Boolean;
119 pragma Inline (Is_Greater_Element_Node);
121 function Is_Less_Element_Node
122 (Left : Element_Type;
123 Right : Node_Type) return Boolean;
124 pragma Inline (Is_Less_Element_Node);
126 function Is_Less_Node_Node (L, R : Node_Type) return Boolean;
127 pragma Inline (Is_Less_Node_Node);
129 procedure Replace_Element
130 (Container : in out Set;
132 Item : Element_Type);
134 --------------------------
135 -- Local Instantiations --
136 --------------------------
138 package Tree_Operations is
139 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
143 package Element_Keys is
144 new Red_Black_Trees.Generic_Bounded_Keys
145 (Tree_Operations => Tree_Operations,
146 Key_Type => Element_Type,
147 Is_Less_Key_Node => Is_Less_Element_Node,
148 Is_Greater_Key_Node => Is_Greater_Element_Node);
151 new Red_Black_Trees.Generic_Bounded_Set_Operations
152 (Tree_Operations => Tree_Operations,
155 Insert_With_Hint => Insert_With_Hint,
156 Is_Less => Is_Less_Node_Node);
162 function "<" (Left, Right : Cursor) return Boolean is
164 if Left.Node = 0 then
165 raise Constraint_Error with "Left cursor equals No_Element";
168 if Right.Node = 0 then
169 raise Constraint_Error with "Right cursor equals No_Element";
172 pragma Assert (Vet (Left.Container.all, Left.Node),
173 "bad Left cursor in ""<""");
175 pragma Assert (Vet (Right.Container.all, Right.Node),
176 "bad Right cursor in ""<""");
179 LN : Nodes_Type renames Left.Container.Nodes;
180 RN : Nodes_Type renames Right.Container.Nodes;
182 return LN (Left.Node).Element < RN (Right.Node).Element;
186 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
188 if Left.Node = 0 then
189 raise Constraint_Error with "Left cursor equals No_Element";
192 pragma Assert (Vet (Left.Container.all, Left.Node),
193 "bad Left cursor in ""<""");
195 return Left.Container.Nodes (Left.Node).Element < Right;
198 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
200 if Right.Node = 0 then
201 raise Constraint_Error with "Right cursor equals No_Element";
204 pragma Assert (Vet (Right.Container.all, Right.Node),
205 "bad Right cursor in ""<""");
207 return Left < Right.Container.Nodes (Right.Node).Element;
214 function "=" (Left, Right : Set) return Boolean is
215 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
216 pragma Inline (Is_Equal_Node_Node);
219 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
221 ------------------------
222 -- Is_Equal_Node_Node --
223 ------------------------
225 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean is
227 return L.Element = R.Element;
228 end Is_Equal_Node_Node;
230 -- Start of processing for Is_Equal
233 return Is_Equal (Left, Right);
240 function ">" (Left, Right : Cursor) return Boolean is
242 if Left.Node = 0 then
243 raise Constraint_Error with "Left cursor equals No_Element";
246 if Right.Node = 0 then
247 raise Constraint_Error with "Right cursor equals No_Element";
250 pragma Assert (Vet (Left.Container.all, Left.Node),
251 "bad Left cursor in "">""");
253 pragma Assert (Vet (Right.Container.all, Right.Node),
254 "bad Right cursor in "">""");
256 -- L > R same as R < L
259 LN : Nodes_Type renames Left.Container.Nodes;
260 RN : Nodes_Type renames Right.Container.Nodes;
262 return RN (Right.Node).Element < LN (Left.Node).Element;
266 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
268 if Right.Node = 0 then
269 raise Constraint_Error with "Right cursor equals No_Element";
272 pragma Assert (Vet (Right.Container.all, Right.Node),
273 "bad Right cursor in "">""");
275 return Right.Container.Nodes (Right.Node).Element < Left;
278 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
280 if Left.Node = 0 then
281 raise Constraint_Error with "Left cursor equals No_Element";
284 pragma Assert (Vet (Left.Container.all, Left.Node),
285 "bad Left cursor in "">""");
287 return Right < Left.Container.Nodes (Left.Node).Element;
294 procedure Assign (Target : in out Set; Source : Set) is
295 procedure Append_Element (Source_Node : Count_Type);
297 procedure Append_Elements is
298 new Tree_Operations.Generic_Iteration (Append_Element);
304 procedure Append_Element (Source_Node : Count_Type) is
305 SN : Node_Type renames Source.Nodes (Source_Node);
307 procedure Set_Element (Node : in out Node_Type);
308 pragma Inline (Set_Element);
310 function New_Node return Count_Type;
311 pragma Inline (New_Node);
313 procedure Insert_Post is
314 new Element_Keys.Generic_Insert_Post (New_Node);
316 procedure Unconditional_Insert_Sans_Hint is
317 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
319 procedure Unconditional_Insert_Avec_Hint is
320 new Element_Keys.Generic_Unconditional_Insert_With_Hint
322 Unconditional_Insert_Sans_Hint);
324 procedure Allocate is
325 new Tree_Operations.Generic_Allocate (Set_Element);
331 function New_Node return Count_Type is
334 Allocate (Target, Result);
342 procedure Set_Element (Node : in out Node_Type) is
344 Node.Element := SN.Element;
347 Target_Node : Count_Type;
349 -- Start of processing for Append_Element
352 Unconditional_Insert_Avec_Hint
356 Node => Target_Node);
359 -- Start of processing for Assign
362 if Target'Address = Source'Address then
366 if Target.Capacity < Source.Length then
368 with "Target capacity is less than Source length";
372 Append_Elements (Source);
379 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
380 Node : constant Count_Type :=
381 Element_Keys.Ceiling (Container, Item);
383 return (if Node = 0 then No_Element
384 else Cursor'(Container'Unrestricted_Access, Node));
391 procedure Clear (Container : in out Set) is
393 Tree_Operations.Clear_Tree (Container);
400 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type is
411 Item : Element_Type) return Boolean
414 return Find (Container, Item) /= No_Element;
421 function Copy (Source : Set; Capacity : Count_Type := 0) return Set is
427 elsif Capacity >= Source.Length then
430 raise Capacity_Error with "Capacity value too small";
433 return Target : Set (Capacity => C) do
434 Assign (Target => Target, Source => Source);
442 procedure Delete (Container : in out Set; Position : in out Cursor) is
444 if Position.Node = 0 then
445 raise Constraint_Error with "Position cursor equals No_Element";
448 if Position.Container /= Container'Unrestricted_Access then
449 raise Program_Error with "Position cursor designates wrong set";
452 pragma Assert (Vet (Container, Position.Node),
453 "bad cursor in Delete");
455 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
456 Tree_Operations.Free (Container, Position.Node);
458 Position := No_Element;
461 procedure Delete (Container : in out Set; Item : Element_Type) is
462 X : constant Count_Type := Element_Keys.Find (Container, Item);
466 raise Constraint_Error with "attempt to delete element not in set";
469 Tree_Operations.Delete_Node_Sans_Free (Container, X);
470 Tree_Operations.Free (Container, X);
477 procedure Delete_First (Container : in out Set) is
478 X : constant Count_Type := Container.First;
481 Tree_Operations.Delete_Node_Sans_Free (Container, X);
482 Tree_Operations.Free (Container, X);
490 procedure Delete_Last (Container : in out Set) is
491 X : constant Count_Type := Container.Last;
494 Tree_Operations.Delete_Node_Sans_Free (Container, X);
495 Tree_Operations.Free (Container, X);
503 procedure Difference (Target : in out Set; Source : Set)
504 renames Set_Ops.Set_Difference;
506 function Difference (Left, Right : Set) return Set
507 renames Set_Ops.Set_Difference;
513 function Element (Position : Cursor) return Element_Type is
515 if Position.Node = 0 then
516 raise Constraint_Error with "Position cursor equals No_Element";
519 pragma Assert (Vet (Position.Container.all, Position.Node),
520 "bad cursor in Element");
522 return Position.Container.Nodes (Position.Node).Element;
525 -------------------------
526 -- Equivalent_Elements --
527 -------------------------
529 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
531 return (if Left < Right or else Right < Left then False else True);
532 end Equivalent_Elements;
534 ---------------------
535 -- Equivalent_Sets --
536 ---------------------
538 function Equivalent_Sets (Left, Right : Set) return Boolean is
539 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean;
540 pragma Inline (Is_Equivalent_Node_Node);
542 function Is_Equivalent is
543 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
545 -----------------------------
546 -- Is_Equivalent_Node_Node --
547 -----------------------------
549 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean is
551 return (if L.Element < R.Element then False
552 elsif R.Element < L.Element then False
554 end Is_Equivalent_Node_Node;
556 -- Start of processing for Equivalent_Sets
559 return Is_Equivalent (Left, Right);
566 procedure Exclude (Container : in out Set; Item : Element_Type) is
567 X : constant Count_Type := Element_Keys.Find (Container, Item);
570 Tree_Operations.Delete_Node_Sans_Free (Container, X);
571 Tree_Operations.Free (Container, X);
579 procedure Finalize (Object : in out Iterator) is
581 if Object.Container /= null then
583 B : Natural renames Object.Container.all.Busy;
594 function Find (Container : Set; Item : Element_Type) return Cursor is
595 Node : constant Count_Type := Element_Keys.Find (Container, Item);
597 return (if Node = 0 then No_Element
598 else Cursor'(Container'Unrestricted_Access, Node));
605 function First (Container : Set) return Cursor is
607 return (if Container.First = 0 then No_Element
608 else Cursor'(Container'Unrestricted_Access, Container.First));
611 function First (Object : Iterator) return Cursor is
613 -- The value of the iterator object's Node component influences the
614 -- behavior of the First (and Last) selector function.
616 -- When the Node component is 0, this means the iterator object was
617 -- constructed without a start expression, in which case the (forward)
618 -- iteration starts from the (logical) beginning of the entire sequence
619 -- of items (corresponding to Container.First, for a forward iterator).
621 -- Otherwise, this is iteration over a partial sequence of items. When
622 -- the Node component is positive, the iterator object was constructed
623 -- with a start expression, that specifies the position from which the
624 -- (forward) partial iteration begins.
626 if Object.Node = 0 then
627 return Bounded_Ordered_Sets.First (Object.Container.all);
629 return Cursor'(Object.Container, Object.Node);
637 function First_Element (Container : Set) return Element_Type is
639 if Container.First = 0 then
640 raise Constraint_Error with "set is empty";
643 return Container.Nodes (Container.First).Element;
650 function Floor (Container : Set; Item : Element_Type) return Cursor is
651 Node : constant Count_Type := Element_Keys.Floor (Container, Item);
653 return (if Node = 0 then No_Element
654 else Cursor'(Container'Unrestricted_Access, Node));
661 package body Generic_Keys is
663 -----------------------
664 -- Local Subprograms --
665 -----------------------
667 function Is_Greater_Key_Node
669 Right : Node_Type) return Boolean;
670 pragma Inline (Is_Greater_Key_Node);
672 function Is_Less_Key_Node
674 Right : Node_Type) return Boolean;
675 pragma Inline (Is_Less_Key_Node);
677 --------------------------
678 -- Local Instantiations --
679 --------------------------
682 new Red_Black_Trees.Generic_Bounded_Keys
683 (Tree_Operations => Tree_Operations,
684 Key_Type => Key_Type,
685 Is_Less_Key_Node => Is_Less_Key_Node,
686 Is_Greater_Key_Node => Is_Greater_Key_Node);
692 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
693 Node : constant Count_Type :=
694 Key_Keys.Ceiling (Container, Key);
696 return (if Node = 0 then No_Element
697 else Cursor'(Container'Unrestricted_Access, Node));
704 function Contains (Container : Set; Key : Key_Type) return Boolean is
706 return Find (Container, Key) /= No_Element;
713 procedure Delete (Container : in out Set; Key : Key_Type) is
714 X : constant Count_Type := Key_Keys.Find (Container, Key);
718 raise Constraint_Error with "attempt to delete key not in set";
721 Tree_Operations.Delete_Node_Sans_Free (Container, X);
722 Tree_Operations.Free (Container, X);
729 function Element (Container : Set; Key : Key_Type) return Element_Type is
730 Node : constant Count_Type := Key_Keys.Find (Container, Key);
734 raise Constraint_Error with "key not in set";
737 return Container.Nodes (Node).Element;
740 ---------------------
741 -- Equivalent_Keys --
742 ---------------------
744 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
746 return (if Left < Right or else Right < Left then False else True);
753 procedure Exclude (Container : in out Set; Key : Key_Type) is
754 X : constant Count_Type := Key_Keys.Find (Container, Key);
757 Tree_Operations.Delete_Node_Sans_Free (Container, X);
758 Tree_Operations.Free (Container, X);
766 function Find (Container : Set; Key : Key_Type) return Cursor is
767 Node : constant Count_Type := Key_Keys.Find (Container, Key);
769 return (if Node = 0 then No_Element
770 else Cursor'(Container'Unrestricted_Access, Node));
777 function Floor (Container : Set; Key : Key_Type) return Cursor is
778 Node : constant Count_Type := Key_Keys.Floor (Container, Key);
780 return (if Node = 0 then No_Element
781 else Cursor'(Container'Unrestricted_Access, Node));
784 -------------------------
785 -- Is_Greater_Key_Node --
786 -------------------------
788 function Is_Greater_Key_Node
790 Right : Node_Type) return Boolean
793 return Key (Right.Element) < Left;
794 end Is_Greater_Key_Node;
796 ----------------------
797 -- Is_Less_Key_Node --
798 ----------------------
800 function Is_Less_Key_Node
802 Right : Node_Type) return Boolean
805 return Left < Key (Right.Element);
806 end Is_Less_Key_Node;
812 function Key (Position : Cursor) return Key_Type is
814 if Position.Node = 0 then
815 raise Constraint_Error with
816 "Position cursor equals No_Element";
819 pragma Assert (Vet (Position.Container.all, Position.Node),
820 "bad cursor in Key");
822 return Key (Position.Container.Nodes (Position.Node).Element);
830 (Container : in out Set;
832 New_Item : Element_Type)
834 Node : constant Count_Type := Key_Keys.Find (Container, Key);
838 raise Constraint_Error with
839 "attempt to replace key not in set";
842 Replace_Element (Container, Node, New_Item);
845 -----------------------------------
846 -- Update_Element_Preserving_Key --
847 -----------------------------------
849 procedure Update_Element_Preserving_Key
850 (Container : in out Set;
852 Process : not null access procedure (Element : in out Element_Type))
855 if Position.Node = 0 then
856 raise Constraint_Error with
857 "Position cursor equals No_Element";
860 if Position.Container /= Container'Unrestricted_Access then
861 raise Program_Error with
862 "Position cursor designates wrong set";
865 pragma Assert (Vet (Container, Position.Node),
866 "bad cursor in Update_Element_Preserving_Key");
869 N : Node_Type renames Container.Nodes (Position.Node);
870 E : Element_Type renames N.Element;
871 K : constant Key_Type := Key (E);
873 B : Natural renames Container.Busy;
874 L : Natural renames Container.Lock;
892 if Equivalent_Keys (K, Key (E)) then
897 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
898 Tree_Operations.Free (Container, Position.Node);
900 raise Program_Error with "key was modified";
901 end Update_Element_Preserving_Key;
903 function Reference_Preserving_Key
904 (Container : aliased in out Set;
905 Key : Key_Type) return Constant_Reference_Type
907 Position : constant Cursor := Find (Container, Key);
910 if Position.Node = 0 then
911 raise Constraint_Error with "Position cursor has no element";
916 Container.Nodes (Position.Node).Element'Unrestricted_Access);
917 end Reference_Preserving_Key;
919 function Reference_Preserving_Key
920 (Container : aliased in out Set;
921 Key : Key_Type) return Reference_Type
923 Position : constant Cursor := Find (Container, Key);
926 if Position.Node = 0 then
927 raise Constraint_Error with "Position cursor has no element";
932 Container.Nodes (Position.Node).Element'Unrestricted_Access);
933 end Reference_Preserving_Key;
936 (Stream : not null access Root_Stream_Type'Class;
937 Item : out Reference_Type)
940 raise Program_Error with "attempt to stream reference";
944 (Stream : not null access Root_Stream_Type'Class;
945 Item : Reference_Type)
948 raise Program_Error with "attempt to stream reference";
956 function Has_Element (Position : Cursor) return Boolean is
958 return Position /= No_Element;
965 procedure Include (Container : in out Set; New_Item : Element_Type) is
970 Insert (Container, New_Item, Position, Inserted);
973 if Container.Lock > 0 then
974 raise Program_Error with
975 "attempt to tamper with elements (set is locked)";
978 Container.Nodes (Position.Node).Element := New_Item;
987 (Container : in out Set;
988 New_Item : Element_Type;
989 Position : out Cursor;
990 Inserted : out Boolean)
999 Position.Container := Container'Unrestricted_Access;
1003 (Container : in out Set;
1004 New_Item : Element_Type)
1007 pragma Unreferenced (Position);
1012 Insert (Container, New_Item, Position, Inserted);
1014 if not Inserted then
1015 raise Constraint_Error with
1016 "attempt to insert element already in set";
1020 ----------------------
1021 -- Insert_Sans_Hint --
1022 ----------------------
1024 procedure Insert_Sans_Hint
1025 (Container : in out Set;
1026 New_Item : Element_Type;
1027 Node : out Count_Type;
1028 Inserted : out Boolean)
1030 procedure Set_Element (Node : in out Node_Type);
1031 pragma Inline (Set_Element);
1033 function New_Node return Count_Type;
1034 pragma Inline (New_Node);
1036 procedure Insert_Post is
1037 new Element_Keys.Generic_Insert_Post (New_Node);
1039 procedure Conditional_Insert_Sans_Hint is
1040 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1042 procedure Allocate is
1043 new Tree_Operations.Generic_Allocate (Set_Element);
1049 function New_Node return Count_Type is
1050 Result : Count_Type;
1052 Allocate (Container, Result);
1060 procedure Set_Element (Node : in out Node_Type) is
1062 Node.Element := New_Item;
1065 -- Start of processing for Insert_Sans_Hint
1068 Conditional_Insert_Sans_Hint
1073 end Insert_Sans_Hint;
1075 ----------------------
1076 -- Insert_With_Hint --
1077 ----------------------
1079 procedure Insert_With_Hint
1080 (Dst_Set : in out Set;
1081 Dst_Hint : Count_Type;
1082 Src_Node : Node_Type;
1083 Dst_Node : out Count_Type)
1086 pragma Unreferenced (Success);
1088 procedure Set_Element (Node : in out Node_Type);
1089 pragma Inline (Set_Element);
1091 function New_Node return Count_Type;
1092 pragma Inline (New_Node);
1094 procedure Insert_Post is
1095 new Element_Keys.Generic_Insert_Post (New_Node);
1097 procedure Insert_Sans_Hint is
1098 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1100 procedure Local_Insert_With_Hint is
1101 new Element_Keys.Generic_Conditional_Insert_With_Hint
1105 procedure Allocate is
1106 new Tree_Operations.Generic_Allocate (Set_Element);
1112 function New_Node return Count_Type is
1113 Result : Count_Type;
1115 Allocate (Dst_Set, Result);
1123 procedure Set_Element (Node : in out Node_Type) is
1125 Node.Element := Src_Node.Element;
1128 -- Start of processing for Insert_With_Hint
1131 Local_Insert_With_Hint
1137 end Insert_With_Hint;
1143 procedure Intersection (Target : in out Set; Source : Set)
1144 renames Set_Ops.Set_Intersection;
1146 function Intersection (Left, Right : Set) return Set
1147 renames Set_Ops.Set_Intersection;
1153 function Is_Empty (Container : Set) return Boolean is
1155 return Container.Length = 0;
1158 -----------------------------
1159 -- Is_Greater_Element_Node --
1160 -----------------------------
1162 function Is_Greater_Element_Node
1163 (Left : Element_Type;
1164 Right : Node_Type) return Boolean
1167 -- Compute e > node same as node < e
1169 return Right.Element < Left;
1170 end Is_Greater_Element_Node;
1172 --------------------------
1173 -- Is_Less_Element_Node --
1174 --------------------------
1176 function Is_Less_Element_Node
1177 (Left : Element_Type;
1178 Right : Node_Type) return Boolean
1181 return Left < Right.Element;
1182 end Is_Less_Element_Node;
1184 -----------------------
1185 -- Is_Less_Node_Node --
1186 -----------------------
1188 function Is_Less_Node_Node (L, R : Node_Type) return Boolean is
1190 return L.Element < R.Element;
1191 end Is_Less_Node_Node;
1197 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean
1198 renames Set_Ops.Set_Subset;
1206 Process : not null access procedure (Position : Cursor))
1208 procedure Process_Node (Node : Count_Type);
1209 pragma Inline (Process_Node);
1211 procedure Local_Iterate is
1212 new Tree_Operations.Generic_Iteration (Process_Node);
1218 procedure Process_Node (Node : Count_Type) is
1220 Process (Cursor'(Container'Unrestricted_Access, Node));
1223 S : Set renames Container'Unrestricted_Access.all;
1224 B : Natural renames S.Busy;
1226 -- Start of processing for Iterate
1242 function Iterate (Container : Set)
1243 return Set_Iterator_Interfaces.Reversible_Iterator'class
1245 B : Natural renames Container'Unrestricted_Access.all.Busy;
1248 -- The value of the Node component influences the behavior of the First
1249 -- and Last selector functions of the iterator object. When the Node
1250 -- component is 0 (as is the case here), this means the iterator object
1251 -- was constructed without a start expression. This is a complete
1252 -- iterator, meaning that the iteration starts from the (logical)
1253 -- beginning of the sequence of items.
1255 -- Note: For a forward iterator, Container.First is the beginning, and
1256 -- for a reverse iterator, Container.Last is the beginning.
1258 return It : constant Iterator :=
1259 Iterator'(Limited_Controlled with
1260 Container => Container'Unrestricted_Access,
1267 function Iterate (Container : Set; Start : Cursor)
1268 return Set_Iterator_Interfaces.Reversible_Iterator'class
1270 B : Natural renames Container'Unrestricted_Access.all.Busy;
1273 -- It was formerly the case that when Start = No_Element, the partial
1274 -- iterator was defined to behave the same as for a complete iterator,
1275 -- and iterate over the entire sequence of items. However, those
1276 -- semantics were unintuitive and arguably error-prone (it is too easy
1277 -- to accidentally create an endless loop), and so they were changed,
1278 -- per the ARG meeting in Denver on 2011/11. However, there was no
1279 -- consensus about what positive meaning this corner case should have,
1280 -- and so it was decided to simply raise an exception. This does imply,
1281 -- however, that it is not possible to use a partial iterator to specify
1282 -- an empty sequence of items.
1284 if Start = No_Element then
1285 raise Constraint_Error with
1286 "Start position for iterator equals No_Element";
1289 if Start.Container /= Container'Unrestricted_Access then
1290 raise Program_Error with
1291 "Start cursor of Iterate designates wrong set";
1294 pragma Assert (Vet (Container, Start.Node),
1295 "Start cursor of Iterate is bad");
1297 -- The value of the Node component influences the behavior of the First
1298 -- and Last selector functions of the iterator object. When the Node
1299 -- component is positive (as is the case here), it means that this
1300 -- is a partial iteration, over a subset of the complete sequence of
1301 -- items. The iterator object was constructed with a start expression,
1302 -- indicating the position from which the iteration begins. (Note that
1303 -- the start position has the same value irrespective of whether this
1304 -- is a forward or reverse iteration.)
1306 return It : constant Iterator :=
1307 Iterator'(Limited_Controlled with
1308 Container => Container'Unrestricted_Access,
1319 function Last (Container : Set) return Cursor is
1321 return (if Container.Last = 0 then No_Element
1322 else Cursor'(Container'Unrestricted_Access, Container.Last));
1325 function Last (Object : Iterator) return Cursor is
1327 -- The value of the iterator object's Node component influences the
1328 -- behavior of the Last (and First) selector function.
1330 -- When the Node component is 0, this means the iterator object was
1331 -- constructed without a start expression, in which case the (reverse)
1332 -- iteration starts from the (logical) beginning of the entire sequence
1333 -- (corresponding to Container.Last, for a reverse iterator).
1335 -- Otherwise, this is iteration over a partial sequence of items. When
1336 -- the Node component is positive, the iterator object was constructed
1337 -- with a start expression, that specifies the position from which the
1338 -- (reverse) partial iteration begins.
1340 if Object.Node = 0 then
1341 return Bounded_Ordered_Sets.Last (Object.Container.all);
1343 return Cursor'(Object.Container, Object.Node);
1351 function Last_Element (Container : Set) return Element_Type is
1353 if Container.Last = 0 then
1354 raise Constraint_Error with "set is empty";
1357 return Container.Nodes (Container.Last).Element;
1364 function Left (Node : Node_Type) return Count_Type is
1373 function Length (Container : Set) return Count_Type is
1375 return Container.Length;
1382 procedure Move (Target : in out Set; Source : in out Set) is
1384 if Target'Address = Source'Address then
1388 if Source.Busy > 0 then
1389 raise Program_Error with
1390 "attempt to tamper with cursors (container is busy)";
1393 Target.Assign (Source);
1401 function Next (Position : Cursor) return Cursor is
1403 if Position = No_Element then
1407 pragma Assert (Vet (Position.Container.all, Position.Node),
1408 "bad cursor in Next");
1411 Node : constant Count_Type :=
1412 Tree_Operations.Next (Position.Container.all, Position.Node);
1419 return Cursor'(Position.Container, Node);
1423 procedure Next (Position : in out Cursor) is
1425 Position := Next (Position);
1428 function Next (Object : Iterator; Position : Cursor) return Cursor is
1430 if Position.Container = null then
1434 if Position.Container /= Object.Container then
1435 raise Program_Error with
1436 "Position cursor of Next designates wrong set";
1439 return Next (Position);
1446 function Overlap (Left, Right : Set) return Boolean
1447 renames Set_Ops.Set_Overlap;
1453 function Parent (Node : Node_Type) return Count_Type is
1462 function Previous (Position : Cursor) return Cursor is
1464 if Position = No_Element then
1468 pragma Assert (Vet (Position.Container.all, Position.Node),
1469 "bad cursor in Previous");
1472 Node : constant Count_Type :=
1473 Tree_Operations.Previous
1474 (Position.Container.all,
1477 return (if Node = 0 then No_Element
1478 else Cursor'(Position.Container, Node));
1482 procedure Previous (Position : in out Cursor) is
1484 Position := Previous (Position);
1487 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1489 if Position.Container = null then
1493 if Position.Container /= Object.Container then
1494 raise Program_Error with
1495 "Position cursor of Previous designates wrong set";
1498 return Previous (Position);
1505 procedure Query_Element
1507 Process : not null access procedure (Element : Element_Type))
1510 if Position.Node = 0 then
1511 raise Constraint_Error with "Position cursor equals No_Element";
1514 pragma Assert (Vet (Position.Container.all, Position.Node),
1515 "bad cursor in Query_Element");
1518 S : Set renames Position.Container.all;
1519 B : Natural renames S.Busy;
1520 L : Natural renames S.Lock;
1527 Process (S.Nodes (Position.Node).Element);
1545 (Stream : not null access Root_Stream_Type'Class;
1546 Container : out Set)
1548 procedure Read_Element (Node : in out Node_Type);
1549 pragma Inline (Read_Element);
1551 procedure Allocate is
1552 new Tree_Operations.Generic_Allocate (Read_Element);
1554 procedure Read_Elements is
1555 new Tree_Operations.Generic_Read (Allocate);
1561 procedure Read_Element (Node : in out Node_Type) is
1563 Element_Type'Read (Stream, Node.Element);
1566 -- Start of processing for Read
1569 Read_Elements (Stream, Container);
1573 (Stream : not null access Root_Stream_Type'Class;
1577 raise Program_Error with "attempt to stream set cursor";
1581 (Stream : not null access Root_Stream_Type'Class;
1582 Item : out Constant_Reference_Type)
1585 raise Program_Error with "attempt to stream reference";
1592 function Constant_Reference (Container : Set; Position : Cursor)
1593 return Constant_Reference_Type
1596 if Position.Container = null then
1597 raise Constraint_Error with "Position cursor has no element";
1601 Container.Nodes (Position.Node).Element'Unrestricted_Access);
1602 end Constant_Reference;
1608 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1609 Node : constant Count_Type := Element_Keys.Find (Container, New_Item);
1613 raise Constraint_Error with
1614 "attempt to replace element not in set";
1617 if Container.Lock > 0 then
1618 raise Program_Error with
1619 "attempt to tamper with elements (set is locked)";
1622 Container.Nodes (Node).Element := New_Item;
1625 ---------------------
1626 -- Replace_Element --
1627 ---------------------
1629 procedure Replace_Element
1630 (Container : in out Set;
1632 Item : Element_Type)
1634 pragma Assert (Index /= 0);
1636 function New_Node return Count_Type;
1637 pragma Inline (New_Node);
1639 procedure Local_Insert_Post is
1640 new Element_Keys.Generic_Insert_Post (New_Node);
1642 procedure Local_Insert_Sans_Hint is
1643 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1645 procedure Local_Insert_With_Hint is
1646 new Element_Keys.Generic_Conditional_Insert_With_Hint
1648 Local_Insert_Sans_Hint);
1650 Nodes : Nodes_Type renames Container.Nodes;
1651 Node : Node_Type renames Nodes (Index);
1657 function New_Node return Count_Type is
1659 Node.Element := Item;
1660 Node.Color := Red_Black_Trees.Red;
1668 Result : Count_Type;
1671 -- Start of processing for Replace_Element
1674 if Item < Node.Element
1675 or else Node.Element < Item
1680 if Container.Lock > 0 then
1681 raise Program_Error with
1682 "attempt to tamper with elements (set is locked)";
1685 Node.Element := Item;
1689 Hint := Element_Keys.Ceiling (Container, Item);
1694 elsif Item < Nodes (Hint).Element then
1695 if Hint = Index then
1696 if Container.Lock > 0 then
1697 raise Program_Error with
1698 "attempt to tamper with elements (set is locked)";
1701 Node.Element := Item;
1706 pragma Assert (not (Nodes (Hint).Element < Item));
1707 raise Program_Error with "attempt to replace existing element";
1710 Tree_Operations.Delete_Node_Sans_Free (Container, Index);
1712 Local_Insert_With_Hint
1717 Inserted => Inserted);
1719 pragma Assert (Inserted);
1720 pragma Assert (Result = Index);
1721 end Replace_Element;
1723 procedure Replace_Element
1724 (Container : in out Set;
1726 New_Item : Element_Type)
1729 if Position.Node = 0 then
1730 raise Constraint_Error with
1731 "Position cursor equals No_Element";
1734 if Position.Container /= Container'Unrestricted_Access then
1735 raise Program_Error with
1736 "Position cursor designates wrong set";
1739 pragma Assert (Vet (Container, Position.Node),
1740 "bad cursor in Replace_Element");
1742 Replace_Element (Container, Position.Node, New_Item);
1743 end Replace_Element;
1745 ---------------------
1746 -- Reverse_Iterate --
1747 ---------------------
1749 procedure Reverse_Iterate
1751 Process : not null access procedure (Position : Cursor))
1753 procedure Process_Node (Node : Count_Type);
1754 pragma Inline (Process_Node);
1756 procedure Local_Reverse_Iterate is
1757 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1763 procedure Process_Node (Node : Count_Type) is
1765 Process (Cursor'(Container'Unrestricted_Access, Node));
1768 S : Set renames Container'Unrestricted_Access.all;
1769 B : Natural renames S.Busy;
1771 -- Start of processing for Reverse_Iterate
1777 Local_Reverse_Iterate (S);
1785 end Reverse_Iterate;
1791 function Right (Node : Node_Type) return Count_Type is
1801 (Node : in out Node_Type;
1802 Color : Red_Black_Trees.Color_Type)
1805 Node.Color := Color;
1812 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1821 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1823 Node.Parent := Parent;
1830 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1832 Node.Right := Right;
1835 --------------------------
1836 -- Symmetric_Difference --
1837 --------------------------
1839 procedure Symmetric_Difference (Target : in out Set; Source : Set)
1840 renames Set_Ops.Set_Symmetric_Difference;
1842 function Symmetric_Difference (Left, Right : Set) return Set
1843 renames Set_Ops.Set_Symmetric_Difference;
1849 function To_Set (New_Item : Element_Type) return Set is
1853 return S : Set (1) do
1854 Insert_Sans_Hint (S, New_Item, Node, Inserted);
1855 pragma Assert (Inserted);
1863 procedure Union (Target : in out Set; Source : Set)
1864 renames Set_Ops.Set_Union;
1866 function Union (Left, Right : Set) return Set
1867 renames Set_Ops.Set_Union;
1874 (Stream : not null access Root_Stream_Type'Class;
1877 procedure Write_Element
1878 (Stream : not null access Root_Stream_Type'Class;
1880 pragma Inline (Write_Element);
1882 procedure Write_Elements is
1883 new Tree_Operations.Generic_Write (Write_Element);
1889 procedure Write_Element
1890 (Stream : not null access Root_Stream_Type'Class;
1894 Element_Type'Write (Stream, Node.Element);
1897 -- Start of processing for Write
1900 Write_Elements (Stream, Container);
1904 (Stream : not null access Root_Stream_Type'Class;
1908 raise Program_Error with "attempt to stream set cursor";
1912 (Stream : not null access Root_Stream_Type'Class;
1913 Item : Constant_Reference_Type)
1916 raise Program_Error with "attempt to stream reference";
1919 end Ada.Containers.Bounded_Ordered_Sets;