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 _ O R D E R E D _ M A P S --
9 -- Copyright (C) 2004-2015, 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
.Helpers
; use Ada
.Containers
.Helpers
;
32 with Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
;
34 (Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
);
36 with Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Keys
;
38 (Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Keys
);
40 with System
; use type System
.Address
;
42 package body Ada
.Containers
.Bounded_Ordered_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 -- Node Access Subprograms --
50 -----------------------------
52 -- These subprograms provide a functional interface to access fields
53 -- of a node, and a procedural interface for modifying these values.
55 function Color
(Node
: Node_Type
) return Color_Type
;
56 pragma Inline
(Color
);
58 function Left
(Node
: Node_Type
) return Count_Type
;
61 function Parent
(Node
: Node_Type
) return Count_Type
;
62 pragma Inline
(Parent
);
64 function Right
(Node
: Node_Type
) return Count_Type
;
65 pragma Inline
(Right
);
67 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
);
68 pragma Inline
(Set_Parent
);
70 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
);
71 pragma Inline
(Set_Left
);
73 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
);
74 pragma Inline
(Set_Right
);
76 procedure Set_Color
(Node
: in out Node_Type
; Color
: Color_Type
);
77 pragma Inline
(Set_Color
);
79 -----------------------
80 -- Local Subprograms --
81 -----------------------
83 function Is_Greater_Key_Node
85 Right
: Node_Type
) return Boolean;
86 pragma Inline
(Is_Greater_Key_Node
);
88 function Is_Less_Key_Node
90 Right
: Node_Type
) return Boolean;
91 pragma Inline
(Is_Less_Key_Node
);
93 --------------------------
94 -- Local Instantiations --
95 --------------------------
97 package Tree_Operations
is
98 new Red_Black_Trees
.Generic_Bounded_Operations
(Tree_Types
);
103 new Red_Black_Trees
.Generic_Bounded_Keys
104 (Tree_Operations
=> Tree_Operations
,
105 Key_Type
=> Key_Type
,
106 Is_Less_Key_Node
=> Is_Less_Key_Node
,
107 Is_Greater_Key_Node
=> Is_Greater_Key_Node
);
113 function "<" (Left
, Right
: Cursor
) return Boolean is
115 if Checks
and then Left
.Node
= 0 then
116 raise Constraint_Error
with "Left cursor of ""<"" equals No_Element";
119 if Checks
and then Right
.Node
= 0 then
120 raise Constraint_Error
with "Right cursor of ""<"" equals No_Element";
123 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
124 "Left cursor of ""<"" is bad");
126 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
127 "Right cursor of ""<"" is bad");
130 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
131 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
134 return LN
.Key
< RN
.Key
;
138 function "<" (Left
: Cursor
; Right
: Key_Type
) return Boolean is
140 if Checks
and then Left
.Node
= 0 then
141 raise Constraint_Error
with "Left cursor of ""<"" equals No_Element";
144 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
145 "Left cursor of ""<"" is bad");
148 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
151 return LN
.Key
< Right
;
155 function "<" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
157 if Checks
and then Right
.Node
= 0 then
158 raise Constraint_Error
with "Right cursor of ""<"" equals No_Element";
161 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
162 "Right cursor of ""<"" is bad");
165 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
168 return Left
< RN
.Key
;
176 function "=" (Left
, Right
: Map
) return Boolean is
177 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean;
178 pragma Inline
(Is_Equal_Node_Node
);
181 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
183 ------------------------
184 -- Is_Equal_Node_Node --
185 ------------------------
187 function Is_Equal_Node_Node
188 (L
, R
: Node_Type
) return Boolean is
190 if L
.Key
< R
.Key
then
193 elsif R
.Key
< L
.Key
then
197 return L
.Element
= R
.Element
;
199 end Is_Equal_Node_Node
;
201 -- Start of processing for "="
204 return Is_Equal
(Left
, Right
);
211 function ">" (Left
, Right
: Cursor
) return Boolean is
213 if Checks
and then Left
.Node
= 0 then
214 raise Constraint_Error
with "Left cursor of "">"" equals No_Element";
217 if Checks
and then Right
.Node
= 0 then
218 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
221 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
222 "Left cursor of "">"" is bad");
224 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
225 "Right cursor of "">"" is bad");
228 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
229 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
232 return RN
.Key
< LN
.Key
;
236 function ">" (Left
: Cursor
; Right
: Key_Type
) return Boolean is
238 if Checks
and then Left
.Node
= 0 then
239 raise Constraint_Error
with "Left cursor of "">"" equals No_Element";
242 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
243 "Left cursor of "">"" is bad");
246 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
248 return Right
< LN
.Key
;
252 function ">" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
254 if Checks
and then Right
.Node
= 0 then
255 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
258 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
259 "Right cursor of "">"" is bad");
262 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
265 return RN
.Key
< Left
;
273 procedure Assign
(Target
: in out Map
; Source
: Map
) is
274 procedure Append_Element
(Source_Node
: Count_Type
);
276 procedure Append_Elements
is
277 new Tree_Operations
.Generic_Iteration
(Append_Element
);
283 procedure Append_Element
(Source_Node
: Count_Type
) is
284 SN
: Node_Type
renames Source
.Nodes
(Source_Node
);
286 procedure Set_Element
(Node
: in out Node_Type
);
287 pragma Inline
(Set_Element
);
289 function New_Node
return Count_Type
;
290 pragma Inline
(New_Node
);
292 procedure Insert_Post
is
293 new Key_Ops
.Generic_Insert_Post
(New_Node
);
295 procedure Unconditional_Insert_Sans_Hint
is
296 new Key_Ops
.Generic_Unconditional_Insert
(Insert_Post
);
298 procedure Unconditional_Insert_Avec_Hint
is
299 new Key_Ops
.Generic_Unconditional_Insert_With_Hint
301 Unconditional_Insert_Sans_Hint
);
303 procedure Allocate
is
304 new Tree_Operations
.Generic_Allocate
(Set_Element
);
310 function New_Node
return Count_Type
is
314 Allocate
(Target
, Result
);
322 procedure Set_Element
(Node
: in out Node_Type
) is
325 Node
.Element
:= SN
.Element
;
328 Target_Node
: Count_Type
;
330 -- Start of processing for Append_Element
333 Unconditional_Insert_Avec_Hint
337 Node
=> Target_Node
);
340 -- Start of processing for Assign
343 if Target
'Address = Source
'Address then
347 if Checks
and then Target
.Capacity
< Source
.Length
then
349 with "Target capacity is less than Source length";
352 Tree_Operations
.Clear_Tree
(Target
);
353 Append_Elements
(Source
);
360 function Ceiling
(Container
: Map
; Key
: Key_Type
) return Cursor
is
361 Node
: constant Count_Type
:= Key_Ops
.Ceiling
(Container
, Key
);
368 return Cursor
'(Container'Unrestricted_Access, Node);
375 procedure Clear (Container : in out Map) is
377 Tree_Operations.Clear_Tree (Container);
384 function Color (Node : Node_Type) return Color_Type is
389 ------------------------
390 -- Constant_Reference --
391 ------------------------
393 function Constant_Reference
394 (Container : aliased Map;
395 Position : Cursor) return Constant_Reference_Type
398 if Checks and then Position.Container = null then
399 raise Constraint_Error with
400 "Position cursor has no element";
403 if Checks and then Position.Container /= Container'Unrestricted_Access
405 raise Program_Error with
406 "Position cursor designates wrong map";
409 pragma Assert (Vet (Container, Position.Node),
410 "Position cursor in Constant_Reference is bad");
413 N : Node_Type renames Container.Nodes (Position.Node);
414 TC : constant Tamper_Counts_Access :=
415 Container.TC'Unrestricted_Access;
417 return R : constant Constant_Reference_Type :=
418 (Element => N.Element'Access,
419 Control => (Controlled with TC))
424 end Constant_Reference;
426 function Constant_Reference
427 (Container : aliased Map;
428 Key : Key_Type) return Constant_Reference_Type
430 Node : constant Count_Type := Key_Ops.Find (Container, Key);
433 if Checks and then Node = 0 then
434 raise Constraint_Error with "key not in map";
438 N : Node_Type renames Container.Nodes (Node);
439 TC : constant Tamper_Counts_Access :=
440 Container.TC'Unrestricted_Access;
442 return R : constant Constant_Reference_Type :=
443 (Element => N.Element'Access,
444 Control => (Controlled with TC))
449 end Constant_Reference;
455 function Contains (Container : Map; Key : Key_Type) return Boolean is
457 return Find (Container, Key) /= No_Element;
464 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
471 elsif Capacity >= Source.Length then
475 raise Capacity_Error with "Capacity value too small";
478 return Target : Map (Capacity => C) do
479 Assign (Target => Target, Source => Source);
487 procedure Delete (Container : in out Map; Position : in out Cursor) is
489 if Checks and then Position.Node = 0 then
490 raise Constraint_Error with
491 "Position cursor of Delete equals No_Element";
494 if Checks and then Position.Container /= Container'Unrestricted_Access
496 raise Program_Error with
497 "Position cursor of Delete designates wrong map";
500 pragma Assert (Vet (Container, Position.Node),
501 "Position cursor of Delete is bad");
503 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
504 Tree_Operations.Free (Container, Position.Node);
506 Position := No_Element;
509 procedure Delete (Container : in out Map; Key : Key_Type) is
510 X : constant Count_Type := Key_Ops.Find (Container, Key);
513 if Checks and then X = 0 then
514 raise Constraint_Error with "key not in map";
517 Tree_Operations.Delete_Node_Sans_Free (Container, X);
518 Tree_Operations.Free (Container, X);
525 procedure Delete_First (Container : in out Map) is
526 X : constant Count_Type := Container.First;
530 Tree_Operations.Delete_Node_Sans_Free (Container, X);
531 Tree_Operations.Free (Container, X);
539 procedure Delete_Last (Container : in out Map) is
540 X : constant Count_Type := Container.Last;
544 Tree_Operations.Delete_Node_Sans_Free (Container, X);
545 Tree_Operations.Free (Container, X);
553 function Element (Position : Cursor) return Element_Type is
555 if Checks and then Position.Node = 0 then
556 raise Constraint_Error with
557 "Position cursor of function Element equals No_Element";
560 pragma Assert (Vet (Position.Container.all, Position.Node),
561 "Position cursor of function Element is bad");
563 return Position.Container.Nodes (Position.Node).Element;
566 function Element (Container : Map; Key : Key_Type) return Element_Type is
567 Node : constant Count_Type := Key_Ops.Find (Container, Key);
569 if Checks and then Node = 0 then
570 raise Constraint_Error with "key not in map";
573 return Container.Nodes (Node).Element;
576 ---------------------
577 -- Equivalent_Keys --
578 ---------------------
580 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
595 procedure Exclude (Container : in out Map; Key : Key_Type) is
596 X : constant Count_Type := Key_Ops.Find (Container, Key);
600 Tree_Operations.Delete_Node_Sans_Free (Container, X);
601 Tree_Operations.Free (Container, X);
609 procedure Finalize (Object : in out Iterator) is
611 if Object.Container /= null then
612 Unbusy (Object.Container.TC);
620 function Find (Container : Map; Key : Key_Type) return Cursor is
621 Node : constant Count_Type := Key_Ops.Find (Container, Key);
626 return Cursor'(Container
'Unrestricted_Access, Node
);
634 function First
(Container
: Map
) return Cursor
is
636 if Container
.First
= 0 then
639 return Cursor
'(Container'Unrestricted_Access, Container.First);
643 function First (Object : Iterator) return Cursor is
645 -- The value of the iterator object's Node component influences the
646 -- behavior of the First (and Last) selector function.
648 -- When the Node component is 0, this means the iterator object was
649 -- constructed without a start expression, in which case the (forward)
650 -- iteration starts from the (logical) beginning of the entire sequence
651 -- of items (corresponding to Container.First, for a forward iterator).
653 -- Otherwise, this is iteration over a partial sequence of items. When
654 -- the Node component is positive, the iterator object was constructed
655 -- with a start expression, that specifies the position from which the
656 -- (forward) partial iteration begins.
658 if Object.Node = 0 then
659 return Bounded_Ordered_Maps.First (Object.Container.all);
661 return Cursor'(Object
.Container
, Object
.Node
);
669 function First_Element
(Container
: Map
) return Element_Type
is
671 if Checks
and then Container
.First
= 0 then
672 raise Constraint_Error
with "map is empty";
675 return Container
.Nodes
(Container
.First
).Element
;
682 function First_Key
(Container
: Map
) return Key_Type
is
684 if Checks
and then Container
.First
= 0 then
685 raise Constraint_Error
with "map is empty";
688 return Container
.Nodes
(Container
.First
).Key
;
695 function Floor
(Container
: Map
; Key
: Key_Type
) return Cursor
is
696 Node
: constant Count_Type
:= Key_Ops
.Floor
(Container
, Key
);
701 return Cursor
'(Container'Unrestricted_Access, Node);
705 ------------------------
706 -- Get_Element_Access --
707 ------------------------
709 function Get_Element_Access
710 (Position : Cursor) return not null Element_Access is
712 return Position.Container.Nodes (Position.Node).Element'Access;
713 end Get_Element_Access;
719 function Has_Element (Position : Cursor) return Boolean is
721 return Position /= No_Element;
729 (Container : in out Map;
731 New_Item : Element_Type)
737 Insert (Container, Key, New_Item, Position, Inserted);
740 TE_Check (Container.TC);
743 N : Node_Type renames Container.Nodes (Position.Node);
746 N.Element := New_Item;
756 (Container : in out Map;
758 New_Item : Element_Type;
759 Position : out Cursor;
760 Inserted : out Boolean)
762 procedure Assign (Node : in out Node_Type);
763 pragma Inline (Assign);
765 function New_Node return Count_Type;
766 pragma Inline (New_Node);
768 procedure Insert_Post is
769 new Key_Ops.Generic_Insert_Post (New_Node);
771 procedure Insert_Sans_Hint is
772 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
774 procedure Allocate is
775 new Tree_Operations.Generic_Allocate (Assign);
781 procedure Assign (Node : in out Node_Type) is
784 Node.Element := New_Item;
791 function New_Node return Count_Type is
794 Allocate (Container, Result);
798 -- Start of processing for Insert
807 Position.Container := Container'Unrestricted_Access;
811 (Container : in out Map;
813 New_Item : Element_Type)
816 pragma Unreferenced (Position);
821 Insert (Container, Key, New_Item, Position, Inserted);
823 if Checks and then not Inserted then
824 raise Constraint_Error with "key already in map";
829 (Container : in out Map;
831 Position : out Cursor;
832 Inserted : out Boolean)
834 procedure Assign (Node : in out Node_Type);
835 pragma Inline (Assign);
837 function New_Node return Count_Type;
838 pragma Inline (New_Node);
840 procedure Insert_Post is
841 new Key_Ops.Generic_Insert_Post (New_Node);
843 procedure Insert_Sans_Hint is
844 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
846 procedure Allocate is
847 new Tree_Operations.Generic_Allocate (Assign);
853 procedure Assign (Node : in out Node_Type) is
854 New_Item : Element_Type;
855 pragma Unmodified (New_Item);
856 -- Default-initialized element (ok to reference, see below)
861 -- There is no explicit element provided, but in an instance the element
862 -- type may be a scalar with a Default_Value aspect, or a composite type
863 -- with such a scalar component or with defaulted components, so insert
864 -- possibly initialized elements at the given position.
866 Node.Element := New_Item;
873 function New_Node return Count_Type is
876 Allocate (Container, Result);
880 -- Start of processing for Insert
889 Position.Container := Container'Unrestricted_Access;
896 function Is_Empty (Container : Map) return Boolean is
898 return Container.Length = 0;
901 -------------------------
902 -- Is_Greater_Key_Node --
903 -------------------------
905 function Is_Greater_Key_Node
907 Right : Node_Type) return Boolean
910 -- Left > Right same as Right < Left
912 return Right.Key < Left;
913 end Is_Greater_Key_Node;
915 ----------------------
916 -- Is_Less_Key_Node --
917 ----------------------
919 function Is_Less_Key_Node
921 Right : Node_Type) return Boolean
924 return Left < Right.Key;
925 end Is_Less_Key_Node;
933 Process : not null access procedure (Position : Cursor))
935 procedure Process_Node (Node : Count_Type);
936 pragma Inline (Process_Node);
938 procedure Local_Iterate is
939 new Tree_Operations.Generic_Iteration (Process_Node);
945 procedure Process_Node (Node : Count_Type) is
947 Process (Cursor'(Container
'Unrestricted_Access, Node
));
950 Busy
: With_Busy
(Container
.TC
'Unrestricted_Access);
952 -- Start of processing for Iterate
955 Local_Iterate
(Container
);
959 (Container
: Map
) return Map_Iterator_Interfaces
.Reversible_Iterator
'Class
962 -- The value of the Node component influences the behavior of the First
963 -- and Last selector functions of the iterator object. When the Node
964 -- component is 0 (as is the case here), this means the iterator object
965 -- was constructed without a start expression. This is a complete
966 -- iterator, meaning that the iteration starts from the (logical)
967 -- beginning of the sequence of items.
969 -- Note: For a forward iterator, Container.First is the beginning, and
970 -- for a reverse iterator, Container.Last is the beginning.
972 return It
: constant Iterator
:=
973 (Limited_Controlled
with
974 Container
=> Container
'Unrestricted_Access,
977 Busy
(Container
.TC
'Unrestricted_Access.all);
984 return Map_Iterator_Interfaces
.Reversible_Iterator
'Class
987 -- Iterator was defined to behave the same as for a complete iterator,
988 -- and iterate over the entire sequence of items. However, those
989 -- semantics were unintuitive and arguably error-prone (it is too easy
990 -- to accidentally create an endless loop), and so they were changed,
991 -- per the ARG meeting in Denver on 2011/11. However, there was no
992 -- consensus about what positive meaning this corner case should have,
993 -- and so it was decided to simply raise an exception. This does imply,
994 -- however, that it is not possible to use a partial iterator to specify
995 -- an empty sequence of items.
997 if Checks
and then Start
= No_Element
then
998 raise Constraint_Error
with
999 "Start position for iterator equals No_Element";
1002 if Checks
and then Start
.Container
/= Container
'Unrestricted_Access then
1003 raise Program_Error
with
1004 "Start cursor of Iterate designates wrong map";
1007 pragma Assert
(Vet
(Container
, Start
.Node
),
1008 "Start cursor of Iterate is bad");
1010 -- The value of the Node component influences the behavior of the First
1011 -- and Last selector functions of the iterator object. When the Node
1012 -- component is positive (as is the case here), it means that this
1013 -- is a partial iteration, over a subset of the complete sequence of
1014 -- items. The iterator object was constructed with a start expression,
1015 -- indicating the position from which the iteration begins. (Note that
1016 -- the start position has the same value irrespective of whether this
1017 -- is a forward or reverse iteration.)
1019 return It
: constant Iterator
:=
1020 (Limited_Controlled
with
1021 Container
=> Container
'Unrestricted_Access,
1024 Busy
(Container
.TC
'Unrestricted_Access.all);
1032 function Key
(Position
: Cursor
) return Key_Type
is
1034 if Checks
and then Position
.Node
= 0 then
1035 raise Constraint_Error
with
1036 "Position cursor of function Key equals No_Element";
1039 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1040 "Position cursor of function Key is bad");
1042 return Position
.Container
.Nodes
(Position
.Node
).Key
;
1049 function Last
(Container
: Map
) return Cursor
is
1051 if Container
.Last
= 0 then
1054 return Cursor
'(Container'Unrestricted_Access, Container.Last);
1058 function Last (Object : Iterator) return Cursor is
1060 -- The value of the iterator object's Node component influences the
1061 -- behavior of the Last (and First) selector function.
1063 -- When the Node component is 0, this means the iterator object was
1064 -- constructed without a start expression, in which case the (reverse)
1065 -- iteration starts from the (logical) beginning of the entire sequence
1066 -- (corresponding to Container.Last, for a reverse iterator).
1068 -- Otherwise, this is iteration over a partial sequence of items. When
1069 -- the Node component is positive, the iterator object was constructed
1070 -- with a start expression, that specifies the position from which the
1071 -- (reverse) partial iteration begins.
1073 if Object.Node = 0 then
1074 return Bounded_Ordered_Maps.Last (Object.Container.all);
1076 return Cursor'(Object
.Container
, Object
.Node
);
1084 function Last_Element
(Container
: Map
) return Element_Type
is
1086 if Checks
and then Container
.Last
= 0 then
1087 raise Constraint_Error
with "map is empty";
1090 return Container
.Nodes
(Container
.Last
).Element
;
1097 function Last_Key
(Container
: Map
) return Key_Type
is
1099 if Checks
and then Container
.Last
= 0 then
1100 raise Constraint_Error
with "map is empty";
1103 return Container
.Nodes
(Container
.Last
).Key
;
1110 function Left
(Node
: Node_Type
) return Count_Type
is
1119 function Length
(Container
: Map
) return Count_Type
is
1121 return Container
.Length
;
1128 procedure Move
(Target
: in out Map
; Source
: in out Map
) is
1130 if Target
'Address = Source
'Address then
1134 TC_Check
(Source
.TC
);
1136 Target
.Assign
(Source
);
1144 procedure Next
(Position
: in out Cursor
) is
1146 Position
:= Next
(Position
);
1149 function Next
(Position
: Cursor
) return Cursor
is
1151 if Position
= No_Element
then
1155 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1156 "Position cursor of Next is bad");
1159 M
: Map
renames Position
.Container
.all;
1161 Node
: constant Count_Type
:=
1162 Tree_Operations
.Next
(M
, Position
.Node
);
1169 return Cursor
'(Position.Container, Node);
1175 Position : Cursor) return Cursor
1178 if Position.Container = null then
1182 if Checks and then Position.Container /= Object.Container then
1183 raise Program_Error with
1184 "Position cursor of Next designates wrong map";
1187 return Next (Position);
1194 function Parent (Node : Node_Type) return Count_Type is
1203 procedure Previous (Position : in out Cursor) is
1205 Position := Previous (Position);
1208 function Previous (Position : Cursor) return Cursor is
1210 if Position = No_Element then
1214 pragma Assert (Vet (Position.Container.all, Position.Node),
1215 "Position cursor of Previous is bad");
1218 M : Map renames Position.Container.all;
1220 Node : constant Count_Type :=
1221 Tree_Operations.Previous (M, Position.Node);
1228 return Cursor'(Position
.Container
, Node
);
1234 Position
: Cursor
) return Cursor
1237 if Position
.Container
= null then
1241 if Checks
and then Position
.Container
/= Object
.Container
then
1242 raise Program_Error
with
1243 "Position cursor of Previous designates wrong map";
1246 return Previous
(Position
);
1249 ----------------------
1250 -- Pseudo_Reference --
1251 ----------------------
1253 function Pseudo_Reference
1254 (Container
: aliased Map
'Class) return Reference_Control_Type
1256 TC
: constant Tamper_Counts_Access
:=
1257 Container
.TC
'Unrestricted_Access;
1259 return R
: constant Reference_Control_Type
:= (Controlled
with TC
) do
1262 end Pseudo_Reference
;
1268 procedure Query_Element
1270 Process
: not null access procedure (Key
: Key_Type
;
1271 Element
: Element_Type
))
1274 if Checks
and then Position
.Node
= 0 then
1275 raise Constraint_Error
with
1276 "Position cursor of Query_Element equals No_Element";
1279 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1280 "Position cursor of Query_Element is bad");
1283 M
: Map
renames Position
.Container
.all;
1284 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
1285 Lock
: With_Lock
(M
.TC
'Unrestricted_Access);
1287 Process
(N
.Key
, N
.Element
);
1296 (Stream
: not null access Root_Stream_Type
'Class;
1297 Container
: out Map
)
1299 procedure Read_Element
(Node
: in out Node_Type
);
1300 pragma Inline
(Read_Element
);
1302 procedure Allocate
is
1303 new Tree_Operations
.Generic_Allocate
(Read_Element
);
1305 procedure Read_Elements
is
1306 new Tree_Operations
.Generic_Read
(Allocate
);
1312 procedure Read_Element
(Node
: in out Node_Type
) is
1314 Key_Type
'Read (Stream
, Node
.Key
);
1315 Element_Type
'Read (Stream
, Node
.Element
);
1318 -- Start of processing for Read
1321 Read_Elements
(Stream
, Container
);
1325 (Stream
: not null access Root_Stream_Type
'Class;
1329 raise Program_Error
with "attempt to stream map cursor";
1333 (Stream
: not null access Root_Stream_Type
'Class;
1334 Item
: out Reference_Type
)
1337 raise Program_Error
with "attempt to stream reference";
1341 (Stream
: not null access Root_Stream_Type
'Class;
1342 Item
: out Constant_Reference_Type
)
1345 raise Program_Error
with "attempt to stream reference";
1353 (Container
: aliased in out Map
;
1354 Position
: Cursor
) return Reference_Type
1357 if Checks
and then Position
.Container
= null then
1358 raise Constraint_Error
with
1359 "Position cursor has no element";
1362 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
1364 raise Program_Error
with
1365 "Position cursor designates wrong map";
1368 pragma Assert
(Vet
(Container
, Position
.Node
),
1369 "Position cursor in function Reference is bad");
1372 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1373 TC
: constant Tamper_Counts_Access
:=
1374 Container
.TC
'Unrestricted_Access;
1376 return R
: constant Reference_Type
:=
1377 (Element
=> N
.Element
'Access,
1378 Control
=> (Controlled
with TC
))
1386 (Container
: aliased in out Map
;
1387 Key
: Key_Type
) return Reference_Type
1389 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1392 if Checks
and then Node
= 0 then
1393 raise Constraint_Error
with "key not in map";
1397 N
: Node_Type
renames Container
.Nodes
(Node
);
1398 TC
: constant Tamper_Counts_Access
:=
1399 Container
.TC
'Unrestricted_Access;
1401 return R
: constant Reference_Type
:=
1402 (Element
=> N
.Element
'Access,
1403 Control
=> (Controlled
with TC
))
1415 (Container
: in out Map
;
1417 New_Item
: Element_Type
)
1419 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1422 if Checks
and then Node
= 0 then
1423 raise Constraint_Error
with "key not in map";
1426 TE_Check
(Container
.TC
);
1429 N
: Node_Type
renames Container
.Nodes
(Node
);
1433 N
.Element
:= New_Item
;
1437 ---------------------
1438 -- Replace_Element --
1439 ---------------------
1441 procedure Replace_Element
1442 (Container
: in out Map
;
1444 New_Item
: Element_Type
)
1447 if Checks
and then Position
.Node
= 0 then
1448 raise Constraint_Error
with
1449 "Position cursor of Replace_Element equals No_Element";
1452 if Checks
and then Position
.Container
/= Container
'Unrestricted_Access
1454 raise Program_Error
with
1455 "Position cursor of Replace_Element designates wrong map";
1458 TE_Check
(Container
.TC
);
1460 pragma Assert
(Vet
(Container
, Position
.Node
),
1461 "Position cursor of Replace_Element is bad");
1463 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1464 end Replace_Element
;
1466 ---------------------
1467 -- Reverse_Iterate --
1468 ---------------------
1470 procedure Reverse_Iterate
1472 Process
: not null access procedure (Position
: Cursor
))
1474 procedure Process_Node
(Node
: Count_Type
);
1475 pragma Inline
(Process_Node
);
1477 procedure Local_Reverse_Iterate
is
1478 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1484 procedure Process_Node
(Node
: Count_Type
) is
1486 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1489 Busy : With_Busy (Container.TC'Unrestricted_Access);
1491 -- Start of processing for Reverse_Iterate
1494 Local_Reverse_Iterate (Container);
1495 end Reverse_Iterate;
1501 function Right (Node : Node_Type) return Count_Type is
1511 (Node : in out Node_Type;
1515 Node.Color := Color;
1522 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1531 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1533 Node.Parent := Parent;
1540 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1542 Node.Right := Right;
1545 --------------------
1546 -- Update_Element --
1547 --------------------
1549 procedure Update_Element
1550 (Container : in out Map;
1552 Process : not null access procedure (Key : Key_Type;
1553 Element : in out Element_Type))
1556 if Checks and then Position.Node = 0 then
1557 raise Constraint_Error with
1558 "Position cursor of Update_Element equals No_Element";
1561 if Checks and then Position.Container /= Container'Unrestricted_Access
1563 raise Program_Error with
1564 "Position cursor of Update_Element designates wrong map";
1567 pragma Assert (Vet (Container, Position.Node),
1568 "Position cursor of Update_Element is bad");
1571 N : Node_Type renames Container.Nodes (Position.Node);
1572 Lock : With_Lock (Container.TC'Unrestricted_Access);
1574 Process (N.Key, N.Element);
1583 (Stream : not null access Root_Stream_Type'Class;
1586 procedure Write_Node
1587 (Stream : not null access Root_Stream_Type'Class;
1589 pragma Inline (Write_Node);
1591 procedure Write_Nodes is
1592 new Tree_Operations.Generic_Write (Write_Node);
1598 procedure Write_Node
1599 (Stream : not null access Root_Stream_Type'Class;
1603 Key_Type'Write (Stream, Node.Key);
1604 Element_Type'Write (Stream, Node.Element);
1607 -- Start of processing for Write
1610 Write_Nodes (Stream, Container);
1614 (Stream : not null access Root_Stream_Type'Class;
1618 raise Program_Error with "attempt to stream map cursor";
1622 (Stream : not null access Root_Stream_Type'Class;
1623 Item : Reference_Type)
1626 raise Program_Error with "attempt to stream reference";
1630 (Stream : not null access Root_Stream_Type'Class;
1631 Item : Constant_Reference_Type)
1634 raise Program_Error with "attempt to stream reference";
1637 end Ada.Containers.Bounded_Ordered_Maps;