1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_MULTISETS --
9 -- Copyright (C) 2004-2012, 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
.Indefinite_Ordered_Multisets
is
45 type Iterator
is new Limited_Controlled
and
46 Set_Iterator_Interfaces
.Reversible_Iterator
with
48 Container
: Set_Access
;
52 overriding
procedure Finalize
(Object
: in out Iterator
);
54 overriding
function First
(Object
: Iterator
) return Cursor
;
55 overriding
function Last
(Object
: Iterator
) return Cursor
;
57 overriding
function Next
59 Position
: Cursor
) return Cursor
;
61 overriding
function Previous
63 Position
: Cursor
) return Cursor
;
65 -----------------------------
66 -- Node Access Subprograms --
67 -----------------------------
69 -- These subprograms provide a functional interface to access fields
70 -- of a node, and a procedural interface for modifying these values.
72 function Color
(Node
: Node_Access
) return Color_Type
;
73 pragma Inline
(Color
);
75 function Left
(Node
: Node_Access
) return Node_Access
;
78 function Parent
(Node
: Node_Access
) return Node_Access
;
79 pragma Inline
(Parent
);
81 function Right
(Node
: Node_Access
) return Node_Access
;
82 pragma Inline
(Right
);
84 procedure Set_Parent
(Node
: Node_Access
; Parent
: Node_Access
);
85 pragma Inline
(Set_Parent
);
87 procedure Set_Left
(Node
: Node_Access
; Left
: Node_Access
);
88 pragma Inline
(Set_Left
);
90 procedure Set_Right
(Node
: Node_Access
; Right
: Node_Access
);
91 pragma Inline
(Set_Right
);
93 procedure Set_Color
(Node
: Node_Access
; Color
: Color_Type
);
94 pragma Inline
(Set_Color
);
96 -----------------------
97 -- Local Subprograms --
98 -----------------------
100 function Copy_Node
(Source
: Node_Access
) return Node_Access
;
101 pragma Inline
(Copy_Node
);
103 procedure Free
(X
: in out Node_Access
);
105 procedure Insert_Sans_Hint
106 (Tree
: in out Tree_Type
;
107 New_Item
: Element_Type
;
108 Node
: out Node_Access
);
110 procedure Insert_With_Hint
111 (Dst_Tree
: in out Tree_Type
;
112 Dst_Hint
: Node_Access
;
113 Src_Node
: Node_Access
;
114 Dst_Node
: out Node_Access
);
116 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean;
117 pragma Inline
(Is_Equal_Node_Node
);
119 function Is_Greater_Element_Node
120 (Left
: Element_Type
;
121 Right
: Node_Access
) return Boolean;
122 pragma Inline
(Is_Greater_Element_Node
);
124 function Is_Less_Element_Node
125 (Left
: Element_Type
;
126 Right
: Node_Access
) return Boolean;
127 pragma Inline
(Is_Less_Element_Node
);
129 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean;
130 pragma Inline
(Is_Less_Node_Node
);
132 procedure Replace_Element
133 (Tree
: in out Tree_Type
;
135 Item
: Element_Type
);
137 --------------------------
138 -- Local Instantiations --
139 --------------------------
141 package Tree_Operations
is
142 new Red_Black_Trees
.Generic_Operations
(Tree_Types
);
144 procedure Delete_Tree
is
145 new Tree_Operations
.Generic_Delete_Tree
(Free
);
147 function Copy_Tree
is
148 new Tree_Operations
.Generic_Copy_Tree
(Copy_Node
, Delete_Tree
);
152 procedure Free_Element
is
153 new Ada
.Unchecked_Deallocation
(Element_Type
, Element_Access
);
156 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
159 new Generic_Set_Operations
160 (Tree_Operations
=> Tree_Operations
,
161 Insert_With_Hint
=> Insert_With_Hint
,
162 Copy_Tree
=> Copy_Tree
,
163 Delete_Tree
=> Delete_Tree
,
164 Is_Less
=> Is_Less_Node_Node
,
167 package Element_Keys
is
168 new Red_Black_Trees
.Generic_Keys
169 (Tree_Operations
=> Tree_Operations
,
170 Key_Type
=> Element_Type
,
171 Is_Less_Key_Node
=> Is_Less_Element_Node
,
172 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
178 function "<" (Left
, Right
: Cursor
) return Boolean is
180 if Left
.Node
= null then
181 raise Constraint_Error
with "Left cursor equals No_Element";
184 if Right
.Node
= null then
185 raise Constraint_Error
with "Right cursor equals No_Element";
188 if Left
.Node
.Element
= null then
189 raise Program_Error
with "Left cursor is bad";
192 if Right
.Node
.Element
= null then
193 raise Program_Error
with "Right cursor is bad";
196 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
197 "bad Left cursor in ""<""");
199 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
200 "bad Right cursor in ""<""");
202 return Left
.Node
.Element
.all < Right
.Node
.Element
.all;
205 function "<" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
207 if Left
.Node
= null then
208 raise Constraint_Error
with "Left cursor equals No_Element";
211 if Left
.Node
.Element
= null then
212 raise Program_Error
with "Left cursor is bad";
215 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
216 "bad Left cursor in ""<""");
218 return Left
.Node
.Element
.all < Right
;
221 function "<" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
223 if Right
.Node
= null then
224 raise Constraint_Error
with "Right cursor equals No_Element";
227 if Right
.Node
.Element
= null then
228 raise Program_Error
with "Right cursor is bad";
231 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
232 "bad Right cursor in ""<""");
234 return Left
< Right
.Node
.Element
.all;
241 function "=" (Left
, Right
: Set
) return Boolean is
243 return Is_Equal
(Left
.Tree
, Right
.Tree
);
250 function ">" (Left
, Right
: Cursor
) return Boolean is
252 if Left
.Node
= null then
253 raise Constraint_Error
with "Left cursor equals No_Element";
256 if Right
.Node
= null then
257 raise Constraint_Error
with "Right cursor equals No_Element";
260 if Left
.Node
.Element
= null then
261 raise Program_Error
with "Left cursor is bad";
264 if Right
.Node
.Element
= null then
265 raise Program_Error
with "Right cursor is bad";
268 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
269 "bad Left cursor in "">""");
271 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
272 "bad Right cursor in "">""");
274 -- L > R same as R < L
276 return Right
.Node
.Element
.all < Left
.Node
.Element
.all;
279 function ">" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
281 if Left
.Node
= null then
282 raise Constraint_Error
with "Left cursor equals No_Element";
285 if Left
.Node
.Element
= null then
286 raise Program_Error
with "Left cursor is bad";
289 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
290 "bad Left cursor in "">""");
292 return Right
< Left
.Node
.Element
.all;
295 function ">" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
297 if Right
.Node
= null then
298 raise Constraint_Error
with "Right cursor equals No_Element";
301 if Right
.Node
.Element
= null then
302 raise Program_Error
with "Right cursor is bad";
305 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
306 "bad Right cursor in "">""");
308 return Right
.Node
.Element
.all < Left
;
316 new Tree_Operations
.Generic_Adjust
(Copy_Tree
);
318 procedure Adjust
(Container
: in out Set
) is
320 Adjust
(Container
.Tree
);
327 procedure Assign
(Target
: in out Set
; Source
: Set
) is
329 if Target
'Address = Source
'Address then
334 Target
.Union
(Source
);
341 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
342 Node
: constant Node_Access
:=
343 Element_Keys
.Ceiling
(Container
.Tree
, Item
);
350 return Cursor
'(Container'Unrestricted_Access, Node);
358 new Tree_Operations.Generic_Clear (Delete_Tree);
360 procedure Clear (Container : in out Set) is
362 Clear (Container.Tree);
369 function Color (Node : Node_Access) return Color_Type is
378 function Contains (Container : Set; Item : Element_Type) return Boolean is
380 return Find (Container, Item) /= No_Element;
387 function Copy (Source : Set) return Set is
389 return Target : Set do
390 Target.Assign (Source);
398 function Copy_Node (Source : Node_Access) return Node_Access is
399 X : Element_Access := new Element_Type'(Source
.Element
.all);
402 return new Node_Type
'(Parent => null,
405 Color => Source.Color,
418 procedure Delete (Container : in out Set; Item : Element_Type) is
419 Tree : Tree_Type renames Container.Tree;
420 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
421 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
426 raise Constraint_Error with "attempt to delete element not in set";
431 Node := Tree_Operations.Next (Node);
432 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
435 exit when Node = Done;
439 procedure Delete (Container : in out Set; Position : in out Cursor) is
441 if Position.Node = null then
442 raise Constraint_Error with "Position cursor equals No_Element";
445 if Position.Node.Element = null then
446 raise Program_Error with "Position cursor is bad";
449 if Position.Container /= Container'Unrestricted_Access then
450 raise Program_Error with "Position cursor designates wrong set";
453 pragma Assert (Vet (Container.Tree, Position.Node),
454 "bad cursor in Delete");
456 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
457 Free (Position.Node);
459 Position.Container := null;
466 procedure Delete_First (Container : in out Set) is
467 Tree : Tree_Type renames Container.Tree;
468 X : Node_Access := Tree.First;
475 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
483 procedure Delete_Last (Container : in out Set) is
484 Tree : Tree_Type renames Container.Tree;
485 X : Node_Access := Tree.Last;
492 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
500 procedure Difference (Target : in out Set; Source : Set) is
502 Set_Ops.Difference (Target.Tree, Source.Tree);
505 function Difference (Left, Right : Set) return Set is
506 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
508 return Set'(Controlled
with Tree
);
515 function Element
(Position
: Cursor
) return Element_Type
is
517 if Position
.Node
= null then
518 raise Constraint_Error
with "Position cursor equals No_Element";
521 if Position
.Node
.Element
= null then
522 raise Program_Error
with "Position cursor is bad";
525 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
526 "bad cursor in Element");
528 return Position
.Node
.Element
.all;
531 -------------------------
532 -- Equivalent_Elements --
533 -------------------------
535 function Equivalent_Elements
(Left
, Right
: Element_Type
) return Boolean is
544 end Equivalent_Elements
;
546 ---------------------
547 -- Equivalent_Sets --
548 ---------------------
550 function Equivalent_Sets
(Left
, Right
: Set
) return Boolean is
552 function Is_Equivalent_Node_Node
(L
, R
: Node_Access
) return Boolean;
553 pragma Inline
(Is_Equivalent_Node_Node
);
555 function Is_Equivalent
is
556 new Tree_Operations
.Generic_Equal
(Is_Equivalent_Node_Node
);
558 -----------------------------
559 -- Is_Equivalent_Node_Node --
560 -----------------------------
562 function Is_Equivalent_Node_Node
(L
, R
: Node_Access
) return Boolean is
564 if L
.Element
.all < R
.Element
.all then
566 elsif R
.Element
.all < L
.Element
.all then
571 end Is_Equivalent_Node_Node
;
573 -- Start of processing for Equivalent_Sets
576 return Is_Equivalent
(Left
.Tree
, Right
.Tree
);
583 procedure Exclude
(Container
: in out Set
; Item
: Element_Type
) is
584 Tree
: Tree_Type
renames Container
.Tree
;
585 Node
: Node_Access
:= Element_Keys
.Ceiling
(Tree
, Item
);
586 Done
: constant Node_Access
:= Element_Keys
.Upper_Bound
(Tree
, Item
);
590 while Node
/= Done
loop
592 Node
:= Tree_Operations
.Next
(Node
);
593 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
602 function Find
(Container
: Set
; Item
: Element_Type
) return Cursor
is
603 Node
: constant Node_Access
:= Element_Keys
.Find
(Container
.Tree
, Item
);
610 return Cursor
'(Container'Unrestricted_Access, Node);
617 procedure Finalize (Object : in out Iterator) is
618 B : Natural renames Object.Container.Tree.Busy;
619 pragma Assert (B > 0);
628 function First (Container : Set) return Cursor is
630 if Container.Tree.First = null then
634 return Cursor'(Container
'Unrestricted_Access, Container
.Tree
.First
);
637 function First
(Object
: Iterator
) return Cursor
is
639 -- The value of the iterator object's Node component influences the
640 -- behavior of the First (and Last) selector function.
642 -- When the Node component is null, this means the iterator object was
643 -- constructed without a start expression, in which case the (forward)
644 -- iteration starts from the (logical) beginning of the entire sequence
645 -- of items (corresponding to Container.First, for a forward iterator).
647 -- Otherwise, this is iteration over a partial sequence of items. When
648 -- the Node component is non-null, the iterator object was constructed
649 -- with a start expression, that specifies the position from which the
650 -- (forward) partial iteration begins.
652 if Object
.Node
= null then
653 return Object
.Container
.First
;
655 return Cursor
'(Object.Container, Object.Node);
663 function First_Element (Container : Set) return Element_Type is
665 if Container.Tree.First = null then
666 raise Constraint_Error with "set is empty";
669 pragma Assert (Container.Tree.First.Element /= null);
670 return Container.Tree.First.Element.all;
677 function Floor (Container : Set; Item : Element_Type) return Cursor is
678 Node : constant Node_Access := Element_Keys.Floor (Container.Tree, Item);
685 return Cursor'(Container
'Unrestricted_Access, Node
);
692 procedure Free
(X
: in out Node_Access
) is
693 procedure Deallocate
is
694 new Ada
.Unchecked_Deallocation
(Node_Type
, Node_Access
);
706 Free_Element
(X
.Element
);
721 package body Generic_Keys
is
723 -----------------------
724 -- Local Subprograms --
725 -----------------------
727 function Is_Less_Key_Node
729 Right
: Node_Access
) return Boolean;
730 pragma Inline
(Is_Less_Key_Node
);
732 function Is_Greater_Key_Node
734 Right
: Node_Access
) return Boolean;
735 pragma Inline
(Is_Greater_Key_Node
);
737 --------------------------
738 -- Local Instantiations --
739 --------------------------
742 new Red_Black_Trees
.Generic_Keys
743 (Tree_Operations
=> Tree_Operations
,
744 Key_Type
=> Key_Type
,
745 Is_Less_Key_Node
=> Is_Less_Key_Node
,
746 Is_Greater_Key_Node
=> Is_Greater_Key_Node
);
752 function Ceiling
(Container
: Set
; Key
: Key_Type
) return Cursor
is
753 Node
: constant Node_Access
:= Key_Keys
.Ceiling
(Container
.Tree
, Key
);
760 return Cursor
'(Container'Unrestricted_Access, Node);
767 function Contains (Container : Set; Key : Key_Type) return Boolean is
769 return Find (Container, Key) /= No_Element;
776 procedure Delete (Container : in out Set; Key : Key_Type) is
777 Tree : Tree_Type renames Container.Tree;
778 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
779 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
784 raise Constraint_Error with "attempt to delete key not in set";
789 Node := Tree_Operations.Next (Node);
790 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
793 exit when Node = Done;
801 function Element (Container : Set; Key : Key_Type) return Element_Type is
802 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
806 raise Constraint_Error with "key not in set";
809 return Node.Element.all;
812 ---------------------
813 -- Equivalent_Keys --
814 ---------------------
816 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
831 procedure Exclude (Container : in out Set; Key : Key_Type) is
832 Tree : Tree_Type renames Container.Tree;
833 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
834 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
838 while Node /= Done loop
840 Node := Tree_Operations.Next (Node);
841 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
850 function Find (Container : Set; Key : Key_Type) return Cursor is
851 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
858 return Cursor'(Container
'Unrestricted_Access, Node
);
865 function Floor
(Container
: Set
; Key
: Key_Type
) return Cursor
is
866 Node
: constant Node_Access
:= Key_Keys
.Floor
(Container
.Tree
, Key
);
873 return Cursor
'(Container'Unrestricted_Access, Node);
876 -------------------------
877 -- Is_Greater_Key_Node --
878 -------------------------
880 function Is_Greater_Key_Node
882 Right : Node_Access) return Boolean
885 return Key (Right.Element.all) < Left;
886 end Is_Greater_Key_Node;
888 ----------------------
889 -- Is_Less_Key_Node --
890 ----------------------
892 function Is_Less_Key_Node
894 Right : Node_Access) return Boolean
897 return Left < Key (Right.Element.all);
898 end Is_Less_Key_Node;
907 Process : not null access procedure (Position : Cursor))
909 procedure Process_Node (Node : Node_Access);
910 pragma Inline (Process_Node);
912 procedure Local_Iterate is
913 new Key_Keys.Generic_Iteration (Process_Node);
919 procedure Process_Node (Node : Node_Access) is
921 Process (Cursor'(Container
'Unrestricted_Access, Node
));
924 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
925 B
: Natural renames T
.Busy
;
927 -- Start of processing for Iterate
933 Local_Iterate
(T
, Key
);
947 function Key
(Position
: Cursor
) return Key_Type
is
949 if Position
.Node
= null then
950 raise Constraint_Error
with
951 "Position cursor equals No_Element";
954 if Position
.Node
.Element
= null then
955 raise Program_Error
with
956 "Position cursor is bad";
959 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
960 "bad cursor in Key");
962 return Key
(Position
.Node
.Element
.all);
965 ---------------------
966 -- Reverse_Iterate --
967 ---------------------
969 procedure Reverse_Iterate
972 Process
: not null access procedure (Position
: Cursor
))
974 procedure Process_Node
(Node
: Node_Access
);
975 pragma Inline
(Process_Node
);
981 procedure Local_Reverse_Iterate
is
982 new Key_Keys
.Generic_Reverse_Iteration
(Process_Node
);
988 procedure Process_Node
(Node
: Node_Access
) is
990 Process
(Cursor
'(Container'Unrestricted_Access, Node));
993 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
994 B : Natural renames T.Busy;
996 -- Start of processing for Reverse_Iterate
1002 Local_Reverse_Iterate (T, Key);
1010 end Reverse_Iterate;
1012 --------------------
1013 -- Update_Element --
1014 --------------------
1016 procedure Update_Element
1017 (Container : in out Set;
1019 Process : not null access procedure (Element : in out Element_Type))
1021 Tree : Tree_Type renames Container.Tree;
1022 Node : constant Node_Access := Position.Node;
1026 raise Constraint_Error with "Position cursor equals No_Element";
1029 if Node.Element = null then
1030 raise Program_Error with "Position cursor is bad";
1033 if Position.Container /= Container'Unrestricted_Access then
1034 raise Program_Error with "Position cursor designates wrong set";
1037 pragma Assert (Vet (Tree, Node),
1038 "bad cursor in Update_Element");
1041 E : Element_Type renames Node.Element.all;
1042 K : constant Key_Type := Key (E);
1044 B : Natural renames Tree.Busy;
1045 L : Natural renames Tree.Lock;
1063 if Equivalent_Keys (Left => K, Right => Key (E)) then
1068 -- Delete_Node checks busy-bit
1070 Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
1072 Insert_New_Item : declare
1073 function New_Node return Node_Access;
1074 pragma Inline (New_Node);
1076 procedure Insert_Post is
1077 new Element_Keys.Generic_Insert_Post (New_Node);
1079 procedure Unconditional_Insert is
1080 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1086 function New_Node return Node_Access is
1088 Node.Color := Red_Black_Trees.Red;
1089 Node.Parent := null;
1096 Result : Node_Access;
1098 -- Start of processing for Insert_New_Item
1101 Unconditional_Insert
1103 Key => Node.Element.all,
1106 pragma Assert (Result = Node);
1107 end Insert_New_Item;
1116 function Has_Element (Position : Cursor) return Boolean is
1118 return Position /= No_Element;
1125 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1127 pragma Unreferenced (Position);
1129 Insert (Container, New_Item, Position);
1133 (Container : in out Set;
1134 New_Item : Element_Type;
1135 Position : out Cursor)
1138 Insert_Sans_Hint (Container.Tree, New_Item, Position.Node);
1139 Position.Container := Container'Unrestricted_Access;
1142 ----------------------
1143 -- Insert_Sans_Hint --
1144 ----------------------
1146 procedure Insert_Sans_Hint
1147 (Tree : in out Tree_Type;
1148 New_Item : Element_Type;
1149 Node : out Node_Access)
1151 function New_Node return Node_Access;
1152 pragma Inline (New_Node);
1154 procedure Insert_Post is
1155 new Element_Keys.Generic_Insert_Post (New_Node);
1157 procedure Unconditional_Insert is
1158 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1164 function New_Node return Node_Access is
1165 -- The element allocator may need an accessibility check in the case
1166 -- the actual type is class-wide or has access discriminants (see
1167 -- RM 4.8(10.1) and AI12-0035).
1169 pragma Unsuppress (Accessibility_Check);
1171 Element : Element_Access := new Element_Type'(New_Item
);
1174 return new Node_Type
'(Parent => null,
1177 Color => Red_Black_Trees.Red,
1178 Element => Element);
1182 Free_Element (Element);
1186 -- Start of processing for Insert_Sans_Hint
1189 Unconditional_Insert (Tree, New_Item, Node);
1190 end Insert_Sans_Hint;
1192 ----------------------
1193 -- Insert_With_Hint --
1194 ----------------------
1196 procedure Insert_With_Hint
1197 (Dst_Tree : in out Tree_Type;
1198 Dst_Hint : Node_Access;
1199 Src_Node : Node_Access;
1200 Dst_Node : out Node_Access)
1202 function New_Node return Node_Access;
1203 pragma Inline (New_Node);
1205 procedure Insert_Post is
1206 new Element_Keys.Generic_Insert_Post (New_Node);
1208 procedure Insert_Sans_Hint is
1209 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1211 procedure Local_Insert_With_Hint is
1212 new Element_Keys.Generic_Unconditional_Insert_With_Hint
1220 function New_Node return Node_Access is
1221 X : Element_Access := new Element_Type'(Src_Node
.Element
.all);
1224 return new Node_Type
'(Parent => null,
1236 -- Start of processing for Insert_With_Hint
1239 Local_Insert_With_Hint
1242 Src_Node.Element.all,
1244 end Insert_With_Hint;
1250 procedure Intersection (Target : in out Set; Source : Set) is
1252 Set_Ops.Intersection (Target.Tree, Source.Tree);
1255 function Intersection (Left, Right : Set) return Set is
1256 Tree : constant Tree_Type :=
1257 Set_Ops.Intersection (Left.Tree, Right.Tree);
1259 return Set'(Controlled
with Tree
);
1266 function Is_Empty
(Container
: Set
) return Boolean is
1268 return Container
.Tree
.Length
= 0;
1271 ------------------------
1272 -- Is_Equal_Node_Node --
1273 ------------------------
1275 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean is
1277 return L
.Element
.all = R
.Element
.all;
1278 end Is_Equal_Node_Node
;
1280 -----------------------------
1281 -- Is_Greater_Element_Node --
1282 -----------------------------
1284 function Is_Greater_Element_Node
1285 (Left
: Element_Type
;
1286 Right
: Node_Access
) return Boolean
1289 -- e > node same as node < e
1291 return Right
.Element
.all < Left
;
1292 end Is_Greater_Element_Node
;
1294 --------------------------
1295 -- Is_Less_Element_Node --
1296 --------------------------
1298 function Is_Less_Element_Node
1299 (Left
: Element_Type
;
1300 Right
: Node_Access
) return Boolean
1303 return Left
< Right
.Element
.all;
1304 end Is_Less_Element_Node
;
1306 -----------------------
1307 -- Is_Less_Node_Node --
1308 -----------------------
1310 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean is
1312 return L
.Element
.all < R
.Element
.all;
1313 end Is_Less_Node_Node
;
1319 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean is
1321 return Set_Ops
.Is_Subset
(Subset
=> Subset
.Tree
, Of_Set
=> Of_Set
.Tree
);
1330 Item
: Element_Type
;
1331 Process
: not null access procedure (Position
: Cursor
))
1333 procedure Process_Node
(Node
: Node_Access
);
1334 pragma Inline
(Process_Node
);
1336 procedure Local_Iterate
is
1337 new Element_Keys
.Generic_Iteration
(Process_Node
);
1343 procedure Process_Node
(Node
: Node_Access
) is
1345 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1348 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1349 B : Natural renames T.Busy;
1351 -- Start of processing for Iterate
1357 Local_Iterate (T, Item);
1369 Process : not null access procedure (Position : Cursor))
1371 procedure Process_Node (Node : Node_Access);
1372 pragma Inline (Process_Node);
1374 procedure Local_Iterate is
1375 new Tree_Operations.Generic_Iteration (Process_Node);
1381 procedure Process_Node (Node : Node_Access) is
1383 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1386 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
1387 B
: Natural renames T
.Busy
;
1389 -- Start of processing for Iterate
1405 function Iterate
(Container
: Set
)
1406 return Set_Iterator_Interfaces
.Reversible_Iterator
'Class
1408 S
: constant Set_Access
:= Container
'Unrestricted_Access;
1409 B
: Natural renames S
.Tree
.Busy
;
1412 -- The value of the Node component influences the behavior of the First
1413 -- and Last selector functions of the iterator object. When the Node
1414 -- component is null (as is the case here), this means the iterator
1415 -- object was constructed without a start expression. This is a complete
1416 -- iterator, meaning that the iteration starts from the (logical)
1417 -- beginning of the sequence of items.
1419 -- Note: For a forward iterator, Container.First is the beginning, and
1420 -- for a reverse iterator, Container.Last is the beginning.
1422 return It
: constant Iterator
:= (Limited_Controlled
with S
, null) do
1427 function Iterate
(Container
: Set
; Start
: Cursor
)
1428 return Set_Iterator_Interfaces
.Reversible_Iterator
'Class
1430 S
: constant Set_Access
:= Container
'Unrestricted_Access;
1431 B
: Natural renames S
.Tree
.Busy
;
1434 -- It was formerly the case that when Start = No_Element, the partial
1435 -- iterator was defined to behave the same as for a complete iterator,
1436 -- and iterate over the entire sequence of items. However, those
1437 -- semantics were unintuitive and arguably error-prone (it is too easy
1438 -- to accidentally create an endless loop), and so they were changed,
1439 -- per the ARG meeting in Denver on 2011/11. However, there was no
1440 -- consensus about what positive meaning this corner case should have,
1441 -- and so it was decided to simply raise an exception. This does imply,
1442 -- however, that it is not possible to use a partial iterator to specify
1443 -- an empty sequence of items.
1445 if Start
= No_Element
then
1446 raise Constraint_Error
with
1447 "Start position for iterator equals No_Element";
1450 if Start
.Container
/= Container
'Unrestricted_Access then
1451 raise Program_Error
with
1452 "Start cursor of Iterate designates wrong set";
1455 pragma Assert
(Vet
(Container
.Tree
, Start
.Node
),
1456 "Start cursor of Iterate is bad");
1458 -- The value of the Node component influences the behavior of the First
1459 -- and Last selector functions of the iterator object. When the Node
1460 -- component is non-null (as is the case here), it means that this is a
1461 -- partial iteration, over a subset of the complete sequence of
1462 -- items. The iterator object was constructed with a start expression,
1463 -- indicating the position from which the iteration begins. Note that
1464 -- the start position has the same value irrespective of whether this is
1465 -- a forward or reverse iteration.
1467 return It
: constant Iterator
:=
1468 (Limited_Controlled
with S
, Start
.Node
)
1478 function Last
(Container
: Set
) return Cursor
is
1480 if Container
.Tree
.Last
= null then
1484 return Cursor
'(Container'Unrestricted_Access, Container.Tree.Last);
1487 function Last (Object : Iterator) return Cursor is
1489 -- The value of the iterator object's Node component influences the
1490 -- behavior of the Last (and First) selector function.
1492 -- When the Node component is null, this means the iterator object was
1493 -- constructed without a start expression, in which case the (reverse)
1494 -- iteration starts from the (logical) beginning of the entire sequence
1495 -- (corresponding to Container.Last, for a reverse iterator).
1497 -- Otherwise, this is iteration over a partial sequence of items. When
1498 -- the Node component is non-null, the iterator object was constructed
1499 -- with a start expression, that specifies the position from which the
1500 -- (reverse) partial iteration begins.
1502 if Object.Node = null then
1503 return Object.Container.Last;
1505 return Cursor'(Object
.Container
, Object
.Node
);
1513 function Last_Element
(Container
: Set
) return Element_Type
is
1515 if Container
.Tree
.Last
= null then
1516 raise Constraint_Error
with "set is empty";
1519 pragma Assert
(Container
.Tree
.Last
.Element
/= null);
1520 return Container
.Tree
.Last
.Element
.all;
1527 function Left
(Node
: Node_Access
) return Node_Access
is
1536 function Length
(Container
: Set
) return Count_Type
is
1538 return Container
.Tree
.Length
;
1546 new Tree_Operations
.Generic_Move
(Clear
);
1548 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
1550 Move
(Target
=> Target
.Tree
, Source
=> Source
.Tree
);
1557 function Next
(Position
: Cursor
) return Cursor
is
1559 if Position
= No_Element
then
1563 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1564 "bad cursor in Next");
1567 Node
: constant Node_Access
:=
1568 Tree_Operations
.Next
(Position
.Node
);
1575 return Cursor
'(Position.Container, Node);
1579 procedure Next (Position : in out Cursor) is
1581 Position := Next (Position);
1584 function Next (Object : Iterator; Position : Cursor) return Cursor is
1586 if Position.Container = null then
1590 if Position.Container /= Object.Container then
1591 raise Program_Error with
1592 "Position cursor of Next designates wrong set";
1595 return Next (Position);
1602 function Overlap (Left, Right : Set) return Boolean is
1604 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1611 function Parent (Node : Node_Access) return Node_Access is
1620 function Previous (Position : Cursor) return Cursor is
1622 if Position = No_Element then
1626 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1627 "bad cursor in Previous");
1630 Node : constant Node_Access :=
1631 Tree_Operations.Previous (Position.Node);
1638 return Cursor'(Position
.Container
, Node
);
1642 procedure Previous
(Position
: in out Cursor
) is
1644 Position
:= Previous
(Position
);
1647 function Previous
(Object
: Iterator
; Position
: Cursor
) return Cursor
is
1649 if Position
.Container
= null then
1653 if Position
.Container
/= Object
.Container
then
1654 raise Program_Error
with
1655 "Position cursor of Previous designates wrong set";
1658 return Previous
(Position
);
1665 procedure Query_Element
1667 Process
: not null access procedure (Element
: Element_Type
))
1670 if Position
.Node
= null then
1671 raise Constraint_Error
with "Position cursor equals No_Element";
1674 if Position
.Node
.Element
= null then
1675 raise Program_Error
with "Position cursor is bad";
1678 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1679 "bad cursor in Query_Element");
1682 T
: Tree_Type
renames Position
.Container
.Tree
;
1684 B
: Natural renames T
.Busy
;
1685 L
: Natural renames T
.Lock
;
1692 Process
(Position
.Node
.Element
.all);
1710 (Stream
: not null access Root_Stream_Type
'Class;
1711 Container
: out Set
)
1714 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
;
1715 pragma Inline
(Read_Node
);
1718 new Tree_Operations
.Generic_Read
(Clear
, Read_Node
);
1725 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
1727 Node
: Node_Access
:= new Node_Type
;
1729 Node
.Element
:= new Element_Type
'(Element_Type'Input (Stream));
1733 Free (Node); -- Note that Free deallocates elem too
1737 -- Start of processing for Read
1740 Read (Stream, Container.Tree);
1744 (Stream : not null access Root_Stream_Type'Class;
1748 raise Program_Error with "attempt to stream set cursor";
1751 ---------------------
1752 -- Replace_Element --
1753 ---------------------
1755 procedure Replace_Element
1756 (Tree : in out Tree_Type;
1758 Item : Element_Type)
1761 if Item < Node.Element.all
1762 or else Node.Element.all < Item
1766 if Tree.Lock > 0 then
1767 raise Program_Error with
1768 "attempt to tamper with elements (set is locked)";
1772 X : Element_Access := Node.Element;
1774 -- The element allocator may need an accessibility check in the
1775 -- case the actual type is class-wide or has access discriminants
1776 -- (see RM 4.8(10.1) and AI12-0035).
1778 pragma Unsuppress (Accessibility_Check);
1781 Node.Element := new Element_Type'(Item
);
1788 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, Node
); -- Checks busy-bit
1790 Insert_New_Item
: declare
1791 function New_Node
return Node_Access
;
1792 pragma Inline
(New_Node
);
1794 procedure Insert_Post
is
1795 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1797 procedure Unconditional_Insert
is
1798 new Element_Keys
.Generic_Unconditional_Insert
(Insert_Post
);
1804 function New_Node
return Node_Access
is
1806 -- The element allocator may need an accessibility check in the
1807 -- case the actual type is class-wide or has access discriminants
1808 -- (see RM 4.8(10.1) and AI12-0035).
1810 pragma Unsuppress
(Accessibility_Check
);
1813 Node
.Element
:= new Element_Type
'(Item); -- OK if fails
1814 Node.Color := Red_Black_Trees.Red;
1815 Node.Parent := null;
1822 Result : Node_Access;
1824 X : Element_Access := Node.Element;
1826 -- Start of processing for Insert_New_Item
1829 Unconditional_Insert
1833 pragma Assert (Result = Node);
1835 Free_Element (X); -- OK if fails
1836 end Insert_New_Item;
1837 end Replace_Element;
1839 procedure Replace_Element
1840 (Container : in out Set;
1842 New_Item : Element_Type)
1845 if Position.Node = null then
1846 raise Constraint_Error with "Position cursor equals No_Element";
1849 if Position.Node.Element = null then
1850 raise Program_Error with "Position cursor is bad";
1853 if Position.Container /= Container'Unrestricted_Access then
1854 raise Program_Error with "Position cursor designates wrong set";
1857 pragma Assert (Vet (Container.Tree, Position.Node),
1858 "bad cursor in Replace_Element");
1860 Replace_Element (Container.Tree, Position.Node, New_Item);
1861 end Replace_Element;
1863 ---------------------
1864 -- Reverse_Iterate --
1865 ---------------------
1867 procedure Reverse_Iterate
1869 Item : Element_Type;
1870 Process : not null access procedure (Position : Cursor))
1872 procedure Process_Node (Node : Node_Access);
1873 pragma Inline (Process_Node);
1875 procedure Local_Reverse_Iterate is
1876 new Element_Keys.Generic_Reverse_Iteration (Process_Node);
1882 procedure Process_Node (Node : Node_Access) is
1884 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1887 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
1888 B
: Natural renames T
.Busy
;
1890 -- Start of processing for Reverse_Iterate
1896 Local_Reverse_Iterate
(T
, Item
);
1904 end Reverse_Iterate
;
1906 procedure Reverse_Iterate
1908 Process
: not null access procedure (Position
: Cursor
))
1910 procedure Process_Node
(Node
: Node_Access
);
1911 pragma Inline
(Process_Node
);
1913 procedure Local_Reverse_Iterate
is
1914 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1920 procedure Process_Node
(Node
: Node_Access
) is
1922 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1925 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1926 B : Natural renames T.Busy;
1928 -- Start of processing for Reverse_Iterate
1934 Local_Reverse_Iterate (T);
1942 end Reverse_Iterate;
1948 function Right (Node : Node_Access) return Node_Access is
1957 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1959 Node.Color := Color;
1966 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1975 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1977 Node.Parent := Parent;
1984 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1986 Node.Right := Right;
1989 --------------------------
1990 -- Symmetric_Difference --
1991 --------------------------
1993 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1995 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1996 end Symmetric_Difference;
1998 function Symmetric_Difference (Left, Right : Set) return Set is
1999 Tree : constant Tree_Type :=
2000 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
2002 return Set'(Controlled
with Tree
);
2003 end Symmetric_Difference
;
2009 function To_Set
(New_Item
: Element_Type
) return Set
is
2012 pragma Unreferenced
(Node
);
2014 Insert_Sans_Hint
(Tree
, New_Item
, Node
);
2015 return Set
'(Controlled with Tree);
2022 procedure Union (Target : in out Set; Source : Set) is
2024 Set_Ops.Union (Target.Tree, Source.Tree);
2027 function Union (Left, Right : Set) return Set is
2028 Tree : constant Tree_Type :=
2029 Set_Ops.Union (Left.Tree, Right.Tree);
2031 return Set'(Controlled
with Tree
);
2039 (Stream
: not null access Root_Stream_Type
'Class;
2042 procedure Write_Node
2043 (Stream
: not null access Root_Stream_Type
'Class;
2044 Node
: Node_Access
);
2045 pragma Inline
(Write_Node
);
2048 new Tree_Operations
.Generic_Write
(Write_Node
);
2054 procedure Write_Node
2055 (Stream
: not null access Root_Stream_Type
'Class;
2059 Element_Type
'Output (Stream
, Node
.Element
.all);
2062 -- Start of processing for Write
2065 Write
(Stream
, Container
.Tree
);
2069 (Stream
: not null access Root_Stream_Type
'Class;
2073 raise Program_Error
with "attempt to stream set cursor";
2076 end Ada
.Containers
.Indefinite_Ordered_Multisets
;