2005-12-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / ada / a-ciormu.adb
blob458e42e4225f25aba98a77cdc05de8dc2fd8c5f6
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . --
6 -- I N D E F I N I T E _ O R D E R E D _ M U L T I S E T S --
7 -- --
8 -- B o d y --
9 -- --
10 -- Copyright (C) 2004-2005, Free Software Foundation, Inc. --
11 -- --
12 -- This specification is derived from the Ada Reference Manual for use with --
13 -- GNAT. The copyright notice above, and the license provisions that follow --
14 -- apply solely to the contents of the part following the private keyword. --
15 -- --
16 -- GNAT is free software; you can redistribute it and/or modify it under --
17 -- terms of the GNU General Public License as published by the Free Soft- --
18 -- ware Foundation; either version 2, or (at your option) any later ver- --
19 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
20 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
21 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
22 -- for more details. You should have received a copy of the GNU General --
23 -- Public License distributed with GNAT; see file COPYING. If not, write --
24 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
25 -- Boston, MA 02110-1301, USA. --
26 -- --
27 -- As a special exception, if other files instantiate generics from this --
28 -- unit, or you link this unit with other files to produce an executable, --
29 -- this unit does not by itself cause the resulting executable to be --
30 -- covered by the GNU General Public License. This exception does not --
31 -- however invalidate any other reasons why the executable file might be --
32 -- covered by the GNU Public License. --
33 -- --
34 -- This unit was originally developed by Matthew J Heaney. --
35 ------------------------------------------------------------------------------
37 with Ada.Unchecked_Deallocation;
39 with Ada.Containers.Red_Black_Trees.Generic_Operations;
40 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
42 with Ada.Containers.Red_Black_Trees.Generic_Keys;
43 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
45 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
46 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
48 package body Ada.Containers.Indefinite_Ordered_Multisets is
50 -----------------------------
51 -- Node Access Subprograms --
52 -----------------------------
54 -- These subprograms provide a functional interface to access fields
55 -- of a node, and a procedural interface for modifying these values.
57 function Color (Node : Node_Access) return Color_Type;
58 pragma Inline (Color);
60 function Left (Node : Node_Access) return Node_Access;
61 pragma Inline (Left);
63 function Parent (Node : Node_Access) return Node_Access;
64 pragma Inline (Parent);
66 function Right (Node : Node_Access) return Node_Access;
67 pragma Inline (Right);
69 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
70 pragma Inline (Set_Parent);
72 procedure Set_Left (Node : Node_Access; Left : Node_Access);
73 pragma Inline (Set_Left);
75 procedure Set_Right (Node : Node_Access; Right : Node_Access);
76 pragma Inline (Set_Right);
78 procedure Set_Color (Node : Node_Access; Color : Color_Type);
79 pragma Inline (Set_Color);
81 -----------------------
82 -- Local Subprograms --
83 -----------------------
85 function Copy_Node (Source : Node_Access) return Node_Access;
86 pragma Inline (Copy_Node);
88 procedure Free (X : in out Node_Access);
90 procedure Insert_Sans_Hint
91 (Tree : in out Tree_Type;
92 New_Item : Element_Type;
93 Node : out Node_Access);
95 procedure Insert_With_Hint
96 (Dst_Tree : in out Tree_Type;
97 Dst_Hint : Node_Access;
98 Src_Node : Node_Access;
99 Dst_Node : out Node_Access);
101 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
102 pragma Inline (Is_Equal_Node_Node);
104 function Is_Greater_Element_Node
105 (Left : Element_Type;
106 Right : Node_Access) return Boolean;
107 pragma Inline (Is_Greater_Element_Node);
109 function Is_Less_Element_Node
110 (Left : Element_Type;
111 Right : Node_Access) return Boolean;
112 pragma Inline (Is_Less_Element_Node);
114 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
115 pragma Inline (Is_Less_Node_Node);
117 procedure Replace_Element
118 (Tree : in out Tree_Type;
119 Node : Node_Access;
120 Item : Element_Type);
122 --------------------------
123 -- Local Instantiations --
124 --------------------------
126 package Tree_Operations is
127 new Red_Black_Trees.Generic_Operations (Tree_Types);
129 procedure Delete_Tree is
130 new Tree_Operations.Generic_Delete_Tree (Free);
132 function Copy_Tree is
133 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
135 use Tree_Operations;
137 procedure Free_Element is
138 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
140 function Is_Equal is
141 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
143 package Set_Ops is
144 new Generic_Set_Operations
145 (Tree_Operations => Tree_Operations,
146 Insert_With_Hint => Insert_With_Hint,
147 Copy_Tree => Copy_Tree,
148 Delete_Tree => Delete_Tree,
149 Is_Less => Is_Less_Node_Node,
150 Free => Free);
152 package Element_Keys is
153 new Red_Black_Trees.Generic_Keys
154 (Tree_Operations => Tree_Operations,
155 Key_Type => Element_Type,
156 Is_Less_Key_Node => Is_Less_Element_Node,
157 Is_Greater_Key_Node => Is_Greater_Element_Node);
159 ---------
160 -- "<" --
161 ---------
163 function "<" (Left, Right : Cursor) return Boolean is
164 begin
165 if Left.Node = null
166 or else Right.Node = null
167 then
168 raise Constraint_Error;
169 end if;
171 if Left.Node.Element = null
172 or else Right.Node.Element = null
173 then
174 raise Program_Error;
175 end if;
177 pragma Assert (Vet (Left.Container.Tree, Left.Node),
178 "bad Left cursor in ""<""");
180 pragma Assert (Vet (Right.Container.Tree, Right.Node),
181 "bad Right cursor in ""<""");
183 return Left.Node.Element.all < Right.Node.Element.all;
184 end "<";
186 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
187 begin
188 if Left.Node = null then
189 raise Constraint_Error;
190 end if;
192 if Left.Node.Element = null then
193 raise Program_Error;
194 end if;
196 pragma Assert (Vet (Left.Container.Tree, Left.Node),
197 "bad Left cursor in ""<""");
199 return Left.Node.Element.all < Right;
200 end "<";
202 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
203 begin
204 if Right.Node = null then
205 raise Constraint_Error;
206 end if;
208 if Right.Node.Element = null then
209 raise Program_Error;
210 end if;
212 pragma Assert (Vet (Right.Container.Tree, Right.Node),
213 "bad Right cursor in ""<""");
215 return Left < Right.Node.Element.all;
216 end "<";
218 ---------
219 -- "=" --
220 ---------
222 function "=" (Left, Right : Set) return Boolean is
223 begin
224 return Is_Equal (Left.Tree, Right.Tree);
225 end "=";
227 ---------
228 -- ">" --
229 ---------
231 function ">" (Left, Right : Cursor) return Boolean is
232 begin
233 if Left.Node = null
234 or else Right.Node = null
235 then
236 raise Constraint_Error;
237 end if;
239 if Left.Node.Element = null
240 or else Right.Node.Element = null
241 then
242 raise Program_Error;
243 end if;
245 pragma Assert (Vet (Left.Container.Tree, Left.Node),
246 "bad Left cursor in "">""");
248 pragma Assert (Vet (Right.Container.Tree, Right.Node),
249 "bad Right cursor in "">""");
251 -- L > R same as R < L
253 return Right.Node.Element.all < Left.Node.Element.all;
254 end ">";
256 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
257 begin
258 if Left.Node = null then
259 raise Constraint_Error;
260 end if;
262 if Left.Node.Element = null then
263 raise Program_Error;
264 end if;
266 pragma Assert (Vet (Left.Container.Tree, Left.Node),
267 "bad Left cursor in "">""");
269 return Right < Left.Node.Element.all;
270 end ">";
272 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
273 begin
274 if Right.Node = null then
275 raise Constraint_Error;
276 end if;
278 if Right.Node.Element = null then
279 raise Program_Error;
280 end if;
282 pragma Assert (Vet (Right.Container.Tree, Right.Node),
283 "bad Right cursor in "">""");
285 return Right.Node.Element.all < Left;
286 end ">";
288 ------------
289 -- Adjust --
290 ------------
292 procedure Adjust is
293 new Tree_Operations.Generic_Adjust (Copy_Tree);
295 procedure Adjust (Container : in out Set) is
296 begin
297 Adjust (Container.Tree);
298 end Adjust;
300 -------------
301 -- Ceiling --
302 -------------
304 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
305 Node : constant Node_Access :=
306 Element_Keys.Ceiling (Container.Tree, Item);
308 begin
309 if Node = null then
310 return No_Element;
311 end if;
313 return Cursor'(Container'Unrestricted_Access, Node);
314 end Ceiling;
316 -----------
317 -- Clear --
318 -----------
320 procedure Clear is
321 new Tree_Operations.Generic_Clear (Delete_Tree);
323 procedure Clear (Container : in out Set) is
324 begin
325 Clear (Container.Tree);
326 end Clear;
328 -----------
329 -- Color --
330 -----------
332 function Color (Node : Node_Access) return Color_Type is
333 begin
334 return Node.Color;
335 end Color;
337 --------------
338 -- Contains --
339 --------------
341 function Contains (Container : Set; Item : Element_Type) return Boolean is
342 begin
343 return Find (Container, Item) /= No_Element;
344 end Contains;
346 ---------------
347 -- Copy_Node --
348 ---------------
350 function Copy_Node (Source : Node_Access) return Node_Access is
351 X : Element_Access := new Element_Type'(Source.Element.all);
353 begin
354 return new Node_Type'(Parent => null,
355 Left => null,
356 Right => null,
357 Color => Source.Color,
358 Element => X);
360 exception
361 when others =>
362 Free_Element (X);
363 raise;
364 end Copy_Node;
366 ------------
367 -- Delete --
368 ------------
370 procedure Delete (Container : in out Set; Item : Element_Type) is
371 Tree : Tree_Type renames Container.Tree;
372 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
373 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
374 X : Node_Access;
376 begin
377 if Node = Done then
378 raise Constraint_Error;
379 end if;
381 loop
382 X := Node;
383 Node := Tree_Operations.Next (Node);
384 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
385 Free (X);
387 exit when Node = Done;
388 end loop;
389 end Delete;
391 procedure Delete (Container : in out Set; Position : in out Cursor) is
392 begin
393 if Position.Node = null then
394 raise Constraint_Error;
395 end if;
397 if Position.Container /= Container'Unrestricted_Access then
398 raise Program_Error;
399 end if;
401 pragma Assert (Vet (Container.Tree, Position.Node),
402 "bad cursor in Delete");
404 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
405 Free (Position.Node);
407 Position.Container := null;
408 end Delete;
410 ------------------
411 -- Delete_First --
412 ------------------
414 procedure Delete_First (Container : in out Set) is
415 Tree : Tree_Type renames Container.Tree;
416 X : Node_Access := Tree.First;
418 begin
419 if X = null then
420 return;
421 end if;
423 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
424 Free (X);
425 end Delete_First;
427 -----------------
428 -- Delete_Last --
429 -----------------
431 procedure Delete_Last (Container : in out Set) is
432 Tree : Tree_Type renames Container.Tree;
433 X : Node_Access := Tree.Last;
435 begin
436 if X = null then
437 return;
438 end if;
440 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
441 Free (X);
442 end Delete_Last;
444 ----------------
445 -- Difference --
446 ----------------
448 procedure Difference (Target : in out Set; Source : Set) is
449 begin
450 Set_Ops.Difference (Target.Tree, Source.Tree);
451 end Difference;
453 function Difference (Left, Right : Set) return Set is
454 Tree : constant Tree_Type :=
455 Set_Ops.Difference (Left.Tree, Right.Tree);
456 begin
457 return Set'(Controlled with Tree);
458 end Difference;
460 -------------
461 -- Element --
462 -------------
464 function Element (Position : Cursor) return Element_Type is
465 begin
466 if Position.Node = null then
467 raise Constraint_Error;
468 end if;
470 if Position.Node.Element = null then
471 raise Program_Error;
472 end if;
474 pragma Assert (Vet (Position.Container.Tree, Position.Node),
475 "bad cursor in Element");
477 return Position.Node.Element.all;
478 end Element;
480 -------------------------
481 -- Equivalent_Elements --
482 -------------------------
484 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
485 begin
486 if Left < Right
487 or else Right < Left
488 then
489 return False;
490 else
491 return True;
492 end if;
493 end Equivalent_Elements;
495 ---------------------
496 -- Equivalent_Sets --
497 ---------------------
499 function Equivalent_Sets (Left, Right : Set) return Boolean is
501 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
502 pragma Inline (Is_Equivalent_Node_Node);
504 function Is_Equivalent is
505 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
507 -----------------------------
508 -- Is_Equivalent_Node_Node --
509 -----------------------------
511 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
512 begin
513 if L.Element.all < R.Element.all then
514 return False;
515 elsif R.Element.all < L.Element.all then
516 return False;
517 else
518 return True;
519 end if;
520 end Is_Equivalent_Node_Node;
522 -- Start of processing for Equivalent_Sets
524 begin
525 return Is_Equivalent (Left.Tree, Right.Tree);
526 end Equivalent_Sets;
528 -------------
529 -- Exclude --
530 -------------
532 procedure Exclude (Container : in out Set; Item : Element_Type) is
533 Tree : Tree_Type renames Container.Tree;
534 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
535 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
536 X : Node_Access;
538 begin
539 while Node /= Done loop
540 X := Node;
541 Node := Tree_Operations.Next (Node);
542 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
543 Free (X);
544 end loop;
545 end Exclude;
547 ----------
548 -- Find --
549 ----------
551 function Find (Container : Set; Item : Element_Type) return Cursor is
552 Node : constant Node_Access :=
553 Element_Keys.Find (Container.Tree, Item);
555 begin
556 if Node = null then
557 return No_Element;
558 end if;
560 return Cursor'(Container'Unrestricted_Access, Node);
561 end Find;
563 -----------
564 -- First --
565 -----------
567 function First (Container : Set) return Cursor is
568 begin
569 if Container.Tree.First = null then
570 return No_Element;
571 end if;
573 return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
574 end First;
576 -------------------
577 -- First_Element --
578 -------------------
580 function First_Element (Container : Set) return Element_Type is
581 begin
582 if Container.Tree.First = null then
583 raise Constraint_Error;
584 end if;
586 if Container.Tree.First.Element = null then
587 raise Program_Error;
588 end if;
590 return Container.Tree.First.Element.all;
591 end First_Element;
593 -----------
594 -- Floor --
595 -----------
597 function Floor (Container : Set; Item : Element_Type) return Cursor is
598 Node : constant Node_Access :=
599 Element_Keys.Floor (Container.Tree, Item);
601 begin
602 if Node = null then
603 return No_Element;
604 end if;
606 return Cursor'(Container'Unrestricted_Access, Node);
607 end Floor;
609 ----------
610 -- Free --
611 ----------
613 procedure Free (X : in out Node_Access) is
614 procedure Deallocate is
615 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
617 begin
618 if X = null then
619 return;
620 end if;
622 X.Parent := X;
623 X.Left := X;
624 X.Right := X;
626 begin
627 Free_Element (X.Element);
628 exception
629 when others =>
630 X.Element := null;
631 Deallocate (X);
632 raise;
633 end;
635 Deallocate (X);
636 end Free;
638 ------------------
639 -- Generic_Keys --
640 ------------------
642 package body Generic_Keys is
644 -----------------------
645 -- Local Subprograms --
646 -----------------------
648 function Is_Less_Key_Node
649 (Left : Key_Type;
650 Right : Node_Access) return Boolean;
651 pragma Inline (Is_Less_Key_Node);
653 function Is_Greater_Key_Node
654 (Left : Key_Type;
655 Right : Node_Access) return Boolean;
656 pragma Inline (Is_Greater_Key_Node);
658 --------------------------
659 -- Local Instantiations --
660 --------------------------
662 package Key_Keys is
663 new Red_Black_Trees.Generic_Keys
664 (Tree_Operations => Tree_Operations,
665 Key_Type => Key_Type,
666 Is_Less_Key_Node => Is_Less_Key_Node,
667 Is_Greater_Key_Node => Is_Greater_Key_Node);
669 -------------
670 -- Ceiling --
671 -------------
673 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
674 Node : constant Node_Access :=
675 Key_Keys.Ceiling (Container.Tree, Key);
677 begin
678 if Node = null then
679 return No_Element;
680 end if;
682 return Cursor'(Container'Unrestricted_Access, Node);
683 end Ceiling;
685 --------------
686 -- Contains --
687 --------------
689 function Contains (Container : Set; Key : Key_Type) return Boolean is
690 begin
691 return Find (Container, Key) /= No_Element;
692 end Contains;
694 ------------
695 -- Delete --
696 ------------
698 procedure Delete (Container : in out Set; Key : Key_Type) is
699 Tree : Tree_Type renames Container.Tree;
700 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
701 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
702 X : Node_Access;
704 begin
705 if Node = Done then
706 raise Constraint_Error;
707 end if;
709 loop
710 X := Node;
711 Node := Tree_Operations.Next (Node);
712 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
713 Free (X);
715 exit when Node = Done;
716 end loop;
717 end Delete;
719 -------------
720 -- Element --
721 -------------
723 function Element (Container : Set; Key : Key_Type) return Element_Type is
724 Node : constant Node_Access :=
725 Key_Keys.Find (Container.Tree, Key);
727 begin
728 if Node = null then
729 raise Constraint_Error;
730 end if;
732 return Node.Element.all;
733 end Element;
735 ---------------------
736 -- Equivalent_Keys --
737 ---------------------
739 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
740 begin
741 if Left < Right
742 or else Right < Left
743 then
744 return False;
745 else
746 return True;
747 end if;
748 end Equivalent_Keys;
750 -------------
751 -- Exclude --
752 -------------
754 procedure Exclude (Container : in out Set; Key : Key_Type) is
755 Tree : Tree_Type renames Container.Tree;
756 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
757 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
758 X : Node_Access;
760 begin
761 while Node /= Done loop
762 X := Node;
763 Node := Tree_Operations.Next (Node);
764 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
765 Free (X);
766 end loop;
767 end Exclude;
769 ----------
770 -- Find --
771 ----------
773 function Find (Container : Set; Key : Key_Type) return Cursor is
774 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
776 begin
777 if Node = null then
778 return No_Element;
779 end if;
781 return Cursor'(Container'Unrestricted_Access, Node);
782 end Find;
784 -----------
785 -- Floor --
786 -----------
788 function Floor (Container : Set; Key : Key_Type) return Cursor is
789 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
791 begin
792 if Node = null then
793 return No_Element;
794 end if;
796 return Cursor'(Container'Unrestricted_Access, Node);
797 end Floor;
799 -------------------------
800 -- Is_Greater_Key_Node --
801 -------------------------
803 function Is_Greater_Key_Node
804 (Left : Key_Type;
805 Right : Node_Access) return Boolean
807 begin
808 return Key (Right.Element.all) < Left;
809 end Is_Greater_Key_Node;
811 ----------------------
812 -- Is_Less_Key_Node --
813 ----------------------
815 function Is_Less_Key_Node
816 (Left : Key_Type;
817 Right : Node_Access) return Boolean
819 begin
820 return Left < Key (Right.Element.all);
821 end Is_Less_Key_Node;
823 -------------
824 -- Iterate --
825 -------------
827 procedure Iterate
828 (Container : Set;
829 Key : Key_Type;
830 Process : not null access procedure (Position : Cursor))
832 procedure Process_Node (Node : Node_Access);
833 pragma Inline (Process_Node);
835 procedure Local_Iterate is
836 new Key_Keys.Generic_Iteration (Process_Node);
838 ------------------
839 -- Process_Node --
840 ------------------
842 procedure Process_Node (Node : Node_Access) is
843 begin
844 Process (Cursor'(Container'Unrestricted_Access, Node));
845 end Process_Node;
847 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
848 B : Natural renames T.Busy;
850 -- Start of processing for Iterate
852 begin
853 B := B + 1;
855 begin
856 Local_Iterate (T, Key);
857 exception
858 when others =>
859 B := B - 1;
860 raise;
861 end;
863 B := B - 1;
864 end Iterate;
866 ---------
867 -- Key --
868 ---------
870 function Key (Position : Cursor) return Key_Type is
871 begin
872 if Position.Node = null then
873 raise Constraint_Error;
874 end if;
876 if Position.Node.Element = null then
877 raise Program_Error;
878 end if;
880 pragma Assert (Vet (Position.Container.Tree, Position.Node),
881 "bad cursor in Key");
883 return Key (Position.Node.Element.all);
884 end Key;
886 ---------------------
887 -- Reverse_Iterate --
888 ---------------------
890 procedure Reverse_Iterate
891 (Container : Set;
892 Key : Key_Type;
893 Process : not null access procedure (Position : Cursor))
895 procedure Process_Node (Node : Node_Access);
896 pragma Inline (Process_Node);
898 -------------
899 -- Iterate --
900 -------------
902 procedure Local_Reverse_Iterate is
903 new Key_Keys.Generic_Reverse_Iteration (Process_Node);
905 ------------------
906 -- Process_Node --
907 ------------------
909 procedure Process_Node (Node : Node_Access) is
910 begin
911 Process (Cursor'(Container'Unrestricted_Access, Node));
912 end Process_Node;
914 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
915 B : Natural renames T.Busy;
917 -- Start of processing for Reverse_Iterate
919 begin
920 B := B + 1;
922 begin
923 Local_Reverse_Iterate (T, Key);
924 exception
925 when others =>
926 B := B - 1;
927 raise;
928 end;
930 B := B - 1;
931 end Reverse_Iterate;
933 -----------------------------------
934 -- Update_Element_Preserving_Key --
935 -----------------------------------
937 procedure Update_Element_Preserving_Key
938 (Container : in out Set;
939 Position : Cursor;
940 Process : not null access procedure (Element : in out Element_Type))
942 Tree : Tree_Type renames Container.Tree;
944 begin
945 if Position.Node = null then
946 raise Constraint_Error;
947 end if;
949 if Position.Node.Element = null then
950 raise Program_Error;
951 end if;
953 if Position.Container /= Container'Unrestricted_Access then
954 raise Program_Error;
955 end if;
957 pragma Assert (Vet (Container.Tree, Position.Node),
958 "bad cursor in Update_Element_Preserving_Key");
960 declare
961 E : Element_Type renames Position.Node.Element.all;
962 K : constant Key_Type := Key (E);
964 B : Natural renames Tree.Busy;
965 L : Natural renames Tree.Lock;
967 begin
968 B := B + 1;
969 L := L + 1;
971 begin
972 Process (E);
973 exception
974 when others =>
975 L := L - 1;
976 B := B - 1;
977 raise;
978 end;
980 L := L - 1;
981 B := B - 1;
983 if Equivalent_Keys (Left => K, Right => Key (E)) then
984 return;
985 end if;
986 end;
988 declare
989 X : Node_Access := Position.Node;
990 begin
991 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
992 Free (X);
993 end;
995 raise Program_Error;
996 end Update_Element_Preserving_Key;
998 end Generic_Keys;
1000 -----------------
1001 -- Has_Element --
1002 -----------------
1004 function Has_Element (Position : Cursor) return Boolean is
1005 begin
1006 return Position /= No_Element;
1007 end Has_Element;
1009 ------------
1010 -- Insert --
1011 ------------
1013 procedure Insert (Container : in out Set; New_Item : Element_Type) is
1014 Position : Cursor;
1015 begin
1016 Insert (Container, New_Item, Position);
1017 end Insert;
1019 procedure Insert
1020 (Container : in out Set;
1021 New_Item : Element_Type;
1022 Position : out Cursor)
1024 begin
1025 Insert_Sans_Hint
1026 (Container.Tree,
1027 New_Item,
1028 Position.Node);
1030 Position.Container := Container'Unrestricted_Access;
1031 end Insert;
1033 ----------------------
1034 -- Insert_Sans_Hint --
1035 ----------------------
1037 procedure Insert_Sans_Hint
1038 (Tree : in out Tree_Type;
1039 New_Item : Element_Type;
1040 Node : out Node_Access)
1042 function New_Node return Node_Access;
1043 pragma Inline (New_Node);
1045 procedure Insert_Post is
1046 new Element_Keys.Generic_Insert_Post (New_Node);
1048 procedure Unconditional_Insert_Sans_Hint is
1049 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1051 --------------
1052 -- New_Node --
1053 --------------
1055 function New_Node return Node_Access is
1056 X : Element_Access := new Element_Type'(New_Item);
1058 begin
1059 return new Node_Type'(Parent => null,
1060 Left => null,
1061 Right => null,
1062 Color => Red_Black_Trees.Red,
1063 Element => X);
1065 exception
1066 when others =>
1067 Free_Element (X);
1068 raise;
1069 end New_Node;
1071 -- Start of processing for Insert_Sans_Hint
1073 begin
1074 Unconditional_Insert_Sans_Hint
1075 (Tree,
1076 New_Item,
1077 Node);
1078 end Insert_Sans_Hint;
1080 ----------------------
1081 -- Insert_With_Hint --
1082 ----------------------
1084 procedure Insert_With_Hint
1085 (Dst_Tree : in out Tree_Type;
1086 Dst_Hint : Node_Access;
1087 Src_Node : Node_Access;
1088 Dst_Node : out Node_Access)
1090 function New_Node return Node_Access;
1091 pragma Inline (New_Node);
1093 procedure Insert_Post is
1094 new Element_Keys.Generic_Insert_Post (New_Node);
1096 procedure Insert_Sans_Hint is
1097 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1099 procedure Local_Insert_With_Hint is
1100 new Element_Keys.Generic_Unconditional_Insert_With_Hint
1101 (Insert_Post,
1102 Insert_Sans_Hint);
1104 --------------
1105 -- New_Node --
1106 --------------
1108 function New_Node return Node_Access is
1109 X : Element_Access := new Element_Type'(Src_Node.Element.all);
1111 begin
1112 return new Node_Type'(Parent => null,
1113 Left => null,
1114 Right => null,
1115 Color => Red,
1116 Element => X);
1118 exception
1119 when others =>
1120 Free_Element (X);
1121 raise;
1122 end New_Node;
1124 -- Start of processing for Insert_With_Hint
1126 begin
1127 Local_Insert_With_Hint
1128 (Dst_Tree,
1129 Dst_Hint,
1130 Src_Node.Element.all,
1131 Dst_Node);
1132 end Insert_With_Hint;
1134 ------------------
1135 -- Intersection --
1136 ------------------
1138 procedure Intersection (Target : in out Set; Source : Set) is
1139 begin
1140 Set_Ops.Intersection (Target.Tree, Source.Tree);
1141 end Intersection;
1143 function Intersection (Left, Right : Set) return Set is
1144 Tree : constant Tree_Type :=
1145 Set_Ops.Intersection (Left.Tree, Right.Tree);
1146 begin
1147 return Set'(Controlled with Tree);
1148 end Intersection;
1150 --------------
1151 -- Is_Empty --
1152 --------------
1154 function Is_Empty (Container : Set) return Boolean is
1155 begin
1156 return Container.Tree.Length = 0;
1157 end Is_Empty;
1159 ------------------------
1160 -- Is_Equal_Node_Node --
1161 ------------------------
1163 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1164 begin
1165 return L.Element.all = R.Element.all;
1166 end Is_Equal_Node_Node;
1168 -----------------------------
1169 -- Is_Greater_Element_Node --
1170 -----------------------------
1172 function Is_Greater_Element_Node
1173 (Left : Element_Type;
1174 Right : Node_Access) return Boolean
1176 begin
1177 -- e > node same as node < e
1179 return Right.Element.all < Left;
1180 end Is_Greater_Element_Node;
1182 --------------------------
1183 -- Is_Less_Element_Node --
1184 --------------------------
1186 function Is_Less_Element_Node
1187 (Left : Element_Type;
1188 Right : Node_Access) return Boolean
1190 begin
1191 return Left < Right.Element.all;
1192 end Is_Less_Element_Node;
1194 -----------------------
1195 -- Is_Less_Node_Node --
1196 -----------------------
1198 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1199 begin
1200 return L.Element.all < R.Element.all;
1201 end Is_Less_Node_Node;
1203 ---------------
1204 -- Is_Subset --
1205 ---------------
1207 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1208 begin
1209 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1210 end Is_Subset;
1212 -------------
1213 -- Iterate --
1214 -------------
1216 procedure Iterate
1217 (Container : Set;
1218 Item : Element_Type;
1219 Process : not null access procedure (Position : Cursor))
1221 procedure Process_Node (Node : Node_Access);
1222 pragma Inline (Process_Node);
1224 procedure Local_Iterate is
1225 new Element_Keys.Generic_Iteration (Process_Node);
1227 ------------------
1228 -- Process_Node --
1229 ------------------
1231 procedure Process_Node (Node : Node_Access) is
1232 begin
1233 Process (Cursor'(Container'Unrestricted_Access, Node));
1234 end Process_Node;
1236 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1237 B : Natural renames T.Busy;
1239 -- Start of processing for Iterate
1241 begin
1242 B := B + 1;
1244 begin
1245 Local_Iterate (T, Item);
1246 exception
1247 when others =>
1248 B := B - 1;
1249 raise;
1250 end;
1252 B := B - 1;
1253 end Iterate;
1255 procedure Iterate
1256 (Container : Set;
1257 Process : not null access procedure (Position : Cursor))
1259 procedure Process_Node (Node : Node_Access);
1260 pragma Inline (Process_Node);
1262 procedure Local_Iterate is
1263 new Tree_Operations.Generic_Iteration (Process_Node);
1265 ------------------
1266 -- Process_Node --
1267 ------------------
1269 procedure Process_Node (Node : Node_Access) is
1270 begin
1271 Process (Cursor'(Container'Unrestricted_Access, Node));
1272 end Process_Node;
1274 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1275 B : Natural renames T.Busy;
1277 -- Start of processing for Iterate
1279 begin
1280 B := B + 1;
1282 begin
1283 Local_Iterate (T);
1284 exception
1285 when others =>
1286 B := B - 1;
1287 raise;
1288 end;
1290 B := B - 1;
1291 end Iterate;
1293 ----------
1294 -- Last --
1295 ----------
1297 function Last (Container : Set) return Cursor is
1298 begin
1299 if Container.Tree.Last = null then
1300 return No_Element;
1301 end if;
1303 return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1304 end Last;
1306 ------------------
1307 -- Last_Element --
1308 ------------------
1310 function Last_Element (Container : Set) return Element_Type is
1311 begin
1312 if Container.Tree.Last = null then
1313 raise Constraint_Error;
1314 end if;
1316 return Container.Tree.Last.Element.all;
1317 end Last_Element;
1319 ----------
1320 -- Left --
1321 ----------
1323 function Left (Node : Node_Access) return Node_Access is
1324 begin
1325 return Node.Left;
1326 end Left;
1328 ------------
1329 -- Length --
1330 ------------
1332 function Length (Container : Set) return Count_Type is
1333 begin
1334 return Container.Tree.Length;
1335 end Length;
1337 ----------
1338 -- Move --
1339 ----------
1341 procedure Move is
1342 new Tree_Operations.Generic_Move (Clear);
1344 procedure Move (Target : in out Set; Source : in out Set) is
1345 begin
1346 Move (Target => Target.Tree, Source => Source.Tree);
1347 end Move;
1349 ----------
1350 -- Next --
1351 ----------
1353 function Next (Position : Cursor) return Cursor is
1354 begin
1355 if Position = No_Element then
1356 return No_Element;
1357 end if;
1359 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1360 "bad cursor in Next");
1362 declare
1363 Node : constant Node_Access :=
1364 Tree_Operations.Next (Position.Node);
1366 begin
1367 if Node = null then
1368 return No_Element;
1369 end if;
1371 return Cursor'(Position.Container, Node);
1372 end;
1373 end Next;
1375 procedure Next (Position : in out Cursor) is
1376 begin
1377 Position := Next (Position);
1378 end Next;
1380 -------------
1381 -- Overlap --
1382 -------------
1384 function Overlap (Left, Right : Set) return Boolean is
1385 begin
1386 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1387 end Overlap;
1389 ------------
1390 -- Parent --
1391 ------------
1393 function Parent (Node : Node_Access) return Node_Access is
1394 begin
1395 return Node.Parent;
1396 end Parent;
1398 --------------
1399 -- Previous --
1400 --------------
1402 function Previous (Position : Cursor) return Cursor is
1403 begin
1404 if Position = No_Element then
1405 return No_Element;
1406 end if;
1408 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1409 "bad cursor in Previous");
1411 declare
1412 Node : constant Node_Access :=
1413 Tree_Operations.Previous (Position.Node);
1415 begin
1416 if Node = null then
1417 return No_Element;
1418 end if;
1420 return Cursor'(Position.Container, Node);
1421 end;
1422 end Previous;
1424 procedure Previous (Position : in out Cursor) is
1425 begin
1426 Position := Previous (Position);
1427 end Previous;
1429 -------------------
1430 -- Query_Element --
1431 -------------------
1433 procedure Query_Element
1434 (Position : Cursor;
1435 Process : not null access procedure (Element : Element_Type))
1437 begin
1438 if Position.Node = null then
1439 raise Constraint_Error;
1440 end if;
1442 if Position.Node.Element = null then
1443 raise Program_Error;
1444 end if;
1446 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1447 "bad cursor in Query_Element");
1449 declare
1450 T : Tree_Type renames Position.Container.Tree;
1452 B : Natural renames T.Busy;
1453 L : Natural renames T.Lock;
1455 begin
1456 B := B + 1;
1457 L := L + 1;
1459 begin
1460 Process (Position.Node.Element.all);
1461 exception
1462 when others =>
1463 L := L - 1;
1464 B := B - 1;
1465 raise;
1466 end;
1468 L := L - 1;
1469 B := B - 1;
1470 end;
1471 end Query_Element;
1473 ----------
1474 -- Read --
1475 ----------
1477 procedure Read
1478 (Stream : access Root_Stream_Type'Class;
1479 Container : out Set)
1481 function Read_Node
1482 (Stream : access Root_Stream_Type'Class) return Node_Access;
1483 pragma Inline (Read_Node);
1485 procedure Read is
1486 new Tree_Operations.Generic_Read (Clear, Read_Node);
1488 ---------------
1489 -- Read_Node --
1490 ---------------
1492 function Read_Node
1493 (Stream : access Root_Stream_Type'Class) return Node_Access
1495 Node : Node_Access := new Node_Type;
1496 begin
1497 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1498 return Node;
1499 exception
1500 when others =>
1501 Free (Node); -- Note that Free deallocates elem too
1502 raise;
1503 end Read_Node;
1505 -- Start of processing for Read
1507 begin
1508 Read (Stream, Container.Tree);
1509 end Read;
1511 procedure Read
1512 (Stream : access Root_Stream_Type'Class;
1513 Item : out Cursor)
1515 begin
1516 raise Program_Error;
1517 end Read;
1519 ---------------------
1520 -- Replace_Element --
1521 ---------------------
1523 procedure Replace_Element
1524 (Tree : in out Tree_Type;
1525 Node : Node_Access;
1526 Item : Element_Type)
1528 begin
1529 if Item < Node.Element.all
1530 or else Node.Element.all < Item
1531 then
1532 null;
1533 else
1534 if Tree.Lock > 0 then
1535 raise Program_Error;
1536 end if;
1538 declare
1539 X : Element_Access := Node.Element;
1540 begin
1541 Node.Element := new Element_Type'(Item);
1542 Free_Element (X);
1543 end;
1545 return;
1546 end if;
1548 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1550 Insert_New_Item : declare
1551 function New_Node return Node_Access;
1552 pragma Inline (New_Node);
1554 procedure Insert_Post is
1555 new Element_Keys.Generic_Insert_Post (New_Node);
1557 procedure Unconditional_Insert is
1558 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
1560 --------------
1561 -- New_Node --
1562 --------------
1564 function New_Node return Node_Access is
1565 begin
1566 Node.Element := new Element_Type'(Item); -- OK if fails
1567 Node.Color := Red_Black_Trees.Red;
1568 Node.Parent := null;
1569 Node.Left := null;
1570 Node.Right := null;
1572 return Node;
1573 end New_Node;
1575 Result : Node_Access;
1577 X : Element_Access := Node.Element;
1579 -- Start of processing for Insert_New_Item
1581 begin
1582 Unconditional_Insert
1583 (Tree => Tree,
1584 Key => Item,
1585 Node => Result);
1586 pragma Assert (Result = Node);
1588 Free_Element (X); -- OK if fails
1589 end Insert_New_Item;
1590 end Replace_Element;
1592 procedure Replace_Element
1593 (Container : in out Set;
1594 Position : Cursor;
1595 New_Item : Element_Type)
1597 begin
1598 if Position.Node = null then
1599 raise Constraint_Error;
1600 end if;
1602 if Position.Node.Element = null then
1603 raise Program_Error;
1604 end if;
1606 if Position.Container /= Container'Unrestricted_Access then
1607 raise Program_Error;
1608 end if;
1610 pragma Assert (Vet (Container.Tree, Position.Node),
1611 "bad cursor in Replace_Element");
1613 Replace_Element (Container.Tree, Position.Node, New_Item);
1614 end Replace_Element;
1616 ---------------------
1617 -- Reverse_Iterate --
1618 ---------------------
1620 procedure Reverse_Iterate
1621 (Container : Set;
1622 Item : Element_Type;
1623 Process : not null access procedure (Position : Cursor))
1625 procedure Process_Node (Node : Node_Access);
1626 pragma Inline (Process_Node);
1628 procedure Local_Reverse_Iterate is
1629 new Element_Keys.Generic_Reverse_Iteration (Process_Node);
1631 ------------------
1632 -- Process_Node --
1633 ------------------
1635 procedure Process_Node (Node : Node_Access) is
1636 begin
1637 Process (Cursor'(Container'Unrestricted_Access, Node));
1638 end Process_Node;
1640 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1641 B : Natural renames T.Busy;
1643 -- Start of processing for Reverse_Iterate
1645 begin
1646 B := B + 1;
1648 begin
1649 Local_Reverse_Iterate (T, Item);
1650 exception
1651 when others =>
1652 B := B - 1;
1653 raise;
1654 end;
1656 B := B - 1;
1657 end Reverse_Iterate;
1659 procedure Reverse_Iterate
1660 (Container : Set;
1661 Process : not null access procedure (Position : Cursor))
1663 procedure Process_Node (Node : Node_Access);
1664 pragma Inline (Process_Node);
1666 procedure Local_Reverse_Iterate is
1667 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1669 ------------------
1670 -- Process_Node --
1671 ------------------
1673 procedure Process_Node (Node : Node_Access) is
1674 begin
1675 Process (Cursor'(Container'Unrestricted_Access, Node));
1676 end Process_Node;
1678 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1679 B : Natural renames T.Busy;
1681 -- Start of processing for Reverse_Iterate
1683 begin
1684 B := B + 1;
1686 begin
1687 Local_Reverse_Iterate (T);
1688 exception
1689 when others =>
1690 B := B - 1;
1691 raise;
1692 end;
1694 B := B - 1;
1695 end Reverse_Iterate;
1697 -----------
1698 -- Right --
1699 -----------
1701 function Right (Node : Node_Access) return Node_Access is
1702 begin
1703 return Node.Right;
1704 end Right;
1706 ---------------
1707 -- Set_Color --
1708 ---------------
1710 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1711 begin
1712 Node.Color := Color;
1713 end Set_Color;
1715 --------------
1716 -- Set_Left --
1717 --------------
1719 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1720 begin
1721 Node.Left := Left;
1722 end Set_Left;
1724 ----------------
1725 -- Set_Parent --
1726 ----------------
1728 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1729 begin
1730 Node.Parent := Parent;
1731 end Set_Parent;
1733 ---------------
1734 -- Set_Right --
1735 ---------------
1737 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1738 begin
1739 Node.Right := Right;
1740 end Set_Right;
1742 --------------------------
1743 -- Symmetric_Difference --
1744 --------------------------
1746 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1747 begin
1748 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1749 end Symmetric_Difference;
1751 function Symmetric_Difference (Left, Right : Set) return Set is
1752 Tree : constant Tree_Type :=
1753 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1754 begin
1755 return Set'(Controlled with Tree);
1756 end Symmetric_Difference;
1758 ------------
1759 -- To_Set --
1760 ------------
1762 function To_Set (New_Item : Element_Type) return Set is
1763 Tree : Tree_Type;
1764 Node : Node_Access;
1766 begin
1767 Insert_Sans_Hint (Tree, New_Item, Node);
1768 return Set'(Controlled with Tree);
1769 end To_Set;
1771 -----------
1772 -- Union --
1773 -----------
1775 procedure Union (Target : in out Set; Source : Set) is
1776 begin
1777 Set_Ops.Union (Target.Tree, Source.Tree);
1778 end Union;
1780 function Union (Left, Right : Set) return Set is
1781 Tree : constant Tree_Type :=
1782 Set_Ops.Union (Left.Tree, Right.Tree);
1783 begin
1784 return Set'(Controlled with Tree);
1785 end Union;
1787 -----------
1788 -- Write --
1789 -----------
1791 procedure Write
1792 (Stream : access Root_Stream_Type'Class;
1793 Container : Set)
1795 procedure Write_Node
1796 (Stream : access Root_Stream_Type'Class;
1797 Node : Node_Access);
1798 pragma Inline (Write_Node);
1800 procedure Write is
1801 new Tree_Operations.Generic_Write (Write_Node);
1803 ----------------
1804 -- Write_Node --
1805 ----------------
1807 procedure Write_Node
1808 (Stream : access Root_Stream_Type'Class;
1809 Node : Node_Access)
1811 begin
1812 Element_Type'Output (Stream, Node.Element.all);
1813 end Write_Node;
1815 -- Start of processing for Write
1817 begin
1818 Write (Stream, Container.Tree);
1819 end Write;
1821 procedure Write
1822 (Stream : access Root_Stream_Type'Class;
1823 Item : Cursor)
1825 begin
1826 raise Program_Error;
1827 end Write;
1829 end Ada.Containers.Indefinite_Ordered_Multisets;