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 pragma Annotate
(CodePeer
, Skip_Analysis
);
44 -----------------------------
45 -- Node Access Subprograms --
46 -----------------------------
48 -- These subprograms provide a functional interface to access fields
49 -- of a node, and a procedural interface for modifying these values.
51 function Color
(Node
: Node_Type
) return Color_Type
;
52 pragma Inline
(Color
);
54 function Left
(Node
: Node_Type
) return Count_Type
;
57 function Parent
(Node
: Node_Type
) return Count_Type
;
58 pragma Inline
(Parent
);
60 function Right
(Node
: Node_Type
) return Count_Type
;
61 pragma Inline
(Right
);
63 procedure Set_Parent
(Node
: in out Node_Type
; Parent
: Count_Type
);
64 pragma Inline
(Set_Parent
);
66 procedure Set_Left
(Node
: in out Node_Type
; Left
: Count_Type
);
67 pragma Inline
(Set_Left
);
69 procedure Set_Right
(Node
: in out Node_Type
; Right
: Count_Type
);
70 pragma Inline
(Set_Right
);
72 procedure Set_Color
(Node
: in out Node_Type
; Color
: Color_Type
);
73 pragma Inline
(Set_Color
);
75 -----------------------
76 -- Local Subprograms --
77 -----------------------
79 function Is_Greater_Key_Node
81 Right
: Node_Type
) return Boolean;
82 pragma Inline
(Is_Greater_Key_Node
);
84 function Is_Less_Key_Node
86 Right
: Node_Type
) return Boolean;
87 pragma Inline
(Is_Less_Key_Node
);
89 --------------------------
90 -- Local Instantiations --
91 --------------------------
93 package Tree_Operations
is
94 new Red_Black_Trees
.Generic_Bounded_Operations
(Tree_Types
);
99 new Red_Black_Trees
.Generic_Bounded_Keys
100 (Tree_Operations
=> Tree_Operations
,
101 Key_Type
=> Key_Type
,
102 Is_Less_Key_Node
=> Is_Less_Key_Node
,
103 Is_Greater_Key_Node
=> Is_Greater_Key_Node
);
109 function "<" (Left
, Right
: Cursor
) return Boolean is
111 if Left
.Node
= 0 then
112 raise Constraint_Error
with "Left cursor of ""<"" equals No_Element";
115 if Right
.Node
= 0 then
116 raise Constraint_Error
with "Right cursor of ""<"" equals No_Element";
119 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
120 "Left cursor of ""<"" is bad");
122 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
123 "Right cursor of ""<"" is bad");
126 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
127 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
130 return LN
.Key
< RN
.Key
;
134 function "<" (Left
: Cursor
; Right
: Key_Type
) return Boolean is
136 if Left
.Node
= 0 then
137 raise Constraint_Error
with "Left cursor of ""<"" equals No_Element";
140 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
141 "Left cursor of ""<"" is bad");
144 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
147 return LN
.Key
< Right
;
151 function "<" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
153 if Right
.Node
= 0 then
154 raise Constraint_Error
with "Right cursor of ""<"" equals No_Element";
157 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
158 "Right cursor of ""<"" is bad");
161 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
164 return Left
< RN
.Key
;
172 function "=" (Left
, Right
: Map
) return Boolean is
173 function Is_Equal_Node_Node
(L
, R
: Node_Type
) return Boolean;
174 pragma Inline
(Is_Equal_Node_Node
);
177 new Tree_Operations
.Generic_Equal
(Is_Equal_Node_Node
);
179 ------------------------
180 -- Is_Equal_Node_Node --
181 ------------------------
183 function Is_Equal_Node_Node
184 (L
, R
: Node_Type
) return Boolean is
186 if L
.Key
< R
.Key
then
189 elsif R
.Key
< L
.Key
then
193 return L
.Element
= R
.Element
;
195 end Is_Equal_Node_Node
;
197 -- Start of processing for "="
200 return Is_Equal
(Left
, Right
);
207 function ">" (Left
, Right
: Cursor
) return Boolean is
209 if Left
.Node
= 0 then
210 raise Constraint_Error
with "Left cursor of "">"" equals No_Element";
213 if Right
.Node
= 0 then
214 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
217 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
218 "Left cursor of "">"" is bad");
220 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
221 "Right cursor of "">"" is bad");
224 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
225 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
228 return RN
.Key
< LN
.Key
;
232 function ">" (Left
: Cursor
; Right
: Key_Type
) return Boolean is
234 if Left
.Node
= 0 then
235 raise Constraint_Error
with "Left cursor of "">"" equals No_Element";
238 pragma Assert
(Vet
(Left
.Container
.all, Left
.Node
),
239 "Left cursor of "">"" is bad");
242 LN
: Node_Type
renames Left
.Container
.Nodes
(Left
.Node
);
244 return Right
< LN
.Key
;
248 function ">" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
250 if Right
.Node
= 0 then
251 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
254 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
255 "Right cursor of "">"" is bad");
258 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
261 return RN
.Key
< Left
;
269 procedure Adjust
(Control
: in out Reference_Control_Type
) is
271 if Control
.Container
/= null then
273 C
: Map
renames Control
.Container
.all;
274 B
: Natural renames C
.Busy
;
275 L
: Natural renames C
.Lock
;
287 procedure Assign
(Target
: in out Map
; Source
: Map
) is
288 procedure Append_Element
(Source_Node
: Count_Type
);
290 procedure Append_Elements
is
291 new Tree_Operations
.Generic_Iteration
(Append_Element
);
297 procedure Append_Element
(Source_Node
: Count_Type
) is
298 SN
: Node_Type
renames Source
.Nodes
(Source_Node
);
300 procedure Set_Element
(Node
: in out Node_Type
);
301 pragma Inline
(Set_Element
);
303 function New_Node
return Count_Type
;
304 pragma Inline
(New_Node
);
306 procedure Insert_Post
is
307 new Key_Ops
.Generic_Insert_Post
(New_Node
);
309 procedure Unconditional_Insert_Sans_Hint
is
310 new Key_Ops
.Generic_Unconditional_Insert
(Insert_Post
);
312 procedure Unconditional_Insert_Avec_Hint
is
313 new Key_Ops
.Generic_Unconditional_Insert_With_Hint
315 Unconditional_Insert_Sans_Hint
);
317 procedure Allocate
is
318 new Tree_Operations
.Generic_Allocate
(Set_Element
);
324 function New_Node
return Count_Type
is
328 Allocate
(Target
, Result
);
336 procedure Set_Element
(Node
: in out Node_Type
) is
339 Node
.Element
:= SN
.Element
;
342 Target_Node
: Count_Type
;
344 -- Start of processing for Append_Element
347 Unconditional_Insert_Avec_Hint
351 Node
=> Target_Node
);
354 -- Start of processing for Assign
357 if Target
'Address = Source
'Address then
361 if Target
.Capacity
< Source
.Length
then
363 with "Target capacity is less than Source length";
366 Tree_Operations
.Clear_Tree
(Target
);
367 Append_Elements
(Source
);
374 function Ceiling
(Container
: Map
; Key
: Key_Type
) return Cursor
is
375 Node
: constant Count_Type
:= Key_Ops
.Ceiling
(Container
, Key
);
382 return Cursor
'(Container'Unrestricted_Access, Node);
389 procedure Clear (Container : in out Map) is
391 Tree_Operations.Clear_Tree (Container);
398 function Color (Node : Node_Type) return Color_Type is
403 ------------------------
404 -- Constant_Reference --
405 ------------------------
407 function Constant_Reference
408 (Container : aliased Map;
409 Position : Cursor) return Constant_Reference_Type
412 if Position.Container = null then
413 raise Constraint_Error with
414 "Position cursor has no element";
417 if Position.Container /= Container'Unrestricted_Access then
418 raise Program_Error with
419 "Position cursor designates wrong map";
422 pragma Assert (Vet (Container, Position.Node),
423 "Position cursor in Constant_Reference is bad");
426 N : Node_Type renames Container.Nodes (Position.Node);
427 B : Natural renames Position.Container.Busy;
428 L : Natural renames Position.Container.Lock;
431 return R : constant Constant_Reference_Type :=
432 (Element => N.Element'Access,
433 Control => (Controlled with Container'Unrestricted_Access))
439 end Constant_Reference;
441 function Constant_Reference
442 (Container : aliased Map;
443 Key : Key_Type) return Constant_Reference_Type
445 Node : constant Count_Type := Key_Ops.Find (Container, Key);
449 raise Constraint_Error with "key not in map";
453 Cur : Cursor := Find (Container, Key);
454 pragma Unmodified (Cur);
456 N : Node_Type renames Container.Nodes (Node);
457 B : Natural renames Cur.Container.Busy;
458 L : Natural renames Cur.Container.Lock;
461 return R : constant Constant_Reference_Type :=
462 (Element => N.Element'Access,
463 Control => (Controlled with Container'Unrestricted_Access))
469 end Constant_Reference;
475 function Contains (Container : Map; Key : Key_Type) return Boolean is
477 return Find (Container, Key) /= No_Element;
484 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
491 elsif Capacity >= Source.Length then
495 raise Capacity_Error with "Capacity value too small";
498 return Target : Map (Capacity => C) do
499 Assign (Target => Target, Source => Source);
507 procedure Delete (Container : in out Map; Position : in out Cursor) is
509 if Position.Node = 0 then
510 raise Constraint_Error with
511 "Position cursor of Delete equals No_Element";
514 if Position.Container /= Container'Unrestricted_Access then
515 raise Program_Error with
516 "Position cursor of Delete designates wrong map";
519 pragma Assert (Vet (Container, Position.Node),
520 "Position cursor of Delete is bad");
522 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
523 Tree_Operations.Free (Container, Position.Node);
525 Position := No_Element;
528 procedure Delete (Container : in out Map; Key : Key_Type) is
529 X : constant Count_Type := Key_Ops.Find (Container, Key);
533 raise Constraint_Error with "key not in map";
536 Tree_Operations.Delete_Node_Sans_Free (Container, X);
537 Tree_Operations.Free (Container, X);
544 procedure Delete_First (Container : in out Map) is
545 X : constant Count_Type := Container.First;
549 Tree_Operations.Delete_Node_Sans_Free (Container, X);
550 Tree_Operations.Free (Container, X);
558 procedure Delete_Last (Container : in out Map) is
559 X : constant Count_Type := Container.Last;
563 Tree_Operations.Delete_Node_Sans_Free (Container, X);
564 Tree_Operations.Free (Container, X);
572 function Element (Position : Cursor) return Element_Type is
574 if Position.Node = 0 then
575 raise Constraint_Error with
576 "Position cursor of function Element equals No_Element";
579 pragma Assert (Vet (Position.Container.all, Position.Node),
580 "Position cursor of function Element is bad");
582 return Position.Container.Nodes (Position.Node).Element;
585 function Element (Container : Map; Key : Key_Type) return Element_Type is
586 Node : constant Count_Type := Key_Ops.Find (Container, Key);
589 raise Constraint_Error with "key not in map";
591 return Container.Nodes (Node).Element;
595 ---------------------
596 -- Equivalent_Keys --
597 ---------------------
599 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
614 procedure Exclude (Container : in out Map; Key : Key_Type) is
615 X : constant Count_Type := Key_Ops.Find (Container, Key);
619 Tree_Operations.Delete_Node_Sans_Free (Container, X);
620 Tree_Operations.Free (Container, X);
628 procedure Finalize (Object : in out Iterator) is
630 if Object.Container /= null then
632 B : Natural renames Object.Container.all.Busy;
639 procedure Finalize (Control : in out Reference_Control_Type) is
641 if Control.Container /= null then
643 C : Map renames Control.Container.all;
644 B : Natural renames C.Busy;
645 L : Natural renames C.Lock;
651 Control.Container := null;
659 function Find (Container : Map; Key : Key_Type) return Cursor is
660 Node : constant Count_Type := Key_Ops.Find (Container, Key);
665 return Cursor'(Container
'Unrestricted_Access, Node
);
673 function First
(Container
: Map
) return Cursor
is
675 if Container
.First
= 0 then
678 return Cursor
'(Container'Unrestricted_Access, Container.First);
682 function First (Object : Iterator) return Cursor is
684 -- The value of the iterator object's Node component influences the
685 -- behavior of the First (and Last) selector function.
687 -- When the Node component is 0, this means the iterator object was
688 -- constructed without a start expression, in which case the (forward)
689 -- iteration starts from the (logical) beginning of the entire sequence
690 -- of items (corresponding to Container.First, for a forward iterator).
692 -- Otherwise, this is iteration over a partial sequence of items. When
693 -- the Node component is positive, the iterator object was constructed
694 -- with a start expression, that specifies the position from which the
695 -- (forward) partial iteration begins.
697 if Object.Node = 0 then
698 return Bounded_Ordered_Maps.First (Object.Container.all);
700 return Cursor'(Object
.Container
, Object
.Node
);
708 function First_Element
(Container
: Map
) return Element_Type
is
710 if Container
.First
= 0 then
711 raise Constraint_Error
with "map is empty";
713 return Container
.Nodes
(Container
.First
).Element
;
721 function First_Key
(Container
: Map
) return Key_Type
is
723 if Container
.First
= 0 then
724 raise Constraint_Error
with "map is empty";
726 return Container
.Nodes
(Container
.First
).Key
;
734 function Floor
(Container
: Map
; Key
: Key_Type
) return Cursor
is
735 Node
: constant Count_Type
:= Key_Ops
.Floor
(Container
, Key
);
740 return Cursor
'(Container'Unrestricted_Access, Node);
748 function Has_Element (Position : Cursor) return Boolean is
750 return Position /= No_Element;
758 (Container : in out Map;
760 New_Item : Element_Type)
766 Insert (Container, Key, New_Item, Position, Inserted);
769 if Container.Lock > 0 then
770 raise Program_Error with
771 "attempt to tamper with elements (map is locked)";
775 N : Node_Type renames Container.Nodes (Position.Node);
778 N.Element := New_Item;
788 (Container : in out Map;
790 New_Item : Element_Type;
791 Position : out Cursor;
792 Inserted : out Boolean)
794 procedure Assign (Node : in out Node_Type);
795 pragma Inline (Assign);
797 function New_Node return Count_Type;
798 pragma Inline (New_Node);
800 procedure Insert_Post is
801 new Key_Ops.Generic_Insert_Post (New_Node);
803 procedure Insert_Sans_Hint is
804 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
806 procedure Allocate is
807 new Tree_Operations.Generic_Allocate (Assign);
813 procedure Assign (Node : in out Node_Type) is
816 Node.Element := New_Item;
823 function New_Node return Count_Type is
826 Allocate (Container, Result);
830 -- Start of processing for Insert
839 Position.Container := Container'Unrestricted_Access;
843 (Container : in out Map;
845 New_Item : Element_Type)
848 pragma Unreferenced (Position);
853 Insert (Container, Key, New_Item, Position, Inserted);
856 raise Constraint_Error with "key already in map";
861 (Container : in out Map;
863 Position : out Cursor;
864 Inserted : out Boolean)
866 procedure Assign (Node : in out Node_Type);
867 pragma Inline (Assign);
869 function New_Node return Count_Type;
870 pragma Inline (New_Node);
872 procedure Insert_Post is
873 new Key_Ops.Generic_Insert_Post (New_Node);
875 procedure Insert_Sans_Hint is
876 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
878 procedure Allocate is
879 new Tree_Operations.Generic_Allocate (Assign);
885 procedure Assign (Node : in out Node_Type) is
886 New_Item : Element_Type;
887 pragma Unmodified (New_Item);
888 -- Default-initialized element (ok to reference, see below)
893 -- There is no explicit element provided, but in an instance the element
894 -- type may be a scalar with a Default_Value aspect, or a composite type
895 -- with such a scalar component or with defaulted components, so insert
896 -- possibly initialized elements at the given position.
898 Node.Element := New_Item;
905 function New_Node return Count_Type is
908 Allocate (Container, Result);
912 -- Start of processing for Insert
921 Position.Container := Container'Unrestricted_Access;
928 function Is_Empty (Container : Map) return Boolean is
930 return Container.Length = 0;
933 -------------------------
934 -- Is_Greater_Key_Node --
935 -------------------------
937 function Is_Greater_Key_Node
939 Right : Node_Type) return Boolean
942 -- Left > Right same as Right < Left
944 return Right.Key < Left;
945 end Is_Greater_Key_Node;
947 ----------------------
948 -- Is_Less_Key_Node --
949 ----------------------
951 function Is_Less_Key_Node
953 Right : Node_Type) return Boolean
956 return Left < Right.Key;
957 end Is_Less_Key_Node;
965 Process : not null access procedure (Position : Cursor))
967 procedure Process_Node (Node : Count_Type);
968 pragma Inline (Process_Node);
970 procedure Local_Iterate is
971 new Tree_Operations.Generic_Iteration (Process_Node);
977 procedure Process_Node (Node : Count_Type) is
979 Process (Cursor'(Container
'Unrestricted_Access, Node
));
982 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
984 -- Start of processing for Iterate
990 Local_Iterate
(Container
);
1001 (Container
: Map
) return Map_Iterator_Interfaces
.Reversible_Iterator
'Class
1003 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
1006 -- The value of the Node component influences the behavior of the First
1007 -- and Last selector functions of the iterator object. When the Node
1008 -- component is 0 (as is the case here), this means the iterator object
1009 -- was constructed without a start expression. This is a complete
1010 -- iterator, meaning that the iteration starts from the (logical)
1011 -- beginning of the sequence of items.
1013 -- Note: For a forward iterator, Container.First is the beginning, and
1014 -- for a reverse iterator, Container.Last is the beginning.
1016 return It
: constant Iterator
:=
1017 (Limited_Controlled
with
1018 Container
=> Container
'Unrestricted_Access,
1028 return Map_Iterator_Interfaces
.Reversible_Iterator
'Class
1030 B
: Natural renames Container
'Unrestricted_Access.all.Busy
;
1033 -- Iterator was defined to behave the same as for a complete iterator,
1034 -- and iterate over the entire sequence of items. However, those
1035 -- semantics were unintuitive and arguably error-prone (it is too easy
1036 -- to accidentally create an endless loop), and so they were changed,
1037 -- per the ARG meeting in Denver on 2011/11. However, there was no
1038 -- consensus about what positive meaning this corner case should have,
1039 -- and so it was decided to simply raise an exception. This does imply,
1040 -- however, that it is not possible to use a partial iterator to specify
1041 -- an empty sequence of items.
1043 if Start
= No_Element
then
1044 raise Constraint_Error
with
1045 "Start position for iterator equals No_Element";
1048 if Start
.Container
/= Container
'Unrestricted_Access then
1049 raise Program_Error
with
1050 "Start cursor of Iterate designates wrong map";
1053 pragma Assert
(Vet
(Container
, Start
.Node
),
1054 "Start cursor of Iterate is bad");
1056 -- The value of the Node component influences the behavior of the First
1057 -- and Last selector functions of the iterator object. When the Node
1058 -- component is positive (as is the case here), it means that this
1059 -- is a partial iteration, over a subset of the complete sequence of
1060 -- items. The iterator object was constructed with a start expression,
1061 -- indicating the position from which the iteration begins. (Note that
1062 -- the start position has the same value irrespective of whether this
1063 -- is a forward or reverse iteration.)
1065 return It
: constant Iterator
:=
1066 (Limited_Controlled
with
1067 Container
=> Container
'Unrestricted_Access,
1078 function Key
(Position
: Cursor
) return Key_Type
is
1080 if Position
.Node
= 0 then
1081 raise Constraint_Error
with
1082 "Position cursor of function Key equals No_Element";
1085 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1086 "Position cursor of function Key is bad");
1088 return Position
.Container
.Nodes
(Position
.Node
).Key
;
1095 function Last
(Container
: Map
) return Cursor
is
1097 if Container
.Last
= 0 then
1100 return Cursor
'(Container'Unrestricted_Access, Container.Last);
1104 function Last (Object : Iterator) return Cursor is
1106 -- The value of the iterator object's Node component influences the
1107 -- behavior of the Last (and First) selector function.
1109 -- When the Node component is 0, this means the iterator object was
1110 -- constructed without a start expression, in which case the (reverse)
1111 -- iteration starts from the (logical) beginning of the entire sequence
1112 -- (corresponding to Container.Last, for a reverse iterator).
1114 -- Otherwise, this is iteration over a partial sequence of items. When
1115 -- the Node component is positive, the iterator object was constructed
1116 -- with a start expression, that specifies the position from which the
1117 -- (reverse) partial iteration begins.
1119 if Object.Node = 0 then
1120 return Bounded_Ordered_Maps.Last (Object.Container.all);
1122 return Cursor'(Object
.Container
, Object
.Node
);
1130 function Last_Element
(Container
: Map
) return Element_Type
is
1132 if Container
.Last
= 0 then
1133 raise Constraint_Error
with "map is empty";
1135 return Container
.Nodes
(Container
.Last
).Element
;
1143 function Last_Key
(Container
: Map
) return Key_Type
is
1145 if Container
.Last
= 0 then
1146 raise Constraint_Error
with "map is empty";
1148 return Container
.Nodes
(Container
.Last
).Key
;
1156 function Left
(Node
: Node_Type
) return Count_Type
is
1165 function Length
(Container
: Map
) return Count_Type
is
1167 return Container
.Length
;
1174 procedure Move
(Target
: in out Map
; Source
: in out Map
) is
1176 if Target
'Address = Source
'Address then
1180 if Source
.Busy
> 0 then
1181 raise Program_Error
with
1182 "attempt to tamper with cursors (container is busy)";
1185 Target
.Assign
(Source
);
1193 procedure Next
(Position
: in out Cursor
) is
1195 Position
:= Next
(Position
);
1198 function Next
(Position
: Cursor
) return Cursor
is
1200 if Position
= No_Element
then
1204 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1205 "Position cursor of Next is bad");
1208 M
: Map
renames Position
.Container
.all;
1210 Node
: constant Count_Type
:=
1211 Tree_Operations
.Next
(M
, Position
.Node
);
1218 return Cursor
'(Position.Container, Node);
1224 Position : Cursor) return Cursor
1227 if Position.Container = null then
1231 if Position.Container /= Object.Container then
1232 raise Program_Error with
1233 "Position cursor of Next designates wrong map";
1236 return Next (Position);
1243 function Parent (Node : Node_Type) return Count_Type is
1252 procedure Previous (Position : in out Cursor) is
1254 Position := Previous (Position);
1257 function Previous (Position : Cursor) return Cursor is
1259 if Position = No_Element then
1263 pragma Assert (Vet (Position.Container.all, Position.Node),
1264 "Position cursor of Previous is bad");
1267 M : Map renames Position.Container.all;
1269 Node : constant Count_Type :=
1270 Tree_Operations.Previous (M, Position.Node);
1277 return Cursor'(Position
.Container
, Node
);
1283 Position
: Cursor
) return Cursor
1286 if Position
.Container
= null then
1290 if Position
.Container
/= Object
.Container
then
1291 raise Program_Error
with
1292 "Position cursor of Previous designates wrong map";
1295 return Previous
(Position
);
1302 procedure Query_Element
1304 Process
: not null access procedure (Key
: Key_Type
;
1305 Element
: Element_Type
))
1308 if Position
.Node
= 0 then
1309 raise Constraint_Error
with
1310 "Position cursor of Query_Element equals No_Element";
1313 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1314 "Position cursor of Query_Element is bad");
1317 M
: Map
renames Position
.Container
.all;
1318 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
1320 B
: Natural renames M
.Busy
;
1321 L
: Natural renames M
.Lock
;
1328 Process
(N
.Key
, N
.Element
);
1346 (Stream
: not null access Root_Stream_Type
'Class;
1347 Container
: out Map
)
1349 procedure Read_Element
(Node
: in out Node_Type
);
1350 pragma Inline
(Read_Element
);
1352 procedure Allocate
is
1353 new Tree_Operations
.Generic_Allocate
(Read_Element
);
1355 procedure Read_Elements
is
1356 new Tree_Operations
.Generic_Read
(Allocate
);
1362 procedure Read_Element
(Node
: in out Node_Type
) is
1364 Key_Type
'Read (Stream
, Node
.Key
);
1365 Element_Type
'Read (Stream
, Node
.Element
);
1368 -- Start of processing for Read
1371 Read_Elements
(Stream
, Container
);
1375 (Stream
: not null access Root_Stream_Type
'Class;
1379 raise Program_Error
with "attempt to stream map cursor";
1383 (Stream
: not null access Root_Stream_Type
'Class;
1384 Item
: out Reference_Type
)
1387 raise Program_Error
with "attempt to stream reference";
1391 (Stream
: not null access Root_Stream_Type
'Class;
1392 Item
: out Constant_Reference_Type
)
1395 raise Program_Error
with "attempt to stream reference";
1403 (Container
: aliased in out Map
;
1404 Position
: Cursor
) return Reference_Type
1407 if Position
.Container
= null then
1408 raise Constraint_Error
with
1409 "Position cursor has no element";
1412 if Position
.Container
/= Container
'Unrestricted_Access then
1413 raise Program_Error
with
1414 "Position cursor designates wrong map";
1417 pragma Assert
(Vet
(Container
, Position
.Node
),
1418 "Position cursor in function Reference is bad");
1421 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
1422 B
: Natural renames Container
.Busy
;
1423 L
: Natural renames Container
.Lock
;
1425 return R
: constant Reference_Type
:=
1426 (Element
=> N
.Element
'Access,
1427 Control
=> (Controlled
with Container
'Unrestricted_Access))
1436 (Container
: aliased in out Map
;
1437 Key
: Key_Type
) return Reference_Type
1439 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1443 raise Constraint_Error
with "key not in map";
1447 N
: Node_Type
renames Container
.Nodes
(Node
);
1448 B
: Natural renames Container
.Busy
;
1449 L
: Natural renames Container
.Lock
;
1451 return R
: constant Reference_Type
:=
1452 (Element
=> N
.Element
'Access,
1453 Control
=> (Controlled
with Container
'Unrestricted_Access))
1466 (Container
: in out Map
;
1468 New_Item
: Element_Type
)
1470 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1474 raise Constraint_Error
with "key not in map";
1477 if Container
.Lock
> 0 then
1478 raise Program_Error
with
1479 "attempt to tamper with elements (map is locked)";
1483 N
: Node_Type
renames Container
.Nodes
(Node
);
1487 N
.Element
:= New_Item
;
1491 ---------------------
1492 -- Replace_Element --
1493 ---------------------
1495 procedure Replace_Element
1496 (Container
: in out Map
;
1498 New_Item
: Element_Type
)
1501 if Position
.Node
= 0 then
1502 raise Constraint_Error
with
1503 "Position cursor of Replace_Element equals No_Element";
1506 if Position
.Container
/= Container
'Unrestricted_Access then
1507 raise Program_Error
with
1508 "Position cursor of Replace_Element designates wrong map";
1511 if Container
.Lock
> 0 then
1512 raise Program_Error
with
1513 "attempt to tamper with elements (map is locked)";
1516 pragma Assert
(Vet
(Container
, Position
.Node
),
1517 "Position cursor of Replace_Element is bad");
1519 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1520 end Replace_Element
;
1522 ---------------------
1523 -- Reverse_Iterate --
1524 ---------------------
1526 procedure Reverse_Iterate
1528 Process
: not null access procedure (Position
: Cursor
))
1530 procedure Process_Node
(Node
: Count_Type
);
1531 pragma Inline
(Process_Node
);
1533 procedure Local_Reverse_Iterate
is
1534 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1540 procedure Process_Node
(Node
: Count_Type
) is
1542 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1545 B : Natural renames Container'Unrestricted_Access.all.Busy;
1547 -- Start of processing for Reverse_Iterate
1553 Local_Reverse_Iterate (Container);
1561 end Reverse_Iterate;
1567 function Right (Node : Node_Type) return Count_Type is
1577 (Node : in out Node_Type;
1581 Node.Color := Color;
1588 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1597 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1599 Node.Parent := Parent;
1606 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1608 Node.Right := Right;
1611 --------------------
1612 -- Update_Element --
1613 --------------------
1615 procedure Update_Element
1616 (Container : in out Map;
1618 Process : not null access procedure (Key : Key_Type;
1619 Element : in out Element_Type))
1622 if Position.Node = 0 then
1623 raise Constraint_Error with
1624 "Position cursor of Update_Element equals No_Element";
1627 if Position.Container /= Container'Unrestricted_Access then
1628 raise Program_Error with
1629 "Position cursor of Update_Element designates wrong map";
1632 pragma Assert (Vet (Container, Position.Node),
1633 "Position cursor of Update_Element is bad");
1636 N : Node_Type renames Container.Nodes (Position.Node);
1637 B : Natural renames Container.Busy;
1638 L : Natural renames Container.Lock;
1645 Process (N.Key, N.Element);
1664 (Stream : not null access Root_Stream_Type'Class;
1667 procedure Write_Node
1668 (Stream : not null access Root_Stream_Type'Class;
1670 pragma Inline (Write_Node);
1672 procedure Write_Nodes is
1673 new Tree_Operations.Generic_Write (Write_Node);
1679 procedure Write_Node
1680 (Stream : not null access Root_Stream_Type'Class;
1684 Key_Type'Write (Stream, Node.Key);
1685 Element_Type'Write (Stream, Node.Element);
1688 -- Start of processing for Write
1691 Write_Nodes (Stream, Container);
1695 (Stream : not null access Root_Stream_Type'Class;
1699 raise Program_Error with "attempt to stream map cursor";
1703 (Stream : not null access Root_Stream_Type'Class;
1704 Item : Reference_Type)
1707 raise Program_Error with "attempt to stream reference";
1711 (Stream : not null access Root_Stream_Type'Class;
1712 Item : Constant_Reference_Type)
1715 raise Program_Error with "attempt to stream reference";
1718 end Ada.Containers.Bounded_Ordered_Maps;