* config/rs6000/rs6000.c (rs6000_option_override_internal): Do not
[official-gcc.git] / gcc / ada / a-cforma.adb
blob6b45ad6036910bb51a8dab7ad5b755d56a53bd72
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . F O R M A L _ O R D E R E D _ M A P S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2010-2012, 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 ------------------------------------------------------------------------------
28 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations;
29 pragma Elaborate_All
30 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations);
32 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
33 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
35 with System; use type System.Address;
37 package body Ada.Containers.Formal_Ordered_Maps is
39 -----------------------------
40 -- Node Access Subprograms --
41 -----------------------------
43 -- These subprograms provide a functional interface to access fields
44 -- of a node, and a procedural interface for modifying these values.
46 function Color
47 (Node : Node_Type) return Ada.Containers.Red_Black_Trees.Color_Type;
48 pragma Inline (Color);
50 function Left_Son (Node : Node_Type) return Count_Type;
51 pragma Inline (Left);
53 function Parent (Node : Node_Type) return Count_Type;
54 pragma Inline (Parent);
56 function Right_Son (Node : Node_Type) return Count_Type;
57 pragma Inline (Right);
59 procedure Set_Color
60 (Node : in out Node_Type;
61 Color : Ada.Containers.Red_Black_Trees.Color_Type);
62 pragma Inline (Set_Color);
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_Parent (Node : in out Node_Type; Parent : Count_Type);
71 pragma Inline (Set_Parent);
73 -----------------------
74 -- Local Subprograms --
75 -----------------------
77 -- All need comments ???
79 generic
80 with procedure Set_Element (Node : in out Node_Type);
81 procedure Generic_Allocate
82 (Tree : in out Tree_Types.Tree_Type'Class;
83 Node : out Count_Type);
85 procedure Free (Tree : in out Map; X : Count_Type);
87 function Is_Greater_Key_Node
88 (Left : Key_Type;
89 Right : Node_Type) return Boolean;
90 pragma Inline (Is_Greater_Key_Node);
92 function Is_Less_Key_Node
93 (Left : Key_Type;
94 Right : Node_Type) return Boolean;
95 pragma Inline (Is_Less_Key_Node);
97 --------------------------
98 -- Local Instantiations --
99 --------------------------
101 package Tree_Operations is
102 new Red_Black_Trees.Generic_Bounded_Operations
103 (Tree_Types => Tree_Types,
104 Left => Left_Son,
105 Right => Right_Son);
107 use Tree_Operations;
109 package Key_Ops is
110 new Red_Black_Trees.Generic_Bounded_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 ---------
117 -- "=" --
118 ---------
120 function "=" (Left, Right : Map) return Boolean is
121 Lst : Count_Type;
122 Node : Count_Type;
123 ENode : Count_Type;
125 begin
126 if Length (Left) /= Length (Right) then
127 return False;
128 end if;
130 if Is_Empty (Left) then
131 return True;
132 end if;
134 Lst := Next (Left, Last (Left).Node);
136 Node := First (Left).Node;
137 while Node /= Lst loop
138 ENode := Find (Right, Left.Nodes (Node).Key).Node;
140 if ENode = 0 or else
141 Left.Nodes (Node).Element /= Right.Nodes (ENode).Element
142 then
143 return False;
144 end if;
146 Node := Next (Left, Node);
147 end loop;
149 return True;
150 end "=";
152 ------------
153 -- Assign --
154 ------------
156 procedure Assign (Target : in out Map; Source : Map) is
157 procedure Append_Element (Source_Node : Count_Type);
159 procedure Append_Elements is
160 new Tree_Operations.Generic_Iteration (Append_Element);
162 --------------------
163 -- Append_Element --
164 --------------------
166 procedure Append_Element (Source_Node : Count_Type) is
167 SN : Node_Type renames Source.Nodes (Source_Node);
169 procedure Set_Element (Node : in out Node_Type);
170 pragma Inline (Set_Element);
172 function New_Node return Count_Type;
173 pragma Inline (New_Node);
175 procedure Insert_Post is new Key_Ops.Generic_Insert_Post (New_Node);
177 procedure Unconditional_Insert_Sans_Hint is
178 new Key_Ops.Generic_Unconditional_Insert (Insert_Post);
180 procedure Unconditional_Insert_Avec_Hint is
181 new Key_Ops.Generic_Unconditional_Insert_With_Hint
182 (Insert_Post,
183 Unconditional_Insert_Sans_Hint);
185 procedure Allocate is new Generic_Allocate (Set_Element);
187 --------------
188 -- New_Node --
189 --------------
191 function New_Node return Count_Type is
192 Result : Count_Type;
193 begin
194 Allocate (Target, Result);
195 return Result;
196 end New_Node;
198 -----------------
199 -- Set_Element --
200 -----------------
202 procedure Set_Element (Node : in out Node_Type) is
203 begin
204 Node.Key := SN.Key;
205 Node.Element := SN.Element;
206 end Set_Element;
208 Target_Node : Count_Type;
210 -- Start of processing for Append_Element
212 begin
213 Unconditional_Insert_Avec_Hint
214 (Tree => Target,
215 Hint => 0,
216 Key => SN.Key,
217 Node => Target_Node);
218 end Append_Element;
220 -- Start of processing for Assign
222 begin
223 if Target'Address = Source'Address then
224 return;
225 end if;
227 if Target.Capacity < Length (Source) then
228 raise Storage_Error with "not enough capacity"; -- SE or CE? ???
229 end if;
231 Tree_Operations.Clear_Tree (Target);
232 Append_Elements (Source);
233 end Assign;
235 -------------
236 -- Ceiling --
237 -------------
239 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
240 Node : constant Count_Type := Key_Ops.Ceiling (Container, Key);
242 begin
243 if Node = 0 then
244 return No_Element;
245 end if;
247 return (Node => Node);
248 end Ceiling;
250 -----------
251 -- Clear --
252 -----------
254 procedure Clear (Container : in out Map) is
255 begin
256 Tree_Operations.Clear_Tree (Container);
257 end Clear;
259 -----------
260 -- Color --
261 -----------
263 function Color (Node : Node_Type) return Color_Type is
264 begin
265 return Node.Color;
266 end Color;
268 --------------
269 -- Contains --
270 --------------
272 function Contains (Container : Map; Key : Key_Type) return Boolean is
273 begin
274 return Find (Container, Key) /= No_Element;
275 end Contains;
277 ----------
278 -- Copy --
279 ----------
281 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
282 Node : Count_Type := 1;
283 N : Count_Type;
285 begin
286 return Target : Map (Count_Type'Max (Source.Capacity, Capacity)) do
287 if Length (Source) > 0 then
288 Target.Length := Source.Length;
289 Target.Root := Source.Root;
290 Target.First := Source.First;
291 Target.Last := Source.Last;
292 Target.Free := Source.Free;
294 while Node <= Source.Capacity loop
295 Target.Nodes (Node).Element :=
296 Source.Nodes (Node).Element;
297 Target.Nodes (Node).Key :=
298 Source.Nodes (Node).Key;
299 Target.Nodes (Node).Parent :=
300 Source.Nodes (Node).Parent;
301 Target.Nodes (Node).Left :=
302 Source.Nodes (Node).Left;
303 Target.Nodes (Node).Right :=
304 Source.Nodes (Node).Right;
305 Target.Nodes (Node).Color :=
306 Source.Nodes (Node).Color;
307 Target.Nodes (Node).Has_Element :=
308 Source.Nodes (Node).Has_Element;
309 Node := Node + 1;
310 end loop;
312 while Node <= Target.Capacity loop
313 N := Node;
314 Formal_Ordered_Maps.Free (Tree => Target, X => N);
315 Node := Node + 1;
316 end loop;
317 end if;
318 end return;
319 end Copy;
321 ------------
322 -- Delete --
323 ------------
325 procedure Delete (Container : in out Map; Position : in out Cursor) is
326 begin
327 if not Has_Element (Container, Position) then
328 raise Constraint_Error with
329 "Position cursor of Delete has no element";
330 end if;
332 pragma Assert (Vet (Container, Position.Node),
333 "Position cursor of Delete is bad");
335 Tree_Operations.Delete_Node_Sans_Free (Container,
336 Position.Node);
337 Formal_Ordered_Maps.Free (Container, Position.Node);
338 end Delete;
340 procedure Delete (Container : in out Map; Key : Key_Type) is
341 X : constant Node_Access := Key_Ops.Find (Container, Key);
343 begin
344 if X = 0 then
345 raise Constraint_Error with "key not in map";
346 end if;
348 Tree_Operations.Delete_Node_Sans_Free (Container, X);
349 Formal_Ordered_Maps.Free (Container, X);
350 end Delete;
352 ------------------
353 -- Delete_First --
354 ------------------
356 procedure Delete_First (Container : in out Map) is
357 X : constant Node_Access := First (Container).Node;
358 begin
359 if X /= 0 then
360 Tree_Operations.Delete_Node_Sans_Free (Container, X);
361 Formal_Ordered_Maps.Free (Container, X);
362 end if;
363 end Delete_First;
365 -----------------
366 -- Delete_Last --
367 -----------------
369 procedure Delete_Last (Container : in out Map) is
370 X : constant Node_Access := Last (Container).Node;
371 begin
372 if X /= 0 then
373 Tree_Operations.Delete_Node_Sans_Free (Container, X);
374 Formal_Ordered_Maps.Free (Container, X);
375 end if;
376 end Delete_Last;
378 -------------
379 -- Element --
380 -------------
382 function Element (Container : Map; Position : Cursor) return Element_Type is
383 begin
384 if not Has_Element (Container, Position) then
385 raise Constraint_Error with
386 "Position cursor of function Element has no element";
387 end if;
389 pragma Assert (Vet (Container, Position.Node),
390 "Position cursor of function Element is bad");
392 return Container.Nodes (Position.Node).Element;
394 end Element;
396 function Element (Container : Map; Key : Key_Type) return Element_Type is
397 Node : constant Node_Access := Find (Container, Key).Node;
399 begin
400 if Node = 0 then
401 raise Constraint_Error with "key not in map";
402 end if;
404 return Container.Nodes (Node).Element;
405 end Element;
407 ---------------------
408 -- Equivalent_Keys --
409 ---------------------
411 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
412 begin
413 if Left < Right
414 or else Right < Left
415 then
416 return False;
417 else
418 return True;
419 end if;
420 end Equivalent_Keys;
422 -------------
423 -- Exclude --
424 -------------
426 procedure Exclude (Container : in out Map; Key : Key_Type) is
427 X : constant Node_Access := Key_Ops.Find (Container, Key);
428 begin
429 if X /= 0 then
430 Tree_Operations.Delete_Node_Sans_Free (Container, X);
431 Formal_Ordered_Maps.Free (Container, X);
432 end if;
433 end Exclude;
435 ----------
436 -- Find --
437 ----------
439 function Find (Container : Map; Key : Key_Type) return Cursor is
440 Node : constant Count_Type := Key_Ops.Find (Container, Key);
442 begin
443 if Node = 0 then
444 return No_Element;
445 end if;
447 return (Node => Node);
448 end Find;
450 -----------
451 -- First --
452 -----------
454 function First (Container : Map) return Cursor is
455 begin
456 if Length (Container) = 0 then
457 return No_Element;
458 end if;
460 return (Node => Container.First);
461 end First;
463 -------------------
464 -- First_Element --
465 -------------------
467 function First_Element (Container : Map) return Element_Type is
468 begin
469 if Is_Empty (Container) then
470 raise Constraint_Error with "map is empty";
471 end if;
473 return Container.Nodes (First (Container).Node).Element;
474 end First_Element;
476 ---------------
477 -- First_Key --
478 ---------------
480 function First_Key (Container : Map) return Key_Type is
481 begin
482 if Is_Empty (Container) then
483 raise Constraint_Error with "map is empty";
484 end if;
486 return Container.Nodes (First (Container).Node).Key;
487 end First_Key;
489 -----------
490 -- Floor --
491 -----------
493 function Floor (Container : Map; Key : Key_Type) return Cursor is
494 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
496 begin
497 if Node = 0 then
498 return No_Element;
499 end if;
501 return (Node => Node);
502 end Floor;
504 ----------
505 -- Free --
506 ----------
508 procedure Free
509 (Tree : in out Map;
510 X : Count_Type)
512 begin
513 Tree.Nodes (X).Has_Element := False;
514 Tree_Operations.Free (Tree, X);
515 end Free;
517 ----------------------
518 -- Generic_Allocate --
519 ----------------------
521 procedure Generic_Allocate
522 (Tree : in out Tree_Types.Tree_Type'Class;
523 Node : out Count_Type)
525 procedure Allocate is
526 new Tree_Operations.Generic_Allocate (Set_Element);
527 begin
528 Allocate (Tree, Node);
529 Tree.Nodes (Node).Has_Element := True;
530 end Generic_Allocate;
532 -----------------
533 -- Has_Element --
534 -----------------
536 function Has_Element (Container : Map; Position : Cursor) return Boolean is
537 begin
538 if Position.Node = 0 then
539 return False;
540 end if;
542 return Container.Nodes (Position.Node).Has_Element;
543 end Has_Element;
545 -------------
546 -- Include --
547 -------------
549 procedure Include
550 (Container : in out Map;
551 Key : Key_Type;
552 New_Item : Element_Type)
554 Position : Cursor;
555 Inserted : Boolean;
557 begin
558 Insert (Container, Key, New_Item, Position, Inserted);
560 if not Inserted then
561 if Container.Lock > 0 then
562 raise Program_Error with
563 "attempt to tamper with cursors (map is locked)";
564 end if;
566 declare
567 N : Node_Type renames Container.Nodes (Position.Node);
568 begin
569 N.Key := Key;
570 N.Element := New_Item;
571 end;
572 end if;
573 end Include;
575 procedure Insert
576 (Container : in out Map;
577 Key : Key_Type;
578 New_Item : Element_Type;
579 Position : out Cursor;
580 Inserted : out Boolean)
582 function New_Node return Node_Access;
583 -- Comment ???
585 procedure Insert_Post is
586 new Key_Ops.Generic_Insert_Post (New_Node);
588 procedure Insert_Sans_Hint is
589 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
591 --------------
592 -- New_Node --
593 --------------
595 function New_Node return Node_Access is
596 procedure Initialize (Node : in out Node_Type);
597 procedure Allocate_Node is new Generic_Allocate (Initialize);
599 procedure Initialize (Node : in out Node_Type) is
600 begin
601 Node.Key := Key;
602 Node.Element := New_Item;
603 end Initialize;
605 X : Node_Access;
607 begin
608 Allocate_Node (Container, X);
609 return X;
610 end New_Node;
612 -- Start of processing for Insert
614 begin
615 Insert_Sans_Hint
616 (Container,
617 Key,
618 Position.Node,
619 Inserted);
620 end Insert;
622 procedure Insert
623 (Container : in out Map;
624 Key : Key_Type;
625 New_Item : Element_Type)
627 Position : Cursor;
628 Inserted : Boolean;
630 begin
631 Insert (Container, Key, New_Item, Position, Inserted);
633 if not Inserted then
634 raise Constraint_Error with "key already in map";
635 end if;
636 end Insert;
638 ------------
639 -- Insert --
640 ------------
642 procedure Insert
643 (Container : in out Map;
644 Key : Key_Type;
645 Position : out Cursor;
646 Inserted : out Boolean)
648 function New_Node return Node_Access;
650 procedure Insert_Post is
651 new Key_Ops.Generic_Insert_Post (New_Node);
653 procedure Insert_Sans_Hint is
654 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
656 --------------
657 -- New_Node --
658 --------------
660 function New_Node return Node_Access is
661 procedure Initialize (Node : in out Node_Type);
662 procedure Allocate_Node is new Generic_Allocate (Initialize);
664 ----------------
665 -- Initialize --
666 ----------------
668 procedure Initialize (Node : in out Node_Type) is
669 begin
670 Node.Key := Key;
671 end Initialize;
673 X : Node_Access;
675 -- Start of processing for New_Node
677 begin
678 Allocate_Node (Container, X);
679 return X;
680 end New_Node;
682 -- Start of processing for Insert
684 begin
685 Insert_Sans_Hint (Container, Key, Position.Node, Inserted);
686 end Insert;
688 --------------
689 -- Is_Empty --
690 --------------
692 function Is_Empty (Container : Map) return Boolean is
693 begin
694 return Length (Container) = 0;
695 end Is_Empty;
697 -------------------------
698 -- Is_Greater_Key_Node --
699 -------------------------
701 function Is_Greater_Key_Node
702 (Left : Key_Type;
703 Right : Node_Type) return Boolean
705 begin
706 -- k > node same as node < k
708 return Right.Key < Left;
709 end Is_Greater_Key_Node;
711 ----------------------
712 -- Is_Less_Key_Node --
713 ----------------------
715 function Is_Less_Key_Node
716 (Left : Key_Type;
717 Right : Node_Type) return Boolean
719 begin
720 return Left < Right.Key;
721 end Is_Less_Key_Node;
723 -------------
724 -- Iterate --
725 -------------
727 procedure Iterate
728 (Container : Map;
729 Process :
730 not null access procedure (Container : Map; Position : Cursor))
732 procedure Process_Node (Node : Node_Access);
733 pragma Inline (Process_Node);
735 procedure Local_Iterate is
736 new Tree_Operations.Generic_Iteration (Process_Node);
738 ------------------
739 -- Process_Node --
740 ------------------
742 procedure Process_Node (Node : Node_Access) is
743 begin
744 Process (Container, (Node => Node));
745 end Process_Node;
747 B : Natural renames Container'Unrestricted_Access.Busy;
749 -- Start of processing for Iterate
751 begin
752 B := B + 1;
754 begin
755 Local_Iterate (Container);
756 exception
757 when others =>
758 B := B - 1;
759 raise;
760 end;
762 B := B - 1;
763 end Iterate;
765 ---------
766 -- Key --
767 ---------
769 function Key (Container : Map; Position : Cursor) return Key_Type is
770 begin
771 if not Has_Element (Container, Position) then
772 raise Constraint_Error with
773 "Position cursor of function Key has no element";
774 end if;
776 pragma Assert (Vet (Container, Position.Node),
777 "Position cursor of function Key is bad");
779 return Container.Nodes (Position.Node).Key;
780 end Key;
782 ----------
783 -- Last --
784 ----------
786 function Last (Container : Map) return Cursor is
787 begin
788 if Length (Container) = 0 then
789 return No_Element;
790 end if;
792 return (Node => Container.Last);
793 end Last;
795 ------------------
796 -- Last_Element --
797 ------------------
799 function Last_Element (Container : Map) return Element_Type is
800 begin
801 if Is_Empty (Container) then
802 raise Constraint_Error with "map is empty";
803 end if;
805 return Container.Nodes (Last (Container).Node).Element;
806 end Last_Element;
808 --------------
809 -- Last_Key --
810 --------------
812 function Last_Key (Container : Map) return Key_Type is
813 begin
814 if Is_Empty (Container) then
815 raise Constraint_Error with "map is empty";
816 end if;
818 return Container.Nodes (Last (Container).Node).Key;
819 end Last_Key;
821 ----------
822 -- Left --
823 ----------
825 function Left (Container : Map; Position : Cursor) return Map is
826 Curs : Cursor := Position;
827 C : Map (Container.Capacity) := Copy (Container, Container.Capacity);
828 Node : Count_Type;
830 begin
831 if Curs = No_Element then
832 return C;
833 end if;
835 if not Has_Element (Container, Curs) then
836 raise Constraint_Error;
837 end if;
839 while Curs.Node /= 0 loop
840 Node := Curs.Node;
841 Delete (C, Curs);
842 Curs := Next (Container, (Node => Node));
843 end loop;
845 return C;
846 end Left;
848 --------------
849 -- Left_Son --
850 --------------
852 function Left_Son (Node : Node_Type) return Count_Type is
853 begin
854 return Node.Left;
855 end Left_Son;
857 ------------
858 -- Length --
859 ------------
861 function Length (Container : Map) return Count_Type is
862 begin
863 return Container.Length;
864 end Length;
866 ----------
867 -- Move --
868 ----------
870 procedure Move (Target : in out Map; Source : in out Map) is
871 NN : Tree_Types.Nodes_Type renames Source.Nodes;
872 X : Node_Access;
874 begin
875 if Target'Address = Source'Address then
876 return;
877 end if;
879 if Target.Capacity < Length (Source) then
880 raise Constraint_Error with -- ???
881 "Source length exceeds Target capacity";
882 end if;
884 if Source.Busy > 0 then
885 raise Program_Error with
886 "attempt to tamper with cursors of Source (list is busy)";
887 end if;
889 Clear (Target);
891 loop
892 X := First (Source).Node;
893 exit when X = 0;
895 -- Here we insert a copy of the source element into the target, and
896 -- then delete the element from the source. Another possibility is
897 -- that delete it first (and hang onto its index), then insert it.
898 -- ???
900 Insert (Target, NN (X).Key, NN (X).Element); -- optimize???
902 Tree_Operations.Delete_Node_Sans_Free (Source, X);
903 Formal_Ordered_Maps.Free (Source, X);
904 end loop;
905 end Move;
907 ----------
908 -- Next --
909 ----------
911 procedure Next (Container : Map; Position : in out Cursor) is
912 begin
913 Position := Next (Container, Position);
914 end Next;
916 function Next (Container : Map; Position : Cursor) return Cursor is
917 begin
918 if Position = No_Element then
919 return No_Element;
920 end if;
922 if not Has_Element (Container, Position) then
923 raise Constraint_Error;
924 end if;
926 pragma Assert (Vet (Container, Position.Node),
927 "bad cursor in Next");
929 return (Node => Tree_Operations.Next (Container, Position.Node));
930 end Next;
932 -------------
933 -- Overlap --
934 -------------
936 function Overlap (Left, Right : Map) return Boolean is
937 begin
938 if Length (Left) = 0 or Length (Right) = 0 then
939 return False;
940 end if;
942 declare
943 L_Node : Count_Type := First (Left).Node;
944 R_Node : Count_Type := First (Right).Node;
945 L_Last : constant Count_Type := Next (Left, Last (Left).Node);
946 R_Last : constant Count_Type := Next (Right, Last (Right).Node);
948 begin
949 if Left'Address = Right'Address then
950 return True;
951 end if;
953 loop
954 if L_Node = L_Last
955 or else R_Node = R_Last
956 then
957 return False;
958 end if;
960 if Left.Nodes (L_Node).Key < Right.Nodes (R_Node).Key then
961 L_Node := Next (Left, L_Node);
963 elsif Right.Nodes (R_Node).Key < Left.Nodes (L_Node).Key then
964 R_Node := Next (Right, R_Node);
966 else
967 return True;
968 end if;
969 end loop;
970 end;
971 end Overlap;
973 ------------
974 -- Parent --
975 ------------
977 function Parent (Node : Node_Type) return Count_Type is
978 begin
979 return Node.Parent;
980 end Parent;
982 --------------
983 -- Previous --
984 --------------
986 procedure Previous (Container : Map; Position : in out Cursor) is
987 begin
988 Position := Previous (Container, Position);
989 end Previous;
991 function Previous (Container : Map; Position : Cursor) return Cursor is
992 begin
993 if Position = No_Element then
994 return No_Element;
995 end if;
997 if not Has_Element (Container, Position) then
998 raise Constraint_Error;
999 end if;
1001 pragma Assert (Vet (Container, Position.Node),
1002 "bad cursor in Previous");
1004 declare
1005 Node : constant Count_Type :=
1006 Tree_Operations.Previous (Container, Position.Node);
1008 begin
1009 if Node = 0 then
1010 return No_Element;
1011 end if;
1013 return (Node => Node);
1014 end;
1015 end Previous;
1017 -------------------
1018 -- Query_Element --
1019 -------------------
1021 procedure Query_Element
1022 (Container : in out Map;
1023 Position : Cursor;
1024 Process : not null access procedure (Key : Key_Type;
1025 Element : Element_Type))
1027 begin
1028 if not Has_Element (Container, Position) then
1029 raise Constraint_Error with
1030 "Position cursor of Query_Element has no element";
1031 end if;
1033 pragma Assert (Vet (Container, Position.Node),
1034 "Position cursor of Query_Element is bad");
1036 declare
1037 B : Natural renames Container.Busy;
1038 L : Natural renames Container.Lock;
1040 begin
1041 B := B + 1;
1042 L := L + 1;
1044 declare
1045 N : Node_Type renames Container.Nodes (Position.Node);
1046 K : Key_Type renames N.Key;
1047 E : Element_Type renames N.Element;
1049 begin
1050 Process (K, E);
1051 exception
1052 when others =>
1053 L := L - 1;
1054 B := B - 1;
1055 raise;
1056 end;
1058 L := L - 1;
1059 B := B - 1;
1060 end;
1061 end Query_Element;
1063 ----------
1064 -- Read --
1065 ----------
1067 procedure Read
1068 (Stream : not null access Root_Stream_Type'Class;
1069 Container : out Map)
1071 procedure Read_Element (Node : in out Node_Type);
1072 pragma Inline (Read_Element);
1074 procedure Allocate is
1075 new Generic_Allocate (Read_Element);
1077 procedure Read_Elements is
1078 new Tree_Operations.Generic_Read (Allocate);
1080 ------------------
1081 -- Read_Element --
1082 ------------------
1084 procedure Read_Element (Node : in out Node_Type) is
1085 begin
1086 Key_Type'Read (Stream, Node.Key);
1087 Element_Type'Read (Stream, Node.Element);
1088 end Read_Element;
1090 -- Start of processing for Read
1092 begin
1093 Read_Elements (Stream, Container);
1094 end Read;
1096 procedure Read
1097 (Stream : not null access Root_Stream_Type'Class;
1098 Item : out Cursor)
1100 begin
1101 raise Program_Error with "attempt to stream map cursor";
1102 end Read;
1104 -------------
1105 -- Replace --
1106 -------------
1108 procedure Replace
1109 (Container : in out Map;
1110 Key : Key_Type;
1111 New_Item : Element_Type)
1113 begin
1114 declare
1115 Node : constant Node_Access := Key_Ops.Find (Container, Key);
1117 begin
1118 if Node = 0 then
1119 raise Constraint_Error with "key not in map";
1120 end if;
1122 if Container.Lock > 0 then
1123 raise Program_Error with
1124 "attempt to tamper with cursors (map is locked)";
1125 end if;
1127 declare
1128 N : Node_Type renames Container.Nodes (Node);
1129 begin
1130 N.Key := Key;
1131 N.Element := New_Item;
1132 end;
1133 end;
1134 end Replace;
1136 ---------------------
1137 -- Replace_Element --
1138 ---------------------
1140 procedure Replace_Element
1141 (Container : in out Map;
1142 Position : Cursor;
1143 New_Item : Element_Type)
1145 begin
1146 if not Has_Element (Container, Position) then
1147 raise Constraint_Error with
1148 "Position cursor of Replace_Element has no element";
1149 end if;
1151 if Container.Lock > 0 then
1152 raise Program_Error with
1153 "attempt to tamper with cursors (map is locked)";
1154 end if;
1156 pragma Assert (Vet (Container, Position.Node),
1157 "Position cursor of Replace_Element is bad");
1159 Container.Nodes (Position.Node).Element := New_Item;
1160 end Replace_Element;
1162 ---------------------
1163 -- Reverse_Iterate --
1164 ---------------------
1166 procedure Reverse_Iterate
1167 (Container : Map;
1168 Process : not null access procedure (Container : Map;
1169 Position : Cursor))
1171 procedure Process_Node (Node : Node_Access);
1172 pragma Inline (Process_Node);
1174 procedure Local_Reverse_Iterate is
1175 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1177 ------------------
1178 -- Process_Node --
1179 ------------------
1181 procedure Process_Node (Node : Node_Access) is
1182 begin
1183 Process (Container, (Node => Node));
1184 end Process_Node;
1186 B : Natural renames Container'Unrestricted_Access.Busy;
1188 -- Start of processing for Reverse_Iterate
1190 begin
1191 B := B + 1;
1193 begin
1194 Local_Reverse_Iterate (Container);
1195 exception
1196 when others =>
1197 B := B - 1;
1198 raise;
1199 end;
1201 B := B - 1;
1202 end Reverse_Iterate;
1204 -----------
1205 -- Right --
1206 -----------
1208 function Right (Container : Map; Position : Cursor) return Map is
1209 Curs : Cursor := First (Container);
1210 C : Map (Container.Capacity) := Copy (Container, Container.Capacity);
1211 Node : Count_Type;
1213 begin
1214 if Curs = No_Element then
1215 Clear (C);
1216 return C;
1218 end if;
1219 if Position /= No_Element and not Has_Element (Container, Position) then
1220 raise Constraint_Error;
1221 end if;
1223 while Curs.Node /= Position.Node loop
1224 Node := Curs.Node;
1225 Delete (C, Curs);
1226 Curs := Next (Container, (Node => Node));
1227 end loop;
1229 return C;
1230 end Right;
1232 ---------------
1233 -- Right_Son --
1234 ---------------
1236 function Right_Son (Node : Node_Type) return Count_Type is
1237 begin
1238 return Node.Right;
1239 end Right_Son;
1241 ---------------
1242 -- Set_Color --
1243 ---------------
1245 procedure Set_Color (Node : in out Node_Type; Color : Color_Type) is
1246 begin
1247 Node.Color := Color;
1248 end Set_Color;
1250 --------------
1251 -- Set_Left --
1252 --------------
1254 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1255 begin
1256 Node.Left := Left;
1257 end Set_Left;
1259 ----------------
1260 -- Set_Parent --
1261 ----------------
1263 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1264 begin
1265 Node.Parent := Parent;
1266 end Set_Parent;
1268 ---------------
1269 -- Set_Right --
1270 ---------------
1272 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1273 begin
1274 Node.Right := Right;
1275 end Set_Right;
1277 ------------------
1278 -- Strict_Equal --
1279 ------------------
1281 function Strict_Equal (Left, Right : Map) return Boolean is
1282 LNode : Count_Type := First (Left).Node;
1283 RNode : Count_Type := First (Right).Node;
1285 begin
1286 if Length (Left) /= Length (Right) then
1287 return False;
1288 end if;
1290 while LNode = RNode loop
1291 if LNode = 0 then
1292 return True;
1293 end if;
1295 if Left.Nodes (LNode).Element /= Right.Nodes (RNode).Element
1296 or else Left.Nodes (LNode).Key /= Right.Nodes (RNode).Key
1297 then
1298 exit;
1299 end if;
1301 LNode := Next (Left, LNode);
1302 RNode := Next (Right, RNode);
1303 end loop;
1305 return False;
1306 end Strict_Equal;
1308 --------------------
1309 -- Update_Element --
1310 --------------------
1312 procedure Update_Element
1313 (Container : in out Map;
1314 Position : Cursor;
1315 Process : not null access procedure (Key : Key_Type;
1316 Element : in out Element_Type))
1318 begin
1319 if not Has_Element (Container, Position) then
1320 raise Constraint_Error with
1321 "Position cursor of Update_Element has no element";
1322 end if;
1324 pragma Assert (Vet (Container, Position.Node),
1325 "Position cursor of Update_Element is bad");
1327 declare
1328 B : Natural renames Container.Busy;
1329 L : Natural renames Container.Lock;
1331 begin
1332 B := B + 1;
1333 L := L + 1;
1335 declare
1336 N : Node_Type renames Container.Nodes (Position.Node);
1337 K : Key_Type renames N.Key;
1338 E : Element_Type renames N.Element;
1340 begin
1341 Process (K, E);
1342 exception
1343 when others =>
1344 L := L - 1;
1345 B := B - 1;
1346 raise;
1347 end;
1349 L := L - 1;
1350 B := B - 1;
1351 end;
1352 end Update_Element;
1354 -----------
1355 -- Write --
1356 -----------
1358 procedure Write
1359 (Stream : not null access Root_Stream_Type'Class;
1360 Container : Map)
1362 procedure Write_Node
1363 (Stream : not null access Root_Stream_Type'Class;
1364 Node : Node_Type);
1365 pragma Inline (Write_Node);
1367 procedure Write_Nodes is
1368 new Tree_Operations.Generic_Write (Write_Node);
1370 ----------------
1371 -- Write_Node --
1372 ----------------
1374 procedure Write_Node
1375 (Stream : not null access Root_Stream_Type'Class;
1376 Node : Node_Type)
1378 begin
1379 Key_Type'Write (Stream, Node.Key);
1380 Element_Type'Write (Stream, Node.Element);
1381 end Write_Node;
1383 -- Start of processing for Write
1385 begin
1386 Write_Nodes (Stream, Container);
1387 end Write;
1389 procedure Write
1390 (Stream : not null access Root_Stream_Type'Class;
1391 Item : Cursor)
1393 begin
1394 raise Program_Error with "attempt to stream map cursor";
1395 end Write;
1397 end Ada.Containers.Formal_Ordered_Maps;