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-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
.Ordered_Sets
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 -- Access to Fields of Node --
67 ------------------------------
69 -- These subprograms provide functional notation for access to fields
70 -- of a node, and procedural notation for modifying these fields.
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_Color
(Node
: Node_Access
; Color
: Color_Type
);
85 pragma Inline
(Set_Color
);
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_Parent
(Node
: Node_Access
; Parent
: Node_Access
);
94 pragma Inline
(Set_Parent
);
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
;
109 Inserted
: out Boolean);
111 procedure Insert_With_Hint
112 (Dst_Tree
: in out Tree_Type
;
113 Dst_Hint
: Node_Access
;
114 Src_Node
: Node_Access
;
115 Dst_Node
: out Node_Access
);
117 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean;
118 pragma Inline
(Is_Equal_Node_Node
);
120 function Is_Greater_Element_Node
121 (Left
: Element_Type
;
122 Right
: Node_Access
) return Boolean;
123 pragma Inline
(Is_Greater_Element_Node
);
125 function Is_Less_Element_Node
126 (Left
: Element_Type
;
127 Right
: Node_Access
) return Boolean;
128 pragma Inline
(Is_Less_Element_Node
);
130 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean;
131 pragma Inline
(Is_Less_Node_Node
);
133 procedure Replace_Element
134 (Tree
: in out Tree_Type
;
136 Item
: Element_Type
);
138 --------------------------
139 -- Local Instantiations --
140 --------------------------
142 package Tree_Operations
is
143 new Red_Black_Trees
.Generic_Operations
(Tree_Types
);
145 procedure Delete_Tree
is
146 new Tree_Operations
.Generic_Delete_Tree
(Free
);
148 function Copy_Tree
is
149 new Tree_Operations
.Generic_Copy_Tree
(Copy_Node
, Delete_Tree
);
154 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
156 package Element_Keys
is
157 new Red_Black_Trees
.Generic_Keys
158 (Tree_Operations
=> Tree_Operations
,
159 Key_Type
=> Element_Type
,
160 Is_Less_Key_Node
=> Is_Less_Element_Node
,
161 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
164 new Generic_Set_Operations
165 (Tree_Operations
=> Tree_Operations
,
166 Insert_With_Hint
=> Insert_With_Hint
,
167 Copy_Tree
=> Copy_Tree
,
168 Delete_Tree
=> Delete_Tree
,
169 Is_Less
=> Is_Less_Node_Node
,
176 function "<" (Left
, Right
: Cursor
) return Boolean is
178 if Left
.Node
= null then
179 raise Constraint_Error
with "Left cursor equals No_Element";
182 if Right
.Node
= null then
183 raise Constraint_Error
with "Right cursor equals No_Element";
186 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
187 "bad Left cursor in ""<""");
189 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
190 "bad Right cursor in ""<""");
192 return Left
.Node
.Element
< Right
.Node
.Element
;
195 function "<" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
197 if Left
.Node
= null then
198 raise Constraint_Error
with "Left cursor equals No_Element";
201 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
202 "bad Left cursor in ""<""");
204 return Left
.Node
.Element
< Right
;
207 function "<" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
209 if Right
.Node
= null then
210 raise Constraint_Error
with "Right cursor equals No_Element";
213 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
214 "bad Right cursor in ""<""");
216 return Left
< Right
.Node
.Element
;
223 function "=" (Left
, Right
: Set
) return Boolean is
225 return Is_Equal
(Left
.Tree
, Right
.Tree
);
232 function ">" (Left
, Right
: Cursor
) return Boolean is
234 if Left
.Node
= null then
235 raise Constraint_Error
with "Left cursor equals No_Element";
238 if Right
.Node
= null then
239 raise Constraint_Error
with "Right cursor equals No_Element";
242 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
243 "bad Left cursor in "">""");
245 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
246 "bad Right cursor in "">""");
248 -- L > R same as R < L
250 return Right
.Node
.Element
< Left
.Node
.Element
;
253 function ">" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
255 if Right
.Node
= null then
256 raise Constraint_Error
with "Right cursor equals No_Element";
259 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
260 "bad Right cursor in "">""");
262 return Right
.Node
.Element
< Left
;
265 function ">" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
267 if Left
.Node
= null then
268 raise Constraint_Error
with "Left cursor equals No_Element";
271 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
272 "bad Left cursor in "">""");
274 return Right
< Left
.Node
.Element
;
281 procedure Adjust
is new Tree_Operations
.Generic_Adjust
(Copy_Tree
);
283 procedure Adjust
(Container
: in out Set
) is
285 Adjust
(Container
.Tree
);
288 procedure Adjust
(Control
: in out Reference_Control_Type
) is
290 if Control
.Container
/= null then
292 Tree
: Tree_Type
renames Control
.Container
.all.Tree
;
293 B
: Natural renames Tree
.Busy
;
294 L
: Natural renames Tree
.Lock
;
306 procedure Assign
(Target
: in out Set
; Source
: Set
) is
308 if Target
'Address = Source
'Address then
313 Target
.Union
(Source
);
320 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
321 Node
: constant Node_Access
:=
322 Element_Keys
.Ceiling
(Container
.Tree
, Item
);
324 return (if Node
= null then No_Element
325 else Cursor
'(Container'Unrestricted_Access, Node));
332 procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
334 procedure Clear (Container : in out Set) is
336 Clear (Container.Tree);
343 function Color (Node : Node_Access) return Color_Type is
348 ------------------------
349 -- Constant_Reference --
350 ------------------------
352 function Constant_Reference
353 (Container : aliased Set;
354 Position : Cursor) return Constant_Reference_Type
357 if Position.Container = null then
358 raise Constraint_Error with "Position cursor has no element";
361 if Position.Container /= Container'Unrestricted_Access then
362 raise Program_Error with
363 "Position cursor designates wrong container";
367 (Vet (Container.Tree, Position.Node),
368 "bad cursor in Constant_Reference");
371 Tree : Tree_Type renames Position.Container.all.Tree;
372 B : Natural renames Tree.Busy;
373 L : Natural renames Tree.Lock;
375 return R : constant Constant_Reference_Type :=
376 (Element => Position.Node.Element'Access,
377 Control => (Controlled with Container'Unrestricted_Access))
383 end Constant_Reference;
391 Item : Element_Type) return Boolean
394 return Find (Container, Item) /= No_Element;
401 function Copy (Source : Set) return Set is
403 return Target : Set do
404 Target.Assign (Source);
412 function Copy_Node (Source : Node_Access) return Node_Access is
413 Target : constant Node_Access :=
414 new Node_Type'(Parent
=> null,
417 Color
=> Source
.Color
,
418 Element
=> Source
.Element
);
427 procedure Delete
(Container
: in out Set
; Position
: in out Cursor
) is
429 if Position
.Node
= null then
430 raise Constraint_Error
with "Position cursor equals No_Element";
433 if Position
.Container
/= Container
'Unrestricted_Access then
434 raise Program_Error
with "Position cursor designates wrong set";
437 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
438 "bad cursor in Delete");
440 Tree_Operations
.Delete_Node_Sans_Free
(Container
.Tree
, Position
.Node
);
441 Free
(Position
.Node
);
442 Position
.Container
:= null;
445 procedure Delete
(Container
: in out Set
; Item
: Element_Type
) is
446 X
: Node_Access
:= Element_Keys
.Find
(Container
.Tree
, Item
);
450 raise Constraint_Error
with "attempt to delete element not in set";
453 Tree_Operations
.Delete_Node_Sans_Free
(Container
.Tree
, X
);
461 procedure Delete_First
(Container
: in out Set
) is
462 Tree
: Tree_Type
renames Container
.Tree
;
463 X
: Node_Access
:= Tree
.First
;
466 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
475 procedure Delete_Last
(Container
: in out Set
) is
476 Tree
: Tree_Type
renames Container
.Tree
;
477 X
: Node_Access
:= Tree
.Last
;
480 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
489 procedure Difference
(Target
: in out Set
; Source
: Set
) is
491 Set_Ops
.Difference
(Target
.Tree
, Source
.Tree
);
494 function Difference
(Left
, Right
: Set
) return Set
is
495 Tree
: constant Tree_Type
:= Set_Ops
.Difference
(Left
.Tree
, Right
.Tree
);
497 return Set
'(Controlled with Tree);
504 function Element (Position : Cursor) return Element_Type is
506 if Position.Node = null then
507 raise Constraint_Error with "Position cursor equals No_Element";
510 pragma Assert (Vet (Position.Container.Tree, Position.Node),
511 "bad cursor in Element");
513 return Position.Node.Element;
516 -------------------------
517 -- Equivalent_Elements --
518 -------------------------
520 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
522 return (if Left < Right or else Right < Left then False else True);
523 end Equivalent_Elements;
525 ---------------------
526 -- Equivalent_Sets --
527 ---------------------
529 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 return (if L.Element < R.Element then False
543 elsif R.Element < L.Element then False
545 end Is_Equivalent_Node_Node;
547 -- Start of processing for Equivalent_Sets
550 return Is_Equivalent (Left.Tree, Right.Tree);
557 procedure Exclude (Container : in out Set; Item : Element_Type) is
558 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
562 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
571 procedure Finalize (Object : in out Iterator) is
573 if Object.Container /= null then
575 B : Natural renames Object.Container.all.Tree.Busy;
582 procedure Finalize (Control : in out Reference_Control_Type) is
584 if Control.Container /= null then
586 Tree : Tree_Type renames Control.Container.all.Tree;
587 B : Natural renames Tree.Busy;
588 L : Natural renames Tree.Lock;
594 Control.Container := null;
602 function Find (Container : Set; Item : Element_Type) return Cursor is
603 Node : constant Node_Access := Element_Keys.Find (Container.Tree, Item);
605 return (if Node = null then No_Element
606 else Cursor'(Container
'Unrestricted_Access, Node
));
613 function First
(Container
: Set
) return Cursor
is
616 (if Container
.Tree
.First
= null then No_Element
617 else Cursor
'(Container'Unrestricted_Access, Container.Tree.First));
620 function First (Object : Iterator) return Cursor is
622 -- The value of the iterator object's Node component influences the
623 -- behavior of the First (and Last) selector function.
625 -- When the Node component is null, this means the iterator object was
626 -- constructed without a start expression, in which case the (forward)
627 -- iteration starts from the (logical) beginning of the entire sequence
628 -- of items (corresponding to Container.First, for a forward iterator).
630 -- Otherwise, this is iteration over a partial sequence of items. When
631 -- the Node component is non-null, the iterator object was constructed
632 -- with a start expression, that specifies the position from which the
633 -- (forward) partial iteration begins.
635 if Object.Node = null then
636 return Object.Container.First;
638 return Cursor'(Object
.Container
, Object
.Node
);
646 function First_Element
(Container
: Set
) return Element_Type
is
648 if Container
.Tree
.First
= null then
649 raise Constraint_Error
with "set is empty";
652 return Container
.Tree
.First
.Element
;
659 function Floor
(Container
: Set
; Item
: Element_Type
) return Cursor
is
660 Node
: constant Node_Access
:= Element_Keys
.Floor
(Container
.Tree
, Item
);
662 return (if Node
= null then No_Element
663 else 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);
686 package body Generic_Keys is
688 -----------------------
689 -- Local Subprograms --
690 -----------------------
692 function Is_Greater_Key_Node
694 Right : Node_Access) return Boolean;
695 pragma Inline (Is_Greater_Key_Node);
697 function Is_Less_Key_Node
699 Right : Node_Access) return Boolean;
700 pragma Inline (Is_Less_Key_Node);
702 --------------------------
703 -- Local Instantiations --
704 --------------------------
707 new Red_Black_Trees.Generic_Keys
708 (Tree_Operations => Tree_Operations,
709 Key_Type => Key_Type,
710 Is_Less_Key_Node => Is_Less_Key_Node,
711 Is_Greater_Key_Node => Is_Greater_Key_Node);
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 function Find
(Container
: Set
; Key
: Key_Type
) return Cursor
is
821 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
823 return (if Node
= null then No_Element
824 else Cursor
'(Container'Unrestricted_Access, Node));
831 function Floor (Container : Set; Key : Key_Type) return Cursor is
832 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
834 return (if Node = null then No_Element
835 else Cursor'(Container
'Unrestricted_Access, Node
));
838 -------------------------
839 -- Is_Greater_Key_Node --
840 -------------------------
842 function Is_Greater_Key_Node
844 Right
: Node_Access
) return Boolean
847 return Key
(Right
.Element
) < Left
;
848 end Is_Greater_Key_Node
;
850 ----------------------
851 -- Is_Less_Key_Node --
852 ----------------------
854 function Is_Less_Key_Node
856 Right
: Node_Access
) return Boolean
859 return Left
< Key
(Right
.Element
);
860 end Is_Less_Key_Node
;
866 function Key
(Position
: Cursor
) return Key_Type
is
868 if Position
.Node
= null then
869 raise Constraint_Error
with
870 "Position cursor equals No_Element";
873 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
874 "bad cursor in Key");
876 return Key
(Position
.Node
.Element
);
884 (Stream
: not null access Root_Stream_Type
'Class;
885 Item
: out Reference_Type
)
888 raise Program_Error
with "attempt to stream reference";
891 ------------------------------
892 -- Reference_Preserving_Key --
893 ------------------------------
895 function Reference_Preserving_Key
896 (Container
: aliased in out Set
;
897 Position
: Cursor
) return Reference_Type
900 if Position
.Container
= null then
901 raise Constraint_Error
with "Position cursor has no element";
904 if Position
.Container
/= Container
'Unrestricted_Access then
905 raise Program_Error
with
906 "Position cursor designates wrong container";
910 (Vet
(Container
.Tree
, Position
.Node
),
911 "bad cursor in function Reference_Preserving_Key");
913 -- Some form of finalization will be required in order to actually
914 -- check that the key-part of the element designated by Position has
917 return (Element
=> Position
.Node
.Element
'Access);
918 end Reference_Preserving_Key
;
920 function Reference_Preserving_Key
921 (Container
: aliased in out Set
;
922 Key
: Key_Type
) return Reference_Type
924 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
928 raise Constraint_Error
with "key not in set";
931 -- Some form of finalization will be required in order to actually
932 -- check that the key-part of the element designated by Position has
935 return (Element
=> Node
.Element
'Access);
936 end Reference_Preserving_Key
;
943 (Container
: in out Set
;
945 New_Item
: Element_Type
)
947 Node
: constant Node_Access
:= Key_Keys
.Find
(Container
.Tree
, Key
);
951 raise Constraint_Error
with
952 "attempt to replace key not in set";
955 Replace_Element
(Container
.Tree
, Node
, New_Item
);
958 -----------------------------------
959 -- Update_Element_Preserving_Key --
960 -----------------------------------
962 procedure Update_Element_Preserving_Key
963 (Container
: in out Set
;
965 Process
: not null access procedure (Element
: in out Element_Type
))
967 Tree
: Tree_Type
renames Container
.Tree
;
970 if Position
.Node
= null then
971 raise Constraint_Error
with
972 "Position cursor equals No_Element";
975 if Position
.Container
/= Container
'Unrestricted_Access then
976 raise Program_Error
with
977 "Position cursor designates wrong set";
980 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
981 "bad cursor in Update_Element_Preserving_Key");
984 E
: Element_Type
renames Position
.Node
.Element
;
985 K
: constant Key_Type
:= Key
(E
);
987 B
: Natural renames Tree
.Busy
;
988 L
: Natural renames Tree
.Lock
;
1006 if Equivalent_Keys
(K
, Key
(E
)) then
1012 X
: Node_Access
:= Position
.Node
;
1014 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, X
);
1018 raise Program_Error
with "key was modified";
1019 end Update_Element_Preserving_Key
;
1026 (Stream
: not null access Root_Stream_Type
'Class;
1027 Item
: Reference_Type
)
1030 raise Program_Error
with "attempt to stream reference";
1039 function Has_Element
(Position
: Cursor
) return Boolean is
1041 return Position
/= No_Element
;
1048 procedure Include
(Container
: in out Set
; New_Item
: Element_Type
) is
1053 Insert
(Container
, New_Item
, Position
, Inserted
);
1055 if not Inserted
then
1056 if Container
.Tree
.Lock
> 0 then
1057 raise Program_Error
with
1058 "attempt to tamper with elements (set is locked)";
1061 Position
.Node
.Element
:= New_Item
;
1070 (Container
: in out Set
;
1071 New_Item
: Element_Type
;
1072 Position
: out Cursor
;
1073 Inserted
: out Boolean)
1082 Position
.Container
:= Container
'Unrestricted_Access;
1086 (Container
: in out Set
;
1087 New_Item
: Element_Type
)
1090 pragma Unreferenced
(Position
);
1095 Insert
(Container
, New_Item
, Position
, Inserted
);
1097 if not Inserted
then
1098 raise Constraint_Error
with
1099 "attempt to insert element already in set";
1103 ----------------------
1104 -- Insert_Sans_Hint --
1105 ----------------------
1107 procedure Insert_Sans_Hint
1108 (Tree
: in out Tree_Type
;
1109 New_Item
: Element_Type
;
1110 Node
: out Node_Access
;
1111 Inserted
: out Boolean)
1113 function New_Node
return Node_Access
;
1114 pragma Inline
(New_Node
);
1116 procedure Insert_Post
is
1117 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1119 procedure Conditional_Insert_Sans_Hint
is
1120 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1126 function New_Node
return Node_Access
is
1128 return new Node_Type
'(Parent => null,
1131 Color => Red_Black_Trees.Red,
1132 Element => New_Item);
1135 -- Start of processing for Insert_Sans_Hint
1138 Conditional_Insert_Sans_Hint
1143 end Insert_Sans_Hint;
1145 ----------------------
1146 -- Insert_With_Hint --
1147 ----------------------
1149 procedure Insert_With_Hint
1150 (Dst_Tree : in out Tree_Type;
1151 Dst_Hint : Node_Access;
1152 Src_Node : Node_Access;
1153 Dst_Node : out Node_Access)
1156 pragma Unreferenced (Success);
1158 function New_Node return Node_Access;
1159 pragma Inline (New_Node);
1161 procedure Insert_Post is
1162 new Element_Keys.Generic_Insert_Post (New_Node);
1164 procedure Insert_Sans_Hint is
1165 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1167 procedure Local_Insert_With_Hint is
1168 new Element_Keys.Generic_Conditional_Insert_With_Hint
1176 function New_Node return Node_Access is
1177 Node : constant Node_Access :=
1178 new Node_Type'(Parent
=> null,
1182 Element
=> Src_Node
.Element
);
1187 -- Start of processing for Insert_With_Hint
1190 Local_Insert_With_Hint
1196 end Insert_With_Hint
;
1202 procedure Intersection
(Target
: in out Set
; Source
: Set
) is
1204 Set_Ops
.Intersection
(Target
.Tree
, Source
.Tree
);
1207 function Intersection
(Left
, Right
: Set
) return Set
is
1208 Tree
: constant Tree_Type
:=
1209 Set_Ops
.Intersection
(Left
.Tree
, Right
.Tree
);
1211 return Set
'(Controlled with Tree);
1218 function Is_Empty (Container : Set) return Boolean is
1220 return Container.Tree.Length = 0;
1223 ------------------------
1224 -- Is_Equal_Node_Node --
1225 ------------------------
1227 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1229 return L.Element = R.Element;
1230 end Is_Equal_Node_Node;
1232 -----------------------------
1233 -- Is_Greater_Element_Node --
1234 -----------------------------
1236 function Is_Greater_Element_Node
1237 (Left : Element_Type;
1238 Right : Node_Access) return Boolean
1241 -- Compute e > node same as node < e
1243 return Right.Element < Left;
1244 end Is_Greater_Element_Node;
1246 --------------------------
1247 -- Is_Less_Element_Node --
1248 --------------------------
1250 function Is_Less_Element_Node
1251 (Left : Element_Type;
1252 Right : Node_Access) return Boolean
1255 return Left < Right.Element;
1256 end Is_Less_Element_Node;
1258 -----------------------
1259 -- Is_Less_Node_Node --
1260 -----------------------
1262 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1264 return L.Element < R.Element;
1265 end Is_Less_Node_Node;
1271 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1273 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1282 Process : not null access procedure (Position : Cursor))
1284 procedure Process_Node (Node : Node_Access);
1285 pragma Inline (Process_Node);
1287 procedure Local_Iterate is
1288 new Tree_Operations.Generic_Iteration (Process_Node);
1294 procedure Process_Node (Node : Node_Access) is
1296 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1299 T
: Tree_Type
renames Container
'Unrestricted_Access.all.Tree
;
1300 B
: Natural renames T
.Busy
;
1302 -- Start of processing for Iterate
1318 function Iterate
(Container
: Set
)
1319 return Set_Iterator_Interfaces
.Reversible_Iterator
'Class
1321 B
: Natural renames Container
'Unrestricted_Access.all.Tree
.Busy
;
1324 -- The value of the Node component influences the behavior of the First
1325 -- and Last selector functions of the iterator object. When the Node
1326 -- component is null (as is the case here), this means the iterator
1327 -- object was constructed without a start expression. This is a complete
1328 -- iterator, meaning that the iteration starts from the (logical)
1329 -- beginning of the sequence of items.
1331 -- Note: For a forward iterator, Container.First is the beginning, and
1332 -- for a reverse iterator, Container.Last is the beginning.
1336 return It
: constant Iterator
:=
1337 Iterator
'(Limited_Controlled with
1338 Container => Container'Unrestricted_Access,
1342 function Iterate (Container : Set; Start : Cursor)
1343 return Set_Iterator_Interfaces.Reversible_Iterator'Class
1345 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1348 -- It was formerly the case that when Start = No_Element, the partial
1349 -- iterator was defined to behave the same as for a complete iterator,
1350 -- and iterate over the entire sequence of items. However, those
1351 -- semantics were unintuitive and arguably error-prone (it is too easy
1352 -- to accidentally create an endless loop), and so they were changed,
1353 -- per the ARG meeting in Denver on 2011/11. However, there was no
1354 -- consensus about what positive meaning this corner case should have,
1355 -- and so it was decided to simply raise an exception. This does imply,
1356 -- however, that it is not possible to use a partial iterator to specify
1357 -- an empty sequence of items.
1359 if Start = No_Element then
1360 raise Constraint_Error with
1361 "Start position for iterator equals No_Element";
1364 if Start.Container /= Container'Unrestricted_Access then
1365 raise Program_Error with
1366 "Start cursor of Iterate designates wrong set";
1369 pragma Assert (Vet (Container.Tree, Start.Node),
1370 "Start cursor of Iterate is bad");
1372 -- The value of the Node component influences the behavior of the First
1373 -- and Last selector functions of the iterator object. When the Node
1374 -- component is non-null (as is the case here), it means that this is a
1375 -- partial iteration, over a subset of the complete sequence of
1376 -- items. The iterator object was constructed with a start expression,
1377 -- indicating the position from which the iteration begins. Note that
1378 -- the start position has the same value irrespective of whether this is
1379 -- a forward or reverse iteration.
1383 return It : constant Iterator :=
1384 Iterator'(Limited_Controlled
with
1385 Container
=> Container
'Unrestricted_Access,
1386 Node
=> Start
.Node
);
1393 function Last
(Container
: Set
) return Cursor
is
1396 (if Container
.Tree
.Last
= null then No_Element
1397 else Cursor
'(Container'Unrestricted_Access, Container.Tree.Last));
1400 function Last (Object : Iterator) return Cursor is
1402 -- The value of the iterator object's Node component influences the
1403 -- behavior of the Last (and First) selector function.
1405 -- When the Node component is null, this means the iterator object was
1406 -- constructed without a start expression, in which case the (reverse)
1407 -- iteration starts from the (logical) beginning of the entire sequence
1408 -- (corresponding to Container.Last, for a reverse iterator).
1410 -- Otherwise, this is iteration over a partial sequence of items. When
1411 -- the Node component is non-null, the iterator object was constructed
1412 -- with a start expression, that specifies the position from which the
1413 -- (reverse) partial iteration begins.
1415 if Object.Node = null then
1416 return Object.Container.Last;
1418 return Cursor'(Object
.Container
, Object
.Node
);
1426 function Last_Element
(Container
: Set
) return Element_Type
is
1428 if Container
.Tree
.Last
= null then
1429 raise Constraint_Error
with "set is empty";
1431 return Container
.Tree
.Last
.Element
;
1439 function Left
(Node
: Node_Access
) return Node_Access
is
1448 function Length
(Container
: Set
) return Count_Type
is
1450 return Container
.Tree
.Length
;
1457 procedure Move
is new Tree_Operations
.Generic_Move
(Clear
);
1459 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
1461 Move
(Target
=> Target
.Tree
, Source
=> Source
.Tree
);
1468 function Next
(Position
: Cursor
) return Cursor
is
1470 if Position
= No_Element
then
1474 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1475 "bad cursor in Next");
1478 Node
: constant Node_Access
:=
1479 Tree_Operations
.Next
(Position
.Node
);
1481 return (if Node
= null then No_Element
1482 else Cursor
'(Position.Container, Node));
1486 procedure Next (Position : in out Cursor) is
1488 Position := Next (Position);
1491 function Next (Object : Iterator; Position : Cursor) return Cursor is
1493 if Position.Container = null then
1497 if Position.Container /= Object.Container then
1498 raise Program_Error with
1499 "Position cursor of Next designates wrong set";
1502 return Next (Position);
1509 function Overlap (Left, Right : Set) return Boolean is
1511 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1518 function Parent (Node : Node_Access) return Node_Access is
1527 function Previous (Position : Cursor) return Cursor is
1529 if Position = No_Element then
1533 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1534 "bad cursor in Previous");
1537 Node : constant Node_Access :=
1538 Tree_Operations.Previous (Position.Node);
1540 return (if Node = null then No_Element
1541 else Cursor'(Position
.Container
, Node
));
1545 procedure Previous
(Position
: in out Cursor
) is
1547 Position
:= Previous
(Position
);
1550 function Previous
(Object
: Iterator
; Position
: Cursor
) return Cursor
is
1552 if Position
.Container
= null then
1556 if Position
.Container
/= Object
.Container
then
1557 raise Program_Error
with
1558 "Position cursor of Previous designates wrong set";
1561 return Previous
(Position
);
1568 procedure Query_Element
1570 Process
: not null access procedure (Element
: Element_Type
))
1573 if Position
.Node
= null then
1574 raise Constraint_Error
with "Position cursor equals No_Element";
1577 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1578 "bad cursor in Query_Element");
1581 T
: Tree_Type
renames Position
.Container
.Tree
;
1583 B
: Natural renames T
.Busy
;
1584 L
: Natural renames T
.Lock
;
1591 Process
(Position
.Node
.Element
);
1609 (Stream
: not null access Root_Stream_Type
'Class;
1610 Container
: out Set
)
1613 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
;
1614 pragma Inline
(Read_Node
);
1617 new Tree_Operations
.Generic_Read
(Clear
, Read_Node
);
1624 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
1626 Node
: Node_Access
:= new Node_Type
;
1628 Element_Type
'Read (Stream
, Node
.Element
);
1636 -- Start of processing for Read
1639 Read
(Stream
, Container
.Tree
);
1643 (Stream
: not null access Root_Stream_Type
'Class;
1647 raise Program_Error
with "attempt to stream set cursor";
1651 (Stream
: not null access Root_Stream_Type
'Class;
1652 Item
: out Constant_Reference_Type
)
1655 raise Program_Error
with "attempt to stream reference";
1662 procedure Replace
(Container
: in out Set
; New_Item
: Element_Type
) is
1663 Node
: constant Node_Access
:=
1664 Element_Keys
.Find
(Container
.Tree
, New_Item
);
1668 raise Constraint_Error
with
1669 "attempt to replace element not in set";
1672 if Container
.Tree
.Lock
> 0 then
1673 raise Program_Error
with
1674 "attempt to tamper with elements (set is locked)";
1677 Node
.Element
:= New_Item
;
1680 ---------------------
1681 -- Replace_Element --
1682 ---------------------
1684 procedure Replace_Element
1685 (Tree
: in out Tree_Type
;
1687 Item
: Element_Type
)
1689 pragma Assert
(Node
/= null);
1691 function New_Node
return Node_Access
;
1692 pragma Inline
(New_Node
);
1694 procedure Local_Insert_Post
is
1695 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1697 procedure Local_Insert_Sans_Hint
is
1698 new Element_Keys
.Generic_Conditional_Insert
(Local_Insert_Post
);
1700 procedure Local_Insert_With_Hint
is
1701 new Element_Keys
.Generic_Conditional_Insert_With_Hint
1703 Local_Insert_Sans_Hint
);
1709 function New_Node
return Node_Access
is
1711 Node
.Element
:= Item
;
1713 Node
.Parent
:= null;
1720 Result
: Node_Access
;
1723 -- Start of processing for Replace_Element
1726 if Item
< Node
.Element
or else Node
.Element
< Item
then
1730 if Tree
.Lock
> 0 then
1731 raise Program_Error
with
1732 "attempt to tamper with elements (set is locked)";
1735 Node
.Element
:= Item
;
1739 Hint
:= Element_Keys
.Ceiling
(Tree
, Item
);
1744 elsif Item
< Hint
.Element
then
1746 if Tree
.Lock
> 0 then
1747 raise Program_Error
with
1748 "attempt to tamper with elements (set is locked)";
1751 Node
.Element
:= Item
;
1756 pragma Assert
(not (Hint
.Element
< Item
));
1757 raise Program_Error
with "attempt to replace existing element";
1760 Tree_Operations
.Delete_Node_Sans_Free
(Tree
, Node
); -- Checks busy-bit
1762 Local_Insert_With_Hint
1767 Inserted
=> Inserted
);
1769 pragma Assert
(Inserted
);
1770 pragma Assert
(Result
= Node
);
1771 end Replace_Element
;
1773 procedure Replace_Element
1774 (Container
: in out Set
;
1776 New_Item
: Element_Type
)
1779 if Position
.Node
= null then
1780 raise Constraint_Error
with
1781 "Position cursor equals No_Element";
1784 if Position
.Container
/= Container
'Unrestricted_Access then
1785 raise Program_Error
with
1786 "Position cursor designates wrong set";
1789 pragma Assert
(Vet
(Container
.Tree
, Position
.Node
),
1790 "bad cursor in Replace_Element");
1792 Replace_Element
(Container
.Tree
, Position
.Node
, New_Item
);
1793 end Replace_Element
;
1795 ---------------------
1796 -- Reverse_Iterate --
1797 ---------------------
1799 procedure Reverse_Iterate
1801 Process
: not null access procedure (Position
: Cursor
))
1803 procedure Process_Node
(Node
: Node_Access
);
1804 pragma Inline
(Process_Node
);
1806 procedure Local_Reverse_Iterate
is
1807 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1813 procedure Process_Node
(Node
: Node_Access
) is
1815 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1818 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1819 B : Natural renames T.Busy;
1821 -- Start of processing for Reverse_Iterate
1827 Local_Reverse_Iterate (T);
1835 end Reverse_Iterate;
1841 function Right (Node : Node_Access) return Node_Access is
1850 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1852 Node.Color := Color;
1859 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1868 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1870 Node.Parent := Parent;
1877 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1879 Node.Right := Right;
1882 --------------------------
1883 -- Symmetric_Difference --
1884 --------------------------
1886 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1888 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1889 end Symmetric_Difference;
1891 function Symmetric_Difference (Left, Right : Set) return Set is
1892 Tree : constant Tree_Type :=
1893 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1895 return Set'(Controlled
with Tree
);
1896 end Symmetric_Difference
;
1902 function To_Set
(New_Item
: Element_Type
) return Set
is
1906 pragma Unreferenced
(Node
, Inserted
);
1908 Insert_Sans_Hint
(Tree
, New_Item
, Node
, Inserted
);
1909 return Set
'(Controlled with Tree);
1916 procedure Union (Target : in out Set; Source : Set) is
1918 Set_Ops.Union (Target.Tree, Source.Tree);
1921 function Union (Left, Right : Set) return Set is
1922 Tree : constant Tree_Type :=
1923 Set_Ops.Union (Left.Tree, Right.Tree);
1925 return Set'(Controlled
with Tree
);
1933 (Stream
: not null access Root_Stream_Type
'Class;
1936 procedure Write_Node
1937 (Stream
: not null access Root_Stream_Type
'Class;
1938 Node
: Node_Access
);
1939 pragma Inline
(Write_Node
);
1942 new Tree_Operations
.Generic_Write
(Write_Node
);
1948 procedure Write_Node
1949 (Stream
: not null access Root_Stream_Type
'Class;
1953 Element_Type
'Write (Stream
, Node
.Element
);
1956 -- Start of processing for Write
1959 Write
(Stream
, Container
.Tree
);
1963 (Stream
: not null access Root_Stream_Type
'Class;
1967 raise Program_Error
with "attempt to stream set cursor";
1971 (Stream
: not null access Root_Stream_Type
'Class;
1972 Item
: Constant_Reference_Type
)
1975 raise Program_Error
with "attempt to stream reference";
1978 end Ada
.Containers
.Ordered_Sets
;