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 Target
.Length
:= Source
.Length
;
237 Target
.Free
:= Source
.Free
;
240 while H
<= Source
.Modulus
loop
241 Target
.Buckets
(H
) := Source
.Buckets
(H
);
246 while N
<= Source
.Capacity
loop
247 Target
.Nodes
(N
) := Source
.Nodes
(N
);
253 Free
(Target
, Cu
.Node
);
260 ---------------------
261 -- Default_Modulus --
262 ---------------------
264 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
266 return To_Prime
(Capacity
);
274 (Container
: in out Set
;
280 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
283 raise Constraint_Error
with "attempt to delete element not in set";
290 (Container
: in out Set
;
291 Position
: in out Cursor
)
294 if not Has_Element
(Container
, Position
) then
295 raise Constraint_Error
with "Position cursor has no element";
298 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Delete");
300 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
301 Free
(Container
, Position
.Node
);
303 Position
:= No_Element
;
311 (Target
: in out Set
;
314 Tgt_Node
, Src_Node
, Src_Last
, Src_Length
: Count_Type
;
316 TN
: Nodes_Type
renames Target
.Nodes
;
317 SN
: Nodes_Type
renames Source
.Nodes
;
320 if Target
'Address = Source
'Address then
325 Src_Length
:= Source
.Length
;
327 if Src_Length
= 0 then
331 if Src_Length
>= Target
.Length
then
332 Tgt_Node
:= HT_Ops
.First
(Target
);
333 while Tgt_Node
/= 0 loop
334 if Element_Keys
.Find
(Source
, TN
(Tgt_Node
).Element
) /= 0 then
336 X
: constant Count_Type
:= Tgt_Node
;
338 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
339 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
344 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
350 Src_Node
:= HT_Ops
.First
(Source
);
354 while Src_Node
/= Src_Last
loop
355 Tgt_Node
:= Element_Keys
.Find
(Target
, SN
(Src_Node
).Element
);
357 if Tgt_Node
/= 0 then
358 HT_Ops
.Delete_Node_Sans_Free
(Target
, Tgt_Node
);
359 Free
(Target
, Tgt_Node
);
362 Src_Node
:= HT_Ops
.Next
(Source
, Src_Node
);
370 procedure Process
(L_Node
: Count_Type
);
373 new HT_Ops
.Generic_Iteration
(Process
);
379 procedure Process
(L_Node
: Count_Type
) is
380 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
384 if Find
(Right
, E
).Node
= 0 then
385 Insert
(Target
, E
, X
, B
);
390 -- Start of processing for Difference
396 function Difference
(Left
, Right
: Set
) return Set
is
401 if Left
'Address = Right
'Address then
405 if Length
(Left
) = 0 then
409 if Length
(Right
) = 0 then
414 H
:= Default_Modulus
(C
);
416 return S
: Set
(C
, H
) do
417 Difference
(Left
, Right
, Target
=> S
);
427 Position
: Cursor
) return Element_Type
430 if not Has_Element
(Container
, Position
) then
431 raise Constraint_Error
with "Position cursor equals No_Element";
434 pragma Assert
(Vet
(Container
, Position
),
435 "bad cursor in function Element");
437 return Container
.Nodes
(Position
.Node
).Element
;
440 ---------------------
441 -- Equivalent_Sets --
442 ---------------------
444 function Equivalent_Sets
(Left
, Right
: Set
) return Boolean is
446 function Find_Equivalent_Key
447 (R_HT
: Hash_Table_Type
'Class;
448 L_Node
: Node_Type
) return Boolean;
449 pragma Inline
(Find_Equivalent_Key
);
451 function Is_Equivalent
is
452 new HT_Ops
.Generic_Equal
(Find_Equivalent_Key
);
454 -------------------------
455 -- Find_Equivalent_Key --
456 -------------------------
458 function Find_Equivalent_Key
459 (R_HT
: Hash_Table_Type
'Class;
460 L_Node
: Node_Type
) return Boolean
462 R_Index
: constant Hash_Type
:=
463 Element_Keys
.Index
(R_HT
, L_Node
.Element
);
464 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
465 RN
: Nodes_Type
renames R_HT
.Nodes
;
473 if Equivalent_Elements
(L_Node
.Element
,
474 RN
(R_Node
).Element
) then
478 R_Node
:= HT_Ops
.Next
(R_HT
, R_Node
);
480 end Find_Equivalent_Key
;
482 -- Start of processing of Equivalent_Sets
485 return Is_Equivalent
(Left
, Right
);
488 -------------------------
489 -- Equivalent_Elements --
490 -------------------------
492 function Equivalent_Elements
496 CRight
: Cursor
) return Boolean
499 if not Has_Element
(Left
, CLeft
) then
500 raise Constraint_Error
with
501 "Left cursor of Equivalent_Elements has no element";
504 if not Has_Element
(Right
, CRight
) then
505 raise Constraint_Error
with
506 "Right cursor of Equivalent_Elements has no element";
509 pragma Assert
(Vet
(Left
, CLeft
),
510 "bad Left cursor in Equivalent_Elements");
511 pragma Assert
(Vet
(Right
, CRight
),
512 "bad Right cursor in Equivalent_Elements");
515 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
516 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
518 return Equivalent_Elements
(LN
.Element
, RN
.Element
);
520 end Equivalent_Elements
;
522 function Equivalent_Elements
525 Right
: Element_Type
) return Boolean
528 if not Has_Element
(Left
, CLeft
) then
529 raise Constraint_Error
with
530 "Left cursor of Equivalent_Elements has no element";
533 pragma Assert
(Vet
(Left
, CLeft
),
534 "Left cursor in Equivalent_Elements is bad");
537 LN
: Node_Type
renames Left
.Nodes
(CLeft
.Node
);
539 return Equivalent_Elements
(LN
.Element
, Right
);
541 end Equivalent_Elements
;
543 function Equivalent_Elements
544 (Left
: Element_Type
;
546 CRight
: Cursor
) return Boolean
549 if not Has_Element
(Right
, CRight
) then
550 raise Constraint_Error
with
551 "Right cursor of Equivalent_Elements has no element";
555 (Vet
(Right
, CRight
),
556 "Right cursor of Equivalent_Elements is bad");
559 RN
: Node_Type
renames Right
.Nodes
(CRight
.Node
);
561 return Equivalent_Elements
(Left
, RN
.Element
);
563 end Equivalent_Elements
;
565 ---------------------
566 -- Equivalent_Keys --
567 ---------------------
569 function Equivalent_Keys
571 Node
: Node_Type
) return Boolean
574 return Equivalent_Elements
(Key
, Node
.Element
);
582 (Container
: in out Set
;
587 Element_Keys
.Delete_Key_Sans_Free
(Container
, Item
, X
);
597 Item
: Element_Type
) return Cursor
599 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, Item
);
606 return (Node
=> Node
);
613 function First
(Container
: Set
) return Cursor
is
614 Node
: constant Count_Type
:= HT_Ops
.First
(Container
);
621 return (Node
=> Node
);
633 HT
.Nodes
(X
).Has_Element
:= False;
637 ----------------------
638 -- Generic_Allocate --
639 ----------------------
641 procedure Generic_Allocate
643 Node
: out Count_Type
)
645 procedure Allocate
is new HT_Ops
.Generic_Allocate
(Set_Element
);
648 HT
.Nodes
(Node
).Has_Element
:= True;
649 end Generic_Allocate
;
655 function Has_Element
(Container
: Set
; Position
: Cursor
) return Boolean is
658 or else not Container
.Nodes
(Position
.Node
).Has_Element
670 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
672 return Hash
(Node
.Element
);
680 (Container
: in out Set
;
681 New_Item
: Element_Type
)
687 Insert
(Container
, New_Item
, Position
, Inserted
);
690 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
699 (Container
: in out Set
;
700 New_Item
: Element_Type
;
701 Position
: out Cursor
;
702 Inserted
: out Boolean)
705 Insert
(Container
, New_Item
, Position
.Node
, Inserted
);
709 (Container
: in out Set
;
710 New_Item
: Element_Type
)
716 Insert
(Container
, New_Item
, Position
, Inserted
);
719 raise Constraint_Error
with
720 "attempt to insert element already in set";
725 (Container
: in out Set
;
726 New_Item
: Element_Type
;
727 Node
: out Count_Type
;
728 Inserted
: out Boolean)
730 procedure Allocate_Set_Element
(Node
: in out Node_Type
);
731 pragma Inline
(Allocate_Set_Element
);
733 function New_Node
return Count_Type
;
734 pragma Inline
(New_Node
);
736 procedure Local_Insert
is
737 new Element_Keys
.Generic_Conditional_Insert
(New_Node
);
739 procedure Allocate
is
740 new Generic_Allocate
(Allocate_Set_Element
);
742 ---------------------------
743 -- Allocate_Set_Element --
744 ---------------------------
746 procedure Allocate_Set_Element
(Node
: in out Node_Type
) is
748 Node
.Element
:= New_Item
;
749 end Allocate_Set_Element
;
755 function New_Node
return Count_Type
is
758 Allocate
(Container
, Result
);
762 -- Start of processing for Insert
765 Local_Insert
(Container
, New_Item
, Node
, Inserted
);
772 procedure Intersection
773 (Target
: in out Set
;
776 Tgt_Node
: Count_Type
;
777 TN
: Nodes_Type
renames Target
.Nodes
;
780 if Target
'Address = Source
'Address then
784 if Source
.Length
= 0 then
789 Tgt_Node
:= HT_Ops
.First
(Target
);
790 while Tgt_Node
/= 0 loop
791 if Find
(Source
, TN
(Tgt_Node
).Element
).Node
/= 0 then
792 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
796 X
: constant Count_Type
:= Tgt_Node
;
798 Tgt_Node
:= HT_Ops
.Next
(Target
, Tgt_Node
);
799 HT_Ops
.Delete_Node_Sans_Free
(Target
, X
);
806 procedure Intersection
811 procedure Process
(L_Node
: Count_Type
);
814 new HT_Ops
.Generic_Iteration
(Process
);
820 procedure Process
(L_Node
: Count_Type
) is
821 E
: Element_Type
renames Left
.Nodes
(L_Node
).Element
;
826 if Find
(Right
, E
).Node
/= 0 then
827 Insert
(Target
, E
, X
, B
);
832 -- Start of processing for Intersection
838 function Intersection
(Left
, Right
: Set
) return Set
is
843 if Left
'Address = Right
'Address then
847 C
:= Count_Type
'Min (Length
(Left
), Length
(Right
)); -- ???
848 H
:= Default_Modulus
(C
);
850 return S
: Set
(C
, H
) do
851 if Length
(Left
) /= 0 and Length
(Right
) /= 0 then
852 Intersection
(Left
, Right
, Target
=> S
);
861 function Is_Empty
(Container
: Set
) return Boolean is
863 return Length
(Container
) = 0;
870 function Is_In
(HT
: Set
; Key
: Node_Type
) return Boolean is
872 return Element_Keys
.Find
(HT
, Key
.Element
) /= 0;
879 function Is_Subset
(Subset
: Set
; Of_Set
: Set
) return Boolean is
880 Subset_Node
: Count_Type
;
881 Subset_Nodes
: Nodes_Type
renames Subset
.Nodes
;
884 if Subset
'Address = Of_Set
'Address then
888 if Length
(Subset
) > Length
(Of_Set
) then
892 Subset_Node
:= First
(Subset
).Node
;
893 while Subset_Node
/= 0 loop
895 N
: Node_Type
renames Subset_Nodes
(Subset_Node
);
896 E
: Element_Type
renames N
.Element
;
899 if Find
(Of_Set
, E
).Node
= 0 then
904 Subset_Node
:= HT_Ops
.Next
(Subset
, Subset_Node
);
914 function Left
(Container
: Set
; Position
: Cursor
) return Set
is
915 Curs
: Cursor
:= Position
;
916 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
917 Copy
(Container
, Container
.Capacity
);
921 if Curs
= No_Element
then
925 if not Has_Element
(Container
, Curs
) then
926 raise Constraint_Error
;
929 while Curs
.Node
/= 0 loop
932 Curs
:= Next
(Container
, (Node
=> Node
));
942 function Length
(Container
: Set
) return Count_Type
is
944 return Container
.Length
;
953 procedure Move
(Target
: in out Set
; Source
: in out Set
) is
954 NN
: HT_Types
.Nodes_Type
renames Source
.Nodes
;
958 if Target
'Address = Source
'Address then
962 if Target
.Capacity
< Length
(Source
) then
963 raise Constraint_Error
with -- ???
964 "Source length exceeds Target capacity";
969 if Source
.Length
= 0 then
973 X
:= HT_Ops
.First
(Source
);
975 Insert
(Target
, NN
(X
).Element
); -- optimize???
977 Y
:= HT_Ops
.Next
(Source
, X
);
979 HT_Ops
.Delete_Node_Sans_Free
(Source
, X
);
990 function Next
(Node
: Node_Type
) return Count_Type
is
995 function Next
(Container
: Set
; Position
: Cursor
) return Cursor
is
997 if Position
.Node
= 0 then
1001 if not Has_Element
(Container
, Position
) then
1002 raise Constraint_Error
1003 with "Position has no element";
1006 pragma Assert
(Vet
(Container
, Position
), "bad cursor in Next");
1008 return (Node
=> HT_Ops
.Next
(Container
, Position
.Node
));
1011 procedure Next
(Container
: Set
; Position
: in out Cursor
) is
1013 Position
:= Next
(Container
, Position
);
1020 function Overlap
(Left
, Right
: Set
) return Boolean is
1021 Left_Node
: Count_Type
;
1022 Left_Nodes
: Nodes_Type
renames Left
.Nodes
;
1025 if Length
(Right
) = 0 or Length
(Left
) = 0 then
1029 if Left
'Address = Right
'Address then
1033 Left_Node
:= First
(Left
).Node
;
1034 while Left_Node
/= 0 loop
1036 N
: Node_Type
renames Left_Nodes
(Left_Node
);
1037 E
: Element_Type
renames N
.Element
;
1039 if Find
(Right
, E
).Node
/= 0 then
1044 Left_Node
:= HT_Ops
.Next
(Left
, Left_Node
);
1055 (Container
: in out Set
;
1056 New_Item
: Element_Type
)
1058 Node
: constant Count_Type
:= Element_Keys
.Find
(Container
, New_Item
);
1062 raise Constraint_Error
with
1063 "attempt to replace element not in set";
1066 Container
.Nodes
(Node
).Element
:= New_Item
;
1069 ---------------------
1070 -- Replace_Element --
1071 ---------------------
1073 procedure Replace_Element
1074 (Container
: in out Set
;
1076 New_Item
: Element_Type
)
1079 if not Has_Element
(Container
, Position
) then
1080 raise Constraint_Error
with
1081 "Position cursor equals No_Element";
1084 pragma Assert
(Vet
(Container
, Position
),
1085 "bad cursor in Replace_Element");
1087 Replace_Element
(Container
, Position
.Node
, New_Item
);
1088 end Replace_Element
;
1090 ----------------------
1091 -- Reserve_Capacity --
1092 ----------------------
1094 procedure Reserve_Capacity
1095 (Container
: in out Set
;
1096 Capacity
: Count_Type
)
1099 if Capacity
> Container
.Capacity
then
1100 raise Constraint_Error
with "requested capacity is too large";
1102 end Reserve_Capacity
;
1108 function Right
(Container
: Set
; Position
: Cursor
) return Set
is
1109 Curs
: Cursor
:= First
(Container
);
1110 C
: Set
(Container
.Capacity
, Container
.Modulus
) :=
1111 Copy
(Container
, Container
.Capacity
);
1115 if Curs
= No_Element
then
1120 if Position
/= No_Element
and not Has_Element
(Container
, Position
) then
1121 raise Constraint_Error
;
1124 while Curs
.Node
/= Position
.Node
loop
1127 Curs
:= Next
(Container
, (Node
=> Node
));
1137 procedure Set_Element
(Node
: in out Node_Type
; Item
: Element_Type
) is
1139 Node
.Element
:= Item
;
1146 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1155 function Strict_Equal
(Left
, Right
: Set
) return Boolean is
1156 CuL
: Cursor
:= First
(Left
);
1157 CuR
: Cursor
:= First
(Right
);
1160 if Length
(Left
) /= Length
(Right
) then
1164 while CuL
.Node
/= 0 or CuR
.Node
/= 0 loop
1165 if CuL
.Node
/= CuR
.Node
1166 or else Left
.Nodes
(CuL
.Node
).Element
/=
1167 Right
.Nodes
(CuR
.Node
).Element
1172 CuL
:= Next
(Left
, CuL
);
1173 CuR
:= Next
(Right
, CuR
);
1179 --------------------------
1180 -- Symmetric_Difference --
1181 --------------------------
1183 procedure Symmetric_Difference
1184 (Target
: in out Set
;
1187 procedure Process
(Source_Node
: Count_Type
);
1188 pragma Inline
(Process
);
1190 procedure Iterate
is new HT_Ops
.Generic_Iteration
(Process
);
1196 procedure Process
(Source_Node
: Count_Type
) is
1197 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
1201 if Is_In
(Target
, N
) then
1202 Delete
(Target
, N
.Element
);
1204 Insert
(Target
, N
.Element
, X
, B
);
1209 -- Start of processing for Symmetric_Difference
1212 if Target
'Address = Source
'Address then
1217 if Length
(Target
) = 0 then
1218 Assign
(Target
, Source
);
1223 end Symmetric_Difference
;
1225 function Symmetric_Difference
(Left
, Right
: Set
) return Set
is
1230 if Left
'Address = Right
'Address then
1234 if Length
(Right
) = 0 then
1238 if Length
(Left
) = 0 then
1242 C
:= Length
(Left
) + Length
(Right
);
1243 H
:= Default_Modulus
(C
);
1245 return S
: Set
(C
, H
) do
1246 Difference
(Left
, Right
, S
);
1247 Difference
(Right
, Left
, S
);
1249 end Symmetric_Difference
;
1255 function To_Set
(New_Item
: Element_Type
) return Set
is
1260 return S
: Set
(Capacity
=> 1, Modulus
=> 1) do
1261 Insert
(S
, New_Item
, X
, B
);
1271 (Target
: in out Set
;
1274 procedure Process
(Src_Node
: Count_Type
);
1276 procedure Iterate
is
1277 new HT_Ops
.Generic_Iteration
(Process
);
1283 procedure Process
(Src_Node
: Count_Type
) is
1284 N
: Node_Type
renames Source
.Nodes
(Src_Node
);
1285 E
: Element_Type
renames N
.Element
;
1291 Insert
(Target
, E
, X
, B
);
1294 -- Start of processing for Union
1297 if Target
'Address = Source
'Address then
1304 function Union
(Left
, Right
: Set
) return Set
is
1309 if Left
'Address = Right
'Address then
1313 if Length
(Right
) = 0 then
1317 if Length
(Left
) = 0 then
1321 C
:= Length
(Left
) + Length
(Right
);
1322 H
:= Default_Modulus
(C
);
1323 return S
: Set
(C
, H
) do
1324 Assign
(Target
=> S
, Source
=> Left
);
1325 Union
(Target
=> S
, Source
=> Right
);
1333 function Vet
(Container
: Set
; Position
: Cursor
) return Boolean is
1335 if Position
.Node
= 0 then
1340 S
: Set
renames Container
;
1341 N
: Nodes_Type
renames S
.Nodes
;
1345 if S
.Length
= 0 then
1349 if Position
.Node
> N
'Last then
1353 if N
(Position
.Node
).Next
= Position
.Node
then
1357 X
:= S
.Buckets
(Element_Keys
.Index
(S
, N
(Position
.Node
).Element
));
1359 for J
in 1 .. S
.Length
loop
1360 if X
= Position
.Node
then
1368 if X
= N
(X
).Next
then -- to prevent unnecessary looping
1379 package body Generic_Keys
is
1381 -----------------------
1382 -- Local Subprograms --
1383 -----------------------
1385 function Equivalent_Key_Node
1387 Node
: Node_Type
) return Boolean;
1388 pragma Inline
(Equivalent_Key_Node
);
1390 --------------------------
1391 -- Local Instantiations --
1392 --------------------------
1395 new Hash_Tables
.Generic_Bounded_Keys
1396 (HT_Types
=> HT_Types
,
1398 Set_Next
=> Set_Next
,
1399 Key_Type
=> Key_Type
,
1401 Equivalent_Keys
=> Equivalent_Key_Node
);
1409 Key
: Key_Type
) return Boolean
1412 return Find
(Container
, Key
) /= No_Element
;
1420 (Container
: in out Set
;
1426 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1429 raise Constraint_Error
with "attempt to delete key not in set";
1432 Free
(Container
, X
);
1441 Key
: Key_Type
) return Element_Type
1443 Node
: constant Count_Type
:= Find
(Container
, Key
).Node
;
1447 raise Constraint_Error
with "key not in map";
1450 return Container
.Nodes
(Node
).Element
;
1453 -------------------------
1454 -- Equivalent_Key_Node --
1455 -------------------------
1457 function Equivalent_Key_Node
1459 Node
: Node_Type
) return Boolean
1462 return Equivalent_Keys
(Key
, Generic_Keys
.Key
(Node
.Element
));
1463 end Equivalent_Key_Node
;
1470 (Container
: in out Set
;
1475 Key_Keys
.Delete_Key_Sans_Free
(Container
, Key
, X
);
1476 Free
(Container
, X
);
1485 Key
: Key_Type
) return Cursor
1487 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1489 return (if Node
= 0 then No_Element
else (Node
=> Node
));
1496 function Key
(Container
: Set
; Position
: Cursor
) return Key_Type
is
1498 if not Has_Element
(Container
, Position
) then
1499 raise Constraint_Error
with
1500 "Position cursor has no element";
1504 (Vet
(Container
, Position
), "bad cursor in function Key");
1507 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1509 return Key
(N
.Element
);
1518 (Container
: in out Set
;
1520 New_Item
: Element_Type
)
1522 Node
: constant Count_Type
:= Key_Keys
.Find
(Container
, Key
);
1526 raise Constraint_Error
with
1527 "attempt to replace key not in set";
1530 Replace_Element
(Container
, Node
, New_Item
);
1535 end Ada
.Containers
.Formal_Hashed_Sets
;