fixing pr42337
[official-gcc.git] / gcc / ada / a-ciorma.adb
blob4093d610b9ae4255596ec4be6203c12b25e61e68
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_MAPS --
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.Indefinite_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
81 (L, R : Node_Access) return Boolean;
82 pragma Inline (Is_Equal_Node_Node);
84 function Is_Greater_Key_Node
85 (Left : Key_Type;
86 Right : Node_Access) return Boolean;
87 pragma Inline (Is_Greater_Key_Node);
89 function Is_Less_Key_Node
90 (Left : Key_Type;
91 Right : Node_Access) return Boolean;
92 pragma Inline (Is_Less_Key_Node);
94 --------------------------
95 -- Local Instantiations --
96 --------------------------
98 package Tree_Operations is
99 new Red_Black_Trees.Generic_Operations (Tree_Types);
101 procedure Delete_Tree is
102 new Tree_Operations.Generic_Delete_Tree (Free);
104 function Copy_Tree is
105 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
107 use Tree_Operations;
109 package Key_Ops is
110 new Red_Black_Trees.Generic_Keys
111 (Tree_Operations => Tree_Operations,
112 Key_Type => Key_Type,
113 Is_Less_Key_Node => Is_Less_Key_Node,
114 Is_Greater_Key_Node => Is_Greater_Key_Node);
116 procedure Free_Key is
117 new Ada.Unchecked_Deallocation (Key_Type, Key_Access);
119 procedure Free_Element is
120 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
122 function Is_Equal is
123 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
125 ---------
126 -- "<" --
127 ---------
129 function "<" (Left, Right : Cursor) return Boolean is
130 begin
131 if Left.Node = null then
132 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
133 end if;
135 if Right.Node = null then
136 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
137 end if;
139 if Left.Node.Key = null then
140 raise Program_Error with "Left cursor in ""<"" is bad";
141 end if;
143 if Right.Node.Key = null then
144 raise Program_Error with "Right cursor in ""<"" is bad";
145 end if;
147 pragma Assert (Vet (Left.Container.Tree, Left.Node),
148 "Left cursor in ""<"" is bad");
150 pragma Assert (Vet (Right.Container.Tree, Right.Node),
151 "Right cursor in ""<"" is bad");
153 return Left.Node.Key.all < Right.Node.Key.all;
154 end "<";
156 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
157 begin
158 if Left.Node = null then
159 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
160 end if;
162 if Left.Node.Key = null then
163 raise Program_Error with "Left cursor in ""<"" is bad";
164 end if;
166 pragma Assert (Vet (Left.Container.Tree, Left.Node),
167 "Left cursor in ""<"" is bad");
169 return Left.Node.Key.all < Right;
170 end "<";
172 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
173 begin
174 if Right.Node = null then
175 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
176 end if;
178 if Right.Node.Key = null then
179 raise Program_Error with "Right cursor in ""<"" is bad";
180 end if;
182 pragma Assert (Vet (Right.Container.Tree, Right.Node),
183 "Right cursor in ""<"" is bad");
185 return Left < Right.Node.Key.all;
186 end "<";
188 ---------
189 -- "=" --
190 ---------
192 function "=" (Left, Right : Map) return Boolean is
193 begin
194 return Is_Equal (Left.Tree, Right.Tree);
195 end "=";
197 ---------
198 -- ">" --
199 ---------
201 function ">" (Left, Right : Cursor) return Boolean is
202 begin
203 if Left.Node = null then
204 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
205 end if;
207 if Right.Node = null then
208 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
209 end if;
211 if Left.Node.Key = null then
212 raise Program_Error with "Left cursor in ""<"" is bad";
213 end if;
215 if Right.Node.Key = null then
216 raise Program_Error with "Right cursor in ""<"" is bad";
217 end if;
219 pragma Assert (Vet (Left.Container.Tree, Left.Node),
220 "Left cursor in "">"" is bad");
222 pragma Assert (Vet (Right.Container.Tree, Right.Node),
223 "Right cursor in "">"" is bad");
225 return Right.Node.Key.all < Left.Node.Key.all;
226 end ">";
228 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
229 begin
230 if Left.Node = null then
231 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
232 end if;
234 if Left.Node.Key = null then
235 raise Program_Error with "Left cursor in ""<"" is bad";
236 end if;
238 pragma Assert (Vet (Left.Container.Tree, Left.Node),
239 "Left cursor in "">"" is bad");
241 return Right < Left.Node.Key.all;
242 end ">";
244 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
245 begin
246 if Right.Node = null then
247 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
248 end if;
250 if Right.Node.Key = null then
251 raise Program_Error with "Right cursor in ""<"" is bad";
252 end if;
254 pragma Assert (Vet (Right.Container.Tree, Right.Node),
255 "Right cursor in "">"" is bad");
257 return Right.Node.Key.all < Left;
258 end ">";
260 ------------
261 -- Adjust --
262 ------------
264 procedure Adjust is
265 new Tree_Operations.Generic_Adjust (Copy_Tree);
267 procedure Adjust (Container : in out Map) is
268 begin
269 Adjust (Container.Tree);
270 end Adjust;
272 -------------
273 -- Ceiling --
274 -------------
276 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
277 Node : constant Node_Access := Key_Ops.Ceiling (Container.Tree, Key);
279 begin
280 if Node = null then
281 return No_Element;
282 end if;
284 return Cursor'(Container'Unrestricted_Access, Node);
285 end Ceiling;
287 -----------
288 -- Clear --
289 -----------
291 procedure Clear is
292 new Tree_Operations.Generic_Clear (Delete_Tree);
294 procedure Clear (Container : in out Map) is
295 begin
296 Clear (Container.Tree);
297 end Clear;
299 -----------
300 -- Color --
301 -----------
303 function Color (Node : Node_Access) return Color_Type is
304 begin
305 return Node.Color;
306 end Color;
308 --------------
309 -- Contains --
310 --------------
312 function Contains (Container : Map; Key : Key_Type) return Boolean is
313 begin
314 return Find (Container, Key) /= No_Element;
315 end Contains;
317 ---------------
318 -- Copy_Node --
319 ---------------
321 function Copy_Node (Source : Node_Access) return Node_Access is
322 K : Key_Access := new Key_Type'(Source.Key.all);
323 E : Element_Access;
324 begin
325 E := new Element_Type'(Source.Element.all);
327 return new Node_Type'(Parent => null,
328 Left => null,
329 Right => null,
330 Color => Source.Color,
331 Key => K,
332 Element => E);
333 exception
334 when others =>
335 Free_Key (K);
336 Free_Element (E);
337 raise;
338 end Copy_Node;
340 ------------
341 -- Delete --
342 ------------
344 procedure Delete
345 (Container : in out Map;
346 Position : in out Cursor)
348 begin
349 if Position.Node = null then
350 raise Constraint_Error with
351 "Position cursor of Delete equals No_Element";
352 end if;
354 if Position.Node.Key = null
355 or else Position.Node.Element = null
356 then
357 raise Program_Error with "Position cursor of Delete is bad";
358 end if;
360 if Position.Container /= Container'Unrestricted_Access then
361 raise Program_Error with
362 "Position cursor of Delete designates wrong map";
363 end if;
365 pragma Assert (Vet (Container.Tree, Position.Node),
366 "Position cursor of Delete is bad");
368 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
369 Free (Position.Node);
371 Position.Container := null;
372 end Delete;
374 procedure Delete (Container : in out Map; Key : Key_Type) is
375 X : Node_Access := Key_Ops.Find (Container.Tree, Key);
377 begin
378 if X = null then
379 raise Constraint_Error with "key not in map";
380 end if;
382 Delete_Node_Sans_Free (Container.Tree, X);
383 Free (X);
384 end Delete;
386 ------------------
387 -- Delete_First --
388 ------------------
390 procedure Delete_First (Container : in out Map) is
391 X : Node_Access := Container.Tree.First;
393 begin
394 if X /= null then
395 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
396 Free (X);
397 end if;
398 end Delete_First;
400 -----------------
401 -- Delete_Last --
402 -----------------
404 procedure Delete_Last (Container : in out Map) is
405 X : Node_Access := Container.Tree.Last;
407 begin
408 if X /= null then
409 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
410 Free (X);
411 end if;
412 end Delete_Last;
414 -------------
415 -- Element --
416 -------------
418 function Element (Position : Cursor) return Element_Type is
419 begin
420 if Position.Node = null then
421 raise Constraint_Error with
422 "Position cursor of function Element equals No_Element";
423 end if;
425 if Position.Node.Element = null then
426 raise Program_Error with
427 "Position cursor of function Element is bad";
428 end if;
430 pragma Assert (Vet (Position.Container.Tree, Position.Node),
431 "Position cursor of function Element is bad");
433 return Position.Node.Element.all;
434 end Element;
436 function Element (Container : Map; Key : Key_Type) return Element_Type is
437 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
439 begin
440 if Node = null then
441 raise Constraint_Error with "key not in map";
442 end if;
444 return Node.Element.all;
445 end Element;
447 ---------------------
448 -- Equivalent_Keys --
449 ---------------------
451 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
452 begin
453 if Left < Right
454 or else Right < Left
455 then
456 return False;
457 else
458 return True;
459 end if;
460 end Equivalent_Keys;
462 -------------
463 -- Exclude --
464 -------------
466 procedure Exclude (Container : in out Map; Key : Key_Type) is
467 X : Node_Access := Key_Ops.Find (Container.Tree, Key);
469 begin
470 if X /= null then
471 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
472 Free (X);
473 end if;
474 end Exclude;
476 ----------
477 -- Find --
478 ----------
480 function Find (Container : Map; Key : Key_Type) return Cursor is
481 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
483 begin
484 if Node = null then
485 return No_Element;
486 end if;
488 return Cursor'(Container'Unrestricted_Access, Node);
489 end Find;
491 -----------
492 -- First --
493 -----------
495 function First (Container : Map) return Cursor is
496 T : Tree_Type renames Container.Tree;
498 begin
499 if T.First = null then
500 return No_Element;
501 end if;
503 return Cursor'(Container'Unrestricted_Access, T.First);
504 end First;
506 -------------------
507 -- First_Element --
508 -------------------
510 function First_Element (Container : Map) return Element_Type is
511 T : Tree_Type renames Container.Tree;
513 begin
514 if T.First = null then
515 raise Constraint_Error with "map is empty";
516 end if;
518 return T.First.Element.all;
519 end First_Element;
521 ---------------
522 -- First_Key --
523 ---------------
525 function First_Key (Container : Map) return Key_Type is
526 T : Tree_Type renames Container.Tree;
528 begin
529 if T.First = null then
530 raise Constraint_Error with "map is empty";
531 end if;
533 return T.First.Key.all;
534 end First_Key;
536 -----------
537 -- Floor --
538 -----------
540 function Floor (Container : Map; Key : Key_Type) return Cursor is
541 Node : constant Node_Access := Key_Ops.Floor (Container.Tree, Key);
543 begin
544 if Node = null then
545 return No_Element;
546 end if;
548 return Cursor'(Container'Unrestricted_Access, Node);
549 end Floor;
551 ----------
552 -- Free --
553 ----------
555 procedure Free (X : in out Node_Access) is
556 procedure Deallocate is
557 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
559 begin
560 if X = null then
561 return;
562 end if;
564 X.Parent := X;
565 X.Left := X;
566 X.Right := X;
568 begin
569 Free_Key (X.Key);
570 exception
571 when others =>
572 X.Key := null;
574 begin
575 Free_Element (X.Element);
576 exception
577 when others =>
578 X.Element := null;
579 end;
581 Deallocate (X);
582 raise;
583 end;
585 begin
586 Free_Element (X.Element);
587 exception
588 when others =>
589 X.Element := null;
591 Deallocate (X);
592 raise;
593 end;
595 Deallocate (X);
596 end Free;
598 -----------------
599 -- Has_Element --
600 -----------------
602 function Has_Element (Position : Cursor) return Boolean is
603 begin
604 return Position /= No_Element;
605 end Has_Element;
607 -------------
608 -- Include --
609 -------------
611 procedure Include
612 (Container : in out Map;
613 Key : Key_Type;
614 New_Item : Element_Type)
616 Position : Cursor;
617 Inserted : Boolean;
619 K : Key_Access;
620 E : Element_Access;
622 begin
623 Insert (Container, Key, New_Item, Position, Inserted);
625 if not Inserted then
626 if Container.Tree.Lock > 0 then
627 raise Program_Error with
628 "attempt to tamper with cursors (map is locked)";
629 end if;
631 K := Position.Node.Key;
632 E := Position.Node.Element;
634 Position.Node.Key := new Key_Type'(Key);
636 begin
637 Position.Node.Element := new Element_Type'(New_Item);
638 exception
639 when others =>
640 Free_Key (K);
641 raise;
642 end;
644 Free_Key (K);
645 Free_Element (E);
646 end if;
647 end Include;
649 ------------
650 -- Insert --
651 ------------
653 procedure Insert
654 (Container : in out Map;
655 Key : Key_Type;
656 New_Item : Element_Type;
657 Position : out Cursor;
658 Inserted : out Boolean)
660 function New_Node return Node_Access;
661 pragma Inline (New_Node);
663 procedure Insert_Post is
664 new Key_Ops.Generic_Insert_Post (New_Node);
666 procedure Insert_Sans_Hint is
667 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
669 --------------
670 -- New_Node --
671 --------------
673 function New_Node return Node_Access is
674 Node : Node_Access := new Node_Type;
676 begin
677 Node.Key := new Key_Type'(Key);
678 Node.Element := new Element_Type'(New_Item);
679 return Node;
681 exception
682 when others =>
684 -- On exception, deallocate key and elem
686 Free (Node); -- Note that Free deallocates key and elem too
687 raise;
688 end New_Node;
690 -- Start of processing for Insert
692 begin
693 Insert_Sans_Hint
694 (Container.Tree,
695 Key,
696 Position.Node,
697 Inserted);
699 Position.Container := Container'Unrestricted_Access;
700 end Insert;
702 procedure Insert
703 (Container : in out Map;
704 Key : Key_Type;
705 New_Item : Element_Type)
707 Position : Cursor;
708 pragma Unreferenced (Position);
710 Inserted : Boolean;
712 begin
713 Insert (Container, Key, New_Item, Position, Inserted);
715 if not Inserted then
716 raise Constraint_Error with "key already in map";
717 end if;
718 end Insert;
720 --------------
721 -- Is_Empty --
722 --------------
724 function Is_Empty (Container : Map) return Boolean is
725 begin
726 return Container.Tree.Length = 0;
727 end Is_Empty;
729 ------------------------
730 -- Is_Equal_Node_Node --
731 ------------------------
733 function Is_Equal_Node_Node
734 (L, R : Node_Access) return Boolean is
735 begin
736 if L.Key.all < R.Key.all then
737 return False;
739 elsif R.Key.all < L.Key.all then
740 return False;
742 else
743 return L.Element.all = R.Element.all;
744 end if;
745 end Is_Equal_Node_Node;
747 -------------------------
748 -- Is_Greater_Key_Node --
749 -------------------------
751 function Is_Greater_Key_Node
752 (Left : Key_Type;
753 Right : Node_Access) return Boolean
755 begin
756 -- k > node same as node < k
758 return Right.Key.all < Left;
759 end Is_Greater_Key_Node;
761 ----------------------
762 -- Is_Less_Key_Node --
763 ----------------------
765 function Is_Less_Key_Node
766 (Left : Key_Type;
767 Right : Node_Access) return Boolean is
768 begin
769 return Left < Right.Key.all;
770 end Is_Less_Key_Node;
772 -------------
773 -- Iterate --
774 -------------
776 procedure Iterate
777 (Container : Map;
778 Process : not null access procedure (Position : Cursor))
780 procedure Process_Node (Node : Node_Access);
781 pragma Inline (Process_Node);
783 procedure Local_Iterate is
784 new Tree_Operations.Generic_Iteration (Process_Node);
786 ------------------
787 -- Process_Node --
788 ------------------
790 procedure Process_Node (Node : Node_Access) is
791 begin
792 Process (Cursor'(Container'Unrestricted_Access, Node));
793 end Process_Node;
795 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
797 -- Start of processing for Iterate
799 begin
800 B := B + 1;
802 begin
803 Local_Iterate (Container.Tree);
804 exception
805 when others =>
806 B := B - 1;
807 raise;
808 end;
810 B := B - 1;
811 end Iterate;
813 ---------
814 -- Key --
815 ---------
817 function Key (Position : Cursor) return Key_Type is
818 begin
819 if Position.Node = null then
820 raise Constraint_Error with
821 "Position cursor of function Key equals No_Element";
822 end if;
824 if Position.Node.Key = null then
825 raise Program_Error with
826 "Position cursor of function Key is bad";
827 end if;
829 pragma Assert (Vet (Position.Container.Tree, Position.Node),
830 "Position cursor of function Key is bad");
832 return Position.Node.Key.all;
833 end Key;
835 ----------
836 -- Last --
837 ----------
839 function Last (Container : Map) return Cursor is
840 T : Tree_Type renames Container.Tree;
842 begin
843 if T.Last = null then
844 return No_Element;
845 end if;
847 return Cursor'(Container'Unrestricted_Access, T.Last);
848 end Last;
850 ------------------
851 -- Last_Element --
852 ------------------
854 function Last_Element (Container : Map) return Element_Type is
855 T : Tree_Type renames Container.Tree;
857 begin
858 if T.Last = null then
859 raise Constraint_Error with "map is empty";
860 end if;
862 return T.Last.Element.all;
863 end Last_Element;
865 --------------
866 -- Last_Key --
867 --------------
869 function Last_Key (Container : Map) return Key_Type is
870 T : Tree_Type renames Container.Tree;
872 begin
873 if T.Last = null then
874 raise Constraint_Error with "map is empty";
875 end if;
877 return T.Last.Key.all;
878 end Last_Key;
880 ----------
881 -- Left --
882 ----------
884 function Left (Node : Node_Access) return Node_Access is
885 begin
886 return Node.Left;
887 end Left;
889 ------------
890 -- Length --
891 ------------
893 function Length (Container : Map) return Count_Type is
894 begin
895 return Container.Tree.Length;
896 end Length;
898 ----------
899 -- Move --
900 ----------
902 procedure Move is
903 new Tree_Operations.Generic_Move (Clear);
905 procedure Move (Target : in out Map; Source : in out Map) is
906 begin
907 Move (Target => Target.Tree, Source => Source.Tree);
908 end Move;
910 ----------
911 -- Next --
912 ----------
914 function Next (Position : Cursor) return Cursor is
915 begin
916 if Position = No_Element then
917 return No_Element;
918 end if;
920 pragma Assert (Position.Node /= null);
921 pragma Assert (Position.Node.Key /= null);
922 pragma Assert (Position.Node.Element /= null);
923 pragma Assert (Vet (Position.Container.Tree, Position.Node),
924 "Position cursor of Next is bad");
926 declare
927 Node : constant Node_Access :=
928 Tree_Operations.Next (Position.Node);
930 begin
931 if Node = null then
932 return No_Element;
933 else
934 return Cursor'(Position.Container, Node);
935 end if;
936 end;
937 end Next;
939 procedure Next (Position : in out Cursor) is
940 begin
941 Position := Next (Position);
942 end Next;
944 ------------
945 -- Parent --
946 ------------
948 function Parent (Node : Node_Access) return Node_Access is
949 begin
950 return Node.Parent;
951 end Parent;
953 --------------
954 -- Previous --
955 --------------
957 function Previous (Position : Cursor) return Cursor is
958 begin
959 if Position = No_Element then
960 return No_Element;
961 end if;
963 pragma Assert (Position.Node /= null);
964 pragma Assert (Position.Node.Key /= null);
965 pragma Assert (Position.Node.Element /= null);
966 pragma Assert (Vet (Position.Container.Tree, Position.Node),
967 "Position cursor of Previous is bad");
969 declare
970 Node : constant Node_Access :=
971 Tree_Operations.Previous (Position.Node);
973 begin
974 if Node = null then
975 return No_Element;
976 end if;
978 return Cursor'(Position.Container, Node);
979 end;
980 end Previous;
982 procedure Previous (Position : in out Cursor) is
983 begin
984 Position := Previous (Position);
985 end Previous;
987 -------------------
988 -- Query_Element --
989 -------------------
991 procedure Query_Element
992 (Position : Cursor;
993 Process : not null access procedure (Key : Key_Type;
994 Element : Element_Type))
996 begin
997 if Position.Node = null then
998 raise Constraint_Error with
999 "Position cursor of Query_Element equals No_Element";
1000 end if;
1002 if Position.Node.Key = null
1003 or else Position.Node.Element = null
1004 then
1005 raise Program_Error with
1006 "Position cursor of Query_Element is bad";
1007 end if;
1009 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1010 "Position cursor of Query_Element is bad");
1012 declare
1013 T : Tree_Type renames Position.Container.Tree;
1015 B : Natural renames T.Busy;
1016 L : Natural renames T.Lock;
1018 begin
1019 B := B + 1;
1020 L := L + 1;
1022 declare
1023 K : Key_Type renames Position.Node.Key.all;
1024 E : Element_Type renames Position.Node.Element.all;
1026 begin
1027 Process (K, E);
1028 exception
1029 when others =>
1030 L := L - 1;
1031 B := B - 1;
1032 raise;
1033 end;
1035 L := L - 1;
1036 B := B - 1;
1037 end;
1038 end Query_Element;
1040 ----------
1041 -- Read --
1042 ----------
1044 procedure Read
1045 (Stream : not null access Root_Stream_Type'Class;
1046 Container : out Map)
1048 function Read_Node
1049 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1050 pragma Inline (Read_Node);
1052 procedure Read is
1053 new Tree_Operations.Generic_Read (Clear, Read_Node);
1055 ---------------
1056 -- Read_Node --
1057 ---------------
1059 function Read_Node
1060 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1062 Node : Node_Access := new Node_Type;
1063 begin
1064 Node.Key := new Key_Type'(Key_Type'Input (Stream));
1065 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1066 return Node;
1067 exception
1068 when others =>
1069 Free (Node); -- Note that Free deallocates key and elem too
1070 raise;
1071 end Read_Node;
1073 -- Start of processing for Read
1075 begin
1076 Read (Stream, Container.Tree);
1077 end Read;
1079 procedure Read
1080 (Stream : not null access Root_Stream_Type'Class;
1081 Item : out Cursor)
1083 begin
1084 raise Program_Error with "attempt to stream map cursor";
1085 end Read;
1087 -------------
1088 -- Replace --
1089 -------------
1091 procedure Replace
1092 (Container : in out Map;
1093 Key : Key_Type;
1094 New_Item : Element_Type)
1096 Node : constant Node_Access :=
1097 Key_Ops.Find (Container.Tree, Key);
1099 K : Key_Access;
1100 E : Element_Access;
1102 begin
1103 if Node = null then
1104 raise Constraint_Error with "key not in map";
1105 end if;
1107 if Container.Tree.Lock > 0 then
1108 raise Program_Error with
1109 "attempt to tamper with cursors (map is locked)";
1110 end if;
1112 K := Node.Key;
1113 E := Node.Element;
1115 Node.Key := new Key_Type'(Key);
1117 begin
1118 Node.Element := new Element_Type'(New_Item);
1119 exception
1120 when others =>
1121 Free_Key (K);
1122 raise;
1123 end;
1125 Free_Key (K);
1126 Free_Element (E);
1127 end Replace;
1129 ---------------------
1130 -- Replace_Element --
1131 ---------------------
1133 procedure Replace_Element
1134 (Container : in out Map;
1135 Position : Cursor;
1136 New_Item : Element_Type)
1138 begin
1139 if Position.Node = null then
1140 raise Constraint_Error with
1141 "Position cursor of Replace_Element equals No_Element";
1142 end if;
1144 if Position.Node.Key = null
1145 or else Position.Node.Element = null
1146 then
1147 raise Program_Error with
1148 "Position cursor of Replace_Element is bad";
1149 end if;
1151 if Position.Container /= Container'Unrestricted_Access then
1152 raise Program_Error with
1153 "Position cursor of Replace_Element designates wrong map";
1154 end if;
1156 if Container.Tree.Lock > 0 then
1157 raise Program_Error with
1158 "attempt to tamper with cursors (map is locked)";
1159 end if;
1161 pragma Assert (Vet (Container.Tree, Position.Node),
1162 "Position cursor of Replace_Element is bad");
1164 declare
1165 X : Element_Access := Position.Node.Element;
1167 begin
1168 Position.Node.Element := new Element_Type'(New_Item);
1169 Free_Element (X);
1170 end;
1171 end Replace_Element;
1173 ---------------------
1174 -- Reverse_Iterate --
1175 ---------------------
1177 procedure Reverse_Iterate
1178 (Container : Map;
1179 Process : not null access procedure (Position : Cursor))
1181 procedure Process_Node (Node : Node_Access);
1182 pragma Inline (Process_Node);
1184 procedure Local_Reverse_Iterate is
1185 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1187 ------------------
1188 -- Process_Node --
1189 ------------------
1191 procedure Process_Node (Node : Node_Access) is
1192 begin
1193 Process (Cursor'(Container'Unrestricted_Access, Node));
1194 end Process_Node;
1196 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
1198 -- Start of processing for Reverse_Iterate
1200 begin
1201 B := B + 1;
1203 begin
1204 Local_Reverse_Iterate (Container.Tree);
1205 exception
1206 when others =>
1207 B := B - 1;
1208 raise;
1209 end;
1211 B := B - 1;
1212 end Reverse_Iterate;
1214 -----------
1215 -- Right --
1216 -----------
1218 function Right (Node : Node_Access) return Node_Access is
1219 begin
1220 return Node.Right;
1221 end Right;
1223 ---------------
1224 -- Set_Color --
1225 ---------------
1227 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1228 begin
1229 Node.Color := Color;
1230 end Set_Color;
1232 --------------
1233 -- Set_Left --
1234 --------------
1236 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1237 begin
1238 Node.Left := Left;
1239 end Set_Left;
1241 ----------------
1242 -- Set_Parent --
1243 ----------------
1245 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1246 begin
1247 Node.Parent := Parent;
1248 end Set_Parent;
1250 ---------------
1251 -- Set_Right --
1252 ---------------
1254 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1255 begin
1256 Node.Right := Right;
1257 end Set_Right;
1259 --------------------
1260 -- Update_Element --
1261 --------------------
1263 procedure Update_Element
1264 (Container : in out Map;
1265 Position : Cursor;
1266 Process : not null access procedure (Key : Key_Type;
1267 Element : in out Element_Type))
1269 begin
1270 if Position.Node = null then
1271 raise Constraint_Error with
1272 "Position cursor of Update_Element equals No_Element";
1273 end if;
1275 if Position.Node.Key = null
1276 or else Position.Node.Element = null
1277 then
1278 raise Program_Error with
1279 "Position cursor of Update_Element is bad";
1280 end if;
1282 if Position.Container /= Container'Unrestricted_Access then
1283 raise Program_Error with
1284 "Position cursor of Update_Element designates wrong map";
1285 end if;
1287 pragma Assert (Vet (Container.Tree, Position.Node),
1288 "Position cursor of Update_Element is bad");
1290 declare
1291 T : Tree_Type renames Position.Container.Tree;
1293 B : Natural renames T.Busy;
1294 L : Natural renames T.Lock;
1296 begin
1297 B := B + 1;
1298 L := L + 1;
1300 declare
1301 K : Key_Type renames Position.Node.Key.all;
1302 E : Element_Type renames Position.Node.Element.all;
1304 begin
1305 Process (K, E);
1307 exception
1308 when others =>
1309 L := L - 1;
1310 B := B - 1;
1311 raise;
1312 end;
1314 L := L - 1;
1315 B := B - 1;
1316 end;
1317 end Update_Element;
1319 -----------
1320 -- Write --
1321 -----------
1323 procedure Write
1324 (Stream : not null access Root_Stream_Type'Class;
1325 Container : Map)
1327 procedure Write_Node
1328 (Stream : not null access Root_Stream_Type'Class;
1329 Node : Node_Access);
1330 pragma Inline (Write_Node);
1332 procedure Write is
1333 new Tree_Operations.Generic_Write (Write_Node);
1335 ----------------
1336 -- Write_Node --
1337 ----------------
1339 procedure Write_Node
1340 (Stream : not null access Root_Stream_Type'Class;
1341 Node : Node_Access)
1343 begin
1344 Key_Type'Output (Stream, Node.Key.all);
1345 Element_Type'Output (Stream, Node.Element.all);
1346 end Write_Node;
1348 -- Start of processing for Write
1350 begin
1351 Write (Stream, Container.Tree);
1352 end Write;
1354 procedure Write
1355 (Stream : not null access Root_Stream_Type'Class;
1356 Item : Cursor)
1358 begin
1359 raise Program_Error with "attempt to stream map cursor";
1360 end Write;
1362 end Ada.Containers.Indefinite_Ordered_Maps;