1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . F O R M A L _ H A S H E D _ S E T S --
9 -- Copyright (C) 2010-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/>. --
26 ------------------------------------------------------------------------------
28 with Ada
.Containers
.Hash_Tables
.Generic_Bounded_Operations
;
29 pragma Elaborate_All
(Ada
.Containers
.Hash_Tables
.Generic_Bounded_Operations
);
31 with Ada
.Containers
.Hash_Tables
.Generic_Bounded_Keys
;
32 pragma Elaborate_All
(Ada
.Containers
.Hash_Tables
.Generic_Bounded_Keys
);
34 with Ada
.Containers
.Prime_Numbers
; use Ada
.Containers
.Prime_Numbers
;
36 with System
; use type System
.Address
;
38 package body Ada
.Containers
.Formal_Hashed_Sets
with
41 pragma Annotate
(CodePeer
, Skip_Analysis
);
43 -----------------------
44 -- Local Subprograms --
45 -----------------------
47 -- All need comments ???
53 function Equivalent_Keys
55 Node
: Node_Type
) return Boolean;
56 pragma Inline
(Equivalent_Keys
);
63 with procedure Set_Element
(Node
: in out Node_Type
);
64 procedure Generic_Allocate
66 Node
: out Count_Type
);
68 function Hash_Node
(Node
: Node_Type
) return Hash_Type
;
69 pragma Inline
(Hash_Node
);
72 (Container
: in out Set
;
73 New_Item
: Element_Type
;
74 Node
: out Count_Type
;
75 Inserted
: out Boolean);
77 procedure Intersection
84 Key
: Node_Type
) return Boolean;
85 pragma Inline
(Is_In
);
87 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
);
88 pragma Inline
(Set_Element
);
90 function Next
(Node
: Node_Type
) return Count_Type
;
93 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
);
94 pragma Inline
(Set_Next
);
96 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean;
98 --------------------------
99 -- Local Instantiations --
100 --------------------------
102 package HT_Ops
is new Hash_Tables
.Generic_Bounded_Operations
103 (HT_Types
=> HT_Types
,
104 Hash_Node
=> Hash_Node
,
106 Set_Next
=> Set_Next
);
108 package Element_Keys
is new Hash_Tables
.Generic_Bounded_Keys
109 (HT_Types
=> HT_Types
,
111 Set_Next
=> Set_Next
,
112 Key_Type
=> Element_Type
,
114 Equivalent_Keys
=> Equivalent_Keys
);
116 procedure Replace_Element
is
117 new Element_Keys
.Generic_Replace_Element
(Hash_Node
, Set_Element
);
123 function "=" (Left
, Right
: Set
) return Boolean is
125 if Length
(Left
) /= Length
(Right
) then
129 if Length
(Left
) = 0 then
138 Node
:= First
(Left
).Node
;
140 ENode
:= Find
(Container
=> Right
,
141 Item
=> Left
.Nodes
(Node
).Element
).Node
;
143 Right
.Nodes
(ENode
).Element
/= Left
.Nodes
(Node
).Element
148 Node
:= HT_Ops
.Next
(Left
, Node
);
161 procedure Assign
(Target
: in out Set
; Source
: Set
) is
162 procedure Insert_Element
(Source_Node
: Count_Type
);
164 procedure Insert_Elements
is
165 new HT_Ops
.Generic_Iteration
(Insert_Element
);
171 procedure Insert_Element
(Source_Node
: Count_Type
) is
172 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
177 Insert
(Target
, N
.Element
, X
, B
);
181 -- Start of processing for Assign
184 if Target
'Address = Source
'Address then
188 if Target
.Capacity
< Length
(Source
) then
189 raise Storage_Error
with "not enough capacity"; -- SE or CE? ???
192 HT_Ops
.Clear
(Target
);
193 Insert_Elements
(Source
);
200 function Capacity
(Container
: Set
) return Count_Type
is
202 return Container
.Nodes
'Length;
209 procedure Clear
(Container
: in out Set
) is
211 HT_Ops
.Clear
(Container
);
218 function Contains
(Container
: Set
; Item
: Element_Type
) return Boolean is
220 return Find
(Container
, Item
) /= No_Element
;
229 Capacity
: Count_Type
:= 0) return Set
231 C
: constant Count_Type
:=
232 Count_Type
'Max (Capacity
, Source
.Capacity
);
235 Target
: Set
(C
, Source
.Modulus
);
239 if 0 < Capacity
and then Capacity
< Source
.Capacity
then
240 raise Capacity_Error
;
243 Target
.Length
:= Source
.Length
;
244 Target
.Free
:= Source
.Free
;
247 while H
<= Source
.Modulus
loop
248 Target
.Buckets
(H
) := Source
.Buckets
(H
);
253 while N
<= Source
.Capacity
loop
254 Target
.Nodes
(N
) := Source
.Nodes
(N
);
260 Free
(Target
, Cu
.Node
);
267 ---------------------
268 -- Current_To_Last --
269 ---------------------
271 function Current_To_Last
(Container
: Set
; Current
: Cursor
) return Set
is
272 Curs
: Cursor
:= First
(Container
);
273 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
274 Copy
(Container
, Container
.Capacity
);
278 if Curs
= No_Element
then
282 elsif Current
/= No_Element
and not Has_Element
(Container
, Current
) then
283 raise Constraint_Error
;
286 while Curs
.Node
/= Current
.Node
loop
289 Curs
:= Next
(Container
, (Node
=> Node
));
296 ---------------------
297 -- Default_Modulus --
298 ---------------------
300 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
302 return To_Prime
(Capacity
);
310 (Container
: in out Set
;
316 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
319 raise Constraint_Error
with "attempt to delete element not in set";
326 (Container
: in out Set
;
327 Position
: in out Cursor
)
330 if not Has_Element
(Container
, Position
) then
331 raise Constraint_Error
with "Position cursor has no element";
334 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Delete");
336 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
337 Free
(Container
, Position
.Node
);
339 Position
:= No_Element
;
347 (Target
: in out Set
;
350 Tgt_Node
, Src_Node
, Src_Last
, Src_Length
: Count_Type
;
352 TN
: Nodes_Type
renames Target
.Nodes
;
353 SN
: Nodes_Type
renames Source
.Nodes
;
356 if Target
'Address = Source
'Address then
361 Src_Length
:= Source
.Length
;
363 if Src_Length
= 0 then
367 if Src_Length
>= Target
.Length
then
368 Tgt_Node
:= HT_Ops
.First
(Target
);
369 while Tgt_Node
/= 0 loop
370 if Element_Keys
.Find
(Source
, TN
(Tgt_Node
).Element
) /= 0 then
372 X
: constant Count_Type
:= Tgt_Node
;
374 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
375 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
380 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
386 Src_Node
:= HT_Ops
.First
(Source
);
390 while Src_Node
/= Src_Last
loop
391 Tgt_Node
:= Element_Keys
.Find
(Target
, SN
(Src_Node
).Element
);
393 if Tgt_Node
/= 0 then
394 HT_Ops
.Delete_Node_Sans_Free
(Target
, Tgt_Node
);
395 Free
(Target
, Tgt_Node
);
398 Src_Node
:= HT_Ops
.Next
(Source
, Src_Node
);
406 procedure Process
(L_Node
: Count_Type
);
409 new HT_Ops
.Generic_Iteration
(Process
);
415 procedure Process
(L_Node
: Count_Type
) is
416 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
420 if Find
(Right
, E
).Node
= 0 then
421 Insert
(Target
, E
, X
, B
);
426 -- Start of processing for Difference
432 function Difference
(Left
, Right
: Set
) return Set
is
437 if Left
'Address = Right
'Address then
441 if Length
(Left
) = 0 then
445 if Length
(Right
) = 0 then
450 H
:= Default_Modulus
(C
);
452 return S
: Set
(C
, H
) do
453 Difference
(Left
, Right
, Target
=> S
);
463 Position
: Cursor
) return Element_Type
466 if not Has_Element
(Container
, Position
) then
467 raise Constraint_Error
with "Position cursor equals No_Element";
470 pragma Assert
(Vet
(Container
, Position
),
471 "bad cursor in function Element");
473 return Container
.Nodes
(Position
.Node
).Element
;
476 ---------------------
477 -- Equivalent_Sets --
478 ---------------------
480 function Equivalent_Sets
(Left
, Right
: Set
) return Boolean is
482 function Find_Equivalent_Key
483 (R_HT
: Hash_Table_Type
'Class;
484 L_Node
: Node_Type
) return Boolean;
485 pragma Inline
(Find_Equivalent_Key
);
487 function Is_Equivalent
is
488 new HT_Ops
.Generic_Equal
(Find_Equivalent_Key
);
490 -------------------------
491 -- Find_Equivalent_Key --
492 -------------------------
494 function Find_Equivalent_Key
495 (R_HT
: Hash_Table_Type
'Class;
496 L_Node
: Node_Type
) return Boolean
498 R_Index
: constant Hash_Type
:=
499 Element_Keys
.Index
(R_HT
, L_Node
.Element
);
500 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
501 RN
: Nodes_Type
renames R_HT
.Nodes
;
509 if Equivalent_Elements
510 (L_Node
.Element
, RN
(R_Node
).Element
)
515 R_Node
:= HT_Ops
.Next
(R_HT
, R_Node
);
517 end Find_Equivalent_Key
;
519 -- Start of processing of Equivalent_Sets
522 return Is_Equivalent
(Left
, Right
);
525 -------------------------
526 -- Equivalent_Elements --
527 -------------------------
529 function Equivalent_Elements
533 CRight
: Cursor
) return Boolean
536 if not Has_Element
(Left
, CLeft
) then
537 raise Constraint_Error
with
538 "Left cursor of Equivalent_Elements has no element";
541 if not Has_Element
(Right
, CRight
) then
542 raise Constraint_Error
with
543 "Right cursor of Equivalent_Elements has no element";
546 pragma Assert
(Vet
(Left
, CLeft
),
547 "bad Left cursor in Equivalent_Elements");
548 pragma Assert
(Vet
(Right
, CRight
),
549 "bad Right cursor in Equivalent_Elements");
552 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
553 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
555 return Equivalent_Elements
(LN
.Element
, RN
.Element
);
557 end Equivalent_Elements
;
559 function Equivalent_Elements
562 Right
: Element_Type
) return Boolean
565 if not Has_Element
(Left
, CLeft
) then
566 raise Constraint_Error
with
567 "Left cursor of Equivalent_Elements has no element";
570 pragma Assert
(Vet
(Left
, CLeft
),
571 "Left cursor in Equivalent_Elements is bad");
574 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
576 return Equivalent_Elements
(LN
.Element
, Right
);
578 end Equivalent_Elements
;
580 function Equivalent_Elements
581 (Left
: Element_Type
;
583 CRight
: Cursor
) return Boolean
586 if not Has_Element
(Right
, CRight
) then
587 raise Constraint_Error
with
588 "Right cursor of Equivalent_Elements has no element";
592 (Vet
(Right
, CRight
),
593 "Right cursor of Equivalent_Elements is bad");
596 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
598 return Equivalent_Elements
(Left
, RN
.Element
);
600 end Equivalent_Elements
;
602 ---------------------
603 -- Equivalent_Keys --
604 ---------------------
606 function Equivalent_Keys
608 Node
: Node_Type
) return Boolean
611 return Equivalent_Elements
(Key
, Node
.Element
);
619 (Container
: in out Set
;
624 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
634 Item
: Element_Type
) return Cursor
636 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, Item
);
643 return (Node
=> Node
);
650 function First
(Container
: Set
) return Cursor
is
651 Node
: constant Count_Type
:= HT_Ops
.First
(Container
);
658 return (Node
=> Node
);
661 -----------------------
662 -- First_To_Previous --
663 -----------------------
665 function First_To_Previous
667 Current
: Cursor
) return Set
669 Curs
: Cursor
:= Current
;
670 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
671 Copy
(Container
, Container
.Capacity
);
675 if Curs
= No_Element
then
678 elsif not Has_Element
(Container
, Curs
) then
679 raise Constraint_Error
;
682 while Curs
.Node
/= 0 loop
685 Curs
:= Next
(Container
, (Node
=> Node
));
690 end First_To_Previous
;
701 HT
.Nodes
(X
).Has_Element
:= False;
705 ----------------------
706 -- Generic_Allocate --
707 ----------------------
709 procedure Generic_Allocate
711 Node
: out Count_Type
)
713 procedure Allocate
is new HT_Ops
.Generic_Allocate
(Set_Element
);
716 HT
.Nodes
(Node
).Has_Element
:= True;
717 end Generic_Allocate
;
723 function Has_Element
(Container
: Set
; Position
: Cursor
) return Boolean is
726 or else not Container
.Nodes
(Position
.Node
).Has_Element
738 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
740 return Hash
(Node
.Element
);
748 (Container
: in out Set
;
749 New_Item
: Element_Type
)
755 Insert
(Container
, New_Item
, Position
, Inserted
);
758 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
767 (Container
: in out Set
;
768 New_Item
: Element_Type
;
769 Position
: out Cursor
;
770 Inserted
: out Boolean)
773 Insert
(Container
, New_Item
, Position
.Node
, Inserted
);
777 (Container
: in out Set
;
778 New_Item
: Element_Type
)
784 Insert
(Container
, New_Item
, Position
, Inserted
);
787 raise Constraint_Error
with
788 "attempt to insert element already in set";
793 (Container
: in out Set
;
794 New_Item
: Element_Type
;
795 Node
: out Count_Type
;
796 Inserted
: out Boolean)
798 procedure Allocate_Set_Element
(Node
: in out Node_Type
);
799 pragma Inline
(Allocate_Set_Element
);
801 function New_Node
return Count_Type
;
802 pragma Inline
(New_Node
);
804 procedure Local_Insert
is
805 new Element_Keys
.Generic_Conditional_Insert
(New_Node
);
807 procedure Allocate
is
808 new Generic_Allocate
(Allocate_Set_Element
);
810 ---------------------------
811 -- Allocate_Set_Element --
812 ---------------------------
814 procedure Allocate_Set_Element
(Node
: in out Node_Type
) is
816 Node
.Element
:= New_Item
;
817 end Allocate_Set_Element
;
823 function New_Node
return Count_Type
is
826 Allocate
(Container
, Result
);
830 -- Start of processing for Insert
833 Local_Insert
(Container
, New_Item
, Node
, Inserted
);
840 procedure Intersection
841 (Target
: in out Set
;
844 Tgt_Node
: Count_Type
;
845 TN
: Nodes_Type
renames Target
.Nodes
;
848 if Target
'Address = Source
'Address then
852 if Source
.Length
= 0 then
857 Tgt_Node
:= HT_Ops
.First
(Target
);
858 while Tgt_Node
/= 0 loop
859 if Find
(Source
, TN
(Tgt_Node
).Element
).Node
/= 0 then
860 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
864 X
: constant Count_Type
:= Tgt_Node
;
866 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
867 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
874 procedure Intersection
879 procedure Process
(L_Node
: Count_Type
);
882 new HT_Ops
.Generic_Iteration
(Process
);
888 procedure Process
(L_Node
: Count_Type
) is
889 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
894 if Find
(Right
, E
).Node
/= 0 then
895 Insert
(Target
, E
, X
, B
);
900 -- Start of processing for Intersection
906 function Intersection
(Left
, Right
: Set
) return Set
is
911 if Left
'Address = Right
'Address then
915 C
:= Count_Type
'Min (Length
(Left
), Length
(Right
)); -- ???
916 H
:= Default_Modulus
(C
);
918 return S
: Set
(C
, H
) do
919 if Length
(Left
) /= 0 and Length
(Right
) /= 0 then
920 Intersection
(Left
, Right
, Target
=> S
);
929 function Is_Empty
(Container
: Set
) return Boolean is
931 return Length
(Container
) = 0;
938 function Is_In
(HT
: Set
; Key
: Node_Type
) return Boolean is
940 return Element_Keys
.Find
(HT
, Key
.Element
) /= 0;
947 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean is
948 Subset_Node
: Count_Type
;
949 Subset_Nodes
: Nodes_Type
renames Subset
.Nodes
;
952 if Subset
'Address = Of_Set
'Address then
956 if Length
(Subset
) > Length
(Of_Set
) then
960 Subset_Node
:= First
(Subset
).Node
;
961 while Subset_Node
/= 0 loop
963 N
: Node_Type
renames Subset_Nodes
(Subset_Node
);
964 E
: Element_Type
renames N
.Element
;
967 if Find
(Of_Set
, E
).Node
= 0 then
972 Subset_Node
:= HT_Ops
.Next
(Subset
, Subset_Node
);
982 function Length
(Container
: Set
) return Count_Type
is
984 return Container
.Length
;
993 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
994 NN
: HT_Types
.Nodes_Type
renames Source
.Nodes
;
998 if Target
'Address = Source
'Address then
1002 if Target
.Capacity
< Length
(Source
) then
1003 raise Constraint_Error
with -- ???
1004 "Source length exceeds Target capacity";
1009 if Source
.Length
= 0 then
1013 X
:= HT_Ops
.First
(Source
);
1015 Insert
(Target
, NN
(X
).Element
); -- optimize???
1017 Y
:= HT_Ops
.Next
(Source
, X
);
1019 HT_Ops
.Delete_Node_Sans_Free
(Source
, X
);
1030 function Next
(Node
: Node_Type
) return Count_Type
is
1035 function Next
(Container
: Set
; Position
: Cursor
) return Cursor
is
1037 if Position
.Node
= 0 then
1041 if not Has_Element
(Container
, Position
) then
1042 raise Constraint_Error
1043 with "Position has no element";
1046 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Next");
1048 return (Node
=> HT_Ops
.Next
(Container
, Position
.Node
));
1051 procedure Next
(Container
: Set
; Position
: in out Cursor
) is
1053 Position
:= Next
(Container
, Position
);
1060 function Overlap
(Left
, Right
: Set
) return Boolean is
1061 Left_Node
: Count_Type
;
1062 Left_Nodes
: Nodes_Type
renames Left
.Nodes
;
1065 if Length
(Right
) = 0 or Length
(Left
) = 0 then
1069 if Left
'Address = Right
'Address then
1073 Left_Node
:= First
(Left
).Node
;
1074 while Left_Node
/= 0 loop
1076 N
: Node_Type
renames Left_Nodes
(Left_Node
);
1077 E
: Element_Type
renames N
.Element
;
1079 if Find
(Right
, E
).Node
/= 0 then
1084 Left_Node
:= HT_Ops
.Next
(Left
, Left_Node
);
1095 (Container
: in out Set
;
1096 New_Item
: Element_Type
)
1098 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, New_Item
);
1102 raise Constraint_Error
with
1103 "attempt to replace element not in set";
1106 Container
.Nodes
(Node
).Element
:= New_Item
;
1109 ---------------------
1110 -- Replace_Element --
1111 ---------------------
1113 procedure Replace_Element
1114 (Container
: in out Set
;
1116 New_Item
: Element_Type
)
1119 if not Has_Element
(Container
, Position
) then
1120 raise Constraint_Error
with
1121 "Position cursor equals No_Element";
1124 pragma Assert
(Vet
(Container
, Position
),
1125 "bad cursor in Replace_Element");
1127 Replace_Element
(Container
, Position
.Node
, New_Item
);
1128 end Replace_Element
;
1130 ----------------------
1131 -- Reserve_Capacity --
1132 ----------------------
1134 procedure Reserve_Capacity
1135 (Container
: in out Set
;
1136 Capacity
: Count_Type
)
1139 if Capacity
> Container
.Capacity
then
1140 raise Constraint_Error
with "requested capacity is too large";
1142 end Reserve_Capacity
;
1148 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
) is
1150 Node
.Element
:= Item
;
1157 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1166 function Strict_Equal
(Left
, Right
: Set
) return Boolean is
1167 CuL
: Cursor
:= First
(Left
);
1168 CuR
: Cursor
:= First
(Right
);
1171 if Length
(Left
) /= Length
(Right
) then
1175 while CuL
.Node
/= 0 or CuR
.Node
/= 0 loop
1176 if CuL
.Node
/= CuR
.Node
1177 or else Left
.Nodes
(CuL
.Node
).Element
/=
1178 Right
.Nodes
(CuR
.Node
).Element
1183 CuL
:= Next
(Left
, CuL
);
1184 CuR
:= Next
(Right
, CuR
);
1190 --------------------------
1191 -- Symmetric_Difference --
1192 --------------------------
1194 procedure Symmetric_Difference
1195 (Target
: in out Set
;
1198 procedure Process
(Source_Node
: Count_Type
);
1199 pragma Inline
(Process
);
1201 procedure Iterate
is new HT_Ops
.Generic_Iteration
(Process
);
1207 procedure Process
(Source_Node
: Count_Type
) is
1208 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
1212 if Is_In
(Target
, N
) then
1213 Delete
(Target
, N
.Element
);
1215 Insert
(Target
, N
.Element
, X
, B
);
1220 -- Start of processing for Symmetric_Difference
1223 if Target
'Address = Source
'Address then
1228 if Length
(Target
) = 0 then
1229 Assign
(Target
, Source
);
1234 end Symmetric_Difference
;
1236 function Symmetric_Difference
(Left
, Right
: Set
) return Set
is
1241 if Left
'Address = Right
'Address then
1245 if Length
(Right
) = 0 then
1249 if Length
(Left
) = 0 then
1253 C
:= Length
(Left
) + Length
(Right
);
1254 H
:= Default_Modulus
(C
);
1256 return S
: Set
(C
, H
) do
1257 Difference
(Left
, Right
, S
);
1258 Difference
(Right
, Left
, S
);
1260 end Symmetric_Difference
;
1266 function To_Set
(New_Item
: Element_Type
) return Set
is
1271 return S
: Set
(Capacity
=> 1, Modulus
=> 1) do
1272 Insert
(S
, New_Item
, X
, B
);
1282 (Target
: in out Set
;
1285 procedure Process
(Src_Node
: Count_Type
);
1287 procedure Iterate
is
1288 new HT_Ops
.Generic_Iteration
(Process
);
1294 procedure Process
(Src_Node
: Count_Type
) is
1295 N
: Node_Type
renames Source
.Nodes
(Src_Node
);
1296 E
: Element_Type
renames N
.Element
;
1302 Insert
(Target
, E
, X
, B
);
1305 -- Start of processing for Union
1308 if Target
'Address = Source
'Address then
1315 function Union
(Left
, Right
: Set
) return Set
is
1320 if Left
'Address = Right
'Address then
1324 if Length
(Right
) = 0 then
1328 if Length
(Left
) = 0 then
1332 C
:= Length
(Left
) + Length
(Right
);
1333 H
:= Default_Modulus
(C
);
1334 return S
: Set
(C
, H
) do
1335 Assign
(Target
=> S
, Source
=> Left
);
1336 Union
(Target
=> S
, Source
=> Right
);
1344 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean is
1346 if Position
.Node
= 0 then
1351 S
: Set
renames Container
;
1352 N
: Nodes_Type
renames S
.Nodes
;
1356 if S
.Length
= 0 then
1360 if Position
.Node
> N
'Last then
1364 if N
(Position
.Node
).Next
= Position
.Node
then
1368 X
:= S
.Buckets
(Element_Keys
.Index
(S
, N
(Position
.Node
).Element
));
1370 for J
in 1 .. S
.Length
loop
1371 if X
= Position
.Node
then
1379 if X
= N
(X
).Next
then -- to prevent unnecessary looping
1390 package body Generic_Keys
is
1392 -----------------------
1393 -- Local Subprograms --
1394 -----------------------
1396 function Equivalent_Key_Node
1398 Node
: Node_Type
) return Boolean;
1399 pragma Inline
(Equivalent_Key_Node
);
1401 --------------------------
1402 -- Local Instantiations --
1403 --------------------------
1406 new Hash_Tables
.Generic_Bounded_Keys
1407 (HT_Types
=> HT_Types
,
1409 Set_Next
=> Set_Next
,
1410 Key_Type
=> Key_Type
,
1412 Equivalent_Keys
=> Equivalent_Key_Node
);
1420 Key
: Key_Type
) return Boolean
1423 return Find
(Container
, Key
) /= No_Element
;
1431 (Container
: in out Set
;
1437 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1440 raise Constraint_Error
with "attempt to delete key not in set";
1443 Free
(Container
, X
);
1452 Key
: Key_Type
) return Element_Type
1454 Node
: constant Count_Type
:= Find
(Container
, Key
).Node
;
1458 raise Constraint_Error
with "key not in map";
1461 return Container
.Nodes
(Node
).Element
;
1464 -------------------------
1465 -- Equivalent_Key_Node --
1466 -------------------------
1468 function Equivalent_Key_Node
1470 Node
: Node_Type
) return Boolean
1473 return Equivalent_Keys
(Key
, Generic_Keys
.Key
(Node
.Element
));
1474 end Equivalent_Key_Node
;
1481 (Container
: in out Set
;
1486 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1487 Free
(Container
, X
);
1496 Key
: Key_Type
) return Cursor
1498 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1500 return (if Node
= 0 then No_Element
else (Node
=> Node
));
1507 function Key
(Container
: Set
; Position
: Cursor
) return Key_Type
is
1509 if not Has_Element
(Container
, Position
) then
1510 raise Constraint_Error
with
1511 "Position cursor has no element";
1515 (Vet
(Container
, Position
), "bad cursor in function Key");
1518 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1520 return Key
(N
.Element
);
1529 (Container
: in out Set
;
1531 New_Item
: Element_Type
)
1533 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1537 raise Constraint_Error
with
1538 "attempt to replace key not in set";
1541 Replace_Element
(Container
, Node
, New_Item
);
1546 end Ada
.Containers
.Formal_Hashed_Sets
;