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-2017, 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 pragma Warnings
(Off
);
582 Default_Initialized_Item
: Element_Type
;
583 pragma Unmodified
(Default_Initialized_Item
);
584 -- Default-initialized element (ok to reference, see below)
589 -- There is no explicit element provided, but in an instance the
590 -- element type may be a scalar with a Default_Value aspect, or a
591 -- composite type with such a scalar component, or components with
592 -- default initialization, so insert a possibly initialized element
593 -- under the given key.
595 Node
.Element
:= Default_Initialized_Item
;
596 pragma Warnings
(On
);
603 function New_Node
return Count_Type
is
606 Allocate
(Container
, Result
);
610 -- Start of processing for Insert
613 -- The buckets array length is specified by the user as a discriminant
614 -- of the container type, so it is possible for the buckets array to
615 -- have a length of zero. We must check for this case specifically, in
616 -- order to prevent divide-by-zero errors later, when we compute the
617 -- buckets array index value for a key, given its hash value.
619 if Checks
and then Container
.Buckets
'Length = 0 then
620 raise Capacity_Error
with "No capacity for insertion";
623 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
624 Position
.Container
:= Container
'Unchecked_Access;
628 (Container
: in out Map
;
630 New_Item
: Element_Type
;
631 Position
: out Cursor
;
632 Inserted
: out Boolean)
634 procedure Assign_Key
(Node
: in out Node_Type
);
635 pragma Inline
(Assign_Key
);
637 function New_Node
return Count_Type
;
638 pragma Inline
(New_Node
);
640 procedure Local_Insert
is
641 new Key_Ops
.Generic_Conditional_Insert
(New_Node
);
643 procedure Allocate
is
644 new HT_Ops
.Generic_Allocate
(Assign_Key
);
650 procedure Assign_Key
(Node
: in out Node_Type
) is
653 Node
.Element
:= New_Item
;
660 function New_Node
return Count_Type
is
663 Allocate
(Container
, Result
);
667 -- Start of processing for Insert
670 -- The buckets array length is specified by the user as a discriminant
671 -- of the container type, so it is possible for the buckets array to
672 -- have a length of zero. We must check for this case specifically, in
673 -- order to prevent divide-by-zero errors later, when we compute the
674 -- buckets array index value for a key, given its hash value.
676 if Checks
and then Container
.Buckets
'Length = 0 then
677 raise Capacity_Error
with "No capacity for insertion";
680 Local_Insert
(Container
, Key
, Position
.Node
, Inserted
);
681 Position
.Container
:= Container
'Unchecked_Access;
685 (Container
: in out Map
;
687 New_Item
: Element_Type
)
690 pragma Unreferenced
(Position
);
695 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
697 if Checks
and then not Inserted
then
698 raise Constraint_Error
with
699 "attempt to insert key already in map";
707 function Is_Empty
(Container
: Map
) return Boolean is
709 return Container
.Length
= 0;
718 Process
: not null access procedure (Position
: Cursor
))
720 procedure Process_Node
(Node
: Count_Type
);
721 pragma Inline
(Process_Node
);
723 procedure Local_Iterate
is new HT_Ops
.Generic_Iteration
(Process_Node
);
729 procedure Process_Node
(Node
: Count_Type
) is
731 Process
(Cursor
'(Container'Unrestricted_Access, Node));
734 Busy : With_Busy (Container.TC'Unrestricted_Access);
736 -- Start of processing for Iterate
739 Local_Iterate (Container);
743 (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class
746 return It : constant Iterator :=
747 (Limited_Controlled with
748 Container => Container'Unrestricted_Access)
750 Busy (Container.TC'Unrestricted_Access.all);
758 function Key (Position : Cursor) return Key_Type is
760 if Checks and then Position.Node = 0 then
761 raise Constraint_Error with
762 "Position cursor of function Key equals No_Element";
765 pragma Assert (Vet (Position), "bad cursor in function Key");
767 return Position.Container.Nodes (Position.Node).Key;
774 function Length (Container : Map) return Count_Type is
776 return Container.Length;
784 (Target : in out Map;
788 if Target'Address = Source'Address then
792 TC_Check (Source.TC);
794 Target.Assign (Source);
802 function Next (Node : Node_Type) return Count_Type is
807 function Next (Position : Cursor) return Cursor is
809 if Position.Node = 0 then
813 pragma Assert (Vet (Position), "bad cursor in function Next");
816 M : Map renames Position.Container.all;
817 Node : constant Count_Type := HT_Ops.Next (M, Position.Node);
822 return Cursor'(Position
.Container
, Node
);
827 procedure Next
(Position
: in out Cursor
) is
829 Position
:= Next
(Position
);
834 Position
: Cursor
) return Cursor
837 if Position
.Container
= null then
841 if Checks
and then Position
.Container
/= Object
.Container
then
842 raise Program_Error
with
843 "Position cursor of Next designates wrong map";
846 return Next
(Position
);
849 ----------------------
850 -- Pseudo_Reference --
851 ----------------------
853 function Pseudo_Reference
854 (Container
: aliased Map
'Class) return Reference_Control_Type
856 TC
: constant Tamper_Counts_Access
:=
857 Container
.TC
'Unrestricted_Access;
859 return R
: constant Reference_Control_Type
:= (Controlled
with TC
) do
862 end Pseudo_Reference
;
868 procedure Query_Element
870 Process
: not null access
871 procedure (Key
: Key_Type
; Element
: Element_Type
))
874 if Checks
and then Position
.Node
= 0 then
875 raise Constraint_Error
with
876 "Position cursor of Query_Element equals No_Element";
879 pragma Assert
(Vet
(Position
), "bad cursor in Query_Element");
882 M
: Map
renames Position
.Container
.all;
883 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
884 Lock
: With_Lock
(M
.TC
'Unrestricted_Access);
886 Process
(N
.Key
, N
.Element
);
895 (Stream
: not null access Root_Stream_Type
'Class;
899 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
;
900 -- pragma Inline (Read_Node); ???
902 procedure Read_Nodes
is new HT_Ops
.Generic_Read
(Read_Node
);
909 (Stream
: not null access Root_Stream_Type
'Class) return Count_Type
911 procedure Read_Element
(Node
: in out Node_Type
);
912 -- pragma Inline (Read_Element); ???
914 procedure Allocate
is
915 new HT_Ops
.Generic_Allocate
(Read_Element
);
917 procedure Read_Element
(Node
: in out Node_Type
) is
919 Key_Type
'Read (Stream
, Node
.Key
);
920 Element_Type
'Read (Stream
, Node
.Element
);
925 -- Start of processing for Read_Node
928 Allocate
(Container
, Node
);
932 -- Start of processing for Read
935 Read_Nodes
(Stream
, Container
);
939 (Stream
: not null access Root_Stream_Type
'Class;
943 raise Program_Error
with "attempt to stream map cursor";
947 (Stream
: not null access Root_Stream_Type
'Class;
948 Item
: out Reference_Type
)
951 raise Program_Error
with "attempt to stream reference";
955 (Stream
: not null access Root_Stream_Type
'Class;
956 Item
: out Constant_Reference_Type
)
959 raise Program_Error
with "attempt to stream reference";
967 (Container
: aliased in out Map
;
968 Position
: Cursor
) return Reference_Type
971 if Checks
and then Position
.Container
= null then
972 raise Constraint_Error
with
973 "Position cursor has no element";
976 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
978 raise Program_Error
with
979 "Position cursor designates wrong map";
982 pragma Assert
(Vet
(Position
),
983 "Position cursor in function Reference is bad");
986 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
987 TC
: constant Tamper_Counts_Access
:=
988 Container
.TC
'Unrestricted_Access;
990 return R
: constant Reference_Type
:=
991 (Element
=> N
.Element
'Access,
992 Control
=> (Controlled
with TC
))
1000 (Container
: aliased in out Map
;
1001 Key
: Key_Type
) return Reference_Type
1003 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1006 if Checks
and then Node
= 0 then
1007 raise Constraint_Error
with "key not in map";
1011 N
: Node_Type
renames Container
.Nodes
(Node
);
1012 TC
: constant Tamper_Counts_Access
:=
1013 Container
.TC
'Unrestricted_Access;
1015 return R
: constant Reference_Type
:=
1016 (Element
=> N
.Element
'Access,
1017 Control
=> (Controlled
with TC
))
1029 (Container
: in out Map
;
1031 New_Item
: Element_Type
)
1033 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1036 if Checks
and then Node
= 0 then
1037 raise Constraint_Error
with
1038 "attempt to replace key not in map";
1041 TE_Check
(Container
.TC
);
1044 N
: Node_Type
renames Container
.Nodes
(Node
);
1047 N
.Element
:= New_Item
;
1051 ---------------------
1052 -- Replace_Element --
1053 ---------------------
1055 procedure Replace_Element
1056 (Container
: in out Map
;
1058 New_Item
: Element_Type
)
1061 if Checks
and then Position
.Node
= 0 then
1062 raise Constraint_Error
with
1063 "Position cursor of Replace_Element equals No_Element";
1066 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
1068 raise Program_Error
with
1069 "Position cursor of Replace_Element designates wrong map";
1072 TE_Check
(Position
.Container
.TC
);
1074 pragma Assert
(Vet
(Position
), "bad cursor in Replace_Element");
1076 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1077 end Replace_Element
;
1079 ----------------------
1080 -- Reserve_Capacity --
1081 ----------------------
1083 procedure Reserve_Capacity
1084 (Container
: in out Map
;
1085 Capacity
: Count_Type
)
1088 if Checks
and then Capacity
> Container
.Capacity
then
1089 raise Capacity_Error
with "requested capacity is too large";
1091 end Reserve_Capacity
;
1097 procedure Set_Next
(Node
: in out Node_Type
; Next
: Count_Type
) is
1102 --------------------
1103 -- Update_Element --
1104 --------------------
1106 procedure Update_Element
1107 (Container
: in out Map
;
1109 Process
: not null access procedure (Key
: Key_Type
;
1110 Element
: in out Element_Type
))
1113 if Checks
and then Position
.Node
= 0 then
1114 raise Constraint_Error
with
1115 "Position cursor of Update_Element equals No_Element";
1118 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
1120 raise Program_Error
with
1121 "Position cursor of Update_Element designates wrong map";
1124 pragma Assert
(Vet
(Position
), "bad cursor in Update_Element");
1127 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1128 Lock
: With_Lock
(Container
.TC
'Unrestricted_Access);
1130 Process
(N
.Key
, N
.Element
);
1138 function Vet
(Position
: Cursor
) return Boolean is
1140 if Position
.Node
= 0 then
1141 return Position
.Container
= null;
1144 if Position
.Container
= null then
1149 M
: Map
renames Position
.Container
.all;
1153 if M
.Length
= 0 then
1157 if M
.Capacity
= 0 then
1161 if M
.Buckets
'Length = 0 then
1165 if Position
.Node
> M
.Capacity
then
1169 if M
.Nodes
(Position
.Node
).Next
= Position
.Node
then
1173 X
:= M
.Buckets
(Key_Ops
.Checked_Index
1174 (M
, M
.Nodes
(Position
.Node
).Key
));
1176 for J
in 1 .. M
.Length
loop
1177 if X
= Position
.Node
then
1185 if X
= M
.Nodes
(X
).Next
then -- to prevent unnecessary looping
1189 X
:= M
.Nodes
(X
).Next
;
1201 (Stream
: not null access Root_Stream_Type
'Class;
1204 procedure Write_Node
1205 (Stream
: not null access Root_Stream_Type
'Class;
1207 pragma Inline
(Write_Node
);
1209 procedure Write_Nodes
is new HT_Ops
.Generic_Write
(Write_Node
);
1215 procedure Write_Node
1216 (Stream
: not null access Root_Stream_Type
'Class;
1220 Key_Type
'Write (Stream
, Node
.Key
);
1221 Element_Type
'Write (Stream
, Node
.Element
);
1224 -- Start of processing for Write
1227 Write_Nodes
(Stream
, Container
);
1231 (Stream
: not null access Root_Stream_Type
'Class;
1235 raise Program_Error
with "attempt to stream map cursor";
1239 (Stream
: not null access Root_Stream_Type
'Class;
1240 Item
: Reference_Type
)
1243 raise Program_Error
with "attempt to stream reference";
1247 (Stream
: not null access Root_Stream_Type
'Class;
1248 Item
: Constant_Reference_Type
)
1251 raise Program_Error
with "attempt to stream reference";
1254 end Ada
.Containers
.Bounded_Hashed_Maps
;