1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_SET_OPERATIONS --
9 -- Copyright (C) 2004-2013, Free Software Foundation, Inc. --
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. --
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. --
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/>. --
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
;
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
);
66 function Copy
(Source
: Tree_Type
) return Tree_Type
is
70 if Source
.Length
= 0 then
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
;
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
;
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)";
109 if Source
.Length
= 0 then
113 if Target
.Busy
> 0 then
114 raise Program_Error
with
115 "attempt to tamper with cursors (container is busy)";
129 -- Per AI05-0022, the container implementation is required to detect
130 -- element tampering by a generic actual subprogram.
139 if Is_Less
(Tgt
, Src
) then
141 elsif Is_Less
(Src
, Tgt
) then
165 Tgt
:= Tree_Operations
.Next
(Tgt
);
167 elsif Compare
> 0 then
168 Src
:= Tree_Operations
.Next
(Src
);
172 X
: Node_Access
:= Tgt
;
174 Tgt
:= Tree_Operations
.Next
(Tgt
);
175 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
179 Src
:= Tree_Operations
.Next
(Src
);
184 function Difference
(Left
, Right
: Tree_Type
) return Tree_Type
is
186 if Left
'Address = Right
'Address then
187 return Tree_Type
'(others => <>); -- Empty set
190 if Left.Length = 0 then
191 return Tree_Type'(others => <>); -- Empty set
194 if Right
.Length
= 0 then
198 -- Per AI05-0022, the container implementation is required to detect
199 -- element tampering by a generic actual subprogram.
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
;
210 L_Node
: Node_Access
;
211 R_Node
: Node_Access
;
213 Dst_Node
: Node_Access
;
214 pragma Warnings
(Off
, Dst_Node
);
223 L_Node
:= Left
.First
;
224 R_Node
:= Right
.First
;
226 if L_Node
= null then
230 if R_Node
= null then
231 while L_Node
/= null loop
236 Dst_Node
=> Dst_Node
);
238 L_Node
:= Tree_Operations
.Next
(L_Node
);
244 if Is_Less
(L_Node
, R_Node
) then
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
);
257 L_Node
:= Tree_Operations
.Next
(L_Node
);
258 R_Node
:= Tree_Operations
.Next
(R_Node
);
278 Delete_Tree
(Tree
.Root
);
287 procedure Intersection
288 (Target
: in out 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
;
303 if Target
'Address = Source
'Address then
307 if Target
.Busy
> 0 then
308 raise Program_Error
with
309 "attempt to tamper with cursors (container is busy)";
312 if Source
.Length
= 0 then
322 -- Per AI05-0022, the container implementation is required to detect
323 -- element tampering by a generic actual subprogram.
332 if Is_Less
(Tgt
, Src
) then
334 elsif Is_Less
(Src
, Tgt
) then
359 X
: Node_Access
:= Tgt
;
361 Tgt
:= Tree_Operations
.Next
(Tgt
);
362 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
366 elsif Compare
> 0 then
367 Src
:= Tree_Operations
.Next
(Src
);
370 Tgt
:= Tree_Operations
.Next
(Tgt
);
371 Src
:= Tree_Operations
.Next
(Src
);
375 while Tgt
/= null loop
377 X
: Node_Access
:= Tgt
;
379 Tgt
:= Tree_Operations
.Next
(Tgt
);
380 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
386 function Intersection
(Left
, Right
: Tree_Type
) return Tree_Type
is
388 if Left
'Address = Right
'Address then
392 -- Per AI05-0022, the container implementation is required to detect
393 -- element tampering by a generic actual subprogram.
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
;
404 L_Node
: Node_Access
;
405 R_Node
: Node_Access
;
407 Dst_Node
: Node_Access
;
408 pragma Warnings
(Off
, Dst_Node
);
417 L_Node
:= Left
.First
;
418 R_Node
:= Right
.First
;
420 if L_Node
= null then
424 if R_Node
= null then
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
);
439 Dst_Node
=> Dst_Node
);
441 L_Node
:= Tree_Operations
.Next
(L_Node
);
442 R_Node
:= Tree_Operations
.Next
(R_Node
);
462 Delete_Tree
(Tree
.Root
);
473 Of_Set
: Tree_Type
) return Boolean
476 if Subset
'Address = Of_Set
'Address then
480 if Subset
.Length
> Of_Set
.Length
then
484 -- Per AI05-0022, the container implementation is required to detect
485 -- element tampering by a generic actual subprogram.
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
;
506 Subset_Node
:= Subset
.First
;
507 Set_Node
:= Of_Set
.First
;
509 if Set_Node
= null then
510 Result
:= Subset_Node
= null;
514 if Subset_Node
= null then
519 if Is_Less
(Subset_Node
, Set_Node
) then
524 if Is_Less
(Set_Node
, Subset_Node
) then
525 Set_Node
:= Tree_Operations
.Next
(Set_Node
);
527 Set_Node
:= Tree_Operations
.Next
(Set_Node
);
528 Subset_Node
:= Tree_Operations
.Next
(Subset_Node
);
556 function Overlap
(Left
, Right
: Tree_Type
) return Boolean is
558 if Left
'Address = Right
'Address then
559 return Left
.Length
/= 0;
562 -- Per AI05-0022, the container implementation is required to detect
563 -- element tampering by a generic actual subprogram.
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
;
584 L_Node
:= Left
.First
;
585 R_Node
:= Right
.First
;
588 or else R_Node
= null
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
);
626 --------------------------
627 -- Symmetric_Difference --
628 --------------------------
630 procedure Symmetric_Difference
631 (Target
: in out 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
;
643 New_Tgt_Node
: Node_Access
;
644 pragma Warnings
(Off
, New_Tgt_Node
);
649 if Target
'Address = Source
'Address then
658 while Src
/= null loop
663 Dst_Node
=> New_Tgt_Node
);
665 Src
:= Tree_Operations
.Next
(Src
);
675 -- Per AI05-0022, the container implementation is required to detect
676 -- element tampering by a generic actual subprogram.
685 if Is_Less
(Tgt
, Src
) then
687 elsif Is_Less
(Src
, Tgt
) then
711 Tgt
:= Tree_Operations
.Next
(Tgt
);
713 elsif Compare
> 0 then
718 Dst_Node
=> New_Tgt_Node
);
720 Src
:= Tree_Operations
.Next
(Src
);
724 X
: Node_Access
:= Tgt
;
726 Tgt
:= Tree_Operations
.Next
(Tgt
);
727 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
731 Src
:= Tree_Operations
.Next
(Src
);
734 end Symmetric_Difference
;
736 function Symmetric_Difference
(Left
, Right
: Tree_Type
) return Tree_Type
is
738 if Left
'Address = Right
'Address then
739 return Tree_Type
'(others => <>); -- Empty set
742 if Right.Length = 0 then
746 if Left.Length = 0 then
750 -- Per AI05-0022, the container implementation is required to detect
751 -- element tampering by a generic actual subprogram.
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;
762 L_Node : Node_Access;
763 R_Node : Node_Access;
765 Dst_Node : Node_Access;
766 pragma Warnings (Off, Dst_Node);
775 L_Node := Left.First;
776 R_Node := Right.First;
778 if L_Node = null then
779 while R_Node /= null loop
784 Dst_Node => Dst_Node);
785 R_Node := Tree_Operations.Next (R_Node);
791 if R_Node = null then
792 while L_Node /= null loop
797 Dst_Node => Dst_Node);
799 L_Node := Tree_Operations.Next (L_Node);
805 if Is_Less (L_Node, R_Node) then
810 Dst_Node => Dst_Node);
812 L_Node := Tree_Operations.Next (L_Node);
814 elsif Is_Less (R_Node, L_Node) then
819 Dst_Node => Dst_Node);
821 R_Node := Tree_Operations.Next (R_Node);
824 L_Node := Tree_Operations.Next (L_Node);
825 R_Node := Tree_Operations.Next (R_Node);
845 Delete_Tree (Tree.Root);
848 end Symmetric_Difference;
854 procedure Union (Target : in out Tree_Type; Source : Tree_Type) is
857 procedure Process (Node : Node_Access);
858 pragma Inline (Process);
860 procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
866 procedure Process (Node : Node_Access) is
870 Dst_Hint => Hint, -- use node most recently inserted as hint
875 -- Start of processing for Union
878 if Target'Address = Source'Address then
882 -- Per AI05-0022, the container implementation is required to detect
883 -- element tampering by a generic actual subprogram.
886 BS : Natural renames Source'Unrestricted_Access.Busy;
887 LS : Natural renames Source'Unrestricted_Access.Lock;
907 function Union (Left, Right : Tree_Type) return Tree_Type is
909 if Left'Address = Right'Address then
913 if Left.Length = 0 then
917 if Right.Length = 0 then
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);
932 procedure Process (Node : Node_Access);
933 pragma Inline (Process);
936 new Tree_Operations.Generic_Iteration (Process);
942 procedure Process (Node : Node_Access) is
946 Dst_Hint => Hint, -- use node most recently inserted as hint
951 -- Start of processing for Union
978 Delete_Tree (Tree.Root);
983 end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;