2010-11-27 François Dumont <francois.cppdevs@free.fr>
[official-gcc.git] / gcc / ada / a-cborma.adb
blob64c248f7b506aafc8cb74d09384a12225b498ed5
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . B O U N D E D _ O R D E R E D _ M A P S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2010, 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.Containers.Red_Black_Trees.Generic_Bounded_Operations;
31 pragma Elaborate_All
32 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations);
34 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
35 pragma Elaborate_All
36 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
38 with System; use type System.Address;
40 package body Ada.Containers.Bounded_Ordered_Maps is
42 -----------------------------
43 -- Node Access Subprograms --
44 -----------------------------
46 -- These subprograms provide a functional interface to access fields
47 -- of a node, and a procedural interface for modifying these values.
49 function Color (Node : Node_Type) return Color_Type;
50 pragma Inline (Color);
52 function Left (Node : Node_Type) return Count_Type;
53 pragma Inline (Left);
55 function Parent (Node : Node_Type) return Count_Type;
56 pragma Inline (Parent);
58 function Right (Node : Node_Type) return Count_Type;
59 pragma Inline (Right);
61 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
62 pragma Inline (Set_Parent);
64 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
65 pragma Inline (Set_Left);
67 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
68 pragma Inline (Set_Right);
70 procedure Set_Color (Node : in out Node_Type; Color : Color_Type);
71 pragma Inline (Set_Color);
73 -----------------------
74 -- Local Subprograms --
75 -----------------------
77 function Is_Greater_Key_Node
78 (Left : Key_Type;
79 Right : Node_Type) return Boolean;
80 pragma Inline (Is_Greater_Key_Node);
82 function Is_Less_Key_Node
83 (Left : Key_Type;
84 Right : Node_Type) return Boolean;
85 pragma Inline (Is_Less_Key_Node);
87 --------------------------
88 -- Local Instantiations --
89 --------------------------
91 package Tree_Operations is
92 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
94 use Tree_Operations;
96 package Key_Ops is
97 new Red_Black_Trees.Generic_Bounded_Keys
98 (Tree_Operations => Tree_Operations,
99 Key_Type => Key_Type,
100 Is_Less_Key_Node => Is_Less_Key_Node,
101 Is_Greater_Key_Node => Is_Greater_Key_Node);
103 ---------
104 -- "<" --
105 ---------
107 function "<" (Left, Right : Cursor) return Boolean is
108 begin
109 if Left.Node = 0 then
110 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
111 end if;
113 if Right.Node = 0 then
114 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
115 end if;
117 pragma Assert (Vet (Left.Container.all, Left.Node),
118 "Left cursor of ""<"" is bad");
120 pragma Assert (Vet (Right.Container.all, Right.Node),
121 "Right cursor of ""<"" is bad");
123 declare
124 LN : Node_Type renames Left.Container.Nodes (Left.Node);
125 RN : Node_Type renames Right.Container.Nodes (Right.Node);
127 begin
128 return LN.Key < RN.Key;
129 end;
130 end "<";
132 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
133 begin
134 if Left.Node = 0 then
135 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
136 end if;
138 pragma Assert (Vet (Left.Container.all, Left.Node),
139 "Left cursor of ""<"" is bad");
141 declare
142 LN : Node_Type renames Left.Container.Nodes (Left.Node);
144 begin
145 return LN.Key < Right;
146 end;
147 end "<";
149 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
150 begin
151 if Right.Node = 0 then
152 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
153 end if;
155 pragma Assert (Vet (Right.Container.all, Right.Node),
156 "Right cursor of ""<"" is bad");
158 declare
159 RN : Node_Type renames Right.Container.Nodes (Right.Node);
161 begin
162 return Left < RN.Key;
163 end;
164 end "<";
166 ---------
167 -- "=" --
168 ---------
170 function "=" (Left, Right : Map) return Boolean is
171 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
172 pragma Inline (Is_Equal_Node_Node);
174 function Is_Equal is
175 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
177 ------------------------
178 -- Is_Equal_Node_Node --
179 ------------------------
181 function Is_Equal_Node_Node
182 (L, R : Node_Type) return Boolean is
183 begin
184 if L.Key < R.Key then
185 return False;
187 elsif R.Key < L.Key then
188 return False;
190 else
191 return L.Element = R.Element;
192 end if;
193 end Is_Equal_Node_Node;
195 -- Start of processing for "="
197 begin
198 return Is_Equal (Left, Right);
199 end "=";
201 ---------
202 -- ">" --
203 ---------
205 function ">" (Left, Right : Cursor) return Boolean is
206 begin
207 if Left.Node = 0 then
208 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
209 end if;
211 if Right.Node = 0 then
212 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
213 end if;
215 pragma Assert (Vet (Left.Container.all, Left.Node),
216 "Left cursor of "">"" is bad");
218 pragma Assert (Vet (Right.Container.all, Right.Node),
219 "Right cursor of "">"" is bad");
221 declare
222 LN : Node_Type renames Left.Container.Nodes (Left.Node);
223 RN : Node_Type renames Right.Container.Nodes (Right.Node);
225 begin
226 return RN.Key < LN.Key;
227 end;
228 end ">";
230 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
231 begin
232 if Left.Node = 0 then
233 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
234 end if;
236 pragma Assert (Vet (Left.Container.all, Left.Node),
237 "Left cursor of "">"" is bad");
239 declare
240 LN : Node_Type renames Left.Container.Nodes (Left.Node);
242 begin
243 return Right < LN.Key;
244 end;
245 end ">";
247 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
248 begin
249 if Right.Node = 0 then
250 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
251 end if;
253 pragma Assert (Vet (Right.Container.all, Right.Node),
254 "Right cursor of "">"" is bad");
256 declare
257 RN : Node_Type renames Right.Container.Nodes (Right.Node);
259 begin
260 return RN.Key < Left;
261 end;
262 end ">";
264 ------------
265 -- Assign --
266 ------------
268 procedure Assign (Target : in out Map; Source : Map) is
269 procedure Append_Element (Source_Node : Count_Type);
271 procedure Append_Elements is
272 new Tree_Operations.Generic_Iteration (Append_Element);
274 --------------------
275 -- Append_Element --
276 --------------------
278 procedure Append_Element (Source_Node : Count_Type) is
279 SN : Node_Type renames Source.Nodes (Source_Node);
281 procedure Set_Element (Node : in out Node_Type);
282 pragma Inline (Set_Element);
284 function New_Node return Count_Type;
285 pragma Inline (New_Node);
287 procedure Insert_Post is
288 new Key_Ops.Generic_Insert_Post (New_Node);
290 procedure Unconditional_Insert_Sans_Hint is
291 new Key_Ops.Generic_Unconditional_Insert (Insert_Post);
293 procedure Unconditional_Insert_Avec_Hint is
294 new Key_Ops.Generic_Unconditional_Insert_With_Hint
295 (Insert_Post,
296 Unconditional_Insert_Sans_Hint);
298 procedure Allocate is
299 new Tree_Operations.Generic_Allocate (Set_Element);
301 --------------
302 -- New_Node --
303 --------------
305 function New_Node return Count_Type is
306 Result : Count_Type;
308 begin
309 Allocate (Target, Result);
310 return Result;
311 end New_Node;
313 -----------------
314 -- Set_Element --
315 -----------------
317 procedure Set_Element (Node : in out Node_Type) is
318 begin
319 Node.Key := SN.Key;
320 Node.Element := SN.Element;
321 end Set_Element;
323 Target_Node : Count_Type;
325 -- Start of processing for Append_Element
327 begin
328 Unconditional_Insert_Avec_Hint
329 (Tree => Target,
330 Hint => 0,
331 Key => SN.Key,
332 Node => Target_Node);
333 end Append_Element;
335 -- Start of processing for Assign
337 begin
338 if Target'Address = Source'Address then
339 return;
340 end if;
342 if Target.Capacity < Source.Length then
343 raise Capacity_Error
344 with "Target capacity is less than Source length";
345 end if;
347 Tree_Operations.Clear_Tree (Target);
348 Append_Elements (Source);
349 end Assign;
351 -------------
352 -- Ceiling --
353 -------------
355 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
356 Node : constant Count_Type := Key_Ops.Ceiling (Container, Key);
358 begin
359 if Node = 0 then
360 return No_Element;
361 end if;
363 return Cursor'(Container'Unrestricted_Access, Node);
364 end Ceiling;
366 -----------
367 -- Clear --
368 -----------
370 procedure Clear (Container : in out Map) is
371 begin
372 Tree_Operations.Clear_Tree (Container);
373 end Clear;
375 -----------
376 -- Color --
377 -----------
379 function Color (Node : Node_Type) return Color_Type is
380 begin
381 return Node.Color;
382 end Color;
384 --------------
385 -- Contains --
386 --------------
388 function Contains (Container : Map; Key : Key_Type) return Boolean is
389 begin
390 return Find (Container, Key) /= No_Element;
391 end Contains;
393 ----------
394 -- Copy --
395 ----------
397 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
398 C : Count_Type;
400 begin
401 if Capacity = 0 then
402 C := Source.Length;
404 elsif Capacity >= Source.Length then
405 C := Capacity;
407 else
408 raise Capacity_Error with "Capacity value too small";
409 end if;
411 return Target : Map (Capacity => C) do
412 Assign (Target => Target, Source => Source);
413 end return;
414 end Copy;
416 ------------
417 -- Delete --
418 ------------
420 procedure Delete (Container : in out Map; Position : in out Cursor) is
421 begin
422 if Position.Node = 0 then
423 raise Constraint_Error with
424 "Position cursor of Delete equals No_Element";
425 end if;
427 if Position.Container /= Container'Unrestricted_Access then
428 raise Program_Error with
429 "Position cursor of Delete designates wrong map";
430 end if;
432 pragma Assert (Vet (Container, Position.Node),
433 "Position cursor of Delete is bad");
435 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
436 Tree_Operations.Free (Container, Position.Node);
438 Position := No_Element;
439 end Delete;
441 procedure Delete (Container : in out Map; Key : Key_Type) is
442 X : constant Count_Type := Key_Ops.Find (Container, Key);
444 begin
445 if X = 0 then
446 raise Constraint_Error with "key not in map";
447 end if;
449 Tree_Operations.Delete_Node_Sans_Free (Container, X);
450 Tree_Operations.Free (Container, X);
451 end Delete;
453 ------------------
454 -- Delete_First --
455 ------------------
457 procedure Delete_First (Container : in out Map) is
458 X : constant Count_Type := Container.First;
460 begin
461 if X /= 0 then
462 Tree_Operations.Delete_Node_Sans_Free (Container, X);
463 Tree_Operations.Free (Container, X);
464 end if;
465 end Delete_First;
467 -----------------
468 -- Delete_Last --
469 -----------------
471 procedure Delete_Last (Container : in out Map) is
472 X : constant Count_Type := Container.Last;
474 begin
475 if X /= 0 then
476 Tree_Operations.Delete_Node_Sans_Free (Container, X);
477 Tree_Operations.Free (Container, X);
478 end if;
479 end Delete_Last;
481 -------------
482 -- Element --
483 -------------
485 function Element (Position : Cursor) return Element_Type is
486 begin
487 if Position.Node = 0 then
488 raise Constraint_Error with
489 "Position cursor of function Element equals No_Element";
490 end if;
492 pragma Assert (Vet (Position.Container.all, Position.Node),
493 "Position cursor of function Element is bad");
495 return Position.Container.Nodes (Position.Node).Element;
496 end Element;
498 function Element (Container : Map; Key : Key_Type) return Element_Type is
499 Node : constant Count_Type := Key_Ops.Find (Container, Key);
501 begin
502 if Node = 0 then
503 raise Constraint_Error with "key not in map";
504 end if;
506 return Container.Nodes (Node).Element;
507 end Element;
509 ---------------------
510 -- Equivalent_Keys --
511 ---------------------
513 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
514 begin
515 if Left < Right
516 or else Right < Left
517 then
518 return False;
519 else
520 return True;
521 end if;
522 end Equivalent_Keys;
524 -------------
525 -- Exclude --
526 -------------
528 procedure Exclude (Container : in out Map; Key : Key_Type) is
529 X : constant Count_Type := Key_Ops.Find (Container, Key);
531 begin
532 if X /= 0 then
533 Tree_Operations.Delete_Node_Sans_Free (Container, X);
534 Tree_Operations.Free (Container, X);
535 end if;
536 end Exclude;
538 ----------
539 -- Find --
540 ----------
542 function Find (Container : Map; Key : Key_Type) return Cursor is
543 Node : constant Count_Type := Key_Ops.Find (Container, Key);
545 begin
546 if Node = 0 then
547 return No_Element;
548 end if;
550 return Cursor'(Container'Unrestricted_Access, Node);
551 end Find;
553 -----------
554 -- First --
555 -----------
557 function First (Container : Map) return Cursor is
558 begin
559 if Container.First = 0 then
560 return No_Element;
561 end if;
563 return Cursor'(Container'Unrestricted_Access, Container.First);
564 end First;
566 -------------------
567 -- First_Element --
568 -------------------
570 function First_Element (Container : Map) return Element_Type is
571 begin
572 if Container.First = 0 then
573 raise Constraint_Error with "map is empty";
574 end if;
576 return Container.Nodes (Container.First).Element;
577 end First_Element;
579 ---------------
580 -- First_Key --
581 ---------------
583 function First_Key (Container : Map) return Key_Type is
584 begin
585 if Container.First = 0 then
586 raise Constraint_Error with "map is empty";
587 end if;
589 return Container.Nodes (Container.First).Key;
590 end First_Key;
592 -----------
593 -- Floor --
594 -----------
596 function Floor (Container : Map; Key : Key_Type) return Cursor is
597 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
599 begin
600 if Node = 0 then
601 return No_Element;
602 end if;
604 return Cursor'(Container'Unrestricted_Access, Node);
605 end Floor;
607 -----------------
608 -- Has_Element --
609 -----------------
611 function Has_Element (Position : Cursor) return Boolean is
612 begin
613 return Position /= No_Element;
614 end Has_Element;
616 -------------
617 -- Include --
618 -------------
620 procedure Include
621 (Container : in out Map;
622 Key : Key_Type;
623 New_Item : Element_Type)
625 Position : Cursor;
626 Inserted : Boolean;
628 begin
629 Insert (Container, Key, New_Item, Position, Inserted);
631 if not Inserted then
632 if Container.Lock > 0 then
633 raise Program_Error with
634 "attempt to tamper with elements (map is locked)";
635 end if;
637 declare
638 N : Node_Type renames Container.Nodes (Position.Node);
640 begin
641 N.Key := Key;
642 N.Element := New_Item;
643 end;
644 end if;
645 end Include;
647 ------------
648 -- Insert --
649 ------------
651 procedure Insert
652 (Container : in out Map;
653 Key : Key_Type;
654 New_Item : Element_Type;
655 Position : out Cursor;
656 Inserted : out Boolean)
658 procedure Assign (Node : in out Node_Type);
659 pragma Inline (Assign);
661 function New_Node return Count_Type;
662 pragma Inline (New_Node);
664 procedure Insert_Post is
665 new Key_Ops.Generic_Insert_Post (New_Node);
667 procedure Insert_Sans_Hint is
668 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
670 procedure Allocate is
671 new Tree_Operations.Generic_Allocate (Assign);
673 ------------
674 -- Assign --
675 ------------
677 procedure Assign (Node : in out Node_Type) is
678 begin
679 Node.Key := Key;
680 Node.Element := New_Item;
681 end Assign;
683 --------------
684 -- New_Node --
685 --------------
687 function New_Node return Count_Type is
688 Result : Count_Type;
690 begin
691 Allocate (Container, Result);
692 return Result;
693 end New_Node;
695 -- Start of processing for Insert
697 begin
698 Insert_Sans_Hint
699 (Container,
700 Key,
701 Position.Node,
702 Inserted);
704 Position.Container := Container'Unrestricted_Access;
705 end Insert;
707 procedure Insert
708 (Container : in out Map;
709 Key : Key_Type;
710 New_Item : Element_Type)
712 Position : Cursor;
713 pragma Unreferenced (Position);
715 Inserted : Boolean;
717 begin
718 Insert (Container, Key, New_Item, Position, Inserted);
720 if not Inserted then
721 raise Constraint_Error with "key already in map";
722 end if;
723 end Insert;
725 procedure Insert
726 (Container : in out Map;
727 Key : Key_Type;
728 Position : out Cursor;
729 Inserted : out Boolean)
731 procedure Assign (Node : in out Node_Type);
732 pragma Inline (Assign);
734 function New_Node return Count_Type;
735 pragma Inline (New_Node);
737 procedure Insert_Post is
738 new Key_Ops.Generic_Insert_Post (New_Node);
740 procedure Insert_Sans_Hint is
741 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
743 procedure Allocate is
744 new Tree_Operations.Generic_Allocate (Assign);
746 ------------
747 -- Assign --
748 ------------
750 procedure Assign (Node : in out Node_Type) is
751 begin
752 Node.Key := Key;
753 -- Node.Element := New_Item;
754 end Assign;
756 --------------
757 -- New_Node --
758 --------------
760 function New_Node return Count_Type is
761 Result : Count_Type;
763 begin
764 Allocate (Container, Result);
765 return Result;
766 end New_Node;
768 -- Start of processing for Insert
770 begin
771 Insert_Sans_Hint
772 (Container,
773 Key,
774 Position.Node,
775 Inserted);
777 Position.Container := Container'Unrestricted_Access;
778 end Insert;
780 --------------
781 -- Is_Empty --
782 --------------
784 function Is_Empty (Container : Map) return Boolean is
785 begin
786 return Container.Length = 0;
787 end Is_Empty;
789 -------------------------
790 -- Is_Greater_Key_Node --
791 -------------------------
793 function Is_Greater_Key_Node
794 (Left : Key_Type;
795 Right : Node_Type) return Boolean
797 begin
798 -- k > node same as node < k
800 return Right.Key < Left;
801 end Is_Greater_Key_Node;
803 ----------------------
804 -- Is_Less_Key_Node --
805 ----------------------
807 function Is_Less_Key_Node
808 (Left : Key_Type;
809 Right : Node_Type) return Boolean
811 begin
812 return Left < Right.Key;
813 end Is_Less_Key_Node;
815 -------------
816 -- Iterate --
817 -------------
819 procedure Iterate
820 (Container : Map;
821 Process : not null access procedure (Position : Cursor))
823 procedure Process_Node (Node : Count_Type);
824 pragma Inline (Process_Node);
826 procedure Local_Iterate is
827 new Tree_Operations.Generic_Iteration (Process_Node);
829 ------------------
830 -- Process_Node --
831 ------------------
833 procedure Process_Node (Node : Count_Type) is
834 begin
835 Process (Cursor'(Container'Unrestricted_Access, Node));
836 end Process_Node;
838 B : Natural renames Container'Unrestricted_Access.all.Busy;
840 -- Start of processing for Iterate
842 begin
843 B := B + 1;
845 begin
846 Local_Iterate (Container);
847 exception
848 when others =>
849 B := B - 1;
850 raise;
851 end;
853 B := B - 1;
854 end Iterate;
856 ---------
857 -- Key --
858 ---------
860 function Key (Position : Cursor) return Key_Type is
861 begin
862 if Position.Node = 0 then
863 raise Constraint_Error with
864 "Position cursor of function Key equals No_Element";
865 end if;
867 pragma Assert (Vet (Position.Container.all, Position.Node),
868 "Position cursor of function Key is bad");
870 return Position.Container.Nodes (Position.Node).Key;
871 end Key;
873 ----------
874 -- Last --
875 ----------
877 function Last (Container : Map) return Cursor is
878 begin
879 if Container.Last = 0 then
880 return No_Element;
881 end if;
883 return Cursor'(Container'Unrestricted_Access, Container.Last);
884 end Last;
886 ------------------
887 -- Last_Element --
888 ------------------
890 function Last_Element (Container : Map) return Element_Type is
891 begin
892 if Container.Last = 0 then
893 raise Constraint_Error with "map is empty";
894 end if;
896 return Container.Nodes (Container.Last).Element;
897 end Last_Element;
899 --------------
900 -- Last_Key --
901 --------------
903 function Last_Key (Container : Map) return Key_Type is
904 begin
905 if Container.Last = 0 then
906 raise Constraint_Error with "map is empty";
907 end if;
909 return Container.Nodes (Container.Last).Key;
910 end Last_Key;
912 ----------
913 -- Left --
914 ----------
916 function Left (Node : Node_Type) return Count_Type is
917 begin
918 return Node.Left;
919 end Left;
921 ------------
922 -- Length --
923 ------------
925 function Length (Container : Map) return Count_Type is
926 begin
927 return Container.Length;
928 end Length;
930 ----------
931 -- Move --
932 ----------
934 procedure Move (Target : in out Map; Source : in out Map) is
935 begin
936 if Target'Address = Source'Address then
937 return;
938 end if;
940 if Source.Busy > 0 then
941 raise Program_Error with
942 "attempt to tamper with cursors (container is busy)";
943 end if;
945 Assign (Target => Target, Source => Source);
946 end Move;
948 ----------
949 -- Next --
950 ----------
952 procedure Next (Position : in out Cursor) is
953 begin
954 Position := Next (Position);
955 end Next;
957 function Next (Position : Cursor) return Cursor is
958 begin
959 if Position = No_Element then
960 return No_Element;
961 end if;
963 pragma Assert (Vet (Position.Container.all, Position.Node),
964 "Position cursor of Next is bad");
966 declare
967 M : Map renames Position.Container.all;
969 Node : constant Count_Type :=
970 Tree_Operations.Next (M, Position.Node);
972 begin
973 if Node = 0 then
974 return No_Element;
975 end if;
977 return Cursor'(Position.Container, Node);
978 end;
979 end Next;
981 ------------
982 -- Parent --
983 ------------
985 function Parent (Node : Node_Type) return Count_Type is
986 begin
987 return Node.Parent;
988 end Parent;
990 --------------
991 -- Previous --
992 --------------
994 procedure Previous (Position : in out Cursor) is
995 begin
996 Position := Previous (Position);
997 end Previous;
999 function Previous (Position : Cursor) return Cursor is
1000 begin
1001 if Position = No_Element then
1002 return No_Element;
1003 end if;
1005 pragma Assert (Vet (Position.Container.all, Position.Node),
1006 "Position cursor of Previous is bad");
1008 declare
1009 M : Map renames Position.Container.all;
1011 Node : constant Count_Type :=
1012 Tree_Operations.Previous (M, Position.Node);
1014 begin
1015 if Node = 0 then
1016 return No_Element;
1017 end if;
1019 return Cursor'(Position.Container, Node);
1020 end;
1021 end Previous;
1023 -------------------
1024 -- Query_Element --
1025 -------------------
1027 procedure Query_Element
1028 (Position : Cursor;
1029 Process : not null access procedure (Key : Key_Type;
1030 Element : Element_Type))
1032 begin
1033 if Position.Node = 0 then
1034 raise Constraint_Error with
1035 "Position cursor of Query_Element equals No_Element";
1036 end if;
1038 pragma Assert (Vet (Position.Container.all, Position.Node),
1039 "Position cursor of Query_Element is bad");
1041 declare
1042 M : Map renames Position.Container.all;
1043 N : Node_Type renames M.Nodes (Position.Node);
1045 B : Natural renames M.Busy;
1046 L : Natural renames M.Lock;
1048 begin
1049 B := B + 1;
1050 L := L + 1;
1052 begin
1053 Process (N.Key, N.Element);
1054 exception
1055 when others =>
1056 L := L - 1;
1057 B := B - 1;
1058 raise;
1059 end;
1061 L := L - 1;
1062 B := B - 1;
1063 end;
1064 end Query_Element;
1066 ----------
1067 -- Read --
1068 ----------
1070 procedure Read
1071 (Stream : not null access Root_Stream_Type'Class;
1072 Container : out Map)
1074 procedure Read_Element (Node : in out Node_Type);
1075 pragma Inline (Read_Element);
1077 procedure Allocate is
1078 new Tree_Operations.Generic_Allocate (Read_Element);
1080 procedure Read_Elements is
1081 new Tree_Operations.Generic_Read (Allocate);
1083 ------------------
1084 -- Read_Element --
1085 ------------------
1087 procedure Read_Element (Node : in out Node_Type) is
1088 begin
1089 Key_Type'Read (Stream, Node.Key);
1090 Element_Type'Read (Stream, Node.Element);
1091 end Read_Element;
1093 -- Start of processing for Read
1095 begin
1096 Read_Elements (Stream, Container);
1097 end Read;
1099 procedure Read
1100 (Stream : not null access Root_Stream_Type'Class;
1101 Item : out Cursor)
1103 begin
1104 raise Program_Error with "attempt to stream map cursor";
1105 end Read;
1107 -------------
1108 -- Replace --
1109 -------------
1111 procedure Replace
1112 (Container : in out Map;
1113 Key : Key_Type;
1114 New_Item : Element_Type)
1116 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1118 begin
1119 if Node = 0 then
1120 raise Constraint_Error with "key not in map";
1121 end if;
1123 if Container.Lock > 0 then
1124 raise Program_Error with
1125 "attempt to tamper with elements (map is locked)";
1126 end if;
1128 declare
1129 N : Node_Type renames Container.Nodes (Node);
1131 begin
1132 N.Key := Key;
1133 N.Element := New_Item;
1134 end;
1135 end Replace;
1137 ---------------------
1138 -- Replace_Element --
1139 ---------------------
1141 procedure Replace_Element
1142 (Container : in out Map;
1143 Position : Cursor;
1144 New_Item : Element_Type)
1146 begin
1147 if Position.Node = 0 then
1148 raise Constraint_Error with
1149 "Position cursor of Replace_Element equals No_Element";
1150 end if;
1152 if Position.Container /= Container'Unrestricted_Access then
1153 raise Program_Error with
1154 "Position cursor of Replace_Element designates wrong map";
1155 end if;
1157 if Container.Lock > 0 then
1158 raise Program_Error with
1159 "attempt to tamper with elements (map is locked)";
1160 end if;
1162 pragma Assert (Vet (Container, Position.Node),
1163 "Position cursor of Replace_Element is bad");
1165 Container.Nodes (Position.Node).Element := New_Item;
1166 end Replace_Element;
1168 ---------------------
1169 -- Reverse_Iterate --
1170 ---------------------
1172 procedure Reverse_Iterate
1173 (Container : Map;
1174 Process : not null access procedure (Position : Cursor))
1176 procedure Process_Node (Node : Count_Type);
1177 pragma Inline (Process_Node);
1179 procedure Local_Reverse_Iterate is
1180 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1182 ------------------
1183 -- Process_Node --
1184 ------------------
1186 procedure Process_Node (Node : Count_Type) is
1187 begin
1188 Process (Cursor'(Container'Unrestricted_Access, Node));
1189 end Process_Node;
1191 B : Natural renames Container'Unrestricted_Access.all.Busy;
1193 -- Start of processing for Reverse_Iterate
1195 begin
1196 B := B + 1;
1198 begin
1199 Local_Reverse_Iterate (Container);
1200 exception
1201 when others =>
1202 B := B - 1;
1203 raise;
1204 end;
1206 B := B - 1;
1207 end Reverse_Iterate;
1209 -----------
1210 -- Right --
1211 -----------
1213 function Right (Node : Node_Type) return Count_Type is
1214 begin
1215 return Node.Right;
1216 end Right;
1218 ---------------
1219 -- Set_Color --
1220 ---------------
1222 procedure Set_Color
1223 (Node : in out Node_Type;
1224 Color : Color_Type)
1226 begin
1227 Node.Color := Color;
1228 end Set_Color;
1230 --------------
1231 -- Set_Left --
1232 --------------
1234 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1235 begin
1236 Node.Left := Left;
1237 end Set_Left;
1239 ----------------
1240 -- Set_Parent --
1241 ----------------
1243 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1244 begin
1245 Node.Parent := Parent;
1246 end Set_Parent;
1248 ---------------
1249 -- Set_Right --
1250 ---------------
1252 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1253 begin
1254 Node.Right := Right;
1255 end Set_Right;
1257 --------------------
1258 -- Update_Element --
1259 --------------------
1261 procedure Update_Element
1262 (Container : in out Map;
1263 Position : Cursor;
1264 Process : not null access procedure (Key : Key_Type;
1265 Element : in out Element_Type))
1267 begin
1268 if Position.Node = 0 then
1269 raise Constraint_Error with
1270 "Position cursor of Update_Element equals No_Element";
1271 end if;
1273 if Position.Container /= Container'Unrestricted_Access then
1274 raise Program_Error with
1275 "Position cursor of Update_Element designates wrong map";
1276 end if;
1278 pragma Assert (Vet (Container, Position.Node),
1279 "Position cursor of Update_Element is bad");
1281 declare
1282 N : Node_Type renames Container.Nodes (Position.Node);
1283 B : Natural renames Container.Busy;
1284 L : Natural renames Container.Lock;
1286 begin
1287 B := B + 1;
1288 L := L + 1;
1290 begin
1291 Process (N.Key, N.Element);
1293 exception
1294 when others =>
1295 L := L - 1;
1296 B := B - 1;
1297 raise;
1298 end;
1300 L := L - 1;
1301 B := B - 1;
1302 end;
1303 end Update_Element;
1305 -----------
1306 -- Write --
1307 -----------
1309 procedure Write
1310 (Stream : not null access Root_Stream_Type'Class;
1311 Container : Map)
1313 procedure Write_Node
1314 (Stream : not null access Root_Stream_Type'Class;
1315 Node : Node_Type);
1316 pragma Inline (Write_Node);
1318 procedure Write_Nodes is
1319 new Tree_Operations.Generic_Write (Write_Node);
1321 ----------------
1322 -- Write_Node --
1323 ----------------
1325 procedure Write_Node
1326 (Stream : not null access Root_Stream_Type'Class;
1327 Node : Node_Type)
1329 begin
1330 Key_Type'Write (Stream, Node.Key);
1331 Element_Type'Write (Stream, Node.Element);
1332 end Write_Node;
1334 -- Start of processing for Write
1336 begin
1337 Write_Nodes (Stream, Container);
1338 end Write;
1340 procedure Write
1341 (Stream : not null access Root_Stream_Type'Class;
1342 Item : Cursor)
1344 begin
1345 raise Program_Error with "attempt to stream map cursor";
1346 end Write;
1348 end Ada.Containers.Bounded_Ordered_Maps;