PR testsuite/44195
[official-gcc.git] / gcc / ada / a-coorma.adb
blob934d9de658c56513a266c1554ea68a805dd7a405
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . O R D E R E D _ M A P S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2009, Free Software Foundation, Inc. --
10 -- --
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. --
17 -- --
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. --
21 -- --
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/>. --
26 -- --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada.Unchecked_Deallocation;
32 with Ada.Containers.Red_Black_Trees.Generic_Operations;
33 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
35 with Ada.Containers.Red_Black_Trees.Generic_Keys;
36 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
38 package body Ada.Containers.Ordered_Maps is
40 -----------------------------
41 -- Node Access Subprograms --
42 -----------------------------
44 -- These subprograms provide a functional interface to access fields
45 -- of a node, and a procedural interface for modifying these values.
47 function Color (Node : Node_Access) return Color_Type;
48 pragma Inline (Color);
50 function Left (Node : Node_Access) return Node_Access;
51 pragma Inline (Left);
53 function Parent (Node : Node_Access) return Node_Access;
54 pragma Inline (Parent);
56 function Right (Node : Node_Access) return Node_Access;
57 pragma Inline (Right);
59 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
60 pragma Inline (Set_Parent);
62 procedure Set_Left (Node : Node_Access; Left : Node_Access);
63 pragma Inline (Set_Left);
65 procedure Set_Right (Node : Node_Access; Right : Node_Access);
66 pragma Inline (Set_Right);
68 procedure Set_Color (Node : Node_Access; Color : Color_Type);
69 pragma Inline (Set_Color);
71 -----------------------
72 -- Local Subprograms --
73 -----------------------
75 function Copy_Node (Source : Node_Access) return Node_Access;
76 pragma Inline (Copy_Node);
78 procedure Free (X : in out Node_Access);
80 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
81 pragma Inline (Is_Equal_Node_Node);
83 function Is_Greater_Key_Node
84 (Left : Key_Type;
85 Right : Node_Access) return Boolean;
86 pragma Inline (Is_Greater_Key_Node);
88 function Is_Less_Key_Node
89 (Left : Key_Type;
90 Right : Node_Access) return Boolean;
91 pragma Inline (Is_Less_Key_Node);
93 --------------------------
94 -- Local Instantiations --
95 --------------------------
97 package Tree_Operations is
98 new Red_Black_Trees.Generic_Operations (Tree_Types);
100 procedure Delete_Tree is
101 new Tree_Operations.Generic_Delete_Tree (Free);
103 function Copy_Tree is
104 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
106 use Tree_Operations;
108 package Key_Ops is
109 new Red_Black_Trees.Generic_Keys
110 (Tree_Operations => Tree_Operations,
111 Key_Type => Key_Type,
112 Is_Less_Key_Node => Is_Less_Key_Node,
113 Is_Greater_Key_Node => Is_Greater_Key_Node);
115 function Is_Equal is
116 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
118 ---------
119 -- "<" --
120 ---------
122 function "<" (Left, Right : Cursor) return Boolean is
123 begin
124 if Left.Node = null then
125 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
126 end if;
128 if Right.Node = null then
129 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
130 end if;
132 pragma Assert (Vet (Left.Container.Tree, Left.Node),
133 "Left cursor of ""<"" is bad");
135 pragma Assert (Vet (Right.Container.Tree, Right.Node),
136 "Right cursor of ""<"" is bad");
138 return Left.Node.Key < Right.Node.Key;
139 end "<";
141 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
142 begin
143 if Left.Node = null then
144 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
145 end if;
147 pragma Assert (Vet (Left.Container.Tree, Left.Node),
148 "Left cursor of ""<"" is bad");
150 return Left.Node.Key < Right;
151 end "<";
153 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
154 begin
155 if Right.Node = null then
156 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
157 end if;
159 pragma Assert (Vet (Right.Container.Tree, Right.Node),
160 "Right cursor of ""<"" is bad");
162 return Left < Right.Node.Key;
163 end "<";
165 ---------
166 -- "=" --
167 ---------
169 function "=" (Left, Right : Map) return Boolean is
170 begin
171 return Is_Equal (Left.Tree, Right.Tree);
172 end "=";
174 ---------
175 -- ">" --
176 ---------
178 function ">" (Left, Right : Cursor) return Boolean is
179 begin
180 if Left.Node = null then
181 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
182 end if;
184 if Right.Node = null then
185 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
186 end if;
188 pragma Assert (Vet (Left.Container.Tree, Left.Node),
189 "Left cursor of "">"" is bad");
191 pragma Assert (Vet (Right.Container.Tree, Right.Node),
192 "Right cursor of "">"" is bad");
194 return Right.Node.Key < Left.Node.Key;
195 end ">";
197 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
198 begin
199 if Left.Node = null then
200 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
201 end if;
203 pragma Assert (Vet (Left.Container.Tree, Left.Node),
204 "Left cursor of "">"" is bad");
206 return Right < Left.Node.Key;
207 end ">";
209 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
210 begin
211 if Right.Node = null then
212 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
213 end if;
215 pragma Assert (Vet (Right.Container.Tree, Right.Node),
216 "Right cursor of "">"" is bad");
218 return Right.Node.Key < Left;
219 end ">";
221 ------------
222 -- Adjust --
223 ------------
225 procedure Adjust is
226 new Tree_Operations.Generic_Adjust (Copy_Tree);
228 procedure Adjust (Container : in out Map) is
229 begin
230 Adjust (Container.Tree);
231 end Adjust;
233 -------------
234 -- Ceiling --
235 -------------
237 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
238 Node : constant Node_Access := Key_Ops.Ceiling (Container.Tree, Key);
240 begin
241 if Node = null then
242 return No_Element;
243 end if;
245 return Cursor'(Container'Unrestricted_Access, Node);
246 end Ceiling;
248 -----------
249 -- Clear --
250 -----------
252 procedure Clear is
253 new Tree_Operations.Generic_Clear (Delete_Tree);
255 procedure Clear (Container : in out Map) is
256 begin
257 Clear (Container.Tree);
258 end Clear;
260 -----------
261 -- Color --
262 -----------
264 function Color (Node : Node_Access) return Color_Type is
265 begin
266 return Node.Color;
267 end Color;
269 --------------
270 -- Contains --
271 --------------
273 function Contains (Container : Map; Key : Key_Type) return Boolean is
274 begin
275 return Find (Container, Key) /= No_Element;
276 end Contains;
278 ---------------
279 -- Copy_Node --
280 ---------------
282 function Copy_Node (Source : Node_Access) return Node_Access is
283 Target : constant Node_Access :=
284 new Node_Type'(Color => Source.Color,
285 Key => Source.Key,
286 Element => Source.Element,
287 Parent => null,
288 Left => null,
289 Right => null);
290 begin
291 return Target;
292 end Copy_Node;
294 ------------
295 -- Delete --
296 ------------
298 procedure Delete (Container : in out Map; Position : in out Cursor) is
299 Tree : Tree_Type renames Container.Tree;
301 begin
302 if Position.Node = null then
303 raise Constraint_Error with
304 "Position cursor of Delete equals No_Element";
305 end if;
307 if Position.Container /= Container'Unrestricted_Access then
308 raise Program_Error with
309 "Position cursor of Delete designates wrong map";
310 end if;
312 pragma Assert (Vet (Tree, Position.Node),
313 "Position cursor of Delete is bad");
315 Tree_Operations.Delete_Node_Sans_Free (Tree, Position.Node);
316 Free (Position.Node);
318 Position.Container := null;
319 end Delete;
321 procedure Delete (Container : in out Map; Key : Key_Type) is
322 X : Node_Access := Key_Ops.Find (Container.Tree, Key);
324 begin
325 if X = null then
326 raise Constraint_Error with "key not in map";
327 end if;
329 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
330 Free (X);
331 end Delete;
333 ------------------
334 -- Delete_First --
335 ------------------
337 procedure Delete_First (Container : in out Map) is
338 X : Node_Access := Container.Tree.First;
340 begin
341 if X /= null then
342 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
343 Free (X);
344 end if;
345 end Delete_First;
347 -----------------
348 -- Delete_Last --
349 -----------------
351 procedure Delete_Last (Container : in out Map) is
352 X : Node_Access := Container.Tree.Last;
354 begin
355 if X /= null then
356 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
357 Free (X);
358 end if;
359 end Delete_Last;
361 -------------
362 -- Element --
363 -------------
365 function Element (Position : Cursor) return Element_Type is
366 begin
367 if Position.Node = null then
368 raise Constraint_Error with
369 "Position cursor of function Element equals No_Element";
370 end if;
372 pragma Assert (Vet (Position.Container.Tree, Position.Node),
373 "Position cursor of function Element is bad");
375 return Position.Node.Element;
376 end Element;
378 function Element (Container : Map; Key : Key_Type) return Element_Type is
379 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
381 begin
382 if Node = null then
383 raise Constraint_Error with "key not in map";
384 end if;
386 return Node.Element;
387 end Element;
389 ---------------------
390 -- Equivalent_Keys --
391 ---------------------
393 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
394 begin
395 if Left < Right
396 or else Right < Left
397 then
398 return False;
399 else
400 return True;
401 end if;
402 end Equivalent_Keys;
404 -------------
405 -- Exclude --
406 -------------
408 procedure Exclude (Container : in out Map; Key : Key_Type) is
409 X : Node_Access := Key_Ops.Find (Container.Tree, Key);
411 begin
412 if X /= null then
413 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
414 Free (X);
415 end if;
416 end Exclude;
418 ----------
419 -- Find --
420 ----------
422 function Find (Container : Map; Key : Key_Type) return Cursor is
423 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
425 begin
426 if Node = null then
427 return No_Element;
428 end if;
430 return Cursor'(Container'Unrestricted_Access, Node);
431 end Find;
433 -----------
434 -- First --
435 -----------
437 function First (Container : Map) return Cursor is
438 T : Tree_Type renames Container.Tree;
440 begin
441 if T.First = null then
442 return No_Element;
443 end if;
445 return Cursor'(Container'Unrestricted_Access, T.First);
446 end First;
448 -------------------
449 -- First_Element --
450 -------------------
452 function First_Element (Container : Map) return Element_Type is
453 T : Tree_Type renames Container.Tree;
455 begin
456 if T.First = null then
457 raise Constraint_Error with "map is empty";
458 end if;
460 return T.First.Element;
461 end First_Element;
463 ---------------
464 -- First_Key --
465 ---------------
467 function First_Key (Container : Map) return Key_Type is
468 T : Tree_Type renames Container.Tree;
470 begin
471 if T.First = null then
472 raise Constraint_Error with "map is empty";
473 end if;
475 return T.First.Key;
476 end First_Key;
478 -----------
479 -- Floor --
480 -----------
482 function Floor (Container : Map; Key : Key_Type) return Cursor is
483 Node : constant Node_Access := Key_Ops.Floor (Container.Tree, Key);
485 begin
486 if Node = null then
487 return No_Element;
488 end if;
490 return Cursor'(Container'Unrestricted_Access, Node);
491 end Floor;
493 ----------
494 -- Free --
495 ----------
497 procedure Free (X : in out Node_Access) is
498 procedure Deallocate is
499 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
501 begin
502 if X = null then
503 return;
504 end if;
506 X.Parent := X;
507 X.Left := X;
508 X.Right := X;
510 Deallocate (X);
511 end Free;
513 -----------------
514 -- Has_Element --
515 -----------------
517 function Has_Element (Position : Cursor) return Boolean is
518 begin
519 return Position /= No_Element;
520 end Has_Element;
522 -------------
523 -- Include --
524 -------------
526 procedure Include
527 (Container : in out Map;
528 Key : Key_Type;
529 New_Item : Element_Type)
531 Position : Cursor;
532 Inserted : Boolean;
534 begin
535 Insert (Container, Key, New_Item, Position, Inserted);
537 if not Inserted then
538 if Container.Tree.Lock > 0 then
539 raise Program_Error with
540 "attempt to tamper with cursors (map is locked)";
541 end if;
543 Position.Node.Key := Key;
544 Position.Node.Element := New_Item;
545 end if;
546 end Include;
548 ------------
549 -- Insert --
550 ------------
552 procedure Insert
553 (Container : in out Map;
554 Key : Key_Type;
555 New_Item : Element_Type;
556 Position : out Cursor;
557 Inserted : out Boolean)
559 function New_Node return Node_Access;
560 pragma Inline (New_Node);
562 procedure Insert_Post is
563 new Key_Ops.Generic_Insert_Post (New_Node);
565 procedure Insert_Sans_Hint is
566 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
568 --------------
569 -- New_Node --
570 --------------
572 function New_Node return Node_Access is
573 begin
574 return new Node_Type'(Key => Key,
575 Element => New_Item,
576 Color => Red_Black_Trees.Red,
577 Parent => null,
578 Left => null,
579 Right => null);
580 end New_Node;
582 -- Start of processing for Insert
584 begin
585 Insert_Sans_Hint
586 (Container.Tree,
587 Key,
588 Position.Node,
589 Inserted);
591 Position.Container := Container'Unrestricted_Access;
592 end Insert;
594 procedure Insert
595 (Container : in out Map;
596 Key : Key_Type;
597 New_Item : Element_Type)
599 Position : Cursor;
600 pragma Unreferenced (Position);
602 Inserted : Boolean;
604 begin
605 Insert (Container, Key, New_Item, Position, Inserted);
607 if not Inserted then
608 raise Constraint_Error with "key already in map";
609 end if;
610 end Insert;
612 procedure Insert
613 (Container : in out Map;
614 Key : Key_Type;
615 Position : out Cursor;
616 Inserted : out Boolean)
618 function New_Node return Node_Access;
619 pragma Inline (New_Node);
621 procedure Insert_Post is
622 new Key_Ops.Generic_Insert_Post (New_Node);
624 procedure Insert_Sans_Hint is
625 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
627 --------------
628 -- New_Node --
629 --------------
631 function New_Node return Node_Access is
632 begin
633 return new Node_Type'(Key => Key,
634 Element => <>,
635 Color => Red_Black_Trees.Red,
636 Parent => null,
637 Left => null,
638 Right => null);
639 end New_Node;
641 -- Start of processing for Insert
643 begin
644 Insert_Sans_Hint
645 (Container.Tree,
646 Key,
647 Position.Node,
648 Inserted);
650 Position.Container := Container'Unrestricted_Access;
651 end Insert;
653 --------------
654 -- Is_Empty --
655 --------------
657 function Is_Empty (Container : Map) return Boolean is
658 begin
659 return Container.Tree.Length = 0;
660 end Is_Empty;
662 ------------------------
663 -- Is_Equal_Node_Node --
664 ------------------------
666 function Is_Equal_Node_Node
667 (L, R : Node_Access) return Boolean is
668 begin
669 if L.Key < R.Key then
670 return False;
672 elsif R.Key < L.Key then
673 return False;
675 else
676 return L.Element = R.Element;
677 end if;
678 end Is_Equal_Node_Node;
680 -------------------------
681 -- Is_Greater_Key_Node --
682 -------------------------
684 function Is_Greater_Key_Node
685 (Left : Key_Type;
686 Right : Node_Access) return Boolean
688 begin
689 -- k > node same as node < k
691 return Right.Key < Left;
692 end Is_Greater_Key_Node;
694 ----------------------
695 -- Is_Less_Key_Node --
696 ----------------------
698 function Is_Less_Key_Node
699 (Left : Key_Type;
700 Right : Node_Access) return Boolean
702 begin
703 return Left < Right.Key;
704 end Is_Less_Key_Node;
706 -------------
707 -- Iterate --
708 -------------
710 procedure Iterate
711 (Container : Map;
712 Process : not null access procedure (Position : Cursor))
714 procedure Process_Node (Node : Node_Access);
715 pragma Inline (Process_Node);
717 procedure Local_Iterate is
718 new Tree_Operations.Generic_Iteration (Process_Node);
720 ------------------
721 -- Process_Node --
722 ------------------
724 procedure Process_Node (Node : Node_Access) is
725 begin
726 Process (Cursor'(Container'Unrestricted_Access, Node));
727 end Process_Node;
729 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
731 -- Start of processing for Iterate
733 begin
734 B := B + 1;
736 begin
737 Local_Iterate (Container.Tree);
738 exception
739 when others =>
740 B := B - 1;
741 raise;
742 end;
744 B := B - 1;
745 end Iterate;
747 ---------
748 -- Key --
749 ---------
751 function Key (Position : Cursor) return Key_Type is
752 begin
753 if Position.Node = null then
754 raise Constraint_Error with
755 "Position cursor of function Key equals No_Element";
756 end if;
758 pragma Assert (Vet (Position.Container.Tree, Position.Node),
759 "Position cursor of function Key is bad");
761 return Position.Node.Key;
762 end Key;
764 ----------
765 -- Last --
766 ----------
768 function Last (Container : Map) return Cursor is
769 T : Tree_Type renames Container.Tree;
771 begin
772 if T.Last = null then
773 return No_Element;
774 end if;
776 return Cursor'(Container'Unrestricted_Access, T.Last);
777 end Last;
779 ------------------
780 -- Last_Element --
781 ------------------
783 function Last_Element (Container : Map) return Element_Type is
784 T : Tree_Type renames Container.Tree;
786 begin
787 if T.Last = null then
788 raise Constraint_Error with "map is empty";
789 end if;
791 return T.Last.Element;
792 end Last_Element;
794 --------------
795 -- Last_Key --
796 --------------
798 function Last_Key (Container : Map) return Key_Type is
799 T : Tree_Type renames Container.Tree;
801 begin
802 if T.Last = null then
803 raise Constraint_Error with "map is empty";
804 end if;
806 return T.Last.Key;
807 end Last_Key;
809 ----------
810 -- Left --
811 ----------
813 function Left (Node : Node_Access) return Node_Access is
814 begin
815 return Node.Left;
816 end Left;
818 ------------
819 -- Length --
820 ------------
822 function Length (Container : Map) return Count_Type is
823 begin
824 return Container.Tree.Length;
825 end Length;
827 ----------
828 -- Move --
829 ----------
831 procedure Move is
832 new Tree_Operations.Generic_Move (Clear);
834 procedure Move (Target : in out Map; Source : in out Map) is
835 begin
836 Move (Target => Target.Tree, Source => Source.Tree);
837 end Move;
839 ----------
840 -- Next --
841 ----------
843 procedure Next (Position : in out Cursor) is
844 begin
845 Position := Next (Position);
846 end Next;
848 function Next (Position : Cursor) return Cursor is
849 begin
850 if Position = No_Element then
851 return No_Element;
852 end if;
854 pragma Assert (Vet (Position.Container.Tree, Position.Node),
855 "Position cursor of Next is bad");
857 declare
858 Node : constant Node_Access :=
859 Tree_Operations.Next (Position.Node);
861 begin
862 if Node = null then
863 return No_Element;
864 end if;
866 return Cursor'(Position.Container, Node);
867 end;
868 end Next;
870 ------------
871 -- Parent --
872 ------------
874 function Parent (Node : Node_Access) return Node_Access is
875 begin
876 return Node.Parent;
877 end Parent;
879 --------------
880 -- Previous --
881 --------------
883 procedure Previous (Position : in out Cursor) is
884 begin
885 Position := Previous (Position);
886 end Previous;
888 function Previous (Position : Cursor) return Cursor is
889 begin
890 if Position = No_Element then
891 return No_Element;
892 end if;
894 pragma Assert (Vet (Position.Container.Tree, Position.Node),
895 "Position cursor of Previous is bad");
897 declare
898 Node : constant Node_Access :=
899 Tree_Operations.Previous (Position.Node);
901 begin
902 if Node = null then
903 return No_Element;
904 end if;
906 return Cursor'(Position.Container, Node);
907 end;
908 end Previous;
910 -------------------
911 -- Query_Element --
912 -------------------
914 procedure Query_Element
915 (Position : Cursor;
916 Process : not null access procedure (Key : Key_Type;
917 Element : Element_Type))
919 begin
920 if Position.Node = null then
921 raise Constraint_Error with
922 "Position cursor of Query_Element equals No_Element";
923 end if;
925 pragma Assert (Vet (Position.Container.Tree, Position.Node),
926 "Position cursor of Query_Element is bad");
928 declare
929 T : Tree_Type renames Position.Container.Tree;
931 B : Natural renames T.Busy;
932 L : Natural renames T.Lock;
934 begin
935 B := B + 1;
936 L := L + 1;
938 declare
939 K : Key_Type renames Position.Node.Key;
940 E : Element_Type renames Position.Node.Element;
942 begin
943 Process (K, E);
944 exception
945 when others =>
946 L := L - 1;
947 B := B - 1;
948 raise;
949 end;
951 L := L - 1;
952 B := B - 1;
953 end;
954 end Query_Element;
956 ----------
957 -- Read --
958 ----------
960 procedure Read
961 (Stream : not null access Root_Stream_Type'Class;
962 Container : out Map)
964 function Read_Node
965 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
966 pragma Inline (Read_Node);
968 procedure Read is
969 new Tree_Operations.Generic_Read (Clear, Read_Node);
971 ---------------
972 -- Read_Node --
973 ---------------
975 function Read_Node
976 (Stream : not null access Root_Stream_Type'Class) return Node_Access
978 Node : Node_Access := new Node_Type;
979 begin
980 Key_Type'Read (Stream, Node.Key);
981 Element_Type'Read (Stream, Node.Element);
982 return Node;
983 exception
984 when others =>
985 Free (Node);
986 raise;
987 end Read_Node;
989 -- Start of processing for Read
991 begin
992 Read (Stream, Container.Tree);
993 end Read;
995 procedure Read
996 (Stream : not null access Root_Stream_Type'Class;
997 Item : out Cursor)
999 begin
1000 raise Program_Error with "attempt to stream map cursor";
1001 end Read;
1003 -------------
1004 -- Replace --
1005 -------------
1007 procedure Replace
1008 (Container : in out Map;
1009 Key : Key_Type;
1010 New_Item : Element_Type)
1012 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
1014 begin
1015 if Node = null then
1016 raise Constraint_Error with "key not in map";
1017 end if;
1019 if Container.Tree.Lock > 0 then
1020 raise Program_Error with
1021 "attempt to tamper with cursors (map is locked)";
1022 end if;
1024 Node.Key := Key;
1025 Node.Element := New_Item;
1026 end Replace;
1028 ---------------------
1029 -- Replace_Element --
1030 ---------------------
1032 procedure Replace_Element
1033 (Container : in out Map;
1034 Position : Cursor;
1035 New_Item : Element_Type)
1037 begin
1038 if Position.Node = null then
1039 raise Constraint_Error with
1040 "Position cursor of Replace_Element equals No_Element";
1041 end if;
1043 if Position.Container /= Container'Unrestricted_Access then
1044 raise Program_Error with
1045 "Position cursor of Replace_Element designates wrong map";
1046 end if;
1048 if Container.Tree.Lock > 0 then
1049 raise Program_Error with
1050 "attempt to tamper with cursors (map is locked)";
1051 end if;
1053 pragma Assert (Vet (Container.Tree, Position.Node),
1054 "Position cursor of Replace_Element is bad");
1056 Position.Node.Element := New_Item;
1057 end Replace_Element;
1059 ---------------------
1060 -- Reverse_Iterate --
1061 ---------------------
1063 procedure Reverse_Iterate
1064 (Container : Map;
1065 Process : not null access procedure (Position : Cursor))
1067 procedure Process_Node (Node : Node_Access);
1068 pragma Inline (Process_Node);
1070 procedure Local_Reverse_Iterate is
1071 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1073 ------------------
1074 -- Process_Node --
1075 ------------------
1077 procedure Process_Node (Node : Node_Access) is
1078 begin
1079 Process (Cursor'(Container'Unrestricted_Access, Node));
1080 end Process_Node;
1082 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
1084 -- Start of processing for Reverse_Iterate
1086 begin
1087 B := B + 1;
1089 begin
1090 Local_Reverse_Iterate (Container.Tree);
1091 exception
1092 when others =>
1093 B := B - 1;
1094 raise;
1095 end;
1097 B := B - 1;
1098 end Reverse_Iterate;
1100 -----------
1101 -- Right --
1102 -----------
1104 function Right (Node : Node_Access) return Node_Access is
1105 begin
1106 return Node.Right;
1107 end Right;
1109 ---------------
1110 -- Set_Color --
1111 ---------------
1113 procedure Set_Color
1114 (Node : Node_Access;
1115 Color : Color_Type)
1117 begin
1118 Node.Color := Color;
1119 end Set_Color;
1121 --------------
1122 -- Set_Left --
1123 --------------
1125 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1126 begin
1127 Node.Left := Left;
1128 end Set_Left;
1130 ----------------
1131 -- Set_Parent --
1132 ----------------
1134 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1135 begin
1136 Node.Parent := Parent;
1137 end Set_Parent;
1139 ---------------
1140 -- Set_Right --
1141 ---------------
1143 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1144 begin
1145 Node.Right := Right;
1146 end Set_Right;
1148 --------------------
1149 -- Update_Element --
1150 --------------------
1152 procedure Update_Element
1153 (Container : in out Map;
1154 Position : Cursor;
1155 Process : not null access procedure (Key : Key_Type;
1156 Element : in out Element_Type))
1158 begin
1159 if Position.Node = null then
1160 raise Constraint_Error with
1161 "Position cursor of Update_Element equals No_Element";
1162 end if;
1164 if Position.Container /= Container'Unrestricted_Access then
1165 raise Program_Error with
1166 "Position cursor of Update_Element designates wrong map";
1167 end if;
1169 pragma Assert (Vet (Container.Tree, Position.Node),
1170 "Position cursor of Update_Element is bad");
1172 declare
1173 T : Tree_Type renames Container.Tree;
1175 B : Natural renames T.Busy;
1176 L : Natural renames T.Lock;
1178 begin
1179 B := B + 1;
1180 L := L + 1;
1182 declare
1183 K : Key_Type renames Position.Node.Key;
1184 E : Element_Type renames Position.Node.Element;
1186 begin
1187 Process (K, E);
1189 exception
1190 when others =>
1191 L := L - 1;
1192 B := B - 1;
1193 raise;
1194 end;
1196 L := L - 1;
1197 B := B - 1;
1198 end;
1199 end Update_Element;
1201 -----------
1202 -- Write --
1203 -----------
1205 procedure Write
1206 (Stream : not null access Root_Stream_Type'Class;
1207 Container : Map)
1209 procedure Write_Node
1210 (Stream : not null access Root_Stream_Type'Class;
1211 Node : Node_Access);
1212 pragma Inline (Write_Node);
1214 procedure Write is
1215 new Tree_Operations.Generic_Write (Write_Node);
1217 ----------------
1218 -- Write_Node --
1219 ----------------
1221 procedure Write_Node
1222 (Stream : not null access Root_Stream_Type'Class;
1223 Node : Node_Access)
1225 begin
1226 Key_Type'Write (Stream, Node.Key);
1227 Element_Type'Write (Stream, Node.Element);
1228 end Write_Node;
1230 -- Start of processing for Write
1232 begin
1233 Write (Stream, Container.Tree);
1234 end Write;
1236 procedure Write
1237 (Stream : not null access Root_Stream_Type'Class;
1238 Item : Cursor)
1240 begin
1241 raise Program_Error with "attempt to stream map cursor";
1242 end Write;
1244 end Ada.Containers.Ordered_Maps;