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-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
.Red_Black_Trees
.Generic_Bounded_Operations
;
32 (Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Operations
);
34 with Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Keys
;
36 (Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Keys
);
38 with System
; use type System
.Address
;
40 package body Ada
.Containers
.Bounded_Ordered_Maps
is
42 -----------------------------
43 -- Node Access Subprograms --
44 -----------------------------
46 -- These subprograms provide a functional interface to access fields
47 -- of a node, and a procedural interface for modifying these values.
49 function Color
(Node
: Node_Type
) return Color_Type
;
50 pragma Inline
(Color
);
52 function Left
(Node
: Node_Type
) return Count_Type
;
55 function Parent
(Node
: Node_Type
) return Count_Type
;
56 pragma Inline
(Parent
);
58 function Right
(Node
: Node_Type
) return Count_Type
;
59 pragma Inline
(Right
);
61 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
);
62 pragma Inline
(Set_Parent
);
64 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
);
65 pragma Inline
(Set_Left
);
67 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
);
68 pragma Inline
(Set_Right
);
70 procedure Set_Color
(Node
: in out Node_Type
; Color
: Color_Type
);
71 pragma Inline
(Set_Color
);
73 -----------------------
74 -- Local Subprograms --
75 -----------------------
77 function Is_Greater_Key_Node
79 Right
: Node_Type
) return Boolean;
80 pragma Inline
(Is_Greater_Key_Node
);
82 function Is_Less_Key_Node
84 Right
: Node_Type
) return Boolean;
85 pragma Inline
(Is_Less_Key_Node
);
87 --------------------------
88 -- Local Instantiations --
89 --------------------------
91 package Tree_Operations
is
92 new Red_Black_Trees
.Generic_Bounded_Operations
(Tree_Types
);
97 new Red_Black_Trees
.Generic_Bounded_Keys
98 (Tree_Operations
=> Tree_Operations
,
100 Is_Less_Key_Node
=> Is_Less_Key_Node
,
101 Is_Greater_Key_Node
=> Is_Greater_Key_Node
);
107 function "<" (Left
, Right
: Cursor
) return Boolean is
109 if Left
.Node
= 0 then
110 raise Constraint_Error
with "Left cursor of ""<"" equals No_Element";
113 if Right
.Node
= 0 then
114 raise Constraint_Error
with "Right cursor of ""<"" equals No_Element";
117 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
118 "Left cursor of ""<"" is bad");
120 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
121 "Right cursor of ""<"" is bad");
124 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
125 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
128 return LN
.Key
< RN
.Key
;
132 function "<" (Left
: Cursor
; Right
: Key_Type
) return Boolean is
134 if Left
.Node
= 0 then
135 raise Constraint_Error
with "Left cursor of ""<"" equals No_Element";
138 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
139 "Left cursor of ""<"" is bad");
142 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
145 return LN
.Key
< Right
;
149 function "<" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
151 if Right
.Node
= 0 then
152 raise Constraint_Error
with "Right cursor of ""<"" equals No_Element";
155 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
156 "Right cursor of ""<"" is bad");
159 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
162 return Left
< RN
.Key
;
170 function "=" (Left
, Right
: Map
) return Boolean is
171 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean;
172 pragma Inline
(Is_Equal_Node_Node
);
175 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
177 ------------------------
178 -- Is_Equal_Node_Node --
179 ------------------------
181 function Is_Equal_Node_Node
182 (L
, R
: Node_Type
) return Boolean is
184 if L
.Key
< R
.Key
then
187 elsif R
.Key
< L
.Key
then
191 return L
.Element
= R
.Element
;
193 end Is_Equal_Node_Node
;
195 -- Start of processing for "="
198 return Is_Equal
(Left
, Right
);
205 function ">" (Left
, Right
: Cursor
) return Boolean is
207 if Left
.Node
= 0 then
208 raise Constraint_Error
with "Left cursor of "">"" equals No_Element";
211 if Right
.Node
= 0 then
212 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
215 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
216 "Left cursor of "">"" is bad");
218 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
219 "Right cursor of "">"" is bad");
222 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
223 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
226 return RN
.Key
< LN
.Key
;
230 function ">" (Left
: Cursor
; Right
: Key_Type
) return Boolean is
232 if Left
.Node
= 0 then
233 raise Constraint_Error
with "Left cursor of "">"" equals No_Element";
236 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
237 "Left cursor of "">"" is bad");
240 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
242 return Right
< LN
.Key
;
246 function ">" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
248 if Right
.Node
= 0 then
249 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
252 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
253 "Right cursor of "">"" is bad");
256 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
259 return RN
.Key
< Left
;
267 procedure Adjust
(Control
: in out Reference_Control_Type
) is
269 if Control
.Container
/= null then
271 C
: Map
renames Control
.Container
.all;
272 B
: Natural renames C
.Busy
;
273 L
: Natural renames C
.Lock
;
285 procedure Assign
(Target
: in out Map
; Source
: Map
) is
286 procedure Append_Element
(Source_Node
: Count_Type
);
288 procedure Append_Elements
is
289 new Tree_Operations
.Generic_Iteration
(Append_Element
);
295 procedure Append_Element
(Source_Node
: Count_Type
) is
296 SN
: Node_Type
renames Source
.Nodes
(Source_Node
);
298 procedure Set_Element
(Node
: in out Node_Type
);
299 pragma Inline
(Set_Element
);
301 function New_Node
return Count_Type
;
302 pragma Inline
(New_Node
);
304 procedure Insert_Post
is
305 new Key_Ops
.Generic_Insert_Post
(New_Node
);
307 procedure Unconditional_Insert_Sans_Hint
is
308 new Key_Ops
.Generic_Unconditional_Insert
(Insert_Post
);
310 procedure Unconditional_Insert_Avec_Hint
is
311 new Key_Ops
.Generic_Unconditional_Insert_With_Hint
313 Unconditional_Insert_Sans_Hint
);
315 procedure Allocate
is
316 new Tree_Operations
.Generic_Allocate
(Set_Element
);
322 function New_Node
return Count_Type
is
326 Allocate
(Target
, Result
);
334 procedure Set_Element
(Node
: in out Node_Type
) is
337 Node
.Element
:= SN
.Element
;
340 Target_Node
: Count_Type
;
342 -- Start of processing for Append_Element
345 Unconditional_Insert_Avec_Hint
349 Node
=> Target_Node
);
352 -- Start of processing for Assign
355 if Target
'Address = Source
'Address then
359 if Target
.Capacity
< Source
.Length
then
361 with "Target capacity is less than Source length";
364 Tree_Operations
.Clear_Tree
(Target
);
365 Append_Elements
(Source
);
372 function Ceiling
(Container
: Map
; Key
: Key_Type
) return Cursor
is
373 Node
: constant Count_Type
:= Key_Ops
.Ceiling
(Container
, Key
);
380 return Cursor
'(Container'Unrestricted_Access, Node);
387 procedure Clear (Container : in out Map) is
389 Tree_Operations.Clear_Tree (Container);
396 function Color (Node : Node_Type) return Color_Type is
401 ------------------------
402 -- Constant_Reference --
403 ------------------------
405 function Constant_Reference
406 (Container : aliased Map;
407 Position : Cursor) return Constant_Reference_Type
410 if Position.Container = null then
411 raise Constraint_Error with
412 "Position cursor has no element";
415 if Position.Container /= Container'Unrestricted_Access then
416 raise Program_Error with
417 "Position cursor designates wrong map";
420 pragma Assert (Vet (Container, Position.Node),
421 "Position cursor in Constant_Reference is bad");
424 N : Node_Type renames Container.Nodes (Position.Node);
425 B : Natural renames Position.Container.Busy;
426 L : Natural renames Position.Container.Lock;
429 return R : constant Constant_Reference_Type :=
430 (Element => N.Element'Access,
431 Control => (Controlled with Container'Unrestricted_Access))
437 end Constant_Reference;
439 function Constant_Reference
440 (Container : aliased Map;
441 Key : Key_Type) return Constant_Reference_Type
443 Node : constant Count_Type := Key_Ops.Find (Container, Key);
447 raise Constraint_Error with "key not in map";
451 Cur : Cursor := Find (Container, Key);
452 pragma Unmodified (Cur);
454 N : Node_Type renames Container.Nodes (Node);
455 B : Natural renames Cur.Container.Busy;
456 L : Natural renames Cur.Container.Lock;
459 return R : constant Constant_Reference_Type :=
460 (Element => N.Element'Access,
461 Control => (Controlled with Container'Unrestricted_Access))
467 end Constant_Reference;
473 function Contains (Container : Map; Key : Key_Type) return Boolean is
475 return Find (Container, Key) /= No_Element;
482 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
489 elsif Capacity >= Source.Length then
493 raise Capacity_Error with "Capacity value too small";
496 return Target : Map (Capacity => C) do
497 Assign (Target => Target, Source => Source);
505 procedure Delete (Container : in out Map; Position : in out Cursor) is
507 if Position.Node = 0 then
508 raise Constraint_Error with
509 "Position cursor of Delete equals No_Element";
512 if Position.Container /= Container'Unrestricted_Access then
513 raise Program_Error with
514 "Position cursor of Delete designates wrong map";
517 pragma Assert (Vet (Container, Position.Node),
518 "Position cursor of Delete is bad");
520 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
521 Tree_Operations.Free (Container, Position.Node);
523 Position := No_Element;
526 procedure Delete (Container : in out Map; Key : Key_Type) is
527 X : constant Count_Type := Key_Ops.Find (Container, Key);
531 raise Constraint_Error with "key not in map";
534 Tree_Operations.Delete_Node_Sans_Free (Container, X);
535 Tree_Operations.Free (Container, X);
542 procedure Delete_First (Container : in out Map) is
543 X : constant Count_Type := Container.First;
547 Tree_Operations.Delete_Node_Sans_Free (Container, X);
548 Tree_Operations.Free (Container, X);
556 procedure Delete_Last (Container : in out Map) is
557 X : constant Count_Type := Container.Last;
561 Tree_Operations.Delete_Node_Sans_Free (Container, X);
562 Tree_Operations.Free (Container, X);
570 function Element (Position : Cursor) return Element_Type is
572 if Position.Node = 0 then
573 raise Constraint_Error with
574 "Position cursor of function Element equals No_Element";
577 pragma Assert (Vet (Position.Container.all, Position.Node),
578 "Position cursor of function Element is bad");
580 return Position.Container.Nodes (Position.Node).Element;
583 function Element (Container : Map; Key : Key_Type) return Element_Type is
584 Node : constant Count_Type := Key_Ops.Find (Container, Key);
587 raise Constraint_Error with "key not in map";
589 return Container.Nodes (Node).Element;
593 ---------------------
594 -- Equivalent_Keys --
595 ---------------------
597 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
612 procedure Exclude (Container : in out Map; Key : Key_Type) is
613 X : constant Count_Type := Key_Ops.Find (Container, Key);
617 Tree_Operations.Delete_Node_Sans_Free (Container, X);
618 Tree_Operations.Free (Container, X);
626 procedure Finalize (Object : in out Iterator) is
628 if Object.Container /= null then
630 B : Natural renames Object.Container.all.Busy;
637 procedure Finalize (Control : in out Reference_Control_Type) is
639 if Control.Container /= null then
641 C : Map renames Control.Container.all;
642 B : Natural renames C.Busy;
643 L : Natural renames C.Lock;
649 Control.Container := null;
657 function Find (Container : Map; Key : Key_Type) return Cursor is
658 Node : constant Count_Type := Key_Ops.Find (Container, Key);
663 return Cursor'(Container
'Unrestricted_Access, Node
);
671 function First
(Container
: Map
) return Cursor
is
673 if Container
.First
= 0 then
676 return Cursor
'(Container'Unrestricted_Access, Container.First);
680 function First (Object : Iterator) return Cursor is
682 -- The value of the iterator object's Node component influences the
683 -- behavior of the First (and Last) selector function.
685 -- When the Node component is 0, this means the iterator object was
686 -- constructed without a start expression, in which case the (forward)
687 -- iteration starts from the (logical) beginning of the entire sequence
688 -- of items (corresponding to Container.First, for a forward iterator).
690 -- Otherwise, this is iteration over a partial sequence of items. When
691 -- the Node component is positive, the iterator object was constructed
692 -- with a start expression, that specifies the position from which the
693 -- (forward) partial iteration begins.
695 if Object.Node = 0 then
696 return Bounded_Ordered_Maps.First (Object.Container.all);
698 return Cursor'(Object
.Container
, Object
.Node
);
706 function First_Element
(Container
: Map
) return Element_Type
is
708 if Container
.First
= 0 then
709 raise Constraint_Error
with "map is empty";
711 return Container
.Nodes
(Container
.First
).Element
;
719 function First_Key
(Container
: Map
) return Key_Type
is
721 if Container
.First
= 0 then
722 raise Constraint_Error
with "map is empty";
724 return Container
.Nodes
(Container
.First
).Key
;
732 function Floor
(Container
: Map
; Key
: Key_Type
) return Cursor
is
733 Node
: constant Count_Type
:= Key_Ops
.Floor
(Container
, Key
);
738 return Cursor
'(Container'Unrestricted_Access, Node);
746 function Has_Element (Position : Cursor) return Boolean is
748 return Position /= No_Element;
756 (Container : in out Map;
758 New_Item : Element_Type)
764 Insert (Container, Key, New_Item, Position, Inserted);
767 if Container.Lock > 0 then
768 raise Program_Error with
769 "attempt to tamper with elements (map is locked)";
773 N : Node_Type renames Container.Nodes (Position.Node);
776 N.Element := New_Item;
786 (Container : in out Map;
788 New_Item : Element_Type;
789 Position : out Cursor;
790 Inserted : out Boolean)
792 procedure Assign (Node : in out Node_Type);
793 pragma Inline (Assign);
795 function New_Node return Count_Type;
796 pragma Inline (New_Node);
798 procedure Insert_Post is
799 new Key_Ops.Generic_Insert_Post (New_Node);
801 procedure Insert_Sans_Hint is
802 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
804 procedure Allocate is
805 new Tree_Operations.Generic_Allocate (Assign);
811 procedure Assign (Node : in out Node_Type) is
814 Node.Element := New_Item;
821 function New_Node return Count_Type is
824 Allocate (Container, Result);
828 -- Start of processing for Insert
837 Position.Container := Container'Unrestricted_Access;
841 (Container : in out Map;
843 New_Item : Element_Type)
846 pragma Unreferenced (Position);
851 Insert (Container, Key, New_Item, Position, Inserted);
854 raise Constraint_Error with "key already in map";
859 (Container : in out Map;
861 Position : out Cursor;
862 Inserted : out Boolean)
864 procedure Assign (Node : in out Node_Type);
865 pragma Inline (Assign);
867 function New_Node return Count_Type;
868 pragma Inline (New_Node);
870 procedure Insert_Post is
871 new Key_Ops.Generic_Insert_Post (New_Node);
873 procedure Insert_Sans_Hint is
874 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
876 procedure Allocate is
877 new Tree_Operations.Generic_Allocate (Assign);
883 procedure Assign (Node : in out Node_Type) is
884 New_Item : Element_Type;
885 pragma Unmodified (New_Item);
886 -- Default-initialized element (ok to reference, see below)
891 -- There is no explicit element provided, but in an instance the element
892 -- type may be a scalar with a Default_Value aspect, or a composite type
893 -- with such a scalar component or with defaulted components, so insert
894 -- possibly initialized elements at the given position.
896 Node.Element := New_Item;
903 function New_Node return Count_Type is
906 Allocate (Container, Result);
910 -- Start of processing for Insert
919 Position.Container := Container'Unrestricted_Access;
926 function Is_Empty (Container : Map) return Boolean is
928 return Container.Length = 0;
931 -------------------------
932 -- Is_Greater_Key_Node --
933 -------------------------
935 function Is_Greater_Key_Node
937 Right : Node_Type) return Boolean
940 -- Left > Right same as Right < Left
942 return Right.Key < Left;
943 end Is_Greater_Key_Node;
945 ----------------------
946 -- Is_Less_Key_Node --
947 ----------------------
949 function Is_Less_Key_Node
951 Right : Node_Type) return Boolean
954 return Left < Right.Key;
955 end Is_Less_Key_Node;
963 Process : not null access procedure (Position : Cursor))
965 procedure Process_Node (Node : Count_Type);
966 pragma Inline (Process_Node);
968 procedure Local_Iterate is
969 new Tree_Operations.Generic_Iteration (Process_Node);
975 procedure Process_Node (Node : Count_Type) is
977 Process (Cursor'(Container
'Unrestricted_Access, Node
));
980 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
982 -- Start of processing for Iterate
988 Local_Iterate
(Container
);
999 (Container
: Map
) return Map_Iterator_Interfaces
.Reversible_Iterator
'Class
1001 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
1004 -- The value of the Node component influences the behavior of the First
1005 -- and Last selector functions of the iterator object. When the Node
1006 -- component is 0 (as is the case here), this means the iterator object
1007 -- was constructed without a start expression. This is a complete
1008 -- iterator, meaning that the iteration starts from the (logical)
1009 -- beginning of the sequence of items.
1011 -- Note: For a forward iterator, Container.First is the beginning, and
1012 -- for a reverse iterator, Container.Last is the beginning.
1014 return It
: constant Iterator
:=
1015 (Limited_Controlled
with
1016 Container
=> Container
'Unrestricted_Access,
1026 return Map_Iterator_Interfaces
.Reversible_Iterator
'Class
1028 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
1031 -- Iterator was defined to behave the same as for a complete iterator,
1032 -- and iterate over the entire sequence of items. However, those
1033 -- semantics were unintuitive and arguably error-prone (it is too easy
1034 -- to accidentally create an endless loop), and so they were changed,
1035 -- per the ARG meeting in Denver on 2011/11. However, there was no
1036 -- consensus about what positive meaning this corner case should have,
1037 -- and so it was decided to simply raise an exception. This does imply,
1038 -- however, that it is not possible to use a partial iterator to specify
1039 -- an empty sequence of items.
1041 if Start
= No_Element
then
1042 raise Constraint_Error
with
1043 "Start position for iterator equals No_Element";
1046 if Start
.Container
/= Container
'Unrestricted_Access then
1047 raise Program_Error
with
1048 "Start cursor of Iterate designates wrong map";
1051 pragma Assert
(Vet
(Container
, Start
.Node
),
1052 "Start cursor of Iterate is bad");
1054 -- The value of the Node component influences the behavior of the First
1055 -- and Last selector functions of the iterator object. When the Node
1056 -- component is positive (as is the case here), it means that this
1057 -- is a partial iteration, over a subset of the complete sequence of
1058 -- items. The iterator object was constructed with a start expression,
1059 -- indicating the position from which the iteration begins. (Note that
1060 -- the start position has the same value irrespective of whether this
1061 -- is a forward or reverse iteration.)
1063 return It
: constant Iterator
:=
1064 (Limited_Controlled
with
1065 Container
=> Container
'Unrestricted_Access,
1076 function Key
(Position
: Cursor
) return Key_Type
is
1078 if Position
.Node
= 0 then
1079 raise Constraint_Error
with
1080 "Position cursor of function Key equals No_Element";
1083 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1084 "Position cursor of function Key is bad");
1086 return Position
.Container
.Nodes
(Position
.Node
).Key
;
1093 function Last
(Container
: Map
) return Cursor
is
1095 if Container
.Last
= 0 then
1098 return Cursor
'(Container'Unrestricted_Access, Container.Last);
1102 function Last (Object : Iterator) return Cursor is
1104 -- The value of the iterator object's Node component influences the
1105 -- behavior of the Last (and First) selector function.
1107 -- When the Node component is 0, this means the iterator object was
1108 -- constructed without a start expression, in which case the (reverse)
1109 -- iteration starts from the (logical) beginning of the entire sequence
1110 -- (corresponding to Container.Last, for a reverse iterator).
1112 -- Otherwise, this is iteration over a partial sequence of items. When
1113 -- the Node component is positive, the iterator object was constructed
1114 -- with a start expression, that specifies the position from which the
1115 -- (reverse) partial iteration begins.
1117 if Object.Node = 0 then
1118 return Bounded_Ordered_Maps.Last (Object.Container.all);
1120 return Cursor'(Object
.Container
, Object
.Node
);
1128 function Last_Element
(Container
: Map
) return Element_Type
is
1130 if Container
.Last
= 0 then
1131 raise Constraint_Error
with "map is empty";
1133 return Container
.Nodes
(Container
.Last
).Element
;
1141 function Last_Key
(Container
: Map
) return Key_Type
is
1143 if Container
.Last
= 0 then
1144 raise Constraint_Error
with "map is empty";
1146 return Container
.Nodes
(Container
.Last
).Key
;
1154 function Left
(Node
: Node_Type
) return Count_Type
is
1163 function Length
(Container
: Map
) return Count_Type
is
1165 return Container
.Length
;
1172 procedure Move
(Target
: in out Map
; Source
: in out Map
) is
1174 if Target
'Address = Source
'Address then
1178 if Source
.Busy
> 0 then
1179 raise Program_Error
with
1180 "attempt to tamper with cursors (container is busy)";
1183 Target
.Assign
(Source
);
1191 procedure Next
(Position
: in out Cursor
) is
1193 Position
:= Next
(Position
);
1196 function Next
(Position
: Cursor
) return Cursor
is
1198 if Position
= No_Element
then
1202 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1203 "Position cursor of Next is bad");
1206 M
: Map
renames Position
.Container
.all;
1208 Node
: constant Count_Type
:=
1209 Tree_Operations
.Next
(M
, Position
.Node
);
1216 return Cursor
'(Position.Container, Node);
1222 Position : Cursor) return Cursor
1225 if Position.Container = null then
1229 if Position.Container /= Object.Container then
1230 raise Program_Error with
1231 "Position cursor of Next designates wrong map";
1234 return Next (Position);
1241 function Parent (Node : Node_Type) return Count_Type is
1250 procedure Previous (Position : in out Cursor) is
1252 Position := Previous (Position);
1255 function Previous (Position : Cursor) return Cursor is
1257 if Position = No_Element then
1261 pragma Assert (Vet (Position.Container.all, Position.Node),
1262 "Position cursor of Previous is bad");
1265 M : Map renames Position.Container.all;
1267 Node : constant Count_Type :=
1268 Tree_Operations.Previous (M, Position.Node);
1275 return Cursor'(Position
.Container
, Node
);
1281 Position
: Cursor
) return Cursor
1284 if Position
.Container
= null then
1288 if Position
.Container
/= Object
.Container
then
1289 raise Program_Error
with
1290 "Position cursor of Previous designates wrong map";
1293 return Previous
(Position
);
1300 procedure Query_Element
1302 Process
: not null access procedure (Key
: Key_Type
;
1303 Element
: Element_Type
))
1306 if Position
.Node
= 0 then
1307 raise Constraint_Error
with
1308 "Position cursor of Query_Element equals No_Element";
1311 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1312 "Position cursor of Query_Element is bad");
1315 M
: Map
renames Position
.Container
.all;
1316 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
1318 B
: Natural renames M
.Busy
;
1319 L
: Natural renames M
.Lock
;
1326 Process
(N
.Key
, N
.Element
);
1344 (Stream
: not null access Root_Stream_Type
'Class;
1345 Container
: out Map
)
1347 procedure Read_Element
(Node
: in out Node_Type
);
1348 pragma Inline
(Read_Element
);
1350 procedure Allocate
is
1351 new Tree_Operations
.Generic_Allocate
(Read_Element
);
1353 procedure Read_Elements
is
1354 new Tree_Operations
.Generic_Read
(Allocate
);
1360 procedure Read_Element
(Node
: in out Node_Type
) is
1362 Key_Type
'Read (Stream
, Node
.Key
);
1363 Element_Type
'Read (Stream
, Node
.Element
);
1366 -- Start of processing for Read
1369 Read_Elements
(Stream
, Container
);
1373 (Stream
: not null access Root_Stream_Type
'Class;
1377 raise Program_Error
with "attempt to stream map cursor";
1381 (Stream
: not null access Root_Stream_Type
'Class;
1382 Item
: out Reference_Type
)
1385 raise Program_Error
with "attempt to stream reference";
1389 (Stream
: not null access Root_Stream_Type
'Class;
1390 Item
: out Constant_Reference_Type
)
1393 raise Program_Error
with "attempt to stream reference";
1401 (Container
: aliased in out Map
;
1402 Position
: Cursor
) return Reference_Type
1405 if Position
.Container
= null then
1406 raise Constraint_Error
with
1407 "Position cursor has no element";
1410 if Position
.Container
/= Container
'Unrestricted_Access then
1411 raise Program_Error
with
1412 "Position cursor designates wrong map";
1415 pragma Assert
(Vet
(Container
, Position
.Node
),
1416 "Position cursor in function Reference is bad");
1419 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1420 B
: Natural renames Container
.Busy
;
1421 L
: Natural renames Container
.Lock
;
1423 return R
: constant Reference_Type
:=
1424 (Element
=> N
.Element
'Access,
1425 Control
=> (Controlled
with Container
'Unrestricted_Access))
1434 (Container
: aliased in out Map
;
1435 Key
: Key_Type
) return Reference_Type
1437 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1441 raise Constraint_Error
with "key not in map";
1445 N
: Node_Type
renames Container
.Nodes
(Node
);
1446 B
: Natural renames Container
.Busy
;
1447 L
: Natural renames Container
.Lock
;
1449 return R
: constant Reference_Type
:=
1450 (Element
=> N
.Element
'Access,
1451 Control
=> (Controlled
with Container
'Unrestricted_Access))
1464 (Container
: in out Map
;
1466 New_Item
: Element_Type
)
1468 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1472 raise Constraint_Error
with "key not in map";
1475 if Container
.Lock
> 0 then
1476 raise Program_Error
with
1477 "attempt to tamper with elements (map is locked)";
1481 N
: Node_Type
renames Container
.Nodes
(Node
);
1485 N
.Element
:= New_Item
;
1489 ---------------------
1490 -- Replace_Element --
1491 ---------------------
1493 procedure Replace_Element
1494 (Container
: in out Map
;
1496 New_Item
: Element_Type
)
1499 if Position
.Node
= 0 then
1500 raise Constraint_Error
with
1501 "Position cursor of Replace_Element equals No_Element";
1504 if Position
.Container
/= Container
'Unrestricted_Access then
1505 raise Program_Error
with
1506 "Position cursor of Replace_Element designates wrong map";
1509 if Container
.Lock
> 0 then
1510 raise Program_Error
with
1511 "attempt to tamper with elements (map is locked)";
1514 pragma Assert
(Vet
(Container
, Position
.Node
),
1515 "Position cursor of Replace_Element is bad");
1517 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1518 end Replace_Element
;
1520 ---------------------
1521 -- Reverse_Iterate --
1522 ---------------------
1524 procedure Reverse_Iterate
1526 Process
: not null access procedure (Position
: Cursor
))
1528 procedure Process_Node
(Node
: Count_Type
);
1529 pragma Inline
(Process_Node
);
1531 procedure Local_Reverse_Iterate
is
1532 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1538 procedure Process_Node
(Node
: Count_Type
) is
1540 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1543 B : Natural renames Container'Unrestricted_Access.all.Busy;
1545 -- Start of processing for Reverse_Iterate
1551 Local_Reverse_Iterate (Container);
1559 end Reverse_Iterate;
1565 function Right (Node : Node_Type) return Count_Type is
1575 (Node : in out Node_Type;
1579 Node.Color := Color;
1586 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1595 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1597 Node.Parent := Parent;
1604 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1606 Node.Right := Right;
1609 --------------------
1610 -- Update_Element --
1611 --------------------
1613 procedure Update_Element
1614 (Container : in out Map;
1616 Process : not null access procedure (Key : Key_Type;
1617 Element : in out Element_Type))
1620 if Position.Node = 0 then
1621 raise Constraint_Error with
1622 "Position cursor of Update_Element equals No_Element";
1625 if Position.Container /= Container'Unrestricted_Access then
1626 raise Program_Error with
1627 "Position cursor of Update_Element designates wrong map";
1630 pragma Assert (Vet (Container, Position.Node),
1631 "Position cursor of Update_Element is bad");
1634 N : Node_Type renames Container.Nodes (Position.Node);
1635 B : Natural renames Container.Busy;
1636 L : Natural renames Container.Lock;
1643 Process (N.Key, N.Element);
1662 (Stream : not null access Root_Stream_Type'Class;
1665 procedure Write_Node
1666 (Stream : not null access Root_Stream_Type'Class;
1668 pragma Inline (Write_Node);
1670 procedure Write_Nodes is
1671 new Tree_Operations.Generic_Write (Write_Node);
1677 procedure Write_Node
1678 (Stream : not null access Root_Stream_Type'Class;
1682 Key_Type'Write (Stream, Node.Key);
1683 Element_Type'Write (Stream, Node.Element);
1686 -- Start of processing for Write
1689 Write_Nodes (Stream, Container);
1693 (Stream : not null access Root_Stream_Type'Class;
1697 raise Program_Error with "attempt to stream map cursor";
1701 (Stream : not null access Root_Stream_Type'Class;
1702 Item : Reference_Type)
1705 raise Program_Error with "attempt to stream reference";
1709 (Stream : not null access Root_Stream_Type'Class;
1710 Item : Constant_Reference_Type)
1713 raise Program_Error with "attempt to stream reference";
1716 end Ada.Containers.Bounded_Ordered_Maps;