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-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/>. --
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
.Prime_Numbers
; use Ada
.Containers
.Prime_Numbers
;
38 with System
; use type System
.Address
;
40 package body Ada
.Containers
.Bounded_Hashed_Maps
is
42 -----------------------
43 -- Local Subprograms --
44 -----------------------
46 function Equivalent_Key_Node
48 Node
: Node_Type
) return Boolean;
49 pragma Inline
(Equivalent_Key_Node
);
51 function Hash_Node
(Node
: Node_Type
) return Hash_Type
;
52 pragma Inline
(Hash_Node
);
54 function Next
(Node
: Node_Type
) return Count_Type
;
57 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
);
58 pragma Inline
(Set_Next
);
60 function Vet
(Position
: Cursor
) return Boolean;
62 --------------------------
63 -- Local Instantiations --
64 --------------------------
66 package HT_Ops
is new Hash_Tables
.Generic_Bounded_Operations
67 (HT_Types
=> HT_Types
,
68 Hash_Node
=> Hash_Node
,
70 Set_Next
=> Set_Next
);
72 package Key_Ops
is new Hash_Tables
.Generic_Bounded_Keys
73 (HT_Types
=> HT_Types
,
78 Equivalent_Keys
=> Equivalent_Key_Node
);
84 function "=" (Left
, Right
: Map
) return Boolean is
85 function Find_Equal_Key
86 (R_HT
: Hash_Table_Type
'Class;
87 L_Node
: Node_Type
) return Boolean;
89 function Is_Equal
is new HT_Ops
.Generic_Equal
(Find_Equal_Key
);
95 function Find_Equal_Key
96 (R_HT
: Hash_Table_Type
'Class;
97 L_Node
: Node_Type
) return Boolean
99 R_Index
: constant Hash_Type
:= Key_Ops
.Index
(R_HT
, L_Node
.Key
);
100 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
103 while R_Node
/= 0 loop
104 if Equivalent_Keys
(L_Node
.Key
, R_HT
.Nodes
(R_Node
).Key
) then
105 return L_Node
.Element
= R_HT
.Nodes
(R_Node
).Element
;
108 R_Node
:= R_HT
.Nodes
(R_Node
).Next
;
114 -- Start of processing for "="
117 return Is_Equal
(Left
, Right
);
124 procedure Adjust
(Control
: in out Reference_Control_Type
) is
126 if Control
.Container
/= null then
128 C
: Map
renames Control
.Container
.all;
129 B
: Natural renames C
.Busy
;
130 L
: Natural renames C
.Lock
;
142 procedure Assign
(Target
: in out Map
; Source
: Map
) is
143 procedure Insert_Element
(Source_Node
: Count_Type
);
145 procedure Insert_Elements
is
146 new HT_Ops
.Generic_Iteration
(Insert_Element
);
152 procedure Insert_Element
(Source_Node
: Count_Type
) is
153 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
158 Insert
(Target
, N
.Key
, N
.Element
, C
, B
);
162 -- Start of processing for Assign
165 if Target
'Address = Source
'Address then
169 if Target
.Capacity
< Source
.Length
then
171 with "Target capacity is less than Source length";
174 HT_Ops
.Clear
(Target
);
175 Insert_Elements
(Source
);
182 function Capacity
(Container
: Map
) return Count_Type
is
184 return Container
.Capacity
;
191 procedure Clear
(Container
: in out Map
) is
193 HT_Ops
.Clear
(Container
);
196 ------------------------
197 -- Constant_Reference --
198 ------------------------
200 function Constant_Reference
201 (Container
: aliased Map
;
202 Position
: Cursor
) return Constant_Reference_Type
205 if Position
.Container
= null then
206 raise Constraint_Error
with
207 "Position cursor has no element";
210 if Position
.Container
/= Container
'Unrestricted_Access then
211 raise Program_Error
with
212 "Position cursor designates wrong map";
215 pragma Assert
(Vet
(Position
),
216 "Position cursor in Constant_Reference is bad");
219 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
220 B
: Natural renames Position
.Container
.Busy
;
221 L
: Natural renames Position
.Container
.Lock
;
223 return R
: constant Constant_Reference_Type
:=
224 (Element
=> N
.Element
'Access,
225 Control
=> (Controlled
with Container
'Unrestricted_Access))
231 end Constant_Reference
;
233 function Constant_Reference
234 (Container
: aliased Map
;
235 Key
: Key_Type
) return Constant_Reference_Type
237 Node
: constant Count_Type
:=
238 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
242 raise Constraint_Error
with "key not in map";
246 Cur
: Cursor
:= Find
(Container
, Key
);
247 pragma Unmodified
(Cur
);
249 N
: Node_Type
renames Container
.Nodes
(Node
);
250 B
: Natural renames Cur
.Container
.Busy
;
251 L
: Natural renames Cur
.Container
.Lock
;
254 return R
: constant Constant_Reference_Type
:=
255 (Element
=> N
.Element
'Access,
256 Control
=> (Controlled
with Container
'Unrestricted_Access))
262 end Constant_Reference
;
268 function Contains
(Container
: Map
; Key
: Key_Type
) return Boolean is
270 return Find
(Container
, Key
) /= No_Element
;
279 Capacity
: Count_Type
:= 0;
280 Modulus
: Hash_Type
:= 0) return Map
289 elsif Capacity
>= Source
.Length
then
293 raise Capacity_Error
with "Capacity value too small";
297 M
:= Default_Modulus
(C
);
302 return Target
: Map
(Capacity
=> C
, Modulus
=> M
) do
303 Assign
(Target
=> Target
, Source
=> Source
);
307 ---------------------
308 -- Default_Modulus --
309 ---------------------
311 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
313 return To_Prime
(Capacity
);
320 procedure Delete
(Container
: in out Map
; Key
: Key_Type
) is
324 Key_Ops
.Delete_Key_Sans_Free
(Container
, Key
, X
);
327 raise Constraint_Error
with "attempt to delete key not in map";
330 HT_Ops
.Free
(Container
, X
);
333 procedure Delete
(Container
: in out Map
; Position
: in out Cursor
) is
335 if Position
.Node
= 0 then
336 raise Constraint_Error
with
337 "Position cursor of Delete equals No_Element";
340 if Position
.Container
/= Container
'Unrestricted_Access then
341 raise Program_Error
with
342 "Position cursor of Delete designates wrong map";
345 if Container
.Busy
> 0 then
346 raise Program_Error
with
347 "Delete attempted to tamper with cursors (map is busy)";
350 pragma Assert
(Vet
(Position
), "bad cursor in Delete");
352 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
353 HT_Ops
.Free
(Container
, Position
.Node
);
355 Position
:= No_Element
;
362 function Element
(Container
: Map
; Key
: Key_Type
) return Element_Type
is
363 Node
: constant Count_Type
:=
364 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
368 raise Constraint_Error
with
369 "no element available because key not in map";
372 return Container
.Nodes
(Node
).Element
;
375 function Element
(Position
: Cursor
) return Element_Type
is
377 if Position
.Node
= 0 then
378 raise Constraint_Error
with
379 "Position cursor of function Element equals No_Element";
382 pragma Assert
(Vet
(Position
), "bad cursor in function Element");
384 return Position
.Container
.Nodes
(Position
.Node
).Element
;
387 -------------------------
388 -- Equivalent_Key_Node --
389 -------------------------
391 function Equivalent_Key_Node
393 Node
: Node_Type
) return Boolean is
395 return Equivalent_Keys
(Key
, Node
.Key
);
396 end Equivalent_Key_Node
;
398 ---------------------
399 -- Equivalent_Keys --
400 ---------------------
402 function Equivalent_Keys
(Left
, Right
: Cursor
)
405 if Left
.Node
= 0 then
406 raise Constraint_Error
with
407 "Left cursor of Equivalent_Keys equals No_Element";
410 if Right
.Node
= 0 then
411 raise Constraint_Error
with
412 "Right cursor of Equivalent_Keys equals No_Element";
415 pragma Assert
(Vet
(Left
), "Left cursor of Equivalent_Keys is bad");
416 pragma Assert
(Vet
(Right
), "Right cursor of Equivalent_Keys is bad");
419 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
420 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
423 return Equivalent_Keys
(LN
.Key
, RN
.Key
);
427 function Equivalent_Keys
(Left
: Cursor
; Right
: Key_Type
) return Boolean is
429 if Left
.Node
= 0 then
430 raise Constraint_Error
with
431 "Left cursor of Equivalent_Keys equals No_Element";
434 pragma Assert
(Vet
(Left
), "Left cursor in Equivalent_Keys is bad");
437 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
440 return Equivalent_Keys
(LN
.Key
, Right
);
444 function Equivalent_Keys
(Left
: Key_Type
; Right
: Cursor
) return Boolean is
446 if Right
.Node
= 0 then
447 raise Constraint_Error
with
448 "Right cursor of Equivalent_Keys equals No_Element";
451 pragma Assert
(Vet
(Right
), "Right cursor of Equivalent_Keys is bad");
454 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
457 return Equivalent_Keys
(Left
, RN
.Key
);
465 procedure Exclude
(Container
: in out Map
; Key
: Key_Type
) is
468 Key_Ops
.Delete_Key_Sans_Free
(Container
, Key
, X
);
469 HT_Ops
.Free
(Container
, X
);
476 procedure Finalize
(Object
: in out Iterator
) is
478 if Object
.Container
/= null then
480 B
: Natural renames Object
.Container
.all.Busy
;
487 procedure Finalize
(Control
: in out Reference_Control_Type
) is
489 if Control
.Container
/= null then
491 C
: Map
renames Control
.Container
.all;
492 B
: Natural renames C
.Busy
;
493 L
: Natural renames C
.Lock
;
499 Control
.Container
:= null;
507 function Find
(Container
: Map
; Key
: Key_Type
) return Cursor
is
508 Node
: constant Count_Type
:=
509 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
514 return Cursor
'(Container'Unrestricted_Access, Node);
522 function First (Container : Map) return Cursor is
523 Node : constant Count_Type := HT_Ops.First (Container);
528 return Cursor'(Container
'Unrestricted_Access, Node
);
532 function First
(Object
: Iterator
) return Cursor
is
534 return Object
.Container
.First
;
541 function Has_Element
(Position
: Cursor
) return Boolean is
543 pragma Assert
(Vet
(Position
), "bad cursor in Has_Element");
544 return Position
.Node
/= 0;
551 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
553 return Hash
(Node
.Key
);
561 (Container
: in out Map
;
563 New_Item
: Element_Type
)
569 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
572 if Container
.Lock
> 0 then
573 raise Program_Error
with
574 "Include attempted to tamper with elements (map is locked)";
578 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
581 N
.Element
:= New_Item
;
591 (Container
: in out Map
;
593 Position
: out Cursor
;
594 Inserted
: out Boolean)
596 procedure Assign_Key
(Node
: in out Node_Type
);
597 pragma Inline
(Assign_Key
);
599 function New_Node
return Count_Type
;
600 pragma Inline
(New_Node
);
602 procedure Local_Insert
is
603 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
605 procedure Allocate
is
606 new HT_Ops
.Generic_Allocate
(Assign_Key
);
612 procedure Assign_Key
(Node
: in out Node_Type
) is
613 New_Item
: Element_Type
;
614 pragma Unmodified
(New_Item
);
615 -- Default-initialized element (ok to reference, see below)
620 -- There is no explicit element provided, but in an instance the
621 -- element type may be a scalar with a Default_Value aspect, or a
622 -- composite type with such a scalar component, or components with
623 -- default initialization, so insert a possibly initialized element
624 -- under the given key.
626 Node
.Element
:= New_Item
;
633 function New_Node
return Count_Type
is
636 Allocate
(Container
, Result
);
640 -- Start of processing for Insert
643 -- The buckets array length is specified by the user as a discriminant
644 -- of the container type, so it is possible for the buckets array to
645 -- have a length of zero. We must check for this case specifically, in
646 -- order to prevent divide-by-zero errors later, when we compute the
647 -- buckets array index value for a key, given its hash value.
649 if Container
.Buckets
'Length = 0 then
650 raise Capacity_Error
with "No capacity for insertion";
653 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
654 Position
.Container
:= Container
'Unchecked_Access;
658 (Container
: in out Map
;
660 New_Item
: Element_Type
;
661 Position
: out Cursor
;
662 Inserted
: out Boolean)
664 procedure Assign_Key
(Node
: in out Node_Type
);
665 pragma Inline
(Assign_Key
);
667 function New_Node
return Count_Type
;
668 pragma Inline
(New_Node
);
670 procedure Local_Insert
is
671 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
673 procedure Allocate
is
674 new HT_Ops
.Generic_Allocate
(Assign_Key
);
680 procedure Assign_Key
(Node
: in out Node_Type
) is
683 Node
.Element
:= New_Item
;
690 function New_Node
return Count_Type
is
693 Allocate
(Container
, Result
);
697 -- Start of processing for Insert
700 -- The buckets array length is specified by the user as a discriminant
701 -- of the container type, so it is possible for the buckets array to
702 -- have a length of zero. We must check for this case specifically, in
703 -- order to prevent divide-by-zero errors later, when we compute the
704 -- buckets array index value for a key, given its hash value.
706 if Container
.Buckets
'Length = 0 then
707 raise Capacity_Error
with "No capacity for insertion";
710 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
711 Position
.Container
:= Container
'Unchecked_Access;
715 (Container
: in out Map
;
717 New_Item
: Element_Type
)
720 pragma Unreferenced
(Position
);
725 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
728 raise Constraint_Error
with
729 "attempt to insert key already in map";
737 function Is_Empty
(Container
: Map
) return Boolean is
739 return Container
.Length
= 0;
748 Process
: not null access procedure (Position
: Cursor
))
750 procedure Process_Node
(Node
: Count_Type
);
751 pragma Inline
(Process_Node
);
753 procedure Local_Iterate
is new HT_Ops
.Generic_Iteration
(Process_Node
);
759 procedure Process_Node
(Node
: Count_Type
) is
761 Process
(Cursor
'(Container'Unrestricted_Access, Node));
764 B : Natural renames Container'Unrestricted_Access.all.Busy;
766 -- Start of processing for Iterate
772 Local_Iterate (Container);
783 (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
785 B : Natural renames Container'Unrestricted_Access.all.Busy;
788 return It : constant Iterator :=
789 (Limited_Controlled with
790 Container => Container'Unrestricted_Access)
800 function Key (Position : Cursor) return Key_Type is
802 if Position.Node = 0 then
803 raise Constraint_Error with
804 "Position cursor of function Key equals No_Element";
807 pragma Assert (Vet (Position), "bad cursor in function Key");
809 return Position.Container.Nodes (Position.Node).Key;
816 function Length (Container : Map) return Count_Type is
818 return Container.Length;
826 (Target : in out Map;
830 if Target'Address = Source'Address then
834 if Source.Busy > 0 then
835 raise Program_Error with
836 "attempt to tamper with cursors (container is busy)";
839 Target.Assign (Source);
847 function Next (Node : Node_Type) return Count_Type is
852 function Next (Position : Cursor) return Cursor is
854 if Position.Node = 0 then
858 pragma Assert (Vet (Position), "bad cursor in function Next");
861 M : Map renames Position.Container.all;
862 Node : constant Count_Type := HT_Ops.Next (M, Position.Node);
867 return Cursor'(Position
.Container
, Node
);
872 procedure Next
(Position
: in out Cursor
) is
874 Position
:= Next
(Position
);
879 Position
: Cursor
) return Cursor
882 if Position
.Container
= null then
886 if Position
.Container
/= Object
.Container
then
887 raise Program_Error
with
888 "Position cursor of Next designates wrong map";
891 return Next
(Position
);
898 procedure Query_Element
900 Process
: not null access
901 procedure (Key
: Key_Type
; Element
: Element_Type
))
904 if Position
.Node
= 0 then
905 raise Constraint_Error
with
906 "Position cursor of Query_Element equals No_Element";
909 pragma Assert
(Vet
(Position
), "bad cursor in Query_Element");
912 M
: Map
renames Position
.Container
.all;
913 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
914 B
: Natural renames M
.Busy
;
915 L
: Natural renames M
.Lock
;
924 Process
(N
.Key
, N
.Element
);
942 (Stream
: not null access Root_Stream_Type
'Class;
946 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
;
947 -- pragma Inline (Read_Node); ???
949 procedure Read_Nodes
is new HT_Ops
.Generic_Read
(Read_Node
);
956 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
958 procedure Read_Element
(Node
: in out Node_Type
);
959 -- pragma Inline (Read_Element); ???
961 procedure Allocate
is
962 new HT_Ops
.Generic_Allocate
(Read_Element
);
964 procedure Read_Element
(Node
: in out Node_Type
) is
966 Key_Type
'Read (Stream
, Node
.Key
);
967 Element_Type
'Read (Stream
, Node
.Element
);
972 -- Start of processing for Read_Node
975 Allocate
(Container
, Node
);
979 -- Start of processing for Read
982 Read_Nodes
(Stream
, Container
);
986 (Stream
: not null access Root_Stream_Type
'Class;
990 raise Program_Error
with "attempt to stream map cursor";
994 (Stream
: not null access Root_Stream_Type
'Class;
995 Item
: out Reference_Type
)
998 raise Program_Error
with "attempt to stream reference";
1002 (Stream
: not null access Root_Stream_Type
'Class;
1003 Item
: out Constant_Reference_Type
)
1006 raise Program_Error
with "attempt to stream reference";
1014 (Container
: aliased in out Map
;
1015 Position
: Cursor
) return Reference_Type
1018 if Position
.Container
= null then
1019 raise Constraint_Error
with
1020 "Position cursor has no element";
1023 if Position
.Container
/= Container
'Unrestricted_Access then
1024 raise Program_Error
with
1025 "Position cursor designates wrong map";
1028 pragma Assert
(Vet
(Position
),
1029 "Position cursor in function Reference is bad");
1032 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1033 B
: Natural renames Container
.Busy
;
1034 L
: Natural renames Container
.Lock
;
1037 return R
: constant Reference_Type
:=
1038 (Element
=> N
.Element
'Access,
1039 Control
=> (Controlled
with Container
'Unrestricted_Access))
1048 (Container
: aliased in out Map
;
1049 Key
: Key_Type
) return Reference_Type
1051 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1055 raise Constraint_Error
with "key not in map";
1059 N
: Node_Type
renames Container
.Nodes
(Node
);
1060 B
: Natural renames Container
.Busy
;
1061 L
: Natural renames Container
.Lock
;
1064 return R
: constant Reference_Type
:=
1065 (Element
=> N
.Element
'Access,
1066 Control
=> (Controlled
with Container
'Unrestricted_Access))
1079 (Container
: in out Map
;
1081 New_Item
: Element_Type
)
1083 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1087 raise Constraint_Error
with
1088 "attempt to replace key not in map";
1091 if Container
.Lock
> 0 then
1092 raise Program_Error
with
1093 "Replace attempted to tamper with elements (map is locked)";
1097 N
: Node_Type
renames Container
.Nodes
(Node
);
1101 N
.Element
:= New_Item
;
1105 ---------------------
1106 -- Replace_Element --
1107 ---------------------
1109 procedure Replace_Element
1110 (Container
: in out Map
;
1112 New_Item
: Element_Type
)
1115 if Position
.Node
= 0 then
1116 raise Constraint_Error
with
1117 "Position cursor of Replace_Element equals No_Element";
1120 if Position
.Container
/= Container
'Unrestricted_Access then
1121 raise Program_Error
with
1122 "Position cursor of Replace_Element designates wrong map";
1125 if Position
.Container
.Lock
> 0 then
1126 raise Program_Error
with
1127 "Replace_Element attempted to tamper with elements (map is locked)";
1130 pragma Assert
(Vet
(Position
), "bad cursor in Replace_Element");
1132 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1133 end Replace_Element
;
1135 ----------------------
1136 -- Reserve_Capacity --
1137 ----------------------
1139 procedure Reserve_Capacity
1140 (Container
: in out Map
;
1141 Capacity
: Count_Type
)
1144 if Capacity
> Container
.Capacity
then
1145 raise Capacity_Error
with "requested capacity is too large";
1147 end Reserve_Capacity
;
1153 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1158 --------------------
1159 -- Update_Element --
1160 --------------------
1162 procedure Update_Element
1163 (Container
: in out Map
;
1165 Process
: not null access procedure (Key
: Key_Type
;
1166 Element
: in out Element_Type
))
1169 if Position
.Node
= 0 then
1170 raise Constraint_Error
with
1171 "Position cursor of Update_Element equals No_Element";
1174 if Position
.Container
/= Container
'Unrestricted_Access then
1175 raise Program_Error
with
1176 "Position cursor of Update_Element designates wrong map";
1179 pragma Assert
(Vet
(Position
), "bad cursor in Update_Element");
1182 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1183 B
: Natural renames Container
.Busy
;
1184 L
: Natural renames Container
.Lock
;
1191 Process
(N
.Key
, N
.Element
);
1208 function Vet
(Position
: Cursor
) return Boolean is
1210 if Position
.Node
= 0 then
1211 return Position
.Container
= null;
1214 if Position
.Container
= null then
1219 M
: Map
renames Position
.Container
.all;
1223 if M
.Length
= 0 then
1227 if M
.Capacity
= 0 then
1231 if M
.Buckets
'Length = 0 then
1235 if Position
.Node
> M
.Capacity
then
1239 if M
.Nodes
(Position
.Node
).Next
= Position
.Node
then
1243 X
:= M
.Buckets
(Key_Ops
.Checked_Index
1244 (M
, M
.Nodes
(Position
.Node
).Key
));
1246 for J
in 1 .. M
.Length
loop
1247 if X
= Position
.Node
then
1255 if X
= M
.Nodes
(X
).Next
then -- to prevent unnecessary looping
1259 X
:= M
.Nodes
(X
).Next
;
1271 (Stream
: not null access Root_Stream_Type
'Class;
1274 procedure Write_Node
1275 (Stream
: not null access Root_Stream_Type
'Class;
1277 pragma Inline
(Write_Node
);
1279 procedure Write_Nodes
is new HT_Ops
.Generic_Write
(Write_Node
);
1285 procedure Write_Node
1286 (Stream
: not null access Root_Stream_Type
'Class;
1290 Key_Type
'Write (Stream
, Node
.Key
);
1291 Element_Type
'Write (Stream
, Node
.Element
);
1294 -- Start of processing for Write
1297 Write_Nodes
(Stream
, Container
);
1301 (Stream
: not null access Root_Stream_Type
'Class;
1305 raise Program_Error
with "attempt to stream map cursor";
1309 (Stream
: not null access Root_Stream_Type
'Class;
1310 Item
: Reference_Type
)
1313 raise Program_Error
with "attempt to stream reference";
1317 (Stream
: not null access Root_Stream_Type
'Class;
1318 Item
: Constant_Reference_Type
)
1321 raise Program_Error
with "attempt to stream reference";
1324 end Ada
.Containers
.Bounded_Hashed_Maps
;