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-2013, 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
is
40 -----------------------
41 -- Local Subprograms --
42 -----------------------
44 -- All need comments ???
50 function Equivalent_Keys
52 Node
: Node_Type
) return Boolean;
53 pragma Inline
(Equivalent_Keys
);
60 with procedure Set_Element
(Node
: in out Node_Type
);
61 procedure Generic_Allocate
63 Node
: out Count_Type
);
65 function Hash_Node
(Node
: Node_Type
) return Hash_Type
;
66 pragma Inline
(Hash_Node
);
69 (Container
: in out Set
;
70 New_Item
: Element_Type
;
71 Node
: out Count_Type
;
72 Inserted
: out Boolean);
74 procedure Intersection
81 Key
: Node_Type
) return Boolean;
82 pragma Inline
(Is_In
);
84 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
);
85 pragma Inline
(Set_Element
);
87 function Next
(Node
: Node_Type
) return Count_Type
;
90 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
);
91 pragma Inline
(Set_Next
);
93 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean;
95 --------------------------
96 -- Local Instantiations --
97 --------------------------
99 package HT_Ops
is new Hash_Tables
.Generic_Bounded_Operations
100 (HT_Types
=> HT_Types
,
101 Hash_Node
=> Hash_Node
,
103 Set_Next
=> Set_Next
);
105 package Element_Keys
is new Hash_Tables
.Generic_Bounded_Keys
106 (HT_Types
=> HT_Types
,
108 Set_Next
=> Set_Next
,
109 Key_Type
=> Element_Type
,
111 Equivalent_Keys
=> Equivalent_Keys
);
113 procedure Replace_Element
is
114 new Element_Keys
.Generic_Replace_Element
(Hash_Node
, Set_Element
);
120 function "=" (Left
, Right
: Set
) return Boolean is
122 if Length
(Left
) /= Length
(Right
) then
126 if Length
(Left
) = 0 then
135 Node
:= First
(Left
).Node
;
137 ENode
:= Find
(Container
=> Right
,
138 Item
=> Left
.Nodes
(Node
).Element
).Node
;
140 Right
.Nodes
(ENode
).Element
/= Left
.Nodes
(Node
).Element
145 Node
:= HT_Ops
.Next
(Left
, Node
);
158 procedure Assign
(Target
: in out Set
; Source
: Set
) is
159 procedure Insert_Element
(Source_Node
: Count_Type
);
161 procedure Insert_Elements
is
162 new HT_Ops
.Generic_Iteration
(Insert_Element
);
168 procedure Insert_Element
(Source_Node
: Count_Type
) is
169 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
174 Insert
(Target
, N
.Element
, X
, B
);
178 -- Start of processing for Assign
181 if Target
'Address = Source
'Address then
185 if Target
.Capacity
< Length
(Source
) then
186 raise Storage_Error
with "not enough capacity"; -- SE or CE? ???
189 HT_Ops
.Clear
(Target
);
190 Insert_Elements
(Source
);
197 function Capacity
(Container
: Set
) return Count_Type
is
199 return Container
.Nodes
'Length;
206 procedure Clear
(Container
: in out Set
) is
208 HT_Ops
.Clear
(Container
);
215 function Contains
(Container
: Set
; Item
: Element_Type
) return Boolean is
217 return Find
(Container
, Item
) /= No_Element
;
226 Capacity
: Count_Type
:= 0) return Set
228 C
: constant Count_Type
:=
229 Count_Type
'Max (Capacity
, Source
.Capacity
);
232 Target
: Set
(C
, Source
.Modulus
);
236 if 0 < Capacity
and then Capacity
< Source
.Capacity
then
237 raise Capacity_Error
;
240 Target
.Length
:= Source
.Length
;
241 Target
.Free
:= Source
.Free
;
244 while H
<= Source
.Modulus
loop
245 Target
.Buckets
(H
) := Source
.Buckets
(H
);
250 while N
<= Source
.Capacity
loop
251 Target
.Nodes
(N
) := Source
.Nodes
(N
);
257 Free
(Target
, Cu
.Node
);
264 ---------------------
265 -- Current_To_Last --
266 ---------------------
268 function Current_To_Last
(Container
: Set
; Current
: Cursor
) return Set
is
269 Curs
: Cursor
:= First
(Container
);
270 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
271 Copy
(Container
, Container
.Capacity
);
275 if Curs
= No_Element
then
279 elsif Current
/= No_Element
and not Has_Element
(Container
, Current
) then
280 raise Constraint_Error
;
283 while Curs
.Node
/= Current
.Node
loop
286 Curs
:= Next
(Container
, (Node
=> Node
));
293 ---------------------
294 -- Default_Modulus --
295 ---------------------
297 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
299 return To_Prime
(Capacity
);
307 (Container
: in out Set
;
313 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
316 raise Constraint_Error
with "attempt to delete element not in set";
323 (Container
: in out Set
;
324 Position
: in out Cursor
)
327 if not Has_Element
(Container
, Position
) then
328 raise Constraint_Error
with "Position cursor has no element";
331 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Delete");
333 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
334 Free
(Container
, Position
.Node
);
336 Position
:= No_Element
;
344 (Target
: in out Set
;
347 Tgt_Node
, Src_Node
, Src_Last
, Src_Length
: Count_Type
;
349 TN
: Nodes_Type
renames Target
.Nodes
;
350 SN
: Nodes_Type
renames Source
.Nodes
;
353 if Target
'Address = Source
'Address then
358 Src_Length
:= Source
.Length
;
360 if Src_Length
= 0 then
364 if Src_Length
>= Target
.Length
then
365 Tgt_Node
:= HT_Ops
.First
(Target
);
366 while Tgt_Node
/= 0 loop
367 if Element_Keys
.Find
(Source
, TN
(Tgt_Node
).Element
) /= 0 then
369 X
: constant Count_Type
:= Tgt_Node
;
371 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
372 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
377 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
383 Src_Node
:= HT_Ops
.First
(Source
);
387 while Src_Node
/= Src_Last
loop
388 Tgt_Node
:= Element_Keys
.Find
(Target
, SN
(Src_Node
).Element
);
390 if Tgt_Node
/= 0 then
391 HT_Ops
.Delete_Node_Sans_Free
(Target
, Tgt_Node
);
392 Free
(Target
, Tgt_Node
);
395 Src_Node
:= HT_Ops
.Next
(Source
, Src_Node
);
403 procedure Process
(L_Node
: Count_Type
);
406 new HT_Ops
.Generic_Iteration
(Process
);
412 procedure Process
(L_Node
: Count_Type
) is
413 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
417 if Find
(Right
, E
).Node
= 0 then
418 Insert
(Target
, E
, X
, B
);
423 -- Start of processing for Difference
429 function Difference
(Left
, Right
: Set
) return Set
is
434 if Left
'Address = Right
'Address then
438 if Length
(Left
) = 0 then
442 if Length
(Right
) = 0 then
447 H
:= Default_Modulus
(C
);
449 return S
: Set
(C
, H
) do
450 Difference
(Left
, Right
, Target
=> S
);
460 Position
: Cursor
) return Element_Type
463 if not Has_Element
(Container
, Position
) then
464 raise Constraint_Error
with "Position cursor equals No_Element";
467 pragma Assert
(Vet
(Container
, Position
),
468 "bad cursor in function Element");
470 return Container
.Nodes
(Position
.Node
).Element
;
473 ---------------------
474 -- Equivalent_Sets --
475 ---------------------
477 function Equivalent_Sets
(Left
, Right
: Set
) return Boolean is
479 function Find_Equivalent_Key
480 (R_HT
: Hash_Table_Type
'Class;
481 L_Node
: Node_Type
) return Boolean;
482 pragma Inline
(Find_Equivalent_Key
);
484 function Is_Equivalent
is
485 new HT_Ops
.Generic_Equal
(Find_Equivalent_Key
);
487 -------------------------
488 -- Find_Equivalent_Key --
489 -------------------------
491 function Find_Equivalent_Key
492 (R_HT
: Hash_Table_Type
'Class;
493 L_Node
: Node_Type
) return Boolean
495 R_Index
: constant Hash_Type
:=
496 Element_Keys
.Index
(R_HT
, L_Node
.Element
);
497 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
498 RN
: Nodes_Type
renames R_HT
.Nodes
;
506 if Equivalent_Elements
507 (L_Node
.Element
, RN
(R_Node
).Element
)
512 R_Node
:= HT_Ops
.Next
(R_HT
, R_Node
);
514 end Find_Equivalent_Key
;
516 -- Start of processing of Equivalent_Sets
519 return Is_Equivalent
(Left
, Right
);
522 -------------------------
523 -- Equivalent_Elements --
524 -------------------------
526 function Equivalent_Elements
530 CRight
: Cursor
) return Boolean
533 if not Has_Element
(Left
, CLeft
) then
534 raise Constraint_Error
with
535 "Left cursor of Equivalent_Elements has no element";
538 if not Has_Element
(Right
, CRight
) then
539 raise Constraint_Error
with
540 "Right cursor of Equivalent_Elements has no element";
543 pragma Assert
(Vet
(Left
, CLeft
),
544 "bad Left cursor in Equivalent_Elements");
545 pragma Assert
(Vet
(Right
, CRight
),
546 "bad Right cursor in Equivalent_Elements");
549 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
550 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
552 return Equivalent_Elements
(LN
.Element
, RN
.Element
);
554 end Equivalent_Elements
;
556 function Equivalent_Elements
559 Right
: Element_Type
) return Boolean
562 if not Has_Element
(Left
, CLeft
) then
563 raise Constraint_Error
with
564 "Left cursor of Equivalent_Elements has no element";
567 pragma Assert
(Vet
(Left
, CLeft
),
568 "Left cursor in Equivalent_Elements is bad");
571 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
573 return Equivalent_Elements
(LN
.Element
, Right
);
575 end Equivalent_Elements
;
577 function Equivalent_Elements
578 (Left
: Element_Type
;
580 CRight
: Cursor
) return Boolean
583 if not Has_Element
(Right
, CRight
) then
584 raise Constraint_Error
with
585 "Right cursor of Equivalent_Elements has no element";
589 (Vet
(Right
, CRight
),
590 "Right cursor of Equivalent_Elements is bad");
593 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
595 return Equivalent_Elements
(Left
, RN
.Element
);
597 end Equivalent_Elements
;
599 ---------------------
600 -- Equivalent_Keys --
601 ---------------------
603 function Equivalent_Keys
605 Node
: Node_Type
) return Boolean
608 return Equivalent_Elements
(Key
, Node
.Element
);
616 (Container
: in out Set
;
621 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
631 Item
: Element_Type
) return Cursor
633 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, Item
);
640 return (Node
=> Node
);
647 function First
(Container
: Set
) return Cursor
is
648 Node
: constant Count_Type
:= HT_Ops
.First
(Container
);
655 return (Node
=> Node
);
658 -----------------------
659 -- First_To_Previous --
660 -----------------------
662 function First_To_Previous
664 Current
: Cursor
) return Set
666 Curs
: Cursor
:= Current
;
667 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
668 Copy
(Container
, Container
.Capacity
);
672 if Curs
= No_Element
then
675 elsif not Has_Element
(Container
, Curs
) then
676 raise Constraint_Error
;
679 while Curs
.Node
/= 0 loop
682 Curs
:= Next
(Container
, (Node
=> Node
));
687 end First_To_Previous
;
698 HT
.Nodes
(X
).Has_Element
:= False;
702 ----------------------
703 -- Generic_Allocate --
704 ----------------------
706 procedure Generic_Allocate
708 Node
: out Count_Type
)
710 procedure Allocate
is new HT_Ops
.Generic_Allocate
(Set_Element
);
713 HT
.Nodes
(Node
).Has_Element
:= True;
714 end Generic_Allocate
;
720 function Has_Element
(Container
: Set
; Position
: Cursor
) return Boolean is
723 or else not Container
.Nodes
(Position
.Node
).Has_Element
735 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
737 return Hash
(Node
.Element
);
745 (Container
: in out Set
;
746 New_Item
: Element_Type
)
752 Insert
(Container
, New_Item
, Position
, Inserted
);
755 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
764 (Container
: in out Set
;
765 New_Item
: Element_Type
;
766 Position
: out Cursor
;
767 Inserted
: out Boolean)
770 Insert
(Container
, New_Item
, Position
.Node
, Inserted
);
774 (Container
: in out Set
;
775 New_Item
: Element_Type
)
781 Insert
(Container
, New_Item
, Position
, Inserted
);
784 raise Constraint_Error
with
785 "attempt to insert element already in set";
790 (Container
: in out Set
;
791 New_Item
: Element_Type
;
792 Node
: out Count_Type
;
793 Inserted
: out Boolean)
795 procedure Allocate_Set_Element
(Node
: in out Node_Type
);
796 pragma Inline
(Allocate_Set_Element
);
798 function New_Node
return Count_Type
;
799 pragma Inline
(New_Node
);
801 procedure Local_Insert
is
802 new Element_Keys
.Generic_Conditional_Insert
(New_Node
);
804 procedure Allocate
is
805 new Generic_Allocate
(Allocate_Set_Element
);
807 ---------------------------
808 -- Allocate_Set_Element --
809 ---------------------------
811 procedure Allocate_Set_Element
(Node
: in out Node_Type
) is
813 Node
.Element
:= New_Item
;
814 end Allocate_Set_Element
;
820 function New_Node
return Count_Type
is
823 Allocate
(Container
, Result
);
827 -- Start of processing for Insert
830 Local_Insert
(Container
, New_Item
, Node
, Inserted
);
837 procedure Intersection
838 (Target
: in out Set
;
841 Tgt_Node
: Count_Type
;
842 TN
: Nodes_Type
renames Target
.Nodes
;
845 if Target
'Address = Source
'Address then
849 if Source
.Length
= 0 then
854 Tgt_Node
:= HT_Ops
.First
(Target
);
855 while Tgt_Node
/= 0 loop
856 if Find
(Source
, TN
(Tgt_Node
).Element
).Node
/= 0 then
857 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
861 X
: constant Count_Type
:= Tgt_Node
;
863 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
864 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
871 procedure Intersection
876 procedure Process
(L_Node
: Count_Type
);
879 new HT_Ops
.Generic_Iteration
(Process
);
885 procedure Process
(L_Node
: Count_Type
) is
886 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
891 if Find
(Right
, E
).Node
/= 0 then
892 Insert
(Target
, E
, X
, B
);
897 -- Start of processing for Intersection
903 function Intersection
(Left
, Right
: Set
) return Set
is
908 if Left
'Address = Right
'Address then
912 C
:= Count_Type
'Min (Length
(Left
), Length
(Right
)); -- ???
913 H
:= Default_Modulus
(C
);
915 return S
: Set
(C
, H
) do
916 if Length
(Left
) /= 0 and Length
(Right
) /= 0 then
917 Intersection
(Left
, Right
, Target
=> S
);
926 function Is_Empty
(Container
: Set
) return Boolean is
928 return Length
(Container
) = 0;
935 function Is_In
(HT
: Set
; Key
: Node_Type
) return Boolean is
937 return Element_Keys
.Find
(HT
, Key
.Element
) /= 0;
944 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean is
945 Subset_Node
: Count_Type
;
946 Subset_Nodes
: Nodes_Type
renames Subset
.Nodes
;
949 if Subset
'Address = Of_Set
'Address then
953 if Length
(Subset
) > Length
(Of_Set
) then
957 Subset_Node
:= First
(Subset
).Node
;
958 while Subset_Node
/= 0 loop
960 N
: Node_Type
renames Subset_Nodes
(Subset_Node
);
961 E
: Element_Type
renames N
.Element
;
964 if Find
(Of_Set
, E
).Node
= 0 then
969 Subset_Node
:= HT_Ops
.Next
(Subset
, Subset_Node
);
979 function Length
(Container
: Set
) return Count_Type
is
981 return Container
.Length
;
990 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
991 NN
: HT_Types
.Nodes_Type
renames Source
.Nodes
;
995 if Target
'Address = Source
'Address then
999 if Target
.Capacity
< Length
(Source
) then
1000 raise Constraint_Error
with -- ???
1001 "Source length exceeds Target capacity";
1006 if Source
.Length
= 0 then
1010 X
:= HT_Ops
.First
(Source
);
1012 Insert
(Target
, NN
(X
).Element
); -- optimize???
1014 Y
:= HT_Ops
.Next
(Source
, X
);
1016 HT_Ops
.Delete_Node_Sans_Free
(Source
, X
);
1027 function Next
(Node
: Node_Type
) return Count_Type
is
1032 function Next
(Container
: Set
; Position
: Cursor
) return Cursor
is
1034 if Position
.Node
= 0 then
1038 if not Has_Element
(Container
, Position
) then
1039 raise Constraint_Error
1040 with "Position has no element";
1043 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Next");
1045 return (Node
=> HT_Ops
.Next
(Container
, Position
.Node
));
1048 procedure Next
(Container
: Set
; Position
: in out Cursor
) is
1050 Position
:= Next
(Container
, Position
);
1057 function Overlap
(Left
, Right
: Set
) return Boolean is
1058 Left_Node
: Count_Type
;
1059 Left_Nodes
: Nodes_Type
renames Left
.Nodes
;
1062 if Length
(Right
) = 0 or Length
(Left
) = 0 then
1066 if Left
'Address = Right
'Address then
1070 Left_Node
:= First
(Left
).Node
;
1071 while Left_Node
/= 0 loop
1073 N
: Node_Type
renames Left_Nodes
(Left_Node
);
1074 E
: Element_Type
renames N
.Element
;
1076 if Find
(Right
, E
).Node
/= 0 then
1081 Left_Node
:= HT_Ops
.Next
(Left
, Left_Node
);
1092 (Container
: in out Set
;
1093 New_Item
: Element_Type
)
1095 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, New_Item
);
1099 raise Constraint_Error
with
1100 "attempt to replace element not in set";
1103 Container
.Nodes
(Node
).Element
:= New_Item
;
1106 ---------------------
1107 -- Replace_Element --
1108 ---------------------
1110 procedure Replace_Element
1111 (Container
: in out Set
;
1113 New_Item
: Element_Type
)
1116 if not Has_Element
(Container
, Position
) then
1117 raise Constraint_Error
with
1118 "Position cursor equals No_Element";
1121 pragma Assert
(Vet
(Container
, Position
),
1122 "bad cursor in Replace_Element");
1124 Replace_Element
(Container
, Position
.Node
, New_Item
);
1125 end Replace_Element
;
1127 ----------------------
1128 -- Reserve_Capacity --
1129 ----------------------
1131 procedure Reserve_Capacity
1132 (Container
: in out Set
;
1133 Capacity
: Count_Type
)
1136 if Capacity
> Container
.Capacity
then
1137 raise Constraint_Error
with "requested capacity is too large";
1139 end Reserve_Capacity
;
1145 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
) is
1147 Node
.Element
:= Item
;
1154 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1163 function Strict_Equal
(Left
, Right
: Set
) return Boolean is
1164 CuL
: Cursor
:= First
(Left
);
1165 CuR
: Cursor
:= First
(Right
);
1168 if Length
(Left
) /= Length
(Right
) then
1172 while CuL
.Node
/= 0 or CuR
.Node
/= 0 loop
1173 if CuL
.Node
/= CuR
.Node
1174 or else Left
.Nodes
(CuL
.Node
).Element
/=
1175 Right
.Nodes
(CuR
.Node
).Element
1180 CuL
:= Next
(Left
, CuL
);
1181 CuR
:= Next
(Right
, CuR
);
1187 --------------------------
1188 -- Symmetric_Difference --
1189 --------------------------
1191 procedure Symmetric_Difference
1192 (Target
: in out Set
;
1195 procedure Process
(Source_Node
: Count_Type
);
1196 pragma Inline
(Process
);
1198 procedure Iterate
is new HT_Ops
.Generic_Iteration
(Process
);
1204 procedure Process
(Source_Node
: Count_Type
) is
1205 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
1209 if Is_In
(Target
, N
) then
1210 Delete
(Target
, N
.Element
);
1212 Insert
(Target
, N
.Element
, X
, B
);
1217 -- Start of processing for Symmetric_Difference
1220 if Target
'Address = Source
'Address then
1225 if Length
(Target
) = 0 then
1226 Assign
(Target
, Source
);
1231 end Symmetric_Difference
;
1233 function Symmetric_Difference
(Left
, Right
: Set
) return Set
is
1238 if Left
'Address = Right
'Address then
1242 if Length
(Right
) = 0 then
1246 if Length
(Left
) = 0 then
1250 C
:= Length
(Left
) + Length
(Right
);
1251 H
:= Default_Modulus
(C
);
1253 return S
: Set
(C
, H
) do
1254 Difference
(Left
, Right
, S
);
1255 Difference
(Right
, Left
, S
);
1257 end Symmetric_Difference
;
1263 function To_Set
(New_Item
: Element_Type
) return Set
is
1268 return S
: Set
(Capacity
=> 1, Modulus
=> 1) do
1269 Insert
(S
, New_Item
, X
, B
);
1279 (Target
: in out Set
;
1282 procedure Process
(Src_Node
: Count_Type
);
1284 procedure Iterate
is
1285 new HT_Ops
.Generic_Iteration
(Process
);
1291 procedure Process
(Src_Node
: Count_Type
) is
1292 N
: Node_Type
renames Source
.Nodes
(Src_Node
);
1293 E
: Element_Type
renames N
.Element
;
1299 Insert
(Target
, E
, X
, B
);
1302 -- Start of processing for Union
1305 if Target
'Address = Source
'Address then
1312 function Union
(Left
, Right
: Set
) return Set
is
1317 if Left
'Address = Right
'Address then
1321 if Length
(Right
) = 0 then
1325 if Length
(Left
) = 0 then
1329 C
:= Length
(Left
) + Length
(Right
);
1330 H
:= Default_Modulus
(C
);
1331 return S
: Set
(C
, H
) do
1332 Assign
(Target
=> S
, Source
=> Left
);
1333 Union
(Target
=> S
, Source
=> Right
);
1341 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean is
1343 if Position
.Node
= 0 then
1348 S
: Set
renames Container
;
1349 N
: Nodes_Type
renames S
.Nodes
;
1353 if S
.Length
= 0 then
1357 if Position
.Node
> N
'Last then
1361 if N
(Position
.Node
).Next
= Position
.Node
then
1365 X
:= S
.Buckets
(Element_Keys
.Index
(S
, N
(Position
.Node
).Element
));
1367 for J
in 1 .. S
.Length
loop
1368 if X
= Position
.Node
then
1376 if X
= N
(X
).Next
then -- to prevent unnecessary looping
1387 package body Generic_Keys
is
1389 -----------------------
1390 -- Local Subprograms --
1391 -----------------------
1393 function Equivalent_Key_Node
1395 Node
: Node_Type
) return Boolean;
1396 pragma Inline
(Equivalent_Key_Node
);
1398 --------------------------
1399 -- Local Instantiations --
1400 --------------------------
1403 new Hash_Tables
.Generic_Bounded_Keys
1404 (HT_Types
=> HT_Types
,
1406 Set_Next
=> Set_Next
,
1407 Key_Type
=> Key_Type
,
1409 Equivalent_Keys
=> Equivalent_Key_Node
);
1417 Key
: Key_Type
) return Boolean
1420 return Find
(Container
, Key
) /= No_Element
;
1428 (Container
: in out Set
;
1434 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1437 raise Constraint_Error
with "attempt to delete key not in set";
1440 Free
(Container
, X
);
1449 Key
: Key_Type
) return Element_Type
1451 Node
: constant Count_Type
:= Find
(Container
, Key
).Node
;
1455 raise Constraint_Error
with "key not in map";
1458 return Container
.Nodes
(Node
).Element
;
1461 -------------------------
1462 -- Equivalent_Key_Node --
1463 -------------------------
1465 function Equivalent_Key_Node
1467 Node
: Node_Type
) return Boolean
1470 return Equivalent_Keys
(Key
, Generic_Keys
.Key
(Node
.Element
));
1471 end Equivalent_Key_Node
;
1478 (Container
: in out Set
;
1483 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1484 Free
(Container
, X
);
1493 Key
: Key_Type
) return Cursor
1495 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1497 return (if Node
= 0 then No_Element
else (Node
=> Node
));
1504 function Key
(Container
: Set
; Position
: Cursor
) return Key_Type
is
1506 if not Has_Element
(Container
, Position
) then
1507 raise Constraint_Error
with
1508 "Position cursor has no element";
1512 (Vet
(Container
, Position
), "bad cursor in function Key");
1515 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1517 return Key
(N
.Element
);
1526 (Container
: in out Set
;
1528 New_Item
: Element_Type
)
1530 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1534 raise Constraint_Error
with
1535 "attempt to replace key not in set";
1538 Replace_Element
(Container
, Node
, New_Item
);
1543 end Ada
.Containers
.Formal_Hashed_Sets
;