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 _ H A S H E D _ M A P S --
9 -- Copyright (C) 2004-2016, 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
.Hash_Tables
.Generic_Bounded_Operations
;
31 pragma Elaborate_All
(Ada
.Containers
.Hash_Tables
.Generic_Bounded_Operations
);
33 with Ada
.Containers
.Hash_Tables
.Generic_Bounded_Keys
;
34 pragma Elaborate_All
(Ada
.Containers
.Hash_Tables
.Generic_Bounded_Keys
);
36 with Ada
.Containers
.Helpers
; use Ada
.Containers
.Helpers
;
38 with Ada
.Containers
.Prime_Numbers
; use Ada
.Containers
.Prime_Numbers
;
40 with System
; use type System
.Address
;
42 package body Ada
.Containers
.Bounded_Hashed_Maps
is
44 pragma Warnings
(Off
, "variable ""Busy*"" is not referenced");
45 pragma Warnings
(Off
, "variable ""Lock*"" is not referenced");
46 -- See comment in Ada.Containers.Helpers
48 -----------------------
49 -- Local Subprograms --
50 -----------------------
52 function Equivalent_Key_Node
54 Node
: Node_Type
) return Boolean;
55 pragma Inline
(Equivalent_Key_Node
);
57 function Hash_Node
(Node
: Node_Type
) return Hash_Type
;
58 pragma Inline
(Hash_Node
);
60 function Next
(Node
: Node_Type
) return Count_Type
;
63 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
);
64 pragma Inline
(Set_Next
);
66 function Vet
(Position
: Cursor
) return Boolean;
68 --------------------------
69 -- Local Instantiations --
70 --------------------------
72 package HT_Ops
is new Hash_Tables
.Generic_Bounded_Operations
73 (HT_Types
=> HT_Types
,
74 Hash_Node
=> Hash_Node
,
76 Set_Next
=> Set_Next
);
78 package Key_Ops
is new Hash_Tables
.Generic_Bounded_Keys
79 (HT_Types
=> HT_Types
,
84 Equivalent_Keys
=> Equivalent_Key_Node
);
90 function "=" (Left
, Right
: Map
) return Boolean is
91 function Find_Equal_Key
92 (R_HT
: Hash_Table_Type
'Class;
93 L_Node
: Node_Type
) return Boolean;
95 function Is_Equal
is new HT_Ops
.Generic_Equal
(Find_Equal_Key
);
101 function Find_Equal_Key
102 (R_HT
: Hash_Table_Type
'Class;
103 L_Node
: Node_Type
) return Boolean
105 R_Index
: constant Hash_Type
:= Key_Ops
.Index
(R_HT
, L_Node
.Key
);
106 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
109 while R_Node
/= 0 loop
110 if Equivalent_Keys
(L_Node
.Key
, R_HT
.Nodes
(R_Node
).Key
) then
111 return L_Node
.Element
= R_HT
.Nodes
(R_Node
).Element
;
114 R_Node
:= R_HT
.Nodes
(R_Node
).Next
;
120 -- Start of processing for "="
123 return Is_Equal
(Left
, Right
);
130 procedure Assign
(Target
: in out Map
; Source
: Map
) is
131 procedure Insert_Element
(Source_Node
: Count_Type
);
133 procedure Insert_Elements
is
134 new HT_Ops
.Generic_Iteration
(Insert_Element
);
140 procedure Insert_Element
(Source_Node
: Count_Type
) is
141 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
146 Insert
(Target
, N
.Key
, N
.Element
, C
, B
);
150 -- Start of processing for Assign
153 if Target
'Address = Source
'Address then
157 if Checks
and then Target
.Capacity
< Source
.Length
then
159 with "Target capacity is less than Source length";
162 HT_Ops
.Clear
(Target
);
163 Insert_Elements
(Source
);
170 function Capacity
(Container
: Map
) return Count_Type
is
172 return Container
.Capacity
;
179 procedure Clear
(Container
: in out Map
) is
181 HT_Ops
.Clear
(Container
);
184 ------------------------
185 -- Constant_Reference --
186 ------------------------
188 function Constant_Reference
189 (Container
: aliased Map
;
190 Position
: Cursor
) return Constant_Reference_Type
193 if Checks
and then Position
.Container
= null then
194 raise Constraint_Error
with
195 "Position cursor has no element";
198 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
200 raise Program_Error
with
201 "Position cursor designates wrong map";
204 pragma Assert
(Vet
(Position
),
205 "Position cursor in Constant_Reference is bad");
208 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
209 TC
: constant Tamper_Counts_Access
:=
210 Container
.TC
'Unrestricted_Access;
212 return R
: constant Constant_Reference_Type
:=
213 (Element
=> N
.Element
'Access,
214 Control
=> (Controlled
with TC
))
219 end Constant_Reference
;
221 function Constant_Reference
222 (Container
: aliased Map
;
223 Key
: Key_Type
) return Constant_Reference_Type
225 Node
: constant Count_Type
:=
226 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
229 if Checks
and then Node
= 0 then
230 raise Constraint_Error
with "key not in map";
234 N
: Node_Type
renames Container
.Nodes
(Node
);
235 TC
: constant Tamper_Counts_Access
:=
236 Container
.TC
'Unrestricted_Access;
238 return R
: constant Constant_Reference_Type
:=
239 (Element
=> N
.Element
'Access,
240 Control
=> (Controlled
with TC
))
245 end Constant_Reference
;
251 function Contains
(Container
: Map
; Key
: Key_Type
) return Boolean is
253 return Find
(Container
, Key
) /= No_Element
;
262 Capacity
: Count_Type
:= 0;
263 Modulus
: Hash_Type
:= 0) return Map
272 elsif Capacity
>= Source
.Length
then
276 raise Capacity_Error
with "Capacity value too small";
280 M
:= Default_Modulus
(C
);
285 return Target
: Map
(Capacity
=> C
, Modulus
=> M
) do
286 Assign
(Target
=> Target
, Source
=> Source
);
290 ---------------------
291 -- Default_Modulus --
292 ---------------------
294 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
296 return To_Prime
(Capacity
);
303 procedure Delete
(Container
: in out Map
; Key
: Key_Type
) is
307 Key_Ops
.Delete_Key_Sans_Free
(Container
, Key
, X
);
309 if Checks
and then X
= 0 then
310 raise Constraint_Error
with "attempt to delete key not in map";
313 HT_Ops
.Free
(Container
, X
);
316 procedure Delete
(Container
: in out Map
; Position
: in out Cursor
) is
318 if Checks
and then Position
.Node
= 0 then
319 raise Constraint_Error
with
320 "Position cursor of Delete equals No_Element";
323 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
325 raise Program_Error
with
326 "Position cursor of Delete designates wrong map";
329 TC_Check
(Container
.TC
);
331 pragma Assert
(Vet
(Position
), "bad cursor in Delete");
333 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
334 HT_Ops
.Free
(Container
, Position
.Node
);
336 Position
:= No_Element
;
343 function Element
(Container
: Map
; Key
: Key_Type
) return Element_Type
is
344 Node
: constant Count_Type
:=
345 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
348 if Checks
and then Node
= 0 then
349 raise Constraint_Error
with
350 "no element available because key not in map";
353 return Container
.Nodes
(Node
).Element
;
356 function Element
(Position
: Cursor
) return Element_Type
is
358 if Checks
and then Position
.Node
= 0 then
359 raise Constraint_Error
with
360 "Position cursor of function Element equals No_Element";
363 pragma Assert
(Vet
(Position
), "bad cursor in function Element");
365 return Position
.Container
.Nodes
(Position
.Node
).Element
;
368 -------------------------
369 -- Equivalent_Key_Node --
370 -------------------------
372 function Equivalent_Key_Node
374 Node
: Node_Type
) return Boolean is
376 return Equivalent_Keys
(Key
, Node
.Key
);
377 end Equivalent_Key_Node
;
379 ---------------------
380 -- Equivalent_Keys --
381 ---------------------
383 function Equivalent_Keys
(Left
, Right
: Cursor
)
386 if Checks
and then Left
.Node
= 0 then
387 raise Constraint_Error
with
388 "Left cursor of Equivalent_Keys equals No_Element";
391 if Checks
and then Right
.Node
= 0 then
392 raise Constraint_Error
with
393 "Right cursor of Equivalent_Keys equals No_Element";
396 pragma Assert
(Vet
(Left
), "Left cursor of Equivalent_Keys is bad");
397 pragma Assert
(Vet
(Right
), "Right cursor of Equivalent_Keys is bad");
400 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
401 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
404 return Equivalent_Keys
(LN
.Key
, RN
.Key
);
408 function Equivalent_Keys
(Left
: Cursor
; Right
: Key_Type
) return Boolean is
410 if Checks
and then Left
.Node
= 0 then
411 raise Constraint_Error
with
412 "Left cursor of Equivalent_Keys equals No_Element";
415 pragma Assert
(Vet
(Left
), "Left cursor in Equivalent_Keys is bad");
418 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
421 return Equivalent_Keys
(LN
.Key
, Right
);
425 function Equivalent_Keys
(Left
: Key_Type
; Right
: Cursor
) return Boolean is
427 if Checks
and then Right
.Node
= 0 then
428 raise Constraint_Error
with
429 "Right cursor of Equivalent_Keys equals No_Element";
432 pragma Assert
(Vet
(Right
), "Right cursor of Equivalent_Keys is bad");
435 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
438 return Equivalent_Keys
(Left
, RN
.Key
);
446 procedure Exclude
(Container
: in out Map
; Key
: Key_Type
) is
449 Key_Ops
.Delete_Key_Sans_Free
(Container
, Key
, X
);
450 HT_Ops
.Free
(Container
, X
);
457 procedure Finalize
(Object
: in out Iterator
) is
459 if Object
.Container
/= null then
460 Unbusy
(Object
.Container
.TC
);
468 function Find
(Container
: Map
; Key
: Key_Type
) return Cursor
is
469 Node
: constant Count_Type
:=
470 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
475 return Cursor
'(Container'Unrestricted_Access, Node);
483 function First (Container : Map) return Cursor is
484 Node : constant Count_Type := HT_Ops.First (Container);
489 return Cursor'(Container
'Unrestricted_Access, Node
);
493 function First
(Object
: Iterator
) return Cursor
is
495 return Object
.Container
.First
;
498 ------------------------
499 -- Get_Element_Access --
500 ------------------------
502 function Get_Element_Access
503 (Position
: Cursor
) return not null Element_Access
is
505 return Position
.Container
.Nodes
(Position
.Node
).Element
'Access;
506 end Get_Element_Access
;
512 function Has_Element
(Position
: Cursor
) return Boolean is
514 pragma Assert
(Vet
(Position
), "bad cursor in Has_Element");
515 return Position
.Node
/= 0;
522 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
524 return Hash
(Node
.Key
);
532 (Container
: in out Map
;
534 New_Item
: Element_Type
)
540 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
543 TE_Check
(Container
.TC
);
546 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
549 N
.Element
:= New_Item
;
559 (Container
: in out Map
;
561 Position
: out Cursor
;
562 Inserted
: out Boolean)
564 procedure Assign_Key
(Node
: in out Node_Type
);
565 pragma Inline
(Assign_Key
);
567 function New_Node
return Count_Type
;
568 pragma Inline
(New_Node
);
570 procedure Local_Insert
is
571 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
573 procedure Allocate
is
574 new HT_Ops
.Generic_Allocate
(Assign_Key
);
580 procedure Assign_Key
(Node
: in out Node_Type
) is
581 New_Item
: Element_Type
;
582 pragma Unmodified
(New_Item
);
583 -- Default-initialized element (ok to reference, see below)
588 -- There is no explicit element provided, but in an instance the
589 -- element type may be a scalar with a Default_Value aspect, or a
590 -- composite type with such a scalar component, or components with
591 -- default initialization, so insert a possibly initialized element
592 -- under the given key.
594 Node
.Element
:= New_Item
;
601 function New_Node
return Count_Type
is
604 Allocate
(Container
, Result
);
608 -- Start of processing for Insert
611 -- The buckets array length is specified by the user as a discriminant
612 -- of the container type, so it is possible for the buckets array to
613 -- have a length of zero. We must check for this case specifically, in
614 -- order to prevent divide-by-zero errors later, when we compute the
615 -- buckets array index value for a key, given its hash value.
617 if Checks
and then Container
.Buckets
'Length = 0 then
618 raise Capacity_Error
with "No capacity for insertion";
621 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
622 Position
.Container
:= Container
'Unchecked_Access;
626 (Container
: in out Map
;
628 New_Item
: Element_Type
;
629 Position
: out Cursor
;
630 Inserted
: out Boolean)
632 procedure Assign_Key
(Node
: in out Node_Type
);
633 pragma Inline
(Assign_Key
);
635 function New_Node
return Count_Type
;
636 pragma Inline
(New_Node
);
638 procedure Local_Insert
is
639 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
641 procedure Allocate
is
642 new HT_Ops
.Generic_Allocate
(Assign_Key
);
648 procedure Assign_Key
(Node
: in out Node_Type
) is
651 Node
.Element
:= New_Item
;
658 function New_Node
return Count_Type
is
661 Allocate
(Container
, Result
);
665 -- Start of processing for Insert
668 -- The buckets array length is specified by the user as a discriminant
669 -- of the container type, so it is possible for the buckets array to
670 -- have a length of zero. We must check for this case specifically, in
671 -- order to prevent divide-by-zero errors later, when we compute the
672 -- buckets array index value for a key, given its hash value.
674 if Checks
and then Container
.Buckets
'Length = 0 then
675 raise Capacity_Error
with "No capacity for insertion";
678 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
679 Position
.Container
:= Container
'Unchecked_Access;
683 (Container
: in out Map
;
685 New_Item
: Element_Type
)
688 pragma Unreferenced
(Position
);
693 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
695 if Checks
and then not Inserted
then
696 raise Constraint_Error
with
697 "attempt to insert key already in map";
705 function Is_Empty
(Container
: Map
) return Boolean is
707 return Container
.Length
= 0;
716 Process
: not null access procedure (Position
: Cursor
))
718 procedure Process_Node
(Node
: Count_Type
);
719 pragma Inline
(Process_Node
);
721 procedure Local_Iterate
is new HT_Ops
.Generic_Iteration
(Process_Node
);
727 procedure Process_Node
(Node
: Count_Type
) is
729 Process
(Cursor
'(Container'Unrestricted_Access, Node));
732 Busy : With_Busy (Container.TC'Unrestricted_Access);
734 -- Start of processing for Iterate
737 Local_Iterate (Container);
741 (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
744 return It : constant Iterator :=
745 (Limited_Controlled with
746 Container => Container'Unrestricted_Access)
748 Busy (Container.TC'Unrestricted_Access.all);
756 function Key (Position : Cursor) return Key_Type is
758 if Checks and then Position.Node = 0 then
759 raise Constraint_Error with
760 "Position cursor of function Key equals No_Element";
763 pragma Assert (Vet (Position), "bad cursor in function Key");
765 return Position.Container.Nodes (Position.Node).Key;
772 function Length (Container : Map) return Count_Type is
774 return Container.Length;
782 (Target : in out Map;
786 if Target'Address = Source'Address then
790 TC_Check (Source.TC);
792 Target.Assign (Source);
800 function Next (Node : Node_Type) return Count_Type is
805 function Next (Position : Cursor) return Cursor is
807 if Position.Node = 0 then
811 pragma Assert (Vet (Position), "bad cursor in function Next");
814 M : Map renames Position.Container.all;
815 Node : constant Count_Type := HT_Ops.Next (M, Position.Node);
820 return Cursor'(Position
.Container
, Node
);
825 procedure Next
(Position
: in out Cursor
) is
827 Position
:= Next
(Position
);
832 Position
: Cursor
) return Cursor
835 if Position
.Container
= null then
839 if Checks
and then Position
.Container
/= Object
.Container
then
840 raise Program_Error
with
841 "Position cursor of Next designates wrong map";
844 return Next
(Position
);
847 ----------------------
848 -- Pseudo_Reference --
849 ----------------------
851 function Pseudo_Reference
852 (Container
: aliased Map
'Class) return Reference_Control_Type
854 TC
: constant Tamper_Counts_Access
:=
855 Container
.TC
'Unrestricted_Access;
857 return R
: constant Reference_Control_Type
:= (Controlled
with TC
) do
860 end Pseudo_Reference
;
866 procedure Query_Element
868 Process
: not null access
869 procedure (Key
: Key_Type
; Element
: Element_Type
))
872 if Checks
and then Position
.Node
= 0 then
873 raise Constraint_Error
with
874 "Position cursor of Query_Element equals No_Element";
877 pragma Assert
(Vet
(Position
), "bad cursor in Query_Element");
880 M
: Map
renames Position
.Container
.all;
881 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
882 Lock
: With_Lock
(M
.TC
'Unrestricted_Access);
884 Process
(N
.Key
, N
.Element
);
893 (Stream
: not null access Root_Stream_Type
'Class;
897 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
;
898 -- pragma Inline (Read_Node); ???
900 procedure Read_Nodes
is new HT_Ops
.Generic_Read
(Read_Node
);
907 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
909 procedure Read_Element
(Node
: in out Node_Type
);
910 -- pragma Inline (Read_Element); ???
912 procedure Allocate
is
913 new HT_Ops
.Generic_Allocate
(Read_Element
);
915 procedure Read_Element
(Node
: in out Node_Type
) is
917 Key_Type
'Read (Stream
, Node
.Key
);
918 Element_Type
'Read (Stream
, Node
.Element
);
923 -- Start of processing for Read_Node
926 Allocate
(Container
, Node
);
930 -- Start of processing for Read
933 Read_Nodes
(Stream
, Container
);
937 (Stream
: not null access Root_Stream_Type
'Class;
941 raise Program_Error
with "attempt to stream map cursor";
945 (Stream
: not null access Root_Stream_Type
'Class;
946 Item
: out Reference_Type
)
949 raise Program_Error
with "attempt to stream reference";
953 (Stream
: not null access Root_Stream_Type
'Class;
954 Item
: out Constant_Reference_Type
)
957 raise Program_Error
with "attempt to stream reference";
965 (Container
: aliased in out Map
;
966 Position
: Cursor
) return Reference_Type
969 if Checks
and then Position
.Container
= null then
970 raise Constraint_Error
with
971 "Position cursor has no element";
974 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
976 raise Program_Error
with
977 "Position cursor designates wrong map";
980 pragma Assert
(Vet
(Position
),
981 "Position cursor in function Reference is bad");
984 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
985 TC
: constant Tamper_Counts_Access
:=
986 Container
.TC
'Unrestricted_Access;
988 return R
: constant Reference_Type
:=
989 (Element
=> N
.Element
'Access,
990 Control
=> (Controlled
with TC
))
998 (Container
: aliased in out Map
;
999 Key
: Key_Type
) return Reference_Type
1001 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1004 if Checks
and then Node
= 0 then
1005 raise Constraint_Error
with "key not in map";
1009 N
: Node_Type
renames Container
.Nodes
(Node
);
1010 TC
: constant Tamper_Counts_Access
:=
1011 Container
.TC
'Unrestricted_Access;
1013 return R
: constant Reference_Type
:=
1014 (Element
=> N
.Element
'Access,
1015 Control
=> (Controlled
with TC
))
1027 (Container
: in out Map
;
1029 New_Item
: Element_Type
)
1031 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1034 if Checks
and then Node
= 0 then
1035 raise Constraint_Error
with
1036 "attempt to replace key not in map";
1039 TE_Check
(Container
.TC
);
1042 N
: Node_Type
renames Container
.Nodes
(Node
);
1045 N
.Element
:= New_Item
;
1049 ---------------------
1050 -- Replace_Element --
1051 ---------------------
1053 procedure Replace_Element
1054 (Container
: in out Map
;
1056 New_Item
: Element_Type
)
1059 if Checks
and then Position
.Node
= 0 then
1060 raise Constraint_Error
with
1061 "Position cursor of Replace_Element equals No_Element";
1064 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
1066 raise Program_Error
with
1067 "Position cursor of Replace_Element designates wrong map";
1070 TE_Check
(Position
.Container
.TC
);
1072 pragma Assert
(Vet
(Position
), "bad cursor in Replace_Element");
1074 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1075 end Replace_Element
;
1077 ----------------------
1078 -- Reserve_Capacity --
1079 ----------------------
1081 procedure Reserve_Capacity
1082 (Container
: in out Map
;
1083 Capacity
: Count_Type
)
1086 if Checks
and then Capacity
> Container
.Capacity
then
1087 raise Capacity_Error
with "requested capacity is too large";
1089 end Reserve_Capacity
;
1095 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1100 --------------------
1101 -- Update_Element --
1102 --------------------
1104 procedure Update_Element
1105 (Container
: in out Map
;
1107 Process
: not null access procedure (Key
: Key_Type
;
1108 Element
: in out Element_Type
))
1111 if Checks
and then Position
.Node
= 0 then
1112 raise Constraint_Error
with
1113 "Position cursor of Update_Element equals No_Element";
1116 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
1118 raise Program_Error
with
1119 "Position cursor of Update_Element designates wrong map";
1122 pragma Assert
(Vet
(Position
), "bad cursor in Update_Element");
1125 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1126 Lock
: With_Lock
(Container
.TC
'Unrestricted_Access);
1128 Process
(N
.Key
, N
.Element
);
1136 function Vet
(Position
: Cursor
) return Boolean is
1138 if Position
.Node
= 0 then
1139 return Position
.Container
= null;
1142 if Position
.Container
= null then
1147 M
: Map
renames Position
.Container
.all;
1151 if M
.Length
= 0 then
1155 if M
.Capacity
= 0 then
1159 if M
.Buckets
'Length = 0 then
1163 if Position
.Node
> M
.Capacity
then
1167 if M
.Nodes
(Position
.Node
).Next
= Position
.Node
then
1171 X
:= M
.Buckets
(Key_Ops
.Checked_Index
1172 (M
, M
.Nodes
(Position
.Node
).Key
));
1174 for J
in 1 .. M
.Length
loop
1175 if X
= Position
.Node
then
1183 if X
= M
.Nodes
(X
).Next
then -- to prevent unnecessary looping
1187 X
:= M
.Nodes
(X
).Next
;
1199 (Stream
: not null access Root_Stream_Type
'Class;
1202 procedure Write_Node
1203 (Stream
: not null access Root_Stream_Type
'Class;
1205 pragma Inline
(Write_Node
);
1207 procedure Write_Nodes
is new HT_Ops
.Generic_Write
(Write_Node
);
1213 procedure Write_Node
1214 (Stream
: not null access Root_Stream_Type
'Class;
1218 Key_Type
'Write (Stream
, Node
.Key
);
1219 Element_Type
'Write (Stream
, Node
.Element
);
1222 -- Start of processing for Write
1225 Write_Nodes
(Stream
, Container
);
1229 (Stream
: not null access Root_Stream_Type
'Class;
1233 raise Program_Error
with "attempt to stream map cursor";
1237 (Stream
: not null access Root_Stream_Type
'Class;
1238 Item
: Reference_Type
)
1241 raise Program_Error
with "attempt to stream reference";
1245 (Stream
: not null access Root_Stream_Type
'Class;
1246 Item
: Constant_Reference_Type
)
1249 raise Program_Error
with "attempt to stream reference";
1252 end Ada
.Containers
.Bounded_Hashed_Maps
;