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-2011, 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 Ada.Finalization; use Ada.Finalization;
40 with System; use type System.Address;
42 package body Ada.Containers.Bounded_Ordered_Maps is
44 type Iterator is new Limited_Controlled and
45 Map_Iterator_Interfaces.Reversible_Iterator with
47 Container : Map_Access;
51 overriding procedure Finalize (Object : in out Iterator);
53 overriding function First (Object : Iterator) return Cursor;
54 overriding function Last (Object : Iterator) return Cursor;
56 overriding function Next
58 Position : Cursor) return Cursor;
60 overriding function Previous
62 Position : Cursor) return Cursor;
64 -----------------------------
65 -- Node Access Subprograms --
66 -----------------------------
68 -- These subprograms provide a functional interface to access fields
69 -- of a node, and a procedural interface for modifying these values.
71 function Color (Node : Node_Type) return Color_Type;
72 pragma Inline (Color);
74 function Left (Node : Node_Type) return Count_Type;
77 function Parent (Node : Node_Type) return Count_Type;
78 pragma Inline (Parent);
80 function Right (Node : Node_Type) return Count_Type;
81 pragma Inline (Right);
83 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
84 pragma Inline (Set_Parent);
86 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
87 pragma Inline (Set_Left);
89 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
90 pragma Inline (Set_Right);
92 procedure Set_Color (Node : in out Node_Type; Color : Color_Type);
93 pragma Inline (Set_Color);
95 -----------------------
96 -- Local Subprograms --
97 -----------------------
99 function Is_Greater_Key_Node
101 Right : Node_Type) return Boolean;
102 pragma Inline (Is_Greater_Key_Node);
104 function Is_Less_Key_Node
106 Right : Node_Type) return Boolean;
107 pragma Inline (Is_Less_Key_Node);
109 --------------------------
110 -- Local Instantiations --
111 --------------------------
113 package Tree_Operations is
114 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
119 new Red_Black_Trees.Generic_Bounded_Keys
120 (Tree_Operations => Tree_Operations,
121 Key_Type => Key_Type,
122 Is_Less_Key_Node => Is_Less_Key_Node,
123 Is_Greater_Key_Node => Is_Greater_Key_Node);
129 function "<" (Left, Right : Cursor) return Boolean is
131 if Left.Node = 0 then
132 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
135 if Right.Node = 0 then
136 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
139 pragma Assert (Vet (Left.Container.all, Left.Node),
140 "Left cursor of ""<"" is bad");
142 pragma Assert (Vet (Right.Container.all, Right.Node),
143 "Right cursor of ""<"" is bad");
146 LN : Node_Type renames Left.Container.Nodes (Left.Node);
147 RN : Node_Type renames Right.Container.Nodes (Right.Node);
150 return LN.Key < RN.Key;
154 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
156 if Left.Node = 0 then
157 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
160 pragma Assert (Vet (Left.Container.all, Left.Node),
161 "Left cursor of ""<"" is bad");
164 LN : Node_Type renames Left.Container.Nodes (Left.Node);
167 return LN.Key < Right;
171 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
173 if Right.Node = 0 then
174 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
177 pragma Assert (Vet (Right.Container.all, Right.Node),
178 "Right cursor of ""<"" is bad");
181 RN : Node_Type renames Right.Container.Nodes (Right.Node);
184 return Left < RN.Key;
192 function "=" (Left, Right : Map) return Boolean is
193 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
194 pragma Inline (Is_Equal_Node_Node);
197 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
199 ------------------------
200 -- Is_Equal_Node_Node --
201 ------------------------
203 function Is_Equal_Node_Node
204 (L, R : Node_Type) return Boolean is
206 if L.Key < R.Key then
209 elsif R.Key < L.Key then
213 return L.Element = R.Element;
215 end Is_Equal_Node_Node;
217 -- Start of processing for "="
220 return Is_Equal (Left, Right);
227 function ">" (Left, Right : Cursor) return Boolean is
229 if Left.Node = 0 then
230 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
233 if Right.Node = 0 then
234 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
237 pragma Assert (Vet (Left.Container.all, Left.Node),
238 "Left cursor of "">"" is bad");
240 pragma Assert (Vet (Right.Container.all, Right.Node),
241 "Right cursor of "">"" is bad");
244 LN : Node_Type renames Left.Container.Nodes (Left.Node);
245 RN : Node_Type renames Right.Container.Nodes (Right.Node);
248 return RN.Key < LN.Key;
252 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
254 if Left.Node = 0 then
255 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
258 pragma Assert (Vet (Left.Container.all, Left.Node),
259 "Left cursor of "">"" is bad");
262 LN : Node_Type renames Left.Container.Nodes (Left.Node);
264 return Right < LN.Key;
268 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
270 if Right.Node = 0 then
271 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
274 pragma Assert (Vet (Right.Container.all, Right.Node),
275 "Right cursor of "">"" is bad");
278 RN : Node_Type renames Right.Container.Nodes (Right.Node);
281 return RN.Key < Left;
289 procedure Assign (Target : in out Map; Source : Map) is
290 procedure Append_Element (Source_Node : Count_Type);
292 procedure Append_Elements is
293 new Tree_Operations.Generic_Iteration (Append_Element);
299 procedure Append_Element (Source_Node : Count_Type) is
300 SN : Node_Type renames Source.Nodes (Source_Node);
302 procedure Set_Element (Node : in out Node_Type);
303 pragma Inline (Set_Element);
305 function New_Node return Count_Type;
306 pragma Inline (New_Node);
308 procedure Insert_Post is
309 new Key_Ops.Generic_Insert_Post (New_Node);
311 procedure Unconditional_Insert_Sans_Hint is
312 new Key_Ops.Generic_Unconditional_Insert (Insert_Post);
314 procedure Unconditional_Insert_Avec_Hint is
315 new Key_Ops.Generic_Unconditional_Insert_With_Hint
317 Unconditional_Insert_Sans_Hint);
319 procedure Allocate is
320 new Tree_Operations.Generic_Allocate (Set_Element);
326 function New_Node return Count_Type is
330 Allocate (Target, Result);
338 procedure Set_Element (Node : in out Node_Type) is
341 Node.Element := SN.Element;
344 Target_Node : Count_Type;
346 -- Start of processing for Append_Element
349 Unconditional_Insert_Avec_Hint
353 Node => Target_Node);
356 -- Start of processing for Assign
359 if Target'Address = Source'Address then
363 if Target.Capacity < Source.Length then
365 with "Target capacity is less than Source length";
368 Tree_Operations.Clear_Tree (Target);
369 Append_Elements (Source);
376 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
377 Node : constant Count_Type := Key_Ops.Ceiling (Container, Key);
384 return Cursor'(Container'Unrestricted_Access, Node);
391 procedure Clear (Container : in out Map) is
393 Tree_Operations.Clear_Tree (Container);
400 function Color (Node : Node_Type) return Color_Type is
409 function Contains (Container : Map; Key : Key_Type) return Boolean is
411 return Find (Container, Key) /= No_Element;
418 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
425 elsif Capacity >= Source.Length then
429 raise Capacity_Error with "Capacity value too small";
432 return Target : Map (Capacity => C) do
433 Assign (Target => Target, Source => Source);
441 procedure Delete (Container : in out Map; Position : in out Cursor) is
443 if Position.Node = 0 then
444 raise Constraint_Error with
445 "Position cursor of Delete equals No_Element";
448 if Position.Container /= Container'Unrestricted_Access then
449 raise Program_Error with
450 "Position cursor of Delete designates wrong map";
453 pragma Assert (Vet (Container, Position.Node),
454 "Position cursor of Delete is bad");
456 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
457 Tree_Operations.Free (Container, Position.Node);
459 Position := No_Element;
462 procedure Delete (Container : in out Map; Key : Key_Type) is
463 X : constant Count_Type := Key_Ops.Find (Container, Key);
467 raise Constraint_Error with "key not in map";
470 Tree_Operations.Delete_Node_Sans_Free (Container, X);
471 Tree_Operations.Free (Container, X);
478 procedure Delete_First (Container : in out Map) is
479 X : constant Count_Type := Container.First;
483 Tree_Operations.Delete_Node_Sans_Free (Container, X);
484 Tree_Operations.Free (Container, X);
492 procedure Delete_Last (Container : in out Map) is
493 X : constant Count_Type := Container.Last;
497 Tree_Operations.Delete_Node_Sans_Free (Container, X);
498 Tree_Operations.Free (Container, X);
506 function Element (Position : Cursor) return Element_Type is
508 if Position.Node = 0 then
509 raise Constraint_Error with
510 "Position cursor of function Element equals No_Element";
513 pragma Assert (Vet (Position.Container.all, Position.Node),
514 "Position cursor of function Element is bad");
516 return Position.Container.Nodes (Position.Node).Element;
519 function Element (Container : Map; Key : Key_Type) return Element_Type is
520 Node : constant Count_Type := Key_Ops.Find (Container, Key);
523 raise Constraint_Error with "key not in map";
525 return Container.Nodes (Node).Element;
529 ---------------------
530 -- Equivalent_Keys --
531 ---------------------
533 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
548 procedure Exclude (Container : in out Map; Key : Key_Type) is
549 X : constant Count_Type := Key_Ops.Find (Container, Key);
553 Tree_Operations.Delete_Node_Sans_Free (Container, X);
554 Tree_Operations.Free (Container, X);
562 procedure Finalize (Object : in out Iterator) is
564 if Object.Container /= null then
566 B : Natural renames Object.Container.all.Busy;
577 function Find (Container : Map; Key : Key_Type) return Cursor is
578 Node : constant Count_Type := Key_Ops.Find (Container, Key);
583 return Cursor'(Container'Unrestricted_Access, Node);
591 function First (Container : Map) return Cursor is
593 if Container.First = 0 then
596 return Cursor'(Container'Unrestricted_Access, Container.First);
600 function First (Object : Iterator) return Cursor is
602 -- The value of the iterator object's Node component influences the
603 -- behavior of the First (and Last) selector function.
605 -- When the Node component is 0, this means the iterator object was
606 -- constructed without a start expression, in which case the (forward)
607 -- iteration starts from the (logical) beginning of the entire sequence
608 -- of items (corresponding to Container.First, for a forward iterator).
610 -- Otherwise, this is iteration over a partial sequence of items. When
611 -- the Node component is positive, the iterator object was constructed
612 -- with a start expression, that specifies the position from which the
613 -- (forward) partial iteration begins.
615 if Object.Node = 0 then
616 return Bounded_Ordered_Maps.First (Object.Container.all);
618 return Cursor'(Object.Container, Object.Node);
626 function First_Element (Container : Map) return Element_Type is
628 if Container.First = 0 then
629 raise Constraint_Error with "map is empty";
631 return Container.Nodes (Container.First).Element;
639 function First_Key (Container : Map) return Key_Type is
641 if Container.First = 0 then
642 raise Constraint_Error with "map is empty";
644 return Container.Nodes (Container.First).Key;
652 function Floor (Container : Map; Key : Key_Type) return Cursor is
653 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
658 return Cursor'(Container'Unrestricted_Access, Node);
666 function Has_Element (Position : Cursor) return Boolean is
668 return Position /= No_Element;
676 (Container : in out Map;
678 New_Item : Element_Type)
684 Insert (Container, Key, New_Item, Position, Inserted);
687 if Container.Lock > 0 then
688 raise Program_Error with
689 "attempt to tamper with elements (map is locked)";
693 N : Node_Type renames Container.Nodes (Position.Node);
696 N.Element := New_Item;
706 (Container : in out Map;
708 New_Item : Element_Type;
709 Position : out Cursor;
710 Inserted : out Boolean)
712 procedure Assign (Node : in out Node_Type);
713 pragma Inline (Assign);
715 function New_Node return Count_Type;
716 pragma Inline (New_Node);
718 procedure Insert_Post is
719 new Key_Ops.Generic_Insert_Post (New_Node);
721 procedure Insert_Sans_Hint is
722 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
724 procedure Allocate is
725 new Tree_Operations.Generic_Allocate (Assign);
731 procedure Assign (Node : in out Node_Type) is
734 Node.Element := New_Item;
741 function New_Node return Count_Type is
744 Allocate (Container, Result);
748 -- Start of processing for Insert
757 Position.Container := Container'Unrestricted_Access;
761 (Container : in out Map;
763 New_Item : Element_Type)
766 pragma Unreferenced (Position);
771 Insert (Container, Key, New_Item, Position, Inserted);
774 raise Constraint_Error with "key already in map";
779 (Container : in out Map;
781 Position : out Cursor;
782 Inserted : out Boolean)
784 procedure Assign (Node : in out Node_Type);
785 pragma Inline (Assign);
787 function New_Node return Count_Type;
788 pragma Inline (New_Node);
790 procedure Insert_Post is
791 new Key_Ops.Generic_Insert_Post (New_Node);
793 procedure Insert_Sans_Hint is
794 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
796 procedure Allocate is
797 new Tree_Operations.Generic_Allocate (Assign);
803 procedure Assign (Node : in out Node_Type) is
807 -- Were this insertion operation to accept an element parameter, this
808 -- is the point where the element value would be used, to update the
809 -- element component of the new node. However, this insertion
810 -- operation is special, in the sense that it does not accept an
811 -- element parameter. Rather, this version of Insert allocates a node
812 -- (inserting it among the active nodes of the container in the
813 -- normal way, with the node's position being determined by the Key),
814 -- and passes back a cursor designating the node. It is then up to
815 -- the caller to assign a value to the node's element.
817 -- Node.Element := New_Item;
824 function New_Node return Count_Type is
827 Allocate (Container, Result);
831 -- Start of processing for Insert
840 Position.Container := Container'Unrestricted_Access;
847 function Is_Empty (Container : Map) return Boolean is
849 return Container.Length = 0;
852 -------------------------
853 -- Is_Greater_Key_Node --
854 -------------------------
856 function Is_Greater_Key_Node
858 Right : Node_Type) return Boolean
861 -- Left > Right same as Right < Left
863 return Right.Key < Left;
864 end Is_Greater_Key_Node;
866 ----------------------
867 -- Is_Less_Key_Node --
868 ----------------------
870 function Is_Less_Key_Node
872 Right : Node_Type) return Boolean
875 return Left < Right.Key;
876 end Is_Less_Key_Node;
884 Process : not null access procedure (Position : Cursor))
886 procedure Process_Node (Node : Count_Type);
887 pragma Inline (Process_Node);
889 procedure Local_Iterate is
890 new Tree_Operations.Generic_Iteration (Process_Node);
896 procedure Process_Node (Node : Count_Type) is
898 Process (Cursor'(Container'Unrestricted_Access, Node));
901 B : Natural renames Container'Unrestricted_Access.all.Busy;
903 -- Start of processing for Iterate
909 Local_Iterate (Container);
920 (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
922 B : Natural renames Container'Unrestricted_Access.all.Busy;
925 -- The value of the Node component influences the behavior of the First
926 -- and Last selector functions of the iterator object. When the Node
927 -- component is 0 (as is the case here), this means the iterator object
928 -- was constructed without a start expression. This is a complete
929 -- iterator, meaning that the iteration starts from the (logical)
930 -- beginning of the sequence of items.
932 -- Note: For a forward iterator, Container.First is the beginning, and
933 -- for a reverse iterator, Container.Last is the beginning.
935 return It : constant Iterator :=
936 (Limited_Controlled with
937 Container => Container'Unrestricted_Access,
947 return Map_Iterator_Interfaces.Reversible_Iterator'Class
949 B : Natural renames Container'Unrestricted_Access.all.Busy;
952 -- Iterator was defined to behave the same as for a complete iterator,
953 -- and iterate over the entire sequence of items. However, those
954 -- semantics were unintuitive and arguably error-prone (it is too easy
955 -- to accidentally create an endless loop), and so they were changed,
956 -- per the ARG meeting in Denver on 2011/11. However, there was no
957 -- consensus about what positive meaning this corner case should have,
958 -- and so it was decided to simply raise an exception. This does imply,
959 -- however, that it is not possible to use a partial iterator to specify
960 -- an empty sequence of items.
962 if Start = No_Element then
963 raise Constraint_Error with
964 "Start position for iterator equals No_Element";
967 if Start.Container /= Container'Unrestricted_Access then
968 raise Program_Error with
969 "Start cursor of Iterate designates wrong map";
972 pragma Assert (Vet (Container, Start.Node),
973 "Start cursor of Iterate is bad");
975 -- The value of the Node component influences the behavior of the First
976 -- and Last selector functions of the iterator object. When the Node
977 -- component is positive (as is the case here), it means that this
978 -- is a partial iteration, over a subset of the complete sequence of
979 -- items. The iterator object was constructed with a start expression,
980 -- indicating the position from which the iteration begins. (Note that
981 -- the start position has the same value irrespective of whether this
982 -- is a forward or reverse iteration.)
984 return It : constant Iterator :=
985 (Limited_Controlled with
986 Container => Container'Unrestricted_Access,
997 function Key (Position : Cursor) return Key_Type is
999 if Position.Node = 0 then
1000 raise Constraint_Error with
1001 "Position cursor of function Key equals No_Element";
1004 pragma Assert (Vet (Position.Container.all, Position.Node),
1005 "Position cursor of function Key is bad");
1007 return Position.Container.Nodes (Position.Node).Key;
1014 function Last (Container : Map) return Cursor is
1016 if Container.Last = 0 then
1019 return Cursor'(Container'Unrestricted_Access, Container.Last);
1023 function Last (Object : Iterator) return Cursor is
1025 -- The value of the iterator object's Node component influences the
1026 -- behavior of the Last (and First) selector function.
1028 -- When the Node component is 0, this means the iterator object was
1029 -- constructed without a start expression, in which case the (reverse)
1030 -- iteration starts from the (logical) beginning of the entire sequence
1031 -- (corresponding to Container.Last, for a reverse iterator).
1033 -- Otherwise, this is iteration over a partial sequence of items. When
1034 -- the Node component is positive, the iterator object was constructed
1035 -- with a start expression, that specifies the position from which the
1036 -- (reverse) partial iteration begins.
1038 if Object.Node = 0 then
1039 return Bounded_Ordered_Maps.Last (Object.Container.all);
1041 return Cursor'(Object.Container, Object.Node);
1049 function Last_Element (Container : Map) return Element_Type is
1051 if Container.Last = 0 then
1052 raise Constraint_Error with "map is empty";
1054 return Container.Nodes (Container.Last).Element;
1062 function Last_Key (Container : Map) return Key_Type is
1064 if Container.Last = 0 then
1065 raise Constraint_Error with "map is empty";
1067 return Container.Nodes (Container.Last).Key;
1075 function Left (Node : Node_Type) return Count_Type is
1084 function Length (Container : Map) return Count_Type is
1086 return Container.Length;
1093 procedure Move (Target : in out Map; Source : in out Map) is
1095 if Target'Address = Source'Address then
1099 if Source.Busy > 0 then
1100 raise Program_Error with
1101 "attempt to tamper with cursors (container is busy)";
1104 Target.Assign (Source);
1112 procedure Next (Position : in out Cursor) is
1114 Position := Next (Position);
1117 function Next (Position : Cursor) return Cursor is
1119 if Position = No_Element then
1123 pragma Assert (Vet (Position.Container.all, Position.Node),
1124 "Position cursor of Next is bad");
1127 M : Map renames Position.Container.all;
1129 Node : constant Count_Type :=
1130 Tree_Operations.Next (M, Position.Node);
1137 return Cursor'(Position.Container, Node);
1143 Position : Cursor) return Cursor
1146 if Position.Container = null then
1150 if Position.Container /= Object.Container then
1151 raise Program_Error with
1152 "Position cursor of Next designates wrong map";
1155 return Next (Position);
1162 function Parent (Node : Node_Type) return Count_Type is
1171 procedure Previous (Position : in out Cursor) is
1173 Position := Previous (Position);
1176 function Previous (Position : Cursor) return Cursor is
1178 if Position = No_Element then
1182 pragma Assert (Vet (Position.Container.all, Position.Node),
1183 "Position cursor of Previous is bad");
1186 M : Map renames Position.Container.all;
1188 Node : constant Count_Type :=
1189 Tree_Operations.Previous (M, Position.Node);
1196 return Cursor'(Position.Container, Node);
1202 Position : Cursor) return Cursor
1205 if Position.Container = null then
1209 if Position.Container /= Object.Container then
1210 raise Program_Error with
1211 "Position cursor of Previous designates wrong map";
1214 return Previous (Position);
1221 procedure Query_Element
1223 Process : not null access procedure (Key : Key_Type;
1224 Element : Element_Type))
1227 if Position.Node = 0 then
1228 raise Constraint_Error with
1229 "Position cursor of Query_Element equals No_Element";
1232 pragma Assert (Vet (Position.Container.all, Position.Node),
1233 "Position cursor of Query_Element is bad");
1236 M : Map renames Position.Container.all;
1237 N : Node_Type renames M.Nodes (Position.Node);
1239 B : Natural renames M.Busy;
1240 L : Natural renames M.Lock;
1247 Process (N.Key, N.Element);
1265 (Stream : not null access Root_Stream_Type'Class;
1266 Container : out Map)
1268 procedure Read_Element (Node : in out Node_Type);
1269 pragma Inline (Read_Element);
1271 procedure Allocate is
1272 new Tree_Operations.Generic_Allocate (Read_Element);
1274 procedure Read_Elements is
1275 new Tree_Operations.Generic_Read (Allocate);
1281 procedure Read_Element (Node : in out Node_Type) is
1283 Key_Type'Read (Stream, Node.Key);
1284 Element_Type'Read (Stream, Node.Element);
1287 -- Start of processing for Read
1290 Read_Elements (Stream, Container);
1294 (Stream : not null access Root_Stream_Type'Class;
1298 raise Program_Error with "attempt to stream map cursor";
1302 (Stream : not null access Root_Stream_Type'Class;
1303 Item : out Reference_Type)
1306 raise Program_Error with "attempt to stream reference";
1310 (Stream : not null access Root_Stream_Type'Class;
1311 Item : out Constant_Reference_Type)
1314 raise Program_Error with "attempt to stream reference";
1321 function Constant_Reference
1323 Key : Key_Type) return Constant_Reference_Type
1326 return (Element => Container.Element (Key)'Unrestricted_Access);
1327 end Constant_Reference;
1331 Key : Key_Type) return Reference_Type
1334 return (Element => Container.Element (Key)'Unrestricted_Access);
1342 (Container : in out Map;
1344 New_Item : Element_Type)
1346 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1350 raise Constraint_Error with "key not in map";
1353 if Container.Lock > 0 then
1354 raise Program_Error with
1355 "attempt to tamper with elements (map is locked)";
1359 N : Node_Type renames Container.Nodes (Node);
1363 N.Element := New_Item;
1367 ---------------------
1368 -- Replace_Element --
1369 ---------------------
1371 procedure Replace_Element
1372 (Container : in out Map;
1374 New_Item : Element_Type)
1377 if Position.Node = 0 then
1378 raise Constraint_Error with
1379 "Position cursor of Replace_Element equals No_Element";
1382 if Position.Container /= Container'Unrestricted_Access then
1383 raise Program_Error with
1384 "Position cursor of Replace_Element designates wrong map";
1387 if Container.Lock > 0 then
1388 raise Program_Error with
1389 "attempt to tamper with elements (map is locked)";
1392 pragma Assert (Vet (Container, Position.Node),
1393 "Position cursor of Replace_Element is bad");
1395 Container.Nodes (Position.Node).Element := New_Item;
1396 end Replace_Element;
1398 ---------------------
1399 -- Reverse_Iterate --
1400 ---------------------
1402 procedure Reverse_Iterate
1404 Process : not null access procedure (Position : Cursor))
1406 procedure Process_Node (Node : Count_Type);
1407 pragma Inline (Process_Node);
1409 procedure Local_Reverse_Iterate is
1410 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1416 procedure Process_Node (Node : Count_Type) is
1418 Process (Cursor'(Container'Unrestricted_Access, Node));
1421 B : Natural renames Container'Unrestricted_Access.all.Busy;
1423 -- Start of processing for Reverse_Iterate
1429 Local_Reverse_Iterate (Container);
1437 end Reverse_Iterate;
1443 function Right (Node : Node_Type) return Count_Type is
1453 (Node : in out Node_Type;
1457 Node.Color := Color;
1464 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1473 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1475 Node.Parent := Parent;
1482 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1484 Node.Right := Right;
1487 --------------------
1488 -- Update_Element --
1489 --------------------
1491 procedure Update_Element
1492 (Container : in out Map;
1494 Process : not null access procedure (Key : Key_Type;
1495 Element : in out Element_Type))
1498 if Position.Node = 0 then
1499 raise Constraint_Error with
1500 "Position cursor of Update_Element equals No_Element";
1503 if Position.Container /= Container'Unrestricted_Access then
1504 raise Program_Error with
1505 "Position cursor of Update_Element designates wrong map";
1508 pragma Assert (Vet (Container, Position.Node),
1509 "Position cursor of Update_Element is bad");
1512 N : Node_Type renames Container.Nodes (Position.Node);
1513 B : Natural renames Container.Busy;
1514 L : Natural renames Container.Lock;
1521 Process (N.Key, N.Element);
1540 (Stream : not null access Root_Stream_Type'Class;
1543 procedure Write_Node
1544 (Stream : not null access Root_Stream_Type'Class;
1546 pragma Inline (Write_Node);
1548 procedure Write_Nodes is
1549 new Tree_Operations.Generic_Write (Write_Node);
1555 procedure Write_Node
1556 (Stream : not null access Root_Stream_Type'Class;
1560 Key_Type'Write (Stream, Node.Key);
1561 Element_Type'Write (Stream, Node.Element);
1564 -- Start of processing for Write
1567 Write_Nodes (Stream, Container);
1571 (Stream : not null access Root_Stream_Type'Class;
1575 raise Program_Error with "attempt to stream map cursor";
1579 (Stream : not null access Root_Stream_Type'Class;
1580 Item : Reference_Type)
1583 raise Program_Error with "attempt to stream reference";
1587 (Stream : not null access Root_Stream_Type'Class;
1588 Item : Constant_Reference_Type)
1591 raise Program_Error with "attempt to stream reference";
1594 end Ada.Containers.Bounded_Ordered_Maps;