2005-03-23 Daniel Berlin <dberlin@dberlin.org>
[official-gcc.git] / gcc / ada / a-coormu.adb
blob20712960bf955b9d60a574bc1bd9b63882db5de6
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.ORDERED_MULTISETS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004 Free Software Foundation, Inc. --
10 -- --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
14 -- --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 2, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21 -- for more details. You should have received a copy of the GNU General --
22 -- Public License distributed with GNAT; see file COPYING. If not, write --
23 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
24 -- MA 02111-1307, USA. --
25 -- --
26 -- As a special exception, if other files instantiate generics from this --
27 -- unit, or you link this unit with other files to produce an executable, --
28 -- this unit does not by itself cause the resulting executable to be --
29 -- covered by the GNU General Public License. This exception does not --
30 -- however invalidate any other reasons why the executable file might be --
31 -- covered by the GNU Public License. --
32 -- --
33 -- This unit was originally developed by Matthew J Heaney. --
34 ------------------------------------------------------------------------------
36 with Ada.Unchecked_Deallocation;
38 with Ada.Containers.Red_Black_Trees.Generic_Operations;
39 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
41 with Ada.Containers.Red_Black_Trees.Generic_Keys;
42 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
44 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
45 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
47 with System; use type System.Address;
49 package body Ada.Containers.Ordered_Multisets is
51 use Red_Black_Trees;
53 type Node_Type is limited record
54 Parent : Node_Access;
55 Left : Node_Access;
56 Right : Node_Access;
57 Color : Red_Black_Trees.Color_Type := Red;
58 Element : Element_Type;
59 end record;
61 -----------------------------
62 -- Node Access Subprograms --
63 -----------------------------
65 -- These subprograms provide a functional interface to access fields
66 -- of a node, and a procedural interface for modifying these values.
68 function Color (Node : Node_Access) return Color_Type;
69 pragma Inline (Color);
71 function Left (Node : Node_Access) return Node_Access;
72 pragma Inline (Left);
74 function Parent (Node : Node_Access) return Node_Access;
75 pragma Inline (Parent);
77 function Right (Node : Node_Access) return Node_Access;
78 pragma Inline (Right);
80 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
81 pragma Inline (Set_Parent);
83 procedure Set_Left (Node : Node_Access; Left : Node_Access);
84 pragma Inline (Set_Left);
86 procedure Set_Right (Node : Node_Access; Right : Node_Access);
87 pragma Inline (Set_Right);
89 procedure Set_Color (Node : Node_Access; Color : Color_Type);
90 pragma Inline (Set_Color);
92 -----------------------
93 -- Local Subprograms --
94 -----------------------
96 function Copy_Node (Source : Node_Access) return Node_Access;
97 pragma Inline (Copy_Node);
99 function Copy_Tree (Source_Root : Node_Access) return Node_Access;
101 procedure Delete_Tree (X : in out Node_Access);
103 procedure Insert_With_Hint
104 (Dst_Tree : in out Tree_Type;
105 Dst_Hint : Node_Access;
106 Src_Node : Node_Access;
107 Dst_Node : out Node_Access);
109 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
110 pragma Inline (Is_Equal_Node_Node);
112 function Is_Greater_Element_Node
113 (Left : Element_Type;
114 Right : Node_Access) return Boolean;
115 pragma Inline (Is_Greater_Element_Node);
117 function Is_Less_Element_Node
118 (Left : Element_Type;
119 Right : Node_Access) return Boolean;
120 pragma Inline (Is_Less_Element_Node);
122 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
123 pragma Inline (Is_Less_Node_Node);
125 --------------------------
126 -- Local Instantiations --
127 --------------------------
129 package Tree_Operations is
130 new Red_Black_Trees.Generic_Operations
131 (Tree_Types => Tree_Types,
132 Null_Node => Node_Access'(null));
134 use Tree_Operations;
136 procedure Free is
137 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
139 function Is_Equal is
140 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
142 package Element_Keys is
143 new Red_Black_Trees.Generic_Keys
144 (Tree_Operations => Tree_Operations,
145 Key_Type => Element_Type,
146 Is_Less_Key_Node => Is_Less_Element_Node,
147 Is_Greater_Key_Node => Is_Greater_Element_Node);
149 package Set_Ops is
150 new Generic_Set_Operations
151 (Tree_Operations => Tree_Operations,
152 Insert_With_Hint => Insert_With_Hint,
153 Copy_Tree => Copy_Tree,
154 Delete_Tree => Delete_Tree,
155 Is_Less => Is_Less_Node_Node,
156 Free => Free);
158 ---------
159 -- "<" --
160 ---------
162 function "<" (Left, Right : Cursor) return Boolean is
163 begin
164 return Left.Node.Element < Right.Node.Element;
165 end "<";
167 function "<" (Left : Cursor; Right : Element_Type)
168 return Boolean is
169 begin
170 return Left.Node.Element < Right;
171 end "<";
173 function "<" (Left : Element_Type; Right : Cursor)
174 return Boolean is
175 begin
176 return Left < Right.Node.Element;
177 end "<";
179 ---------
180 -- "=" --
181 ---------
183 function "=" (Left, Right : Set) return Boolean is
184 begin
185 if Left'Address = Right'Address then
186 return True;
187 end if;
189 return Is_Equal (Left.Tree, Right.Tree);
190 end "=";
192 ---------
193 -- ">" --
194 ---------
196 function ">" (Left, Right : Cursor) return Boolean is
197 begin
198 -- L > R same as R < L
200 return Right.Node.Element < Left.Node.Element;
201 end ">";
203 function ">" (Left : Cursor; Right : Element_Type)
204 return Boolean is
205 begin
206 return Right < Left.Node.Element;
207 end ">";
209 function ">" (Left : Element_Type; Right : Cursor)
210 return Boolean is
211 begin
212 return Right.Node.Element < Left;
213 end ">";
215 ------------
216 -- Adjust --
217 ------------
219 procedure Adjust (Container : in out Set) is
220 Tree : Tree_Type renames Container.Tree;
222 N : constant Count_Type := Tree.Length;
223 X : constant Node_Access := Tree.Root;
225 begin
226 if N = 0 then
227 pragma Assert (X = null);
228 return;
229 end if;
231 Tree := (Length => 0, others => null);
233 Tree.Root := Copy_Tree (X);
234 Tree.First := Min (Tree.Root);
235 Tree.Last := Max (Tree.Root);
236 Tree.Length := N;
237 end Adjust;
239 -------------
240 -- Ceiling --
241 -------------
243 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
244 Node : constant Node_Access :=
245 Element_Keys.Ceiling (Container.Tree, Item);
247 begin
248 if Node = null then
249 return No_Element;
250 end if;
252 return Cursor'(Container'Unchecked_Access, Node);
253 end Ceiling;
255 -----------
256 -- Clear --
257 -----------
259 procedure Clear (Container : in out Set) is
260 Tree : Tree_Type renames Container.Tree;
261 Root : Node_Access := Tree.Root;
262 begin
263 Tree := (Length => 0, others => null);
264 Delete_Tree (Root);
265 end Clear;
267 -----------
268 -- Color --
269 -----------
271 function Color (Node : Node_Access) return Color_Type is
272 begin
273 return Node.Color;
274 end Color;
276 --------------
277 -- Contains --
278 --------------
280 function Contains (Container : Set; Item : Element_Type) return Boolean is
281 begin
282 return Find (Container, Item) /= No_Element;
283 end Contains;
285 ---------------
286 -- Copy_Node --
287 ---------------
289 function Copy_Node (Source : Node_Access) return Node_Access is
290 Target : constant Node_Access :=
291 new Node_Type'(Parent => null,
292 Left => null,
293 Right => null,
294 Color => Source.Color,
295 Element => Source.Element);
296 begin
297 return Target;
298 end Copy_Node;
300 ---------------
301 -- Copy_Tree --
302 ---------------
304 function Copy_Tree (Source_Root : Node_Access) return Node_Access is
305 Target_Root : Node_Access := Copy_Node (Source_Root);
307 P, X : Node_Access;
309 begin
310 if Source_Root.Right /= null then
311 Target_Root.Right := Copy_Tree (Source_Root.Right);
312 Target_Root.Right.Parent := Target_Root;
313 end if;
315 P := Target_Root;
316 X := Source_Root.Left;
317 while X /= null loop
318 declare
319 Y : Node_Access := Copy_Node (X);
321 begin
322 P.Left := Y;
323 Y.Parent := P;
325 if X.Right /= null then
326 Y.Right := Copy_Tree (X.Right);
327 Y.Right.Parent := Y;
328 end if;
330 P := Y;
331 X := X.Left;
332 end;
333 end loop;
335 return Target_Root;
337 exception
338 when others =>
339 Delete_Tree (Target_Root);
340 raise;
341 end Copy_Tree;
343 ------------
344 -- Delete --
345 ------------
347 procedure Delete (Container : in out Set; Item : Element_Type) is
348 Tree : Tree_Type renames Container.Tree;
349 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
350 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
351 X : Node_Access;
353 begin
354 if Node = Done then
355 raise Constraint_Error;
356 end if;
358 loop
359 X := Node;
360 Node := Tree_Operations.Next (Node);
361 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
362 Free (X);
364 exit when Node = Done;
365 end loop;
366 end Delete;
368 procedure Delete (Container : in out Set; Position : in out Cursor) is
369 begin
370 if Position = No_Element then
371 return;
372 end if;
374 if Position.Container /= Set_Access'(Container'Unchecked_Access) then
375 raise Program_Error;
376 end if;
378 Delete_Node_Sans_Free (Container.Tree, Position.Node);
379 Free (Position.Node);
381 Position.Container := null;
382 end Delete;
384 ------------------
385 -- Delete_First --
386 ------------------
388 procedure Delete_First (Container : in out Set) is
389 Tree : Tree_Type renames Container.Tree;
390 X : Node_Access := Tree.First;
392 begin
393 if X = null then
394 return;
395 end if;
397 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
398 Free (X);
399 end Delete_First;
401 -----------------
402 -- Delete_Last --
403 -----------------
405 procedure Delete_Last (Container : in out Set) is
406 Tree : Tree_Type renames Container.Tree;
407 X : Node_Access := Tree.Last;
409 begin
410 if X = null then
411 return;
412 end if;
414 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
415 Free (X);
416 end Delete_Last;
418 -----------------
419 -- Delete_Tree --
420 -----------------
422 procedure Delete_Tree (X : in out Node_Access) is
423 Y : Node_Access;
424 begin
425 while X /= null loop
426 Y := X.Right;
427 Delete_Tree (Y);
428 Y := X.Left;
429 Free (X);
430 X := Y;
431 end loop;
432 end Delete_Tree;
434 ----------------
435 -- Difference --
436 ----------------
438 procedure Difference (Target : in out Set; Source : Set) is
439 begin
440 if Target'Address = Source'Address then
441 Clear (Target);
442 return;
443 end if;
445 Set_Ops.Difference (Target.Tree, Source.Tree);
446 end Difference;
448 function Difference (Left, Right : Set) return Set is
449 begin
450 if Left'Address = Right'Address then
451 return Empty_Set;
452 end if;
454 declare
455 Tree : constant Tree_Type :=
456 Set_Ops.Difference (Left.Tree, Right.Tree);
457 begin
458 return (Controlled with Tree);
459 end;
460 end Difference;
462 -------------
463 -- Element --
464 -------------
466 function Element (Position : Cursor) return Element_Type is
467 begin
468 return Position.Node.Element;
469 end Element;
471 -------------
472 -- Exclude --
473 -------------
475 procedure Exclude (Container : in out Set; Item : Element_Type) is
476 Tree : Tree_Type renames Container.Tree;
477 Node : Node_Access := Element_Keys.Ceiling (Tree, Item);
478 Done : constant Node_Access := Element_Keys.Upper_Bound (Tree, Item);
479 X : Node_Access;
480 begin
481 while Node /= Done loop
482 X := Node;
483 Node := Tree_Operations.Next (Node);
484 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
485 Free (X);
486 end loop;
487 end Exclude;
489 ----------
490 -- Find --
491 ----------
493 function Find (Container : Set; Item : Element_Type) return Cursor is
494 Node : constant Node_Access :=
495 Element_Keys.Find (Container.Tree, Item);
497 begin
498 if Node = null then
499 return No_Element;
500 end if;
502 return Cursor'(Container'Unchecked_Access, Node);
503 end Find;
505 -----------
506 -- First --
507 -----------
509 function First (Container : Set) return Cursor is
510 begin
511 if Container.Tree.First = null then
512 return No_Element;
513 end if;
515 return Cursor'(Container'Unchecked_Access, Container.Tree.First);
516 end First;
518 -------------------
519 -- First_Element --
520 -------------------
522 function First_Element (Container : Set) return Element_Type is
523 begin
524 return Container.Tree.First.Element;
525 end First_Element;
527 -----------
528 -- Floor --
529 -----------
531 function Floor (Container : Set; Item : Element_Type) return Cursor is
532 Node : constant Node_Access :=
533 Element_Keys.Floor (Container.Tree, Item);
535 begin
536 if Node = null then
537 return No_Element;
538 end if;
540 return Cursor'(Container'Unchecked_Access, Node);
541 end Floor;
543 ------------------
544 -- Generic_Keys --
545 ------------------
547 package body Generic_Keys is
549 -----------------------
550 -- Local Subprograms --
551 -----------------------
553 function Is_Greater_Key_Node
554 (Left : Key_Type;
555 Right : Node_Access) return Boolean;
556 pragma Inline (Is_Greater_Key_Node);
558 function Is_Less_Key_Node
559 (Left : Key_Type;
560 Right : Node_Access) return Boolean;
561 pragma Inline (Is_Less_Key_Node);
563 --------------------------
564 -- Local_Instantiations --
565 --------------------------
567 package Key_Keys is
568 new Red_Black_Trees.Generic_Keys
569 (Tree_Operations => Tree_Operations,
570 Key_Type => Key_Type,
571 Is_Less_Key_Node => Is_Less_Key_Node,
572 Is_Greater_Key_Node => Is_Greater_Key_Node);
574 ---------
575 -- "<" --
576 ---------
578 function "<" (Left : Key_Type; Right : Cursor) return Boolean is
579 begin
580 return Left < Right.Node.Element;
581 end "<";
583 function "<" (Left : Cursor; Right : Key_Type) return Boolean is
584 begin
585 return Right > Left.Node.Element;
586 end "<";
588 ---------
589 -- ">" --
590 ---------
592 function ">" (Left : Cursor; Right : Key_Type) return Boolean is
593 begin
594 return Right < Left.Node.Element;
595 end ">";
597 function ">" (Left : Key_Type; Right : Cursor) return Boolean is
598 begin
599 return Left > Right.Node.Element;
600 end ">";
602 -------------
603 -- Ceiling --
604 -------------
606 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
607 Node : constant Node_Access :=
608 Key_Keys.Ceiling (Container.Tree, Key);
610 begin
611 if Node = null then
612 return No_Element;
613 end if;
615 return Cursor'(Container'Unchecked_Access, Node);
616 end Ceiling;
618 ----------------------------
619 -- Checked_Update_Element --
620 ----------------------------
622 procedure Checked_Update_Element
623 (Container : in out Set;
624 Position : Cursor;
625 Process : not null access procedure (Element : in out Element_Type))
627 begin
628 if Position.Container = null then
629 raise Constraint_Error;
630 end if;
632 if Position.Container /= Set_Access'(Container'Unchecked_Access) then
633 raise Program_Error;
634 end if;
636 declare
637 Old_Key : Key_Type renames Key (Position.Node.Element);
639 begin
640 Process (Position.Node.Element);
642 if Old_Key < Position.Node.Element
643 or else Old_Key > Position.Node.Element
644 then
645 null;
646 else
647 return;
648 end if;
649 end;
651 Delete_Node_Sans_Free (Container.Tree, Position.Node);
653 Do_Insert : declare
654 Result : Node_Access;
656 function New_Node return Node_Access;
657 pragma Inline (New_Node);
659 procedure Insert_Post is
660 new Key_Keys.Generic_Insert_Post (New_Node);
662 procedure Insert is
663 new Key_Keys.Generic_Unconditional_Insert (Insert_Post);
665 --------------
666 -- New_Node --
667 --------------
669 function New_Node return Node_Access is
670 begin
671 return Position.Node;
672 end New_Node;
674 -- Start of processing for Do_Insert
676 begin
677 Insert
678 (Tree => Container.Tree,
679 Key => Key (Position.Node.Element),
680 Node => Result);
682 pragma Assert (Result = Position.Node);
683 end Do_Insert;
684 end Checked_Update_Element;
686 --------------
687 -- Contains --
688 --------------
690 function Contains (Container : Set; Key : Key_Type) return Boolean is
691 begin
692 return Find (Container, Key) /= No_Element;
693 end Contains;
695 ------------
696 -- Delete --
697 ------------
699 procedure Delete (Container : in out Set; Key : Key_Type) is
700 Tree : Tree_Type renames Container.Tree;
701 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
702 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
703 X : Node_Access;
705 begin
706 if Node = Done then
707 raise Constraint_Error;
708 end if;
710 loop
711 X := Node;
712 Node := Tree_Operations.Next (Node);
713 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
714 Free (X);
716 exit when Node = Done;
717 end loop;
718 end Delete;
720 -------------
721 -- Element --
722 -------------
724 function Element (Container : Set; Key : Key_Type) return Element_Type is
725 Node : constant Node_Access :=
726 Key_Keys.Find (Container.Tree, Key);
727 begin
728 return Node.Element;
729 end Element;
731 -------------
732 -- Exclude --
733 -------------
735 procedure Exclude (Container : in out Set; Key : Key_Type) is
736 Tree : Tree_Type renames Container.Tree;
737 Node : Node_Access := Key_Keys.Ceiling (Tree, Key);
738 Done : constant Node_Access := Key_Keys.Upper_Bound (Tree, Key);
739 X : Node_Access;
740 begin
741 while Node /= Done loop
742 X := Node;
743 Node := Tree_Operations.Next (Node);
744 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
745 Free (X);
746 end loop;
747 end Exclude;
749 ----------
750 -- Find --
751 ----------
753 function Find (Container : Set; Key : Key_Type) return Cursor is
754 Node : constant Node_Access :=
755 Key_Keys.Find (Container.Tree, Key);
757 begin
758 if Node = null then
759 return No_Element;
760 end if;
762 return Cursor'(Container'Unchecked_Access, Node);
763 end Find;
765 -----------
766 -- Floor --
767 -----------
769 function Floor (Container : Set; Key : Key_Type) return Cursor is
770 Node : constant Node_Access :=
771 Key_Keys.Floor (Container.Tree, Key);
773 begin
774 if Node = null then
775 return No_Element;
776 end if;
778 return Cursor'(Container'Unchecked_Access, Node);
779 end Floor;
781 -------------------------
782 -- Is_Greater_Key_Node --
783 -------------------------
785 function Is_Greater_Key_Node
786 (Left : Key_Type;
787 Right : Node_Access) return Boolean is
788 begin
789 return Left > Right.Element;
790 end Is_Greater_Key_Node;
792 ----------------------
793 -- Is_Less_Key_Node --
794 ----------------------
796 function Is_Less_Key_Node
797 (Left : Key_Type;
798 Right : Node_Access) return Boolean is
799 begin
800 return Left < Right.Element;
801 end Is_Less_Key_Node;
803 -------------
804 -- Iterate --
805 -------------
807 procedure Iterate
808 (Container : Set;
809 Key : Key_Type;
810 Process : not null access procedure (Position : Cursor))
812 procedure Process_Node (Node : Node_Access);
813 pragma Inline (Process_Node);
815 procedure Local_Iterate is
816 new Key_Keys.Generic_Iteration (Process_Node);
818 ------------------
819 -- Process_Node --
820 ------------------
822 procedure Process_Node (Node : Node_Access) is
823 begin
824 Process (Cursor'(Container'Unchecked_Access, Node));
825 end Process_Node;
827 -- Start of processing for Iterate
829 begin
830 Local_Iterate (Container.Tree, Key);
831 end Iterate;
833 ---------
834 -- Key --
835 ---------
837 function Key (Position : Cursor) return Key_Type is
838 begin
839 return Key (Position.Node.Element);
840 end Key;
842 -------------
843 -- Replace --
844 -------------
846 -- In post-madision api:???
848 -- procedure Replace
849 -- (Container : in out Set;
850 -- Key : Key_Type;
851 -- New_Item : Element_Type)
852 -- is
853 -- Node : Node_Access := Key_Keys.Find (Container.Tree, Key);
855 -- begin
856 -- if Node = null then
857 -- raise Constraint_Error;
858 -- end if;
860 -- Replace_Node (Container, Node, New_Item);
861 -- end Replace;
863 ---------------------
864 -- Reverse_Iterate --
865 ---------------------
867 procedure Reverse_Iterate
868 (Container : Set;
869 Key : Key_Type;
870 Process : not null access procedure (Position : Cursor))
872 procedure Process_Node (Node : Node_Access);
873 pragma Inline (Process_Node);
875 procedure Local_Reverse_Iterate is
876 new Key_Keys.Generic_Reverse_Iteration (Process_Node);
878 ------------------
879 -- Process_Node --
880 ------------------
882 procedure Process_Node (Node : Node_Access) is
883 begin
884 Process (Cursor'(Container'Unchecked_Access, Node));
885 end Process_Node;
887 -- Start of processing for Reverse_Iterate
889 begin
890 Local_Reverse_Iterate (Container.Tree, Key);
891 end Reverse_Iterate;
893 end Generic_Keys;
895 -----------------
896 -- Has_Element --
897 -----------------
899 function Has_Element (Position : Cursor) return Boolean is
900 begin
901 return Position /= No_Element;
902 end Has_Element;
904 ------------
905 -- Insert --
906 ------------
908 procedure Insert (Container : in out Set; New_Item : Element_Type) is
909 Position : Cursor;
910 begin
911 Insert (Container, New_Item, Position);
912 end Insert;
914 procedure Insert
915 (Container : in out Set;
916 New_Item : Element_Type;
917 Position : out Cursor)
919 function New_Node return Node_Access;
920 pragma Inline (New_Node);
922 procedure Insert_Post is
923 new Element_Keys.Generic_Insert_Post (New_Node);
925 procedure Unconditional_Insert_Sans_Hint is
926 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
928 --------------
929 -- New_Node --
930 --------------
932 function New_Node return Node_Access is
933 Node : constant Node_Access :=
934 new Node_Type'(Parent => null,
935 Left => null,
936 Right => null,
937 Color => Red,
938 Element => New_Item);
939 begin
940 return Node;
941 end New_Node;
943 -- Start of processing for Insert
945 begin
946 Unconditional_Insert_Sans_Hint
947 (Container.Tree,
948 New_Item,
949 Position.Node);
951 Position.Container := Container'Unchecked_Access;
952 end Insert;
954 ----------------------
955 -- Insert_With_Hint --
956 ----------------------
958 procedure Insert_With_Hint
959 (Dst_Tree : in out Tree_Type;
960 Dst_Hint : Node_Access;
961 Src_Node : Node_Access;
962 Dst_Node : out Node_Access)
964 function New_Node return Node_Access;
965 pragma Inline (New_Node);
967 procedure Insert_Post is
968 new Element_Keys.Generic_Insert_Post (New_Node);
970 procedure Insert_Sans_Hint is
971 new Element_Keys.Generic_Unconditional_Insert (Insert_Post);
973 procedure Local_Insert_With_Hint is
974 new Element_Keys.Generic_Unconditional_Insert_With_Hint
975 (Insert_Post,
976 Insert_Sans_Hint);
978 --------------
979 -- New_Node --
980 --------------
982 function New_Node return Node_Access is
983 Node : constant Node_Access :=
984 new Node_Type'(Parent => null,
985 Left => null,
986 Right => null,
987 Color => Red,
988 Element => Src_Node.Element);
989 begin
990 return Node;
991 end New_Node;
993 -- Start of processing for Insert_With_Hint
995 begin
996 Local_Insert_With_Hint
997 (Dst_Tree,
998 Dst_Hint,
999 Src_Node.Element,
1000 Dst_Node);
1001 end Insert_With_Hint;
1003 ------------------
1004 -- Intersection --
1005 ------------------
1007 procedure Intersection (Target : in out Set; Source : Set) is
1008 begin
1009 if Target'Address = Source'Address then
1010 return;
1011 end if;
1013 Set_Ops.Intersection (Target.Tree, Source.Tree);
1014 end Intersection;
1016 function Intersection (Left, Right : Set) return Set is
1017 begin
1018 if Left'Address = Right'Address then
1019 return Left;
1020 end if;
1022 declare
1023 Tree : constant Tree_Type :=
1024 Set_Ops.Intersection (Left.Tree, Right.Tree);
1025 begin
1026 return (Controlled with Tree);
1027 end;
1028 end Intersection;
1030 --------------
1031 -- Is_Empty --
1032 --------------
1034 function Is_Empty (Container : Set) return Boolean is
1035 begin
1036 return Container.Tree.Length = 0;
1037 end Is_Empty;
1039 ------------------------
1040 -- Is_Equal_Node_Node --
1041 ------------------------
1043 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1044 begin
1045 return L.Element = R.Element;
1046 end Is_Equal_Node_Node;
1048 -----------------------------
1049 -- Is_Greater_Element_Node --
1050 -----------------------------
1052 function Is_Greater_Element_Node
1053 (Left : Element_Type;
1054 Right : Node_Access) return Boolean
1056 begin
1057 -- e > node same as node < e
1059 return Right.Element < Left;
1060 end Is_Greater_Element_Node;
1062 --------------------------
1063 -- Is_Less_Element_Node --
1064 --------------------------
1066 function Is_Less_Element_Node
1067 (Left : Element_Type;
1068 Right : Node_Access) return Boolean
1070 begin
1071 return Left < Right.Element;
1072 end Is_Less_Element_Node;
1074 -----------------------
1075 -- Is_Less_Node_Node --
1076 -----------------------
1078 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1079 begin
1080 return L.Element < R.Element;
1081 end Is_Less_Node_Node;
1083 ---------------
1084 -- Is_Subset --
1085 ---------------
1087 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1088 begin
1089 if Subset'Address = Of_Set'Address then
1090 return True;
1091 end if;
1093 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1094 end Is_Subset;
1096 -------------
1097 -- Iterate --
1098 -------------
1100 procedure Iterate
1101 (Container : Set;
1102 Process : not null access procedure (Position : Cursor))
1104 procedure Process_Node (Node : Node_Access);
1105 pragma Inline (Process_Node);
1107 procedure Local_Iterate is
1108 new Tree_Operations.Generic_Iteration (Process_Node);
1110 ------------------
1111 -- Process_Node --
1112 ------------------
1114 procedure Process_Node (Node : Node_Access) is
1115 begin
1116 Process (Cursor'(Container'Unchecked_Access, Node));
1117 end Process_Node;
1119 -- Start of processing for Iterate
1121 begin
1122 Local_Iterate (Container.Tree);
1123 end Iterate;
1125 procedure Iterate
1126 (Container : Set;
1127 Item : Element_Type;
1128 Process : not null access procedure (Position : Cursor))
1130 procedure Process_Node (Node : Node_Access);
1131 pragma Inline (Process_Node);
1133 procedure Local_Iterate is
1134 new Element_Keys.Generic_Iteration (Process_Node);
1136 ------------------
1137 -- Process_Node --
1138 ------------------
1140 procedure Process_Node (Node : Node_Access) is
1141 begin
1142 Process (Cursor'(Container'Unchecked_Access, Node));
1143 end Process_Node;
1145 -- Start of processing for Iterate
1147 begin
1148 Local_Iterate (Container.Tree, Item);
1149 end Iterate;
1151 ----------
1152 -- Last --
1153 ----------
1155 function Last (Container : Set) return Cursor is
1156 begin
1157 if Container.Tree.Last = null then
1158 return No_Element;
1159 end if;
1161 return Cursor'(Container'Unchecked_Access, Container.Tree.Last);
1162 end Last;
1164 ------------------
1165 -- Last_Element --
1166 ------------------
1168 function Last_Element (Container : Set) return Element_Type is
1169 begin
1170 return Container.Tree.Last.Element;
1171 end Last_Element;
1173 ----------
1174 -- Left --
1175 ----------
1177 function Left (Node : Node_Access) return Node_Access is
1178 begin
1179 return Node.Left;
1180 end Left;
1182 ------------
1183 -- Length --
1184 ------------
1186 function Length (Container : Set) return Count_Type is
1187 begin
1188 return Container.Tree.Length;
1189 end Length;
1191 ----------
1192 -- Move --
1193 ----------
1195 procedure Move (Target : in out Set; Source : in out Set) is
1196 begin
1197 if Target'Address = Source'Address then
1198 return;
1199 end if;
1201 Move (Target => Target.Tree, Source => Source.Tree);
1202 end Move;
1204 ----------
1205 -- Next --
1206 ----------
1208 procedure Next (Position : in out Cursor)
1210 begin
1211 Position := Next (Position);
1212 end Next;
1214 function Next (Position : Cursor) return Cursor is
1215 begin
1216 if Position = No_Element then
1217 return No_Element;
1218 end if;
1220 declare
1221 Node : constant Node_Access :=
1222 Tree_Operations.Next (Position.Node);
1223 begin
1224 if Node = null then
1225 return No_Element;
1226 end if;
1228 return Cursor'(Position.Container, Node);
1229 end;
1230 end Next;
1232 -------------
1233 -- Overlap --
1234 -------------
1236 function Overlap (Left, Right : Set) return Boolean is
1237 begin
1238 if Left'Address = Right'Address then
1239 return Left.Tree.Length /= 0;
1240 end if;
1242 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1243 end Overlap;
1245 ------------
1246 -- Parent --
1247 ------------
1249 function Parent (Node : Node_Access) return Node_Access is
1250 begin
1251 return Node.Parent;
1252 end Parent;
1254 --------------
1255 -- Previous --
1256 --------------
1258 procedure Previous (Position : in out Cursor)
1260 begin
1261 Position := Previous (Position);
1262 end Previous;
1264 function Previous (Position : Cursor) return Cursor is
1265 begin
1266 if Position = No_Element then
1267 return No_Element;
1268 end if;
1270 declare
1271 Node : constant Node_Access :=
1272 Tree_Operations.Previous (Position.Node);
1273 begin
1274 if Node = null then
1275 return No_Element;
1276 end if;
1278 return Cursor'(Position.Container, Node);
1279 end;
1280 end Previous;
1282 -------------------
1283 -- Query_Element --
1284 -------------------
1286 procedure Query_Element
1287 (Position : Cursor;
1288 Process : not null access procedure (Element : Element_Type))
1290 begin
1291 Process (Position.Node.Element);
1292 end Query_Element;
1294 ----------
1295 -- Read --
1296 ----------
1298 procedure Read
1299 (Stream : access Root_Stream_Type'Class;
1300 Container : out Set)
1302 N : Count_Type'Base;
1304 function New_Node return Node_Access;
1305 pragma Inline (New_Node);
1307 procedure Local_Read is new Tree_Operations.Generic_Read (New_Node);
1309 --------------
1310 -- New_Node --
1311 --------------
1313 function New_Node return Node_Access is
1314 Node : Node_Access := new Node_Type;
1316 begin
1317 begin
1318 Element_Type'Read (Stream, Node.Element);
1320 exception
1321 when others =>
1322 Free (Node);
1323 raise;
1324 end;
1326 return Node;
1327 end New_Node;
1329 -- Start of processing for Read
1331 begin
1332 Clear (Container);
1334 Count_Type'Base'Read (Stream, N);
1335 pragma Assert (N >= 0);
1337 Local_Read (Container.Tree, N);
1338 end Read;
1340 -------------
1341 -- Replace --
1342 -------------
1344 -- NOTE: from post-madison api ???
1346 -- procedure Replace
1347 -- (Container : in out Set;
1348 -- Position : Cursor;
1349 -- By : Element_Type)
1350 -- is
1351 -- begin
1352 -- if Position.Container = null then
1353 -- raise Constraint_Error;
1354 -- end if;
1356 -- if Position.Container /= Set_Access'(Container'Unchecked_Access) then
1357 -- raise Program_Error;
1358 -- end if;
1360 -- Replace_Node (Container, Position.Node, By);
1361 -- end Replace;
1363 ------------------
1364 -- Replace_Node --
1365 ------------------
1367 -- NOTE: from post-madison api ???
1369 -- procedure Replace_Node
1370 -- (Container : in out Set;
1371 -- Position : Node_Access;
1372 -- By : Element_Type)
1373 -- is
1374 -- Tree : Tree_Type renames Container.Tree;
1375 -- Node : Node_Access := Position;
1377 -- begin
1378 -- if By < Node.Element
1379 -- or else Node.Element < By
1380 -- then
1381 -- null;
1383 -- else
1384 -- begin
1385 -- Node.Element := By;
1387 -- exception
1388 -- when others =>
1389 -- Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
1390 -- Free (Node);
1391 -- raise;
1392 -- end;
1394 -- return;
1395 -- end if;
1397 -- Tree_Operations.Delete_Node_Sans_Free (Tree, Node);
1399 -- begin
1400 -- Node.Element := By;
1402 -- exception
1403 -- when others =>
1404 -- Free (Node);
1405 -- raise;
1406 -- end;
1408 -- Do_Insert : declare
1409 -- Result : Node_Access;
1410 -- Success : Boolean;
1412 -- function New_Node return Node_Access;
1413 -- pragma Inline (New_Node);
1415 -- procedure Insert_Post is
1416 -- new Element_Keys.Generic_Insert_Post (New_Node);
1418 -- procedure Insert is
1419 -- new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1421 -- --------------
1422 -- -- New_Node --
1423 -- --------------
1425 -- function New_Node return Node_Access is
1426 -- begin
1427 -- return Node;
1428 -- end New_Node;
1430 -- -- Start of processing for Do_Insert
1432 -- begin
1433 -- Insert
1434 -- (Tree => Tree,
1435 -- Key => Node.Element,
1436 -- Node => Result,
1437 -- Success => Success);
1439 -- if not Success then
1440 -- Free (Node);
1441 -- raise Program_Error;
1442 -- end if;
1444 -- pragma Assert (Result = Node);
1445 -- end Do_Insert;
1446 -- end Replace_Node;
1448 ---------------------
1449 -- Reverse_Iterate --
1450 ---------------------
1452 procedure Reverse_Iterate
1453 (Container : Set;
1454 Process : not null access procedure (Position : Cursor))
1456 procedure Process_Node (Node : Node_Access);
1457 pragma Inline (Process_Node);
1459 procedure Local_Reverse_Iterate is
1460 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1462 ------------------
1463 -- Process_Node --
1464 ------------------
1466 procedure Process_Node (Node : Node_Access) is
1467 begin
1468 Process (Cursor'(Container'Unchecked_Access, Node));
1469 end Process_Node;
1471 -- Start of processing for Reverse_Iterate
1473 begin
1474 Local_Reverse_Iterate (Container.Tree);
1475 end Reverse_Iterate;
1477 procedure Reverse_Iterate
1478 (Container : Set;
1479 Item : Element_Type;
1480 Process : not null access procedure (Position : Cursor))
1482 procedure Process_Node (Node : Node_Access);
1483 pragma Inline (Process_Node);
1485 procedure Local_Reverse_Iterate is
1486 new Element_Keys.Generic_Reverse_Iteration (Process_Node);
1488 ------------------
1489 -- Process_Node --
1490 ------------------
1492 procedure Process_Node (Node : Node_Access) is
1493 begin
1494 Process (Cursor'(Container'Unchecked_Access, Node));
1495 end Process_Node;
1497 -- Start of processing for Reverse_Iterate
1499 begin
1500 Local_Reverse_Iterate (Container.Tree, Item);
1501 end Reverse_Iterate;
1503 -----------
1504 -- Right --
1505 -----------
1507 function Right (Node : Node_Access) return Node_Access is
1508 begin
1509 return Node.Right;
1510 end Right;
1512 ---------------
1513 -- Set_Color --
1514 ---------------
1516 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1517 begin
1518 Node.Color := Color;
1519 end Set_Color;
1521 --------------
1522 -- Set_Left --
1523 --------------
1525 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1526 begin
1527 Node.Left := Left;
1528 end Set_Left;
1530 ----------------
1531 -- Set_Parent --
1532 ----------------
1534 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1535 begin
1536 Node.Parent := Parent;
1537 end Set_Parent;
1539 ---------------
1540 -- Set_Right --
1541 ---------------
1543 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1544 begin
1545 Node.Right := Right;
1546 end Set_Right;
1548 --------------------------
1549 -- Symmetric_Difference --
1550 --------------------------
1552 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1553 begin
1554 if Target'Address = Source'Address then
1555 Clear (Target);
1556 return;
1557 end if;
1559 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1560 end Symmetric_Difference;
1562 function Symmetric_Difference (Left, Right : Set) return Set is
1563 begin
1564 if Left'Address = Right'Address then
1565 return Empty_Set;
1566 end if;
1568 declare
1569 Tree : constant Tree_Type :=
1570 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1571 begin
1572 return (Controlled with Tree);
1573 end;
1574 end Symmetric_Difference;
1576 -----------
1577 -- Union --
1578 -----------
1580 procedure Union (Target : in out Set; Source : Set) is
1581 begin
1582 if Target'Address = Source'Address then
1583 return;
1584 end if;
1586 Set_Ops.Union (Target.Tree, Source.Tree);
1587 end Union;
1589 function Union (Left, Right : Set) return Set is
1590 begin
1591 if Left'Address = Right'Address then
1592 return Left;
1593 end if;
1595 declare
1596 Tree : constant Tree_Type :=
1597 Set_Ops.Union (Left.Tree, Right.Tree);
1598 begin
1599 return (Controlled with Tree);
1600 end;
1601 end Union;
1603 -----------
1604 -- Write --
1605 -----------
1607 procedure Write
1608 (Stream : access Root_Stream_Type'Class;
1609 Container : Set)
1611 procedure Process (Node : Node_Access);
1612 pragma Inline (Process);
1614 procedure Iterate is
1615 new Tree_Operations.Generic_Iteration (Process);
1617 -------------
1618 -- Process --
1619 -------------
1621 procedure Process (Node : Node_Access) is
1622 begin
1623 Element_Type'Write (Stream, Node.Element);
1624 end Process;
1626 -- Start of processing for Write
1628 begin
1629 Count_Type'Base'Write (Stream, Container.Tree.Length);
1630 Iterate (Container.Tree);
1631 end Write;
1633 end Ada.Containers.Ordered_Multisets;