1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_SETS --
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
.Containers
.Red_Black_Trees
.Generic_Operations
;
31 pragma Elaborate_All
(Ada
.Containers
.Red_Black_Trees
.Generic_Operations
);
33 with Ada
.Containers
.Red_Black_Trees
.Generic_Keys
;
34 pragma Elaborate_All
(Ada
.Containers
.Red_Black_Trees
.Generic_Keys
);
36 with Ada
.Containers
.Red_Black_Trees
.Generic_Set_Operations
;
37 pragma Elaborate_All
(Ada
.Containers
.Red_Black_Trees
.Generic_Set_Operations
);
39 with Ada
.Unchecked_Deallocation
;
41 with System
; use type System
.Address
;
43 package body Ada
.Containers
.Indefinite_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 -- Local Subprograms --
67 -----------------------
69 function Color
(Node
: Node_Access
) return Color_Type
;
70 pragma Inline
(Color
);
72 function Copy_Node
(Source
: Node_Access
) return Node_Access
;
73 pragma Inline
(Copy_Node
);
75 procedure Free
(X
: in out Node_Access
);
77 procedure Insert_Sans_Hint
78 (Tree
: in out Tree_Type
;
79 New_Item
: Element_Type
;
80 Node
: out Node_Access
;
81 Inserted
: out Boolean);
83 procedure Insert_With_Hint
84 (Dst_Tree
: in out Tree_Type
;
85 Dst_Hint
: Node_Access
;
86 Src_Node
: Node_Access
;
87 Dst_Node
: out Node_Access
);
89 function Is_Greater_Element_Node
91 Right
: Node_Access
) return Boolean;
92 pragma Inline
(Is_Greater_Element_Node
);
94 function Is_Less_Element_Node
96 Right
: Node_Access
) return Boolean;
97 pragma Inline
(Is_Less_Element_Node
);
99 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean;
100 pragma Inline
(Is_Less_Node_Node
);
102 function Left
(Node
: Node_Access
) return Node_Access
;
103 pragma Inline
(Left
);
105 function Parent
(Node
: Node_Access
) return Node_Access
;
106 pragma Inline
(Parent
);
108 procedure Replace_Element
109 (Tree
: in out Tree_Type
;
111 Item
: Element_Type
);
113 function Right
(Node
: Node_Access
) return Node_Access
;
114 pragma Inline
(Right
);
116 procedure Set_Color
(Node
: Node_Access
; Color
: Color_Type
);
117 pragma Inline
(Set_Color
);
119 procedure Set_Left
(Node
: Node_Access
; Left
: Node_Access
);
120 pragma Inline
(Set_Left
);
122 procedure Set_Parent
(Node
: Node_Access
; Parent
: Node_Access
);
123 pragma Inline
(Set_Parent
);
125 procedure Set_Right
(Node
: Node_Access
; Right
: Node_Access
);
126 pragma Inline
(Set_Right
);
128 --------------------------
129 -- Local Instantiations --
130 --------------------------
132 procedure Free_Element
is
133 new Ada
.Unchecked_Deallocation
(Element_Type
, Element_Access
);
135 package Tree_Operations
is
136 new Red_Black_Trees
.Generic_Operations
(Tree_Types
);
138 procedure Delete_Tree
is
139 new Tree_Operations
.Generic_Delete_Tree
(Free
);
141 function Copy_Tree
is
142 new Tree_Operations
.Generic_Copy_Tree
(Copy_Node
, Delete_Tree
);
146 package Element_Keys
is
147 new Red_Black_Trees
.Generic_Keys
148 (Tree_Operations
=> Tree_Operations
,
149 Key_Type
=> Element_Type
,
150 Is_Less_Key_Node
=> Is_Less_Element_Node
,
151 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
154 new Generic_Set_Operations
155 (Tree_Operations
=> Tree_Operations
,
156 Insert_With_Hint
=> Insert_With_Hint
,
157 Copy_Tree
=> Copy_Tree
,
158 Delete_Tree
=> Delete_Tree
,
159 Is_Less
=> Is_Less_Node_Node
,
166 function "<" (Left
, Right
: Cursor
) return Boolean is
168 if Left
.Node
= null then
169 raise Constraint_Error
with "Left cursor equals No_Element";
172 if Right
.Node
= null then
173 raise Constraint_Error
with "Right cursor equals No_Element";
176 if Left
.Node
.Element
= null then
177 raise Program_Error
with "Left cursor is bad";
180 if Right
.Node
.Element
= null then
181 raise Program_Error
with "Right cursor is bad";
184 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
185 "bad Left cursor in ""<""");
187 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
188 "bad Right cursor in ""<""");
190 return Left
.Node
.Element
.all < Right
.Node
.Element
.all;
193 function "<" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
195 if Left
.Node
= null then
196 raise Constraint_Error
with "Left cursor equals No_Element";
199 if Left
.Node
.Element
= null then
200 raise Program_Error
with "Left cursor is bad";
203 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
204 "bad Left cursor in ""<""");
206 return Left
.Node
.Element
.all < Right
;
209 function "<" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
211 if Right
.Node
= null then
212 raise Constraint_Error
with "Right cursor equals No_Element";
215 if Right
.Node
.Element
= null then
216 raise Program_Error
with "Right cursor is bad";
219 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
220 "bad Right cursor in ""<""");
222 return Left
< Right
.Node
.Element
.all;
229 function "=" (Left
, Right
: Set
) return Boolean is
231 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean;
232 pragma Inline
(Is_Equal_Node_Node
);
235 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
237 ------------------------
238 -- Is_Equal_Node_Node --
239 ------------------------
241 function Is_Equal_Node_Node
(L
, R
: Node_Access
) return Boolean is
243 return L
.Element
.all = R
.Element
.all;
244 end Is_Equal_Node_Node
;
246 -- Start of processing for "="
249 return Is_Equal
(Left
.Tree
, Right
.Tree
);
256 function ">" (Left
, Right
: Cursor
) return Boolean is
258 if Left
.Node
= null then
259 raise Constraint_Error
with "Left cursor equals No_Element";
262 if Right
.Node
= null then
263 raise Constraint_Error
with "Right cursor equals No_Element";
266 if Left
.Node
.Element
= null then
267 raise Program_Error
with "Left cursor is bad";
270 if Right
.Node
.Element
= null then
271 raise Program_Error
with "Right cursor is bad";
274 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
275 "bad Left cursor in "">""");
277 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
278 "bad Right cursor in "">""");
280 -- L > R same as R < L
282 return Right
.Node
.Element
.all < Left
.Node
.Element
.all;
285 function ">" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
287 if Left
.Node
= null then
288 raise Constraint_Error
with "Left cursor equals No_Element";
291 if Left
.Node
.Element
= null then
292 raise Program_Error
with "Left cursor is bad";
295 pragma Assert
(Vet
(Left
.Container
.Tree
, Left
.Node
),
296 "bad Left cursor in "">""");
298 return Right
< Left
.Node
.Element
.all;
301 function ">" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
303 if Right
.Node
= null then
304 raise Constraint_Error
with "Right cursor equals No_Element";
307 if Right
.Node
.Element
= null then
308 raise Program_Error
with "Right cursor is bad";
311 pragma Assert
(Vet
(Right
.Container
.Tree
, Right
.Node
),
312 "bad Right cursor in "">""");
314 return Right
.Node
.Element
.all < Left
;
321 procedure Adjust
is new Tree_Operations
.Generic_Adjust
(Copy_Tree
);
323 procedure Adjust
(Container
: in out Set
) is
325 Adjust
(Container
.Tree
);
328 procedure Adjust
(Control
: in out Reference_Control_Type
) is
330 if Control
.Container
/= null then
332 Tree
: Tree_Type
renames Control
.Container
.all.Tree
;
333 B
: Natural renames Tree
.Busy
;
334 L
: Natural renames Tree
.Lock
;
346 procedure Assign
(Target
: in out Set
; Source
: Set
) is
348 if Target
'Address = Source
'Address then
353 Target
.Union
(Source
);
360 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
361 Node
: constant Node_Access
:=
362 Element_Keys
.Ceiling
(Container
.Tree
, Item
);
364 return (if Node
= null then No_Element
365 else Cursor
'(Container'Unrestricted_Access, Node));
373 new Tree_Operations.Generic_Clear (Delete_Tree);
375 procedure Clear (Container : in out Set) is
377 Clear (Container.Tree);
384 function Color (Node : Node_Access) return Color_Type is
389 ------------------------
390 -- Constant_Reference --
391 ------------------------
393 function Constant_Reference
394 (Container : aliased Set;
395 Position : Cursor) return Constant_Reference_Type
398 if Position.Container = null then
399 raise Constraint_Error with "Position cursor has no element";
402 if Position.Container /= Container'Unrestricted_Access then
403 raise Program_Error with
404 "Position cursor designates wrong container";
407 if Position.Node.Element = null then
408 raise Program_Error with "Node has no element";
412 (Vet (Container.Tree, Position.Node),
413 "bad cursor in Constant_Reference");
416 Tree : Tree_Type renames Position.Container.all.Tree;
417 B : Natural renames Tree.Busy;
418 L : Natural renames Tree.Lock;
420 return R : constant Constant_Reference_Type :=
421 (Element => Position.Node.Element.all'Access,
422 Control => (Controlled with Container'Unrestricted_Access))
428 end Constant_Reference;
434 function Contains (Container : Set; Item : Element_Type) return Boolean is
436 return Find (Container, Item) /= No_Element;
443 function Copy (Source : Set) return Set is
445 return Target : Set do
446 Target.Assign (Source);
454 function Copy_Node (Source : Node_Access) return Node_Access is
455 Element : Element_Access := new Element_Type'(Source
.Element
.all);
458 return new Node_Type
'(Parent => null,
461 Color => Source.Color,
465 Free_Element (Element);
473 procedure Delete (Container : in out Set; Position : in out Cursor) is
475 if Position.Node = null then
476 raise Constraint_Error with "Position cursor equals No_Element";
479 if Position.Node.Element = null then
480 raise Program_Error with "Position cursor is bad";
483 if Position.Container /= Container'Unrestricted_Access then
484 raise Program_Error with "Position cursor designates wrong set";
487 pragma Assert (Vet (Container.Tree, Position.Node),
488 "bad cursor in Delete");
490 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
491 Free (Position.Node);
492 Position.Container := null;
495 procedure Delete (Container : in out Set; Item : Element_Type) is
496 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
500 raise Constraint_Error with "attempt to delete element not in set";
503 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
511 procedure Delete_First (Container : in out Set) is
512 Tree : Tree_Type renames Container.Tree;
513 X : Node_Access := Tree.First;
516 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
525 procedure Delete_Last (Container : in out Set) is
526 Tree : Tree_Type renames Container.Tree;
527 X : Node_Access := Tree.Last;
530 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
539 procedure Difference (Target : in out Set; Source : Set) is
541 Set_Ops.Difference (Target.Tree, Source.Tree);
544 function Difference (Left, Right : Set) return Set is
545 Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
547 return Set'(Controlled
with Tree
);
554 function Element
(Position
: Cursor
) return Element_Type
is
556 if Position
.Node
= null then
557 raise Constraint_Error
with "Position cursor equals No_Element";
560 if Position
.Node
.Element
= null then
561 raise Program_Error
with "Position cursor is bad";
564 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
565 "bad cursor in Element");
567 return Position
.Node
.Element
.all;
570 -------------------------
571 -- Equivalent_Elements --
572 -------------------------
574 function Equivalent_Elements
(Left
, Right
: Element_Type
) return Boolean is
576 if Left
< Right
or else Right
< Left
then
581 end Equivalent_Elements
;
583 ---------------------
584 -- Equivalent_Sets --
585 ---------------------
587 function Equivalent_Sets
(Left
, Right
: Set
) return Boolean is
589 function Is_Equivalent_Node_Node
(L
, R
: Node_Access
) return Boolean;
590 pragma Inline
(Is_Equivalent_Node_Node
);
592 function Is_Equivalent
is
593 new Tree_Operations
.Generic_Equal
(Is_Equivalent_Node_Node
);
595 -----------------------------
596 -- Is_Equivalent_Node_Node --
597 -----------------------------
599 function Is_Equivalent_Node_Node
(L
, R
: Node_Access
) return Boolean is
601 if L
.Element
.all < R
.Element
.all then
603 elsif R
.Element
.all < L
.Element
.all then
608 end Is_Equivalent_Node_Node
;
610 -- Start of processing for Equivalent_Sets
613 return Is_Equivalent
(Left
.Tree
, Right
.Tree
);
620 procedure Exclude
(Container
: in out Set
; Item
: Element_Type
) is
621 X
: Node_Access
:= Element_Keys
.Find
(Container
.Tree
, Item
);
624 Tree_Operations
.Delete_Node_Sans_Free
(Container
.Tree
, X
);
633 procedure Finalize
(Object
: in out Iterator
) is
635 if Object
.Container
/= null then
637 B
: Natural renames Object
.Container
.all.Tree
.Busy
;
644 procedure Finalize
(Control
: in out Reference_Control_Type
) is
646 if Control
.Container
/= null then
648 Tree
: Tree_Type
renames Control
.Container
.all.Tree
;
649 B
: Natural renames Tree
.Busy
;
650 L
: Natural renames Tree
.Lock
;
656 Control
.Container
:= null;
664 function Find
(Container
: Set
; Item
: Element_Type
) return Cursor
is
665 Node
: constant Node_Access
:= Element_Keys
.Find
(Container
.Tree
, Item
);
670 return Cursor
'(Container'Unrestricted_Access, Node);
678 function First (Container : Set) return Cursor is
681 (if Container.Tree.First = null then No_Element
682 else Cursor'(Container
'Unrestricted_Access, Container
.Tree
.First
));
685 function First
(Object
: Iterator
) return Cursor
is
687 -- The value of the iterator object's Node component influences the
688 -- behavior of the First (and Last) selector function.
690 -- When the Node component is null, this means the iterator object was
691 -- constructed without a start expression, in which case the (forward)
692 -- iteration starts from the (logical) beginning of the entire sequence
693 -- of items (corresponding to Container.First, for a forward iterator).
695 -- Otherwise, this is iteration over a partial sequence of items. When
696 -- the Node component is non-null, the iterator object was constructed
697 -- with a start expression, that specifies the position from which the
698 -- (forward) partial iteration begins.
700 if Object
.Node
= null then
701 return Object
.Container
.First
;
703 return Cursor
'(Object.Container, Object.Node);
711 function First_Element (Container : Set) return Element_Type is
713 if Container.Tree.First = null then
714 raise Constraint_Error with "set is empty";
716 return Container.Tree.First.Element.all;
724 function Floor (Container : Set; Item : Element_Type) return Cursor is
725 Node : constant Node_Access := Element_Keys.Floor (Container.Tree, Item);
727 return (if Node = null then No_Element
728 else Cursor'(Container
'Unrestricted_Access, Node
));
735 procedure Free
(X
: in out Node_Access
) is
736 procedure Deallocate
is
737 new Ada
.Unchecked_Deallocation
(Node_Type
, Node_Access
);
749 Free_Element
(X
.Element
);
764 package body Generic_Keys
is
766 -----------------------
767 -- Local Subprograms --
768 -----------------------
770 function Is_Greater_Key_Node
772 Right
: Node_Access
) return Boolean;
773 pragma Inline
(Is_Greater_Key_Node
);
775 function Is_Less_Key_Node
777 Right
: Node_Access
) return Boolean;
778 pragma Inline
(Is_Less_Key_Node
);
780 --------------------------
781 -- Local Instantiations --
782 --------------------------
785 new Red_Black_Trees
.Generic_Keys
786 (Tree_Operations
=> Tree_Operations
,
787 Key_Type
=> Key_Type
,
788 Is_Less_Key_Node
=> Is_Less_Key_Node
,
789 Is_Greater_Key_Node
=> Is_Greater_Key_Node
);
795 function Ceiling
(Container
: Set
; Key
: Key_Type
) return Cursor
is
796 Node
: constant Node_Access
:= Key_Keys
.Ceiling
(Container
.Tree
, Key
);
798 return (if Node
= null then No_Element
799 else Cursor
'(Container'Unrestricted_Access, Node));
802 ------------------------
803 -- Constant_Reference --
804 ------------------------
806 function Constant_Reference
807 (Container : aliased Set;
808 Key : Key_Type) return Constant_Reference_Type
810 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
814 raise Constraint_Error with "Key not in set";
817 if Node.Element = null then
818 raise Program_Error with "Node has no element";
822 Tree : Tree_Type renames Container'Unrestricted_Access.all.Tree;
823 B : Natural renames Tree.Busy;
824 L : Natural renames Tree.Lock;
826 return R : constant Constant_Reference_Type :=
827 (Element => Node.Element.all'Access,
828 Control => (Controlled with Container'Unrestricted_Access))
834 end Constant_Reference;
840 function Contains (Container : Set; Key : Key_Type) return Boolean is
842 return Find (Container, Key) /= No_Element;
849 procedure Delete (Container : in out Set; Key : Key_Type) is
850 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
854 raise Constraint_Error with "attempt to delete key not in set";
857 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
865 function Element (Container : Set; Key : Key_Type) return Element_Type is
866 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
869 raise Constraint_Error with "key not in set";
871 return Node.Element.all;
875 ---------------------
876 -- Equivalent_Keys --
877 ---------------------
879 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
881 if Left < Right or else Right < Left then
892 procedure Exclude (Container : in out Set; Key : Key_Type) is
893 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
896 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
905 function Find (Container : Set; Key : Key_Type) return Cursor is
906 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
908 return (if Node = null then No_Element
909 else Cursor'(Container
'Unrestricted_Access, Node
));
916 function Floor
(Container
: Set
; Key
: Key_Type
) return Cursor
is
917 Node
: constant Node_Access
:= Key_Keys
.Floor
(Container
.Tree
, Key
);
919 return (if Node
= null then No_Element
920 else Cursor
'(Container'Unrestricted_Access, Node));
923 -------------------------
924 -- Is_Greater_Key_Node --
925 -------------------------
927 function Is_Greater_Key_Node
929 Right : Node_Access) return Boolean
932 return Key (Right.Element.all) < Left;
933 end Is_Greater_Key_Node;
935 ----------------------
936 -- Is_Less_Key_Node --
937 ----------------------
939 function Is_Less_Key_Node
941 Right : Node_Access) return Boolean
944 return Left < Key (Right.Element.all);
945 end Is_Less_Key_Node;
951 function Key (Position : Cursor) return Key_Type is
953 if Position.Node = null then
954 raise Constraint_Error with
955 "Position cursor equals No_Element";
958 if Position.Node.Element = null then
959 raise Program_Error with
960 "Position cursor is bad";
963 pragma Assert (Vet (Position.Container.Tree, Position.Node),
964 "bad cursor in Key");
966 return Key (Position.Node.Element.all);
974 (Container : in out Set;
976 New_Item : Element_Type)
978 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
982 raise Constraint_Error with
983 "attempt to replace key not in set";
986 Replace_Element (Container.Tree, Node, New_Item);
994 (Stream : not null access Root_Stream_Type'Class;
995 Item : out Reference_Type)
998 raise Program_Error with "attempt to stream reference";
1001 ------------------------------
1002 -- Reference_Preserving_Key --
1003 ------------------------------
1005 function Reference_Preserving_Key
1006 (Container : aliased in out Set;
1007 Position : Cursor) return Reference_Type
1010 if Position.Container = null then
1011 raise Constraint_Error with "Position cursor has no element";
1014 if Position.Container /= Container'Unrestricted_Access then
1015 raise Program_Error with
1016 "Position cursor designates wrong container";
1019 if Position.Node.Element = null then
1020 raise Program_Error with "Node has no element";
1024 (Vet (Container.Tree, Position.Node),
1025 "bad cursor in function Reference_Preserving_Key");
1027 -- Some form of finalization will be required in order to actually
1028 -- check that the key-part of the element designated by Position has
1031 return (Element => Position.Node.Element.all'Access);
1032 end Reference_Preserving_Key;
1034 function Reference_Preserving_Key
1035 (Container : aliased in out Set;
1036 Key : Key_Type) return Reference_Type
1038 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
1042 raise Constraint_Error with "Key not in set";
1045 if Node.Element = null then
1046 raise Program_Error with "Node has no element";
1049 -- Some form of finalization will be required in order to actually
1050 -- check that the key-part of the element designated by Key has not
1053 return (Element => Node.Element.all'Access);
1054 end Reference_Preserving_Key;
1056 -----------------------------------
1057 -- Update_Element_Preserving_Key --
1058 -----------------------------------
1060 procedure Update_Element_Preserving_Key
1061 (Container : in out Set;
1063 Process : not null access
1064 procedure (Element : in out Element_Type))
1066 Tree : Tree_Type renames Container.Tree;
1069 if Position.Node = null then
1070 raise Constraint_Error with "Position cursor equals No_Element";
1073 if Position.Node.Element = null then
1074 raise Program_Error with "Position cursor is bad";
1077 if Position.Container /= Container'Unrestricted_Access then
1078 raise Program_Error with "Position cursor designates wrong set";
1081 pragma Assert (Vet (Container.Tree, Position.Node),
1082 "bad cursor in Update_Element_Preserving_Key");
1085 E : Element_Type renames Position.Node.Element.all;
1086 K : constant Key_Type := Key (E);
1088 B : Natural renames Tree.Busy;
1089 L : Natural renames Tree.Lock;
1107 if Equivalent_Keys (K, Key (E)) then
1113 X : Node_Access := Position.Node;
1115 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
1119 raise Program_Error with "key was modified";
1120 end Update_Element_Preserving_Key;
1127 (Stream : not null access Root_Stream_Type'Class;
1128 Item : Reference_Type)
1131 raise Program_Error with "attempt to stream reference";
1140 function Has_Element (Position : Cursor) return Boolean is
1142 return Position /= No_Element;
1149 procedure Include (Container : in out Set; New_Item : Element_Type) is
1156 Insert (Container, New_Item, Position, Inserted);
1158 if not Inserted then
1159 if Container.Tree.Lock > 0 then
1160 raise Program_Error with
1161 "attempt to tamper with elements (set is locked)";
1165 -- The element allocator may need an accessibility check in the
1166 -- case the actual type is class-wide or has access discriminants
1167 -- (see RM 4.8(10.1) and AI12-0035).
1169 pragma Unsuppress (Accessibility_Check);
1172 X := Position.Node.Element;
1173 Position.Node.Element := new Element_Type'(New_Item
);
1184 (Container
: in out Set
;
1185 New_Item
: Element_Type
;
1186 Position
: out Cursor
;
1187 Inserted
: out Boolean)
1196 Position
.Container
:= Container
'Unrestricted_Access;
1199 procedure Insert
(Container
: in out Set
; New_Item
: Element_Type
) is
1201 pragma Unreferenced
(Position
);
1206 Insert
(Container
, New_Item
, Position
, Inserted
);
1208 if not Inserted
then
1209 raise Constraint_Error
with
1210 "attempt to insert element already in set";
1214 ----------------------
1215 -- Insert_Sans_Hint --
1216 ----------------------
1218 procedure Insert_Sans_Hint
1219 (Tree
: in out Tree_Type
;
1220 New_Item
: Element_Type
;
1221 Node
: out Node_Access
;
1222 Inserted
: out Boolean)
1224 function New_Node
return Node_Access
;
1225 pragma Inline
(New_Node
);
1227 procedure Insert_Post
is
1228 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1230 procedure Conditional_Insert_Sans_Hint
is
1231 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1237 function New_Node
return Node_Access
is
1238 -- The element allocator may need an accessibility check in the case
1239 -- the actual type is class-wide or has access discriminants (see
1240 -- RM 4.8(10.1) and AI12-0035).
1242 pragma Unsuppress
(Accessibility_Check
);
1244 Element
: Element_Access
:= new Element_Type
'(New_Item);
1247 return new Node_Type'(Parent
=> null,
1250 Color
=> Red_Black_Trees
.Red
,
1251 Element
=> Element
);
1255 Free_Element
(Element
);
1259 -- Start of processing for Insert_Sans_Hint
1262 Conditional_Insert_Sans_Hint
1267 end Insert_Sans_Hint
;
1269 ----------------------
1270 -- Insert_With_Hint --
1271 ----------------------
1273 procedure Insert_With_Hint
1274 (Dst_Tree
: in out Tree_Type
;
1275 Dst_Hint
: Node_Access
;
1276 Src_Node
: Node_Access
;
1277 Dst_Node
: out Node_Access
)
1280 pragma Unreferenced
(Success
);
1282 function New_Node
return Node_Access
;
1284 procedure Insert_Post
is
1285 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1287 procedure Insert_Sans_Hint
is
1288 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1290 procedure Insert_With_Hint
is
1291 new Element_Keys
.Generic_Conditional_Insert_With_Hint
1299 function New_Node
return Node_Access
is
1300 Element
: Element_Access
:= new Element_Type
'(Src_Node.Element.all);
1305 Node := new Node_Type;
1308 Free_Element (Element);
1312 Node.Element := Element;
1316 -- Start of processing for Insert_With_Hint
1322 Src_Node.Element.all,
1325 end Insert_With_Hint;
1331 procedure Intersection (Target : in out Set; Source : Set) is
1333 Set_Ops.Intersection (Target.Tree, Source.Tree);
1336 function Intersection (Left, Right : Set) return Set is
1337 Tree : constant Tree_Type :=
1338 Set_Ops.Intersection (Left.Tree, Right.Tree);
1340 return Set'(Controlled
with Tree
);
1347 function Is_Empty
(Container
: Set
) return Boolean is
1349 return Container
.Tree
.Length
= 0;
1352 -----------------------------
1353 -- Is_Greater_Element_Node --
1354 -----------------------------
1356 function Is_Greater_Element_Node
1357 (Left
: Element_Type
;
1358 Right
: Node_Access
) return Boolean
1361 -- e > node same as node < e
1363 return Right
.Element
.all < Left
;
1364 end Is_Greater_Element_Node
;
1366 --------------------------
1367 -- Is_Less_Element_Node --
1368 --------------------------
1370 function Is_Less_Element_Node
1371 (Left
: Element_Type
;
1372 Right
: Node_Access
) return Boolean
1375 return Left
< Right
.Element
.all;
1376 end Is_Less_Element_Node
;
1378 -----------------------
1379 -- Is_Less_Node_Node --
1380 -----------------------
1382 function Is_Less_Node_Node
(L
, R
: Node_Access
) return Boolean is
1384 return L
.Element
.all < R
.Element
.all;
1385 end Is_Less_Node_Node
;
1391 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean is
1393 return Set_Ops
.Is_Subset
(Subset
=> Subset
.Tree
, Of_Set
=> Of_Set
.Tree
);
1402 Process
: not null access procedure (Position
: Cursor
))
1404 procedure Process_Node
(Node
: Node_Access
);
1405 pragma Inline
(Process_Node
);
1407 procedure Local_Iterate
is
1408 new Tree_Operations
.Generic_Iteration
(Process_Node
);
1414 procedure Process_Node
(Node
: Node_Access
) is
1416 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1419 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
1420 B : Natural renames T.Busy;
1422 -- Start of processing for Iterate
1440 return Set_Iterator_Interfaces.Reversible_Iterator'class
1442 B : Natural renames Container'Unrestricted_Access.all.Tree.Busy;
1445 -- The value of the Node component influences the behavior of the First
1446 -- and Last selector functions of the iterator object. When the Node
1447 -- component is null (as is the case here), this means the iterator
1448 -- object was constructed without a start expression. This is a complete
1449 -- iterator, meaning that the iteration starts from the (logical)
1450 -- beginning of the sequence of items.
1452 -- Note: For a forward iterator, Container.First is the beginning, and
1453 -- for a reverse iterator, Container.Last is the beginning.
1455 return It : constant Iterator :=
1456 Iterator'(Limited_Controlled
with
1457 Container
=> Container
'Unrestricted_Access,
1467 return Set_Iterator_Interfaces
.Reversible_Iterator
'class
1469 B
: Natural renames Container
'Unrestricted_Access.all.Tree
.Busy
;
1472 -- It was formerly the case that when Start = No_Element, the partial
1473 -- iterator was defined to behave the same as for a complete iterator,
1474 -- and iterate over the entire sequence of items. However, those
1475 -- semantics were unintuitive and arguably error-prone (it is too easy
1476 -- to accidentally create an endless loop), and so they were changed,
1477 -- per the ARG meeting in Denver on 2011/11. However, there was no
1478 -- consensus about what positive meaning this corner case should have,
1479 -- and so it was decided to simply raise an exception. This does imply,
1480 -- however, that it is not possible to use a partial iterator to specify
1481 -- an empty sequence of items.
1483 if Start
= No_Element
then
1484 raise Constraint_Error
with
1485 "Start position for iterator equals No_Element";
1488 if Start
.Container
/= Container
'Unrestricted_Access then
1489 raise Program_Error
with
1490 "Start cursor of Iterate designates wrong set";
1493 pragma Assert
(Vet
(Container
.Tree
, Start
.Node
),
1494 "Start cursor of Iterate is bad");
1496 -- The value of the Node component influences the behavior of the First
1497 -- and Last selector functions of the iterator object. When the Node
1498 -- component is non-null (as is the case here), it means that this is a
1499 -- partial iteration, over a subset of the complete sequence of
1500 -- items. The iterator object was constructed with a start expression,
1501 -- indicating the position from which the iteration begins. Note that
1502 -- the start position has the same value irrespective of whether this is
1503 -- a forward or reverse iteration.
1505 return It
: constant Iterator
:=
1506 (Limited_Controlled
with
1507 Container
=> Container
'Unrestricted_Access,
1518 function Last
(Container
: Set
) return Cursor
is
1521 (if Container
.Tree
.Last
= null then No_Element
1522 else Cursor
'(Container'Unrestricted_Access, Container.Tree.Last));
1525 function Last (Object : Iterator) return Cursor is
1527 -- The value of the iterator object's Node component influences the
1528 -- behavior of the Last (and First) selector function.
1530 -- When the Node component is null, this means the iterator object was
1531 -- constructed without a start expression, in which case the (reverse)
1532 -- iteration starts from the (logical) beginning of the entire sequence
1533 -- (corresponding to Container.Last, for a reverse iterator).
1535 -- Otherwise, this is iteration over a partial sequence of items. When
1536 -- the Node component is non-null, the iterator object was constructed
1537 -- with a start expression, that specifies the position from which the
1538 -- (reverse) partial iteration begins.
1540 if Object.Node = null then
1541 return Object.Container.Last;
1543 return Cursor'(Object
.Container
, Object
.Node
);
1551 function Last_Element
(Container
: Set
) return Element_Type
is
1553 if Container
.Tree
.Last
= null then
1554 raise Constraint_Error
with "set is empty";
1556 return Container
.Tree
.Last
.Element
.all;
1564 function Left
(Node
: Node_Access
) return Node_Access
is
1573 function Length
(Container
: Set
) return Count_Type
is
1575 return Container
.Tree
.Length
;
1582 procedure Move
is new Tree_Operations
.Generic_Move
(Clear
);
1584 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
1586 Move
(Target
=> Target
.Tree
, Source
=> Source
.Tree
);
1593 procedure Next
(Position
: in out Cursor
) is
1595 Position
:= Next
(Position
);
1598 function Next
(Position
: Cursor
) return Cursor
is
1600 if Position
= No_Element
then
1604 if Position
.Node
.Element
= null then
1605 raise Program_Error
with "Position cursor is bad";
1608 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1609 "bad cursor in Next");
1612 Node
: constant Node_Access
:= Tree_Operations
.Next
(Position
.Node
);
1614 return (if Node
= null then No_Element
1615 else Cursor
'(Position.Container, Node));
1621 Position : Cursor) return Cursor
1624 if Position.Container = null then
1628 if Position.Container /= Object.Container then
1629 raise Program_Error with
1630 "Position cursor of Next designates wrong set";
1633 return Next (Position);
1640 function Overlap (Left, Right : Set) return Boolean is
1642 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1649 function Parent (Node : Node_Access) return Node_Access is
1658 procedure Previous (Position : in out Cursor) is
1660 Position := Previous (Position);
1663 function Previous (Position : Cursor) return Cursor is
1665 if Position = No_Element then
1669 if Position.Node.Element = null then
1670 raise Program_Error with "Position cursor is bad";
1673 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1674 "bad cursor in Previous");
1677 Node : constant Node_Access :=
1678 Tree_Operations.Previous (Position.Node);
1680 return (if Node = null then No_Element
1681 else Cursor'(Position
.Container
, Node
));
1687 Position
: Cursor
) return Cursor
1690 if Position
.Container
= null then
1694 if Position
.Container
/= Object
.Container
then
1695 raise Program_Error
with
1696 "Position cursor of Previous designates wrong set";
1699 return Previous
(Position
);
1706 procedure Query_Element
1708 Process
: not null access procedure (Element
: Element_Type
))
1711 if Position
.Node
= null then
1712 raise Constraint_Error
with "Position cursor equals No_Element";
1715 if Position
.Node
.Element
= null then
1716 raise Program_Error
with "Position cursor is bad";
1719 pragma Assert
(Vet
(Position
.Container
.Tree
, Position
.Node
),
1720 "bad cursor in Query_Element");
1723 T
: Tree_Type
renames Position
.Container
.Tree
;
1725 B
: Natural renames T
.Busy
;
1726 L
: Natural renames T
.Lock
;
1733 Process
(Position
.Node
.Element
.all);
1751 (Stream
: not null access Root_Stream_Type
'Class;
1752 Container
: out Set
)
1755 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
;
1756 pragma Inline
(Read_Node
);
1759 new Tree_Operations
.Generic_Read
(Clear
, Read_Node
);
1766 (Stream
: not null access Root_Stream_Type
'Class) return Node_Access
1768 Node
: Node_Access
:= new Node_Type
;
1771 Node
.Element
:= new Element_Type
'(Element_Type'Input (Stream));
1776 Free (Node); -- Note that Free deallocates elem too
1780 -- Start of processing for Read
1783 Read (Stream, Container.Tree);
1787 (Stream : not null access Root_Stream_Type'Class;
1791 raise Program_Error with "attempt to stream set cursor";
1795 (Stream : not null access Root_Stream_Type'Class;
1796 Item : out Constant_Reference_Type)
1799 raise Program_Error with "attempt to stream reference";
1806 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1807 Node : constant Node_Access :=
1808 Element_Keys.Find (Container.Tree, New_Item);
1811 pragma Warnings (Off, X);
1815 raise Constraint_Error with "attempt to replace element not in set";
1818 if Container.Tree.Lock > 0 then
1819 raise Program_Error with
1820 "attempt to tamper with elements (set is locked)";
1824 -- The element allocator may need an accessibility check in the case
1825 -- the actual type is class-wide or has access discriminants (see
1826 -- RM 4.8(10.1) and AI12-0035).
1828 pragma Unsuppress (Accessibility_Check);
1832 Node.Element := new Element_Type'(New_Item
);
1837 ---------------------
1838 -- Replace_Element --
1839 ---------------------
1841 procedure Replace_Element
1842 (Tree
: in out Tree_Type
;
1844 Item
: Element_Type
)
1846 pragma Assert
(Node
/= null);
1847 pragma Assert
(Node
.Element
/= null);
1849 function New_Node
return Node_Access
;
1850 pragma Inline
(New_Node
);
1852 procedure Local_Insert_Post
is
1853 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1855 procedure Local_Insert_Sans_Hint
is
1856 new Element_Keys
.Generic_Conditional_Insert
(Local_Insert_Post
);
1858 procedure Local_Insert_With_Hint
is
1859 new Element_Keys
.Generic_Conditional_Insert_With_Hint
1861 Local_Insert_Sans_Hint
);
1867 function New_Node
return Node_Access
is
1869 -- The element allocator may need an accessibility check in the case
1870 -- the actual type is class-wide or has access discriminants (see
1871 -- RM 4.8(10.1) and AI12-0035).
1873 pragma Unsuppress
(Accessibility_Check
);
1876 Node
.Element
:= new Element_Type
'(Item); -- OK if fails
1878 Node.Parent := null;
1885 Result : Node_Access;
1888 X : Element_Access := Node.Element;
1890 -- Start of processing for Replace_Element
1893 if Item < Node.Element.all or else Node.Element.all < Item then
1897 if Tree.Lock > 0 then
1898 raise Program_Error with
1899 "attempt to tamper with elements (set is locked)";
1903 -- The element allocator may need an accessibility check in the
1904 -- case the actual type is class-wide or has access discriminants
1905 -- (see RM 4.8(10.1) and AI12-0035).
1907 pragma Unsuppress (Accessibility_Check);
1910 Node.Element := new Element_Type'(Item
);
1917 Hint
:= Element_Keys
.Ceiling
(Tree
, Item
);
1922 elsif Item
< Hint
.Element
.all then
1924 if Tree
.Lock
> 0 then
1925 raise Program_Error
with
1926 "attempt to tamper with elements (set is locked)";
1930 -- The element allocator may need an accessibility check in the
1931 -- case actual type is class-wide or has access discriminants
1932 -- (see RM 4.8(10.1) and AI12-0035).
1934 pragma Unsuppress
(Accessibility_Check
);
1937 Node
.Element
:= new Element_Type
'(Item);
1945 pragma Assert (not (Hint.Element.all < Item));
1946 raise Program_Error with "attempt to replace existing element";
1949 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1951 Local_Insert_With_Hint
1956 Inserted => Inserted);
1958 pragma Assert (Inserted);
1959 pragma Assert (Result = Node);
1962 end Replace_Element;
1964 procedure Replace_Element
1965 (Container : in out Set;
1967 New_Item : Element_Type)
1970 if Position.Node = null then
1971 raise Constraint_Error with "Position cursor equals No_Element";
1974 if Position.Node.Element = null then
1975 raise Program_Error with "Position cursor is bad";
1978 if Position.Container /= Container'Unrestricted_Access then
1979 raise Program_Error with "Position cursor designates wrong set";
1982 pragma Assert (Vet (Container.Tree, Position.Node),
1983 "bad cursor in Replace_Element");
1985 Replace_Element (Container.Tree, Position.Node, New_Item);
1986 end Replace_Element;
1988 ---------------------
1989 -- Reverse_Iterate --
1990 ---------------------
1992 procedure Reverse_Iterate
1994 Process : not null access procedure (Position : Cursor))
1996 procedure Process_Node (Node : Node_Access);
1997 pragma Inline (Process_Node);
1999 procedure Local_Reverse_Iterate is
2000 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
2006 procedure Process_Node (Node : Node_Access) is
2008 Process (Cursor'(Container
'Unrestricted_Access, Node
));
2011 T
: Tree_Type
renames Container
.Tree
'Unrestricted_Access.all;
2012 B
: Natural renames T
.Busy
;
2014 -- Start of processing for Reverse_Iterate
2020 Local_Reverse_Iterate
(T
);
2028 end Reverse_Iterate
;
2034 function Right
(Node
: Node_Access
) return Node_Access
is
2043 procedure Set_Color
(Node
: Node_Access
; Color
: Color_Type
) is
2045 Node
.Color
:= Color
;
2052 procedure Set_Left
(Node
: Node_Access
; Left
: Node_Access
) is
2061 procedure Set_Parent
(Node
: Node_Access
; Parent
: Node_Access
) is
2063 Node
.Parent
:= Parent
;
2070 procedure Set_Right
(Node
: Node_Access
; Right
: Node_Access
) is
2072 Node
.Right
:= Right
;
2075 --------------------------
2076 -- Symmetric_Difference --
2077 --------------------------
2079 procedure Symmetric_Difference
(Target
: in out Set
; Source
: Set
) is
2081 Set_Ops
.Symmetric_Difference
(Target
.Tree
, Source
.Tree
);
2082 end Symmetric_Difference
;
2084 function Symmetric_Difference
(Left
, Right
: Set
) return Set
is
2085 Tree
: constant Tree_Type
:=
2086 Set_Ops
.Symmetric_Difference
(Left
.Tree
, Right
.Tree
);
2088 return Set
'(Controlled with Tree);
2089 end Symmetric_Difference;
2095 function To_Set (New_Item : Element_Type) return Set is
2099 pragma Unreferenced (Node, Inserted);
2101 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
2102 return Set'(Controlled
with Tree
);
2109 procedure Union
(Target
: in out Set
; Source
: Set
) is
2111 Set_Ops
.Union
(Target
.Tree
, Source
.Tree
);
2114 function Union
(Left
, Right
: Set
) return Set
is
2115 Tree
: constant Tree_Type
:= Set_Ops
.Union
(Left
.Tree
, Right
.Tree
);
2117 return Set
'(Controlled with Tree);
2125 (Stream : not null access Root_Stream_Type'Class;
2128 procedure Write_Node
2129 (Stream : not null access Root_Stream_Type'Class;
2130 Node : Node_Access);
2131 pragma Inline (Write_Node);
2134 new Tree_Operations.Generic_Write (Write_Node);
2140 procedure Write_Node
2141 (Stream : not null access Root_Stream_Type'Class;
2145 Element_Type'Output (Stream, Node.Element.all);
2148 -- Start of processing for Write
2151 Write (Stream, Container.Tree);
2155 (Stream : not null access Root_Stream_Type'Class;
2159 raise Program_Error with "attempt to stream set cursor";
2163 (Stream : not null access Root_Stream_Type'Class;
2164 Item : Constant_Reference_Type)
2167 raise Program_Error with "attempt to stream reference";
2170 end Ada.Containers.Indefinite_Ordered_Sets;