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-2010, 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
);
243 return Right
< LN
.Key
;
247 function ">" (Left
: Key_Type
; Right
: Cursor
) return Boolean is
249 if Right
.Node
= 0 then
250 raise Constraint_Error
with "Right cursor of "">"" equals No_Element";
253 pragma Assert
(Vet
(Right
.Container
.all, Right
.Node
),
254 "Right cursor of "">"" is bad");
257 RN
: Node_Type
renames Right
.Container
.Nodes
(Right
.Node
);
260 return RN
.Key
< Left
;
268 procedure Assign
(Target
: in out Map
; Source
: Map
) is
269 procedure Append_Element
(Source_Node
: Count_Type
);
271 procedure Append_Elements
is
272 new Tree_Operations
.Generic_Iteration
(Append_Element
);
278 procedure Append_Element
(Source_Node
: Count_Type
) is
279 SN
: Node_Type
renames Source
.Nodes
(Source_Node
);
281 procedure Set_Element
(Node
: in out Node_Type
);
282 pragma Inline
(Set_Element
);
284 function New_Node
return Count_Type
;
285 pragma Inline
(New_Node
);
287 procedure Insert_Post
is
288 new Key_Ops
.Generic_Insert_Post
(New_Node
);
290 procedure Unconditional_Insert_Sans_Hint
is
291 new Key_Ops
.Generic_Unconditional_Insert
(Insert_Post
);
293 procedure Unconditional_Insert_Avec_Hint
is
294 new Key_Ops
.Generic_Unconditional_Insert_With_Hint
296 Unconditional_Insert_Sans_Hint
);
298 procedure Allocate
is
299 new Tree_Operations
.Generic_Allocate
(Set_Element
);
305 function New_Node
return Count_Type
is
309 Allocate
(Target
, Result
);
317 procedure Set_Element
(Node
: in out Node_Type
) is
320 Node
.Element
:= SN
.Element
;
323 Target_Node
: Count_Type
;
325 -- Start of processing for Append_Element
328 Unconditional_Insert_Avec_Hint
332 Node
=> Target_Node
);
335 -- Start of processing for Assign
338 if Target
'Address = Source
'Address then
342 if Target
.Capacity
< Source
.Length
then
344 with "Target capacity is less than Source length";
347 Tree_Operations
.Clear_Tree
(Target
);
348 Append_Elements
(Source
);
355 function Ceiling
(Container
: Map
; Key
: Key_Type
) return Cursor
is
356 Node
: constant Count_Type
:= Key_Ops
.Ceiling
(Container
, Key
);
363 return Cursor
'(Container'Unrestricted_Access, Node);
370 procedure Clear (Container : in out Map) is
372 Tree_Operations.Clear_Tree (Container);
379 function Color (Node : Node_Type) return Color_Type is
388 function Contains (Container : Map; Key : Key_Type) return Boolean is
390 return Find (Container, Key) /= No_Element;
397 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
404 elsif Capacity >= Source.Length then
408 raise Capacity_Error with "Capacity value too small";
411 return Target : Map (Capacity => C) do
412 Assign (Target => Target, Source => Source);
420 procedure Delete (Container : in out Map; Position : in out Cursor) is
422 if Position.Node = 0 then
423 raise Constraint_Error with
424 "Position cursor of Delete equals No_Element";
427 if Position.Container /= Container'Unrestricted_Access then
428 raise Program_Error with
429 "Position cursor of Delete designates wrong map";
432 pragma Assert (Vet (Container, Position.Node),
433 "Position cursor of Delete is bad");
435 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
436 Tree_Operations.Free (Container, Position.Node);
438 Position := No_Element;
441 procedure Delete (Container : in out Map; Key : Key_Type) is
442 X : constant Count_Type := Key_Ops.Find (Container, Key);
446 raise Constraint_Error with "key not in map";
449 Tree_Operations.Delete_Node_Sans_Free (Container, X);
450 Tree_Operations.Free (Container, X);
457 procedure Delete_First (Container : in out Map) is
458 X : constant Count_Type := Container.First;
462 Tree_Operations.Delete_Node_Sans_Free (Container, X);
463 Tree_Operations.Free (Container, X);
471 procedure Delete_Last (Container : in out Map) is
472 X : constant Count_Type := Container.Last;
476 Tree_Operations.Delete_Node_Sans_Free (Container, X);
477 Tree_Operations.Free (Container, X);
485 function Element (Position : Cursor) return Element_Type is
487 if Position.Node = 0 then
488 raise Constraint_Error with
489 "Position cursor of function Element equals No_Element";
492 pragma Assert (Vet (Position.Container.all, Position.Node),
493 "Position cursor of function Element is bad");
495 return Position.Container.Nodes (Position.Node).Element;
498 function Element (Container : Map; Key : Key_Type) return Element_Type is
499 Node : constant Count_Type := Key_Ops.Find (Container, Key);
503 raise Constraint_Error with "key not in map";
506 return Container.Nodes (Node).Element;
509 ---------------------
510 -- Equivalent_Keys --
511 ---------------------
513 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
528 procedure Exclude (Container : in out Map; Key : Key_Type) is
529 X : constant Count_Type := Key_Ops.Find (Container, Key);
533 Tree_Operations.Delete_Node_Sans_Free (Container, X);
534 Tree_Operations.Free (Container, X);
542 function Find (Container : Map; Key : Key_Type) return Cursor is
543 Node : constant Count_Type := Key_Ops.Find (Container, Key);
550 return Cursor'(Container
'Unrestricted_Access, Node
);
557 function First
(Container
: Map
) return Cursor
is
559 if Container
.First
= 0 then
563 return Cursor
'(Container'Unrestricted_Access, Container.First);
570 function First_Element (Container : Map) return Element_Type is
572 if Container.First = 0 then
573 raise Constraint_Error with "map is empty";
576 return Container.Nodes (Container.First).Element;
583 function First_Key (Container : Map) return Key_Type is
585 if Container.First = 0 then
586 raise Constraint_Error with "map is empty";
589 return Container.Nodes (Container.First).Key;
596 function Floor (Container : Map; Key : Key_Type) return Cursor is
597 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
604 return Cursor'(Container
'Unrestricted_Access, Node
);
611 function Has_Element
(Position
: Cursor
) return Boolean is
613 return Position
/= No_Element
;
621 (Container
: in out Map
;
623 New_Item
: Element_Type
)
629 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
632 if Container
.Lock
> 0 then
633 raise Program_Error
with
634 "attempt to tamper with elements (map is locked)";
638 N
: Node_Type
renames Container
.Nodes
(Position
.Node
);
642 N
.Element
:= New_Item
;
652 (Container
: in out Map
;
654 New_Item
: Element_Type
;
655 Position
: out Cursor
;
656 Inserted
: out Boolean)
658 procedure Assign
(Node
: in out Node_Type
);
659 pragma Inline
(Assign
);
661 function New_Node
return Count_Type
;
662 pragma Inline
(New_Node
);
664 procedure Insert_Post
is
665 new Key_Ops
.Generic_Insert_Post
(New_Node
);
667 procedure Insert_Sans_Hint
is
668 new Key_Ops
.Generic_Conditional_Insert
(Insert_Post
);
670 procedure Allocate
is
671 new Tree_Operations
.Generic_Allocate
(Assign
);
677 procedure Assign
(Node
: in out Node_Type
) is
680 Node
.Element
:= New_Item
;
687 function New_Node
return Count_Type
is
691 Allocate
(Container
, Result
);
695 -- Start of processing for Insert
704 Position
.Container
:= Container
'Unrestricted_Access;
708 (Container
: in out Map
;
710 New_Item
: Element_Type
)
713 pragma Unreferenced
(Position
);
718 Insert
(Container
, Key
, New_Item
, Position
, Inserted
);
721 raise Constraint_Error
with "key already in map";
726 (Container
: in out Map
;
728 Position
: out Cursor
;
729 Inserted
: out Boolean)
731 procedure Assign
(Node
: in out Node_Type
);
732 pragma Inline
(Assign
);
734 function New_Node
return Count_Type
;
735 pragma Inline
(New_Node
);
737 procedure Insert_Post
is
738 new Key_Ops
.Generic_Insert_Post
(New_Node
);
740 procedure Insert_Sans_Hint
is
741 new Key_Ops
.Generic_Conditional_Insert
(Insert_Post
);
743 procedure Allocate
is
744 new Tree_Operations
.Generic_Allocate
(Assign
);
750 procedure Assign
(Node
: in out Node_Type
) is
753 -- Node.Element := New_Item;
760 function New_Node
return Count_Type
is
764 Allocate
(Container
, Result
);
768 -- Start of processing for Insert
777 Position
.Container
:= Container
'Unrestricted_Access;
784 function Is_Empty
(Container
: Map
) return Boolean is
786 return Container
.Length
= 0;
789 -------------------------
790 -- Is_Greater_Key_Node --
791 -------------------------
793 function Is_Greater_Key_Node
795 Right
: Node_Type
) return Boolean
798 -- k > node same as node < k
800 return Right
.Key
< Left
;
801 end Is_Greater_Key_Node
;
803 ----------------------
804 -- Is_Less_Key_Node --
805 ----------------------
807 function Is_Less_Key_Node
809 Right
: Node_Type
) return Boolean
812 return Left
< Right
.Key
;
813 end Is_Less_Key_Node
;
821 Process
: not null access procedure (Position
: Cursor
))
823 procedure Process_Node
(Node
: Count_Type
);
824 pragma Inline
(Process_Node
);
826 procedure Local_Iterate
is
827 new Tree_Operations
.Generic_Iteration
(Process_Node
);
833 procedure Process_Node
(Node
: Count_Type
) is
835 Process
(Cursor
'(Container'Unrestricted_Access, Node));
838 B : Natural renames Container'Unrestricted_Access.all.Busy;
840 -- Start of processing for Iterate
846 Local_Iterate (Container);
860 function Key (Position : Cursor) return Key_Type is
862 if Position.Node = 0 then
863 raise Constraint_Error with
864 "Position cursor of function Key equals No_Element";
867 pragma Assert (Vet (Position.Container.all, Position.Node),
868 "Position cursor of function Key is bad");
870 return Position.Container.Nodes (Position.Node).Key;
877 function Last (Container : Map) return Cursor is
879 if Container.Last = 0 then
883 return Cursor'(Container
'Unrestricted_Access, Container
.Last
);
890 function Last_Element
(Container
: Map
) return Element_Type
is
892 if Container
.Last
= 0 then
893 raise Constraint_Error
with "map is empty";
896 return Container
.Nodes
(Container
.Last
).Element
;
903 function Last_Key
(Container
: Map
) return Key_Type
is
905 if Container
.Last
= 0 then
906 raise Constraint_Error
with "map is empty";
909 return Container
.Nodes
(Container
.Last
).Key
;
916 function Left
(Node
: Node_Type
) return Count_Type
is
925 function Length
(Container
: Map
) return Count_Type
is
927 return Container
.Length
;
934 procedure Move
(Target
: in out Map
; Source
: in out Map
) is
936 if Target
'Address = Source
'Address then
940 if Source
.Busy
> 0 then
941 raise Program_Error
with
942 "attempt to tamper with cursors (container is busy)";
945 Assign
(Target
=> Target
, Source
=> Source
);
952 procedure Next
(Position
: in out Cursor
) is
954 Position
:= Next
(Position
);
957 function Next
(Position
: Cursor
) return Cursor
is
959 if Position
= No_Element
then
963 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
964 "Position cursor of Next is bad");
967 M
: Map
renames Position
.Container
.all;
969 Node
: constant Count_Type
:=
970 Tree_Operations
.Next
(M
, Position
.Node
);
977 return Cursor
'(Position.Container, Node);
985 function Parent (Node : Node_Type) return Count_Type is
994 procedure Previous (Position : in out Cursor) is
996 Position := Previous (Position);
999 function Previous (Position : Cursor) return Cursor is
1001 if Position = No_Element then
1005 pragma Assert (Vet (Position.Container.all, Position.Node),
1006 "Position cursor of Previous is bad");
1009 M : Map renames Position.Container.all;
1011 Node : constant Count_Type :=
1012 Tree_Operations.Previous (M, Position.Node);
1019 return Cursor'(Position
.Container
, Node
);
1027 procedure Query_Element
1029 Process
: not null access procedure (Key
: Key_Type
;
1030 Element
: Element_Type
))
1033 if Position
.Node
= 0 then
1034 raise Constraint_Error
with
1035 "Position cursor of Query_Element equals No_Element";
1038 pragma Assert
(Vet
(Position
.Container
.all, Position
.Node
),
1039 "Position cursor of Query_Element is bad");
1042 M
: Map
renames Position
.Container
.all;
1043 N
: Node_Type
renames M
.Nodes
(Position
.Node
);
1045 B
: Natural renames M
.Busy
;
1046 L
: Natural renames M
.Lock
;
1053 Process
(N
.Key
, N
.Element
);
1071 (Stream
: not null access Root_Stream_Type
'Class;
1072 Container
: out Map
)
1074 procedure Read_Element
(Node
: in out Node_Type
);
1075 pragma Inline
(Read_Element
);
1077 procedure Allocate
is
1078 new Tree_Operations
.Generic_Allocate
(Read_Element
);
1080 procedure Read_Elements
is
1081 new Tree_Operations
.Generic_Read
(Allocate
);
1087 procedure Read_Element
(Node
: in out Node_Type
) is
1089 Key_Type
'Read (Stream
, Node
.Key
);
1090 Element_Type
'Read (Stream
, Node
.Element
);
1093 -- Start of processing for Read
1096 Read_Elements
(Stream
, Container
);
1100 (Stream
: not null access Root_Stream_Type
'Class;
1104 raise Program_Error
with "attempt to stream map cursor";
1112 (Container
: in out Map
;
1114 New_Item
: Element_Type
)
1116 Node
: constant Count_Type
:= Key_Ops
.Find
(Container
, Key
);
1120 raise Constraint_Error
with "key not in map";
1123 if Container
.Lock
> 0 then
1124 raise Program_Error
with
1125 "attempt to tamper with elements (map is locked)";
1129 N
: Node_Type
renames Container
.Nodes
(Node
);
1133 N
.Element
:= New_Item
;
1137 ---------------------
1138 -- Replace_Element --
1139 ---------------------
1141 procedure Replace_Element
1142 (Container
: in out Map
;
1144 New_Item
: Element_Type
)
1147 if Position
.Node
= 0 then
1148 raise Constraint_Error
with
1149 "Position cursor of Replace_Element equals No_Element";
1152 if Position
.Container
/= Container
'Unrestricted_Access then
1153 raise Program_Error
with
1154 "Position cursor of Replace_Element designates wrong map";
1157 if Container
.Lock
> 0 then
1158 raise Program_Error
with
1159 "attempt to tamper with elements (map is locked)";
1162 pragma Assert
(Vet
(Container
, Position
.Node
),
1163 "Position cursor of Replace_Element is bad");
1165 Container
.Nodes
(Position
.Node
).Element
:= New_Item
;
1166 end Replace_Element
;
1168 ---------------------
1169 -- Reverse_Iterate --
1170 ---------------------
1172 procedure Reverse_Iterate
1174 Process
: not null access procedure (Position
: Cursor
))
1176 procedure Process_Node
(Node
: Count_Type
);
1177 pragma Inline
(Process_Node
);
1179 procedure Local_Reverse_Iterate
is
1180 new Tree_Operations
.Generic_Reverse_Iteration
(Process_Node
);
1186 procedure Process_Node
(Node
: Count_Type
) is
1188 Process
(Cursor
'(Container'Unrestricted_Access, Node));
1191 B : Natural renames Container'Unrestricted_Access.all.Busy;
1193 -- Start of processing for Reverse_Iterate
1199 Local_Reverse_Iterate (Container);
1207 end Reverse_Iterate;
1213 function Right (Node : Node_Type) return Count_Type is
1223 (Node : in out Node_Type;
1227 Node.Color := Color;
1234 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1243 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1245 Node.Parent := Parent;
1252 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1254 Node.Right := Right;
1257 --------------------
1258 -- Update_Element --
1259 --------------------
1261 procedure Update_Element
1262 (Container : in out Map;
1264 Process : not null access procedure (Key : Key_Type;
1265 Element : in out Element_Type))
1268 if Position.Node = 0 then
1269 raise Constraint_Error with
1270 "Position cursor of Update_Element equals No_Element";
1273 if Position.Container /= Container'Unrestricted_Access then
1274 raise Program_Error with
1275 "Position cursor of Update_Element designates wrong map";
1278 pragma Assert (Vet (Container, Position.Node),
1279 "Position cursor of Update_Element is bad");
1282 N : Node_Type renames Container.Nodes (Position.Node);
1283 B : Natural renames Container.Busy;
1284 L : Natural renames Container.Lock;
1291 Process (N.Key, N.Element);
1310 (Stream : not null access Root_Stream_Type'Class;
1313 procedure Write_Node
1314 (Stream : not null access Root_Stream_Type'Class;
1316 pragma Inline (Write_Node);
1318 procedure Write_Nodes is
1319 new Tree_Operations.Generic_Write (Write_Node);
1325 procedure Write_Node
1326 (Stream : not null access Root_Stream_Type'Class;
1330 Key_Type'Write (Stream, Node.Key);
1331 Element_Type'Write (Stream, Node.Element);
1334 -- Start of processing for Write
1337 Write_Nodes (Stream, Container);
1341 (Stream : not null access Root_Stream_Type'Class;
1345 raise Program_Error with "attempt to stream map cursor";
1348 end Ada.Containers.Bounded_Ordered_Maps;