cap frequency in make_forwarder_block
[official-gcc.git] / gcc / ada / a-coorma.adb
blob0794ba3f62bdc8ba57410a303a0d4d6150e100f2
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . O R D E R E D _ M A P S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2014, 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 with System; use type System.Address;
40 package body Ada.Containers.Ordered_Maps is
42 pragma Annotate (CodePeer, Skip_Analysis);
44 -----------------------------
45 -- Node Access Subprograms --
46 -----------------------------
48 -- These subprograms provide a functional interface to access fields
49 -- of a node, and a procedural interface for modifying these values.
51 function Color (Node : Node_Access) return Color_Type;
52 pragma Inline (Color);
54 function Left (Node : Node_Access) return Node_Access;
55 pragma Inline (Left);
57 function Parent (Node : Node_Access) return Node_Access;
58 pragma Inline (Parent);
60 function Right (Node : Node_Access) return Node_Access;
61 pragma Inline (Right);
63 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
64 pragma Inline (Set_Parent);
66 procedure Set_Left (Node : Node_Access; Left : Node_Access);
67 pragma Inline (Set_Left);
69 procedure Set_Right (Node : Node_Access; Right : Node_Access);
70 pragma Inline (Set_Right);
72 procedure Set_Color (Node : Node_Access; Color : Color_Type);
73 pragma Inline (Set_Color);
75 -----------------------
76 -- Local Subprograms --
77 -----------------------
79 function Copy_Node (Source : Node_Access) return Node_Access;
80 pragma Inline (Copy_Node);
82 procedure Free (X : in out Node_Access);
84 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
85 pragma Inline (Is_Equal_Node_Node);
87 function Is_Greater_Key_Node
88 (Left : Key_Type;
89 Right : Node_Access) return Boolean;
90 pragma Inline (Is_Greater_Key_Node);
92 function Is_Less_Key_Node
93 (Left : Key_Type;
94 Right : Node_Access) 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_Operations (Tree_Types);
104 procedure Delete_Tree is
105 new Tree_Operations.Generic_Delete_Tree (Free);
107 function Copy_Tree is
108 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
110 use Tree_Operations;
112 package Key_Ops is
113 new Red_Black_Trees.Generic_Keys
114 (Tree_Operations => Tree_Operations,
115 Key_Type => Key_Type,
116 Is_Less_Key_Node => Is_Less_Key_Node,
117 Is_Greater_Key_Node => Is_Greater_Key_Node);
119 function Is_Equal is
120 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
122 ---------
123 -- "<" --
124 ---------
126 function "<" (Left, Right : Cursor) return Boolean is
127 begin
128 if Left.Node = null then
129 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
130 end if;
132 if Right.Node = null then
133 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
134 end if;
136 pragma Assert (Vet (Left.Container.Tree, Left.Node),
137 "Left cursor of ""<"" is bad");
139 pragma Assert (Vet (Right.Container.Tree, Right.Node),
140 "Right cursor of ""<"" is bad");
142 return Left.Node.Key < Right.Node.Key;
143 end "<";
145 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
146 begin
147 if Left.Node = null then
148 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
149 end if;
151 pragma Assert (Vet (Left.Container.Tree, Left.Node),
152 "Left cursor of ""<"" is bad");
154 return Left.Node.Key < Right;
155 end "<";
157 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
158 begin
159 if Right.Node = null then
160 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
161 end if;
163 pragma Assert (Vet (Right.Container.Tree, Right.Node),
164 "Right cursor of ""<"" is bad");
166 return Left < Right.Node.Key;
167 end "<";
169 ---------
170 -- "=" --
171 ---------
173 function "=" (Left, Right : Map) return Boolean is
174 begin
175 return Is_Equal (Left.Tree, Right.Tree);
176 end "=";
178 ---------
179 -- ">" --
180 ---------
182 function ">" (Left, Right : Cursor) return Boolean is
183 begin
184 if Left.Node = null then
185 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
186 end if;
188 if Right.Node = null then
189 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
190 end if;
192 pragma Assert (Vet (Left.Container.Tree, Left.Node),
193 "Left cursor of "">"" is bad");
195 pragma Assert (Vet (Right.Container.Tree, Right.Node),
196 "Right cursor of "">"" is bad");
198 return Right.Node.Key < Left.Node.Key;
199 end ">";
201 function ">" (Left : Cursor; Right : Key_Type) 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 pragma Assert (Vet (Left.Container.Tree, Left.Node),
208 "Left cursor of "">"" is bad");
210 return Right < Left.Node.Key;
211 end ">";
213 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
214 begin
215 if Right.Node = null then
216 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
217 end if;
219 pragma Assert (Vet (Right.Container.Tree, Right.Node),
220 "Right cursor of "">"" is bad");
222 return Right.Node.Key < Left;
223 end ">";
225 ------------
226 -- Adjust --
227 ------------
229 procedure Adjust is
230 new Tree_Operations.Generic_Adjust (Copy_Tree);
232 procedure Adjust (Container : in out Map) is
233 begin
234 Adjust (Container.Tree);
235 end Adjust;
237 procedure Adjust (Control : in out Reference_Control_Type) is
238 begin
239 if Control.Container /= null then
240 declare
241 T : Tree_Type renames Control.Container.all.Tree;
242 B : Natural renames T.Busy;
243 L : Natural renames T.Lock;
244 begin
245 B := B + 1;
246 L := L + 1;
247 end;
248 end if;
249 end Adjust;
251 ------------
252 -- Assign --
253 ------------
255 procedure Assign (Target : in out Map; Source : Map) is
256 procedure Insert_Item (Node : Node_Access);
257 pragma Inline (Insert_Item);
259 procedure Insert_Items is
260 new Tree_Operations.Generic_Iteration (Insert_Item);
262 -----------------
263 -- Insert_Item --
264 -----------------
266 procedure Insert_Item (Node : Node_Access) is
267 begin
268 Target.Insert (Key => Node.Key, New_Item => Node.Element);
269 end Insert_Item;
271 -- Start of processing for Assign
273 begin
274 if Target'Address = Source'Address then
275 return;
276 end if;
278 Target.Clear;
279 Insert_Items (Source.Tree);
280 end Assign;
282 -------------
283 -- Ceiling --
284 -------------
286 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
287 Node : constant Node_Access := Key_Ops.Ceiling (Container.Tree, Key);
289 begin
290 if Node = null then
291 return No_Element;
292 end if;
294 return Cursor'(Container'Unrestricted_Access, Node);
295 end Ceiling;
297 -----------
298 -- Clear --
299 -----------
301 procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
303 procedure Clear (Container : in out Map) is
304 begin
305 Clear (Container.Tree);
306 end Clear;
308 -----------
309 -- Color --
310 -----------
312 function Color (Node : Node_Access) return Color_Type is
313 begin
314 return Node.Color;
315 end Color;
317 ------------------------
318 -- Constant_Reference --
319 ------------------------
321 function Constant_Reference
322 (Container : aliased Map;
323 Position : Cursor) return Constant_Reference_Type
325 begin
326 if Position.Container = null then
327 raise Constraint_Error with
328 "Position cursor has no element";
329 end if;
331 if Position.Container /= Container'Unrestricted_Access then
332 raise Program_Error with
333 "Position cursor designates wrong map";
334 end if;
336 pragma Assert (Vet (Container.Tree, Position.Node),
337 "Position cursor in Constant_Reference is bad");
339 declare
340 T : Tree_Type renames Position.Container.all.Tree;
341 B : Natural renames T.Busy;
342 L : Natural renames T.Lock;
343 begin
344 return R : constant Constant_Reference_Type :=
345 (Element => Position.Node.Element'Access,
346 Control => (Controlled with Position.Container))
348 B := B + 1;
349 L := L + 1;
350 end return;
351 end;
352 end Constant_Reference;
354 function Constant_Reference
355 (Container : aliased Map;
356 Key : Key_Type) return Constant_Reference_Type
358 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
360 begin
361 if Node = null then
362 raise Constraint_Error with "key not in map";
363 end if;
365 declare
366 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
367 B : Natural renames T.Busy;
368 L : Natural renames T.Lock;
369 begin
370 return R : constant Constant_Reference_Type :=
371 (Element => Node.Element'Access,
372 Control => (Controlled with Container'Unrestricted_Access))
374 B := B + 1;
375 L := L + 1;
376 end return;
377 end;
378 end Constant_Reference;
380 --------------
381 -- Contains --
382 --------------
384 function Contains (Container : Map; Key : Key_Type) return Boolean is
385 begin
386 return Find (Container, Key) /= No_Element;
387 end Contains;
389 ----------
390 -- Copy --
391 ----------
393 function Copy (Source : Map) return Map is
394 begin
395 return Target : Map do
396 Target.Assign (Source);
397 end return;
398 end Copy;
400 ---------------
401 -- Copy_Node --
402 ---------------
404 function Copy_Node (Source : Node_Access) return Node_Access is
405 Target : constant Node_Access :=
406 new Node_Type'(Color => Source.Color,
407 Key => Source.Key,
408 Element => Source.Element,
409 Parent => null,
410 Left => null,
411 Right => null);
412 begin
413 return Target;
414 end Copy_Node;
416 ------------
417 -- Delete --
418 ------------
420 procedure Delete (Container : in out Map; Position : in out Cursor) is
421 Tree : Tree_Type renames Container.Tree;
423 begin
424 if Position.Node = null then
425 raise Constraint_Error with
426 "Position cursor of Delete equals No_Element";
427 end if;
429 if Position.Container /= Container'Unrestricted_Access then
430 raise Program_Error with
431 "Position cursor of Delete designates wrong map";
432 end if;
434 pragma Assert (Vet (Tree, Position.Node),
435 "Position cursor of Delete is bad");
437 Tree_Operations.Delete_Node_Sans_Free (Tree, Position.Node);
438 Free (Position.Node);
440 Position.Container := null;
441 end Delete;
443 procedure Delete (Container : in out Map; Key : Key_Type) is
444 X : Node_Access := Key_Ops.Find (Container.Tree, Key);
446 begin
447 if X = null then
448 raise Constraint_Error with "key not in map";
449 end if;
451 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
452 Free (X);
453 end Delete;
455 ------------------
456 -- Delete_First --
457 ------------------
459 procedure Delete_First (Container : in out Map) is
460 X : Node_Access := Container.Tree.First;
462 begin
463 if X /= null then
464 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
465 Free (X);
466 end if;
467 end Delete_First;
469 -----------------
470 -- Delete_Last --
471 -----------------
473 procedure Delete_Last (Container : in out Map) is
474 X : Node_Access := Container.Tree.Last;
476 begin
477 if X /= null then
478 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
479 Free (X);
480 end if;
481 end Delete_Last;
483 -------------
484 -- Element --
485 -------------
487 function Element (Position : Cursor) return Element_Type is
488 begin
489 if Position.Node = null then
490 raise Constraint_Error with
491 "Position cursor of function Element equals No_Element";
492 end if;
494 pragma Assert (Vet (Position.Container.Tree, Position.Node),
495 "Position cursor of function Element is bad");
497 return Position.Node.Element;
498 end Element;
500 function Element (Container : Map; Key : Key_Type) return Element_Type is
501 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
503 begin
504 if Node = null then
505 raise Constraint_Error with "key not in map";
506 end if;
508 return Node.Element;
509 end Element;
511 ---------------------
512 -- Equivalent_Keys --
513 ---------------------
515 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
516 begin
517 if Left < Right
518 or else Right < Left
519 then
520 return False;
521 else
522 return True;
523 end if;
524 end Equivalent_Keys;
526 -------------
527 -- Exclude --
528 -------------
530 procedure Exclude (Container : in out Map; Key : Key_Type) is
531 X : Node_Access := Key_Ops.Find (Container.Tree, Key);
533 begin
534 if X /= null then
535 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
536 Free (X);
537 end if;
538 end Exclude;
540 --------------
541 -- Finalize --
542 --------------
544 procedure Finalize (Object : in out Iterator) is
545 begin
546 if Object.Container /= null then
547 declare
548 B : Natural renames Object.Container.all.Tree.Busy;
549 begin
550 B := B - 1;
551 end;
552 end if;
553 end Finalize;
555 procedure Finalize (Control : in out Reference_Control_Type) is
556 begin
557 if Control.Container /= null then
558 declare
559 T : Tree_Type renames Control.Container.all.Tree;
560 B : Natural renames T.Busy;
561 L : Natural renames T.Lock;
562 begin
563 B := B - 1;
564 L := L - 1;
565 end;
567 Control.Container := null;
568 end if;
569 end Finalize;
571 ----------
572 -- Find --
573 ----------
575 function Find (Container : Map; Key : Key_Type) return Cursor is
576 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
577 begin
578 return (if Node = null then No_Element
579 else Cursor'(Container'Unrestricted_Access, Node));
580 end Find;
582 -----------
583 -- First --
584 -----------
586 function First (Container : Map) return Cursor is
587 T : Tree_Type renames Container.Tree;
588 begin
589 if T.First = null then
590 return No_Element;
591 else
592 return Cursor'(Container'Unrestricted_Access, T.First);
593 end if;
594 end First;
596 function First (Object : Iterator) return Cursor is
597 begin
598 -- The value of the iterator object's Node component influences the
599 -- behavior of the First (and Last) selector function.
601 -- When the Node component is null, this means the iterator object was
602 -- constructed without a start expression, in which case the (forward)
603 -- iteration starts from the (logical) beginning of the entire sequence
604 -- of items (corresponding to Container.First, for a forward iterator).
606 -- Otherwise, this is iteration over a partial sequence of items. When
607 -- the Node component is non-null, the iterator object was constructed
608 -- with a start expression, that specifies the position from which the
609 -- (forward) partial iteration begins.
611 if Object.Node = null then
612 return Object.Container.First;
613 else
614 return Cursor'(Object.Container, Object.Node);
615 end if;
616 end First;
618 -------------------
619 -- First_Element --
620 -------------------
622 function First_Element (Container : Map) return Element_Type is
623 T : Tree_Type renames Container.Tree;
624 begin
625 if T.First = null then
626 raise Constraint_Error with "map is empty";
627 else
628 return T.First.Element;
629 end if;
630 end First_Element;
632 ---------------
633 -- First_Key --
634 ---------------
636 function First_Key (Container : Map) return Key_Type is
637 T : Tree_Type renames Container.Tree;
638 begin
639 if T.First = null then
640 raise Constraint_Error with "map is empty";
641 else
642 return T.First.Key;
643 end if;
644 end First_Key;
646 -----------
647 -- Floor --
648 -----------
650 function Floor (Container : Map; Key : Key_Type) return Cursor is
651 Node : constant Node_Access := Key_Ops.Floor (Container.Tree, Key);
652 begin
653 if Node = null then
654 return No_Element;
655 else
656 return Cursor'(Container'Unrestricted_Access, Node);
657 end if;
658 end Floor;
660 ----------
661 -- Free --
662 ----------
664 procedure Free (X : in out Node_Access) is
665 procedure Deallocate is
666 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
668 begin
669 if X = null then
670 return;
671 end if;
673 X.Parent := X;
674 X.Left := X;
675 X.Right := X;
677 Deallocate (X);
678 end Free;
680 -----------------
681 -- Has_Element --
682 -----------------
684 function Has_Element (Position : Cursor) return Boolean is
685 begin
686 return Position /= No_Element;
687 end Has_Element;
689 -------------
690 -- Include --
691 -------------
693 procedure Include
694 (Container : in out Map;
695 Key : Key_Type;
696 New_Item : Element_Type)
698 Position : Cursor;
699 Inserted : Boolean;
701 begin
702 Insert (Container, Key, New_Item, Position, Inserted);
704 if not Inserted then
705 if Container.Tree.Lock > 0 then
706 raise Program_Error with
707 "attempt to tamper with elements (map is locked)";
708 end if;
710 Position.Node.Key := Key;
711 Position.Node.Element := New_Item;
712 end if;
713 end Include;
715 ------------
716 -- Insert --
717 ------------
719 procedure Insert
720 (Container : in out Map;
721 Key : Key_Type;
722 New_Item : Element_Type;
723 Position : out Cursor;
724 Inserted : out Boolean)
726 function New_Node return Node_Access;
727 pragma Inline (New_Node);
729 procedure Insert_Post is
730 new Key_Ops.Generic_Insert_Post (New_Node);
732 procedure Insert_Sans_Hint is
733 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
735 --------------
736 -- New_Node --
737 --------------
739 function New_Node return Node_Access is
740 begin
741 return new Node_Type'(Key => Key,
742 Element => New_Item,
743 Color => Red_Black_Trees.Red,
744 Parent => null,
745 Left => null,
746 Right => null);
747 end New_Node;
749 -- Start of processing for Insert
751 begin
752 Insert_Sans_Hint
753 (Container.Tree,
754 Key,
755 Position.Node,
756 Inserted);
758 Position.Container := Container'Unrestricted_Access;
759 end Insert;
761 procedure Insert
762 (Container : in out Map;
763 Key : Key_Type;
764 New_Item : Element_Type)
766 Position : Cursor;
767 pragma Unreferenced (Position);
769 Inserted : Boolean;
771 begin
772 Insert (Container, Key, New_Item, Position, Inserted);
774 if not Inserted then
775 raise Constraint_Error with "key already in map";
776 end if;
777 end Insert;
779 procedure Insert
780 (Container : in out Map;
781 Key : Key_Type;
782 Position : out Cursor;
783 Inserted : out Boolean)
785 function New_Node return Node_Access;
786 pragma Inline (New_Node);
788 procedure Insert_Post is
789 new Key_Ops.Generic_Insert_Post (New_Node);
791 procedure Insert_Sans_Hint is
792 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
794 --------------
795 -- New_Node --
796 --------------
798 function New_Node return Node_Access is
799 begin
800 return new Node_Type'(Key => Key,
801 Element => <>,
802 Color => Red_Black_Trees.Red,
803 Parent => null,
804 Left => null,
805 Right => null);
806 end New_Node;
808 -- Start of processing for Insert
810 begin
811 Insert_Sans_Hint
812 (Container.Tree,
813 Key,
814 Position.Node,
815 Inserted);
817 Position.Container := Container'Unrestricted_Access;
818 end Insert;
820 --------------
821 -- Is_Empty --
822 --------------
824 function Is_Empty (Container : Map) return Boolean is
825 begin
826 return Container.Tree.Length = 0;
827 end Is_Empty;
829 ------------------------
830 -- Is_Equal_Node_Node --
831 ------------------------
833 function Is_Equal_Node_Node
834 (L, R : Node_Access) return Boolean
836 begin
837 if L.Key < R.Key then
838 return False;
839 elsif R.Key < L.Key then
840 return False;
841 else
842 return L.Element = R.Element;
843 end if;
844 end Is_Equal_Node_Node;
846 -------------------------
847 -- Is_Greater_Key_Node --
848 -------------------------
850 function Is_Greater_Key_Node
851 (Left : Key_Type;
852 Right : Node_Access) return Boolean
854 begin
855 -- Left > Right same as Right < Left
857 return Right.Key < Left;
858 end Is_Greater_Key_Node;
860 ----------------------
861 -- Is_Less_Key_Node --
862 ----------------------
864 function Is_Less_Key_Node
865 (Left : Key_Type;
866 Right : Node_Access) return Boolean
868 begin
869 return Left < Right.Key;
870 end Is_Less_Key_Node;
872 -------------
873 -- Iterate --
874 -------------
876 procedure Iterate
877 (Container : Map;
878 Process : not null access procedure (Position : Cursor))
880 procedure Process_Node (Node : Node_Access);
881 pragma Inline (Process_Node);
883 procedure Local_Iterate is
884 new Tree_Operations.Generic_Iteration (Process_Node);
886 ------------------
887 -- Process_Node --
888 ------------------
890 procedure Process_Node (Node : Node_Access) is
891 begin
892 Process (Cursor'(Container'Unrestricted_Access, Node));
893 end Process_Node;
895 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
897 -- Start of processing for Iterate
899 begin
900 B := B + 1;
902 begin
903 Local_Iterate (Container.Tree);
904 exception
905 when others =>
906 B := B - 1;
907 raise;
908 end;
910 B := B - 1;
911 end Iterate;
913 function Iterate
914 (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
916 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
918 begin
919 -- The value of the Node component influences the behavior of the First
920 -- and Last selector functions of the iterator object. When the Node
921 -- component is null (as is the case here), this means the iterator
922 -- object was constructed without a start expression. This is a
923 -- complete iterator, meaning that the iteration starts from the
924 -- (logical) beginning of the sequence of items.
926 -- Note: For a forward iterator, Container.First is the beginning, and
927 -- for a reverse iterator, Container.Last is the beginning.
929 return It : constant Iterator :=
930 (Limited_Controlled with
931 Container => Container'Unrestricted_Access,
932 Node => null)
934 B := B + 1;
935 end return;
936 end Iterate;
938 function Iterate (Container : Map; Start : Cursor)
939 return Map_Iterator_Interfaces.Reversible_Iterator'Class
941 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
943 begin
944 -- It was formerly the case that when Start = No_Element, the partial
945 -- iterator was defined to behave the same as for a complete iterator,
946 -- and iterate over the entire sequence of items. However, those
947 -- semantics were unintuitive and arguably error-prone (it is too easy
948 -- to accidentally create an endless loop), and so they were changed,
949 -- per the ARG meeting in Denver on 2011/11. However, there was no
950 -- consensus about what positive meaning this corner case should have,
951 -- and so it was decided to simply raise an exception. This does imply,
952 -- however, that it is not possible to use a partial iterator to specify
953 -- an empty sequence of items.
955 if Start = No_Element then
956 raise Constraint_Error with
957 "Start position for iterator equals No_Element";
958 end if;
960 if Start.Container /= Container'Unrestricted_Access then
961 raise Program_Error with
962 "Start cursor of Iterate designates wrong map";
963 end if;
965 pragma Assert (Vet (Container.Tree, Start.Node),
966 "Start cursor of Iterate is bad");
968 -- The value of the Node component influences the behavior of the First
969 -- and Last selector functions of the iterator object. When the Node
970 -- component is non-null (as is the case here), it means that this
971 -- is a partial iteration, over a subset of the complete sequence of
972 -- items. The iterator object was constructed with a start expression,
973 -- indicating the position from which the iteration begins. Note that
974 -- the start position has the same value irrespective of whether this
975 -- is a forward or reverse iteration.
977 return It : constant Iterator :=
978 (Limited_Controlled with
979 Container => Container'Unrestricted_Access,
980 Node => Start.Node)
982 B := B + 1;
983 end return;
984 end Iterate;
986 ---------
987 -- Key --
988 ---------
990 function Key (Position : Cursor) return Key_Type is
991 begin
992 if Position.Node = null then
993 raise Constraint_Error with
994 "Position cursor of function Key equals No_Element";
995 end if;
997 pragma Assert (Vet (Position.Container.Tree, Position.Node),
998 "Position cursor of function Key is bad");
1000 return Position.Node.Key;
1001 end Key;
1003 ----------
1004 -- Last --
1005 ----------
1007 function Last (Container : Map) return Cursor is
1008 T : Tree_Type renames Container.Tree;
1009 begin
1010 if T.Last = null then
1011 return No_Element;
1012 else
1013 return Cursor'(Container'Unrestricted_Access, T.Last);
1014 end if;
1015 end Last;
1017 function Last (Object : Iterator) return Cursor is
1018 begin
1019 -- The value of the iterator object's Node component influences the
1020 -- behavior of the Last (and First) selector function.
1022 -- When the Node component is null, this means the iterator object was
1023 -- constructed without a start expression, in which case the (reverse)
1024 -- iteration starts from the (logical) beginning of the entire sequence
1025 -- (corresponding to Container.Last, for a reverse iterator).
1027 -- Otherwise, this is iteration over a partial sequence of items. When
1028 -- the Node component is non-null, the iterator object was constructed
1029 -- with a start expression, that specifies the position from which the
1030 -- (reverse) partial iteration begins.
1032 if Object.Node = null then
1033 return Object.Container.Last;
1034 else
1035 return Cursor'(Object.Container, Object.Node);
1036 end if;
1037 end Last;
1039 ------------------
1040 -- Last_Element --
1041 ------------------
1043 function Last_Element (Container : Map) return Element_Type is
1044 T : Tree_Type renames Container.Tree;
1045 begin
1046 if T.Last = null then
1047 raise Constraint_Error with "map is empty";
1048 else
1049 return T.Last.Element;
1050 end if;
1051 end Last_Element;
1053 --------------
1054 -- Last_Key --
1055 --------------
1057 function Last_Key (Container : Map) return Key_Type is
1058 T : Tree_Type renames Container.Tree;
1059 begin
1060 if T.Last = null then
1061 raise Constraint_Error with "map is empty";
1062 else
1063 return T.Last.Key;
1064 end if;
1065 end Last_Key;
1067 ----------
1068 -- Left --
1069 ----------
1071 function Left (Node : Node_Access) return Node_Access is
1072 begin
1073 return Node.Left;
1074 end Left;
1076 ------------
1077 -- Length --
1078 ------------
1080 function Length (Container : Map) return Count_Type is
1081 begin
1082 return Container.Tree.Length;
1083 end Length;
1085 ----------
1086 -- Move --
1087 ----------
1089 procedure Move is
1090 new Tree_Operations.Generic_Move (Clear);
1092 procedure Move (Target : in out Map; Source : in out Map) is
1093 begin
1094 Move (Target => Target.Tree, Source => Source.Tree);
1095 end Move;
1097 ----------
1098 -- Next --
1099 ----------
1101 procedure Next (Position : in out Cursor) is
1102 begin
1103 Position := Next (Position);
1104 end Next;
1106 function Next (Position : Cursor) return Cursor is
1107 begin
1108 if Position = No_Element then
1109 return No_Element;
1110 end if;
1112 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1113 "Position cursor of Next is bad");
1115 declare
1116 Node : constant Node_Access := Tree_Operations.Next (Position.Node);
1118 begin
1119 if Node = null then
1120 return No_Element;
1121 end if;
1123 return Cursor'(Position.Container, Node);
1124 end;
1125 end Next;
1127 function Next
1128 (Object : Iterator;
1129 Position : Cursor) return Cursor
1131 begin
1132 if Position.Container = null then
1133 return No_Element;
1134 end if;
1136 if Position.Container /= Object.Container then
1137 raise Program_Error with
1138 "Position cursor of Next designates wrong map";
1139 end if;
1141 return Next (Position);
1142 end Next;
1144 ------------
1145 -- Parent --
1146 ------------
1148 function Parent (Node : Node_Access) return Node_Access is
1149 begin
1150 return Node.Parent;
1151 end Parent;
1153 --------------
1154 -- Previous --
1155 --------------
1157 procedure Previous (Position : in out Cursor) is
1158 begin
1159 Position := Previous (Position);
1160 end Previous;
1162 function Previous (Position : Cursor) return Cursor is
1163 begin
1164 if Position = No_Element then
1165 return No_Element;
1166 end if;
1168 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1169 "Position cursor of Previous is bad");
1171 declare
1172 Node : constant Node_Access :=
1173 Tree_Operations.Previous (Position.Node);
1175 begin
1176 if Node = null then
1177 return No_Element;
1178 end if;
1180 return Cursor'(Position.Container, Node);
1181 end;
1182 end Previous;
1184 function Previous
1185 (Object : Iterator;
1186 Position : Cursor) return Cursor
1188 begin
1189 if Position.Container = null then
1190 return No_Element;
1191 end if;
1193 if Position.Container /= Object.Container then
1194 raise Program_Error with
1195 "Position cursor of Previous designates wrong map";
1196 end if;
1198 return Previous (Position);
1199 end Previous;
1201 -------------------
1202 -- Query_Element --
1203 -------------------
1205 procedure Query_Element
1206 (Position : Cursor;
1207 Process : not null access procedure (Key : Key_Type;
1208 Element : Element_Type))
1210 begin
1211 if Position.Node = null then
1212 raise Constraint_Error with
1213 "Position cursor of Query_Element equals No_Element";
1214 end if;
1216 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1217 "Position cursor of Query_Element is bad");
1219 declare
1220 T : Tree_Type renames Position.Container.Tree;
1222 B : Natural renames T.Busy;
1223 L : Natural renames T.Lock;
1225 begin
1226 B := B + 1;
1227 L := L + 1;
1229 declare
1230 K : Key_Type renames Position.Node.Key;
1231 E : Element_Type renames Position.Node.Element;
1233 begin
1234 Process (K, E);
1235 exception
1236 when others =>
1237 L := L - 1;
1238 B := B - 1;
1239 raise;
1240 end;
1242 L := L - 1;
1243 B := B - 1;
1244 end;
1245 end Query_Element;
1247 ----------
1248 -- Read --
1249 ----------
1251 procedure Read
1252 (Stream : not null access Root_Stream_Type'Class;
1253 Container : out Map)
1255 function Read_Node
1256 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1257 pragma Inline (Read_Node);
1259 procedure Read is
1260 new Tree_Operations.Generic_Read (Clear, Read_Node);
1262 ---------------
1263 -- Read_Node --
1264 ---------------
1266 function Read_Node
1267 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1269 Node : Node_Access := new Node_Type;
1270 begin
1271 Key_Type'Read (Stream, Node.Key);
1272 Element_Type'Read (Stream, Node.Element);
1273 return Node;
1274 exception
1275 when others =>
1276 Free (Node);
1277 raise;
1278 end Read_Node;
1280 -- Start of processing for Read
1282 begin
1283 Read (Stream, Container.Tree);
1284 end Read;
1286 procedure Read
1287 (Stream : not null access Root_Stream_Type'Class;
1288 Item : out Cursor)
1290 begin
1291 raise Program_Error with "attempt to stream map cursor";
1292 end Read;
1294 procedure Read
1295 (Stream : not null access Root_Stream_Type'Class;
1296 Item : out Reference_Type)
1298 begin
1299 raise Program_Error with "attempt to stream reference";
1300 end Read;
1302 procedure Read
1303 (Stream : not null access Root_Stream_Type'Class;
1304 Item : out Constant_Reference_Type)
1306 begin
1307 raise Program_Error with "attempt to stream reference";
1308 end Read;
1310 ---------------
1311 -- Reference --
1312 ---------------
1314 function Reference
1315 (Container : aliased in out Map;
1316 Position : Cursor) return Reference_Type
1318 begin
1319 if Position.Container = null then
1320 raise Constraint_Error with
1321 "Position cursor has no element";
1322 end if;
1324 if Position.Container /= Container'Unrestricted_Access then
1325 raise Program_Error with
1326 "Position cursor designates wrong map";
1327 end if;
1329 pragma Assert (Vet (Container.Tree, Position.Node),
1330 "Position cursor in function Reference is bad");
1332 declare
1333 T : Tree_Type renames Position.Container.all.Tree;
1334 B : Natural renames T.Busy;
1335 L : Natural renames T.Lock;
1336 begin
1337 return R : constant Reference_Type :=
1338 (Element => Position.Node.Element'Access,
1339 Control => (Controlled with Position.Container))
1341 B := B + 1;
1342 L := L + 1;
1343 end return;
1344 end;
1345 end Reference;
1347 function Reference
1348 (Container : aliased in out Map;
1349 Key : Key_Type) return Reference_Type
1351 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
1353 begin
1354 if Node = null then
1355 raise Constraint_Error with "key not in map";
1356 end if;
1358 declare
1359 T : Tree_Type renames Container'Unrestricted_Access.all.Tree;
1360 B : Natural renames T.Busy;
1361 L : Natural renames T.Lock;
1362 begin
1363 return R : constant Reference_Type :=
1364 (Element => Node.Element'Access,
1365 Control => (Controlled with Container'Unrestricted_Access))
1367 B := B + 1;
1368 L := L + 1;
1369 end return;
1370 end;
1371 end Reference;
1373 -------------
1374 -- Replace --
1375 -------------
1377 procedure Replace
1378 (Container : in out Map;
1379 Key : Key_Type;
1380 New_Item : Element_Type)
1382 Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
1384 begin
1385 if Node = null then
1386 raise Constraint_Error with "key not in map";
1387 end if;
1389 if Container.Tree.Lock > 0 then
1390 raise Program_Error with
1391 "attempt to tamper with elements (map is locked)";
1392 end if;
1394 Node.Key := Key;
1395 Node.Element := New_Item;
1396 end Replace;
1398 ---------------------
1399 -- Replace_Element --
1400 ---------------------
1402 procedure Replace_Element
1403 (Container : in out Map;
1404 Position : Cursor;
1405 New_Item : Element_Type)
1407 begin
1408 if Position.Node = null then
1409 raise Constraint_Error with
1410 "Position cursor of Replace_Element equals No_Element";
1411 end if;
1413 if Position.Container /= Container'Unrestricted_Access then
1414 raise Program_Error with
1415 "Position cursor of Replace_Element designates wrong map";
1416 end if;
1418 if Container.Tree.Lock > 0 then
1419 raise Program_Error with
1420 "attempt to tamper with elements (map is locked)";
1421 end if;
1423 pragma Assert (Vet (Container.Tree, Position.Node),
1424 "Position cursor of Replace_Element is bad");
1426 Position.Node.Element := New_Item;
1427 end Replace_Element;
1429 ---------------------
1430 -- Reverse_Iterate --
1431 ---------------------
1433 procedure Reverse_Iterate
1434 (Container : Map;
1435 Process : not null access procedure (Position : Cursor))
1437 procedure Process_Node (Node : Node_Access);
1438 pragma Inline (Process_Node);
1440 procedure Local_Reverse_Iterate is
1441 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1443 ------------------
1444 -- Process_Node --
1445 ------------------
1447 procedure Process_Node (Node : Node_Access) is
1448 begin
1449 Process (Cursor'(Container'Unrestricted_Access, Node));
1450 end Process_Node;
1452 B : Natural renames Container.Tree'Unrestricted_Access.all.Busy;
1454 -- Start of processing for Reverse_Iterate
1456 begin
1457 B := B + 1;
1459 begin
1460 Local_Reverse_Iterate (Container.Tree);
1461 exception
1462 when others =>
1463 B := B - 1;
1464 raise;
1465 end;
1467 B := B - 1;
1468 end Reverse_Iterate;
1470 -----------
1471 -- Right --
1472 -----------
1474 function Right (Node : Node_Access) return Node_Access is
1475 begin
1476 return Node.Right;
1477 end Right;
1479 ---------------
1480 -- Set_Color --
1481 ---------------
1483 procedure Set_Color
1484 (Node : Node_Access;
1485 Color : Color_Type)
1487 begin
1488 Node.Color := Color;
1489 end Set_Color;
1491 --------------
1492 -- Set_Left --
1493 --------------
1495 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1496 begin
1497 Node.Left := Left;
1498 end Set_Left;
1500 ----------------
1501 -- Set_Parent --
1502 ----------------
1504 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1505 begin
1506 Node.Parent := Parent;
1507 end Set_Parent;
1509 ---------------
1510 -- Set_Right --
1511 ---------------
1513 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1514 begin
1515 Node.Right := Right;
1516 end Set_Right;
1518 --------------------
1519 -- Update_Element --
1520 --------------------
1522 procedure Update_Element
1523 (Container : in out Map;
1524 Position : Cursor;
1525 Process : not null access procedure (Key : Key_Type;
1526 Element : in out Element_Type))
1528 begin
1529 if Position.Node = null then
1530 raise Constraint_Error with
1531 "Position cursor of Update_Element equals No_Element";
1532 end if;
1534 if Position.Container /= Container'Unrestricted_Access then
1535 raise Program_Error with
1536 "Position cursor of Update_Element designates wrong map";
1537 end if;
1539 pragma Assert (Vet (Container.Tree, Position.Node),
1540 "Position cursor of Update_Element is bad");
1542 declare
1543 T : Tree_Type renames Container.Tree;
1545 B : Natural renames T.Busy;
1546 L : Natural renames T.Lock;
1548 begin
1549 B := B + 1;
1550 L := L + 1;
1552 declare
1553 K : Key_Type renames Position.Node.Key;
1554 E : Element_Type renames Position.Node.Element;
1556 begin
1557 Process (K, E);
1559 exception
1560 when others =>
1561 L := L - 1;
1562 B := B - 1;
1563 raise;
1564 end;
1566 L := L - 1;
1567 B := B - 1;
1568 end;
1569 end Update_Element;
1571 -----------
1572 -- Write --
1573 -----------
1575 procedure Write
1576 (Stream : not null access Root_Stream_Type'Class;
1577 Container : Map)
1579 procedure Write_Node
1580 (Stream : not null access Root_Stream_Type'Class;
1581 Node : Node_Access);
1582 pragma Inline (Write_Node);
1584 procedure Write is
1585 new Tree_Operations.Generic_Write (Write_Node);
1587 ----------------
1588 -- Write_Node --
1589 ----------------
1591 procedure Write_Node
1592 (Stream : not null access Root_Stream_Type'Class;
1593 Node : Node_Access)
1595 begin
1596 Key_Type'Write (Stream, Node.Key);
1597 Element_Type'Write (Stream, Node.Element);
1598 end Write_Node;
1600 -- Start of processing for Write
1602 begin
1603 Write (Stream, Container.Tree);
1604 end Write;
1606 procedure Write
1607 (Stream : not null access Root_Stream_Type'Class;
1608 Item : Cursor)
1610 begin
1611 raise Program_Error with "attempt to stream map cursor";
1612 end Write;
1614 procedure Write
1615 (Stream : not null access Root_Stream_Type'Class;
1616 Item : Reference_Type)
1618 begin
1619 raise Program_Error with "attempt to stream reference";
1620 end Write;
1622 procedure Write
1623 (Stream : not null access Root_Stream_Type'Class;
1624 Item : Constant_Reference_Type)
1626 begin
1627 raise Program_Error with "attempt to stream reference";
1628 end Write;
1630 end Ada.Containers.Ordered_Maps;