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 _ S E T S --
9 -- Copyright (C) 2004-2014, 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_Sets
is
45 pragma Annotate
(CodePeer
, Skip_Analysis
);
47 ------------------------------
48 -- Access to Fields of Node --
49 ------------------------------
51 -- These subprograms provide functional notation for access to fields
52 -- of a node, and procedural notation for modifying these fields.
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_Color
(Node
: Node_Access
; Color
: Color_Type
);
67 pragma Inline
(Set_Color
);
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_Parent
(Node
: Node_Access
; Parent
: Node_Access
);
76 pragma Inline
(Set_Parent
);
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
;
91 Inserted
: out Boolean);
93 procedure Insert_With_Hint
94 (Dst_Tree
: in out Tree_Type
;
95 Dst_Hint
: Node_Access
;
96 Src_Node
: Node_Access
;
97 Dst_Node
: out Node_Access
);
99 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean;
100 pragma Inline
(Is_Equal_Node_Node
);
102 function Is_Greater_Element_Node
103 (Left
: Element_Type
;
104 Right
: Node_Access
) return Boolean;
105 pragma Inline
(Is_Greater_Element_Node
);
107 function Is_Less_Element_Node
108 (Left
: Element_Type
;
109 Right
: Node_Access
) return Boolean;
110 pragma Inline
(Is_Less_Element_Node
);
112 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean;
113 pragma Inline
(Is_Less_Node_Node
);
115 procedure Replace_Element
116 (Tree
: in out Tree_Type
;
118 Item
: Element_Type
);
120 --------------------------
121 -- Local Instantiations --
122 --------------------------
124 package Tree_Operations
is
125 new Red_Black_Trees
.Generic_Operations
(Tree_Types
);
127 procedure Delete_Tree
is
128 new Tree_Operations
.Generic_Delete_Tree
(Free
);
130 function Copy_Tree
is
131 new Tree_Operations
.Generic_Copy_Tree
(Copy_Node
, Delete_Tree
);
136 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
138 package Element_Keys
is
139 new Red_Black_Trees
.Generic_Keys
140 (Tree_Operations
=> Tree_Operations
,
141 Key_Type
=> Element_Type
,
142 Is_Less_Key_Node
=> Is_Less_Element_Node
,
143 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
146 new Generic_Set_Operations
147 (Tree_Operations
=> Tree_Operations
,
148 Insert_With_Hint
=> Insert_With_Hint
,
149 Copy_Tree
=> Copy_Tree
,
150 Delete_Tree
=> Delete_Tree
,
151 Is_Less
=> Is_Less_Node_Node
,
158 function "<" (Left
, Right
: Cursor
) return Boolean is
160 if Left
.Node
= null then
161 raise Constraint_Error
with "Left cursor equals No_Element";
164 if Right
.Node
= null then
165 raise Constraint_Error
with "Right cursor equals No_Element";
168 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
169 "bad Left cursor in ""<""");
171 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
172 "bad Right cursor in ""<""");
174 return Left
.Node
.Element
< Right
.Node
.Element
;
177 function "<" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
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
) return Boolean is
191 if Right
.Node
= null then
192 raise Constraint_Error
with "Right cursor equals No_Element";
195 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
196 "bad Right cursor in ""<""");
198 return Left
< Right
.Node
.Element
;
205 function "=" (Left
, Right
: Set
) return Boolean is
207 return Is_Equal
(Left
.Tree
, Right
.Tree
);
214 function ">" (Left
, Right
: Cursor
) return Boolean is
216 if Left
.Node
= null then
217 raise Constraint_Error
with "Left cursor equals No_Element";
220 if Right
.Node
= null then
221 raise Constraint_Error
with "Right cursor equals No_Element";
224 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
225 "bad Left cursor in "">""");
227 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
228 "bad Right cursor in "">""");
230 -- L > R same as R < L
232 return Right
.Node
.Element
< Left
.Node
.Element
;
235 function ">" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
237 if Right
.Node
= null then
238 raise Constraint_Error
with "Right cursor equals No_Element";
241 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
242 "bad Right cursor in "">""");
244 return Right
.Node
.Element
< Left
;
247 function ">" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
249 if Left
.Node
= null then
250 raise Constraint_Error
with "Left cursor equals No_Element";
253 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
254 "bad Left cursor in "">""");
256 return Right
< Left
.Node
.Element
;
263 procedure Adjust
is new Tree_Operations
.Generic_Adjust
(Copy_Tree
);
265 procedure Adjust
(Container
: in out Set
) is
267 Adjust
(Container
.Tree
);
270 procedure Adjust
(Control
: in out Reference_Control_Type
) is
272 if Control
.Container
/= null then
274 Tree
: Tree_Type
renames Control
.Container
.all.Tree
;
275 B
: Natural renames Tree
.Busy
;
276 L
: Natural renames Tree
.Lock
;
288 procedure Assign
(Target
: in out Set
; Source
: Set
) is
290 if Target
'Address = Source
'Address then
295 Target
.Union
(Source
);
302 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
303 Node
: constant Node_Access
:=
304 Element_Keys
.Ceiling
(Container
.Tree
, Item
);
306 return (if Node
= null then No_Element
307 else Cursor
'(Container'Unrestricted_Access, Node));
314 procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
316 procedure Clear (Container : in out Set) is
318 Clear (Container.Tree);
325 function Color (Node : Node_Access) return Color_Type is
330 ------------------------
331 -- Constant_Reference --
332 ------------------------
334 function Constant_Reference
335 (Container : aliased Set;
336 Position : Cursor) return Constant_Reference_Type
339 if Position.Container = null then
340 raise Constraint_Error with "Position cursor has no element";
343 if Position.Container /= Container'Unrestricted_Access then
344 raise Program_Error with
345 "Position cursor designates wrong container";
349 (Vet (Container.Tree, Position.Node),
350 "bad cursor in Constant_Reference");
353 Tree : Tree_Type renames Position.Container.all.Tree;
354 B : Natural renames Tree.Busy;
355 L : Natural renames Tree.Lock;
357 return R : constant Constant_Reference_Type :=
358 (Element => Position.Node.Element'Access,
359 Control => (Controlled with Container'Unrestricted_Access))
365 end Constant_Reference;
373 Item : Element_Type) return Boolean
376 return Find (Container, Item) /= No_Element;
383 function Copy (Source : Set) return Set is
385 return Target : Set do
386 Target.Assign (Source);
394 function Copy_Node (Source : Node_Access) return Node_Access is
395 Target : constant Node_Access :=
396 new Node_Type'(Parent
=> null,
399 Color
=> Source
.Color
,
400 Element
=> Source
.Element
);
409 procedure Delete
(Container
: in out Set
; Position
: in out Cursor
) is
411 if Position
.Node
= null then
412 raise Constraint_Error
with "Position cursor equals No_Element";
415 if Position
.Container
/= Container
'Unrestricted_Access then
416 raise Program_Error
with "Position cursor designates wrong set";
419 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
420 "bad cursor in Delete");
422 Tree_Operations
.Delete_Node_Sans_Free
(Container
.Tree
, Position
.Node
);
423 Free
(Position
.Node
);
424 Position
.Container
:= null;
427 procedure Delete
(Container
: in out Set
; Item
: Element_Type
) is
428 X
: Node_Access
:= Element_Keys
.Find
(Container
.Tree
, Item
);
432 raise Constraint_Error
with "attempt to delete element not in set";
435 Tree_Operations
.Delete_Node_Sans_Free
(Container
.Tree
, X
);
443 procedure Delete_First
(Container
: in out Set
) is
444 Tree
: Tree_Type
renames Container
.Tree
;
445 X
: Node_Access
:= Tree
.First
;
448 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
457 procedure Delete_Last
(Container
: in out Set
) is
458 Tree
: Tree_Type
renames Container
.Tree
;
459 X
: Node_Access
:= Tree
.Last
;
462 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
471 procedure Difference
(Target
: in out Set
; Source
: Set
) is
473 Set_Ops
.Difference
(Target
.Tree
, Source
.Tree
);
476 function Difference
(Left
, Right
: Set
) return Set
is
477 Tree
: constant Tree_Type
:= Set_Ops
.Difference
(Left
.Tree
, Right
.Tree
);
479 return Set
'(Controlled with Tree);
486 function Element (Position : Cursor) return Element_Type is
488 if Position.Node = null then
489 raise Constraint_Error with "Position cursor equals No_Element";
492 pragma Assert (Vet (Position.Container.Tree, Position.Node),
493 "bad cursor in Element");
495 return Position.Node.Element;
498 -------------------------
499 -- Equivalent_Elements --
500 -------------------------
502 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
504 return (if Left < Right or else Right < Left then False else True);
505 end Equivalent_Elements;
507 ---------------------
508 -- Equivalent_Sets --
509 ---------------------
511 function Equivalent_Sets (Left, Right : Set) return Boolean is
512 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
513 pragma Inline (Is_Equivalent_Node_Node);
515 function Is_Equivalent is
516 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
518 -----------------------------
519 -- Is_Equivalent_Node_Node --
520 -----------------------------
522 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
524 return (if L.Element < R.Element then False
525 elsif R.Element < L.Element then False
527 end Is_Equivalent_Node_Node;
529 -- Start of processing for Equivalent_Sets
532 return Is_Equivalent (Left.Tree, Right.Tree);
539 procedure Exclude (Container : in out Set; Item : Element_Type) is
540 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
544 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
553 procedure Finalize (Object : in out Iterator) is
555 if Object.Container /= null then
557 B : Natural renames Object.Container.all.Tree.Busy;
564 procedure Finalize (Control : in out Reference_Control_Type) is
566 if Control.Container /= null then
568 Tree : Tree_Type renames Control.Container.all.Tree;
569 B : Natural renames Tree.Busy;
570 L : Natural renames Tree.Lock;
576 Control.Container := null;
584 function Find (Container : Set; Item : Element_Type) return Cursor is
585 Node : constant Node_Access := Element_Keys.Find (Container.Tree, Item);
587 return (if Node = null then No_Element
588 else Cursor'(Container
'Unrestricted_Access, Node
));
595 function First
(Container
: Set
) return Cursor
is
598 (if Container
.Tree
.First
= null then No_Element
599 else Cursor
'(Container'Unrestricted_Access, Container.Tree.First));
602 function First (Object : Iterator) return Cursor is
604 -- The value of the iterator object's Node component influences the
605 -- behavior of the First (and Last) selector function.
607 -- When the Node component is null, this means the iterator object was
608 -- constructed without a start expression, in which case the (forward)
609 -- iteration starts from the (logical) beginning of the entire sequence
610 -- of items (corresponding to Container.First, for a forward iterator).
612 -- Otherwise, this is iteration over a partial sequence of items. When
613 -- the Node component is non-null, the iterator object was constructed
614 -- with a start expression, that specifies the position from which the
615 -- (forward) partial iteration begins.
617 if Object.Node = null then
618 return Object.Container.First;
620 return Cursor'(Object
.Container
, Object
.Node
);
628 function First_Element
(Container
: Set
) return Element_Type
is
630 if Container
.Tree
.First
= null then
631 raise Constraint_Error
with "set is empty";
634 return Container
.Tree
.First
.Element
;
641 function Floor
(Container
: Set
; Item
: Element_Type
) return Cursor
is
642 Node
: constant Node_Access
:= Element_Keys
.Floor
(Container
.Tree
, Item
);
644 return (if Node
= null then No_Element
645 else Cursor
'(Container'Unrestricted_Access, Node));
652 procedure Free (X : in out Node_Access) is
653 procedure Deallocate is
654 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
668 package body Generic_Keys is
670 -----------------------
671 -- Local Subprograms --
672 -----------------------
674 function Is_Greater_Key_Node
676 Right : Node_Access) return Boolean;
677 pragma Inline (Is_Greater_Key_Node);
679 function Is_Less_Key_Node
681 Right : Node_Access) return Boolean;
682 pragma Inline (Is_Less_Key_Node);
684 --------------------------
685 -- Local Instantiations --
686 --------------------------
689 new Red_Black_Trees.Generic_Keys
690 (Tree_Operations => Tree_Operations,
691 Key_Type => Key_Type,
692 Is_Less_Key_Node => Is_Less_Key_Node,
693 Is_Greater_Key_Node => Is_Greater_Key_Node);
699 procedure Adjust (Control : in out Reference_Control_Type) is
701 if Control.Container /= null then
703 Tree : Tree_Type renames Control.Container.Tree;
704 B : Natural renames Tree.Busy;
705 L : Natural renames Tree.Lock;
717 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
718 Node : constant Node_Access := Key_Keys.Ceiling (Container.Tree, Key);
720 return (if Node = null then No_Element
721 else Cursor'(Container
'Unrestricted_Access, Node
));
724 ------------------------
725 -- Constant_Reference --
726 ------------------------
728 function Constant_Reference
729 (Container
: aliased Set
;
730 Key
: Key_Type
) return Constant_Reference_Type
732 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
736 raise Constraint_Error
with "key not in set";
740 Tree
: Tree_Type
renames Container
'Unrestricted_Access.all.Tree
;
741 B
: Natural renames Tree
.Busy
;
742 L
: Natural renames Tree
.Lock
;
744 return R
: constant Constant_Reference_Type
:=
745 (Element
=> Node
.Element
'Access,
746 Control
=> (Controlled
with Container
'Unrestricted_Access))
752 end Constant_Reference
;
758 function Contains
(Container
: Set
; Key
: Key_Type
) return Boolean is
760 return Find
(Container
, Key
) /= No_Element
;
767 procedure Delete
(Container
: in out Set
; Key
: Key_Type
) is
768 X
: Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
772 raise Constraint_Error
with "attempt to delete key not in set";
775 Delete_Node_Sans_Free
(Container
.Tree
, X
);
783 function Element
(Container
: Set
; Key
: Key_Type
) return Element_Type
is
784 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
788 raise Constraint_Error
with "key not in set";
794 ---------------------
795 -- Equivalent_Keys --
796 ---------------------
798 function Equivalent_Keys
(Left
, Right
: Key_Type
) return Boolean is
800 return (if Left
< Right
or else Right
< Left
then False else True);
807 procedure Exclude
(Container
: in out Set
; Key
: Key_Type
) is
808 X
: Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
811 Delete_Node_Sans_Free
(Container
.Tree
, X
);
820 procedure Finalize
(Control
: in out Reference_Control_Type
) is
822 if Control
.Container
/= null then
824 Tree
: Tree_Type
renames Control
.Container
.Tree
;
825 B
: Natural renames Tree
.Busy
;
826 L
: Natural renames Tree
.Lock
;
832 if not (Key
(Control
.Pos
) = Control
.Old_Key
.all) then
833 Delete
(Control
.Container
.all, Key
(Control
.Pos
));
837 Control
.Container
:= null;
838 Control
.Old_Key
:= null;
846 function Find
(Container
: Set
; Key
: Key_Type
) return Cursor
is
847 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
849 return (if Node
= null then No_Element
850 else Cursor
'(Container'Unrestricted_Access, Node));
857 function Floor (Container : Set; Key : Key_Type) return Cursor is
858 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
860 return (if Node = null then No_Element
861 else Cursor'(Container
'Unrestricted_Access, Node
));
864 -------------------------
865 -- Is_Greater_Key_Node --
866 -------------------------
868 function Is_Greater_Key_Node
870 Right
: Node_Access
) return Boolean
873 return Key
(Right
.Element
) < Left
;
874 end Is_Greater_Key_Node
;
876 ----------------------
877 -- Is_Less_Key_Node --
878 ----------------------
880 function Is_Less_Key_Node
882 Right
: Node_Access
) return Boolean
885 return Left
< Key
(Right
.Element
);
886 end Is_Less_Key_Node
;
892 function Key
(Position
: Cursor
) return Key_Type
is
894 if Position
.Node
= null then
895 raise Constraint_Error
with
896 "Position cursor equals No_Element";
899 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
900 "bad cursor in Key");
902 return Key
(Position
.Node
.Element
);
910 (Stream
: not null access Root_Stream_Type
'Class;
911 Item
: out Reference_Type
)
914 raise Program_Error
with "attempt to stream reference";
917 ------------------------------
918 -- Reference_Preserving_Key --
919 ------------------------------
921 function Reference_Preserving_Key
922 (Container
: aliased in out Set
;
923 Position
: Cursor
) return Reference_Type
926 if Position
.Container
= null then
927 raise Constraint_Error
with "Position cursor has no element";
930 if Position
.Container
/= Container
'Unrestricted_Access then
931 raise Program_Error
with
932 "Position cursor designates wrong container";
936 (Vet
(Container
.Tree
, Position
.Node
),
937 "bad cursor in function Reference_Preserving_Key");
940 Tree
: Tree_Type
renames Container
.Tree
;
941 B
: Natural renames Tree
.Busy
;
942 L
: Natural renames Tree
.Lock
;
945 return R
: constant Reference_Type
:=
946 (Element
=> Position
.Node
.Element
'Access,
949 Container
=> Container
'Access,
951 Old_Key
=> new Key_Type
'(Key (Position))))
957 end Reference_Preserving_Key;
959 function Reference_Preserving_Key
960 (Container : aliased in out Set;
961 Key : Key_Type) return Reference_Type
963 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
967 raise Constraint_Error with "key not in set";
971 Tree : Tree_Type renames Container.Tree;
972 B : Natural renames Tree.Busy;
973 L : Natural renames Tree.Lock;
976 return R : constant Reference_Type :=
977 (Element => Node.Element'Access,
980 Container => Container'Access,
981 Pos => Find (Container, Key),
982 Old_Key => new Key_Type'(Key
)))
988 end Reference_Preserving_Key
;
995 (Container
: in out Set
;
997 New_Item
: Element_Type
)
999 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
1003 raise Constraint_Error
with
1004 "attempt to replace key not in set";
1007 Replace_Element
(Container
.Tree
, Node
, New_Item
);
1010 -----------------------------------
1011 -- Update_Element_Preserving_Key --
1012 -----------------------------------
1014 procedure Update_Element_Preserving_Key
1015 (Container
: in out Set
;
1017 Process
: not null access procedure (Element
: in out Element_Type
))
1019 Tree
: Tree_Type
renames Container
.Tree
;
1022 if Position
.Node
= null then
1023 raise Constraint_Error
with
1024 "Position cursor equals No_Element";
1027 if Position
.Container
/= Container
'Unrestricted_Access then
1028 raise Program_Error
with
1029 "Position cursor designates wrong set";
1032 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
1033 "bad cursor in Update_Element_Preserving_Key");
1036 E
: Element_Type
renames Position
.Node
.Element
;
1037 K
: constant Key_Type
:= Key
(E
);
1039 B
: Natural renames Tree
.Busy
;
1040 L
: Natural renames Tree
.Lock
;
1050 Eq
:= Equivalent_Keys
(K
, Key
(E
));
1067 X
: Node_Access
:= Position
.Node
;
1069 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
1073 raise Program_Error
with "key was modified";
1074 end Update_Element_Preserving_Key
;
1081 (Stream
: not null access Root_Stream_Type
'Class;
1082 Item
: Reference_Type
)
1085 raise Program_Error
with "attempt to stream reference";
1094 function Has_Element
(Position
: Cursor
) return Boolean is
1096 return Position
/= No_Element
;
1103 procedure Include
(Container
: in out Set
; New_Item
: Element_Type
) is
1108 Insert
(Container
, New_Item
, Position
, Inserted
);
1110 if not Inserted
then
1111 if Container
.Tree
.Lock
> 0 then
1112 raise Program_Error
with
1113 "attempt to tamper with elements (set is locked)";
1116 Position
.Node
.Element
:= New_Item
;
1125 (Container
: in out Set
;
1126 New_Item
: Element_Type
;
1127 Position
: out Cursor
;
1128 Inserted
: out Boolean)
1137 Position
.Container
:= Container
'Unrestricted_Access;
1141 (Container
: in out Set
;
1142 New_Item
: Element_Type
)
1145 pragma Unreferenced
(Position
);
1150 Insert
(Container
, New_Item
, Position
, Inserted
);
1152 if not Inserted
then
1153 raise Constraint_Error
with
1154 "attempt to insert element already in set";
1158 ----------------------
1159 -- Insert_Sans_Hint --
1160 ----------------------
1162 procedure Insert_Sans_Hint
1163 (Tree
: in out Tree_Type
;
1164 New_Item
: Element_Type
;
1165 Node
: out Node_Access
;
1166 Inserted
: out Boolean)
1168 function New_Node
return Node_Access
;
1169 pragma Inline
(New_Node
);
1171 procedure Insert_Post
is
1172 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1174 procedure Conditional_Insert_Sans_Hint
is
1175 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1181 function New_Node
return Node_Access
is
1183 return new Node_Type
'(Parent => null,
1186 Color => Red_Black_Trees.Red,
1187 Element => New_Item);
1190 -- Start of processing for Insert_Sans_Hint
1193 Conditional_Insert_Sans_Hint
1198 end Insert_Sans_Hint;
1200 ----------------------
1201 -- Insert_With_Hint --
1202 ----------------------
1204 procedure Insert_With_Hint
1205 (Dst_Tree : in out Tree_Type;
1206 Dst_Hint : Node_Access;
1207 Src_Node : Node_Access;
1208 Dst_Node : out Node_Access)
1211 pragma Unreferenced (Success);
1213 function New_Node return Node_Access;
1214 pragma Inline (New_Node);
1216 procedure Insert_Post is
1217 new Element_Keys.Generic_Insert_Post (New_Node);
1219 procedure Insert_Sans_Hint is
1220 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1222 procedure Local_Insert_With_Hint is
1223 new Element_Keys.Generic_Conditional_Insert_With_Hint
1231 function New_Node return Node_Access is
1232 Node : constant Node_Access :=
1233 new Node_Type'(Parent
=> null,
1237 Element
=> Src_Node
.Element
);
1242 -- Start of processing for Insert_With_Hint
1245 Local_Insert_With_Hint
1251 end Insert_With_Hint
;
1257 procedure Intersection
(Target
: in out Set
; Source
: Set
) is
1259 Set_Ops
.Intersection
(Target
.Tree
, Source
.Tree
);
1262 function Intersection
(Left
, Right
: Set
) return Set
is
1263 Tree
: constant Tree_Type
:=
1264 Set_Ops
.Intersection
(Left
.Tree
, Right
.Tree
);
1266 return Set
'(Controlled with Tree);
1273 function Is_Empty (Container : Set) return Boolean is
1275 return Container.Tree.Length = 0;
1278 ------------------------
1279 -- Is_Equal_Node_Node --
1280 ------------------------
1282 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1284 return L.Element = R.Element;
1285 end Is_Equal_Node_Node;
1287 -----------------------------
1288 -- Is_Greater_Element_Node --
1289 -----------------------------
1291 function Is_Greater_Element_Node
1292 (Left : Element_Type;
1293 Right : Node_Access) return Boolean
1296 -- Compute e > node same as node < e
1298 return Right.Element < Left;
1299 end Is_Greater_Element_Node;
1301 --------------------------
1302 -- Is_Less_Element_Node --
1303 --------------------------
1305 function Is_Less_Element_Node
1306 (Left : Element_Type;
1307 Right : Node_Access) return Boolean
1310 return Left < Right.Element;
1311 end Is_Less_Element_Node;
1313 -----------------------
1314 -- Is_Less_Node_Node --
1315 -----------------------
1317 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1319 return L.Element < R.Element;
1320 end Is_Less_Node_Node;
1326 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1328 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1337 Process : not null access procedure (Position : Cursor))
1339 procedure Process_Node (Node : Node_Access);
1340 pragma Inline (Process_Node);
1342 procedure Local_Iterate is
1343 new Tree_Operations.Generic_Iteration (Process_Node);
1349 procedure Process_Node (Node : Node_Access) is
1351 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1354 T
: Tree_Type
renames Container
'Unrestricted_Access.all.Tree
;
1355 B
: Natural renames T
.Busy
;
1357 -- Start of processing for Iterate
1373 function Iterate
(Container
: Set
)
1374 return Set_Iterator_Interfaces
.Reversible_Iterator
'Class
1376 B
: Natural renames Container
'Unrestricted_Access.all.Tree
.Busy
;
1379 -- The value of the Node component influences the behavior of the First
1380 -- and Last selector functions of the iterator object. When the Node
1381 -- component is null (as is the case here), this means the iterator
1382 -- object was constructed without a start expression. This is a complete
1383 -- iterator, meaning that the iteration starts from the (logical)
1384 -- beginning of the sequence of items.
1386 -- Note: For a forward iterator, Container.First is the beginning, and
1387 -- for a reverse iterator, Container.Last is the beginning.
1391 return It
: constant Iterator
:=
1392 Iterator
'(Limited_Controlled with
1393 Container => Container'Unrestricted_Access,
1397 function Iterate (Container : Set; Start : Cursor)
1398 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1400 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1403 -- It was formerly the case that when Start = No_Element, the partial
1404 -- iterator was defined to behave the same as for a complete iterator,
1405 -- and iterate over the entire sequence of items. However, those
1406 -- semantics were unintuitive and arguably error-prone (it is too easy
1407 -- to accidentally create an endless loop), and so they were changed,
1408 -- per the ARG meeting in Denver on 2011/11. However, there was no
1409 -- consensus about what positive meaning this corner case should have,
1410 -- and so it was decided to simply raise an exception. This does imply,
1411 -- however, that it is not possible to use a partial iterator to specify
1412 -- an empty sequence of items.
1414 if Start = No_Element then
1415 raise Constraint_Error with
1416 "Start position for iterator equals No_Element";
1419 if Start.Container /= Container'Unrestricted_Access then
1420 raise Program_Error with
1421 "Start cursor of Iterate designates wrong set";
1424 pragma Assert (Vet (Container.Tree, Start.Node),
1425 "Start cursor of Iterate is bad");
1427 -- The value of the Node component influences the behavior of the First
1428 -- and Last selector functions of the iterator object. When the Node
1429 -- component is non-null (as is the case here), it means that this is a
1430 -- partial iteration, over a subset of the complete sequence of
1431 -- items. The iterator object was constructed with a start expression,
1432 -- indicating the position from which the iteration begins. Note that
1433 -- the start position has the same value irrespective of whether this is
1434 -- a forward or reverse iteration.
1438 return It : constant Iterator :=
1439 Iterator'(Limited_Controlled
with
1440 Container
=> Container
'Unrestricted_Access,
1441 Node
=> Start
.Node
);
1448 function Last
(Container
: Set
) return Cursor
is
1451 (if Container
.Tree
.Last
= null then No_Element
1452 else Cursor
'(Container'Unrestricted_Access, Container.Tree.Last));
1455 function Last (Object : Iterator) return Cursor is
1457 -- The value of the iterator object's Node component influences the
1458 -- behavior of the Last (and First) selector function.
1460 -- When the Node component is null, this means the iterator object was
1461 -- constructed without a start expression, in which case the (reverse)
1462 -- iteration starts from the (logical) beginning of the entire sequence
1463 -- (corresponding to Container.Last, for a reverse iterator).
1465 -- Otherwise, this is iteration over a partial sequence of items. When
1466 -- the Node component is non-null, the iterator object was constructed
1467 -- with a start expression, that specifies the position from which the
1468 -- (reverse) partial iteration begins.
1470 if Object.Node = null then
1471 return Object.Container.Last;
1473 return Cursor'(Object
.Container
, Object
.Node
);
1481 function Last_Element
(Container
: Set
) return Element_Type
is
1483 if Container
.Tree
.Last
= null then
1484 raise Constraint_Error
with "set is empty";
1486 return Container
.Tree
.Last
.Element
;
1494 function Left
(Node
: Node_Access
) return Node_Access
is
1503 function Length
(Container
: Set
) return Count_Type
is
1505 return Container
.Tree
.Length
;
1512 procedure Move
is new Tree_Operations
.Generic_Move
(Clear
);
1514 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
1516 Move
(Target
=> Target
.Tree
, Source
=> Source
.Tree
);
1523 function Next
(Position
: Cursor
) return Cursor
is
1525 if Position
= No_Element
then
1529 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1530 "bad cursor in Next");
1533 Node
: constant Node_Access
:=
1534 Tree_Operations
.Next
(Position
.Node
);
1536 return (if Node
= null then No_Element
1537 else Cursor
'(Position.Container, Node));
1541 procedure Next (Position : in out Cursor) is
1543 Position := Next (Position);
1546 function Next (Object : Iterator; Position : Cursor) return Cursor is
1548 if Position.Container = null then
1552 if Position.Container /= Object.Container then
1553 raise Program_Error with
1554 "Position cursor of Next designates wrong set";
1557 return Next (Position);
1564 function Overlap (Left, Right : Set) return Boolean is
1566 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1573 function Parent (Node : Node_Access) return Node_Access is
1582 function Previous (Position : Cursor) return Cursor is
1584 if Position = No_Element then
1588 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1589 "bad cursor in Previous");
1592 Node : constant Node_Access :=
1593 Tree_Operations.Previous (Position.Node);
1595 return (if Node = null then No_Element
1596 else Cursor'(Position
.Container
, Node
));
1600 procedure Previous
(Position
: in out Cursor
) is
1602 Position
:= Previous
(Position
);
1605 function Previous
(Object
: Iterator
; Position
: Cursor
) return Cursor
is
1607 if Position
.Container
= null then
1611 if Position
.Container
/= Object
.Container
then
1612 raise Program_Error
with
1613 "Position cursor of Previous designates wrong set";
1616 return Previous
(Position
);
1623 procedure Query_Element
1625 Process
: not null access procedure (Element
: Element_Type
))
1628 if Position
.Node
= null then
1629 raise Constraint_Error
with "Position cursor equals No_Element";
1632 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1633 "bad cursor in Query_Element");
1636 T
: Tree_Type
renames Position
.Container
.Tree
;
1638 B
: Natural renames T
.Busy
;
1639 L
: Natural renames T
.Lock
;
1646 Process
(Position
.Node
.Element
);
1664 (Stream
: not null access Root_Stream_Type
'Class;
1665 Container
: out Set
)
1668 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
;
1669 pragma Inline
(Read_Node
);
1672 new Tree_Operations
.Generic_Read
(Clear
, Read_Node
);
1679 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
1681 Node
: Node_Access
:= new Node_Type
;
1683 Element_Type
'Read (Stream
, Node
.Element
);
1691 -- Start of processing for Read
1694 Read
(Stream
, Container
.Tree
);
1698 (Stream
: not null access Root_Stream_Type
'Class;
1702 raise Program_Error
with "attempt to stream set cursor";
1706 (Stream
: not null access Root_Stream_Type
'Class;
1707 Item
: out Constant_Reference_Type
)
1710 raise Program_Error
with "attempt to stream reference";
1717 procedure Replace
(Container
: in out Set
; New_Item
: Element_Type
) is
1718 Node
: constant Node_Access
:=
1719 Element_Keys
.Find
(Container
.Tree
, New_Item
);
1723 raise Constraint_Error
with
1724 "attempt to replace element not in set";
1727 if Container
.Tree
.Lock
> 0 then
1728 raise Program_Error
with
1729 "attempt to tamper with elements (set is locked)";
1732 Node
.Element
:= New_Item
;
1735 ---------------------
1736 -- Replace_Element --
1737 ---------------------
1739 procedure Replace_Element
1740 (Tree
: in out Tree_Type
;
1742 Item
: Element_Type
)
1744 pragma Assert
(Node
/= null);
1746 function New_Node
return Node_Access
;
1747 pragma Inline
(New_Node
);
1749 procedure Local_Insert_Post
is
1750 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1752 procedure Local_Insert_Sans_Hint
is
1753 new Element_Keys
.Generic_Conditional_Insert
(Local_Insert_Post
);
1755 procedure Local_Insert_With_Hint
is
1756 new Element_Keys
.Generic_Conditional_Insert_With_Hint
1758 Local_Insert_Sans_Hint
);
1764 function New_Node
return Node_Access
is
1766 Node
.Element
:= Item
;
1768 Node
.Parent
:= null;
1775 Result
: Node_Access
;
1779 -- Per AI05-0022, the container implementation is required to detect
1780 -- element tampering by a generic actual subprogram.
1782 B
: Natural renames Tree
.Busy
;
1783 L
: Natural renames Tree
.Lock
;
1785 -- Start of processing for Replace_Element
1788 -- Replace_Element assigns value Item to the element designated by Node,
1789 -- per certain semantic constraints.
1791 -- If Item is equivalent to the element, then element is replaced and
1792 -- there's nothing else to do. This is the easy case.
1794 -- If Item is not equivalent, then the node will (possibly) have to move
1795 -- to some other place in the tree. This is slighly more complicated,
1796 -- because we must ensure that Item is not equivalent to some other
1797 -- element in the tree (in which case, the replacement is not allowed).
1799 -- Determine whether Item is equivalent to element on the specified
1806 Compare
:= (if Item
< Node
.Element
then False
1807 elsif Node
.Element
< Item
then False
1822 -- Item is equivalent to the node's element, so we will not have to
1825 if Tree
.Lock
> 0 then
1826 raise Program_Error
with
1827 "attempt to tamper with elements (set is locked)";
1830 Node
.Element
:= Item
;
1834 -- The replacement Item is not equivalent to the element on the
1835 -- specified node, which means that it will need to be re-inserted in a
1836 -- different position in the tree. We must now determine whether Item is
1837 -- equivalent to some other element in the tree (which would prohibit
1838 -- the assignment and hence the move).
1840 -- Ceiling returns the smallest element equivalent or greater than the
1841 -- specified Item; if there is no such element, then it returns null.
1843 Hint
:= Element_Keys
.Ceiling
(Tree
, Item
);
1845 if Hint
/= null then
1850 Compare
:= Item
< Hint
.Element
;
1863 -- Item >= Hint.Element
1867 -- Ceiling returns an element that is equivalent or greater
1868 -- than Item. If Item is "not less than" the element, then
1869 -- by elimination we know that Item is equivalent to the element.
1871 -- But this means that it is not possible to assign the value of
1872 -- Item to the specified element (on Node), because a different
1873 -- element (on Hint) equivalent to Item already exsits. (Were we
1874 -- to change Node's element value, we would have to move Node, but
1875 -- we would be unable to move the Node, because its new position
1876 -- in the tree is already occupied by an equivalent element.)
1878 raise Program_Error
with "attempt to replace existing element";
1881 -- Item is not equivalent to any other element in the tree, so it is
1882 -- safe to assign the value of Item to Node.Element. This means that
1883 -- the node will have to move to a different position in the tree
1884 -- (because its element will have a different value).
1886 -- The nearest (greater) neighbor of Item is Hint. This will be the
1887 -- insertion position of Node (because its element will have Item as
1890 -- If Node equals Hint, the relative position of Node does not
1891 -- change. This allows us to perform an optimization: we need not
1892 -- remove Node from the tree and then reinsert it with its new value,
1893 -- because it would only be placed in the exact same position.
1896 if Tree
.Lock
> 0 then
1897 raise Program_Error
with
1898 "attempt to tamper with elements (set is locked)";
1901 Node
.Element
:= Item
;
1906 -- If we get here, it is because Item was greater than all elements in
1907 -- the tree (Hint = null), or because Item was less than some element at
1908 -- a different place in the tree (Item < Hint.Element). In either case,
1909 -- we remove Node from the tree (without actually deallocating it), and
1910 -- then insert Item into the tree, onto the same Node (so no new node is
1911 -- actually allocated).
1913 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, Node
); -- Checks busy-bit
1915 Local_Insert_With_Hint
-- use unconditional insert here instead???
1920 Inserted
=> Inserted
);
1922 pragma Assert
(Inserted
);
1923 pragma Assert
(Result
= Node
);
1924 end Replace_Element
;
1926 procedure Replace_Element
1927 (Container
: in out Set
;
1929 New_Item
: Element_Type
)
1932 if Position
.Node
= null then
1933 raise Constraint_Error
with
1934 "Position cursor equals No_Element";
1937 if Position
.Container
/= Container
'Unrestricted_Access then
1938 raise Program_Error
with
1939 "Position cursor designates wrong set";
1942 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
1943 "bad cursor in Replace_Element");
1945 Replace_Element
(Container
.Tree
, Position
.Node
, New_Item
);
1946 end Replace_Element
;
1948 ---------------------
1949 -- Reverse_Iterate --
1950 ---------------------
1952 procedure Reverse_Iterate
1954 Process
: not null access procedure (Position
: Cursor
))
1956 procedure Process_Node
(Node
: Node_Access
);
1957 pragma Inline
(Process_Node
);
1959 procedure Local_Reverse_Iterate
is
1960 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1966 procedure Process_Node
(Node
: Node_Access
) is
1968 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1971 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1972 B : Natural renames T.Busy;
1974 -- Start of processing for Reverse_Iterate
1980 Local_Reverse_Iterate (T);
1988 end Reverse_Iterate;
1994 function Right (Node : Node_Access) return Node_Access is
2003 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
2005 Node.Color := Color;
2012 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
2021 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
2023 Node.Parent := Parent;
2030 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
2032 Node.Right := Right;
2035 --------------------------
2036 -- Symmetric_Difference --
2037 --------------------------
2039 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
2041 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
2042 end Symmetric_Difference;
2044 function Symmetric_Difference (Left, Right : Set) return Set is
2045 Tree : constant Tree_Type :=
2046 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
2048 return Set'(Controlled
with Tree
);
2049 end Symmetric_Difference
;
2055 function To_Set
(New_Item
: Element_Type
) return Set
is
2059 pragma Unreferenced
(Node
, Inserted
);
2061 Insert_Sans_Hint
(Tree
, New_Item
, Node
, Inserted
);
2062 return Set
'(Controlled with Tree);
2069 procedure Union (Target : in out Set; Source : Set) is
2071 Set_Ops.Union (Target.Tree, Source.Tree);
2074 function Union (Left, Right : Set) return Set is
2075 Tree : constant Tree_Type :=
2076 Set_Ops.Union (Left.Tree, Right.Tree);
2078 return Set'(Controlled
with Tree
);
2086 (Stream
: not null access Root_Stream_Type
'Class;
2089 procedure Write_Node
2090 (Stream
: not null access Root_Stream_Type
'Class;
2091 Node
: Node_Access
);
2092 pragma Inline
(Write_Node
);
2095 new Tree_Operations
.Generic_Write
(Write_Node
);
2101 procedure Write_Node
2102 (Stream
: not null access Root_Stream_Type
'Class;
2106 Element_Type
'Write (Stream
, Node
.Element
);
2109 -- Start of processing for Write
2112 Write
(Stream
, Container
.Tree
);
2116 (Stream
: not null access Root_Stream_Type
'Class;
2120 raise Program_Error
with "attempt to stream set cursor";
2124 (Stream
: not null access Root_Stream_Type
'Class;
2125 Item
: Constant_Reference_Type
)
2128 raise Program_Error
with "attempt to stream reference";
2131 end Ada
.Containers
.Ordered_Sets
;