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-2015, 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 pragma Annotate
(CodePeer
, Skip_Analysis
);
47 -----------------------------
48 -- Node Access Subprograms --
49 -----------------------------
51 -- These subprograms provide a functional interface to access fields
52 -- of a node, and a procedural interface for modifying these values.
54 function Color
(Node
: Node_Access
) return Color_Type
;
55 pragma Inline
(Color
);
57 function Left
(Node
: Node_Access
) return Node_Access
;
60 function Parent
(Node
: Node_Access
) return Node_Access
;
61 pragma Inline
(Parent
);
63 function Right
(Node
: Node_Access
) return Node_Access
;
64 pragma Inline
(Right
);
66 procedure Set_Parent
(Node
: Node_Access
; Parent
: Node_Access
);
67 pragma Inline
(Set_Parent
);
69 procedure Set_Left
(Node
: Node_Access
; Left
: Node_Access
);
70 pragma Inline
(Set_Left
);
72 procedure Set_Right
(Node
: Node_Access
; Right
: Node_Access
);
73 pragma Inline
(Set_Right
);
75 procedure Set_Color
(Node
: Node_Access
; Color
: Color_Type
);
76 pragma Inline
(Set_Color
);
78 -----------------------
79 -- Local Subprograms --
80 -----------------------
82 function Copy_Node
(Source
: Node_Access
) return Node_Access
;
83 pragma Inline
(Copy_Node
);
85 procedure Free
(X
: in out Node_Access
);
87 procedure Insert_Sans_Hint
88 (Tree
: in out Tree_Type
;
89 New_Item
: Element_Type
;
90 Node
: out Node_Access
);
92 procedure Insert_With_Hint
93 (Dst_Tree
: in out Tree_Type
;
94 Dst_Hint
: Node_Access
;
95 Src_Node
: Node_Access
;
96 Dst_Node
: out Node_Access
);
98 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean;
99 pragma Inline
(Is_Equal_Node_Node
);
101 function Is_Greater_Element_Node
102 (Left
: Element_Type
;
103 Right
: Node_Access
) return Boolean;
104 pragma Inline
(Is_Greater_Element_Node
);
106 function Is_Less_Element_Node
107 (Left
: Element_Type
;
108 Right
: Node_Access
) return Boolean;
109 pragma Inline
(Is_Less_Element_Node
);
111 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean;
112 pragma Inline
(Is_Less_Node_Node
);
114 procedure Replace_Element
115 (Tree
: in out Tree_Type
;
117 Item
: Element_Type
);
119 --------------------------
120 -- Local Instantiations --
121 --------------------------
123 package Tree_Operations
is
124 new Red_Black_Trees
.Generic_Operations
(Tree_Types
);
126 procedure Delete_Tree
is
127 new Tree_Operations
.Generic_Delete_Tree
(Free
);
129 function Copy_Tree
is
130 new Tree_Operations
.Generic_Copy_Tree
(Copy_Node
, Delete_Tree
);
135 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
137 package Element_Keys
is
138 new Red_Black_Trees
.Generic_Keys
139 (Tree_Operations
=> Tree_Operations
,
140 Key_Type
=> Element_Type
,
141 Is_Less_Key_Node
=> Is_Less_Element_Node
,
142 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
145 new Generic_Set_Operations
146 (Tree_Operations
=> Tree_Operations
,
147 Insert_With_Hint
=> Insert_With_Hint
,
148 Copy_Tree
=> Copy_Tree
,
149 Delete_Tree
=> Delete_Tree
,
150 Is_Less
=> Is_Less_Node_Node
,
157 function "<" (Left
, Right
: Cursor
) return Boolean is
159 if Left
.Node
= null then
160 raise Constraint_Error
with "Left cursor equals No_Element";
163 if Right
.Node
= null then
164 raise Constraint_Error
with "Right cursor equals No_Element";
167 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
168 "bad Left cursor in ""<""");
170 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
171 "bad Right cursor in ""<""");
173 return Left
.Node
.Element
< Right
.Node
.Element
;
176 function "<" (Left
: Cursor
; Right
: Element_Type
)
179 if Left
.Node
= null then
180 raise Constraint_Error
with "Left cursor equals No_Element";
183 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
184 "bad Left cursor in ""<""");
186 return Left
.Node
.Element
< Right
;
189 function "<" (Left
: Element_Type
; Right
: Cursor
)
192 if Right
.Node
= null then
193 raise Constraint_Error
with "Right cursor equals No_Element";
196 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
197 "bad Right cursor in ""<""");
199 return Left
< Right
.Node
.Element
;
206 function "=" (Left
, Right
: Set
) return Boolean is
208 return Is_Equal
(Left
.Tree
, Right
.Tree
);
215 function ">" (Left
, Right
: Cursor
) return Boolean is
217 if Left
.Node
= null then
218 raise Constraint_Error
with "Left cursor equals No_Element";
221 if Right
.Node
= null then
222 raise Constraint_Error
with "Right cursor equals No_Element";
225 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
226 "bad Left cursor in "">""");
228 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
229 "bad Right cursor in "">""");
231 -- L > R same as R < L
233 return Right
.Node
.Element
< Left
.Node
.Element
;
236 function ">" (Left
: Cursor
; Right
: Element_Type
)
239 if Left
.Node
= null then
240 raise Constraint_Error
with "Left cursor equals No_Element";
243 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
244 "bad Left cursor in "">""");
246 return Right
< Left
.Node
.Element
;
249 function ">" (Left
: Element_Type
; Right
: Cursor
)
252 if Right
.Node
= null then
253 raise Constraint_Error
with "Right cursor equals No_Element";
256 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
257 "bad Right cursor in "">""");
259 return Right
.Node
.Element
< Left
;
266 procedure Adjust
is new Tree_Operations
.Generic_Adjust
(Copy_Tree
);
268 procedure Adjust
(Container
: in out Set
) is
270 Adjust
(Container
.Tree
);
277 procedure Assign
(Target
: in out Set
; Source
: Set
) is
279 if Target
'Address = Source
'Address then
284 Target
.Union
(Source
);
291 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
292 Node
: constant Node_Access
:=
293 Element_Keys
.Ceiling
(Container
.Tree
, Item
);
300 return Cursor
'(Container'Unrestricted_Access, Node);
308 new Tree_Operations.Generic_Clear (Delete_Tree);
310 procedure Clear (Container : in out Set) is
312 Clear (Container.Tree);
319 function Color (Node : Node_Access) return Color_Type is
324 ------------------------
325 -- Constant_Reference --
326 ------------------------
328 function Constant_Reference
329 (Container : aliased Set;
330 Position : Cursor) return Constant_Reference_Type
333 if Position.Container = null then
334 raise Constraint_Error with "Position cursor has no element";
337 if Position.Container /= Container'Unrestricted_Access then
338 raise Program_Error with
339 "Position cursor designates wrong container";
342 pragma Assert (Vet (Position.Container.Tree, Position.Node),
343 "bad cursor in Constant_Reference");
345 -- Note: in predefined container units, the creation of a reference
346 -- increments the busy bit of the container, and its finalization
347 -- decrements it. In the absence of control machinery, this tampering
348 -- protection is missing.
351 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
352 pragma Unreferenced (T);
354 return R : constant Constant_Reference_Type :=
355 (Element => Position.Node.Element'Unrestricted_Access,
356 Control => (Container => Container'Unrestricted_Access))
361 end Constant_Reference;
367 function Contains (Container : Set; Item : Element_Type) return Boolean is
369 return Find (Container, Item) /= No_Element;
376 function Copy (Source : Set) return Set is
378 return Target : Set do
379 Target.Assign (Source);
387 function Copy_Node (Source : Node_Access) return Node_Access is
388 Target : constant Node_Access :=
389 new Node_Type'(Parent
=> null,
392 Color
=> Source
.Color
,
393 Element
=> Source
.Element
);
402 procedure Delete
(Container
: in out Set
; Item
: Element_Type
) is
403 Tree
: Tree_Type
renames Container
.Tree
;
404 Node
: Node_Access
:= Element_Keys
.Ceiling
(Tree
, Item
);
405 Done
: constant Node_Access
:= Element_Keys
.Upper_Bound
(Tree
, Item
);
410 raise Constraint_Error
with
411 "attempt to delete element not in set";
416 Node
:= Tree_Operations
.Next
(Node
);
417 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
420 exit when Node
= Done
;
424 procedure Delete
(Container
: in out Set
; Position
: in out Cursor
) is
426 if Position
.Node
= null then
427 raise Constraint_Error
with "Position cursor equals No_Element";
430 if Position
.Container
/= Container
'Unrestricted_Access then
431 raise Program_Error
with "Position cursor designates wrong set";
434 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
435 "bad cursor in Delete");
437 Delete_Node_Sans_Free
(Container
.Tree
, Position
.Node
);
438 Free
(Position
.Node
);
440 Position
.Container
:= null;
447 procedure Delete_First
(Container
: in out Set
) is
448 Tree
: Tree_Type
renames Container
.Tree
;
449 X
: Node_Access
:= Tree
.First
;
456 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
464 procedure Delete_Last
(Container
: in out Set
) is
465 Tree
: Tree_Type
renames Container
.Tree
;
466 X
: Node_Access
:= Tree
.Last
;
473 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
481 procedure Difference
(Target
: in out Set
; Source
: Set
) is
483 Set_Ops
.Difference
(Target
.Tree
, Source
.Tree
);
486 function Difference
(Left
, Right
: Set
) return Set
is
487 Tree
: constant Tree_Type
:=
488 Set_Ops
.Difference
(Left
.Tree
, Right
.Tree
);
490 return Set
'(Controlled with Tree);
497 function Element (Position : Cursor) return Element_Type is
499 if Position.Node = null then
500 raise Constraint_Error with "Position cursor equals No_Element";
503 pragma Assert (Vet (Position.Container.Tree, Position.Node),
504 "bad cursor in Element");
506 return Position.Node.Element;
509 -------------------------
510 -- Equivalent_Elements --
511 -------------------------
513 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
522 end Equivalent_Elements;
524 ---------------------
525 -- Equivalent_Sets --
526 ---------------------
528 function Equivalent_Sets (Left, Right : Set) return Boolean is
530 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
531 pragma Inline (Is_Equivalent_Node_Node);
533 function Is_Equivalent is
534 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
536 -----------------------------
537 -- Is_Equivalent_Node_Node --
538 -----------------------------
540 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
542 if L.Element < R.Element then
544 elsif R.Element < L.Element then
549 end Is_Equivalent_Node_Node;
551 -- Start of processing for Equivalent_Sets
554 return Is_Equivalent (Left.Tree, Right.Tree);
561 procedure Exclude (Container : in out Set; Item : Element_Type) is
562 Tree : Tree_Type renames Container.Tree;
563 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
564 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
567 while Node /= Done loop
569 Node := Tree_Operations.Next (Node);
570 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
579 procedure Finalize (Object : in out Iterator) is
580 B : Natural renames Object.Container.Tree.Busy;
581 pragma Assert (B > 0);
590 function Find (Container : Set; Item : Element_Type) return Cursor is
591 Node : constant Node_Access :=
592 Element_Keys.Find (Container.Tree, Item);
599 return Cursor'(Container
'Unrestricted_Access, Node
);
606 function First
(Container
: Set
) return Cursor
is
608 if Container
.Tree
.First
= null then
612 return Cursor
'(Container'Unrestricted_Access, Container.Tree.First);
615 function First (Object : Iterator) return Cursor is
617 -- The value of the iterator object's Node component influences the
618 -- behavior of the First (and Last) selector function.
620 -- When the Node component is null, this means the iterator object was
621 -- constructed without a start expression, in which case the (forward)
622 -- iteration starts from the (logical) beginning of the entire sequence
623 -- of items (corresponding to Container.First, for a forward iterator).
625 -- Otherwise, this is iteration over a partial sequence of items. When
626 -- the Node component is non-null, the iterator object was constructed
627 -- with a start expression, that specifies the position from which the
628 -- (forward) partial iteration begins.
630 if Object.Node = null then
631 return Object.Container.First;
633 return Cursor'(Object
.Container
, Object
.Node
);
641 function First_Element
(Container
: Set
) return Element_Type
is
643 if Container
.Tree
.First
= null then
644 raise Constraint_Error
with "set is empty";
647 return Container
.Tree
.First
.Element
;
654 function Floor
(Container
: Set
; Item
: Element_Type
) return Cursor
is
655 Node
: constant Node_Access
:=
656 Element_Keys
.Floor
(Container
.Tree
, Item
);
663 return Cursor
'(Container'Unrestricted_Access, Node);
670 procedure Free (X : in out Node_Access) is
671 procedure Deallocate is
672 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
688 package body Generic_Keys is
690 -----------------------
691 -- Local Subprograms --
692 -----------------------
694 function Is_Greater_Key_Node
696 Right : Node_Access) return Boolean;
697 pragma Inline (Is_Greater_Key_Node);
699 function Is_Less_Key_Node
701 Right : Node_Access) return Boolean;
702 pragma Inline (Is_Less_Key_Node);
704 --------------------------
705 -- Local_Instantiations --
706 --------------------------
709 new Red_Black_Trees.Generic_Keys
710 (Tree_Operations => Tree_Operations,
711 Key_Type => Key_Type,
712 Is_Less_Key_Node => Is_Less_Key_Node,
713 Is_Greater_Key_Node => Is_Greater_Key_Node);
719 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
720 Node : constant Node_Access :=
721 Key_Keys.Ceiling (Container.Tree, Key);
728 return Cursor'(Container
'Unrestricted_Access, Node
);
735 function Contains
(Container
: Set
; Key
: Key_Type
) return Boolean is
737 return Find
(Container
, Key
) /= No_Element
;
744 procedure Delete
(Container
: in out Set
; Key
: Key_Type
) is
745 Tree
: Tree_Type
renames Container
.Tree
;
746 Node
: Node_Access
:= Key_Keys
.Ceiling
(Tree
, Key
);
747 Done
: constant Node_Access
:= Key_Keys
.Upper_Bound
(Tree
, Key
);
752 raise Constraint_Error
with "attempt to delete key not in set";
757 Node
:= Tree_Operations
.Next
(Node
);
758 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
761 exit when Node
= Done
;
769 function Element
(Container
: Set
; Key
: Key_Type
) return Element_Type
is
770 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
773 raise Constraint_Error
with "key not in set";
779 ---------------------
780 -- Equivalent_Keys --
781 ---------------------
783 function Equivalent_Keys
(Left
, Right
: Key_Type
) return Boolean is
798 procedure Exclude
(Container
: in out Set
; Key
: Key_Type
) is
799 Tree
: Tree_Type
renames Container
.Tree
;
800 Node
: Node_Access
:= Key_Keys
.Ceiling
(Tree
, Key
);
801 Done
: constant Node_Access
:= Key_Keys
.Upper_Bound
(Tree
, Key
);
805 while Node
/= Done
loop
807 Node
:= Tree_Operations
.Next
(Node
);
808 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
817 function Find
(Container
: Set
; Key
: Key_Type
) return Cursor
is
818 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
825 return Cursor
'(Container'Unrestricted_Access, Node);
832 function Floor (Container : Set; Key : Key_Type) return Cursor is
833 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
840 return Cursor'(Container
'Unrestricted_Access, Node
);
843 -------------------------
844 -- Is_Greater_Key_Node --
845 -------------------------
847 function Is_Greater_Key_Node
849 Right
: Node_Access
) return Boolean is
851 return Key
(Right
.Element
) < Left
;
852 end Is_Greater_Key_Node
;
854 ----------------------
855 -- Is_Less_Key_Node --
856 ----------------------
858 function Is_Less_Key_Node
860 Right
: Node_Access
) return Boolean is
862 return Left
< Key
(Right
.Element
);
863 end Is_Less_Key_Node
;
872 Process
: not null access procedure (Position
: Cursor
))
874 procedure Process_Node
(Node
: Node_Access
);
875 pragma Inline
(Process_Node
);
877 procedure Local_Iterate
is
878 new Key_Keys
.Generic_Iteration
(Process_Node
);
884 procedure Process_Node
(Node
: Node_Access
) is
886 Process
(Cursor
'(Container'Unrestricted_Access, Node));
889 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
890 B : Natural renames T.Busy;
892 -- Start of processing for Iterate
898 Local_Iterate (T, Key);
912 function Key (Position : Cursor) return Key_Type is
914 if Position.Node = null then
915 raise Constraint_Error with
916 "Position cursor equals No_Element";
919 pragma Assert (Vet (Position.Container.Tree, Position.Node),
920 "bad cursor in Key");
922 return Key (Position.Node.Element);
925 ---------------------
926 -- Reverse_Iterate --
927 ---------------------
929 procedure Reverse_Iterate
932 Process : not null access procedure (Position : Cursor))
934 procedure Process_Node (Node : Node_Access);
935 pragma Inline (Process_Node);
937 procedure Local_Reverse_Iterate is
938 new Key_Keys.Generic_Reverse_Iteration (Process_Node);
944 procedure Process_Node (Node : Node_Access) is
946 Process (Cursor'(Container
'Unrestricted_Access, Node
));
949 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
950 B
: Natural renames T
.Busy
;
952 -- Start of processing for Reverse_Iterate
958 Local_Reverse_Iterate
(T
, Key
);
972 procedure Update_Element
973 (Container
: in out Set
;
975 Process
: not null access procedure (Element
: in out Element_Type
))
977 Tree
: Tree_Type
renames Container
.Tree
;
978 Node
: constant Node_Access
:= Position
.Node
;
982 raise Constraint_Error
with
983 "Position cursor equals No_Element";
986 if Position
.Container
/= Container
'Unrestricted_Access then
987 raise Program_Error
with
988 "Position cursor designates wrong set";
991 pragma Assert
(Vet
(Tree
, Node
),
992 "bad cursor in Update_Element");
995 E
: Element_Type
renames Node
.Element
;
996 K
: constant Key_Type
:= Key
(E
);
998 B
: Natural renames Tree
.Busy
;
999 L
: Natural renames Tree
.Lock
;
1017 if Equivalent_Keys
(Left
=> K
, Right
=> Key
(E
)) then
1022 -- Delete_Node checks busy-bit
1024 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, Node
);
1026 Insert_New_Item
: declare
1027 function New_Node
return Node_Access
;
1028 pragma Inline
(New_Node
);
1030 procedure Insert_Post
is
1031 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1033 procedure Unconditional_Insert
is
1034 new Element_Keys
.Generic_Unconditional_Insert
(Insert_Post
);
1040 function New_Node
return Node_Access
is
1042 Node
.Color
:= Red_Black_Trees
.Red
;
1043 Node
.Parent
:= null;
1050 Result
: Node_Access
;
1052 -- Start of processing for Insert_New_Item
1055 Unconditional_Insert
1057 Key
=> Node
.Element
,
1060 pragma Assert
(Result
= Node
);
1061 end Insert_New_Item
;
1070 function Has_Element
(Position
: Cursor
) return Boolean is
1072 return Position
/= No_Element
;
1079 procedure Insert
(Container
: in out Set
; New_Item
: Element_Type
) is
1081 pragma Unreferenced
(Position
);
1083 Insert
(Container
, New_Item
, Position
);
1087 (Container
: in out Set
;
1088 New_Item
: Element_Type
;
1089 Position
: out Cursor
)
1092 Insert_Sans_Hint
(Container
.Tree
, New_Item
, Position
.Node
);
1093 Position
.Container
:= Container
'Unrestricted_Access;
1096 ----------------------
1097 -- Insert_Sans_Hint --
1098 ----------------------
1100 procedure Insert_Sans_Hint
1101 (Tree
: in out Tree_Type
;
1102 New_Item
: Element_Type
;
1103 Node
: out Node_Access
)
1105 function New_Node
return Node_Access
;
1106 pragma Inline
(New_Node
);
1108 procedure Insert_Post
is
1109 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1111 procedure Unconditional_Insert
is
1112 new Element_Keys
.Generic_Unconditional_Insert
(Insert_Post
);
1118 function New_Node
return Node_Access
is
1119 Node
: constant Node_Access
:=
1120 new Node_Type
'(Parent => null,
1123 Color => Red_Black_Trees.Red,
1124 Element => New_Item);
1129 -- Start of processing for Insert_Sans_Hint
1132 Unconditional_Insert (Tree, New_Item, Node);
1133 end Insert_Sans_Hint;
1135 ----------------------
1136 -- Insert_With_Hint --
1137 ----------------------
1139 procedure Insert_With_Hint
1140 (Dst_Tree : in out Tree_Type;
1141 Dst_Hint : Node_Access;
1142 Src_Node : Node_Access;
1143 Dst_Node : out Node_Access)
1145 function New_Node return Node_Access;
1146 pragma Inline (New_Node);
1148 procedure Insert_Post is
1149 new Element_Keys.Generic_Insert_Post (New_Node);
1151 procedure Insert_Sans_Hint is
1152 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1154 procedure Local_Insert_With_Hint is
1155 new Element_Keys.Generic_Unconditional_Insert_With_Hint
1163 function New_Node return Node_Access is
1164 Node : constant Node_Access :=
1165 new Node_Type'(Parent
=> null,
1169 Element
=> Src_Node
.Element
);
1174 -- Start of processing for Insert_With_Hint
1177 Local_Insert_With_Hint
1182 end Insert_With_Hint
;
1188 procedure Intersection
(Target
: in out Set
; Source
: Set
) is
1190 Set_Ops
.Intersection
(Target
.Tree
, Source
.Tree
);
1193 function Intersection
(Left
, Right
: Set
) return Set
is
1194 Tree
: constant Tree_Type
:=
1195 Set_Ops
.Intersection
(Left
.Tree
, Right
.Tree
);
1197 return Set
'(Controlled with Tree);
1204 function Is_Empty (Container : Set) return Boolean is
1206 return Container.Tree.Length = 0;
1209 ------------------------
1210 -- Is_Equal_Node_Node --
1211 ------------------------
1213 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1215 return L.Element = R.Element;
1216 end Is_Equal_Node_Node;
1218 -----------------------------
1219 -- Is_Greater_Element_Node --
1220 -----------------------------
1222 function Is_Greater_Element_Node
1223 (Left : Element_Type;
1224 Right : Node_Access) return Boolean
1227 -- e > node same as node < e
1229 return Right.Element < Left;
1230 end Is_Greater_Element_Node;
1232 --------------------------
1233 -- Is_Less_Element_Node --
1234 --------------------------
1236 function Is_Less_Element_Node
1237 (Left : Element_Type;
1238 Right : Node_Access) return Boolean
1241 return Left < Right.Element;
1242 end Is_Less_Element_Node;
1244 -----------------------
1245 -- Is_Less_Node_Node --
1246 -----------------------
1248 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1250 return L.Element < R.Element;
1251 end Is_Less_Node_Node;
1257 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1259 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1268 Process : not null access procedure (Position : Cursor))
1270 procedure Process_Node (Node : Node_Access);
1271 pragma Inline (Process_Node);
1273 procedure Local_Iterate is
1274 new Tree_Operations.Generic_Iteration (Process_Node);
1280 procedure Process_Node (Node : Node_Access) is
1282 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1285 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
1286 B
: Natural renames T
.Busy
;
1288 -- Start of processing for Iterate
1306 Item
: Element_Type
;
1307 Process
: not null access procedure (Position
: Cursor
))
1309 procedure Process_Node
(Node
: Node_Access
);
1310 pragma Inline
(Process_Node
);
1312 procedure Local_Iterate
is
1313 new Element_Keys
.Generic_Iteration
(Process_Node
);
1319 procedure Process_Node
(Node
: Node_Access
) is
1321 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1324 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1325 B : Natural renames T.Busy;
1327 -- Start of processing for Iterate
1333 Local_Iterate (T, Item);
1343 function Iterate (Container : Set)
1344 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1346 S : constant Set_Access := Container'Unrestricted_Access;
1347 B : Natural renames S.Tree.Busy;
1350 -- The value of the Node component influences the behavior of the First
1351 -- and Last selector functions of the iterator object. When the Node
1352 -- component is null (as is the case here), this means the iterator
1353 -- object was constructed without a start expression. This is a complete
1354 -- iterator, meaning that the iteration starts from the (logical)
1355 -- beginning of the sequence of items.
1357 -- Note: For a forward iterator, Container.First is the beginning, and
1358 -- for a reverse iterator, Container.Last is the beginning.
1360 return It : constant Iterator := (Limited_Controlled with S, null) do
1365 function Iterate (Container : Set; Start : Cursor)
1366 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1368 S : constant Set_Access := Container'Unrestricted_Access;
1369 B : Natural renames S.Tree.Busy;
1372 -- It was formerly the case that when Start = No_Element, the partial
1373 -- iterator was defined to behave the same as for a complete iterator,
1374 -- and iterate over the entire sequence of items. However, those
1375 -- semantics were unintuitive and arguably error-prone (it is too easy
1376 -- to accidentally create an endless loop), and so they were changed,
1377 -- per the ARG meeting in Denver on 2011/11. However, there was no
1378 -- consensus about what positive meaning this corner case should have,
1379 -- and so it was decided to simply raise an exception. This does imply,
1380 -- however, that it is not possible to use a partial iterator to specify
1381 -- an empty sequence of items.
1383 if Start = No_Element then
1384 raise Constraint_Error with
1385 "Start position for iterator equals No_Element";
1388 if Start.Container /= Container'Unrestricted_Access then
1389 raise Program_Error with
1390 "Start cursor of Iterate designates wrong set";
1393 pragma Assert (Vet (Container.Tree, Start.Node),
1394 "Start cursor of Iterate is bad");
1396 -- The value of the Node component influences the behavior of the First
1397 -- and Last selector functions of the iterator object. When the Node
1398 -- component is non-null (as is the case here), it means that this is a
1399 -- partial iteration, over a subset of the complete sequence of
1400 -- items. The iterator object was constructed with a start expression,
1401 -- indicating the position from which the iteration begins. Note that
1402 -- the start position has the same value irrespective of whether this is
1403 -- a forward or reverse iteration.
1405 return It : constant Iterator :=
1406 (Limited_Controlled with S, Start.Node)
1416 function Last (Container : Set) return Cursor is
1418 if Container.Tree.Last = null then
1422 return Cursor'(Container
'Unrestricted_Access, Container
.Tree
.Last
);
1425 function Last
(Object
: Iterator
) return Cursor
is
1427 -- The value of the iterator object's Node component influences the
1428 -- behavior of the Last (and First) selector function.
1430 -- When the Node component is null, this means the iterator object was
1431 -- constructed without a start expression, in which case the (reverse)
1432 -- iteration starts from the (logical) beginning of the entire sequence
1433 -- (corresponding to Container.Last, for a reverse iterator).
1435 -- Otherwise, this is iteration over a partial sequence of items. When
1436 -- the Node component is non-null, the iterator object was constructed
1437 -- with a start expression, that specifies the position from which the
1438 -- (reverse) partial iteration begins.
1440 if Object
.Node
= null then
1441 return Object
.Container
.Last
;
1443 return Cursor
'(Object.Container, Object.Node);
1451 function Last_Element (Container : Set) return Element_Type is
1453 if Container.Tree.Last = null then
1454 raise Constraint_Error with "set is empty";
1457 return Container.Tree.Last.Element;
1464 function Left (Node : Node_Access) return Node_Access is
1473 function Length (Container : Set) return Count_Type is
1475 return Container.Tree.Length;
1483 new Tree_Operations.Generic_Move (Clear);
1485 procedure Move (Target : in out Set; Source : in out Set) is
1487 Move (Target => Target.Tree, Source => Source.Tree);
1494 procedure Next (Position : in out Cursor)
1497 Position := Next (Position);
1500 function Next (Position : Cursor) return Cursor is
1502 if Position = No_Element then
1506 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1507 "bad cursor in Next");
1510 Node : constant Node_Access := Tree_Operations.Next (Position.Node);
1516 return Cursor'(Position
.Container
, Node
);
1520 function Next
(Object
: Iterator
; Position
: Cursor
) return Cursor
is
1522 if Position
.Container
= null then
1526 if Position
.Container
/= Object
.Container
then
1527 raise Program_Error
with
1528 "Position cursor of Next designates wrong set";
1531 return Next
(Position
);
1538 function Overlap
(Left
, Right
: Set
) return Boolean is
1540 return Set_Ops
.Overlap
(Left
.Tree
, Right
.Tree
);
1547 function Parent
(Node
: Node_Access
) return Node_Access
is
1556 procedure Previous
(Position
: in out Cursor
)
1559 Position
:= Previous
(Position
);
1562 function Previous
(Position
: Cursor
) return Cursor
is
1564 if Position
= No_Element
then
1568 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1569 "bad cursor in Previous");
1572 Node
: constant Node_Access
:=
1573 Tree_Operations
.Previous
(Position
.Node
);
1575 return (if Node
= null then No_Element
1576 else Cursor
'(Position.Container, Node));
1580 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1582 if Position.Container = null then
1586 if Position.Container /= Object.Container then
1587 raise Program_Error with
1588 "Position cursor of Previous designates wrong set";
1591 return Previous (Position);
1598 procedure Query_Element
1600 Process : not null access procedure (Element : Element_Type))
1603 if Position.Node = null then
1604 raise Constraint_Error with "Position cursor equals No_Element";
1607 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1608 "bad cursor in Query_Element");
1611 T : Tree_Type renames Position.Container.Tree;
1613 B : Natural renames T.Busy;
1614 L : Natural renames T.Lock;
1621 Process (Position.Node.Element);
1639 (Stream : not null access Root_Stream_Type'Class;
1640 Container : out Set)
1643 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1644 pragma Inline (Read_Node);
1647 new Tree_Operations.Generic_Read (Clear, Read_Node);
1654 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1656 Node : Node_Access := new Node_Type;
1658 Element_Type'Read (Stream, Node.Element);
1662 Free (Node); -- Note that Free deallocates elem too
1666 -- Start of processing for Read
1669 Read (Stream, Container.Tree);
1673 (Stream : not null access Root_Stream_Type'Class;
1677 raise Program_Error with "attempt to stream set cursor";
1681 (Stream : not null access Root_Stream_Type'Class;
1682 Item : out Constant_Reference_Type)
1685 raise Program_Error with "attempt to stream reference";
1688 ---------------------
1689 -- Replace_Element --
1690 ---------------------
1692 procedure Replace_Element
1693 (Tree : in out Tree_Type;
1695 Item : Element_Type)
1698 if Item < Node.Element
1699 or else Node.Element < Item
1703 if Tree.Lock > 0 then
1704 raise Program_Error with
1705 "attempt to tamper with elements (set is locked)";
1708 Node.Element := Item;
1712 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1714 Insert_New_Item : declare
1715 function New_Node return Node_Access;
1716 pragma Inline (New_Node);
1718 procedure Insert_Post is
1719 new Element_Keys.Generic_Insert_Post (New_Node);
1721 procedure Unconditional_Insert is
1722 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1728 function New_Node return Node_Access is
1730 Node.Element := Item;
1731 Node.Color := Red_Black_Trees.Red;
1732 Node.Parent := null;
1739 Result : Node_Access;
1741 -- Start of processing for Insert_New_Item
1744 Unconditional_Insert
1749 pragma Assert (Result = Node);
1750 end Insert_New_Item;
1751 end Replace_Element;
1753 procedure Replace_Element
1754 (Container : in out Set;
1756 New_Item : Element_Type)
1759 if Position.Node = null then
1760 raise Constraint_Error with
1761 "Position cursor equals No_Element";
1764 if Position.Container /= Container'Unrestricted_Access then
1765 raise Program_Error with
1766 "Position cursor designates wrong set";
1769 pragma Assert (Vet (Container.Tree, Position.Node),
1770 "bad cursor in Replace_Element");
1772 Replace_Element (Container.Tree, Position.Node, New_Item);
1773 end Replace_Element;
1775 ---------------------
1776 -- Reverse_Iterate --
1777 ---------------------
1779 procedure Reverse_Iterate
1781 Process : not null access procedure (Position : Cursor))
1783 procedure Process_Node (Node : Node_Access);
1784 pragma Inline (Process_Node);
1786 procedure Local_Reverse_Iterate is
1787 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1793 procedure Process_Node (Node : Node_Access) is
1795 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1798 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
1799 B
: Natural renames T
.Busy
;
1801 -- Start of processing for Reverse_Iterate
1807 Local_Reverse_Iterate
(T
);
1815 end Reverse_Iterate
;
1817 procedure Reverse_Iterate
1819 Item
: Element_Type
;
1820 Process
: not null access procedure (Position
: Cursor
))
1822 procedure Process_Node
(Node
: Node_Access
);
1823 pragma Inline
(Process_Node
);
1825 procedure Local_Reverse_Iterate
is
1826 new Element_Keys
.Generic_Reverse_Iteration
(Process_Node
);
1832 procedure Process_Node
(Node
: Node_Access
) is
1834 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1837 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1838 B : Natural renames T.Busy;
1840 -- Start of processing for Reverse_Iterate
1846 Local_Reverse_Iterate (T, Item);
1854 end Reverse_Iterate;
1860 function Right (Node : Node_Access) return Node_Access is
1869 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1871 Node.Color := Color;
1878 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1887 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1889 Node.Parent := Parent;
1896 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1898 Node.Right := Right;
1901 --------------------------
1902 -- Symmetric_Difference --
1903 --------------------------
1905 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1907 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1908 end Symmetric_Difference;
1910 function Symmetric_Difference (Left, Right : Set) return Set is
1911 Tree : constant Tree_Type :=
1912 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1914 return Set'(Controlled
with Tree
);
1915 end Symmetric_Difference
;
1921 function To_Set
(New_Item
: Element_Type
) return Set
is
1924 pragma Unreferenced
(Node
);
1926 Insert_Sans_Hint
(Tree
, New_Item
, Node
);
1927 return Set
'(Controlled with Tree);
1934 procedure Union (Target : in out Set; Source : Set) is
1936 Set_Ops.Union (Target.Tree, Source.Tree);
1939 function Union (Left, Right : Set) return Set is
1940 Tree : constant Tree_Type := Set_Ops.Union (Left.Tree, Right.Tree);
1942 return Set'(Controlled
with Tree
);
1950 (Stream
: not null access Root_Stream_Type
'Class;
1953 procedure Write_Node
1954 (Stream
: not null access Root_Stream_Type
'Class;
1955 Node
: Node_Access
);
1956 pragma Inline
(Write_Node
);
1959 new Tree_Operations
.Generic_Write
(Write_Node
);
1965 procedure Write_Node
1966 (Stream
: not null access Root_Stream_Type
'Class;
1970 Element_Type
'Write (Stream
, Node
.Element
);
1973 -- Start of processing for Write
1976 Write
(Stream
, Container
.Tree
);
1980 (Stream
: not null access Root_Stream_Type
'Class;
1984 raise Program_Error
with "attempt to stream set cursor";
1988 (Stream
: not null access Root_Stream_Type
'Class;
1989 Item
: Constant_Reference_Type
)
1992 raise Program_Error
with "attempt to stream reference";
1994 end Ada
.Containers
.Ordered_Multisets
;