2014-10-10 Robert Dewar <dewar@adacore.com>
[official-gcc.git] / gcc / ada / a-rbtgso.adb
blob06a78e922c32aed58582e473f7c322c34f9473ef
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_SET_OPERATIONS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004-2013, 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 System; use type System.Address;
32 package body Ada.Containers.Red_Black_Trees.Generic_Set_Operations is
34 -----------------------
35 -- Local Subprograms --
36 -----------------------
38 procedure Clear (Tree : in out Tree_Type);
40 function Copy (Source : Tree_Type) return Tree_Type;
42 -----------
43 -- Clear --
44 -----------
46 procedure Clear (Tree : in out Tree_Type) is
47 pragma Assert (Tree.Busy = 0);
48 pragma Assert (Tree.Lock = 0);
50 Root : Node_Access := Tree.Root;
51 pragma Warnings (Off, Root);
53 begin
54 Tree.Root := null;
55 Tree.First := null;
56 Tree.Last := null;
57 Tree.Length := 0;
59 Delete_Tree (Root);
60 end Clear;
62 ----------
63 -- Copy --
64 ----------
66 function Copy (Source : Tree_Type) return Tree_Type is
67 Target : Tree_Type;
69 begin
70 if Source.Length = 0 then
71 return Target;
72 end if;
74 Target.Root := Copy_Tree (Source.Root);
75 Target.First := Tree_Operations.Min (Target.Root);
76 Target.Last := Tree_Operations.Max (Target.Root);
77 Target.Length := Source.Length;
79 return Target;
80 end Copy;
82 ----------------
83 -- Difference --
84 ----------------
86 procedure Difference (Target : in out Tree_Type; Source : Tree_Type) is
87 BT : Natural renames Target.Busy;
88 LT : Natural renames Target.Lock;
90 BS : Natural renames Source'Unrestricted_Access.Busy;
91 LS : Natural renames Source'Unrestricted_Access.Lock;
93 Tgt : Node_Access;
94 Src : Node_Access;
96 Compare : Integer;
98 begin
99 if Target'Address = Source'Address then
100 if Target.Busy > 0 then
101 raise Program_Error with
102 "attempt to tamper with cursors (container is busy)";
103 end if;
105 Clear (Target);
106 return;
107 end if;
109 if Source.Length = 0 then
110 return;
111 end if;
113 if Target.Busy > 0 then
114 raise Program_Error with
115 "attempt to tamper with cursors (container is busy)";
116 end if;
118 Tgt := Target.First;
119 Src := Source.First;
120 loop
121 if Tgt = null then
122 exit;
123 end if;
125 if Src = null then
126 exit;
127 end if;
129 -- Per AI05-0022, the container implementation is required to detect
130 -- element tampering by a generic actual subprogram.
132 begin
133 BT := BT + 1;
134 LT := LT + 1;
136 BS := BS + 1;
137 LS := LS + 1;
139 if Is_Less (Tgt, Src) then
140 Compare := -1;
141 elsif Is_Less (Src, Tgt) then
142 Compare := 1;
143 else
144 Compare := 0;
145 end if;
147 BT := BT - 1;
148 LT := LT - 1;
150 BS := BS - 1;
151 LS := LS - 1;
153 exception
154 when others =>
155 BT := BT - 1;
156 LT := LT - 1;
158 BS := BS - 1;
159 LS := LS - 1;
161 raise;
162 end;
164 if Compare < 0 then
165 Tgt := Tree_Operations.Next (Tgt);
167 elsif Compare > 0 then
168 Src := Tree_Operations.Next (Src);
170 else
171 declare
172 X : Node_Access := Tgt;
173 begin
174 Tgt := Tree_Operations.Next (Tgt);
175 Tree_Operations.Delete_Node_Sans_Free (Target, X);
176 Free (X);
177 end;
179 Src := Tree_Operations.Next (Src);
180 end if;
181 end loop;
182 end Difference;
184 function Difference (Left, Right : Tree_Type) return Tree_Type is
185 begin
186 if Left'Address = Right'Address then
187 return Tree_Type'(others => <>); -- Empty set
188 end if;
190 if Left.Length = 0 then
191 return Tree_Type'(others => <>); -- Empty set
192 end if;
194 if Right.Length = 0 then
195 return Copy (Left);
196 end if;
198 -- Per AI05-0022, the container implementation is required to detect
199 -- element tampering by a generic actual subprogram.
201 declare
202 BL : Natural renames Left'Unrestricted_Access.Busy;
203 LL : Natural renames Left'Unrestricted_Access.Lock;
205 BR : Natural renames Right'Unrestricted_Access.Busy;
206 LR : Natural renames Right'Unrestricted_Access.Lock;
208 Tree : Tree_Type;
210 L_Node : Node_Access;
211 R_Node : Node_Access;
213 Dst_Node : Node_Access;
214 pragma Warnings (Off, Dst_Node);
216 begin
217 BL := BL + 1;
218 LL := LL + 1;
220 BR := BR + 1;
221 LR := LR + 1;
223 L_Node := Left.First;
224 R_Node := Right.First;
225 loop
226 if L_Node = null then
227 exit;
228 end if;
230 if R_Node = null then
231 while L_Node /= null loop
232 Insert_With_Hint
233 (Dst_Tree => Tree,
234 Dst_Hint => null,
235 Src_Node => L_Node,
236 Dst_Node => Dst_Node);
238 L_Node := Tree_Operations.Next (L_Node);
239 end loop;
241 exit;
242 end if;
244 if Is_Less (L_Node, R_Node) then
245 Insert_With_Hint
246 (Dst_Tree => Tree,
247 Dst_Hint => null,
248 Src_Node => L_Node,
249 Dst_Node => Dst_Node);
251 L_Node := Tree_Operations.Next (L_Node);
253 elsif Is_Less (R_Node, L_Node) then
254 R_Node := Tree_Operations.Next (R_Node);
256 else
257 L_Node := Tree_Operations.Next (L_Node);
258 R_Node := Tree_Operations.Next (R_Node);
259 end if;
260 end loop;
262 BL := BL - 1;
263 LL := LL - 1;
265 BR := BR - 1;
266 LR := LR - 1;
268 return Tree;
270 exception
271 when others =>
272 BL := BL - 1;
273 LL := LL - 1;
275 BR := BR - 1;
276 LR := LR - 1;
278 Delete_Tree (Tree.Root);
279 raise;
280 end;
281 end Difference;
283 ------------------
284 -- Intersection --
285 ------------------
287 procedure Intersection
288 (Target : in out Tree_Type;
289 Source : Tree_Type)
291 BT : Natural renames Target.Busy;
292 LT : Natural renames Target.Lock;
294 BS : Natural renames Source'Unrestricted_Access.Busy;
295 LS : Natural renames Source'Unrestricted_Access.Lock;
297 Tgt : Node_Access;
298 Src : Node_Access;
300 Compare : Integer;
302 begin
303 if Target'Address = Source'Address then
304 return;
305 end if;
307 if Target.Busy > 0 then
308 raise Program_Error with
309 "attempt to tamper with cursors (container is busy)";
310 end if;
312 if Source.Length = 0 then
313 Clear (Target);
314 return;
315 end if;
317 Tgt := Target.First;
318 Src := Source.First;
319 while Tgt /= null
320 and then Src /= null
321 loop
322 -- Per AI05-0022, the container implementation is required to detect
323 -- element tampering by a generic actual subprogram.
325 begin
326 BT := BT + 1;
327 LT := LT + 1;
329 BS := BS + 1;
330 LS := LS + 1;
332 if Is_Less (Tgt, Src) then
333 Compare := -1;
334 elsif Is_Less (Src, Tgt) then
335 Compare := 1;
336 else
337 Compare := 0;
338 end if;
340 BT := BT - 1;
341 LT := LT - 1;
343 BS := BS - 1;
344 LS := LS - 1;
346 exception
347 when others =>
348 BT := BT - 1;
349 LT := LT - 1;
351 BS := BS - 1;
352 LS := LS - 1;
354 raise;
355 end;
357 if Compare < 0 then
358 declare
359 X : Node_Access := Tgt;
360 begin
361 Tgt := Tree_Operations.Next (Tgt);
362 Tree_Operations.Delete_Node_Sans_Free (Target, X);
363 Free (X);
364 end;
366 elsif Compare > 0 then
367 Src := Tree_Operations.Next (Src);
369 else
370 Tgt := Tree_Operations.Next (Tgt);
371 Src := Tree_Operations.Next (Src);
372 end if;
373 end loop;
375 while Tgt /= null loop
376 declare
377 X : Node_Access := Tgt;
378 begin
379 Tgt := Tree_Operations.Next (Tgt);
380 Tree_Operations.Delete_Node_Sans_Free (Target, X);
381 Free (X);
382 end;
383 end loop;
384 end Intersection;
386 function Intersection (Left, Right : Tree_Type) return Tree_Type is
387 begin
388 if Left'Address = Right'Address then
389 return Copy (Left);
390 end if;
392 -- Per AI05-0022, the container implementation is required to detect
393 -- element tampering by a generic actual subprogram.
395 declare
396 BL : Natural renames Left'Unrestricted_Access.Busy;
397 LL : Natural renames Left'Unrestricted_Access.Lock;
399 BR : Natural renames Right'Unrestricted_Access.Busy;
400 LR : Natural renames Right'Unrestricted_Access.Lock;
402 Tree : Tree_Type;
404 L_Node : Node_Access;
405 R_Node : Node_Access;
407 Dst_Node : Node_Access;
408 pragma Warnings (Off, Dst_Node);
410 begin
411 BL := BL + 1;
412 LL := LL + 1;
414 BR := BR + 1;
415 LR := LR + 1;
417 L_Node := Left.First;
418 R_Node := Right.First;
419 loop
420 if L_Node = null then
421 exit;
422 end if;
424 if R_Node = null then
425 exit;
426 end if;
428 if Is_Less (L_Node, R_Node) then
429 L_Node := Tree_Operations.Next (L_Node);
431 elsif Is_Less (R_Node, L_Node) then
432 R_Node := Tree_Operations.Next (R_Node);
434 else
435 Insert_With_Hint
436 (Dst_Tree => Tree,
437 Dst_Hint => null,
438 Src_Node => L_Node,
439 Dst_Node => Dst_Node);
441 L_Node := Tree_Operations.Next (L_Node);
442 R_Node := Tree_Operations.Next (R_Node);
443 end if;
444 end loop;
446 BL := BL - 1;
447 LL := LL - 1;
449 BR := BR - 1;
450 LR := LR - 1;
452 return Tree;
454 exception
455 when others =>
456 BL := BL - 1;
457 LL := LL - 1;
459 BR := BR - 1;
460 LR := LR - 1;
462 Delete_Tree (Tree.Root);
463 raise;
464 end;
465 end Intersection;
467 ---------------
468 -- Is_Subset --
469 ---------------
471 function Is_Subset
472 (Subset : Tree_Type;
473 Of_Set : Tree_Type) return Boolean
475 begin
476 if Subset'Address = Of_Set'Address then
477 return True;
478 end if;
480 if Subset.Length > Of_Set.Length then
481 return False;
482 end if;
484 -- Per AI05-0022, the container implementation is required to detect
485 -- element tampering by a generic actual subprogram.
487 declare
488 BL : Natural renames Subset'Unrestricted_Access.Busy;
489 LL : Natural renames Subset'Unrestricted_Access.Lock;
491 BR : Natural renames Of_Set'Unrestricted_Access.Busy;
492 LR : Natural renames Of_Set'Unrestricted_Access.Lock;
494 Subset_Node : Node_Access;
495 Set_Node : Node_Access;
497 Result : Boolean;
499 begin
500 BL := BL + 1;
501 LL := LL + 1;
503 BR := BR + 1;
504 LR := LR + 1;
506 Subset_Node := Subset.First;
507 Set_Node := Of_Set.First;
508 loop
509 if Set_Node = null then
510 Result := Subset_Node = null;
511 exit;
512 end if;
514 if Subset_Node = null then
515 Result := True;
516 exit;
517 end if;
519 if Is_Less (Subset_Node, Set_Node) then
520 Result := False;
521 exit;
522 end if;
524 if Is_Less (Set_Node, Subset_Node) then
525 Set_Node := Tree_Operations.Next (Set_Node);
526 else
527 Set_Node := Tree_Operations.Next (Set_Node);
528 Subset_Node := Tree_Operations.Next (Subset_Node);
529 end if;
530 end loop;
532 BL := BL - 1;
533 LL := LL - 1;
535 BR := BR - 1;
536 LR := LR - 1;
538 return Result;
540 exception
541 when others =>
542 BL := BL - 1;
543 LL := LL - 1;
545 BR := BR - 1;
546 LR := LR - 1;
548 raise;
549 end;
550 end Is_Subset;
552 -------------
553 -- Overlap --
554 -------------
556 function Overlap (Left, Right : Tree_Type) return Boolean is
557 begin
558 if Left'Address = Right'Address then
559 return Left.Length /= 0;
560 end if;
562 -- Per AI05-0022, the container implementation is required to detect
563 -- element tampering by a generic actual subprogram.
565 declare
566 BL : Natural renames Left'Unrestricted_Access.Busy;
567 LL : Natural renames Left'Unrestricted_Access.Lock;
569 BR : Natural renames Right'Unrestricted_Access.Busy;
570 LR : Natural renames Right'Unrestricted_Access.Lock;
572 L_Node : Node_Access;
573 R_Node : Node_Access;
575 Result : Boolean;
577 begin
578 BL := BL + 1;
579 LL := LL + 1;
581 BR := BR + 1;
582 LR := LR + 1;
584 L_Node := Left.First;
585 R_Node := Right.First;
586 loop
587 if L_Node = null
588 or else R_Node = null
589 then
590 Result := False;
591 exit;
592 end if;
594 if Is_Less (L_Node, R_Node) then
595 L_Node := Tree_Operations.Next (L_Node);
597 elsif Is_Less (R_Node, L_Node) then
598 R_Node := Tree_Operations.Next (R_Node);
600 else
601 Result := True;
602 exit;
603 end if;
604 end loop;
606 BL := BL - 1;
607 LL := LL - 1;
609 BR := BR - 1;
610 LR := LR - 1;
612 return Result;
614 exception
615 when others =>
616 BL := BL - 1;
617 LL := LL - 1;
619 BR := BR - 1;
620 LR := LR - 1;
622 raise;
623 end;
624 end Overlap;
626 --------------------------
627 -- Symmetric_Difference --
628 --------------------------
630 procedure Symmetric_Difference
631 (Target : in out Tree_Type;
632 Source : Tree_Type)
634 BT : Natural renames Target.Busy;
635 LT : Natural renames Target.Lock;
637 BS : Natural renames Source'Unrestricted_Access.Busy;
638 LS : Natural renames Source'Unrestricted_Access.Lock;
640 Tgt : Node_Access;
641 Src : Node_Access;
643 New_Tgt_Node : Node_Access;
644 pragma Warnings (Off, New_Tgt_Node);
646 Compare : Integer;
648 begin
649 if Target'Address = Source'Address then
650 Clear (Target);
651 return;
652 end if;
654 Tgt := Target.First;
655 Src := Source.First;
656 loop
657 if Tgt = null then
658 while Src /= null loop
659 Insert_With_Hint
660 (Dst_Tree => Target,
661 Dst_Hint => null,
662 Src_Node => Src,
663 Dst_Node => New_Tgt_Node);
665 Src := Tree_Operations.Next (Src);
666 end loop;
668 return;
669 end if;
671 if Src = null then
672 return;
673 end if;
675 -- Per AI05-0022, the container implementation is required to detect
676 -- element tampering by a generic actual subprogram.
678 begin
679 BT := BT + 1;
680 LT := LT + 1;
682 BS := BS + 1;
683 LS := LS + 1;
685 if Is_Less (Tgt, Src) then
686 Compare := -1;
687 elsif Is_Less (Src, Tgt) then
688 Compare := 1;
689 else
690 Compare := 0;
691 end if;
693 BT := BT - 1;
694 LT := LT - 1;
696 BS := BS - 1;
697 LS := LS - 1;
699 exception
700 when others =>
701 BT := BT - 1;
702 LT := LT - 1;
704 BS := BS - 1;
705 LS := LS - 1;
707 raise;
708 end;
710 if Compare < 0 then
711 Tgt := Tree_Operations.Next (Tgt);
713 elsif Compare > 0 then
714 Insert_With_Hint
715 (Dst_Tree => Target,
716 Dst_Hint => Tgt,
717 Src_Node => Src,
718 Dst_Node => New_Tgt_Node);
720 Src := Tree_Operations.Next (Src);
722 else
723 declare
724 X : Node_Access := Tgt;
725 begin
726 Tgt := Tree_Operations.Next (Tgt);
727 Tree_Operations.Delete_Node_Sans_Free (Target, X);
728 Free (X);
729 end;
731 Src := Tree_Operations.Next (Src);
732 end if;
733 end loop;
734 end Symmetric_Difference;
736 function Symmetric_Difference (Left, Right : Tree_Type) return Tree_Type is
737 begin
738 if Left'Address = Right'Address then
739 return Tree_Type'(others => <>); -- Empty set
740 end if;
742 if Right.Length = 0 then
743 return Copy (Left);
744 end if;
746 if Left.Length = 0 then
747 return Copy (Right);
748 end if;
750 -- Per AI05-0022, the container implementation is required to detect
751 -- element tampering by a generic actual subprogram.
753 declare
754 BL : Natural renames Left'Unrestricted_Access.Busy;
755 LL : Natural renames Left'Unrestricted_Access.Lock;
757 BR : Natural renames Right'Unrestricted_Access.Busy;
758 LR : Natural renames Right'Unrestricted_Access.Lock;
760 Tree : Tree_Type;
762 L_Node : Node_Access;
763 R_Node : Node_Access;
765 Dst_Node : Node_Access;
766 pragma Warnings (Off, Dst_Node);
768 begin
769 BL := BL + 1;
770 LL := LL + 1;
772 BR := BR + 1;
773 LR := LR + 1;
775 L_Node := Left.First;
776 R_Node := Right.First;
777 loop
778 if L_Node = null then
779 while R_Node /= null loop
780 Insert_With_Hint
781 (Dst_Tree => Tree,
782 Dst_Hint => null,
783 Src_Node => R_Node,
784 Dst_Node => Dst_Node);
785 R_Node := Tree_Operations.Next (R_Node);
786 end loop;
788 exit;
789 end if;
791 if R_Node = null then
792 while L_Node /= null loop
793 Insert_With_Hint
794 (Dst_Tree => Tree,
795 Dst_Hint => null,
796 Src_Node => L_Node,
797 Dst_Node => Dst_Node);
799 L_Node := Tree_Operations.Next (L_Node);
800 end loop;
802 exit;
803 end if;
805 if Is_Less (L_Node, R_Node) then
806 Insert_With_Hint
807 (Dst_Tree => Tree,
808 Dst_Hint => null,
809 Src_Node => L_Node,
810 Dst_Node => Dst_Node);
812 L_Node := Tree_Operations.Next (L_Node);
814 elsif Is_Less (R_Node, L_Node) then
815 Insert_With_Hint
816 (Dst_Tree => Tree,
817 Dst_Hint => null,
818 Src_Node => R_Node,
819 Dst_Node => Dst_Node);
821 R_Node := Tree_Operations.Next (R_Node);
823 else
824 L_Node := Tree_Operations.Next (L_Node);
825 R_Node := Tree_Operations.Next (R_Node);
826 end if;
827 end loop;
829 BL := BL - 1;
830 LL := LL - 1;
832 BR := BR - 1;
833 LR := LR - 1;
835 return Tree;
837 exception
838 when others =>
839 BL := BL - 1;
840 LL := LL - 1;
842 BR := BR - 1;
843 LR := LR - 1;
845 Delete_Tree (Tree.Root);
846 raise;
847 end;
848 end Symmetric_Difference;
850 -----------
851 -- Union --
852 -----------
854 procedure Union (Target : in out Tree_Type; Source : Tree_Type) is
855 Hint : Node_Access;
857 procedure Process (Node : Node_Access);
858 pragma Inline (Process);
860 procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
862 -------------
863 -- Process --
864 -------------
866 procedure Process (Node : Node_Access) is
867 begin
868 Insert_With_Hint
869 (Dst_Tree => Target,
870 Dst_Hint => Hint, -- use node most recently inserted as hint
871 Src_Node => Node,
872 Dst_Node => Hint);
873 end Process;
875 -- Start of processing for Union
877 begin
878 if Target'Address = Source'Address then
879 return;
880 end if;
882 -- Per AI05-0022, the container implementation is required to detect
883 -- element tampering by a generic actual subprogram.
885 declare
886 BS : Natural renames Source'Unrestricted_Access.Busy;
887 LS : Natural renames Source'Unrestricted_Access.Lock;
889 begin
890 BS := BS + 1;
891 LS := LS + 1;
893 Iterate (Source);
895 BS := BS - 1;
896 LS := LS - 1;
898 exception
899 when others =>
900 BS := BS - 1;
901 LS := LS - 1;
903 raise;
904 end;
905 end Union;
907 function Union (Left, Right : Tree_Type) return Tree_Type is
908 begin
909 if Left'Address = Right'Address then
910 return Copy (Left);
911 end if;
913 if Left.Length = 0 then
914 return Copy (Right);
915 end if;
917 if Right.Length = 0 then
918 return Copy (Left);
919 end if;
921 declare
922 BL : Natural renames Left'Unrestricted_Access.Busy;
923 LL : Natural renames Left'Unrestricted_Access.Lock;
925 BR : Natural renames Right'Unrestricted_Access.Busy;
926 LR : Natural renames Right'Unrestricted_Access.Lock;
928 Tree : Tree_Type := Copy (Left);
930 Hint : Node_Access;
932 procedure Process (Node : Node_Access);
933 pragma Inline (Process);
935 procedure Iterate is
936 new Tree_Operations.Generic_Iteration (Process);
938 -------------
939 -- Process --
940 -------------
942 procedure Process (Node : Node_Access) is
943 begin
944 Insert_With_Hint
945 (Dst_Tree => Tree,
946 Dst_Hint => Hint, -- use node most recently inserted as hint
947 Src_Node => Node,
948 Dst_Node => Hint);
949 end Process;
951 -- Start of processing for Union
953 begin
954 BL := BL + 1;
955 LL := LL + 1;
957 BR := BR + 1;
958 LR := LR + 1;
960 Iterate (Right);
962 BL := BL - 1;
963 LL := LL - 1;
965 BR := BR - 1;
966 LR := LR - 1;
968 return Tree;
970 exception
971 when others =>
972 BL := BL - 1;
973 LL := LL - 1;
975 BR := BR - 1;
976 LR := LR - 1;
978 Delete_Tree (Tree.Root);
979 raise;
980 end;
981 end Union;
983 end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;