* contrib-list.mk (LIST): Remove arm-freebsd6, arm-linux,
[official-gcc.git] / gcc / ada / a-cborma.adb
bloba782d39af7139d05da97e610d750228a68db4894
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-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 -- --
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 Ada.Finalization; use Ada.Finalization;
40 with System; use type System.Address;
42 package body Ada.Containers.Bounded_Ordered_Maps is
44 type Iterator is new Limited_Controlled and
45 Map_Iterator_Interfaces.Reversible_Iterator with
46 record
47 Container : Map_Access;
48 Node : Count_Type;
49 end record;
51 overriding procedure Finalize (Object : in out Iterator);
53 overriding function First (Object : Iterator) return Cursor;
54 overriding function Last (Object : Iterator) return Cursor;
56 overriding function Next
57 (Object : Iterator;
58 Position : Cursor) return Cursor;
60 overriding function Previous
61 (Object : Iterator;
62 Position : Cursor) return Cursor;
64 -----------------------------
65 -- Node Access Subprograms --
66 -----------------------------
68 -- These subprograms provide a functional interface to access fields
69 -- of a node, and a procedural interface for modifying these values.
71 function Color (Node : Node_Type) return Color_Type;
72 pragma Inline (Color);
74 function Left (Node : Node_Type) return Count_Type;
75 pragma Inline (Left);
77 function Parent (Node : Node_Type) return Count_Type;
78 pragma Inline (Parent);
80 function Right (Node : Node_Type) return Count_Type;
81 pragma Inline (Right);
83 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
84 pragma Inline (Set_Parent);
86 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
87 pragma Inline (Set_Left);
89 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
90 pragma Inline (Set_Right);
92 procedure Set_Color (Node : in out Node_Type; Color : Color_Type);
93 pragma Inline (Set_Color);
95 -----------------------
96 -- Local Subprograms --
97 -----------------------
99 function Is_Greater_Key_Node
100 (Left : Key_Type;
101 Right : Node_Type) return Boolean;
102 pragma Inline (Is_Greater_Key_Node);
104 function Is_Less_Key_Node
105 (Left : Key_Type;
106 Right : Node_Type) return Boolean;
107 pragma Inline (Is_Less_Key_Node);
109 --------------------------
110 -- Local Instantiations --
111 --------------------------
113 package Tree_Operations is
114 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
116 use Tree_Operations;
118 package Key_Ops is
119 new Red_Black_Trees.Generic_Bounded_Keys
120 (Tree_Operations => Tree_Operations,
121 Key_Type => Key_Type,
122 Is_Less_Key_Node => Is_Less_Key_Node,
123 Is_Greater_Key_Node => Is_Greater_Key_Node);
125 ---------
126 -- "<" --
127 ---------
129 function "<" (Left, Right : Cursor) return Boolean is
130 begin
131 if Left.Node = 0 then
132 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
133 end if;
135 if Right.Node = 0 then
136 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
137 end if;
139 pragma Assert (Vet (Left.Container.all, Left.Node),
140 "Left cursor of ""<"" is bad");
142 pragma Assert (Vet (Right.Container.all, Right.Node),
143 "Right cursor of ""<"" is bad");
145 declare
146 LN : Node_Type renames Left.Container.Nodes (Left.Node);
147 RN : Node_Type renames Right.Container.Nodes (Right.Node);
149 begin
150 return LN.Key < RN.Key;
151 end;
152 end "<";
154 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
155 begin
156 if Left.Node = 0 then
157 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
158 end if;
160 pragma Assert (Vet (Left.Container.all, Left.Node),
161 "Left cursor of ""<"" is bad");
163 declare
164 LN : Node_Type renames Left.Container.Nodes (Left.Node);
166 begin
167 return LN.Key < Right;
168 end;
169 end "<";
171 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
172 begin
173 if Right.Node = 0 then
174 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
175 end if;
177 pragma Assert (Vet (Right.Container.all, Right.Node),
178 "Right cursor of ""<"" is bad");
180 declare
181 RN : Node_Type renames Right.Container.Nodes (Right.Node);
183 begin
184 return Left < RN.Key;
185 end;
186 end "<";
188 ---------
189 -- "=" --
190 ---------
192 function "=" (Left, Right : Map) return Boolean is
193 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
194 pragma Inline (Is_Equal_Node_Node);
196 function Is_Equal is
197 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
199 ------------------------
200 -- Is_Equal_Node_Node --
201 ------------------------
203 function Is_Equal_Node_Node
204 (L, R : Node_Type) return Boolean is
205 begin
206 if L.Key < R.Key then
207 return False;
209 elsif R.Key < L.Key then
210 return False;
212 else
213 return L.Element = R.Element;
214 end if;
215 end Is_Equal_Node_Node;
217 -- Start of processing for "="
219 begin
220 return Is_Equal (Left, Right);
221 end "=";
223 ---------
224 -- ">" --
225 ---------
227 function ">" (Left, Right : Cursor) return Boolean is
228 begin
229 if Left.Node = 0 then
230 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
231 end if;
233 if Right.Node = 0 then
234 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
235 end if;
237 pragma Assert (Vet (Left.Container.all, Left.Node),
238 "Left cursor of "">"" is bad");
240 pragma Assert (Vet (Right.Container.all, Right.Node),
241 "Right cursor of "">"" is bad");
243 declare
244 LN : Node_Type renames Left.Container.Nodes (Left.Node);
245 RN : Node_Type renames Right.Container.Nodes (Right.Node);
247 begin
248 return RN.Key < LN.Key;
249 end;
250 end ">";
252 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
253 begin
254 if Left.Node = 0 then
255 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
256 end if;
258 pragma Assert (Vet (Left.Container.all, Left.Node),
259 "Left cursor of "">"" is bad");
261 declare
262 LN : Node_Type renames Left.Container.Nodes (Left.Node);
263 begin
264 return Right < LN.Key;
265 end;
266 end ">";
268 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
269 begin
270 if Right.Node = 0 then
271 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
272 end if;
274 pragma Assert (Vet (Right.Container.all, Right.Node),
275 "Right cursor of "">"" is bad");
277 declare
278 RN : Node_Type renames Right.Container.Nodes (Right.Node);
280 begin
281 return RN.Key < Left;
282 end;
283 end ">";
285 ------------
286 -- Assign --
287 ------------
289 procedure Assign (Target : in out Map; Source : Map) is
290 procedure Append_Element (Source_Node : Count_Type);
292 procedure Append_Elements is
293 new Tree_Operations.Generic_Iteration (Append_Element);
295 --------------------
296 -- Append_Element --
297 --------------------
299 procedure Append_Element (Source_Node : Count_Type) is
300 SN : Node_Type renames Source.Nodes (Source_Node);
302 procedure Set_Element (Node : in out Node_Type);
303 pragma Inline (Set_Element);
305 function New_Node return Count_Type;
306 pragma Inline (New_Node);
308 procedure Insert_Post is
309 new Key_Ops.Generic_Insert_Post (New_Node);
311 procedure Unconditional_Insert_Sans_Hint is
312 new Key_Ops.Generic_Unconditional_Insert (Insert_Post);
314 procedure Unconditional_Insert_Avec_Hint is
315 new Key_Ops.Generic_Unconditional_Insert_With_Hint
316 (Insert_Post,
317 Unconditional_Insert_Sans_Hint);
319 procedure Allocate is
320 new Tree_Operations.Generic_Allocate (Set_Element);
322 --------------
323 -- New_Node --
324 --------------
326 function New_Node return Count_Type is
327 Result : Count_Type;
329 begin
330 Allocate (Target, Result);
331 return Result;
332 end New_Node;
334 -----------------
335 -- Set_Element --
336 -----------------
338 procedure Set_Element (Node : in out Node_Type) is
339 begin
340 Node.Key := SN.Key;
341 Node.Element := SN.Element;
342 end Set_Element;
344 Target_Node : Count_Type;
346 -- Start of processing for Append_Element
348 begin
349 Unconditional_Insert_Avec_Hint
350 (Tree => Target,
351 Hint => 0,
352 Key => SN.Key,
353 Node => Target_Node);
354 end Append_Element;
356 -- Start of processing for Assign
358 begin
359 if Target'Address = Source'Address then
360 return;
361 end if;
363 if Target.Capacity < Source.Length then
364 raise Capacity_Error
365 with "Target capacity is less than Source length";
366 end if;
368 Tree_Operations.Clear_Tree (Target);
369 Append_Elements (Source);
370 end Assign;
372 -------------
373 -- Ceiling --
374 -------------
376 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
377 Node : constant Count_Type := Key_Ops.Ceiling (Container, Key);
379 begin
380 if Node = 0 then
381 return No_Element;
382 end if;
384 return Cursor'(Container'Unrestricted_Access, Node);
385 end Ceiling;
387 -----------
388 -- Clear --
389 -----------
391 procedure Clear (Container : in out Map) is
392 begin
393 Tree_Operations.Clear_Tree (Container);
394 end Clear;
396 -----------
397 -- Color --
398 -----------
400 function Color (Node : Node_Type) return Color_Type is
401 begin
402 return Node.Color;
403 end Color;
405 ------------------------
406 -- Constant_Reference --
407 ------------------------
409 function Constant_Reference
410 (Container : aliased Map;
411 Position : Cursor) return Constant_Reference_Type
413 begin
414 if Position.Container = null then
415 raise Constraint_Error with
416 "Position cursor has no element";
417 end if;
419 if Position.Container /= Container'Unrestricted_Access then
420 raise Program_Error with
421 "Position cursor designates wrong map";
422 end if;
424 pragma Assert (Vet (Container, Position.Node),
425 "Position cursor in Constant_Reference is bad");
427 declare
428 N : Node_Type renames Container.Nodes (Position.Node);
429 begin
430 return (Element => N.Element'Access);
431 end;
432 end Constant_Reference;
434 function Constant_Reference
435 (Container : aliased Map;
436 Key : Key_Type) return Constant_Reference_Type
438 Node : constant Count_Type := Key_Ops.Find (Container, Key);
440 begin
441 if Node = 0 then
442 raise Constraint_Error with "key not in map";
443 end if;
445 declare
446 N : Node_Type renames Container.Nodes (Node);
447 begin
448 return (Element => N.Element'Access);
449 end;
450 end Constant_Reference;
452 --------------
453 -- Contains --
454 --------------
456 function Contains (Container : Map; Key : Key_Type) return Boolean is
457 begin
458 return Find (Container, Key) /= No_Element;
459 end Contains;
461 ----------
462 -- Copy --
463 ----------
465 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
466 C : Count_Type;
468 begin
469 if Capacity = 0 then
470 C := Source.Length;
472 elsif Capacity >= Source.Length then
473 C := Capacity;
475 else
476 raise Capacity_Error with "Capacity value too small";
477 end if;
479 return Target : Map (Capacity => C) do
480 Assign (Target => Target, Source => Source);
481 end return;
482 end Copy;
484 ------------
485 -- Delete --
486 ------------
488 procedure Delete (Container : in out Map; Position : in out Cursor) is
489 begin
490 if Position.Node = 0 then
491 raise Constraint_Error with
492 "Position cursor of Delete equals No_Element";
493 end if;
495 if Position.Container /= Container'Unrestricted_Access then
496 raise Program_Error with
497 "Position cursor of Delete designates wrong map";
498 end if;
500 pragma Assert (Vet (Container, Position.Node),
501 "Position cursor of Delete is bad");
503 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
504 Tree_Operations.Free (Container, Position.Node);
506 Position := No_Element;
507 end Delete;
509 procedure Delete (Container : in out Map; Key : Key_Type) is
510 X : constant Count_Type := Key_Ops.Find (Container, Key);
512 begin
513 if X = 0 then
514 raise Constraint_Error with "key not in map";
515 end if;
517 Tree_Operations.Delete_Node_Sans_Free (Container, X);
518 Tree_Operations.Free (Container, X);
519 end Delete;
521 ------------------
522 -- Delete_First --
523 ------------------
525 procedure Delete_First (Container : in out Map) is
526 X : constant Count_Type := Container.First;
528 begin
529 if X /= 0 then
530 Tree_Operations.Delete_Node_Sans_Free (Container, X);
531 Tree_Operations.Free (Container, X);
532 end if;
533 end Delete_First;
535 -----------------
536 -- Delete_Last --
537 -----------------
539 procedure Delete_Last (Container : in out Map) is
540 X : constant Count_Type := Container.Last;
542 begin
543 if X /= 0 then
544 Tree_Operations.Delete_Node_Sans_Free (Container, X);
545 Tree_Operations.Free (Container, X);
546 end if;
547 end Delete_Last;
549 -------------
550 -- Element --
551 -------------
553 function Element (Position : Cursor) return Element_Type is
554 begin
555 if Position.Node = 0 then
556 raise Constraint_Error with
557 "Position cursor of function Element equals No_Element";
558 end if;
560 pragma Assert (Vet (Position.Container.all, Position.Node),
561 "Position cursor of function Element is bad");
563 return Position.Container.Nodes (Position.Node).Element;
564 end Element;
566 function Element (Container : Map; Key : Key_Type) return Element_Type is
567 Node : constant Count_Type := Key_Ops.Find (Container, Key);
568 begin
569 if Node = 0 then
570 raise Constraint_Error with "key not in map";
571 else
572 return Container.Nodes (Node).Element;
573 end if;
574 end Element;
576 ---------------------
577 -- Equivalent_Keys --
578 ---------------------
580 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
581 begin
582 if Left < Right
583 or else Right < Left
584 then
585 return False;
586 else
587 return True;
588 end if;
589 end Equivalent_Keys;
591 -------------
592 -- Exclude --
593 -------------
595 procedure Exclude (Container : in out Map; Key : Key_Type) is
596 X : constant Count_Type := Key_Ops.Find (Container, Key);
598 begin
599 if X /= 0 then
600 Tree_Operations.Delete_Node_Sans_Free (Container, X);
601 Tree_Operations.Free (Container, X);
602 end if;
603 end Exclude;
605 --------------
606 -- Finalize --
607 --------------
609 procedure Finalize (Object : in out Iterator) is
610 begin
611 if Object.Container /= null then
612 declare
613 B : Natural renames Object.Container.all.Busy;
614 begin
615 B := B - 1;
616 end;
617 end if;
618 end Finalize;
620 ----------
621 -- Find --
622 ----------
624 function Find (Container : Map; Key : Key_Type) return Cursor is
625 Node : constant Count_Type := Key_Ops.Find (Container, Key);
626 begin
627 if Node = 0 then
628 return No_Element;
629 else
630 return Cursor'(Container'Unrestricted_Access, Node);
631 end if;
632 end Find;
634 -----------
635 -- First --
636 -----------
638 function First (Container : Map) return Cursor is
639 begin
640 if Container.First = 0 then
641 return No_Element;
642 else
643 return Cursor'(Container'Unrestricted_Access, Container.First);
644 end if;
645 end First;
647 function First (Object : Iterator) return Cursor is
648 begin
649 -- The value of the iterator object's Node component influences the
650 -- behavior of the First (and Last) selector function.
652 -- When the Node component is 0, this means the iterator object was
653 -- constructed without a start expression, in which case the (forward)
654 -- iteration starts from the (logical) beginning of the entire sequence
655 -- of items (corresponding to Container.First, for a forward iterator).
657 -- Otherwise, this is iteration over a partial sequence of items. When
658 -- the Node component is positive, the iterator object was constructed
659 -- with a start expression, that specifies the position from which the
660 -- (forward) partial iteration begins.
662 if Object.Node = 0 then
663 return Bounded_Ordered_Maps.First (Object.Container.all);
664 else
665 return Cursor'(Object.Container, Object.Node);
666 end if;
667 end First;
669 -------------------
670 -- First_Element --
671 -------------------
673 function First_Element (Container : Map) return Element_Type is
674 begin
675 if Container.First = 0 then
676 raise Constraint_Error with "map is empty";
677 else
678 return Container.Nodes (Container.First).Element;
679 end if;
680 end First_Element;
682 ---------------
683 -- First_Key --
684 ---------------
686 function First_Key (Container : Map) return Key_Type is
687 begin
688 if Container.First = 0 then
689 raise Constraint_Error with "map is empty";
690 else
691 return Container.Nodes (Container.First).Key;
692 end if;
693 end First_Key;
695 -----------
696 -- Floor --
697 -----------
699 function Floor (Container : Map; Key : Key_Type) return Cursor is
700 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
701 begin
702 if Node = 0 then
703 return No_Element;
704 else
705 return Cursor'(Container'Unrestricted_Access, Node);
706 end if;
707 end Floor;
709 -----------------
710 -- Has_Element --
711 -----------------
713 function Has_Element (Position : Cursor) return Boolean is
714 begin
715 return Position /= No_Element;
716 end Has_Element;
718 -------------
719 -- Include --
720 -------------
722 procedure Include
723 (Container : in out Map;
724 Key : Key_Type;
725 New_Item : Element_Type)
727 Position : Cursor;
728 Inserted : Boolean;
730 begin
731 Insert (Container, Key, New_Item, Position, Inserted);
733 if not Inserted then
734 if Container.Lock > 0 then
735 raise Program_Error with
736 "attempt to tamper with elements (map is locked)";
737 end if;
739 declare
740 N : Node_Type renames Container.Nodes (Position.Node);
741 begin
742 N.Key := Key;
743 N.Element := New_Item;
744 end;
745 end if;
746 end Include;
748 ------------
749 -- Insert --
750 ------------
752 procedure Insert
753 (Container : in out Map;
754 Key : Key_Type;
755 New_Item : Element_Type;
756 Position : out Cursor;
757 Inserted : out Boolean)
759 procedure Assign (Node : in out Node_Type);
760 pragma Inline (Assign);
762 function New_Node return Count_Type;
763 pragma Inline (New_Node);
765 procedure Insert_Post is
766 new Key_Ops.Generic_Insert_Post (New_Node);
768 procedure Insert_Sans_Hint is
769 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
771 procedure Allocate is
772 new Tree_Operations.Generic_Allocate (Assign);
774 ------------
775 -- Assign --
776 ------------
778 procedure Assign (Node : in out Node_Type) is
779 begin
780 Node.Key := Key;
781 Node.Element := New_Item;
782 end Assign;
784 --------------
785 -- New_Node --
786 --------------
788 function New_Node return Count_Type is
789 Result : Count_Type;
790 begin
791 Allocate (Container, Result);
792 return Result;
793 end New_Node;
795 -- Start of processing for Insert
797 begin
798 Insert_Sans_Hint
799 (Container,
800 Key,
801 Position.Node,
802 Inserted);
804 Position.Container := Container'Unrestricted_Access;
805 end Insert;
807 procedure Insert
808 (Container : in out Map;
809 Key : Key_Type;
810 New_Item : Element_Type)
812 Position : Cursor;
813 pragma Unreferenced (Position);
815 Inserted : Boolean;
817 begin
818 Insert (Container, Key, New_Item, Position, Inserted);
820 if not Inserted then
821 raise Constraint_Error with "key already in map";
822 end if;
823 end Insert;
825 procedure Insert
826 (Container : in out Map;
827 Key : Key_Type;
828 Position : out Cursor;
829 Inserted : out Boolean)
831 procedure Assign (Node : in out Node_Type);
832 pragma Inline (Assign);
834 function New_Node return Count_Type;
835 pragma Inline (New_Node);
837 procedure Insert_Post is
838 new Key_Ops.Generic_Insert_Post (New_Node);
840 procedure Insert_Sans_Hint is
841 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
843 procedure Allocate is
844 new Tree_Operations.Generic_Allocate (Assign);
846 ------------
847 -- Assign --
848 ------------
850 procedure Assign (Node : in out Node_Type) is
851 begin
852 Node.Key := Key;
854 -- Were this insertion operation to accept an element parameter, this
855 -- is the point where the element value would be used, to update the
856 -- element component of the new node. However, this insertion
857 -- operation is special, in the sense that it does not accept an
858 -- element parameter. Rather, this version of Insert allocates a node
859 -- (inserting it among the active nodes of the container in the
860 -- normal way, with the node's position being determined by the Key),
861 -- and passes back a cursor designating the node. It is then up to
862 -- the caller to assign a value to the node's element.
864 -- Node.Element := New_Item;
865 end Assign;
867 --------------
868 -- New_Node --
869 --------------
871 function New_Node return Count_Type is
872 Result : Count_Type;
873 begin
874 Allocate (Container, Result);
875 return Result;
876 end New_Node;
878 -- Start of processing for Insert
880 begin
881 Insert_Sans_Hint
882 (Container,
883 Key,
884 Position.Node,
885 Inserted);
887 Position.Container := Container'Unrestricted_Access;
888 end Insert;
890 --------------
891 -- Is_Empty --
892 --------------
894 function Is_Empty (Container : Map) return Boolean is
895 begin
896 return Container.Length = 0;
897 end Is_Empty;
899 -------------------------
900 -- Is_Greater_Key_Node --
901 -------------------------
903 function Is_Greater_Key_Node
904 (Left : Key_Type;
905 Right : Node_Type) return Boolean
907 begin
908 -- Left > Right same as Right < Left
910 return Right.Key < Left;
911 end Is_Greater_Key_Node;
913 ----------------------
914 -- Is_Less_Key_Node --
915 ----------------------
917 function Is_Less_Key_Node
918 (Left : Key_Type;
919 Right : Node_Type) return Boolean
921 begin
922 return Left < Right.Key;
923 end Is_Less_Key_Node;
925 -------------
926 -- Iterate --
927 -------------
929 procedure Iterate
930 (Container : Map;
931 Process : not null access procedure (Position : Cursor))
933 procedure Process_Node (Node : Count_Type);
934 pragma Inline (Process_Node);
936 procedure Local_Iterate is
937 new Tree_Operations.Generic_Iteration (Process_Node);
939 ------------------
940 -- Process_Node --
941 ------------------
943 procedure Process_Node (Node : Count_Type) is
944 begin
945 Process (Cursor'(Container'Unrestricted_Access, Node));
946 end Process_Node;
948 B : Natural renames Container'Unrestricted_Access.all.Busy;
950 -- Start of processing for Iterate
952 begin
953 B := B + 1;
955 begin
956 Local_Iterate (Container);
957 exception
958 when others =>
959 B := B - 1;
960 raise;
961 end;
963 B := B - 1;
964 end Iterate;
966 function Iterate
967 (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
969 B : Natural renames Container'Unrestricted_Access.all.Busy;
971 begin
972 -- The value of the Node component influences the behavior of the First
973 -- and Last selector functions of the iterator object. When the Node
974 -- component is 0 (as is the case here), this means the iterator object
975 -- was constructed without a start expression. This is a complete
976 -- iterator, meaning that the iteration starts from the (logical)
977 -- beginning of the sequence of items.
979 -- Note: For a forward iterator, Container.First is the beginning, and
980 -- for a reverse iterator, Container.Last is the beginning.
982 return It : constant Iterator :=
983 (Limited_Controlled with
984 Container => Container'Unrestricted_Access,
985 Node => 0)
987 B := B + 1;
988 end return;
989 end Iterate;
991 function Iterate
992 (Container : Map;
993 Start : Cursor)
994 return Map_Iterator_Interfaces.Reversible_Iterator'Class
996 B : Natural renames Container'Unrestricted_Access.all.Busy;
998 begin
999 -- Iterator was defined to behave the same as for a complete iterator,
1000 -- and iterate over the entire sequence of items. However, those
1001 -- semantics were unintuitive and arguably error-prone (it is too easy
1002 -- to accidentally create an endless loop), and so they were changed,
1003 -- per the ARG meeting in Denver on 2011/11. However, there was no
1004 -- consensus about what positive meaning this corner case should have,
1005 -- and so it was decided to simply raise an exception. This does imply,
1006 -- however, that it is not possible to use a partial iterator to specify
1007 -- an empty sequence of items.
1009 if Start = No_Element then
1010 raise Constraint_Error with
1011 "Start position for iterator equals No_Element";
1012 end if;
1014 if Start.Container /= Container'Unrestricted_Access then
1015 raise Program_Error with
1016 "Start cursor of Iterate designates wrong map";
1017 end if;
1019 pragma Assert (Vet (Container, Start.Node),
1020 "Start cursor of Iterate is bad");
1022 -- The value of the Node component influences the behavior of the First
1023 -- and Last selector functions of the iterator object. When the Node
1024 -- component is positive (as is the case here), it means that this
1025 -- is a partial iteration, over a subset of the complete sequence of
1026 -- items. The iterator object was constructed with a start expression,
1027 -- indicating the position from which the iteration begins. (Note that
1028 -- the start position has the same value irrespective of whether this
1029 -- is a forward or reverse iteration.)
1031 return It : constant Iterator :=
1032 (Limited_Controlled with
1033 Container => Container'Unrestricted_Access,
1034 Node => Start.Node)
1036 B := B + 1;
1037 end return;
1038 end Iterate;
1040 ---------
1041 -- Key --
1042 ---------
1044 function Key (Position : Cursor) return Key_Type is
1045 begin
1046 if Position.Node = 0 then
1047 raise Constraint_Error with
1048 "Position cursor of function Key equals No_Element";
1049 end if;
1051 pragma Assert (Vet (Position.Container.all, Position.Node),
1052 "Position cursor of function Key is bad");
1054 return Position.Container.Nodes (Position.Node).Key;
1055 end Key;
1057 ----------
1058 -- Last --
1059 ----------
1061 function Last (Container : Map) return Cursor is
1062 begin
1063 if Container.Last = 0 then
1064 return No_Element;
1065 else
1066 return Cursor'(Container'Unrestricted_Access, Container.Last);
1067 end if;
1068 end Last;
1070 function Last (Object : Iterator) return Cursor is
1071 begin
1072 -- The value of the iterator object's Node component influences the
1073 -- behavior of the Last (and First) selector function.
1075 -- When the Node component is 0, this means the iterator object was
1076 -- constructed without a start expression, in which case the (reverse)
1077 -- iteration starts from the (logical) beginning of the entire sequence
1078 -- (corresponding to Container.Last, for a reverse iterator).
1080 -- Otherwise, this is iteration over a partial sequence of items. When
1081 -- the Node component is positive, the iterator object was constructed
1082 -- with a start expression, that specifies the position from which the
1083 -- (reverse) partial iteration begins.
1085 if Object.Node = 0 then
1086 return Bounded_Ordered_Maps.Last (Object.Container.all);
1087 else
1088 return Cursor'(Object.Container, Object.Node);
1089 end if;
1090 end Last;
1092 ------------------
1093 -- Last_Element --
1094 ------------------
1096 function Last_Element (Container : Map) return Element_Type is
1097 begin
1098 if Container.Last = 0 then
1099 raise Constraint_Error with "map is empty";
1100 else
1101 return Container.Nodes (Container.Last).Element;
1102 end if;
1103 end Last_Element;
1105 --------------
1106 -- Last_Key --
1107 --------------
1109 function Last_Key (Container : Map) return Key_Type is
1110 begin
1111 if Container.Last = 0 then
1112 raise Constraint_Error with "map is empty";
1113 else
1114 return Container.Nodes (Container.Last).Key;
1115 end if;
1116 end Last_Key;
1118 ----------
1119 -- Left --
1120 ----------
1122 function Left (Node : Node_Type) return Count_Type is
1123 begin
1124 return Node.Left;
1125 end Left;
1127 ------------
1128 -- Length --
1129 ------------
1131 function Length (Container : Map) return Count_Type is
1132 begin
1133 return Container.Length;
1134 end Length;
1136 ----------
1137 -- Move --
1138 ----------
1140 procedure Move (Target : in out Map; Source : in out Map) is
1141 begin
1142 if Target'Address = Source'Address then
1143 return;
1144 end if;
1146 if Source.Busy > 0 then
1147 raise Program_Error with
1148 "attempt to tamper with cursors (container is busy)";
1149 end if;
1151 Target.Assign (Source);
1152 Source.Clear;
1153 end Move;
1155 ----------
1156 -- Next --
1157 ----------
1159 procedure Next (Position : in out Cursor) is
1160 begin
1161 Position := Next (Position);
1162 end Next;
1164 function Next (Position : Cursor) return Cursor is
1165 begin
1166 if Position = No_Element then
1167 return No_Element;
1168 end if;
1170 pragma Assert (Vet (Position.Container.all, Position.Node),
1171 "Position cursor of Next is bad");
1173 declare
1174 M : Map renames Position.Container.all;
1176 Node : constant Count_Type :=
1177 Tree_Operations.Next (M, Position.Node);
1179 begin
1180 if Node = 0 then
1181 return No_Element;
1182 end if;
1184 return Cursor'(Position.Container, Node);
1185 end;
1186 end Next;
1188 function Next
1189 (Object : Iterator;
1190 Position : Cursor) return Cursor
1192 begin
1193 if Position.Container = null then
1194 return No_Element;
1195 end if;
1197 if Position.Container /= Object.Container then
1198 raise Program_Error with
1199 "Position cursor of Next designates wrong map";
1200 end if;
1202 return Next (Position);
1203 end Next;
1205 ------------
1206 -- Parent --
1207 ------------
1209 function Parent (Node : Node_Type) return Count_Type is
1210 begin
1211 return Node.Parent;
1212 end Parent;
1214 --------------
1215 -- Previous --
1216 --------------
1218 procedure Previous (Position : in out Cursor) is
1219 begin
1220 Position := Previous (Position);
1221 end Previous;
1223 function Previous (Position : Cursor) return Cursor is
1224 begin
1225 if Position = No_Element then
1226 return No_Element;
1227 end if;
1229 pragma Assert (Vet (Position.Container.all, Position.Node),
1230 "Position cursor of Previous is bad");
1232 declare
1233 M : Map renames Position.Container.all;
1235 Node : constant Count_Type :=
1236 Tree_Operations.Previous (M, Position.Node);
1238 begin
1239 if Node = 0 then
1240 return No_Element;
1241 end if;
1243 return Cursor'(Position.Container, Node);
1244 end;
1245 end Previous;
1247 function Previous
1248 (Object : Iterator;
1249 Position : Cursor) return Cursor
1251 begin
1252 if Position.Container = null then
1253 return No_Element;
1254 end if;
1256 if Position.Container /= Object.Container then
1257 raise Program_Error with
1258 "Position cursor of Previous designates wrong map";
1259 end if;
1261 return Previous (Position);
1262 end Previous;
1264 -------------------
1265 -- Query_Element --
1266 -------------------
1268 procedure Query_Element
1269 (Position : Cursor;
1270 Process : not null access procedure (Key : Key_Type;
1271 Element : Element_Type))
1273 begin
1274 if Position.Node = 0 then
1275 raise Constraint_Error with
1276 "Position cursor of Query_Element equals No_Element";
1277 end if;
1279 pragma Assert (Vet (Position.Container.all, Position.Node),
1280 "Position cursor of Query_Element is bad");
1282 declare
1283 M : Map renames Position.Container.all;
1284 N : Node_Type renames M.Nodes (Position.Node);
1286 B : Natural renames M.Busy;
1287 L : Natural renames M.Lock;
1289 begin
1290 B := B + 1;
1291 L := L + 1;
1293 begin
1294 Process (N.Key, N.Element);
1295 exception
1296 when others =>
1297 L := L - 1;
1298 B := B - 1;
1299 raise;
1300 end;
1302 L := L - 1;
1303 B := B - 1;
1304 end;
1305 end Query_Element;
1307 ----------
1308 -- Read --
1309 ----------
1311 procedure Read
1312 (Stream : not null access Root_Stream_Type'Class;
1313 Container : out Map)
1315 procedure Read_Element (Node : in out Node_Type);
1316 pragma Inline (Read_Element);
1318 procedure Allocate is
1319 new Tree_Operations.Generic_Allocate (Read_Element);
1321 procedure Read_Elements is
1322 new Tree_Operations.Generic_Read (Allocate);
1324 ------------------
1325 -- Read_Element --
1326 ------------------
1328 procedure Read_Element (Node : in out Node_Type) is
1329 begin
1330 Key_Type'Read (Stream, Node.Key);
1331 Element_Type'Read (Stream, Node.Element);
1332 end Read_Element;
1334 -- Start of processing for Read
1336 begin
1337 Read_Elements (Stream, Container);
1338 end Read;
1340 procedure Read
1341 (Stream : not null access Root_Stream_Type'Class;
1342 Item : out Cursor)
1344 begin
1345 raise Program_Error with "attempt to stream map cursor";
1346 end Read;
1348 procedure Read
1349 (Stream : not null access Root_Stream_Type'Class;
1350 Item : out Reference_Type)
1352 begin
1353 raise Program_Error with "attempt to stream reference";
1354 end Read;
1356 procedure Read
1357 (Stream : not null access Root_Stream_Type'Class;
1358 Item : out Constant_Reference_Type)
1360 begin
1361 raise Program_Error with "attempt to stream reference";
1362 end Read;
1364 ---------------
1365 -- Reference --
1366 ---------------
1368 function Reference
1369 (Container : aliased in out Map;
1370 Position : Cursor) return Reference_Type
1372 begin
1373 if Position.Container = null then
1374 raise Constraint_Error with
1375 "Position cursor has no element";
1376 end if;
1378 if Position.Container /= Container'Unrestricted_Access then
1379 raise Program_Error with
1380 "Position cursor designates wrong map";
1381 end if;
1383 pragma Assert (Vet (Container, Position.Node),
1384 "Position cursor in function Reference is bad");
1386 declare
1387 N : Node_Type renames Container.Nodes (Position.Node);
1388 begin
1389 return (Element => N.Element'Access);
1390 end;
1391 end Reference;
1393 function Reference
1394 (Container : aliased in out Map;
1395 Key : Key_Type) return Reference_Type
1397 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1399 begin
1400 if Node = 0 then
1401 raise Constraint_Error with "key not in map";
1402 end if;
1404 declare
1405 N : Node_Type renames Container.Nodes (Node);
1406 begin
1407 return (Element => N.Element'Access);
1408 end;
1409 end Reference;
1411 -------------
1412 -- Replace --
1413 -------------
1415 procedure Replace
1416 (Container : in out Map;
1417 Key : Key_Type;
1418 New_Item : Element_Type)
1420 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1422 begin
1423 if Node = 0 then
1424 raise Constraint_Error with "key not in map";
1425 end if;
1427 if Container.Lock > 0 then
1428 raise Program_Error with
1429 "attempt to tamper with elements (map is locked)";
1430 end if;
1432 declare
1433 N : Node_Type renames Container.Nodes (Node);
1435 begin
1436 N.Key := Key;
1437 N.Element := New_Item;
1438 end;
1439 end Replace;
1441 ---------------------
1442 -- Replace_Element --
1443 ---------------------
1445 procedure Replace_Element
1446 (Container : in out Map;
1447 Position : Cursor;
1448 New_Item : Element_Type)
1450 begin
1451 if Position.Node = 0 then
1452 raise Constraint_Error with
1453 "Position cursor of Replace_Element equals No_Element";
1454 end if;
1456 if Position.Container /= Container'Unrestricted_Access then
1457 raise Program_Error with
1458 "Position cursor of Replace_Element designates wrong map";
1459 end if;
1461 if Container.Lock > 0 then
1462 raise Program_Error with
1463 "attempt to tamper with elements (map is locked)";
1464 end if;
1466 pragma Assert (Vet (Container, Position.Node),
1467 "Position cursor of Replace_Element is bad");
1469 Container.Nodes (Position.Node).Element := New_Item;
1470 end Replace_Element;
1472 ---------------------
1473 -- Reverse_Iterate --
1474 ---------------------
1476 procedure Reverse_Iterate
1477 (Container : Map;
1478 Process : not null access procedure (Position : Cursor))
1480 procedure Process_Node (Node : Count_Type);
1481 pragma Inline (Process_Node);
1483 procedure Local_Reverse_Iterate is
1484 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1486 ------------------
1487 -- Process_Node --
1488 ------------------
1490 procedure Process_Node (Node : Count_Type) is
1491 begin
1492 Process (Cursor'(Container'Unrestricted_Access, Node));
1493 end Process_Node;
1495 B : Natural renames Container'Unrestricted_Access.all.Busy;
1497 -- Start of processing for Reverse_Iterate
1499 begin
1500 B := B + 1;
1502 begin
1503 Local_Reverse_Iterate (Container);
1504 exception
1505 when others =>
1506 B := B - 1;
1507 raise;
1508 end;
1510 B := B - 1;
1511 end Reverse_Iterate;
1513 -----------
1514 -- Right --
1515 -----------
1517 function Right (Node : Node_Type) return Count_Type is
1518 begin
1519 return Node.Right;
1520 end Right;
1522 ---------------
1523 -- Set_Color --
1524 ---------------
1526 procedure Set_Color
1527 (Node : in out Node_Type;
1528 Color : Color_Type)
1530 begin
1531 Node.Color := Color;
1532 end Set_Color;
1534 --------------
1535 -- Set_Left --
1536 --------------
1538 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1539 begin
1540 Node.Left := Left;
1541 end Set_Left;
1543 ----------------
1544 -- Set_Parent --
1545 ----------------
1547 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1548 begin
1549 Node.Parent := Parent;
1550 end Set_Parent;
1552 ---------------
1553 -- Set_Right --
1554 ---------------
1556 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1557 begin
1558 Node.Right := Right;
1559 end Set_Right;
1561 --------------------
1562 -- Update_Element --
1563 --------------------
1565 procedure Update_Element
1566 (Container : in out Map;
1567 Position : Cursor;
1568 Process : not null access procedure (Key : Key_Type;
1569 Element : in out Element_Type))
1571 begin
1572 if Position.Node = 0 then
1573 raise Constraint_Error with
1574 "Position cursor of Update_Element equals No_Element";
1575 end if;
1577 if Position.Container /= Container'Unrestricted_Access then
1578 raise Program_Error with
1579 "Position cursor of Update_Element designates wrong map";
1580 end if;
1582 pragma Assert (Vet (Container, Position.Node),
1583 "Position cursor of Update_Element is bad");
1585 declare
1586 N : Node_Type renames Container.Nodes (Position.Node);
1587 B : Natural renames Container.Busy;
1588 L : Natural renames Container.Lock;
1590 begin
1591 B := B + 1;
1592 L := L + 1;
1594 begin
1595 Process (N.Key, N.Element);
1597 exception
1598 when others =>
1599 L := L - 1;
1600 B := B - 1;
1601 raise;
1602 end;
1604 L := L - 1;
1605 B := B - 1;
1606 end;
1607 end Update_Element;
1609 -----------
1610 -- Write --
1611 -----------
1613 procedure Write
1614 (Stream : not null access Root_Stream_Type'Class;
1615 Container : Map)
1617 procedure Write_Node
1618 (Stream : not null access Root_Stream_Type'Class;
1619 Node : Node_Type);
1620 pragma Inline (Write_Node);
1622 procedure Write_Nodes is
1623 new Tree_Operations.Generic_Write (Write_Node);
1625 ----------------
1626 -- Write_Node --
1627 ----------------
1629 procedure Write_Node
1630 (Stream : not null access Root_Stream_Type'Class;
1631 Node : Node_Type)
1633 begin
1634 Key_Type'Write (Stream, Node.Key);
1635 Element_Type'Write (Stream, Node.Element);
1636 end Write_Node;
1638 -- Start of processing for Write
1640 begin
1641 Write_Nodes (Stream, Container);
1642 end Write;
1644 procedure Write
1645 (Stream : not null access Root_Stream_Type'Class;
1646 Item : Cursor)
1648 begin
1649 raise Program_Error with "attempt to stream map cursor";
1650 end Write;
1652 procedure Write
1653 (Stream : not null access Root_Stream_Type'Class;
1654 Item : Reference_Type)
1656 begin
1657 raise Program_Error with "attempt to stream reference";
1658 end Write;
1660 procedure Write
1661 (Stream : not null access Root_Stream_Type'Class;
1662 Item : Constant_Reference_Type)
1664 begin
1665 raise Program_Error with "attempt to stream reference";
1666 end Write;
1668 end Ada.Containers.Bounded_Ordered_Maps;