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 pragma Annotate
(CodePeer
, Skip_Analysis
);
44 -----------------------
45 -- Local Subprograms --
46 -----------------------
48 function Equivalent_Key_Node
50 Node
: Node_Type
) return Boolean;
51 pragma Inline
(Equivalent_Key_Node
);
53 function Hash_Node
(Node
: Node_Type
) return Hash_Type
;
54 pragma Inline
(Hash_Node
);
56 function Next
(Node
: Node_Type
) return Count_Type
;
59 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
);
60 pragma Inline
(Set_Next
);
62 function Vet
(Position
: Cursor
) return Boolean;
64 --------------------------
65 -- Local Instantiations --
66 --------------------------
68 package HT_Ops
is new Hash_Tables
.Generic_Bounded_Operations
69 (HT_Types
=> HT_Types
,
70 Hash_Node
=> Hash_Node
,
72 Set_Next
=> Set_Next
);
74 package Key_Ops
is new Hash_Tables
.Generic_Bounded_Keys
75 (HT_Types
=> HT_Types
,
80 Equivalent_Keys
=> Equivalent_Key_Node
);
86 function "=" (Left
, Right
: Map
) return Boolean is
87 function Find_Equal_Key
88 (R_HT
: Hash_Table_Type
'Class;
89 L_Node
: Node_Type
) return Boolean;
91 function Is_Equal
is new HT_Ops
.Generic_Equal
(Find_Equal_Key
);
97 function Find_Equal_Key
98 (R_HT
: Hash_Table_Type
'Class;
99 L_Node
: Node_Type
) return Boolean
101 R_Index
: constant Hash_Type
:= Key_Ops
.Index
(R_HT
, L_Node
.Key
);
102 R_Node
: Count_Type
:= R_HT
.Buckets
(R_Index
);
105 while R_Node
/= 0 loop
106 if Equivalent_Keys
(L_Node
.Key
, R_HT
.Nodes
(R_Node
).Key
) then
107 return L_Node
.Element
= R_HT
.Nodes
(R_Node
).Element
;
110 R_Node
:= R_HT
.Nodes
(R_Node
).Next
;
116 -- Start of processing for "="
119 return Is_Equal
(Left
, Right
);
126 procedure Adjust
(Control
: in out Reference_Control_Type
) is
128 if Control
.Container
/= null then
130 C
: Map
renames Control
.Container
.all;
131 B
: Natural renames C
.Busy
;
132 L
: Natural renames C
.Lock
;
144 procedure Assign
(Target
: in out Map
; Source
: Map
) is
145 procedure Insert_Element
(Source_Node
: Count_Type
);
147 procedure Insert_Elements
is
148 new HT_Ops
.Generic_Iteration
(Insert_Element
);
154 procedure Insert_Element
(Source_Node
: Count_Type
) is
155 N
: Node_Type
renames Source
.Nodes
(Source_Node
);
160 Insert
(Target
, N
.Key
, N
.Element
, C
, B
);
164 -- Start of processing for Assign
167 if Target
'Address = Source
'Address then
171 if Target
.Capacity
< Source
.Length
then
173 with "Target capacity is less than Source length";
176 HT_Ops
.Clear
(Target
);
177 Insert_Elements
(Source
);
184 function Capacity
(Container
: Map
) return Count_Type
is
186 return Container
.Capacity
;
193 procedure Clear
(Container
: in out Map
) is
195 HT_Ops
.Clear
(Container
);
198 ------------------------
199 -- Constant_Reference --
200 ------------------------
202 function Constant_Reference
203 (Container
: aliased Map
;
204 Position
: Cursor
) return Constant_Reference_Type
207 if Position
.Container
= null then
208 raise Constraint_Error
with
209 "Position cursor has no element";
212 if Position
.Container
/= Container
'Unrestricted_Access then
213 raise Program_Error
with
214 "Position cursor designates wrong map";
217 pragma Assert
(Vet
(Position
),
218 "Position cursor in Constant_Reference is bad");
221 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
222 B
: Natural renames Position
.Container
.Busy
;
223 L
: Natural renames Position
.Container
.Lock
;
225 return R
: constant Constant_Reference_Type
:=
226 (Element
=> N
.Element
'Access,
227 Control
=> (Controlled
with Container
'Unrestricted_Access))
233 end Constant_Reference
;
235 function Constant_Reference
236 (Container
: aliased Map
;
237 Key
: Key_Type
) return Constant_Reference_Type
239 Node
: constant Count_Type
:=
240 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
244 raise Constraint_Error
with "key not in map";
248 Cur
: Cursor
:= Find
(Container
, Key
);
249 pragma Unmodified
(Cur
);
251 N
: Node_Type
renames Container
.Nodes
(Node
);
252 B
: Natural renames Cur
.Container
.Busy
;
253 L
: Natural renames Cur
.Container
.Lock
;
256 return R
: constant Constant_Reference_Type
:=
257 (Element
=> N
.Element
'Access,
258 Control
=> (Controlled
with Container
'Unrestricted_Access))
264 end Constant_Reference
;
270 function Contains
(Container
: Map
; Key
: Key_Type
) return Boolean is
272 return Find
(Container
, Key
) /= No_Element
;
281 Capacity
: Count_Type
:= 0;
282 Modulus
: Hash_Type
:= 0) return Map
291 elsif Capacity
>= Source
.Length
then
295 raise Capacity_Error
with "Capacity value too small";
299 M
:= Default_Modulus
(C
);
304 return Target
: Map
(Capacity
=> C
, Modulus
=> M
) do
305 Assign
(Target
=> Target
, Source
=> Source
);
309 ---------------------
310 -- Default_Modulus --
311 ---------------------
313 function Default_Modulus
(Capacity
: Count_Type
) return Hash_Type
is
315 return To_Prime
(Capacity
);
322 procedure Delete
(Container
: in out Map
; Key
: Key_Type
) is
326 Key_Ops
.Delete_Key_Sans_Free
(Container
, Key
, X
);
329 raise Constraint_Error
with "attempt to delete key not in map";
332 HT_Ops
.Free
(Container
, X
);
335 procedure Delete
(Container
: in out Map
; Position
: in out Cursor
) is
337 if Position
.Node
= 0 then
338 raise Constraint_Error
with
339 "Position cursor of Delete equals No_Element";
342 if Position
.Container
/= Container
'Unrestricted_Access then
343 raise Program_Error
with
344 "Position cursor of Delete designates wrong map";
347 if Container
.Busy
> 0 then
348 raise Program_Error
with
349 "Delete attempted to tamper with cursors (map is busy)";
352 pragma Assert
(Vet
(Position
), "bad cursor in Delete");
354 HT_Ops
.Delete_Node_Sans_Free
(Container
, Position
.Node
);
355 HT_Ops
.Free
(Container
, Position
.Node
);
357 Position
:= No_Element
;
364 function Element
(Container
: Map
; Key
: Key_Type
) return Element_Type
is
365 Node
: constant Count_Type
:=
366 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
370 raise Constraint_Error
with
371 "no element available because key not in map";
374 return Container
.Nodes
(Node
).Element
;
377 function Element
(Position
: Cursor
) return Element_Type
is
379 if Position
.Node
= 0 then
380 raise Constraint_Error
with
381 "Position cursor of function Element equals No_Element";
384 pragma Assert
(Vet
(Position
), "bad cursor in function Element");
386 return Position
.Container
.Nodes
(Position
.Node
).Element
;
389 -------------------------
390 -- Equivalent_Key_Node --
391 -------------------------
393 function Equivalent_Key_Node
395 Node
: Node_Type
) return Boolean is
397 return Equivalent_Keys
(Key
, Node
.Key
);
398 end Equivalent_Key_Node
;
400 ---------------------
401 -- Equivalent_Keys --
402 ---------------------
404 function Equivalent_Keys
(Left
, Right
: Cursor
)
407 if Left
.Node
= 0 then
408 raise Constraint_Error
with
409 "Left cursor of Equivalent_Keys equals No_Element";
412 if Right
.Node
= 0 then
413 raise Constraint_Error
with
414 "Right cursor of Equivalent_Keys equals No_Element";
417 pragma Assert
(Vet
(Left
), "Left cursor of Equivalent_Keys is bad");
418 pragma Assert
(Vet
(Right
), "Right cursor of Equivalent_Keys is bad");
421 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
422 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
425 return Equivalent_Keys
(LN
.Key
, RN
.Key
);
429 function Equivalent_Keys
(Left
: Cursor
; Right
: Key_Type
) return Boolean is
431 if Left
.Node
= 0 then
432 raise Constraint_Error
with
433 "Left cursor of Equivalent_Keys equals No_Element";
436 pragma Assert
(Vet
(Left
), "Left cursor in Equivalent_Keys is bad");
439 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
442 return Equivalent_Keys
(LN
.Key
, Right
);
446 function Equivalent_Keys
(Left
: Key_Type
; Right
: Cursor
) return Boolean is
448 if Right
.Node
= 0 then
449 raise Constraint_Error
with
450 "Right cursor of Equivalent_Keys equals No_Element";
453 pragma Assert
(Vet
(Right
), "Right cursor of Equivalent_Keys is bad");
456 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
459 return Equivalent_Keys
(Left
, RN
.Key
);
467 procedure Exclude
(Container
: in out Map
; Key
: Key_Type
) is
470 Key_Ops
.Delete_Key_Sans_Free
(Container
, Key
, X
);
471 HT_Ops
.Free
(Container
, X
);
478 procedure Finalize
(Object
: in out Iterator
) is
480 if Object
.Container
/= null then
482 B
: Natural renames Object
.Container
.all.Busy
;
489 procedure Finalize
(Control
: in out Reference_Control_Type
) is
491 if Control
.Container
/= null then
493 C
: Map
renames Control
.Container
.all;
494 B
: Natural renames C
.Busy
;
495 L
: Natural renames C
.Lock
;
501 Control
.Container
:= null;
509 function Find
(Container
: Map
; Key
: Key_Type
) return Cursor
is
510 Node
: constant Count_Type
:=
511 Key_Ops
.Find
(Container
'Unrestricted_Access.all, Key
);
516 return Cursor
'(Container'Unrestricted_Access, Node);
524 function First (Container : Map) return Cursor is
525 Node : constant Count_Type := HT_Ops.First (Container);
530 return Cursor'(Container
'Unrestricted_Access, Node
);
534 function First
(Object
: Iterator
) return Cursor
is
536 return Object
.Container
.First
;
543 function Has_Element
(Position
: Cursor
) return Boolean is
545 pragma Assert
(Vet
(Position
), "bad cursor in Has_Element");
546 return Position
.Node
/= 0;
553 function Hash_Node
(Node
: Node_Type
) return Hash_Type
is
555 return Hash
(Node
.Key
);
563 (Container
: in out Map
;
565 New_Item
: Element_Type
)
571 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
574 if Container
.Lock
> 0 then
575 raise Program_Error
with
576 "Include attempted to tamper with elements (map is locked)";
580 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
583 N
.Element
:= New_Item
;
593 (Container
: in out Map
;
595 Position
: out Cursor
;
596 Inserted
: out Boolean)
598 procedure Assign_Key
(Node
: in out Node_Type
);
599 pragma Inline
(Assign_Key
);
601 function New_Node
return Count_Type
;
602 pragma Inline
(New_Node
);
604 procedure Local_Insert
is
605 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
607 procedure Allocate
is
608 new HT_Ops
.Generic_Allocate
(Assign_Key
);
614 procedure Assign_Key
(Node
: in out Node_Type
) is
615 New_Item
: Element_Type
;
616 pragma Unmodified
(New_Item
);
617 -- Default-initialized element (ok to reference, see below)
622 -- There is no explicit element provided, but in an instance the
623 -- element type may be a scalar with a Default_Value aspect, or a
624 -- composite type with such a scalar component, or components with
625 -- default initialization, so insert a possibly initialized element
626 -- under the given key.
628 Node
.Element
:= New_Item
;
635 function New_Node
return Count_Type
is
638 Allocate
(Container
, Result
);
642 -- Start of processing for Insert
645 -- The buckets array length is specified by the user as a discriminant
646 -- of the container type, so it is possible for the buckets array to
647 -- have a length of zero. We must check for this case specifically, in
648 -- order to prevent divide-by-zero errors later, when we compute the
649 -- buckets array index value for a key, given its hash value.
651 if Container
.Buckets
'Length = 0 then
652 raise Capacity_Error
with "No capacity for insertion";
655 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
656 Position
.Container
:= Container
'Unchecked_Access;
660 (Container
: in out Map
;
662 New_Item
: Element_Type
;
663 Position
: out Cursor
;
664 Inserted
: out Boolean)
666 procedure Assign_Key
(Node
: in out Node_Type
);
667 pragma Inline
(Assign_Key
);
669 function New_Node
return Count_Type
;
670 pragma Inline
(New_Node
);
672 procedure Local_Insert
is
673 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
675 procedure Allocate
is
676 new HT_Ops
.Generic_Allocate
(Assign_Key
);
682 procedure Assign_Key
(Node
: in out Node_Type
) is
685 Node
.Element
:= New_Item
;
692 function New_Node
return Count_Type
is
695 Allocate
(Container
, Result
);
699 -- Start of processing for Insert
702 -- The buckets array length is specified by the user as a discriminant
703 -- of the container type, so it is possible for the buckets array to
704 -- have a length of zero. We must check for this case specifically, in
705 -- order to prevent divide-by-zero errors later, when we compute the
706 -- buckets array index value for a key, given its hash value.
708 if Container
.Buckets
'Length = 0 then
709 raise Capacity_Error
with "No capacity for insertion";
712 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
713 Position
.Container
:= Container
'Unchecked_Access;
717 (Container
: in out Map
;
719 New_Item
: Element_Type
)
722 pragma Unreferenced
(Position
);
727 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
730 raise Constraint_Error
with
731 "attempt to insert key already in map";
739 function Is_Empty
(Container
: Map
) return Boolean is
741 return Container
.Length
= 0;
750 Process
: not null access procedure (Position
: Cursor
))
752 procedure Process_Node
(Node
: Count_Type
);
753 pragma Inline
(Process_Node
);
755 procedure Local_Iterate
is new HT_Ops
.Generic_Iteration
(Process_Node
);
761 procedure Process_Node
(Node
: Count_Type
) is
763 Process
(Cursor
'(Container'Unrestricted_Access, Node));
766 B : Natural renames Container'Unrestricted_Access.all.Busy;
768 -- Start of processing for Iterate
774 Local_Iterate (Container);
785 (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
787 B : Natural renames Container'Unrestricted_Access.all.Busy;
790 return It : constant Iterator :=
791 (Limited_Controlled with
792 Container => Container'Unrestricted_Access)
802 function Key (Position : Cursor) return Key_Type is
804 if Position.Node = 0 then
805 raise Constraint_Error with
806 "Position cursor of function Key equals No_Element";
809 pragma Assert (Vet (Position), "bad cursor in function Key");
811 return Position.Container.Nodes (Position.Node).Key;
818 function Length (Container : Map) return Count_Type is
820 return Container.Length;
828 (Target : in out Map;
832 if Target'Address = Source'Address then
836 if Source.Busy > 0 then
837 raise Program_Error with
838 "attempt to tamper with cursors (container is busy)";
841 Target.Assign (Source);
849 function Next (Node : Node_Type) return Count_Type is
854 function Next (Position : Cursor) return Cursor is
856 if Position.Node = 0 then
860 pragma Assert (Vet (Position), "bad cursor in function Next");
863 M : Map renames Position.Container.all;
864 Node : constant Count_Type := HT_Ops.Next (M, Position.Node);
869 return Cursor'(Position
.Container
, Node
);
874 procedure Next
(Position
: in out Cursor
) is
876 Position
:= Next
(Position
);
881 Position
: Cursor
) return Cursor
884 if Position
.Container
= null then
888 if Position
.Container
/= Object
.Container
then
889 raise Program_Error
with
890 "Position cursor of Next designates wrong map";
893 return Next
(Position
);
900 procedure Query_Element
902 Process
: not null access
903 procedure (Key
: Key_Type
; Element
: Element_Type
))
906 if Position
.Node
= 0 then
907 raise Constraint_Error
with
908 "Position cursor of Query_Element equals No_Element";
911 pragma Assert
(Vet
(Position
), "bad cursor in Query_Element");
914 M
: Map
renames Position
.Container
.all;
915 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
916 B
: Natural renames M
.Busy
;
917 L
: Natural renames M
.Lock
;
926 Process
(N
.Key
, N
.Element
);
944 (Stream
: not null access Root_Stream_Type
'Class;
948 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
;
949 -- pragma Inline (Read_Node); ???
951 procedure Read_Nodes
is new HT_Ops
.Generic_Read
(Read_Node
);
958 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
960 procedure Read_Element
(Node
: in out Node_Type
);
961 -- pragma Inline (Read_Element); ???
963 procedure Allocate
is
964 new HT_Ops
.Generic_Allocate
(Read_Element
);
966 procedure Read_Element
(Node
: in out Node_Type
) is
968 Key_Type
'Read (Stream
, Node
.Key
);
969 Element_Type
'Read (Stream
, Node
.Element
);
974 -- Start of processing for Read_Node
977 Allocate
(Container
, Node
);
981 -- Start of processing for Read
984 Read_Nodes
(Stream
, Container
);
988 (Stream
: not null access Root_Stream_Type
'Class;
992 raise Program_Error
with "attempt to stream map cursor";
996 (Stream
: not null access Root_Stream_Type
'Class;
997 Item
: out Reference_Type
)
1000 raise Program_Error
with "attempt to stream reference";
1004 (Stream
: not null access Root_Stream_Type
'Class;
1005 Item
: out Constant_Reference_Type
)
1008 raise Program_Error
with "attempt to stream reference";
1016 (Container
: aliased in out Map
;
1017 Position
: Cursor
) return Reference_Type
1020 if Position
.Container
= null then
1021 raise Constraint_Error
with
1022 "Position cursor has no element";
1025 if Position
.Container
/= Container
'Unrestricted_Access then
1026 raise Program_Error
with
1027 "Position cursor designates wrong map";
1030 pragma Assert
(Vet
(Position
),
1031 "Position cursor in function Reference is bad");
1034 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1035 B
: Natural renames Container
.Busy
;
1036 L
: Natural renames Container
.Lock
;
1039 return R
: constant Reference_Type
:=
1040 (Element
=> N
.Element
'Access,
1041 Control
=> (Controlled
with Container
'Unrestricted_Access))
1050 (Container
: aliased in out Map
;
1051 Key
: Key_Type
) return Reference_Type
1053 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1057 raise Constraint_Error
with "key not in map";
1061 N
: Node_Type
renames Container
.Nodes
(Node
);
1062 B
: Natural renames Container
.Busy
;
1063 L
: Natural renames Container
.Lock
;
1066 return R
: constant Reference_Type
:=
1067 (Element
=> N
.Element
'Access,
1068 Control
=> (Controlled
with Container
'Unrestricted_Access))
1081 (Container
: in out Map
;
1083 New_Item
: Element_Type
)
1085 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1089 raise Constraint_Error
with
1090 "attempt to replace key not in map";
1093 if Container
.Lock
> 0 then
1094 raise Program_Error
with
1095 "Replace attempted to tamper with elements (map is locked)";
1099 N
: Node_Type
renames Container
.Nodes
(Node
);
1103 N
.Element
:= New_Item
;
1107 ---------------------
1108 -- Replace_Element --
1109 ---------------------
1111 procedure Replace_Element
1112 (Container
: in out Map
;
1114 New_Item
: Element_Type
)
1117 if Position
.Node
= 0 then
1118 raise Constraint_Error
with
1119 "Position cursor of Replace_Element equals No_Element";
1122 if Position
.Container
/= Container
'Unrestricted_Access then
1123 raise Program_Error
with
1124 "Position cursor of Replace_Element designates wrong map";
1127 if Position
.Container
.Lock
> 0 then
1128 raise Program_Error
with
1129 "Replace_Element attempted to tamper with elements (map is locked)";
1132 pragma Assert
(Vet
(Position
), "bad cursor in Replace_Element");
1134 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1135 end Replace_Element
;
1137 ----------------------
1138 -- Reserve_Capacity --
1139 ----------------------
1141 procedure Reserve_Capacity
1142 (Container
: in out Map
;
1143 Capacity
: Count_Type
)
1146 if Capacity
> Container
.Capacity
then
1147 raise Capacity_Error
with "requested capacity is too large";
1149 end Reserve_Capacity
;
1155 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1160 --------------------
1161 -- Update_Element --
1162 --------------------
1164 procedure Update_Element
1165 (Container
: in out Map
;
1167 Process
: not null access procedure (Key
: Key_Type
;
1168 Element
: in out Element_Type
))
1171 if Position
.Node
= 0 then
1172 raise Constraint_Error
with
1173 "Position cursor of Update_Element equals No_Element";
1176 if Position
.Container
/= Container
'Unrestricted_Access then
1177 raise Program_Error
with
1178 "Position cursor of Update_Element designates wrong map";
1181 pragma Assert
(Vet
(Position
), "bad cursor in Update_Element");
1184 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1185 B
: Natural renames Container
.Busy
;
1186 L
: Natural renames Container
.Lock
;
1193 Process
(N
.Key
, N
.Element
);
1210 function Vet
(Position
: Cursor
) return Boolean is
1212 if Position
.Node
= 0 then
1213 return Position
.Container
= null;
1216 if Position
.Container
= null then
1221 M
: Map
renames Position
.Container
.all;
1225 if M
.Length
= 0 then
1229 if M
.Capacity
= 0 then
1233 if M
.Buckets
'Length = 0 then
1237 if Position
.Node
> M
.Capacity
then
1241 if M
.Nodes
(Position
.Node
).Next
= Position
.Node
then
1245 X
:= M
.Buckets
(Key_Ops
.Checked_Index
1246 (M
, M
.Nodes
(Position
.Node
).Key
));
1248 for J
in 1 .. M
.Length
loop
1249 if X
= Position
.Node
then
1257 if X
= M
.Nodes
(X
).Next
then -- to prevent unnecessary looping
1261 X
:= M
.Nodes
(X
).Next
;
1273 (Stream
: not null access Root_Stream_Type
'Class;
1276 procedure Write_Node
1277 (Stream
: not null access Root_Stream_Type
'Class;
1279 pragma Inline
(Write_Node
);
1281 procedure Write_Nodes
is new HT_Ops
.Generic_Write
(Write_Node
);
1287 procedure Write_Node
1288 (Stream
: not null access Root_Stream_Type
'Class;
1292 Key_Type
'Write (Stream
, Node
.Key
);
1293 Element_Type
'Write (Stream
, Node
.Element
);
1296 -- Start of processing for Write
1299 Write_Nodes
(Stream
, Container
);
1303 (Stream
: not null access Root_Stream_Type
'Class;
1307 raise Program_Error
with "attempt to stream map cursor";
1311 (Stream
: not null access Root_Stream_Type
'Class;
1312 Item
: Reference_Type
)
1315 raise Program_Error
with "attempt to stream reference";
1319 (Stream
: not null access Root_Stream_Type
'Class;
1320 Item
: Constant_Reference_Type
)
1323 raise Program_Error
with "attempt to stream reference";
1326 end Ada
.Containers
.Bounded_Hashed_Maps
;