1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_SET_OPERATIONS --
9 -- Copyright (C) 2004-2015, 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 pragma Warnings
(Off
, "variable ""Busy*"" is not referenced");
35 pragma Warnings
(Off
, "variable ""Lock*"" is not referenced");
36 -- See comment in Ada.Containers.Helpers
38 -----------------------
39 -- Local Subprograms --
40 -----------------------
42 procedure Clear
(Tree
: in out Tree_Type
);
44 function Copy
(Source
: Tree_Type
) return Tree_Type
;
50 procedure Clear
(Tree
: in out Tree_Type
) is
51 use type Helpers
.Tamper_Counts
;
52 pragma Assert
(Tree
.TC
= (Busy
=> 0, Lock
=> 0));
54 Root
: Node_Access
:= Tree
.Root
;
55 pragma Warnings
(Off
, Root
);
70 function Copy
(Source
: Tree_Type
) return Tree_Type
is
74 if Source
.Length
= 0 then
78 Target
.Root
:= Copy_Tree
(Source
.Root
);
79 Target
.First
:= Tree_Operations
.Min
(Target
.Root
);
80 Target
.Last
:= Tree_Operations
.Max
(Target
.Root
);
81 Target
.Length
:= Source
.Length
;
90 procedure Difference
(Target
: in out Tree_Type
; Source
: Tree_Type
) is
97 if Target
'Address = Source
'Address then
104 if Source
.Length
= 0 then
108 TC_Check
(Target
.TC
);
121 -- Per AI05-0022, the container implementation is required to detect
122 -- element tampering by a generic actual subprogram.
125 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
126 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
128 if Is_Less
(Tgt
, Src
) then
130 elsif Is_Less
(Src
, Tgt
) then
138 Tgt
:= Tree_Operations
.Next
(Tgt
);
140 elsif Compare
> 0 then
141 Src
:= Tree_Operations
.Next
(Src
);
145 X
: Node_Access
:= Tgt
;
147 Tgt
:= Tree_Operations
.Next
(Tgt
);
148 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
152 Src
:= Tree_Operations
.Next
(Src
);
157 function Difference
(Left
, Right
: Tree_Type
) return Tree_Type
is
159 if Left
'Address = Right
'Address then
160 return Tree_Type
'(others => <>); -- Empty set
163 if Left.Length = 0 then
164 return Tree_Type'(others => <>); -- Empty set
167 if Right
.Length
= 0 then
171 -- Per AI05-0022, the container implementation is required to detect
172 -- element tampering by a generic actual subprogram.
175 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
176 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
180 L_Node
: Node_Access
;
181 R_Node
: Node_Access
;
183 Dst_Node
: Node_Access
;
184 pragma Warnings
(Off
, Dst_Node
);
187 L_Node
:= Left
.First
;
188 R_Node
:= Right
.First
;
190 if L_Node
= null then
194 if R_Node
= null then
195 while L_Node
/= null loop
200 Dst_Node
=> Dst_Node
);
202 L_Node
:= Tree_Operations
.Next
(L_Node
);
208 if Is_Less
(L_Node
, R_Node
) then
213 Dst_Node
=> Dst_Node
);
215 L_Node
:= Tree_Operations
.Next
(L_Node
);
217 elsif Is_Less
(R_Node
, L_Node
) then
218 R_Node
:= Tree_Operations
.Next
(R_Node
);
221 L_Node
:= Tree_Operations
.Next
(L_Node
);
222 R_Node
:= Tree_Operations
.Next
(R_Node
);
230 Delete_Tree
(Tree
.Root
);
239 procedure Intersection
240 (Target
: in out Tree_Type
;
249 if Target
'Address = Source
'Address then
253 TC_Check
(Target
.TC
);
255 if Source
.Length
= 0 then
265 -- Per AI05-0022, the container implementation is required to detect
266 -- element tampering by a generic actual subprogram.
269 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
270 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
272 if Is_Less
(Tgt
, Src
) then
274 elsif Is_Less
(Src
, Tgt
) then
283 X
: Node_Access
:= Tgt
;
285 Tgt
:= Tree_Operations
.Next
(Tgt
);
286 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
290 elsif Compare
> 0 then
291 Src
:= Tree_Operations
.Next
(Src
);
294 Tgt
:= Tree_Operations
.Next
(Tgt
);
295 Src
:= Tree_Operations
.Next
(Src
);
299 while Tgt
/= null loop
301 X
: Node_Access
:= Tgt
;
303 Tgt
:= Tree_Operations
.Next
(Tgt
);
304 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
310 function Intersection
(Left
, Right
: Tree_Type
) return Tree_Type
is
312 if Left
'Address = Right
'Address then
316 -- Per AI05-0022, the container implementation is required to detect
317 -- element tampering by a generic actual subprogram.
320 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
321 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
325 L_Node
: Node_Access
;
326 R_Node
: Node_Access
;
328 Dst_Node
: Node_Access
;
329 pragma Warnings
(Off
, Dst_Node
);
332 L_Node
:= Left
.First
;
333 R_Node
:= Right
.First
;
335 if L_Node
= null then
339 if R_Node
= null then
343 if Is_Less
(L_Node
, R_Node
) then
344 L_Node
:= Tree_Operations
.Next
(L_Node
);
346 elsif Is_Less
(R_Node
, L_Node
) then
347 R_Node
:= Tree_Operations
.Next
(R_Node
);
354 Dst_Node
=> Dst_Node
);
356 L_Node
:= Tree_Operations
.Next
(L_Node
);
357 R_Node
:= Tree_Operations
.Next
(R_Node
);
365 Delete_Tree
(Tree
.Root
);
376 Of_Set
: Tree_Type
) return Boolean
379 if Subset
'Address = Of_Set
'Address then
383 if Subset
.Length
> Of_Set
.Length
then
387 -- Per AI05-0022, the container implementation is required to detect
388 -- element tampering by a generic actual subprogram.
391 Lock_Subset
: With_Lock
(Subset
.TC
'Unrestricted_Access);
392 Lock_Of_Set
: With_Lock
(Of_Set
.TC
'Unrestricted_Access);
394 Subset_Node
: Node_Access
;
395 Set_Node
: Node_Access
;
398 Subset_Node
:= Subset
.First
;
399 Set_Node
:= Of_Set
.First
;
401 if Set_Node
= null then
402 return Subset_Node
= null;
405 if Subset_Node
= null then
409 if Is_Less
(Subset_Node
, Set_Node
) then
413 if Is_Less
(Set_Node
, Subset_Node
) then
414 Set_Node
:= Tree_Operations
.Next
(Set_Node
);
416 Set_Node
:= Tree_Operations
.Next
(Set_Node
);
417 Subset_Node
:= Tree_Operations
.Next
(Subset_Node
);
427 function Overlap
(Left
, Right
: Tree_Type
) return Boolean is
429 if Left
'Address = Right
'Address then
430 return Left
.Length
/= 0;
433 -- Per AI05-0022, the container implementation is required to detect
434 -- element tampering by a generic actual subprogram.
437 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
438 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
440 L_Node
: Node_Access
;
441 R_Node
: Node_Access
;
443 L_Node
:= Left
.First
;
444 R_Node
:= Right
.First
;
447 or else R_Node
= null
452 if Is_Less
(L_Node
, R_Node
) then
453 L_Node
:= Tree_Operations
.Next
(L_Node
);
455 elsif Is_Less
(R_Node
, L_Node
) then
456 R_Node
:= Tree_Operations
.Next
(R_Node
);
465 --------------------------
466 -- Symmetric_Difference --
467 --------------------------
469 procedure Symmetric_Difference
470 (Target
: in out Tree_Type
;
476 New_Tgt_Node
: Node_Access
;
477 pragma Warnings
(Off
, New_Tgt_Node
);
482 if Target
'Address = Source
'Address then
491 while Src
/= null loop
496 Dst_Node
=> New_Tgt_Node
);
498 Src
:= Tree_Operations
.Next
(Src
);
508 -- Per AI05-0022, the container implementation is required to detect
509 -- element tampering by a generic actual subprogram.
512 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
513 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
515 if Is_Less
(Tgt
, Src
) then
517 elsif Is_Less
(Src
, Tgt
) then
525 Tgt
:= Tree_Operations
.Next
(Tgt
);
527 elsif Compare
> 0 then
532 Dst_Node
=> New_Tgt_Node
);
534 Src
:= Tree_Operations
.Next
(Src
);
538 X
: Node_Access
:= Tgt
;
540 Tgt
:= Tree_Operations
.Next
(Tgt
);
541 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
545 Src
:= Tree_Operations
.Next
(Src
);
548 end Symmetric_Difference
;
550 function Symmetric_Difference
(Left
, Right
: Tree_Type
) return Tree_Type
is
552 if Left
'Address = Right
'Address then
553 return Tree_Type
'(others => <>); -- Empty set
556 if Right.Length = 0 then
560 if Left.Length = 0 then
564 -- Per AI05-0022, the container implementation is required to detect
565 -- element tampering by a generic actual subprogram.
568 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
569 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
573 L_Node : Node_Access;
574 R_Node : Node_Access;
576 Dst_Node : Node_Access;
577 pragma Warnings (Off, Dst_Node);
580 L_Node := Left.First;
581 R_Node := Right.First;
583 if L_Node = null then
584 while R_Node /= null loop
589 Dst_Node => Dst_Node);
590 R_Node := Tree_Operations.Next (R_Node);
596 if R_Node = null then
597 while L_Node /= null loop
602 Dst_Node => Dst_Node);
604 L_Node := Tree_Operations.Next (L_Node);
610 if Is_Less (L_Node, R_Node) then
615 Dst_Node => Dst_Node);
617 L_Node := Tree_Operations.Next (L_Node);
619 elsif Is_Less (R_Node, L_Node) then
624 Dst_Node => Dst_Node);
626 R_Node := Tree_Operations.Next (R_Node);
629 L_Node := Tree_Operations.Next (L_Node);
630 R_Node := Tree_Operations.Next (R_Node);
638 Delete_Tree (Tree.Root);
641 end Symmetric_Difference;
647 procedure Union (Target : in out Tree_Type; Source : Tree_Type) is
650 procedure Process (Node : Node_Access);
651 pragma Inline (Process);
653 procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
659 procedure Process (Node : Node_Access) is
663 Dst_Hint => Hint, -- use node most recently inserted as hint
668 -- Start of processing for Union
671 if Target'Address = Source'Address then
675 -- Per AI05-0022, the container implementation is required to detect
676 -- element tampering by a generic actual subprogram.
679 Lock_Source : With_Lock (Source.TC'Unrestricted_Access);
685 function Union (Left, Right : Tree_Type) return Tree_Type is
687 if Left'Address = Right'Address then
691 if Left.Length = 0 then
695 if Right.Length = 0 then
700 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
701 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
703 Tree : Tree_Type := Copy (Left);
707 procedure Process (Node : Node_Access);
708 pragma Inline (Process);
711 new Tree_Operations.Generic_Iteration (Process);
717 procedure Process (Node : Node_Access) is
721 Dst_Hint => Hint, -- use node most recently inserted as hint
726 -- Start of processing for Union
734 Delete_Tree (Tree.Root);
739 end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;