2014-10-10 Robert Dewar <dewar@adacore.com>
[official-gcc.git] / gcc / ada / a-cborma.adb
blob68b6befaad8d5db0262e49c27e0de201c84efb8e
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-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.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);
241 begin
242 return Right < LN.Key;
243 end;
244 end ">";
246 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
247 begin
248 if Right.Node = 0 then
249 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
250 end if;
252 pragma Assert (Vet (Right.Container.all, Right.Node),
253 "Right cursor of "">"" is bad");
255 declare
256 RN : Node_Type renames Right.Container.Nodes (Right.Node);
258 begin
259 return RN.Key < Left;
260 end;
261 end ">";
263 ------------
264 -- Adjust --
265 ------------
267 procedure Adjust (Control : in out Reference_Control_Type) is
268 begin
269 if Control.Container /= null then
270 declare
271 C : Map renames Control.Container.all;
272 B : Natural renames C.Busy;
273 L : Natural renames C.Lock;
274 begin
275 B := B + 1;
276 L := L + 1;
277 end;
278 end if;
279 end Adjust;
281 ------------
282 -- Assign --
283 ------------
285 procedure Assign (Target : in out Map; Source : Map) is
286 procedure Append_Element (Source_Node : Count_Type);
288 procedure Append_Elements is
289 new Tree_Operations.Generic_Iteration (Append_Element);
291 --------------------
292 -- Append_Element --
293 --------------------
295 procedure Append_Element (Source_Node : Count_Type) is
296 SN : Node_Type renames Source.Nodes (Source_Node);
298 procedure Set_Element (Node : in out Node_Type);
299 pragma Inline (Set_Element);
301 function New_Node return Count_Type;
302 pragma Inline (New_Node);
304 procedure Insert_Post is
305 new Key_Ops.Generic_Insert_Post (New_Node);
307 procedure Unconditional_Insert_Sans_Hint is
308 new Key_Ops.Generic_Unconditional_Insert (Insert_Post);
310 procedure Unconditional_Insert_Avec_Hint is
311 new Key_Ops.Generic_Unconditional_Insert_With_Hint
312 (Insert_Post,
313 Unconditional_Insert_Sans_Hint);
315 procedure Allocate is
316 new Tree_Operations.Generic_Allocate (Set_Element);
318 --------------
319 -- New_Node --
320 --------------
322 function New_Node return Count_Type is
323 Result : Count_Type;
325 begin
326 Allocate (Target, Result);
327 return Result;
328 end New_Node;
330 -----------------
331 -- Set_Element --
332 -----------------
334 procedure Set_Element (Node : in out Node_Type) is
335 begin
336 Node.Key := SN.Key;
337 Node.Element := SN.Element;
338 end Set_Element;
340 Target_Node : Count_Type;
342 -- Start of processing for Append_Element
344 begin
345 Unconditional_Insert_Avec_Hint
346 (Tree => Target,
347 Hint => 0,
348 Key => SN.Key,
349 Node => Target_Node);
350 end Append_Element;
352 -- Start of processing for Assign
354 begin
355 if Target'Address = Source'Address then
356 return;
357 end if;
359 if Target.Capacity < Source.Length then
360 raise Capacity_Error
361 with "Target capacity is less than Source length";
362 end if;
364 Tree_Operations.Clear_Tree (Target);
365 Append_Elements (Source);
366 end Assign;
368 -------------
369 -- Ceiling --
370 -------------
372 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
373 Node : constant Count_Type := Key_Ops.Ceiling (Container, Key);
375 begin
376 if Node = 0 then
377 return No_Element;
378 end if;
380 return Cursor'(Container'Unrestricted_Access, Node);
381 end Ceiling;
383 -----------
384 -- Clear --
385 -----------
387 procedure Clear (Container : in out Map) is
388 begin
389 Tree_Operations.Clear_Tree (Container);
390 end Clear;
392 -----------
393 -- Color --
394 -----------
396 function Color (Node : Node_Type) return Color_Type is
397 begin
398 return Node.Color;
399 end Color;
401 ------------------------
402 -- Constant_Reference --
403 ------------------------
405 function Constant_Reference
406 (Container : aliased Map;
407 Position : Cursor) return Constant_Reference_Type
409 begin
410 if Position.Container = null then
411 raise Constraint_Error with
412 "Position cursor has no element";
413 end if;
415 if Position.Container /= Container'Unrestricted_Access then
416 raise Program_Error with
417 "Position cursor designates wrong map";
418 end if;
420 pragma Assert (Vet (Container, Position.Node),
421 "Position cursor in Constant_Reference is bad");
423 declare
424 N : Node_Type renames Container.Nodes (Position.Node);
425 B : Natural renames Position.Container.Busy;
426 L : Natural renames Position.Container.Lock;
428 begin
429 return R : constant Constant_Reference_Type :=
430 (Element => N.Element'Access,
431 Control => (Controlled with Container'Unrestricted_Access))
433 B := B + 1;
434 L := L + 1;
435 end return;
436 end;
437 end Constant_Reference;
439 function Constant_Reference
440 (Container : aliased Map;
441 Key : Key_Type) return Constant_Reference_Type
443 Node : constant Count_Type := Key_Ops.Find (Container, Key);
445 begin
446 if Node = 0 then
447 raise Constraint_Error with "key not in map";
448 end if;
450 declare
451 Cur : Cursor := Find (Container, Key);
452 pragma Unmodified (Cur);
454 N : Node_Type renames Container.Nodes (Node);
455 B : Natural renames Cur.Container.Busy;
456 L : Natural renames Cur.Container.Lock;
458 begin
459 return R : constant Constant_Reference_Type :=
460 (Element => N.Element'Access,
461 Control => (Controlled with Container'Unrestricted_Access))
463 B := B + 1;
464 L := L + 1;
465 end return;
466 end;
467 end Constant_Reference;
469 --------------
470 -- Contains --
471 --------------
473 function Contains (Container : Map; Key : Key_Type) return Boolean is
474 begin
475 return Find (Container, Key) /= No_Element;
476 end Contains;
478 ----------
479 -- Copy --
480 ----------
482 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
483 C : Count_Type;
485 begin
486 if Capacity = 0 then
487 C := Source.Length;
489 elsif Capacity >= Source.Length then
490 C := Capacity;
492 else
493 raise Capacity_Error with "Capacity value too small";
494 end if;
496 return Target : Map (Capacity => C) do
497 Assign (Target => Target, Source => Source);
498 end return;
499 end Copy;
501 ------------
502 -- Delete --
503 ------------
505 procedure Delete (Container : in out Map; Position : in out Cursor) is
506 begin
507 if Position.Node = 0 then
508 raise Constraint_Error with
509 "Position cursor of Delete equals No_Element";
510 end if;
512 if Position.Container /= Container'Unrestricted_Access then
513 raise Program_Error with
514 "Position cursor of Delete designates wrong map";
515 end if;
517 pragma Assert (Vet (Container, Position.Node),
518 "Position cursor of Delete is bad");
520 Tree_Operations.Delete_Node_Sans_Free (Container, Position.Node);
521 Tree_Operations.Free (Container, Position.Node);
523 Position := No_Element;
524 end Delete;
526 procedure Delete (Container : in out Map; Key : Key_Type) is
527 X : constant Count_Type := Key_Ops.Find (Container, Key);
529 begin
530 if X = 0 then
531 raise Constraint_Error with "key not in map";
532 end if;
534 Tree_Operations.Delete_Node_Sans_Free (Container, X);
535 Tree_Operations.Free (Container, X);
536 end Delete;
538 ------------------
539 -- Delete_First --
540 ------------------
542 procedure Delete_First (Container : in out Map) is
543 X : constant Count_Type := Container.First;
545 begin
546 if X /= 0 then
547 Tree_Operations.Delete_Node_Sans_Free (Container, X);
548 Tree_Operations.Free (Container, X);
549 end if;
550 end Delete_First;
552 -----------------
553 -- Delete_Last --
554 -----------------
556 procedure Delete_Last (Container : in out Map) is
557 X : constant Count_Type := Container.Last;
559 begin
560 if X /= 0 then
561 Tree_Operations.Delete_Node_Sans_Free (Container, X);
562 Tree_Operations.Free (Container, X);
563 end if;
564 end Delete_Last;
566 -------------
567 -- Element --
568 -------------
570 function Element (Position : Cursor) return Element_Type is
571 begin
572 if Position.Node = 0 then
573 raise Constraint_Error with
574 "Position cursor of function Element equals No_Element";
575 end if;
577 pragma Assert (Vet (Position.Container.all, Position.Node),
578 "Position cursor of function Element is bad");
580 return Position.Container.Nodes (Position.Node).Element;
581 end Element;
583 function Element (Container : Map; Key : Key_Type) return Element_Type is
584 Node : constant Count_Type := Key_Ops.Find (Container, Key);
585 begin
586 if Node = 0 then
587 raise Constraint_Error with "key not in map";
588 else
589 return Container.Nodes (Node).Element;
590 end if;
591 end Element;
593 ---------------------
594 -- Equivalent_Keys --
595 ---------------------
597 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
598 begin
599 if Left < Right
600 or else Right < Left
601 then
602 return False;
603 else
604 return True;
605 end if;
606 end Equivalent_Keys;
608 -------------
609 -- Exclude --
610 -------------
612 procedure Exclude (Container : in out Map; Key : Key_Type) is
613 X : constant Count_Type := Key_Ops.Find (Container, Key);
615 begin
616 if X /= 0 then
617 Tree_Operations.Delete_Node_Sans_Free (Container, X);
618 Tree_Operations.Free (Container, X);
619 end if;
620 end Exclude;
622 --------------
623 -- Finalize --
624 --------------
626 procedure Finalize (Object : in out Iterator) is
627 begin
628 if Object.Container /= null then
629 declare
630 B : Natural renames Object.Container.all.Busy;
631 begin
632 B := B - 1;
633 end;
634 end if;
635 end Finalize;
637 procedure Finalize (Control : in out Reference_Control_Type) is
638 begin
639 if Control.Container /= null then
640 declare
641 C : Map renames Control.Container.all;
642 B : Natural renames C.Busy;
643 L : Natural renames C.Lock;
644 begin
645 B := B - 1;
646 L := L - 1;
647 end;
649 Control.Container := null;
650 end if;
651 end Finalize;
653 ----------
654 -- Find --
655 ----------
657 function Find (Container : Map; Key : Key_Type) return Cursor is
658 Node : constant Count_Type := Key_Ops.Find (Container, Key);
659 begin
660 if Node = 0 then
661 return No_Element;
662 else
663 return Cursor'(Container'Unrestricted_Access, Node);
664 end if;
665 end Find;
667 -----------
668 -- First --
669 -----------
671 function First (Container : Map) return Cursor is
672 begin
673 if Container.First = 0 then
674 return No_Element;
675 else
676 return Cursor'(Container'Unrestricted_Access, Container.First);
677 end if;
678 end First;
680 function First (Object : Iterator) return Cursor is
681 begin
682 -- The value of the iterator object's Node component influences the
683 -- behavior of the First (and Last) selector function.
685 -- When the Node component is 0, this means the iterator object was
686 -- constructed without a start expression, in which case the (forward)
687 -- iteration starts from the (logical) beginning of the entire sequence
688 -- of items (corresponding to Container.First, for a forward iterator).
690 -- Otherwise, this is iteration over a partial sequence of items. When
691 -- the Node component is positive, the iterator object was constructed
692 -- with a start expression, that specifies the position from which the
693 -- (forward) partial iteration begins.
695 if Object.Node = 0 then
696 return Bounded_Ordered_Maps.First (Object.Container.all);
697 else
698 return Cursor'(Object.Container, Object.Node);
699 end if;
700 end First;
702 -------------------
703 -- First_Element --
704 -------------------
706 function First_Element (Container : Map) return Element_Type is
707 begin
708 if Container.First = 0 then
709 raise Constraint_Error with "map is empty";
710 else
711 return Container.Nodes (Container.First).Element;
712 end if;
713 end First_Element;
715 ---------------
716 -- First_Key --
717 ---------------
719 function First_Key (Container : Map) return Key_Type is
720 begin
721 if Container.First = 0 then
722 raise Constraint_Error with "map is empty";
723 else
724 return Container.Nodes (Container.First).Key;
725 end if;
726 end First_Key;
728 -----------
729 -- Floor --
730 -----------
732 function Floor (Container : Map; Key : Key_Type) return Cursor is
733 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
734 begin
735 if Node = 0 then
736 return No_Element;
737 else
738 return Cursor'(Container'Unrestricted_Access, Node);
739 end if;
740 end Floor;
742 -----------------
743 -- Has_Element --
744 -----------------
746 function Has_Element (Position : Cursor) return Boolean is
747 begin
748 return Position /= No_Element;
749 end Has_Element;
751 -------------
752 -- Include --
753 -------------
755 procedure Include
756 (Container : in out Map;
757 Key : Key_Type;
758 New_Item : Element_Type)
760 Position : Cursor;
761 Inserted : Boolean;
763 begin
764 Insert (Container, Key, New_Item, Position, Inserted);
766 if not Inserted then
767 if Container.Lock > 0 then
768 raise Program_Error with
769 "attempt to tamper with elements (map is locked)";
770 end if;
772 declare
773 N : Node_Type renames Container.Nodes (Position.Node);
774 begin
775 N.Key := Key;
776 N.Element := New_Item;
777 end;
778 end if;
779 end Include;
781 ------------
782 -- Insert --
783 ------------
785 procedure Insert
786 (Container : in out Map;
787 Key : Key_Type;
788 New_Item : Element_Type;
789 Position : out Cursor;
790 Inserted : out Boolean)
792 procedure Assign (Node : in out Node_Type);
793 pragma Inline (Assign);
795 function New_Node return Count_Type;
796 pragma Inline (New_Node);
798 procedure Insert_Post is
799 new Key_Ops.Generic_Insert_Post (New_Node);
801 procedure Insert_Sans_Hint is
802 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
804 procedure Allocate is
805 new Tree_Operations.Generic_Allocate (Assign);
807 ------------
808 -- Assign --
809 ------------
811 procedure Assign (Node : in out Node_Type) is
812 begin
813 Node.Key := Key;
814 Node.Element := New_Item;
815 end Assign;
817 --------------
818 -- New_Node --
819 --------------
821 function New_Node return Count_Type is
822 Result : Count_Type;
823 begin
824 Allocate (Container, Result);
825 return Result;
826 end New_Node;
828 -- Start of processing for Insert
830 begin
831 Insert_Sans_Hint
832 (Container,
833 Key,
834 Position.Node,
835 Inserted);
837 Position.Container := Container'Unrestricted_Access;
838 end Insert;
840 procedure Insert
841 (Container : in out Map;
842 Key : Key_Type;
843 New_Item : Element_Type)
845 Position : Cursor;
846 pragma Unreferenced (Position);
848 Inserted : Boolean;
850 begin
851 Insert (Container, Key, New_Item, Position, Inserted);
853 if not Inserted then
854 raise Constraint_Error with "key already in map";
855 end if;
856 end Insert;
858 procedure Insert
859 (Container : in out Map;
860 Key : Key_Type;
861 Position : out Cursor;
862 Inserted : out Boolean)
864 procedure Assign (Node : in out Node_Type);
865 pragma Inline (Assign);
867 function New_Node return Count_Type;
868 pragma Inline (New_Node);
870 procedure Insert_Post is
871 new Key_Ops.Generic_Insert_Post (New_Node);
873 procedure Insert_Sans_Hint is
874 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
876 procedure Allocate is
877 new Tree_Operations.Generic_Allocate (Assign);
879 ------------
880 -- Assign --
881 ------------
883 procedure Assign (Node : in out Node_Type) is
884 New_Item : Element_Type;
885 pragma Unmodified (New_Item);
886 -- Default-initialized element (ok to reference, see below)
888 begin
889 Node.Key := Key;
891 -- There is no explicit element provided, but in an instance the element
892 -- type may be a scalar with a Default_Value aspect, or a composite type
893 -- with such a scalar component or with defaulted components, so insert
894 -- possibly initialized elements at the given position.
896 Node.Element := New_Item;
897 end Assign;
899 --------------
900 -- New_Node --
901 --------------
903 function New_Node return Count_Type is
904 Result : Count_Type;
905 begin
906 Allocate (Container, Result);
907 return Result;
908 end New_Node;
910 -- Start of processing for Insert
912 begin
913 Insert_Sans_Hint
914 (Container,
915 Key,
916 Position.Node,
917 Inserted);
919 Position.Container := Container'Unrestricted_Access;
920 end Insert;
922 --------------
923 -- Is_Empty --
924 --------------
926 function Is_Empty (Container : Map) return Boolean is
927 begin
928 return Container.Length = 0;
929 end Is_Empty;
931 -------------------------
932 -- Is_Greater_Key_Node --
933 -------------------------
935 function Is_Greater_Key_Node
936 (Left : Key_Type;
937 Right : Node_Type) return Boolean
939 begin
940 -- Left > Right same as Right < Left
942 return Right.Key < Left;
943 end Is_Greater_Key_Node;
945 ----------------------
946 -- Is_Less_Key_Node --
947 ----------------------
949 function Is_Less_Key_Node
950 (Left : Key_Type;
951 Right : Node_Type) return Boolean
953 begin
954 return Left < Right.Key;
955 end Is_Less_Key_Node;
957 -------------
958 -- Iterate --
959 -------------
961 procedure Iterate
962 (Container : Map;
963 Process : not null access procedure (Position : Cursor))
965 procedure Process_Node (Node : Count_Type);
966 pragma Inline (Process_Node);
968 procedure Local_Iterate is
969 new Tree_Operations.Generic_Iteration (Process_Node);
971 ------------------
972 -- Process_Node --
973 ------------------
975 procedure Process_Node (Node : Count_Type) is
976 begin
977 Process (Cursor'(Container'Unrestricted_Access, Node));
978 end Process_Node;
980 B : Natural renames Container'Unrestricted_Access.all.Busy;
982 -- Start of processing for Iterate
984 begin
985 B := B + 1;
987 begin
988 Local_Iterate (Container);
989 exception
990 when others =>
991 B := B - 1;
992 raise;
993 end;
995 B := B - 1;
996 end Iterate;
998 function Iterate
999 (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
1001 B : Natural renames Container'Unrestricted_Access.all.Busy;
1003 begin
1004 -- The value of the Node component influences the behavior of the First
1005 -- and Last selector functions of the iterator object. When the Node
1006 -- component is 0 (as is the case here), this means the iterator object
1007 -- was constructed without a start expression. This is a complete
1008 -- iterator, meaning that the iteration starts from the (logical)
1009 -- beginning of the sequence of items.
1011 -- Note: For a forward iterator, Container.First is the beginning, and
1012 -- for a reverse iterator, Container.Last is the beginning.
1014 return It : constant Iterator :=
1015 (Limited_Controlled with
1016 Container => Container'Unrestricted_Access,
1017 Node => 0)
1019 B := B + 1;
1020 end return;
1021 end Iterate;
1023 function Iterate
1024 (Container : Map;
1025 Start : Cursor)
1026 return Map_Iterator_Interfaces.Reversible_Iterator'Class
1028 B : Natural renames Container'Unrestricted_Access.all.Busy;
1030 begin
1031 -- Iterator was defined to behave the same as for a complete iterator,
1032 -- and iterate over the entire sequence of items. However, those
1033 -- semantics were unintuitive and arguably error-prone (it is too easy
1034 -- to accidentally create an endless loop), and so they were changed,
1035 -- per the ARG meeting in Denver on 2011/11. However, there was no
1036 -- consensus about what positive meaning this corner case should have,
1037 -- and so it was decided to simply raise an exception. This does imply,
1038 -- however, that it is not possible to use a partial iterator to specify
1039 -- an empty sequence of items.
1041 if Start = No_Element then
1042 raise Constraint_Error with
1043 "Start position for iterator equals No_Element";
1044 end if;
1046 if Start.Container /= Container'Unrestricted_Access then
1047 raise Program_Error with
1048 "Start cursor of Iterate designates wrong map";
1049 end if;
1051 pragma Assert (Vet (Container, Start.Node),
1052 "Start cursor of Iterate is bad");
1054 -- The value of the Node component influences the behavior of the First
1055 -- and Last selector functions of the iterator object. When the Node
1056 -- component is positive (as is the case here), it means that this
1057 -- is a partial iteration, over a subset of the complete sequence of
1058 -- items. The iterator object was constructed with a start expression,
1059 -- indicating the position from which the iteration begins. (Note that
1060 -- the start position has the same value irrespective of whether this
1061 -- is a forward or reverse iteration.)
1063 return It : constant Iterator :=
1064 (Limited_Controlled with
1065 Container => Container'Unrestricted_Access,
1066 Node => Start.Node)
1068 B := B + 1;
1069 end return;
1070 end Iterate;
1072 ---------
1073 -- Key --
1074 ---------
1076 function Key (Position : Cursor) return Key_Type is
1077 begin
1078 if Position.Node = 0 then
1079 raise Constraint_Error with
1080 "Position cursor of function Key equals No_Element";
1081 end if;
1083 pragma Assert (Vet (Position.Container.all, Position.Node),
1084 "Position cursor of function Key is bad");
1086 return Position.Container.Nodes (Position.Node).Key;
1087 end Key;
1089 ----------
1090 -- Last --
1091 ----------
1093 function Last (Container : Map) return Cursor is
1094 begin
1095 if Container.Last = 0 then
1096 return No_Element;
1097 else
1098 return Cursor'(Container'Unrestricted_Access, Container.Last);
1099 end if;
1100 end Last;
1102 function Last (Object : Iterator) return Cursor is
1103 begin
1104 -- The value of the iterator object's Node component influences the
1105 -- behavior of the Last (and First) selector function.
1107 -- When the Node component is 0, this means the iterator object was
1108 -- constructed without a start expression, in which case the (reverse)
1109 -- iteration starts from the (logical) beginning of the entire sequence
1110 -- (corresponding to Container.Last, for a reverse iterator).
1112 -- Otherwise, this is iteration over a partial sequence of items. When
1113 -- the Node component is positive, the iterator object was constructed
1114 -- with a start expression, that specifies the position from which the
1115 -- (reverse) partial iteration begins.
1117 if Object.Node = 0 then
1118 return Bounded_Ordered_Maps.Last (Object.Container.all);
1119 else
1120 return Cursor'(Object.Container, Object.Node);
1121 end if;
1122 end Last;
1124 ------------------
1125 -- Last_Element --
1126 ------------------
1128 function Last_Element (Container : Map) return Element_Type is
1129 begin
1130 if Container.Last = 0 then
1131 raise Constraint_Error with "map is empty";
1132 else
1133 return Container.Nodes (Container.Last).Element;
1134 end if;
1135 end Last_Element;
1137 --------------
1138 -- Last_Key --
1139 --------------
1141 function Last_Key (Container : Map) return Key_Type is
1142 begin
1143 if Container.Last = 0 then
1144 raise Constraint_Error with "map is empty";
1145 else
1146 return Container.Nodes (Container.Last).Key;
1147 end if;
1148 end Last_Key;
1150 ----------
1151 -- Left --
1152 ----------
1154 function Left (Node : Node_Type) return Count_Type is
1155 begin
1156 return Node.Left;
1157 end Left;
1159 ------------
1160 -- Length --
1161 ------------
1163 function Length (Container : Map) return Count_Type is
1164 begin
1165 return Container.Length;
1166 end Length;
1168 ----------
1169 -- Move --
1170 ----------
1172 procedure Move (Target : in out Map; Source : in out Map) is
1173 begin
1174 if Target'Address = Source'Address then
1175 return;
1176 end if;
1178 if Source.Busy > 0 then
1179 raise Program_Error with
1180 "attempt to tamper with cursors (container is busy)";
1181 end if;
1183 Target.Assign (Source);
1184 Source.Clear;
1185 end Move;
1187 ----------
1188 -- Next --
1189 ----------
1191 procedure Next (Position : in out Cursor) is
1192 begin
1193 Position := Next (Position);
1194 end Next;
1196 function Next (Position : Cursor) return Cursor is
1197 begin
1198 if Position = No_Element then
1199 return No_Element;
1200 end if;
1202 pragma Assert (Vet (Position.Container.all, Position.Node),
1203 "Position cursor of Next is bad");
1205 declare
1206 M : Map renames Position.Container.all;
1208 Node : constant Count_Type :=
1209 Tree_Operations.Next (M, Position.Node);
1211 begin
1212 if Node = 0 then
1213 return No_Element;
1214 end if;
1216 return Cursor'(Position.Container, Node);
1217 end;
1218 end Next;
1220 function Next
1221 (Object : Iterator;
1222 Position : Cursor) return Cursor
1224 begin
1225 if Position.Container = null then
1226 return No_Element;
1227 end if;
1229 if Position.Container /= Object.Container then
1230 raise Program_Error with
1231 "Position cursor of Next designates wrong map";
1232 end if;
1234 return Next (Position);
1235 end Next;
1237 ------------
1238 -- Parent --
1239 ------------
1241 function Parent (Node : Node_Type) return Count_Type is
1242 begin
1243 return Node.Parent;
1244 end Parent;
1246 --------------
1247 -- Previous --
1248 --------------
1250 procedure Previous (Position : in out Cursor) is
1251 begin
1252 Position := Previous (Position);
1253 end Previous;
1255 function Previous (Position : Cursor) return Cursor is
1256 begin
1257 if Position = No_Element then
1258 return No_Element;
1259 end if;
1261 pragma Assert (Vet (Position.Container.all, Position.Node),
1262 "Position cursor of Previous is bad");
1264 declare
1265 M : Map renames Position.Container.all;
1267 Node : constant Count_Type :=
1268 Tree_Operations.Previous (M, Position.Node);
1270 begin
1271 if Node = 0 then
1272 return No_Element;
1273 end if;
1275 return Cursor'(Position.Container, Node);
1276 end;
1277 end Previous;
1279 function Previous
1280 (Object : Iterator;
1281 Position : Cursor) return Cursor
1283 begin
1284 if Position.Container = null then
1285 return No_Element;
1286 end if;
1288 if Position.Container /= Object.Container then
1289 raise Program_Error with
1290 "Position cursor of Previous designates wrong map";
1291 end if;
1293 return Previous (Position);
1294 end Previous;
1296 -------------------
1297 -- Query_Element --
1298 -------------------
1300 procedure Query_Element
1301 (Position : Cursor;
1302 Process : not null access procedure (Key : Key_Type;
1303 Element : Element_Type))
1305 begin
1306 if Position.Node = 0 then
1307 raise Constraint_Error with
1308 "Position cursor of Query_Element equals No_Element";
1309 end if;
1311 pragma Assert (Vet (Position.Container.all, Position.Node),
1312 "Position cursor of Query_Element is bad");
1314 declare
1315 M : Map renames Position.Container.all;
1316 N : Node_Type renames M.Nodes (Position.Node);
1318 B : Natural renames M.Busy;
1319 L : Natural renames M.Lock;
1321 begin
1322 B := B + 1;
1323 L := L + 1;
1325 begin
1326 Process (N.Key, N.Element);
1327 exception
1328 when others =>
1329 L := L - 1;
1330 B := B - 1;
1331 raise;
1332 end;
1334 L := L - 1;
1335 B := B - 1;
1336 end;
1337 end Query_Element;
1339 ----------
1340 -- Read --
1341 ----------
1343 procedure Read
1344 (Stream : not null access Root_Stream_Type'Class;
1345 Container : out Map)
1347 procedure Read_Element (Node : in out Node_Type);
1348 pragma Inline (Read_Element);
1350 procedure Allocate is
1351 new Tree_Operations.Generic_Allocate (Read_Element);
1353 procedure Read_Elements is
1354 new Tree_Operations.Generic_Read (Allocate);
1356 ------------------
1357 -- Read_Element --
1358 ------------------
1360 procedure Read_Element (Node : in out Node_Type) is
1361 begin
1362 Key_Type'Read (Stream, Node.Key);
1363 Element_Type'Read (Stream, Node.Element);
1364 end Read_Element;
1366 -- Start of processing for Read
1368 begin
1369 Read_Elements (Stream, Container);
1370 end Read;
1372 procedure Read
1373 (Stream : not null access Root_Stream_Type'Class;
1374 Item : out Cursor)
1376 begin
1377 raise Program_Error with "attempt to stream map cursor";
1378 end Read;
1380 procedure Read
1381 (Stream : not null access Root_Stream_Type'Class;
1382 Item : out Reference_Type)
1384 begin
1385 raise Program_Error with "attempt to stream reference";
1386 end Read;
1388 procedure Read
1389 (Stream : not null access Root_Stream_Type'Class;
1390 Item : out Constant_Reference_Type)
1392 begin
1393 raise Program_Error with "attempt to stream reference";
1394 end Read;
1396 ---------------
1397 -- Reference --
1398 ---------------
1400 function Reference
1401 (Container : aliased in out Map;
1402 Position : Cursor) return Reference_Type
1404 begin
1405 if Position.Container = null then
1406 raise Constraint_Error with
1407 "Position cursor has no element";
1408 end if;
1410 if Position.Container /= Container'Unrestricted_Access then
1411 raise Program_Error with
1412 "Position cursor designates wrong map";
1413 end if;
1415 pragma Assert (Vet (Container, Position.Node),
1416 "Position cursor in function Reference is bad");
1418 declare
1419 N : Node_Type renames Container.Nodes (Position.Node);
1420 B : Natural renames Container.Busy;
1421 L : Natural renames Container.Lock;
1422 begin
1423 return R : constant Reference_Type :=
1424 (Element => N.Element'Access,
1425 Control => (Controlled with Container'Unrestricted_Access))
1427 B := B + 1;
1428 L := L + 1;
1429 end return;
1430 end;
1431 end Reference;
1433 function Reference
1434 (Container : aliased in out Map;
1435 Key : Key_Type) return Reference_Type
1437 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1439 begin
1440 if Node = 0 then
1441 raise Constraint_Error with "key not in map";
1442 end if;
1444 declare
1445 N : Node_Type renames Container.Nodes (Node);
1446 B : Natural renames Container.Busy;
1447 L : Natural renames Container.Lock;
1448 begin
1449 return R : constant Reference_Type :=
1450 (Element => N.Element'Access,
1451 Control => (Controlled with Container'Unrestricted_Access))
1453 B := B + 1;
1454 L := L + 1;
1455 end return;
1456 end;
1457 end Reference;
1459 -------------
1460 -- Replace --
1461 -------------
1463 procedure Replace
1464 (Container : in out Map;
1465 Key : Key_Type;
1466 New_Item : Element_Type)
1468 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1470 begin
1471 if Node = 0 then
1472 raise Constraint_Error with "key not in map";
1473 end if;
1475 if Container.Lock > 0 then
1476 raise Program_Error with
1477 "attempt to tamper with elements (map is locked)";
1478 end if;
1480 declare
1481 N : Node_Type renames Container.Nodes (Node);
1483 begin
1484 N.Key := Key;
1485 N.Element := New_Item;
1486 end;
1487 end Replace;
1489 ---------------------
1490 -- Replace_Element --
1491 ---------------------
1493 procedure Replace_Element
1494 (Container : in out Map;
1495 Position : Cursor;
1496 New_Item : Element_Type)
1498 begin
1499 if Position.Node = 0 then
1500 raise Constraint_Error with
1501 "Position cursor of Replace_Element equals No_Element";
1502 end if;
1504 if Position.Container /= Container'Unrestricted_Access then
1505 raise Program_Error with
1506 "Position cursor of Replace_Element designates wrong map";
1507 end if;
1509 if Container.Lock > 0 then
1510 raise Program_Error with
1511 "attempt to tamper with elements (map is locked)";
1512 end if;
1514 pragma Assert (Vet (Container, Position.Node),
1515 "Position cursor of Replace_Element is bad");
1517 Container.Nodes (Position.Node).Element := New_Item;
1518 end Replace_Element;
1520 ---------------------
1521 -- Reverse_Iterate --
1522 ---------------------
1524 procedure Reverse_Iterate
1525 (Container : Map;
1526 Process : not null access procedure (Position : Cursor))
1528 procedure Process_Node (Node : Count_Type);
1529 pragma Inline (Process_Node);
1531 procedure Local_Reverse_Iterate is
1532 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1534 ------------------
1535 -- Process_Node --
1536 ------------------
1538 procedure Process_Node (Node : Count_Type) is
1539 begin
1540 Process (Cursor'(Container'Unrestricted_Access, Node));
1541 end Process_Node;
1543 B : Natural renames Container'Unrestricted_Access.all.Busy;
1545 -- Start of processing for Reverse_Iterate
1547 begin
1548 B := B + 1;
1550 begin
1551 Local_Reverse_Iterate (Container);
1552 exception
1553 when others =>
1554 B := B - 1;
1555 raise;
1556 end;
1558 B := B - 1;
1559 end Reverse_Iterate;
1561 -----------
1562 -- Right --
1563 -----------
1565 function Right (Node : Node_Type) return Count_Type is
1566 begin
1567 return Node.Right;
1568 end Right;
1570 ---------------
1571 -- Set_Color --
1572 ---------------
1574 procedure Set_Color
1575 (Node : in out Node_Type;
1576 Color : Color_Type)
1578 begin
1579 Node.Color := Color;
1580 end Set_Color;
1582 --------------
1583 -- Set_Left --
1584 --------------
1586 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1587 begin
1588 Node.Left := Left;
1589 end Set_Left;
1591 ----------------
1592 -- Set_Parent --
1593 ----------------
1595 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1596 begin
1597 Node.Parent := Parent;
1598 end Set_Parent;
1600 ---------------
1601 -- Set_Right --
1602 ---------------
1604 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1605 begin
1606 Node.Right := Right;
1607 end Set_Right;
1609 --------------------
1610 -- Update_Element --
1611 --------------------
1613 procedure Update_Element
1614 (Container : in out Map;
1615 Position : Cursor;
1616 Process : not null access procedure (Key : Key_Type;
1617 Element : in out Element_Type))
1619 begin
1620 if Position.Node = 0 then
1621 raise Constraint_Error with
1622 "Position cursor of Update_Element equals No_Element";
1623 end if;
1625 if Position.Container /= Container'Unrestricted_Access then
1626 raise Program_Error with
1627 "Position cursor of Update_Element designates wrong map";
1628 end if;
1630 pragma Assert (Vet (Container, Position.Node),
1631 "Position cursor of Update_Element is bad");
1633 declare
1634 N : Node_Type renames Container.Nodes (Position.Node);
1635 B : Natural renames Container.Busy;
1636 L : Natural renames Container.Lock;
1638 begin
1639 B := B + 1;
1640 L := L + 1;
1642 begin
1643 Process (N.Key, N.Element);
1645 exception
1646 when others =>
1647 L := L - 1;
1648 B := B - 1;
1649 raise;
1650 end;
1652 L := L - 1;
1653 B := B - 1;
1654 end;
1655 end Update_Element;
1657 -----------
1658 -- Write --
1659 -----------
1661 procedure Write
1662 (Stream : not null access Root_Stream_Type'Class;
1663 Container : Map)
1665 procedure Write_Node
1666 (Stream : not null access Root_Stream_Type'Class;
1667 Node : Node_Type);
1668 pragma Inline (Write_Node);
1670 procedure Write_Nodes is
1671 new Tree_Operations.Generic_Write (Write_Node);
1673 ----------------
1674 -- Write_Node --
1675 ----------------
1677 procedure Write_Node
1678 (Stream : not null access Root_Stream_Type'Class;
1679 Node : Node_Type)
1681 begin
1682 Key_Type'Write (Stream, Node.Key);
1683 Element_Type'Write (Stream, Node.Element);
1684 end Write_Node;
1686 -- Start of processing for Write
1688 begin
1689 Write_Nodes (Stream, Container);
1690 end Write;
1692 procedure Write
1693 (Stream : not null access Root_Stream_Type'Class;
1694 Item : Cursor)
1696 begin
1697 raise Program_Error with "attempt to stream map cursor";
1698 end Write;
1700 procedure Write
1701 (Stream : not null access Root_Stream_Type'Class;
1702 Item : Reference_Type)
1704 begin
1705 raise Program_Error with "attempt to stream reference";
1706 end Write;
1708 procedure Write
1709 (Stream : not null access Root_Stream_Type'Class;
1710 Item : Constant_Reference_Type)
1712 begin
1713 raise Program_Error with "attempt to stream reference";
1714 end Write;
1716 end Ada.Containers.Bounded_Ordered_Maps;