1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . B O U N D E D _ 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
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
;
32 (Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
);
34 with Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Keys
;
35 pragma Elaborate_All
(Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Keys
);
37 with Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Set_Operations
;
39 (Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Set_Operations
);
41 with System
; use type System
.Address
;
43 package body Ada
.Containers
.Bounded_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_Type
) return Red_Black_Trees
.Color_Type
;
55 pragma Inline
(Color
);
57 function Left
(Node
: Node_Type
) return Count_Type
;
60 function Parent
(Node
: Node_Type
) return Count_Type
;
61 pragma Inline
(Parent
);
63 function Right
(Node
: Node_Type
) return Count_Type
;
64 pragma Inline
(Right
);
67 (Node
: in out Node_Type
;
68 Color
: Red_Black_Trees
.Color_Type
);
69 pragma Inline
(Set_Color
);
71 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
);
72 pragma Inline
(Set_Left
);
74 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
);
75 pragma Inline
(Set_Right
);
77 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
);
78 pragma Inline
(Set_Parent
);
80 -----------------------
81 -- Local Subprograms --
82 -----------------------
84 procedure Insert_Sans_Hint
85 (Container
: in out Set
;
86 New_Item
: Element_Type
;
87 Node
: out Count_Type
;
88 Inserted
: out Boolean);
90 procedure Insert_With_Hint
91 (Dst_Set
: in out Set
;
92 Dst_Hint
: Count_Type
;
94 Dst_Node
: out Count_Type
);
96 function Is_Greater_Element_Node
98 Right
: Node_Type
) return Boolean;
99 pragma Inline
(Is_Greater_Element_Node
);
101 function Is_Less_Element_Node
102 (Left
: Element_Type
;
103 Right
: Node_Type
) return Boolean;
104 pragma Inline
(Is_Less_Element_Node
);
106 function Is_Less_Node_Node
(L
, R
: Node_Type
) return Boolean;
107 pragma Inline
(Is_Less_Node_Node
);
109 procedure Replace_Element
110 (Container
: in out Set
;
112 Item
: Element_Type
);
114 --------------------------
115 -- Local Instantiations --
116 --------------------------
118 package Tree_Operations
is
119 new Red_Black_Trees
.Generic_Bounded_Operations
(Tree_Types
);
123 package Element_Keys
is
124 new Red_Black_Trees
.Generic_Bounded_Keys
125 (Tree_Operations
=> Tree_Operations
,
126 Key_Type
=> Element_Type
,
127 Is_Less_Key_Node
=> Is_Less_Element_Node
,
128 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
131 new Red_Black_Trees
.Generic_Bounded_Set_Operations
132 (Tree_Operations
=> Tree_Operations
,
135 Insert_With_Hint
=> Insert_With_Hint
,
136 Is_Less
=> Is_Less_Node_Node
);
142 function "<" (Left
, Right
: Cursor
) return Boolean is
144 if Left
.Node
= 0 then
145 raise Constraint_Error
with "Left cursor equals No_Element";
148 if Right
.Node
= 0 then
149 raise Constraint_Error
with "Right cursor equals No_Element";
152 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
153 "bad Left cursor in ""<""");
155 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
156 "bad Right cursor in ""<""");
159 LN
: Nodes_Type
renames Left
.Container
.Nodes
;
160 RN
: Nodes_Type
renames Right
.Container
.Nodes
;
162 return LN
(Left
.Node
).Element
< RN
(Right
.Node
).Element
;
166 function "<" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
168 if Left
.Node
= 0 then
169 raise Constraint_Error
with "Left cursor equals No_Element";
172 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
173 "bad Left cursor in ""<""");
175 return Left
.Container
.Nodes
(Left
.Node
).Element
< Right
;
178 function "<" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
180 if Right
.Node
= 0 then
181 raise Constraint_Error
with "Right cursor equals No_Element";
184 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
185 "bad Right cursor in ""<""");
187 return Left
< Right
.Container
.Nodes
(Right
.Node
).Element
;
194 function "=" (Left
, Right
: Set
) return Boolean is
195 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean;
196 pragma Inline
(Is_Equal_Node_Node
);
199 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
201 ------------------------
202 -- Is_Equal_Node_Node --
203 ------------------------
205 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean is
207 return L
.Element
= R
.Element
;
208 end Is_Equal_Node_Node
;
210 -- Start of processing for Is_Equal
213 return Is_Equal
(Left
, Right
);
220 function ">" (Left
, Right
: Cursor
) return Boolean is
222 if Left
.Node
= 0 then
223 raise Constraint_Error
with "Left cursor equals No_Element";
226 if Right
.Node
= 0 then
227 raise Constraint_Error
with "Right cursor equals No_Element";
230 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
231 "bad Left cursor in "">""");
233 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
234 "bad Right cursor in "">""");
236 -- L > R same as R < L
239 LN
: Nodes_Type
renames Left
.Container
.Nodes
;
240 RN
: Nodes_Type
renames Right
.Container
.Nodes
;
242 return RN
(Right
.Node
).Element
< LN
(Left
.Node
).Element
;
246 function ">" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
248 if Right
.Node
= 0 then
249 raise Constraint_Error
with "Right cursor equals No_Element";
252 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
253 "bad Right cursor in "">""");
255 return Right
.Container
.Nodes
(Right
.Node
).Element
< Left
;
258 function ">" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
260 if Left
.Node
= 0 then
261 raise Constraint_Error
with "Left cursor equals No_Element";
264 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
265 "bad Left cursor in "">""");
267 return Right
< Left
.Container
.Nodes
(Left
.Node
).Element
;
274 procedure Adjust
(Control
: in out Reference_Control_Type
) is
276 if Control
.Container
/= null then
278 C
: Set
renames Control
.Container
.all;
279 B
: Natural renames C
.Busy
;
280 L
: Natural renames C
.Lock
;
292 procedure Assign
(Target
: in out Set
; Source
: Set
) is
293 procedure Append_Element
(Source_Node
: Count_Type
);
295 procedure Append_Elements
is
296 new Tree_Operations
.Generic_Iteration
(Append_Element
);
302 procedure Append_Element
(Source_Node
: Count_Type
) is
303 SN
: Node_Type
renames Source
.Nodes
(Source_Node
);
305 procedure Set_Element
(Node
: in out Node_Type
);
306 pragma Inline
(Set_Element
);
308 function New_Node
return Count_Type
;
309 pragma Inline
(New_Node
);
311 procedure Insert_Post
is
312 new Element_Keys
.Generic_Insert_Post
(New_Node
);
314 procedure Unconditional_Insert_Sans_Hint
is
315 new Element_Keys
.Generic_Unconditional_Insert
(Insert_Post
);
317 procedure Unconditional_Insert_Avec_Hint
is
318 new Element_Keys
.Generic_Unconditional_Insert_With_Hint
320 Unconditional_Insert_Sans_Hint
);
322 procedure Allocate
is
323 new Tree_Operations
.Generic_Allocate
(Set_Element
);
329 function New_Node
return Count_Type
is
332 Allocate
(Target
, Result
);
340 procedure Set_Element
(Node
: in out Node_Type
) is
342 Node
.Element
:= SN
.Element
;
345 Target_Node
: Count_Type
;
347 -- Start of processing for Append_Element
350 Unconditional_Insert_Avec_Hint
354 Node
=> Target_Node
);
357 -- Start of processing for Assign
360 if Target
'Address = Source
'Address then
364 if Target
.Capacity
< Source
.Length
then
366 with "Target capacity is less than Source length";
370 Append_Elements
(Source
);
377 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
378 Node
: constant Count_Type
:=
379 Element_Keys
.Ceiling
(Container
, Item
);
381 return (if Node
= 0 then No_Element
382 else Cursor
'(Container'Unrestricted_Access, Node));
389 procedure Clear (Container : in out Set) is
391 Tree_Operations.Clear_Tree (Container);
398 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type is
403 ------------------------
404 -- Constant_Reference --
405 ------------------------
407 function Constant_Reference
408 (Container : aliased Set;
409 Position : Cursor) return Constant_Reference_Type
412 if Position.Container = null then
413 raise Constraint_Error with "Position cursor has no element";
416 if Position.Container /= Container'Unrestricted_Access then
417 raise Program_Error with
418 "Position cursor designates wrong container";
422 (Vet (Container, Position.Node),
423 "bad cursor in Constant_Reference");
426 N : Node_Type renames Container.Nodes (Position.Node);
427 B : Natural renames Position.Container.Busy;
428 L : Natural renames Position.Container.Lock;
430 return R : constant Constant_Reference_Type :=
431 (Element => N.Element'Access,
432 Control => (Controlled with Container'Unrestricted_Access))
438 end Constant_Reference;
446 Item : Element_Type) return Boolean
449 return Find (Container, Item) /= No_Element;
456 function Copy (Source : Set; Capacity : Count_Type := 0) return Set is
462 elsif Capacity >= Source.Length then
465 raise Capacity_Error with "Capacity value too small";
468 return Target : Set (Capacity => C) do
469 Assign (Target => Target, Source => Source);
477 procedure Delete (Container : in out Set; Position : in out Cursor) is
479 if Position.Node = 0 then
480 raise Constraint_Error with "Position cursor equals No_Element";
483 if Position.Container /= Container'Unrestricted_Access then
484 raise Program_Error with "Position cursor designates wrong set";
487 if Container.Busy > 0 then
488 raise Program_Error with
489 "attempt to tamper with cursors (set is busy)";
492 pragma Assert (Vet (Container, Position.Node),
493 "bad cursor in Delete");
495 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
496 Tree_Operations.Free (Container, Position.Node);
498 Position := No_Element;
501 procedure Delete (Container : in out Set; Item : Element_Type) is
502 X : constant Count_Type := Element_Keys.Find (Container, Item);
505 Tree_Operations.Delete_Node_Sans_Free (Container, X);
508 raise Constraint_Error with "attempt to delete element not in set";
511 Tree_Operations.Free (Container, X);
518 procedure Delete_First (Container : in out Set) is
519 X : constant Count_Type := Container.First;
522 Tree_Operations.Delete_Node_Sans_Free (Container, X);
523 Tree_Operations.Free (Container, X);
531 procedure Delete_Last (Container : in out Set) is
532 X : constant Count_Type := Container.Last;
535 Tree_Operations.Delete_Node_Sans_Free (Container, X);
536 Tree_Operations.Free (Container, X);
544 procedure Difference (Target : in out Set; Source : Set)
545 renames Set_Ops.Set_Difference;
547 function Difference (Left, Right : Set) return Set
548 renames Set_Ops.Set_Difference;
554 function Element (Position : Cursor) return Element_Type is
556 if Position.Node = 0 then
557 raise Constraint_Error with "Position cursor equals No_Element";
560 pragma Assert (Vet (Position.Container.all, Position.Node),
561 "bad cursor in Element");
563 return Position.Container.Nodes (Position.Node).Element;
566 -------------------------
567 -- Equivalent_Elements --
568 -------------------------
570 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
572 return (if Left < Right or else Right < Left then False else True);
573 end Equivalent_Elements;
575 ---------------------
576 -- Equivalent_Sets --
577 ---------------------
579 function Equivalent_Sets (Left, Right : Set) return Boolean is
580 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean;
581 pragma Inline (Is_Equivalent_Node_Node);
583 function Is_Equivalent is
584 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
586 -----------------------------
587 -- Is_Equivalent_Node_Node --
588 -----------------------------
590 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean is
592 return (if L.Element < R.Element then False
593 elsif R.Element < L.Element then False
595 end Is_Equivalent_Node_Node;
597 -- Start of processing for Equivalent_Sets
600 return Is_Equivalent (Left, Right);
607 procedure Exclude (Container : in out Set; Item : Element_Type) is
608 X : constant Count_Type := Element_Keys.Find (Container, Item);
611 Tree_Operations.Delete_Node_Sans_Free (Container, X);
612 Tree_Operations.Free (Container, X);
620 procedure Finalize (Object : in out Iterator) is
622 if Object.Container /= null then
624 B : Natural renames Object.Container.all.Busy;
631 procedure Finalize (Control : in out Reference_Control_Type) is
633 if Control.Container /= null then
635 C : Set renames Control.Container.all;
636 B : Natural renames C.Busy;
637 L : Natural renames C.Lock;
643 Control.Container := null;
651 function Find (Container : Set; Item : Element_Type) return Cursor is
652 Node : constant Count_Type := Element_Keys.Find (Container, Item);
654 return (if Node = 0 then No_Element
655 else Cursor'(Container
'Unrestricted_Access, Node
));
662 function First
(Container
: Set
) return Cursor
is
664 return (if Container
.First
= 0 then No_Element
665 else Cursor
'(Container'Unrestricted_Access, Container.First));
668 function First (Object : Iterator) return Cursor is
670 -- The value of the iterator object's Node component influences the
671 -- behavior of the First (and Last) selector function.
673 -- When the Node component is 0, this means the iterator object was
674 -- constructed without a start expression, in which case the (forward)
675 -- iteration starts from the (logical) beginning of the entire sequence
676 -- of items (corresponding to Container.First, for a forward iterator).
678 -- Otherwise, this is iteration over a partial sequence of items. When
679 -- the Node component is positive, the iterator object was constructed
680 -- with a start expression, that specifies the position from which the
681 -- (forward) partial iteration begins.
683 if Object.Node = 0 then
684 return Bounded_Ordered_Sets.First (Object.Container.all);
686 return Cursor'(Object
.Container
, Object
.Node
);
694 function First_Element
(Container
: Set
) return Element_Type
is
696 if Container
.First
= 0 then
697 raise Constraint_Error
with "set is empty";
700 return Container
.Nodes
(Container
.First
).Element
;
707 function Floor
(Container
: Set
; Item
: Element_Type
) return Cursor
is
708 Node
: constant Count_Type
:= Element_Keys
.Floor
(Container
, Item
);
710 return (if Node
= 0 then No_Element
711 else Cursor
'(Container'Unrestricted_Access, Node));
718 package body Generic_Keys is
720 -----------------------
721 -- Local Subprograms --
722 -----------------------
724 function Is_Greater_Key_Node
726 Right : Node_Type) return Boolean;
727 pragma Inline (Is_Greater_Key_Node);
729 function Is_Less_Key_Node
731 Right : Node_Type) return Boolean;
732 pragma Inline (Is_Less_Key_Node);
734 --------------------------
735 -- Local Instantiations --
736 --------------------------
739 new Red_Black_Trees.Generic_Bounded_Keys
740 (Tree_Operations => Tree_Operations,
741 Key_Type => Key_Type,
742 Is_Less_Key_Node => Is_Less_Key_Node,
743 Is_Greater_Key_Node => Is_Greater_Key_Node);
749 procedure Adjust (Control : in out Reference_Control_Type) is
751 if Control.Container /= null then
753 B : Natural renames Control.Container.Busy;
754 L : Natural renames Control.Container.Lock;
766 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
767 Node : constant Count_Type :=
768 Key_Keys.Ceiling (Container, Key);
770 return (if Node = 0 then No_Element
771 else Cursor'(Container
'Unrestricted_Access, Node
));
774 ------------------------
775 -- Constant_Reference --
776 ------------------------
778 function Constant_Reference
779 (Container
: aliased Set
;
780 Key
: Key_Type
) return Constant_Reference_Type
782 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
786 raise Constraint_Error
with "key not in set";
790 Cur
: Cursor
:= Find
(Container
, Key
);
791 pragma Unmodified
(Cur
);
793 N
: Node_Type
renames Container
.Nodes
(Node
);
794 B
: Natural renames Cur
.Container
.Busy
;
795 L
: Natural renames Cur
.Container
.Lock
;
798 return R
: constant Constant_Reference_Type
:=
799 (Element
=> N
.Element
'Access,
800 Control
=> (Controlled
with Container
'Unrestricted_Access))
806 end Constant_Reference
;
812 function Contains
(Container
: Set
; Key
: Key_Type
) return Boolean is
814 return Find
(Container
, Key
) /= No_Element
;
821 procedure Delete
(Container
: in out Set
; Key
: Key_Type
) is
822 X
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
826 raise Constraint_Error
with "attempt to delete key not in set";
829 Tree_Operations
.Delete_Node_Sans_Free
(Container
, X
);
830 Tree_Operations
.Free
(Container
, X
);
837 function Element
(Container
: Set
; Key
: Key_Type
) return Element_Type
is
838 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
842 raise Constraint_Error
with "key not in set";
845 return Container
.Nodes
(Node
).Element
;
848 ---------------------
849 -- Equivalent_Keys --
850 ---------------------
852 function Equivalent_Keys
(Left
, Right
: Key_Type
) return Boolean is
854 return (if Left
< Right
or else Right
< Left
then False else True);
861 procedure Exclude
(Container
: in out Set
; Key
: Key_Type
) is
862 X
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
865 Tree_Operations
.Delete_Node_Sans_Free
(Container
, X
);
866 Tree_Operations
.Free
(Container
, X
);
874 procedure Finalize
(Control
: in out Reference_Control_Type
) is
876 if Control
.Container
/= null then
878 B
: Natural renames Control
.Container
.Busy
;
879 L
: Natural renames Control
.Container
.Lock
;
885 if not (Key
(Control
.Pos
) = Control
.Old_Key
.all) then
886 Delete
(Control
.Container
.all, Key
(Control
.Pos
));
890 Control
.Container
:= null;
898 function Find
(Container
: Set
; Key
: Key_Type
) return Cursor
is
899 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
901 return (if Node
= 0 then No_Element
902 else Cursor
'(Container'Unrestricted_Access, Node));
909 function Floor (Container : Set; Key : Key_Type) return Cursor is
910 Node : constant Count_Type := Key_Keys.Floor (Container, Key);
912 return (if Node = 0 then No_Element
913 else Cursor'(Container
'Unrestricted_Access, Node
));
916 -------------------------
917 -- Is_Greater_Key_Node --
918 -------------------------
920 function Is_Greater_Key_Node
922 Right
: Node_Type
) return Boolean
925 return Key
(Right
.Element
) < Left
;
926 end Is_Greater_Key_Node
;
928 ----------------------
929 -- Is_Less_Key_Node --
930 ----------------------
932 function Is_Less_Key_Node
934 Right
: Node_Type
) return Boolean
937 return Left
< Key
(Right
.Element
);
938 end Is_Less_Key_Node
;
944 function Key
(Position
: Cursor
) return Key_Type
is
946 if Position
.Node
= 0 then
947 raise Constraint_Error
with
948 "Position cursor equals No_Element";
951 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
952 "bad cursor in Key");
954 return Key
(Position
.Container
.Nodes
(Position
.Node
).Element
);
962 (Stream
: not null access Root_Stream_Type
'Class;
963 Item
: out Reference_Type
)
966 raise Program_Error
with "attempt to stream reference";
969 ------------------------------
970 -- Reference_Preserving_Key --
971 ------------------------------
973 function Reference_Preserving_Key
974 (Container
: aliased in out Set
;
975 Position
: Cursor
) return Reference_Type
978 if Position
.Container
= null then
979 raise Constraint_Error
with "Position cursor has no element";
982 if Position
.Container
/= Container
'Unrestricted_Access then
983 raise Program_Error
with
984 "Position cursor designates wrong container";
988 (Vet
(Container
, Position
.Node
),
989 "bad cursor in function Reference_Preserving_Key");
992 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
993 B
: Natural renames Container
.Busy
;
994 L
: Natural renames Container
.Lock
;
996 return R
: constant Reference_Type
:=
997 (Element
=> N
.Element
'Access,
1000 Container
=> Container
'Access,
1002 Old_Key
=> new Key_Type
'(Key (Position))))
1008 end Reference_Preserving_Key;
1010 function Reference_Preserving_Key
1011 (Container : aliased in out Set;
1012 Key : Key_Type) return Reference_Type
1014 Node : constant Count_Type := Key_Keys.Find (Container, Key);
1018 raise Constraint_Error with "key not in set";
1022 N : Node_Type renames Container.Nodes (Node);
1023 B : Natural renames Container.Busy;
1024 L : Natural renames Container.Lock;
1026 return R : constant Reference_Type :=
1027 (Element => N.Element'Access,
1030 Container => Container'Access,
1031 Pos => Find (Container, Key),
1032 Old_Key => new Key_Type'(Key
)))
1038 end Reference_Preserving_Key
;
1045 (Container
: in out Set
;
1047 New_Item
: Element_Type
)
1049 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1053 raise Constraint_Error
with
1054 "attempt to replace key not in set";
1057 Replace_Element
(Container
, Node
, New_Item
);
1060 -----------------------------------
1061 -- Update_Element_Preserving_Key --
1062 -----------------------------------
1064 procedure Update_Element_Preserving_Key
1065 (Container
: in out Set
;
1067 Process
: not null access procedure (Element
: in out Element_Type
))
1070 if Position
.Node
= 0 then
1071 raise Constraint_Error
with
1072 "Position cursor equals No_Element";
1075 if Position
.Container
/= Container
'Unrestricted_Access then
1076 raise Program_Error
with
1077 "Position cursor designates wrong set";
1080 pragma Assert
(Vet
(Container
, Position
.Node
),
1081 "bad cursor in Update_Element_Preserving_Key");
1083 -- Per AI05-0022, the container implementation is required to detect
1084 -- element tampering by a generic actual subprogram.
1087 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1088 E
: Element_Type
renames N
.Element
;
1089 K
: constant Key_Type
:= Key
(E
);
1091 B
: Natural renames Container
.Busy
;
1092 L
: Natural renames Container
.Lock
;
1102 Eq
:= Equivalent_Keys
(K
, Key
(E
));
1118 Tree_Operations
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
1119 Tree_Operations
.Free
(Container
, Position
.Node
);
1121 raise Program_Error
with "key was modified";
1122 end Update_Element_Preserving_Key
;
1129 (Stream
: not null access Root_Stream_Type
'Class;
1130 Item
: Reference_Type
)
1133 raise Program_Error
with "attempt to stream reference";
1141 function Has_Element
(Position
: Cursor
) return Boolean is
1143 return Position
/= No_Element
;
1150 procedure Include
(Container
: in out Set
; New_Item
: Element_Type
) is
1155 Insert
(Container
, New_Item
, Position
, Inserted
);
1157 if not Inserted
then
1158 if Container
.Lock
> 0 then
1159 raise Program_Error
with
1160 "attempt to tamper with elements (set is locked)";
1163 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1172 (Container
: in out Set
;
1173 New_Item
: Element_Type
;
1174 Position
: out Cursor
;
1175 Inserted
: out Boolean)
1184 Position
.Container
:= Container
'Unrestricted_Access;
1188 (Container
: in out Set
;
1189 New_Item
: Element_Type
)
1192 pragma Unreferenced
(Position
);
1197 Insert
(Container
, New_Item
, Position
, Inserted
);
1199 if not Inserted
then
1200 raise Constraint_Error
with
1201 "attempt to insert element already in set";
1205 ----------------------
1206 -- Insert_Sans_Hint --
1207 ----------------------
1209 procedure Insert_Sans_Hint
1210 (Container
: in out Set
;
1211 New_Item
: Element_Type
;
1212 Node
: out Count_Type
;
1213 Inserted
: out Boolean)
1215 procedure Set_Element
(Node
: in out Node_Type
);
1216 pragma Inline
(Set_Element
);
1218 function New_Node
return Count_Type
;
1219 pragma Inline
(New_Node
);
1221 procedure Insert_Post
is
1222 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1224 procedure Conditional_Insert_Sans_Hint
is
1225 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1227 procedure Allocate
is
1228 new Tree_Operations
.Generic_Allocate
(Set_Element
);
1234 function New_Node
return Count_Type
is
1235 Result
: Count_Type
;
1237 Allocate
(Container
, Result
);
1245 procedure Set_Element
(Node
: in out Node_Type
) is
1247 Node
.Element
:= New_Item
;
1250 -- Start of processing for Insert_Sans_Hint
1253 if Container
.Busy
> 0 then
1254 raise Program_Error
with
1255 "attemot to tamper with cursors (set is busy)";
1258 Conditional_Insert_Sans_Hint
1263 end Insert_Sans_Hint
;
1265 ----------------------
1266 -- Insert_With_Hint --
1267 ----------------------
1269 procedure Insert_With_Hint
1270 (Dst_Set
: in out Set
;
1271 Dst_Hint
: Count_Type
;
1272 Src_Node
: Node_Type
;
1273 Dst_Node
: out Count_Type
)
1276 pragma Unreferenced
(Success
);
1278 procedure Set_Element
(Node
: in out Node_Type
);
1279 pragma Inline
(Set_Element
);
1281 function New_Node
return Count_Type
;
1282 pragma Inline
(New_Node
);
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 Local_Insert_With_Hint
is
1291 new Element_Keys
.Generic_Conditional_Insert_With_Hint
1295 procedure Allocate
is
1296 new Tree_Operations
.Generic_Allocate
(Set_Element
);
1302 function New_Node
return Count_Type
is
1303 Result
: Count_Type
;
1305 Allocate
(Dst_Set
, Result
);
1313 procedure Set_Element
(Node
: in out Node_Type
) is
1315 Node
.Element
:= Src_Node
.Element
;
1318 -- Start of processing for Insert_With_Hint
1321 Local_Insert_With_Hint
1327 end Insert_With_Hint
;
1333 procedure Intersection
(Target
: in out Set
; Source
: Set
)
1334 renames Set_Ops
.Set_Intersection
;
1336 function Intersection
(Left
, Right
: Set
) return Set
1337 renames Set_Ops
.Set_Intersection
;
1343 function Is_Empty
(Container
: Set
) return Boolean is
1345 return Container
.Length
= 0;
1348 -----------------------------
1349 -- Is_Greater_Element_Node --
1350 -----------------------------
1352 function Is_Greater_Element_Node
1353 (Left
: Element_Type
;
1354 Right
: Node_Type
) return Boolean
1357 -- Compute e > node same as node < e
1359 return Right
.Element
< Left
;
1360 end Is_Greater_Element_Node
;
1362 --------------------------
1363 -- Is_Less_Element_Node --
1364 --------------------------
1366 function Is_Less_Element_Node
1367 (Left
: Element_Type
;
1368 Right
: Node_Type
) return Boolean
1371 return Left
< Right
.Element
;
1372 end Is_Less_Element_Node
;
1374 -----------------------
1375 -- Is_Less_Node_Node --
1376 -----------------------
1378 function Is_Less_Node_Node
(L
, R
: Node_Type
) return Boolean is
1380 return L
.Element
< R
.Element
;
1381 end Is_Less_Node_Node
;
1387 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean
1388 renames Set_Ops
.Set_Subset
;
1396 Process
: not null access procedure (Position
: Cursor
))
1398 procedure Process_Node
(Node
: Count_Type
);
1399 pragma Inline
(Process_Node
);
1401 procedure Local_Iterate
is
1402 new Tree_Operations
.Generic_Iteration
(Process_Node
);
1408 procedure Process_Node
(Node
: Count_Type
) is
1410 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1413 S : Set renames Container'Unrestricted_Access.all;
1414 B : Natural renames S.Busy;
1416 -- Start of processing for Iterate
1432 function Iterate (Container : Set)
1433 return Set_Iterator_Interfaces.Reversible_Iterator'class
1435 B : Natural renames Container'Unrestricted_Access.all.Busy;
1438 -- The value of the Node component influences the behavior of the First
1439 -- and Last selector functions of the iterator object. When the Node
1440 -- component is 0 (as is the case here), this means the iterator object
1441 -- was constructed without a start expression. This is a complete
1442 -- iterator, meaning that the iteration starts from the (logical)
1443 -- beginning of the sequence of items.
1445 -- Note: For a forward iterator, Container.First is the beginning, and
1446 -- for a reverse iterator, Container.Last is the beginning.
1448 return It : constant Iterator :=
1449 Iterator'(Limited_Controlled
with
1450 Container
=> Container
'Unrestricted_Access,
1457 function Iterate
(Container
: Set
; Start
: Cursor
)
1458 return Set_Iterator_Interfaces
.Reversible_Iterator
'class
1460 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
1463 -- It was formerly the case that when Start = No_Element, the partial
1464 -- iterator was defined to behave the same as for a complete iterator,
1465 -- and iterate over the entire sequence of items. However, those
1466 -- semantics were unintuitive and arguably error-prone (it is too easy
1467 -- to accidentally create an endless loop), and so they were changed,
1468 -- per the ARG meeting in Denver on 2011/11. However, there was no
1469 -- consensus about what positive meaning this corner case should have,
1470 -- and so it was decided to simply raise an exception. This does imply,
1471 -- however, that it is not possible to use a partial iterator to specify
1472 -- an empty sequence of items.
1474 if Start
= No_Element
then
1475 raise Constraint_Error
with
1476 "Start position for iterator equals No_Element";
1479 if Start
.Container
/= Container
'Unrestricted_Access then
1480 raise Program_Error
with
1481 "Start cursor of Iterate designates wrong set";
1484 pragma Assert
(Vet
(Container
, Start
.Node
),
1485 "Start cursor of Iterate is bad");
1487 -- The value of the Node component influences the behavior of the First
1488 -- and Last selector functions of the iterator object. When the Node
1489 -- component is positive (as is the case here), it means that this
1490 -- is a partial iteration, over a subset of the complete sequence of
1491 -- items. The iterator object was constructed with a start expression,
1492 -- indicating the position from which the iteration begins. (Note that
1493 -- the start position has the same value irrespective of whether this
1494 -- is a forward or reverse iteration.)
1496 return It
: constant Iterator
:=
1497 Iterator
'(Limited_Controlled with
1498 Container => Container'Unrestricted_Access,
1509 function Last (Container : Set) return Cursor is
1511 return (if Container.Last = 0 then No_Element
1512 else Cursor'(Container
'Unrestricted_Access, Container
.Last
));
1515 function Last
(Object
: Iterator
) return Cursor
is
1517 -- The value of the iterator object's Node component influences the
1518 -- behavior of the Last (and First) selector function.
1520 -- When the Node component is 0, this means the iterator object was
1521 -- constructed without a start expression, in which case the (reverse)
1522 -- iteration starts from the (logical) beginning of the entire sequence
1523 -- (corresponding to Container.Last, for a reverse iterator).
1525 -- Otherwise, this is iteration over a partial sequence of items. When
1526 -- the Node component is positive, the iterator object was constructed
1527 -- with a start expression, that specifies the position from which the
1528 -- (reverse) partial iteration begins.
1530 if Object
.Node
= 0 then
1531 return Bounded_Ordered_Sets
.Last
(Object
.Container
.all);
1533 return Cursor
'(Object.Container, Object.Node);
1541 function Last_Element (Container : Set) return Element_Type is
1543 if Container.Last = 0 then
1544 raise Constraint_Error with "set is empty";
1547 return Container.Nodes (Container.Last).Element;
1554 function Left (Node : Node_Type) return Count_Type is
1563 function Length (Container : Set) return Count_Type is
1565 return Container.Length;
1572 procedure Move (Target : in out Set; Source : in out Set) is
1574 if Target'Address = Source'Address then
1578 if Source.Busy > 0 then
1579 raise Program_Error with
1580 "attempt to tamper with cursors (container is busy)";
1583 Target.Assign (Source);
1591 function Next (Position : Cursor) return Cursor is
1593 if Position = No_Element then
1597 pragma Assert (Vet (Position.Container.all, Position.Node),
1598 "bad cursor in Next");
1601 Node : constant Count_Type :=
1602 Tree_Operations.Next (Position.Container.all, Position.Node);
1609 return Cursor'(Position
.Container
, Node
);
1613 procedure Next
(Position
: in out Cursor
) is
1615 Position
:= Next
(Position
);
1618 function Next
(Object
: Iterator
; Position
: Cursor
) return Cursor
is
1620 if Position
.Container
= null then
1624 if Position
.Container
/= Object
.Container
then
1625 raise Program_Error
with
1626 "Position cursor of Next designates wrong set";
1629 return Next
(Position
);
1636 function Overlap
(Left
, Right
: Set
) return Boolean
1637 renames Set_Ops
.Set_Overlap
;
1643 function Parent
(Node
: Node_Type
) return Count_Type
is
1652 function Previous
(Position
: Cursor
) return Cursor
is
1654 if Position
= No_Element
then
1658 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1659 "bad cursor in Previous");
1662 Node
: constant Count_Type
:=
1663 Tree_Operations
.Previous
(Position
.Container
.all, Position
.Node
);
1665 return (if Node
= 0 then No_Element
1666 else Cursor
'(Position.Container, Node));
1670 procedure Previous (Position : in out Cursor) is
1672 Position := Previous (Position);
1675 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1677 if Position.Container = null then
1681 if Position.Container /= Object.Container then
1682 raise Program_Error with
1683 "Position cursor of Previous designates wrong set";
1686 return Previous (Position);
1693 procedure Query_Element
1695 Process : not null access procedure (Element : Element_Type))
1698 if Position.Node = 0 then
1699 raise Constraint_Error with "Position cursor equals No_Element";
1702 pragma Assert (Vet (Position.Container.all, Position.Node),
1703 "bad cursor in Query_Element");
1706 S : Set renames Position.Container.all;
1707 B : Natural renames S.Busy;
1708 L : Natural renames S.Lock;
1715 Process (S.Nodes (Position.Node).Element);
1733 (Stream : not null access Root_Stream_Type'Class;
1734 Container : out Set)
1736 procedure Read_Element (Node : in out Node_Type);
1737 pragma Inline (Read_Element);
1739 procedure Allocate is
1740 new Tree_Operations.Generic_Allocate (Read_Element);
1742 procedure Read_Elements is
1743 new Tree_Operations.Generic_Read (Allocate);
1749 procedure Read_Element (Node : in out Node_Type) is
1751 Element_Type'Read (Stream, Node.Element);
1754 -- Start of processing for Read
1757 Read_Elements (Stream, Container);
1761 (Stream : not null access Root_Stream_Type'Class;
1765 raise Program_Error with "attempt to stream set cursor";
1769 (Stream : not null access Root_Stream_Type'Class;
1770 Item : out Constant_Reference_Type)
1773 raise Program_Error with "attempt to stream reference";
1780 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1781 Node : constant Count_Type := Element_Keys.Find (Container, New_Item);
1785 raise Constraint_Error with
1786 "attempt to replace element not in set";
1789 if Container.Lock > 0 then
1790 raise Program_Error with
1791 "attempt to tamper with elements (set is locked)";
1794 Container.Nodes (Node).Element := New_Item;
1797 ---------------------
1798 -- Replace_Element --
1799 ---------------------
1801 procedure Replace_Element
1802 (Container : in out Set;
1804 Item : Element_Type)
1806 pragma Assert (Index /= 0);
1808 function New_Node return Count_Type;
1809 pragma Inline (New_Node);
1811 procedure Local_Insert_Post is
1812 new Element_Keys.Generic_Insert_Post (New_Node);
1814 procedure Local_Insert_Sans_Hint is
1815 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1817 procedure Local_Insert_With_Hint is
1818 new Element_Keys.Generic_Conditional_Insert_With_Hint
1820 Local_Insert_Sans_Hint);
1822 Nodes : Nodes_Type renames Container.Nodes;
1823 Node : Node_Type renames Nodes (Index);
1829 function New_Node return Count_Type is
1831 Node.Element := Item;
1832 Node.Color := Red_Black_Trees.Red;
1840 Result : Count_Type;
1844 -- Per AI05-0022, the container implementation is required to detect
1845 -- element tampering by a generic actual subprogram.
1847 B : Natural renames Container.Busy;
1848 L : Natural renames Container.Lock;
1850 -- Start of processing for Replace_Element
1853 -- Replace_Element assigns value Item to the element designated by Node,
1854 -- per certain semantic constraints, described as follows.
1856 -- If Item is equivalent to the element, then element is replaced and
1857 -- there's nothing else to do. This is the easy case.
1859 -- If Item is not equivalent, then the node will (possibly) have to move
1860 -- to some other place in the tree. This is slighly more complicated,
1861 -- because we must ensure that Item is not equivalent to some other
1862 -- element in the tree (in which case, the replacement is not allowed).
1864 -- Determine whether Item is equivalent to element on the specified
1871 Compare := (if Item < Node.Element then False
1872 elsif Node.Element < Item then False
1887 -- Item is equivalent to the node's element, so we will not have to
1890 if Container.Lock > 0 then
1891 raise Program_Error with
1892 "attempt to tamper with elements (set is locked)";
1895 Node.Element := Item;
1899 -- The replacement Item is not equivalent to the element on the
1900 -- specified node, which means that it will need to be re-inserted in a
1901 -- different position in the tree. We must now determine whether Item is
1902 -- equivalent to some other element in the tree (which would prohibit
1903 -- the assignment and hence the move).
1905 -- Ceiling returns the smallest element equivalent or greater than the
1906 -- specified Item; if there is no such element, then it returns 0.
1908 Hint := Element_Keys.Ceiling (Container, Item);
1910 if Hint /= 0 then -- Item <= Nodes (Hint).Element
1915 Compare := Item < Nodes (Hint).Element;
1927 -- Item is equivalent to Nodes (Hint).Element
1931 -- Ceiling returns an element that is equivalent or greater than
1932 -- Item. If Item is "not less than" the element, then by
1933 -- elimination we know that Item is equivalent to the element.
1935 -- But this means that it is not possible to assign the value of
1936 -- Item to the specified element (on Node), because a different
1937 -- element (on Hint) equivalent to Item already exsits. (Were we
1938 -- to change Node's element value, we would have to move Node, but
1939 -- we would be unable to move the Node, because its new position
1940 -- in the tree is already occupied by an equivalent element.)
1942 raise Program_Error with "attempt to replace existing element";
1945 -- Item is not equivalent to any other element in the tree
1946 -- (specifically, it is less than Nodes (Hint).Element), so it is
1947 -- safe to assign the value of Item to Node.Element. This means that
1948 -- the node will have to move to a different position in the tree
1949 -- (because its element will have a different value).
1951 -- The nearest (greater) neighbor of Item is Hint. This will be the
1952 -- insertion position of Node (because its element will have Item as
1955 -- If Node equals Hint, the relative position of Node does not
1956 -- change. This allows us to perform an optimization: we need not
1957 -- remove Node from the tree and then reinsert it with its new value,
1958 -- because it would only be placed in the exact same position.
1960 if Hint = Index then
1961 if Container.Lock > 0 then
1962 raise Program_Error with
1963 "attempt to tamper with elements (set is locked)";
1966 Node.Element := Item;
1971 -- If we get here, it is because Item was greater than all elements in
1972 -- the tree (Hint = 0), or because Item was less than some element at a
1973 -- different place in the tree (Item < Nodes (Hint).Element and Hint /=
1974 -- Index). In either case, we remove Node from the tree and then insert
1975 -- Item into the tree, onto the same Node.
1977 Tree_Operations.Delete_Node_Sans_Free (Container, Index);
1979 Local_Insert_With_Hint
1984 Inserted => Inserted);
1986 pragma Assert (Inserted);
1987 pragma Assert (Result = Index);
1988 end Replace_Element;
1990 procedure Replace_Element
1991 (Container : in out Set;
1993 New_Item : Element_Type)
1996 if Position.Node = 0 then
1997 raise Constraint_Error with
1998 "Position cursor equals No_Element";
2001 if Position.Container /= Container'Unrestricted_Access then
2002 raise Program_Error with
2003 "Position cursor designates wrong set";
2006 pragma Assert (Vet (Container, Position.Node),
2007 "bad cursor in Replace_Element");
2009 Replace_Element (Container, Position.Node, New_Item);
2010 end Replace_Element;
2012 ---------------------
2013 -- Reverse_Iterate --
2014 ---------------------
2016 procedure Reverse_Iterate
2018 Process : not null access procedure (Position : Cursor))
2020 procedure Process_Node (Node : Count_Type);
2021 pragma Inline (Process_Node);
2023 procedure Local_Reverse_Iterate is
2024 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
2030 procedure Process_Node (Node : Count_Type) is
2032 Process (Cursor'(Container
'Unrestricted_Access, Node
));
2035 S
: Set
renames Container
'Unrestricted_Access.all;
2036 B
: Natural renames S
.Busy
;
2038 -- Start of processing for Reverse_Iterate
2044 Local_Reverse_Iterate
(S
);
2052 end Reverse_Iterate
;
2058 function Right
(Node
: Node_Type
) return Count_Type
is
2068 (Node
: in out Node_Type
;
2069 Color
: Red_Black_Trees
.Color_Type
)
2072 Node
.Color
:= Color
;
2079 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
) is
2088 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
) is
2090 Node
.Parent
:= Parent
;
2097 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
) is
2099 Node
.Right
:= Right
;
2102 --------------------------
2103 -- Symmetric_Difference --
2104 --------------------------
2106 procedure Symmetric_Difference
(Target
: in out Set
; Source
: Set
)
2107 renames Set_Ops
.Set_Symmetric_Difference
;
2109 function Symmetric_Difference
(Left
, Right
: Set
) return Set
2110 renames Set_Ops
.Set_Symmetric_Difference
;
2116 function To_Set
(New_Item
: Element_Type
) return Set
is
2120 return S
: Set
(1) do
2121 Insert_Sans_Hint
(S
, New_Item
, Node
, Inserted
);
2122 pragma Assert
(Inserted
);
2130 procedure Union
(Target
: in out Set
; Source
: Set
)
2131 renames Set_Ops
.Set_Union
;
2133 function Union
(Left
, Right
: Set
) return Set
2134 renames Set_Ops
.Set_Union
;
2141 (Stream
: not null access Root_Stream_Type
'Class;
2144 procedure Write_Element
2145 (Stream
: not null access Root_Stream_Type
'Class;
2147 pragma Inline
(Write_Element
);
2149 procedure Write_Elements
is
2150 new Tree_Operations
.Generic_Write
(Write_Element
);
2156 procedure Write_Element
2157 (Stream
: not null access Root_Stream_Type
'Class;
2161 Element_Type
'Write (Stream
, Node
.Element
);
2164 -- Start of processing for Write
2167 Write_Elements
(Stream
, Container
);
2171 (Stream
: not null access Root_Stream_Type
'Class;
2175 raise Program_Error
with "attempt to stream set cursor";
2179 (Stream
: not null access Root_Stream_Type
'Class;
2180 Item
: Constant_Reference_Type
)
2183 raise Program_Error
with "attempt to stream reference";
2186 end Ada
.Containers
.Bounded_Ordered_Sets
;