Skip 30_threads/future/members/poll.cc on hppa*-*-linux*
[official-gcc.git] / gcc / ada / libgnat / a-cborma.adb
blobd844d0dce6905e68f81996775d6fc2588f312cd7
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-2024, 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.Helpers; use Ada.Containers.Helpers;
32 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations;
33 pragma Elaborate_All
34 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Operations);
36 with Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys;
37 pragma Elaborate_All
38 (Ada.Containers.Red_Black_Trees.Generic_Bounded_Keys);
40 with System; use type System.Address;
41 with System.Put_Images;
43 package body Ada.Containers.Bounded_Ordered_Maps with
44 SPARK_Mode => Off
47 pragma Warnings (Off, "variable ""Busy*"" is not referenced");
48 pragma Warnings (Off, "variable ""Lock*"" is not referenced");
49 -- See comment in Ada.Containers.Helpers
51 -----------------------------
52 -- Node Access Subprograms --
53 -----------------------------
55 -- These subprograms provide a functional interface to access fields
56 -- of a node, and a procedural interface for modifying these values.
58 function Color (Node : Node_Type) return Color_Type;
59 pragma Inline (Color);
61 function Left (Node : Node_Type) return Count_Type;
62 pragma Inline (Left);
64 function Parent (Node : Node_Type) return Count_Type;
65 pragma Inline (Parent);
67 function Right (Node : Node_Type) return Count_Type;
68 pragma Inline (Right);
70 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type);
71 pragma Inline (Set_Parent);
73 procedure Set_Left (Node : in out Node_Type; Left : Count_Type);
74 pragma Inline (Set_Left);
76 procedure Set_Right (Node : in out Node_Type; Right : Count_Type);
77 pragma Inline (Set_Right);
79 procedure Set_Color (Node : in out Node_Type; Color : Color_Type);
80 pragma Inline (Set_Color);
82 -----------------------
83 -- Local Subprograms --
84 -----------------------
86 function Is_Greater_Key_Node
87 (Left : Key_Type;
88 Right : Node_Type) return Boolean;
89 pragma Inline (Is_Greater_Key_Node);
91 function Is_Less_Key_Node
92 (Left : Key_Type;
93 Right : Node_Type) return Boolean;
94 pragma Inline (Is_Less_Key_Node);
96 --------------------------
97 -- Local Instantiations --
98 --------------------------
100 package Tree_Operations is
101 new Red_Black_Trees.Generic_Bounded_Operations (Tree_Types);
103 use Tree_Operations;
105 package Key_Ops is
106 new Red_Black_Trees.Generic_Bounded_Keys
107 (Tree_Operations => Tree_Operations,
108 Key_Type => Key_Type,
109 Is_Less_Key_Node => Is_Less_Key_Node,
110 Is_Greater_Key_Node => Is_Greater_Key_Node);
112 ---------
113 -- "<" --
114 ---------
116 function "<" (Left, Right : Cursor) return Boolean is
117 begin
118 if Checks and then Left.Node = 0 then
119 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
120 end if;
122 if Checks and then Right.Node = 0 then
123 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
124 end if;
126 pragma Assert (Vet (Left.Container.all, Left.Node),
127 "Left cursor of ""<"" is bad");
129 pragma Assert (Vet (Right.Container.all, Right.Node),
130 "Right cursor of ""<"" is bad");
132 declare
133 LN : Node_Type renames Left.Container.Nodes (Left.Node);
134 RN : Node_Type renames Right.Container.Nodes (Right.Node);
136 begin
137 return LN.Key < RN.Key;
138 end;
139 end "<";
141 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
142 begin
143 if Checks and then Left.Node = 0 then
144 raise Constraint_Error with "Left cursor of ""<"" equals No_Element";
145 end if;
147 pragma Assert (Vet (Left.Container.all, Left.Node),
148 "Left cursor of ""<"" is bad");
150 declare
151 LN : Node_Type renames Left.Container.Nodes (Left.Node);
153 begin
154 return LN.Key < Right;
155 end;
156 end "<";
158 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
159 begin
160 if Checks and then Right.Node = 0 then
161 raise Constraint_Error with "Right cursor of ""<"" equals No_Element";
162 end if;
164 pragma Assert (Vet (Right.Container.all, Right.Node),
165 "Right cursor of ""<"" is bad");
167 declare
168 RN : Node_Type renames Right.Container.Nodes (Right.Node);
170 begin
171 return Left < RN.Key;
172 end;
173 end "<";
175 ---------
176 -- "=" --
177 ---------
179 function "=" (Left, Right : Map) return Boolean is
180 function Is_Equal_Node_Node (L, R : Node_Type) return Boolean;
181 pragma Inline (Is_Equal_Node_Node);
183 function Is_Equal is
184 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
186 ------------------------
187 -- Is_Equal_Node_Node --
188 ------------------------
190 function Is_Equal_Node_Node
191 (L, R : Node_Type) return Boolean is
192 begin
193 if L.Key < R.Key then
194 return False;
196 elsif R.Key < L.Key then
197 return False;
199 else
200 return L.Element = R.Element;
201 end if;
202 end Is_Equal_Node_Node;
204 -- Start of processing for "="
206 begin
207 return Is_Equal (Left, Right);
208 end "=";
210 ---------
211 -- ">" --
212 ---------
214 function ">" (Left, Right : Cursor) return Boolean is
215 begin
216 if Checks and then Left.Node = 0 then
217 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
218 end if;
220 if Checks and then Right.Node = 0 then
221 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
222 end if;
224 pragma Assert (Vet (Left.Container.all, Left.Node),
225 "Left cursor of "">"" is bad");
227 pragma Assert (Vet (Right.Container.all, Right.Node),
228 "Right cursor of "">"" is bad");
230 declare
231 LN : Node_Type renames Left.Container.Nodes (Left.Node);
232 RN : Node_Type renames Right.Container.Nodes (Right.Node);
234 begin
235 return RN.Key < LN.Key;
236 end;
237 end ">";
239 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
240 begin
241 if Checks and then Left.Node = 0 then
242 raise Constraint_Error with "Left cursor of "">"" equals No_Element";
243 end if;
245 pragma Assert (Vet (Left.Container.all, Left.Node),
246 "Left cursor of "">"" is bad");
248 declare
249 LN : Node_Type renames Left.Container.Nodes (Left.Node);
250 begin
251 return Right < LN.Key;
252 end;
253 end ">";
255 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
256 begin
257 if Checks and then Right.Node = 0 then
258 raise Constraint_Error with "Right cursor of "">"" equals No_Element";
259 end if;
261 pragma Assert (Vet (Right.Container.all, Right.Node),
262 "Right cursor of "">"" is bad");
264 declare
265 RN : Node_Type renames Right.Container.Nodes (Right.Node);
267 begin
268 return RN.Key < Left;
269 end;
270 end ">";
272 ------------
273 -- Assign --
274 ------------
276 procedure Assign (Target : in out Map; Source : Map) is
277 procedure Append_Element (Source_Node : Count_Type);
279 procedure Append_Elements is
280 new Tree_Operations.Generic_Iteration (Append_Element);
282 --------------------
283 -- Append_Element --
284 --------------------
286 procedure Append_Element (Source_Node : Count_Type) is
287 SN : Node_Type renames Source.Nodes (Source_Node);
289 procedure Set_Element (Node : in out Node_Type);
290 pragma Inline (Set_Element);
292 function New_Node return Count_Type;
293 pragma Inline (New_Node);
295 procedure Insert_Post is
296 new Key_Ops.Generic_Insert_Post (New_Node);
298 procedure Unconditional_Insert_Sans_Hint is
299 new Key_Ops.Generic_Unconditional_Insert (Insert_Post);
301 procedure Unconditional_Insert_Avec_Hint is
302 new Key_Ops.Generic_Unconditional_Insert_With_Hint
303 (Insert_Post,
304 Unconditional_Insert_Sans_Hint);
306 procedure Allocate is
307 new Tree_Operations.Generic_Allocate (Set_Element);
309 --------------
310 -- New_Node --
311 --------------
313 function New_Node return Count_Type is
314 Result : Count_Type;
316 begin
317 Allocate (Target, Result);
318 return Result;
319 end New_Node;
321 -----------------
322 -- Set_Element --
323 -----------------
325 procedure Set_Element (Node : in out Node_Type) is
326 begin
327 Node.Key := SN.Key;
328 Node.Element := SN.Element;
329 end Set_Element;
331 Target_Node : Count_Type;
333 -- Start of processing for Append_Element
335 begin
336 Unconditional_Insert_Avec_Hint
337 (Tree => Target,
338 Hint => 0,
339 Key => SN.Key,
340 Node => Target_Node);
341 end Append_Element;
343 -- Start of processing for Assign
345 begin
346 if Target'Address = Source'Address then
347 return;
348 end if;
350 if Checks and then Target.Capacity < Source.Length then
351 raise Capacity_Error
352 with "Target capacity is less than Source length";
353 end if;
355 Tree_Operations.Clear_Tree (Target);
356 Append_Elements (Source);
357 end Assign;
359 -------------
360 -- Ceiling --
361 -------------
363 function Ceiling (Container : Map; Key : Key_Type) return Cursor is
364 Node : constant Count_Type := Key_Ops.Ceiling (Container, Key);
366 begin
367 if Node = 0 then
368 return No_Element;
369 end if;
371 return Cursor'(Container'Unrestricted_Access, Node);
372 end Ceiling;
374 -----------
375 -- Clear --
376 -----------
378 procedure Clear (Container : in out Map) is
379 begin
380 while not Container.Is_Empty loop
381 Container.Delete_Last;
382 end loop;
383 end Clear;
385 -----------
386 -- Color --
387 -----------
389 function Color (Node : Node_Type) return Color_Type is
390 begin
391 return Node.Color;
392 end Color;
394 ------------------------
395 -- Constant_Reference --
396 ------------------------
398 function Constant_Reference
399 (Container : aliased Map;
400 Position : Cursor) return Constant_Reference_Type
402 begin
403 if Checks and then Position.Container = null then
404 raise Constraint_Error with
405 "Position cursor has no element";
406 end if;
408 if Checks and then Position.Container /= Container'Unrestricted_Access
409 then
410 raise Program_Error with
411 "Position cursor designates wrong map";
412 end if;
414 pragma Assert (Vet (Container, Position.Node),
415 "Position cursor in Constant_Reference is bad");
417 declare
418 N : Node_Type renames Container.Nodes (Position.Node);
419 TC : constant Tamper_Counts_Access :=
420 Container.TC'Unrestricted_Access;
421 begin
422 return R : constant Constant_Reference_Type :=
423 (Element => N.Element'Unchecked_Access,
424 Control => (Controlled with TC))
426 Busy (TC.all);
427 end return;
428 end;
429 end Constant_Reference;
431 function Constant_Reference
432 (Container : aliased Map;
433 Key : Key_Type) return Constant_Reference_Type
435 Node : constant Count_Type := Key_Ops.Find (Container, Key);
437 begin
438 if Checks and then Node = 0 then
439 raise Constraint_Error with "key not in map";
440 end if;
442 declare
443 N : Node_Type renames Container.Nodes (Node);
444 TC : constant Tamper_Counts_Access :=
445 Container.TC'Unrestricted_Access;
446 begin
447 return R : constant Constant_Reference_Type :=
448 (Element => N.Element'Unchecked_Access,
449 Control => (Controlled with TC))
451 Busy (TC.all);
452 end return;
453 end;
454 end Constant_Reference;
456 --------------
457 -- Contains --
458 --------------
460 function Contains (Container : Map; Key : Key_Type) return Boolean is
461 begin
462 return Find (Container, Key) /= No_Element;
463 end Contains;
465 ----------
466 -- Copy --
467 ----------
469 function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
470 C : constant Count_Type :=
471 (if Capacity = 0 then Source.Length
472 else Capacity);
473 begin
474 if Checks and then C < Source.Length then
475 raise Capacity_Error with "Capacity too small";
476 end if;
478 return Target : Map (Capacity => C) do
479 Assign (Target => Target, Source => Source);
480 end return;
481 end Copy;
483 ------------
484 -- Delete --
485 ------------
487 procedure Delete (Container : in out Map; Position : in out Cursor) is
488 begin
489 if Checks and then Position.Node = 0 then
490 raise Constraint_Error with
491 "Position cursor of Delete equals No_Element";
492 end if;
494 if Checks and then Position.Container /= Container'Unrestricted_Access
495 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 Checks and then 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 Checks and then 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 Checks and then Node = 0 then
570 raise Constraint_Error with "key not in map";
571 end if;
573 return Container.Nodes (Node).Element;
574 end Element;
576 -----------
577 -- Empty --
578 -----------
580 function Empty (Capacity : Count_Type := 10) return Map is
581 begin
582 return Result : Map (Capacity) do
583 null;
584 end return;
585 end Empty;
587 ---------------------
588 -- Equivalent_Keys --
589 ---------------------
591 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
592 begin
593 if Left < Right
594 or else Right < Left
595 then
596 return False;
597 else
598 return True;
599 end if;
600 end Equivalent_Keys;
602 -------------
603 -- Exclude --
604 -------------
606 procedure Exclude (Container : in out Map; Key : Key_Type) is
607 X : constant Count_Type := Key_Ops.Find (Container, Key);
609 begin
610 if X /= 0 then
611 Tree_Operations.Delete_Node_Sans_Free (Container, X);
612 Tree_Operations.Free (Container, X);
613 end if;
614 end Exclude;
616 --------------
617 -- Finalize --
618 --------------
620 procedure Finalize (Object : in out Iterator) is
621 begin
622 if Object.Container /= null then
623 Unbusy (Object.Container.TC);
624 end if;
625 end Finalize;
627 ----------
628 -- Find --
629 ----------
631 function Find (Container : Map; Key : Key_Type) return Cursor is
632 Node : constant Count_Type := Key_Ops.Find (Container, Key);
633 begin
634 if Node = 0 then
635 return No_Element;
636 else
637 return Cursor'(Container'Unrestricted_Access, Node);
638 end if;
639 end Find;
641 -----------
642 -- First --
643 -----------
645 function First (Container : Map) return Cursor is
646 begin
647 if Container.First = 0 then
648 return No_Element;
649 else
650 return Cursor'(Container'Unrestricted_Access, Container.First);
651 end if;
652 end First;
654 function First (Object : Iterator) return Cursor is
655 begin
656 -- The value of the iterator object's Node component influences the
657 -- behavior of the First (and Last) selector function.
659 -- When the Node component is 0, this means the iterator object was
660 -- constructed without a start expression, in which case the (forward)
661 -- iteration starts from the (logical) beginning of the entire sequence
662 -- of items (corresponding to Container.First, for a forward iterator).
664 -- Otherwise, this is iteration over a partial sequence of items. When
665 -- the Node component is positive, the iterator object was constructed
666 -- with a start expression, that specifies the position from which the
667 -- (forward) partial iteration begins.
669 if Object.Node = 0 then
670 return Bounded_Ordered_Maps.First (Object.Container.all);
671 else
672 return Cursor'(Object.Container, Object.Node);
673 end if;
674 end First;
676 -------------------
677 -- First_Element --
678 -------------------
680 function First_Element (Container : Map) return Element_Type is
681 begin
682 if Checks and then Container.First = 0 then
683 raise Constraint_Error with "map is empty";
684 end if;
686 return Container.Nodes (Container.First).Element;
687 end First_Element;
689 ---------------
690 -- First_Key --
691 ---------------
693 function First_Key (Container : Map) return Key_Type is
694 begin
695 if Checks and then Container.First = 0 then
696 raise Constraint_Error with "map is empty";
697 end if;
699 return Container.Nodes (Container.First).Key;
700 end First_Key;
702 -----------
703 -- Floor --
704 -----------
706 function Floor (Container : Map; Key : Key_Type) return Cursor is
707 Node : constant Count_Type := Key_Ops.Floor (Container, Key);
708 begin
709 if Node = 0 then
710 return No_Element;
711 else
712 return Cursor'(Container'Unrestricted_Access, Node);
713 end if;
714 end Floor;
716 ------------------------
717 -- Get_Element_Access --
718 ------------------------
720 function Get_Element_Access
721 (Position : Cursor) return not null Element_Access is
722 begin
723 return Position.Container.Nodes (Position.Node).Element'Access;
724 end Get_Element_Access;
726 -----------------
727 -- Has_Element --
728 -----------------
730 function Has_Element (Position : Cursor) return Boolean is
731 begin
732 return Position /= No_Element;
733 end Has_Element;
735 -------------
736 -- Include --
737 -------------
739 procedure Include
740 (Container : in out Map;
741 Key : Key_Type;
742 New_Item : Element_Type)
744 Position : Cursor;
745 Inserted : Boolean;
747 begin
748 Insert (Container, Key, New_Item, Position, Inserted);
750 if not Inserted then
751 TE_Check (Container.TC);
753 declare
754 N : Node_Type renames Container.Nodes (Position.Node);
755 begin
756 N.Key := Key;
757 N.Element := New_Item;
758 end;
759 end if;
760 end Include;
762 ------------
763 -- Insert --
764 ------------
766 procedure Insert
767 (Container : in out Map;
768 Key : Key_Type;
769 New_Item : Element_Type;
770 Position : out Cursor;
771 Inserted : out Boolean)
773 procedure Assign (Node : in out Node_Type);
774 pragma Inline (Assign);
776 function New_Node return Count_Type;
777 pragma Inline (New_Node);
779 procedure Insert_Post is
780 new Key_Ops.Generic_Insert_Post (New_Node);
782 procedure Insert_Sans_Hint is
783 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
785 procedure Allocate is
786 new Tree_Operations.Generic_Allocate (Assign);
788 ------------
789 -- Assign --
790 ------------
792 procedure Assign (Node : in out Node_Type) is
793 begin
794 Node.Key := Key;
795 Node.Element := New_Item;
796 end Assign;
798 --------------
799 -- New_Node --
800 --------------
802 function New_Node return Count_Type is
803 Result : Count_Type;
804 begin
805 Allocate (Container, Result);
806 return Result;
807 end New_Node;
809 -- Start of processing for Insert
811 begin
812 Insert_Sans_Hint
813 (Container,
814 Key,
815 Position.Node,
816 Inserted);
818 Position.Container := Container'Unrestricted_Access;
819 end Insert;
821 procedure Insert
822 (Container : in out Map;
823 Key : Key_Type;
824 New_Item : Element_Type)
826 Position : Cursor;
827 Inserted : Boolean;
829 begin
830 Insert (Container, Key, New_Item, Position, Inserted);
832 if Checks and then not Inserted then
833 raise Constraint_Error with "key already in map";
834 end if;
835 end Insert;
837 procedure Insert
838 (Container : in out Map;
839 Key : Key_Type;
840 Position : out Cursor;
841 Inserted : out Boolean)
843 procedure Assign (Node : in out Node_Type);
844 pragma Inline (Assign);
846 function New_Node return Count_Type;
847 pragma Inline (New_Node);
849 procedure Insert_Post is
850 new Key_Ops.Generic_Insert_Post (New_Node);
852 procedure Insert_Sans_Hint is
853 new Key_Ops.Generic_Conditional_Insert (Insert_Post);
855 procedure Allocate is
856 new Tree_Operations.Generic_Allocate (Assign);
858 ------------
859 -- Assign --
860 ------------
862 procedure Assign (Node : in out Node_Type) is
863 pragma Warnings (Off);
864 Default_Initialized_Item : Element_Type;
865 pragma Unmodified (Default_Initialized_Item);
866 -- Default-initialized element (ok to reference, see below)
868 begin
869 Node.Key := Key;
871 -- There is no explicit element provided, but in an instance the element
872 -- type may be a scalar with a Default_Value aspect, or a composite type
873 -- with such a scalar component or with defaulted components, so insert
874 -- possibly initialized elements at the given position.
876 Node.Element := Default_Initialized_Item;
877 pragma Warnings (On);
878 end Assign;
880 --------------
881 -- New_Node --
882 --------------
884 function New_Node return Count_Type is
885 Result : Count_Type;
886 begin
887 Allocate (Container, Result);
888 return Result;
889 end New_Node;
891 -- Start of processing for Insert
893 begin
894 Insert_Sans_Hint
895 (Container,
896 Key,
897 Position.Node,
898 Inserted);
900 Position.Container := Container'Unrestricted_Access;
901 end Insert;
903 --------------
904 -- Is_Empty --
905 --------------
907 function Is_Empty (Container : Map) return Boolean is
908 begin
909 return Container.Length = 0;
910 end Is_Empty;
912 -------------------------
913 -- Is_Greater_Key_Node --
914 -------------------------
916 function Is_Greater_Key_Node
917 (Left : Key_Type;
918 Right : Node_Type) return Boolean
920 begin
921 -- Left > Right same as Right < Left
923 return Right.Key < Left;
924 end Is_Greater_Key_Node;
926 ----------------------
927 -- Is_Less_Key_Node --
928 ----------------------
930 function Is_Less_Key_Node
931 (Left : Key_Type;
932 Right : Node_Type) return Boolean
934 begin
935 return Left < Right.Key;
936 end Is_Less_Key_Node;
938 -------------
939 -- Iterate --
940 -------------
942 procedure Iterate
943 (Container : Map;
944 Process : not null access procedure (Position : Cursor))
946 procedure Process_Node (Node : Count_Type);
947 pragma Inline (Process_Node);
949 procedure Local_Iterate is
950 new Tree_Operations.Generic_Iteration (Process_Node);
952 ------------------
953 -- Process_Node --
954 ------------------
956 procedure Process_Node (Node : Count_Type) is
957 begin
958 Process (Cursor'(Container'Unrestricted_Access, Node));
959 end Process_Node;
961 Busy : With_Busy (Container.TC'Unrestricted_Access);
963 -- Start of processing for Iterate
965 begin
966 Local_Iterate (Container);
967 end Iterate;
969 function Iterate
970 (Container : Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class
972 begin
973 -- The value of the Node component influences the behavior of the First
974 -- and Last selector functions of the iterator object. When the Node
975 -- component is 0 (as is the case here), this means the iterator object
976 -- was constructed without a start expression. This is a complete
977 -- iterator, meaning that the iteration starts from the (logical)
978 -- beginning of the sequence of items.
980 -- Note: For a forward iterator, Container.First is the beginning, and
981 -- for a reverse iterator, Container.Last is the beginning.
983 return It : constant Iterator :=
984 (Limited_Controlled with
985 Container => Container'Unrestricted_Access,
986 Node => 0)
988 Busy (Container.TC'Unrestricted_Access.all);
989 end return;
990 end Iterate;
992 function Iterate
993 (Container : Map;
994 Start : Cursor)
995 return Map_Iterator_Interfaces.Reversible_Iterator'Class
997 begin
998 -- Iterator was defined to behave the same as for a complete iterator,
999 -- and iterate over the entire sequence of items. However, those
1000 -- semantics were unintuitive and arguably error-prone (it is too easy
1001 -- to accidentally create an endless loop), and so they were changed,
1002 -- per the ARG meeting in Denver on 2011/11. However, there was no
1003 -- consensus about what positive meaning this corner case should have,
1004 -- and so it was decided to simply raise an exception. This does imply,
1005 -- however, that it is not possible to use a partial iterator to specify
1006 -- an empty sequence of items.
1008 if Checks and then Start = No_Element then
1009 raise Constraint_Error with
1010 "Start position for iterator equals No_Element";
1011 end if;
1013 if Checks and then Start.Container /= Container'Unrestricted_Access then
1014 raise Program_Error with
1015 "Start cursor of Iterate designates wrong map";
1016 end if;
1018 pragma Assert (Vet (Container, Start.Node),
1019 "Start cursor of Iterate is bad");
1021 -- The value of the Node component influences the behavior of the First
1022 -- and Last selector functions of the iterator object. When the Node
1023 -- component is positive (as is the case here), it means that this
1024 -- is a partial iteration, over a subset of the complete sequence of
1025 -- items. The iterator object was constructed with a start expression,
1026 -- indicating the position from which the iteration begins. (Note that
1027 -- the start position has the same value irrespective of whether this
1028 -- is a forward or reverse iteration.)
1030 return It : constant Iterator :=
1031 (Limited_Controlled with
1032 Container => Container'Unrestricted_Access,
1033 Node => Start.Node)
1035 Busy (Container.TC'Unrestricted_Access.all);
1036 end return;
1037 end Iterate;
1039 ---------
1040 -- Key --
1041 ---------
1043 function Key (Position : Cursor) return Key_Type is
1044 begin
1045 if Checks and then Position.Node = 0 then
1046 raise Constraint_Error with
1047 "Position cursor of function Key equals No_Element";
1048 end if;
1050 pragma Assert (Vet (Position.Container.all, Position.Node),
1051 "Position cursor of function Key is bad");
1053 return Position.Container.Nodes (Position.Node).Key;
1054 end Key;
1056 ----------
1057 -- Last --
1058 ----------
1060 function Last (Container : Map) return Cursor is
1061 begin
1062 if Container.Last = 0 then
1063 return No_Element;
1064 else
1065 return Cursor'(Container'Unrestricted_Access, Container.Last);
1066 end if;
1067 end Last;
1069 function Last (Object : Iterator) return Cursor is
1070 begin
1071 -- The value of the iterator object's Node component influences the
1072 -- behavior of the Last (and First) selector function.
1074 -- When the Node component is 0, this means the iterator object was
1075 -- constructed without a start expression, in which case the (reverse)
1076 -- iteration starts from the (logical) beginning of the entire sequence
1077 -- (corresponding to Container.Last, for a reverse iterator).
1079 -- Otherwise, this is iteration over a partial sequence of items. When
1080 -- the Node component is positive, the iterator object was constructed
1081 -- with a start expression, that specifies the position from which the
1082 -- (reverse) partial iteration begins.
1084 if Object.Node = 0 then
1085 return Bounded_Ordered_Maps.Last (Object.Container.all);
1086 else
1087 return Cursor'(Object.Container, Object.Node);
1088 end if;
1089 end Last;
1091 ------------------
1092 -- Last_Element --
1093 ------------------
1095 function Last_Element (Container : Map) return Element_Type is
1096 begin
1097 if Checks and then Container.Last = 0 then
1098 raise Constraint_Error with "map is empty";
1099 end if;
1101 return Container.Nodes (Container.Last).Element;
1102 end Last_Element;
1104 --------------
1105 -- Last_Key --
1106 --------------
1108 function Last_Key (Container : Map) return Key_Type is
1109 begin
1110 if Checks and then Container.Last = 0 then
1111 raise Constraint_Error with "map is empty";
1112 end if;
1114 return Container.Nodes (Container.Last).Key;
1115 end Last_Key;
1117 ----------
1118 -- Left --
1119 ----------
1121 function Left (Node : Node_Type) return Count_Type is
1122 begin
1123 return Node.Left;
1124 end Left;
1126 ------------
1127 -- Length --
1128 ------------
1130 function Length (Container : Map) return Count_Type is
1131 begin
1132 return Container.Length;
1133 end Length;
1135 ----------
1136 -- Move --
1137 ----------
1139 procedure Move (Target : in out Map; Source : in out Map) is
1140 begin
1141 if Target'Address = Source'Address then
1142 return;
1143 end if;
1145 TC_Check (Source.TC);
1147 Target.Assign (Source);
1148 Source.Clear;
1149 end Move;
1151 ----------
1152 -- Next --
1153 ----------
1155 procedure Next (Position : in out Cursor) is
1156 begin
1157 Position := Next (Position);
1158 end Next;
1160 function Next (Position : Cursor) return Cursor is
1161 begin
1162 if Position = No_Element then
1163 return No_Element;
1164 end if;
1166 pragma Assert (Vet (Position.Container.all, Position.Node),
1167 "Position cursor of Next is bad");
1169 declare
1170 M : Map renames Position.Container.all;
1172 Node : constant Count_Type :=
1173 Tree_Operations.Next (M, Position.Node);
1175 begin
1176 if Node = 0 then
1177 return No_Element;
1178 end if;
1180 return Cursor'(Position.Container, Node);
1181 end;
1182 end Next;
1184 function Next
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 Checks and then Position.Container /= Object.Container then
1194 raise Program_Error with
1195 "Position cursor of Next designates wrong map";
1196 end if;
1198 return Next (Position);
1199 end Next;
1201 ------------
1202 -- Parent --
1203 ------------
1205 function Parent (Node : Node_Type) return Count_Type is
1206 begin
1207 return Node.Parent;
1208 end Parent;
1210 --------------
1211 -- Previous --
1212 --------------
1214 procedure Previous (Position : in out Cursor) is
1215 begin
1216 Position := Previous (Position);
1217 end Previous;
1219 function Previous (Position : Cursor) return Cursor is
1220 begin
1221 if Position = No_Element then
1222 return No_Element;
1223 end if;
1225 pragma Assert (Vet (Position.Container.all, Position.Node),
1226 "Position cursor of Previous is bad");
1228 declare
1229 M : Map renames Position.Container.all;
1231 Node : constant Count_Type :=
1232 Tree_Operations.Previous (M, Position.Node);
1234 begin
1235 if Node = 0 then
1236 return No_Element;
1237 end if;
1239 return Cursor'(Position.Container, Node);
1240 end;
1241 end Previous;
1243 function Previous
1244 (Object : Iterator;
1245 Position : Cursor) return Cursor
1247 begin
1248 if Position.Container = null then
1249 return No_Element;
1250 end if;
1252 if Checks and then Position.Container /= Object.Container then
1253 raise Program_Error with
1254 "Position cursor of Previous designates wrong map";
1255 end if;
1257 return Previous (Position);
1258 end Previous;
1260 ----------------------
1261 -- Pseudo_Reference --
1262 ----------------------
1264 function Pseudo_Reference
1265 (Container : aliased Map'Class) return Reference_Control_Type
1267 TC : constant Tamper_Counts_Access :=
1268 Container.TC'Unrestricted_Access;
1269 begin
1270 return R : constant Reference_Control_Type := (Controlled with TC) do
1271 Busy (TC.all);
1272 end return;
1273 end Pseudo_Reference;
1275 -------------------
1276 -- Query_Element --
1277 -------------------
1279 procedure Query_Element
1280 (Position : Cursor;
1281 Process : not null access procedure (Key : Key_Type;
1282 Element : Element_Type))
1284 begin
1285 if Checks and then Position.Node = 0 then
1286 raise Constraint_Error with
1287 "Position cursor of Query_Element equals No_Element";
1288 end if;
1290 pragma Assert (Vet (Position.Container.all, Position.Node),
1291 "Position cursor of Query_Element is bad");
1293 declare
1294 M : Map renames Position.Container.all;
1295 N : Node_Type renames M.Nodes (Position.Node);
1296 Lock : With_Lock (M.TC'Unrestricted_Access);
1297 begin
1298 Process (N.Key, N.Element);
1299 end;
1300 end Query_Element;
1302 ---------------
1303 -- Put_Image --
1304 ---------------
1306 procedure Put_Image
1307 (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; V : Map)
1309 First_Time : Boolean := True;
1310 use System.Put_Images;
1312 procedure Put_Key_Value (Position : Cursor);
1313 procedure Put_Key_Value (Position : Cursor) is
1314 begin
1315 if First_Time then
1316 First_Time := False;
1317 else
1318 Simple_Array_Between (S);
1319 end if;
1321 Key_Type'Put_Image (S, Key (Position));
1322 Put_Arrow (S);
1323 Element_Type'Put_Image (S, Element (Position));
1324 end Put_Key_Value;
1326 begin
1327 Array_Before (S);
1328 Iterate (V, Put_Key_Value'Access);
1329 Array_After (S);
1330 end Put_Image;
1332 ----------
1333 -- Read --
1334 ----------
1336 procedure Read
1337 (Stream : not null access Root_Stream_Type'Class;
1338 Container : out Map)
1340 procedure Read_Element (Node : in out Node_Type);
1341 pragma Inline (Read_Element);
1343 procedure Allocate is
1344 new Tree_Operations.Generic_Allocate (Read_Element);
1346 procedure Read_Elements is
1347 new Tree_Operations.Generic_Read (Allocate);
1349 ------------------
1350 -- Read_Element --
1351 ------------------
1353 procedure Read_Element (Node : in out Node_Type) is
1354 begin
1355 Key_Type'Read (Stream, Node.Key);
1356 Element_Type'Read (Stream, Node.Element);
1357 end Read_Element;
1359 -- Start of processing for Read
1361 begin
1362 Read_Elements (Stream, Container);
1363 end Read;
1365 procedure Read
1366 (Stream : not null access Root_Stream_Type'Class;
1367 Item : out Cursor)
1369 begin
1370 raise Program_Error with "attempt to stream map cursor";
1371 end Read;
1373 procedure Read
1374 (Stream : not null access Root_Stream_Type'Class;
1375 Item : out Reference_Type)
1377 begin
1378 raise Program_Error with "attempt to stream reference";
1379 end Read;
1381 procedure Read
1382 (Stream : not null access Root_Stream_Type'Class;
1383 Item : out Constant_Reference_Type)
1385 begin
1386 raise Program_Error with "attempt to stream reference";
1387 end Read;
1389 ---------------
1390 -- Reference --
1391 ---------------
1393 function Reference
1394 (Container : aliased in out Map;
1395 Position : Cursor) return Reference_Type
1397 begin
1398 if Checks and then Position.Container = null then
1399 raise Constraint_Error with
1400 "Position cursor has no element";
1401 end if;
1403 if Checks and then Position.Container /= Container'Unrestricted_Access
1404 then
1405 raise Program_Error with
1406 "Position cursor designates wrong map";
1407 end if;
1409 pragma Assert (Vet (Container, Position.Node),
1410 "Position cursor in function Reference is bad");
1412 declare
1413 N : Node_Type renames Container.Nodes (Position.Node);
1414 TC : constant Tamper_Counts_Access :=
1415 Container.TC'Unrestricted_Access;
1416 begin
1417 return R : constant Reference_Type :=
1418 (Element => N.Element'Unchecked_Access,
1419 Control => (Controlled with TC))
1421 Busy (TC.all);
1422 end return;
1423 end;
1424 end Reference;
1426 function Reference
1427 (Container : aliased in out Map;
1428 Key : Key_Type) return Reference_Type
1430 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1432 begin
1433 if Checks and then Node = 0 then
1434 raise Constraint_Error with "key not in map";
1435 end if;
1437 declare
1438 N : Node_Type renames Container.Nodes (Node);
1439 TC : constant Tamper_Counts_Access :=
1440 Container.TC'Unrestricted_Access;
1441 begin
1442 return R : constant Reference_Type :=
1443 (Element => N.Element'Unchecked_Access,
1444 Control => (Controlled with TC))
1446 Busy (TC.all);
1447 end return;
1448 end;
1449 end Reference;
1451 -------------
1452 -- Replace --
1453 -------------
1455 procedure Replace
1456 (Container : in out Map;
1457 Key : Key_Type;
1458 New_Item : Element_Type)
1460 Node : constant Count_Type := Key_Ops.Find (Container, Key);
1462 begin
1463 TE_Check (Container.TC);
1465 if Checks and then Node = 0 then
1466 raise Constraint_Error with "key not in map";
1467 end if;
1469 declare
1470 N : Node_Type renames Container.Nodes (Node);
1472 begin
1473 N.Key := Key;
1474 N.Element := New_Item;
1475 end;
1476 end Replace;
1478 ---------------------
1479 -- Replace_Element --
1480 ---------------------
1482 procedure Replace_Element
1483 (Container : in out Map;
1484 Position : Cursor;
1485 New_Item : Element_Type)
1487 begin
1488 TE_Check (Container.TC);
1490 if Checks and then Position.Node = 0 then
1491 raise Constraint_Error with
1492 "Position cursor of Replace_Element equals No_Element";
1493 end if;
1495 if Checks and then Position.Container /= Container'Unrestricted_Access
1496 then
1497 raise Program_Error with
1498 "Position cursor of Replace_Element designates wrong map";
1499 end if;
1501 pragma Assert (Vet (Container, Position.Node),
1502 "Position cursor of Replace_Element is bad");
1504 Container.Nodes (Position.Node).Element := New_Item;
1505 end Replace_Element;
1507 ---------------------
1508 -- Reverse_Iterate --
1509 ---------------------
1511 procedure Reverse_Iterate
1512 (Container : Map;
1513 Process : not null access procedure (Position : Cursor))
1515 procedure Process_Node (Node : Count_Type);
1516 pragma Inline (Process_Node);
1518 procedure Local_Reverse_Iterate is
1519 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1521 ------------------
1522 -- Process_Node --
1523 ------------------
1525 procedure Process_Node (Node : Count_Type) is
1526 begin
1527 Process (Cursor'(Container'Unrestricted_Access, Node));
1528 end Process_Node;
1530 Busy : With_Busy (Container.TC'Unrestricted_Access);
1532 -- Start of processing for Reverse_Iterate
1534 begin
1535 Local_Reverse_Iterate (Container);
1536 end Reverse_Iterate;
1538 -----------
1539 -- Right --
1540 -----------
1542 function Right (Node : Node_Type) return Count_Type is
1543 begin
1544 return Node.Right;
1545 end Right;
1547 ---------------
1548 -- Set_Color --
1549 ---------------
1551 procedure Set_Color
1552 (Node : in out Node_Type;
1553 Color : Color_Type)
1555 begin
1556 Node.Color := Color;
1557 end Set_Color;
1559 --------------
1560 -- Set_Left --
1561 --------------
1563 procedure Set_Left (Node : in out Node_Type; Left : Count_Type) is
1564 begin
1565 Node.Left := Left;
1566 end Set_Left;
1568 ----------------
1569 -- Set_Parent --
1570 ----------------
1572 procedure Set_Parent (Node : in out Node_Type; Parent : Count_Type) is
1573 begin
1574 Node.Parent := Parent;
1575 end Set_Parent;
1577 ---------------
1578 -- Set_Right --
1579 ---------------
1581 procedure Set_Right (Node : in out Node_Type; Right : Count_Type) is
1582 begin
1583 Node.Right := Right;
1584 end Set_Right;
1586 --------------------
1587 -- Update_Element --
1588 --------------------
1590 procedure Update_Element
1591 (Container : in out Map;
1592 Position : Cursor;
1593 Process : not null access procedure (Key : Key_Type;
1594 Element : in out Element_Type))
1596 begin
1597 if Checks and then Position.Node = 0 then
1598 raise Constraint_Error with
1599 "Position cursor of Update_Element equals No_Element";
1600 end if;
1602 if Checks and then Position.Container /= Container'Unrestricted_Access
1603 then
1604 raise Program_Error with
1605 "Position cursor of Update_Element designates wrong map";
1606 end if;
1608 pragma Assert (Vet (Container, Position.Node),
1609 "Position cursor of Update_Element is bad");
1611 declare
1612 N : Node_Type renames Container.Nodes (Position.Node);
1613 Lock : With_Lock (Container.TC'Unrestricted_Access);
1614 begin
1615 Process (N.Key, N.Element);
1616 end;
1617 end Update_Element;
1619 -----------
1620 -- Write --
1621 -----------
1623 procedure Write
1624 (Stream : not null access Root_Stream_Type'Class;
1625 Container : Map)
1627 procedure Write_Node
1628 (Stream : not null access Root_Stream_Type'Class;
1629 Node : Node_Type);
1630 pragma Inline (Write_Node);
1632 procedure Write_Nodes is
1633 new Tree_Operations.Generic_Write (Write_Node);
1635 ----------------
1636 -- Write_Node --
1637 ----------------
1639 procedure Write_Node
1640 (Stream : not null access Root_Stream_Type'Class;
1641 Node : Node_Type)
1643 begin
1644 Key_Type'Write (Stream, Node.Key);
1645 Element_Type'Write (Stream, Node.Element);
1646 end Write_Node;
1648 -- Start of processing for Write
1650 begin
1651 Write_Nodes (Stream, Container);
1652 end Write;
1654 procedure Write
1655 (Stream : not null access Root_Stream_Type'Class;
1656 Item : Cursor)
1658 begin
1659 raise Program_Error with "attempt to stream map cursor";
1660 end Write;
1662 procedure Write
1663 (Stream : not null access Root_Stream_Type'Class;
1664 Item : Reference_Type)
1666 begin
1667 raise Program_Error with "attempt to stream reference";
1668 end Write;
1670 procedure Write
1671 (Stream : not null access Root_Stream_Type'Class;
1672 Item : Constant_Reference_Type)
1674 begin
1675 raise Program_Error with "attempt to stream reference";
1676 end Write;
1678 end Ada.Containers.Bounded_Ordered_Maps;