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-2011, 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 Ada
.Finalization
; use Ada
.Finalization
;
42 with System
; use type System
.Address
;
44 package body Ada
.Containers
.Bounded_Ordered_Sets
is
46 type Iterator
is new Limited_Controlled
and
47 Set_Iterator_Interfaces
.Reversible_Iterator
with
49 Container
: Set_Access
;
53 overriding
procedure Finalize
(Object
: in out Iterator
);
55 overriding
function First
(Object
: Iterator
) return Cursor
;
56 overriding
function Last
(Object
: Iterator
) return Cursor
;
58 overriding
function Next
60 Position
: Cursor
) return Cursor
;
62 overriding
function Previous
64 Position
: Cursor
) return Cursor
;
66 ------------------------------
67 -- Access to Fields of Node --
68 ------------------------------
70 -- These subprograms provide functional notation for access to fields
71 -- of a node, and procedural notation for modifying these fields.
73 function Color
(Node
: Node_Type
) return Red_Black_Trees
.Color_Type
;
74 pragma Inline
(Color
);
76 function Left
(Node
: Node_Type
) return Count_Type
;
79 function Parent
(Node
: Node_Type
) return Count_Type
;
80 pragma Inline
(Parent
);
82 function Right
(Node
: Node_Type
) return Count_Type
;
83 pragma Inline
(Right
);
86 (Node
: in out Node_Type
;
87 Color
: Red_Black_Trees
.Color_Type
);
88 pragma Inline
(Set_Color
);
90 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
);
91 pragma Inline
(Set_Left
);
93 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
);
94 pragma Inline
(Set_Right
);
96 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
);
97 pragma Inline
(Set_Parent
);
99 -----------------------
100 -- Local Subprograms --
101 -----------------------
103 procedure Insert_Sans_Hint
104 (Container
: in out Set
;
105 New_Item
: Element_Type
;
106 Node
: out Count_Type
;
107 Inserted
: out Boolean);
109 procedure Insert_With_Hint
110 (Dst_Set
: in out Set
;
111 Dst_Hint
: Count_Type
;
112 Src_Node
: Node_Type
;
113 Dst_Node
: out Count_Type
);
115 function Is_Greater_Element_Node
116 (Left
: Element_Type
;
117 Right
: Node_Type
) return Boolean;
118 pragma Inline
(Is_Greater_Element_Node
);
120 function Is_Less_Element_Node
121 (Left
: Element_Type
;
122 Right
: Node_Type
) return Boolean;
123 pragma Inline
(Is_Less_Element_Node
);
125 function Is_Less_Node_Node
(L
, R
: Node_Type
) return Boolean;
126 pragma Inline
(Is_Less_Node_Node
);
128 procedure Replace_Element
129 (Container
: in out Set
;
131 Item
: Element_Type
);
133 --------------------------
134 -- Local Instantiations --
135 --------------------------
137 package Tree_Operations
is
138 new Red_Black_Trees
.Generic_Bounded_Operations
(Tree_Types
);
142 package Element_Keys
is
143 new Red_Black_Trees
.Generic_Bounded_Keys
144 (Tree_Operations
=> Tree_Operations
,
145 Key_Type
=> Element_Type
,
146 Is_Less_Key_Node
=> Is_Less_Element_Node
,
147 Is_Greater_Key_Node
=> Is_Greater_Element_Node
);
150 new Red_Black_Trees
.Generic_Bounded_Set_Operations
151 (Tree_Operations
=> Tree_Operations
,
154 Insert_With_Hint
=> Insert_With_Hint
,
155 Is_Less
=> Is_Less_Node_Node
);
161 function "<" (Left
, Right
: Cursor
) return Boolean is
163 if Left
.Node
= 0 then
164 raise Constraint_Error
with "Left cursor equals No_Element";
167 if Right
.Node
= 0 then
168 raise Constraint_Error
with "Right cursor equals No_Element";
171 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
172 "bad Left cursor in ""<""");
174 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
175 "bad Right cursor in ""<""");
178 LN
: Nodes_Type
renames Left
.Container
.Nodes
;
179 RN
: Nodes_Type
renames Right
.Container
.Nodes
;
181 return LN
(Left
.Node
).Element
< RN
(Right
.Node
).Element
;
185 function "<" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
187 if Left
.Node
= 0 then
188 raise Constraint_Error
with "Left cursor equals No_Element";
191 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
192 "bad Left cursor in ""<""");
194 return Left
.Container
.Nodes
(Left
.Node
).Element
< Right
;
197 function "<" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
199 if Right
.Node
= 0 then
200 raise Constraint_Error
with "Right cursor equals No_Element";
203 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
204 "bad Right cursor in ""<""");
206 return Left
< Right
.Container
.Nodes
(Right
.Node
).Element
;
213 function "=" (Left
, Right
: Set
) return Boolean is
214 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean;
215 pragma Inline
(Is_Equal_Node_Node
);
218 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
220 ------------------------
221 -- Is_Equal_Node_Node --
222 ------------------------
224 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean is
226 return L
.Element
= R
.Element
;
227 end Is_Equal_Node_Node
;
229 -- Start of processing for Is_Equal
232 return Is_Equal
(Left
, Right
);
239 function ">" (Left
, Right
: Cursor
) return Boolean is
241 if Left
.Node
= 0 then
242 raise Constraint_Error
with "Left cursor equals No_Element";
245 if Right
.Node
= 0 then
246 raise Constraint_Error
with "Right cursor equals No_Element";
249 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
250 "bad Left cursor in "">""");
252 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
253 "bad Right cursor in "">""");
255 -- L > R same as R < L
258 LN
: Nodes_Type
renames Left
.Container
.Nodes
;
259 RN
: Nodes_Type
renames Right
.Container
.Nodes
;
261 return RN
(Right
.Node
).Element
< LN
(Left
.Node
).Element
;
265 function ">" (Left
: Element_Type
; Right
: Cursor
) return Boolean is
267 if Right
.Node
= 0 then
268 raise Constraint_Error
with "Right cursor equals No_Element";
271 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
272 "bad Right cursor in "">""");
274 return Right
.Container
.Nodes
(Right
.Node
).Element
< Left
;
277 function ">" (Left
: Cursor
; Right
: Element_Type
) return Boolean is
279 if Left
.Node
= 0 then
280 raise Constraint_Error
with "Left cursor equals No_Element";
283 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
284 "bad Left cursor in "">""");
286 return Right
< Left
.Container
.Nodes
(Left
.Node
).Element
;
293 procedure Assign
(Target
: in out Set
; Source
: Set
) is
294 procedure Append_Element
(Source_Node
: Count_Type
);
296 procedure Append_Elements
is
297 new Tree_Operations
.Generic_Iteration
(Append_Element
);
303 procedure Append_Element
(Source_Node
: Count_Type
) is
304 SN
: Node_Type
renames Source
.Nodes
(Source_Node
);
306 procedure Set_Element
(Node
: in out Node_Type
);
307 pragma Inline
(Set_Element
);
309 function New_Node
return Count_Type
;
310 pragma Inline
(New_Node
);
312 procedure Insert_Post
is
313 new Element_Keys
.Generic_Insert_Post
(New_Node
);
315 procedure Unconditional_Insert_Sans_Hint
is
316 new Element_Keys
.Generic_Unconditional_Insert
(Insert_Post
);
318 procedure Unconditional_Insert_Avec_Hint
is
319 new Element_Keys
.Generic_Unconditional_Insert_With_Hint
321 Unconditional_Insert_Sans_Hint
);
323 procedure Allocate
is
324 new Tree_Operations
.Generic_Allocate
(Set_Element
);
330 function New_Node
return Count_Type
is
333 Allocate
(Target
, Result
);
341 procedure Set_Element
(Node
: in out Node_Type
) is
343 Node
.Element
:= SN
.Element
;
346 Target_Node
: Count_Type
;
348 -- Start of processing for Append_Element
351 Unconditional_Insert_Avec_Hint
355 Node
=> Target_Node
);
358 -- Start of processing for Assign
361 if Target
'Address = Source
'Address then
365 if Target
.Capacity
< Source
.Length
then
367 with "Target capacity is less than Source length";
371 Append_Elements
(Source
);
378 function Ceiling
(Container
: Set
; Item
: Element_Type
) return Cursor
is
379 Node
: constant Count_Type
:=
380 Element_Keys
.Ceiling
(Container
, Item
);
382 return (if Node
= 0 then No_Element
383 else Cursor
'(Container'Unrestricted_Access, Node));
390 procedure Clear (Container : in out Set) is
392 Tree_Operations.Clear_Tree (Container);
399 function Color (Node : Node_Type) return Red_Black_Trees.Color_Type is
410 Item : Element_Type) return Boolean
413 return Find (Container, Item) /= No_Element;
420 function Copy (Source : Set; Capacity : Count_Type := 0) return Set is
426 elsif Capacity >= Source.Length then
429 raise Capacity_Error with "Capacity value too small";
432 return Target : Set (Capacity => C) do
433 Assign (Target => Target, Source => Source);
441 procedure Delete (Container : in out Set; Position : in out Cursor) is
443 if Position.Node = 0 then
444 raise Constraint_Error with "Position cursor equals No_Element";
447 if Position.Container /= Container'Unrestricted_Access then
448 raise Program_Error with "Position cursor designates wrong set";
451 pragma Assert (Vet (Container, Position.Node),
452 "bad cursor in Delete");
454 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
455 Tree_Operations.Free (Container, Position.Node);
457 Position := No_Element;
460 procedure Delete (Container : in out Set; Item : Element_Type) is
461 X : constant Count_Type := Element_Keys.Find (Container, Item);
465 raise Constraint_Error with "attempt to delete element not in set";
468 Tree_Operations.Delete_Node_Sans_Free (Container, X);
469 Tree_Operations.Free (Container, X);
476 procedure Delete_First (Container : in out Set) is
477 X : constant Count_Type := Container.First;
480 Tree_Operations.Delete_Node_Sans_Free (Container, X);
481 Tree_Operations.Free (Container, X);
489 procedure Delete_Last (Container : in out Set) is
490 X : constant Count_Type := Container.Last;
493 Tree_Operations.Delete_Node_Sans_Free (Container, X);
494 Tree_Operations.Free (Container, X);
502 procedure Difference (Target : in out Set; Source : Set)
503 renames Set_Ops.Set_Difference;
505 function Difference (Left, Right : Set) return Set
506 renames Set_Ops.Set_Difference;
512 function Element (Position : Cursor) return Element_Type is
514 if Position.Node = 0 then
515 raise Constraint_Error with "Position cursor equals No_Element";
518 pragma Assert (Vet (Position.Container.all, Position.Node),
519 "bad cursor in Element");
521 return Position.Container.Nodes (Position.Node).Element;
524 -------------------------
525 -- Equivalent_Elements --
526 -------------------------
528 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
530 return (if Left < Right or else Right < Left then False else True);
531 end Equivalent_Elements;
533 ---------------------
534 -- Equivalent_Sets --
535 ---------------------
537 function Equivalent_Sets (Left, Right : Set) return Boolean is
538 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean;
539 pragma Inline (Is_Equivalent_Node_Node);
541 function Is_Equivalent is
542 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
544 -----------------------------
545 -- Is_Equivalent_Node_Node --
546 -----------------------------
548 function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean is
550 return (if L.Element < R.Element then False
551 elsif R.Element < L.Element then False
553 end Is_Equivalent_Node_Node;
555 -- Start of processing for Equivalent_Sets
558 return Is_Equivalent (Left, Right);
565 procedure Exclude (Container : in out Set; Item : Element_Type) is
566 X : constant Count_Type := Element_Keys.Find (Container, Item);
569 Tree_Operations.Delete_Node_Sans_Free (Container, X);
570 Tree_Operations.Free (Container, X);
578 procedure Finalize (Object : in out Iterator) is
580 if Object.Container /= null then
582 B : Natural renames Object.Container.all.Busy;
594 function Find (Container : Set; Item : Element_Type) return Cursor is
595 Node : constant Count_Type := Element_Keys.Find (Container, Item);
597 return (if Node = 0 then No_Element
598 else Cursor'(Container
'Unrestricted_Access, Node
));
605 function First
(Container
: Set
) return Cursor
is
607 return (if Container
.First
= 0 then No_Element
608 else Cursor
'(Container'Unrestricted_Access, Container.First));
611 function First (Object : Iterator) return Cursor is
613 -- The value of the iterator object's Node component influences the
614 -- behavior of the First (and Last) selector function.
616 -- When the Node component is 0, this means the iterator object was
617 -- constructed without a start expression, in which case the (forward)
618 -- iteration starts from the (logical) beginning of the entire sequence
619 -- of items (corresponding to Container.First, for a forward iterator).
621 -- Otherwise, this is iteration over a partial sequence of items. When
622 -- the Node component is positive, the iterator object was constructed
623 -- with a start expression, that specifies the position from which the
624 -- (forward) partial iteration begins.
626 if Object.Node = 0 then
627 return Bounded_Ordered_Sets.First (Object.Container.all);
629 return Cursor'(Object
.Container
, Object
.Node
);
637 function First_Element
(Container
: Set
) return Element_Type
is
639 if Container
.First
= 0 then
640 raise Constraint_Error
with "set is empty";
643 return Container
.Nodes
(Container
.First
).Element
;
650 function Floor
(Container
: Set
; Item
: Element_Type
) return Cursor
is
651 Node
: constant Count_Type
:= Element_Keys
.Floor
(Container
, Item
);
653 return (if Node
= 0 then No_Element
654 else Cursor
'(Container'Unrestricted_Access, Node));
661 package body Generic_Keys is
663 -----------------------
664 -- Local Subprograms --
665 -----------------------
667 function Is_Greater_Key_Node
669 Right : Node_Type) return Boolean;
670 pragma Inline (Is_Greater_Key_Node);
672 function Is_Less_Key_Node
674 Right : Node_Type) return Boolean;
675 pragma Inline (Is_Less_Key_Node);
677 --------------------------
678 -- Local Instantiations --
679 --------------------------
682 new Red_Black_Trees.Generic_Bounded_Keys
683 (Tree_Operations => Tree_Operations,
684 Key_Type => Key_Type,
685 Is_Less_Key_Node => Is_Less_Key_Node,
686 Is_Greater_Key_Node => Is_Greater_Key_Node);
692 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
693 Node : constant Count_Type :=
694 Key_Keys.Ceiling (Container, Key);
696 return (if Node = 0 then No_Element
697 else Cursor'(Container
'Unrestricted_Access, Node
));
704 function Contains
(Container
: Set
; Key
: Key_Type
) return Boolean is
706 return Find
(Container
, Key
) /= No_Element
;
713 procedure Delete
(Container
: in out Set
; Key
: Key_Type
) is
714 X
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
718 raise Constraint_Error
with "attempt to delete key not in set";
721 Tree_Operations
.Delete_Node_Sans_Free
(Container
, X
);
722 Tree_Operations
.Free
(Container
, X
);
729 function Element
(Container
: Set
; Key
: Key_Type
) return Element_Type
is
730 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
734 raise Constraint_Error
with "key not in set";
737 return Container
.Nodes
(Node
).Element
;
740 ---------------------
741 -- Equivalent_Keys --
742 ---------------------
744 function Equivalent_Keys
(Left
, Right
: Key_Type
) return Boolean is
746 return (if Left
< Right
or else Right
< Left
then False else True);
753 procedure Exclude
(Container
: in out Set
; Key
: Key_Type
) is
754 X
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
757 Tree_Operations
.Delete_Node_Sans_Free
(Container
, X
);
758 Tree_Operations
.Free
(Container
, X
);
766 function Find
(Container
: Set
; Key
: Key_Type
) return Cursor
is
767 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
769 return (if Node
= 0 then No_Element
770 else Cursor
'(Container'Unrestricted_Access, Node));
777 function Floor (Container : Set; Key : Key_Type) return Cursor is
778 Node : constant Count_Type := Key_Keys.Floor (Container, Key);
780 return (if Node = 0 then No_Element
781 else Cursor'(Container
'Unrestricted_Access, Node
));
784 -------------------------
785 -- Is_Greater_Key_Node --
786 -------------------------
788 function Is_Greater_Key_Node
790 Right
: Node_Type
) return Boolean
793 return Key
(Right
.Element
) < Left
;
794 end Is_Greater_Key_Node
;
796 ----------------------
797 -- Is_Less_Key_Node --
798 ----------------------
800 function Is_Less_Key_Node
802 Right
: Node_Type
) return Boolean
805 return Left
< Key
(Right
.Element
);
806 end Is_Less_Key_Node
;
812 function Key
(Position
: Cursor
) return Key_Type
is
814 if Position
.Node
= 0 then
815 raise Constraint_Error
with
816 "Position cursor equals No_Element";
819 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
820 "bad cursor in Key");
822 return Key
(Position
.Container
.Nodes
(Position
.Node
).Element
);
830 (Container
: in out Set
;
832 New_Item
: Element_Type
)
834 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
838 raise Constraint_Error
with
839 "attempt to replace key not in set";
842 Replace_Element
(Container
, Node
, New_Item
);
845 -----------------------------------
846 -- Update_Element_Preserving_Key --
847 -----------------------------------
849 procedure Update_Element_Preserving_Key
850 (Container
: in out Set
;
852 Process
: not null access procedure (Element
: in out Element_Type
))
855 if Position
.Node
= 0 then
856 raise Constraint_Error
with
857 "Position cursor equals No_Element";
860 if Position
.Container
/= Container
'Unrestricted_Access then
861 raise Program_Error
with
862 "Position cursor designates wrong set";
865 pragma Assert
(Vet
(Container
, Position
.Node
),
866 "bad cursor in Update_Element_Preserving_Key");
869 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
870 E
: Element_Type
renames N
.Element
;
871 K
: constant Key_Type
:= Key
(E
);
873 B
: Natural renames Container
.Busy
;
874 L
: Natural renames Container
.Lock
;
892 if Equivalent_Keys
(K
, Key
(E
)) then
897 Tree_Operations
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
898 Tree_Operations
.Free
(Container
, Position
.Node
);
900 raise Program_Error
with "key was modified";
901 end Update_Element_Preserving_Key
;
903 function Reference_Preserving_Key
904 (Container
: aliased in out Set
;
905 Key
: Key_Type
) return Constant_Reference_Type
907 Position
: constant Cursor
:= Find
(Container
, Key
);
910 if Position
.Node
= 0 then
911 raise Constraint_Error
with "Position cursor has no element";
916 Container
.Nodes
(Position
.Node
).Element
'Unrestricted_Access);
917 end Reference_Preserving_Key
;
919 function Reference_Preserving_Key
920 (Container
: aliased in out Set
;
921 Key
: Key_Type
) return Reference_Type
923 Position
: constant Cursor
:= Find
(Container
, Key
);
926 if Position
.Node
= 0 then
927 raise Constraint_Error
with "Position cursor has no element";
932 Container
.Nodes
(Position
.Node
).Element
'Unrestricted_Access);
933 end Reference_Preserving_Key
;
936 (Stream
: not null access Root_Stream_Type
'Class;
937 Item
: out Reference_Type
)
940 raise Program_Error
with "attempt to stream reference";
944 (Stream
: not null access Root_Stream_Type
'Class;
945 Item
: Reference_Type
)
948 raise Program_Error
with "attempt to stream reference";
956 function Has_Element
(Position
: Cursor
) return Boolean is
958 return Position
/= No_Element
;
965 procedure Include
(Container
: in out Set
; New_Item
: Element_Type
) is
970 Insert
(Container
, New_Item
, Position
, Inserted
);
973 if Container
.Lock
> 0 then
974 raise Program_Error
with
975 "attempt to tamper with elements (set is locked)";
978 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
987 (Container
: in out Set
;
988 New_Item
: Element_Type
;
989 Position
: out Cursor
;
990 Inserted
: out Boolean)
999 Position
.Container
:= Container
'Unrestricted_Access;
1003 (Container
: in out Set
;
1004 New_Item
: Element_Type
)
1007 pragma Unreferenced
(Position
);
1012 Insert
(Container
, New_Item
, Position
, Inserted
);
1014 if not Inserted
then
1015 raise Constraint_Error
with
1016 "attempt to insert element already in set";
1020 ----------------------
1021 -- Insert_Sans_Hint --
1022 ----------------------
1024 procedure Insert_Sans_Hint
1025 (Container
: in out Set
;
1026 New_Item
: Element_Type
;
1027 Node
: out Count_Type
;
1028 Inserted
: out Boolean)
1030 procedure Set_Element
(Node
: in out Node_Type
);
1031 pragma Inline
(Set_Element
);
1033 function New_Node
return Count_Type
;
1034 pragma Inline
(New_Node
);
1036 procedure Insert_Post
is
1037 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1039 procedure Conditional_Insert_Sans_Hint
is
1040 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1042 procedure Allocate
is
1043 new Tree_Operations
.Generic_Allocate
(Set_Element
);
1049 function New_Node
return Count_Type
is
1050 Result
: Count_Type
;
1052 Allocate
(Container
, Result
);
1060 procedure Set_Element
(Node
: in out Node_Type
) is
1062 Node
.Element
:= New_Item
;
1065 -- Start of processing for Insert_Sans_Hint
1068 Conditional_Insert_Sans_Hint
1073 end Insert_Sans_Hint
;
1075 ----------------------
1076 -- Insert_With_Hint --
1077 ----------------------
1079 procedure Insert_With_Hint
1080 (Dst_Set
: in out Set
;
1081 Dst_Hint
: Count_Type
;
1082 Src_Node
: Node_Type
;
1083 Dst_Node
: out Count_Type
)
1086 pragma Unreferenced
(Success
);
1088 procedure Set_Element
(Node
: in out Node_Type
);
1089 pragma Inline
(Set_Element
);
1091 function New_Node
return Count_Type
;
1092 pragma Inline
(New_Node
);
1094 procedure Insert_Post
is
1095 new Element_Keys
.Generic_Insert_Post
(New_Node
);
1097 procedure Insert_Sans_Hint
is
1098 new Element_Keys
.Generic_Conditional_Insert
(Insert_Post
);
1100 procedure Local_Insert_With_Hint
is
1101 new Element_Keys
.Generic_Conditional_Insert_With_Hint
1105 procedure Allocate
is
1106 new Tree_Operations
.Generic_Allocate
(Set_Element
);
1112 function New_Node
return Count_Type
is
1113 Result
: Count_Type
;
1115 Allocate
(Dst_Set
, Result
);
1123 procedure Set_Element
(Node
: in out Node_Type
) is
1125 Node
.Element
:= Src_Node
.Element
;
1128 -- Start of processing for Insert_With_Hint
1131 Local_Insert_With_Hint
1137 end Insert_With_Hint
;
1143 procedure Intersection
(Target
: in out Set
; Source
: Set
)
1144 renames Set_Ops
.Set_Intersection
;
1146 function Intersection
(Left
, Right
: Set
) return Set
1147 renames Set_Ops
.Set_Intersection
;
1153 function Is_Empty
(Container
: Set
) return Boolean is
1155 return Container
.Length
= 0;
1158 -----------------------------
1159 -- Is_Greater_Element_Node --
1160 -----------------------------
1162 function Is_Greater_Element_Node
1163 (Left
: Element_Type
;
1164 Right
: Node_Type
) return Boolean
1167 -- Compute e > node same as node < e
1169 return Right
.Element
< Left
;
1170 end Is_Greater_Element_Node
;
1172 --------------------------
1173 -- Is_Less_Element_Node --
1174 --------------------------
1176 function Is_Less_Element_Node
1177 (Left
: Element_Type
;
1178 Right
: Node_Type
) return Boolean
1181 return Left
< Right
.Element
;
1182 end Is_Less_Element_Node
;
1184 -----------------------
1185 -- Is_Less_Node_Node --
1186 -----------------------
1188 function Is_Less_Node_Node
(L
, R
: Node_Type
) return Boolean is
1190 return L
.Element
< R
.Element
;
1191 end Is_Less_Node_Node
;
1197 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean
1198 renames Set_Ops
.Set_Subset
;
1206 Process
: not null access procedure (Position
: Cursor
))
1208 procedure Process_Node
(Node
: Count_Type
);
1209 pragma Inline
(Process_Node
);
1211 procedure Local_Iterate
is
1212 new Tree_Operations
.Generic_Iteration
(Process_Node
);
1218 procedure Process_Node
(Node
: Count_Type
) is
1220 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1223 S : Set renames Container'Unrestricted_Access.all;
1224 B : Natural renames S.Busy;
1226 -- Start of processing for Iterate
1242 function Iterate (Container : Set)
1243 return Set_Iterator_Interfaces.Reversible_Iterator'class
1245 B : Natural renames Container'Unrestricted_Access.all.Busy;
1248 -- The value of the Node component influences the behavior of the First
1249 -- and Last selector functions of the iterator object. When the Node
1250 -- component is 0 (as is the case here), this means the iterator object
1251 -- was constructed without a start expression. This is a complete
1252 -- iterator, meaning that the iteration starts from the (logical)
1253 -- beginning of the sequence of items.
1255 -- Note: For a forward iterator, Container.First is the beginning, and
1256 -- for a reverse iterator, Container.Last is the beginning.
1258 return It : constant Iterator :=
1259 Iterator'(Limited_Controlled
with
1260 Container
=> Container
'Unrestricted_Access,
1267 function Iterate
(Container
: Set
; Start
: Cursor
)
1268 return Set_Iterator_Interfaces
.Reversible_Iterator
'class
1270 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
1273 -- It was formerly the case that when Start = No_Element, the partial
1274 -- iterator was defined to behave the same as for a complete iterator,
1275 -- and iterate over the entire sequence of items. However, those
1276 -- semantics were unintuitive and arguably error-prone (it is too easy
1277 -- to accidentally create an endless loop), and so they were changed,
1278 -- per the ARG meeting in Denver on 2011/11. However, there was no
1279 -- consensus about what positive meaning this corner case should have,
1280 -- and so it was decided to simply raise an exception. This does imply,
1281 -- however, that it is not possible to use a partial iterator to specify
1282 -- an empty sequence of items.
1284 if Start
= No_Element
then
1285 raise Constraint_Error
with
1286 "Start position for iterator equals No_Element";
1289 if Start
.Container
/= Container
'Unrestricted_Access then
1290 raise Program_Error
with
1291 "Start cursor of Iterate designates wrong set";
1294 pragma Assert
(Vet
(Container
, Start
.Node
),
1295 "Start cursor of Iterate is bad");
1297 -- The value of the Node component influences the behavior of the First
1298 -- and Last selector functions of the iterator object. When the Node
1299 -- component is positive (as is the case here), it means that this
1300 -- is a partial iteration, over a subset of the complete sequence of
1301 -- items. The iterator object was constructed with a start expression,
1302 -- indicating the position from which the iteration begins. (Note that
1303 -- the start position has the same value irrespective of whether this
1304 -- is a forward or reverse iteration.)
1306 return It
: constant Iterator
:=
1307 Iterator
'(Limited_Controlled with
1308 Container => Container'Unrestricted_Access,
1319 function Last (Container : Set) return Cursor is
1321 return (if Container.Last = 0 then No_Element
1322 else Cursor'(Container
'Unrestricted_Access, Container
.Last
));
1325 function Last
(Object
: Iterator
) return Cursor
is
1327 -- The value of the iterator object's Node component influences the
1328 -- behavior of the Last (and First) selector function.
1330 -- When the Node component is 0, this means the iterator object was
1331 -- constructed without a start expression, in which case the (reverse)
1332 -- iteration starts from the (logical) beginning of the entire sequence
1333 -- (corresponding to Container.Last, for a reverse iterator).
1335 -- Otherwise, this is iteration over a partial sequence of items. When
1336 -- the Node component is positive, the iterator object was constructed
1337 -- with a start expression, that specifies the position from which the
1338 -- (reverse) partial iteration begins.
1340 if Object
.Node
= 0 then
1341 return Bounded_Ordered_Sets
.Last
(Object
.Container
.all);
1343 return Cursor
'(Object.Container, Object.Node);
1351 function Last_Element (Container : Set) return Element_Type is
1353 if Container.Last = 0 then
1354 raise Constraint_Error with "set is empty";
1357 return Container.Nodes (Container.Last).Element;
1364 function Left (Node : Node_Type) return Count_Type is
1373 function Length (Container : Set) return Count_Type is
1375 return Container.Length;
1382 procedure Move (Target : in out Set; Source : in out Set) is
1384 if Target'Address = Source'Address then
1388 if Source.Busy > 0 then
1389 raise Program_Error with
1390 "attempt to tamper with cursors (container is busy)";
1393 Target.Assign (Source);
1401 function Next (Position : Cursor) return Cursor is
1403 if Position = No_Element then
1407 pragma Assert (Vet (Position.Container.all, Position.Node),
1408 "bad cursor in Next");
1411 Node : constant Count_Type :=
1412 Tree_Operations.Next (Position.Container.all, Position.Node);
1419 return Cursor'(Position
.Container
, Node
);
1423 procedure Next
(Position
: in out Cursor
) is
1425 Position
:= Next
(Position
);
1428 function Next
(Object
: Iterator
; Position
: Cursor
) return Cursor
is
1430 if Position
.Container
= null then
1434 if Position
.Container
/= Object
.Container
then
1435 raise Program_Error
with
1436 "Position cursor of Next designates wrong set";
1439 return Next
(Position
);
1446 function Overlap
(Left
, Right
: Set
) return Boolean
1447 renames Set_Ops
.Set_Overlap
;
1453 function Parent
(Node
: Node_Type
) return Count_Type
is
1462 function Previous
(Position
: Cursor
) return Cursor
is
1464 if Position
= No_Element
then
1468 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1469 "bad cursor in Previous");
1472 Node
: constant Count_Type
:=
1473 Tree_Operations
.Previous
1474 (Position
.Container
.all,
1477 return (if Node
= 0 then No_Element
1478 else Cursor
'(Position.Container, Node));
1482 procedure Previous (Position : in out Cursor) is
1484 Position := Previous (Position);
1487 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1489 if Position.Container = null then
1493 if Position.Container /= Object.Container then
1494 raise Program_Error with
1495 "Position cursor of Previous designates wrong set";
1498 return Previous (Position);
1505 procedure Query_Element
1507 Process : not null access procedure (Element : Element_Type))
1510 if Position.Node = 0 then
1511 raise Constraint_Error with "Position cursor equals No_Element";
1514 pragma Assert (Vet (Position.Container.all, Position.Node),
1515 "bad cursor in Query_Element");
1518 S : Set renames Position.Container.all;
1519 B : Natural renames S.Busy;
1520 L : Natural renames S.Lock;
1527 Process (S.Nodes (Position.Node).Element);
1545 (Stream : not null access Root_Stream_Type'Class;
1546 Container : out Set)
1548 procedure Read_Element (Node : in out Node_Type);
1549 pragma Inline (Read_Element);
1551 procedure Allocate is
1552 new Tree_Operations.Generic_Allocate (Read_Element);
1554 procedure Read_Elements is
1555 new Tree_Operations.Generic_Read (Allocate);
1561 procedure Read_Element (Node : in out Node_Type) is
1563 Element_Type'Read (Stream, Node.Element);
1566 -- Start of processing for Read
1569 Read_Elements (Stream, Container);
1573 (Stream : not null access Root_Stream_Type'Class;
1577 raise Program_Error with "attempt to stream set cursor";
1581 (Stream : not null access Root_Stream_Type'Class;
1582 Item : out Constant_Reference_Type)
1585 raise Program_Error with "attempt to stream reference";
1592 function Constant_Reference (Container : Set; Position : Cursor)
1593 return Constant_Reference_Type
1596 if Position.Container = null then
1597 raise Constraint_Error with "Position cursor has no element";
1601 Container.Nodes (Position.Node).Element'Unrestricted_Access);
1602 end Constant_Reference;
1608 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1609 Node : constant Count_Type := Element_Keys.Find (Container, New_Item);
1613 raise Constraint_Error with
1614 "attempt to replace element not in set";
1617 if Container.Lock > 0 then
1618 raise Program_Error with
1619 "attempt to tamper with elements (set is locked)";
1622 Container.Nodes (Node).Element := New_Item;
1625 ---------------------
1626 -- Replace_Element --
1627 ---------------------
1629 procedure Replace_Element
1630 (Container : in out Set;
1632 Item : Element_Type)
1634 pragma Assert (Index /= 0);
1636 function New_Node return Count_Type;
1637 pragma Inline (New_Node);
1639 procedure Local_Insert_Post is
1640 new Element_Keys.Generic_Insert_Post (New_Node);
1642 procedure Local_Insert_Sans_Hint is
1643 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1645 procedure Local_Insert_With_Hint is
1646 new Element_Keys.Generic_Conditional_Insert_With_Hint
1648 Local_Insert_Sans_Hint);
1650 Nodes : Nodes_Type renames Container.Nodes;
1651 Node : Node_Type renames Nodes (Index);
1657 function New_Node return Count_Type is
1659 Node.Element := Item;
1660 Node.Color := Red_Black_Trees.Red;
1668 Result : Count_Type;
1671 -- Start of processing for Replace_Element
1674 if Item < Node.Element
1675 or else Node.Element < Item
1680 if Container.Lock > 0 then
1681 raise Program_Error with
1682 "attempt to tamper with elements (set is locked)";
1685 Node.Element := Item;
1689 Hint := Element_Keys.Ceiling (Container, Item);
1694 elsif Item < Nodes (Hint).Element then
1695 if Hint = Index then
1696 if Container.Lock > 0 then
1697 raise Program_Error with
1698 "attempt to tamper with elements (set is locked)";
1701 Node.Element := Item;
1706 pragma Assert (not (Nodes (Hint).Element < Item));
1707 raise Program_Error with "attempt to replace existing element";
1710 Tree_Operations.Delete_Node_Sans_Free (Container, Index);
1712 Local_Insert_With_Hint
1717 Inserted => Inserted);
1719 pragma Assert (Inserted);
1720 pragma Assert (Result = Index);
1721 end Replace_Element;
1723 procedure Replace_Element
1724 (Container : in out Set;
1726 New_Item : Element_Type)
1729 if Position.Node = 0 then
1730 raise Constraint_Error with
1731 "Position cursor equals No_Element";
1734 if Position.Container /= Container'Unrestricted_Access then
1735 raise Program_Error with
1736 "Position cursor designates wrong set";
1739 pragma Assert (Vet (Container, Position.Node),
1740 "bad cursor in Replace_Element");
1742 Replace_Element (Container, Position.Node, New_Item);
1743 end Replace_Element;
1745 ---------------------
1746 -- Reverse_Iterate --
1747 ---------------------
1749 procedure Reverse_Iterate
1751 Process : not null access procedure (Position : Cursor))
1753 procedure Process_Node (Node : Count_Type);
1754 pragma Inline (Process_Node);
1756 procedure Local_Reverse_Iterate is
1757 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1763 procedure Process_Node (Node : Count_Type) is
1765 Process (Cursor'(Container
'Unrestricted_Access, Node
));
1768 S
: Set
renames Container
'Unrestricted_Access.all;
1769 B
: Natural renames S
.Busy
;
1771 -- Start of processing for Reverse_Iterate
1777 Local_Reverse_Iterate
(S
);
1785 end Reverse_Iterate
;
1791 function Right
(Node
: Node_Type
) return Count_Type
is
1801 (Node
: in out Node_Type
;
1802 Color
: Red_Black_Trees
.Color_Type
)
1805 Node
.Color
:= Color
;
1812 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
) is
1821 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
) is
1823 Node
.Parent
:= Parent
;
1830 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
) is
1832 Node
.Right
:= Right
;
1835 --------------------------
1836 -- Symmetric_Difference --
1837 --------------------------
1839 procedure Symmetric_Difference
(Target
: in out Set
; Source
: Set
)
1840 renames Set_Ops
.Set_Symmetric_Difference
;
1842 function Symmetric_Difference
(Left
, Right
: Set
) return Set
1843 renames Set_Ops
.Set_Symmetric_Difference
;
1849 function To_Set
(New_Item
: Element_Type
) return Set
is
1853 return S
: Set
(1) do
1854 Insert_Sans_Hint
(S
, New_Item
, Node
, Inserted
);
1855 pragma Assert
(Inserted
);
1863 procedure Union
(Target
: in out Set
; Source
: Set
)
1864 renames Set_Ops
.Set_Union
;
1866 function Union
(Left
, Right
: Set
) return Set
1867 renames Set_Ops
.Set_Union
;
1874 (Stream
: not null access Root_Stream_Type
'Class;
1877 procedure Write_Element
1878 (Stream
: not null access Root_Stream_Type
'Class;
1880 pragma Inline
(Write_Element
);
1882 procedure Write_Elements
is
1883 new Tree_Operations
.Generic_Write
(Write_Element
);
1889 procedure Write_Element
1890 (Stream
: not null access Root_Stream_Type
'Class;
1894 Element_Type
'Write (Stream
, Node
.Element
);
1897 -- Start of processing for Write
1900 Write_Elements
(Stream
, Container
);
1904 (Stream
: not null access Root_Stream_Type
'Class;
1908 raise Program_Error
with "attempt to stream set cursor";
1912 (Stream
: not null access Root_Stream_Type
'Class;
1913 Item
: Constant_Reference_Type
)
1916 raise Program_Error
with "attempt to stream reference";
1919 end Ada
.Containers
.Bounded_Ordered_Sets
;