1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_SET_OPERATIONS --
9 -- Copyright (C) 2004-2024, 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
99 if Target
'Address = Source
'Address then
104 if Source
.Length
= 0 then
119 -- Per AI05-0022, the container implementation is required to detect
120 -- element tampering by a generic actual subprogram.
123 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
124 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
126 if Is_Less
(Tgt
, Src
) then
128 elsif Is_Less
(Src
, Tgt
) then
136 Tgt
:= Tree_Operations
.Next
(Tgt
);
138 elsif Compare
> 0 then
139 Src
:= Tree_Operations
.Next
(Src
);
143 X
: Node_Access
:= Tgt
;
145 Tgt
:= Tree_Operations
.Next
(Tgt
);
146 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
150 Src
:= Tree_Operations
.Next
(Src
);
155 function Difference
(Left
, Right
: Tree_Type
) return Tree_Type
is
157 if Left
'Address = Right
'Address then
158 return Tree_Type
'(others => <>); -- Empty set
161 if Left.Length = 0 then
162 return Tree_Type'(others => <>); -- Empty set
165 if Right
.Length
= 0 then
169 -- Per AI05-0022, the container implementation is required to detect
170 -- element tampering by a generic actual subprogram.
173 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
174 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
178 L_Node
: Node_Access
;
179 R_Node
: Node_Access
;
181 Dst_Node
: Node_Access
;
182 pragma Warnings
(Off
, Dst_Node
);
185 L_Node
:= Left
.First
;
186 R_Node
:= Right
.First
;
188 if L_Node
= null then
192 if R_Node
= null then
193 while L_Node
/= null loop
198 Dst_Node
=> Dst_Node
);
200 L_Node
:= Tree_Operations
.Next
(L_Node
);
206 if Is_Less
(L_Node
, R_Node
) then
211 Dst_Node
=> Dst_Node
);
213 L_Node
:= Tree_Operations
.Next
(L_Node
);
215 elsif Is_Less
(R_Node
, L_Node
) then
216 R_Node
:= Tree_Operations
.Next
(R_Node
);
219 L_Node
:= Tree_Operations
.Next
(L_Node
);
220 R_Node
:= Tree_Operations
.Next
(R_Node
);
228 Delete_Tree
(Tree
.Root
);
237 procedure Intersection
238 (Target
: in out Tree_Type
;
247 if Target
'Address = Source
'Address then
251 TC_Check
(Target
.TC
);
253 if Source
.Length
= 0 then
263 -- Per AI05-0022, the container implementation is required to detect
264 -- element tampering by a generic actual subprogram.
267 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
268 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
270 if Is_Less
(Tgt
, Src
) then
272 elsif Is_Less
(Src
, Tgt
) then
281 X
: Node_Access
:= Tgt
;
283 Tgt
:= Tree_Operations
.Next
(Tgt
);
284 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
288 elsif Compare
> 0 then
289 Src
:= Tree_Operations
.Next
(Src
);
292 Tgt
:= Tree_Operations
.Next
(Tgt
);
293 Src
:= Tree_Operations
.Next
(Src
);
297 while Tgt
/= null loop
299 X
: Node_Access
:= Tgt
;
301 Tgt
:= Tree_Operations
.Next
(Tgt
);
302 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
308 function Intersection
(Left
, Right
: Tree_Type
) return Tree_Type
is
310 if Left
'Address = Right
'Address then
314 -- Per AI05-0022, the container implementation is required to detect
315 -- element tampering by a generic actual subprogram.
318 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
319 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
323 L_Node
: Node_Access
;
324 R_Node
: Node_Access
;
326 Dst_Node
: Node_Access
;
327 pragma Warnings
(Off
, Dst_Node
);
330 L_Node
:= Left
.First
;
331 R_Node
:= Right
.First
;
333 if L_Node
= null then
337 if R_Node
= null then
341 if Is_Less
(L_Node
, R_Node
) then
342 L_Node
:= Tree_Operations
.Next
(L_Node
);
344 elsif Is_Less
(R_Node
, L_Node
) then
345 R_Node
:= Tree_Operations
.Next
(R_Node
);
352 Dst_Node
=> Dst_Node
);
354 L_Node
:= Tree_Operations
.Next
(L_Node
);
355 R_Node
:= Tree_Operations
.Next
(R_Node
);
363 Delete_Tree
(Tree
.Root
);
374 Of_Set
: Tree_Type
) return Boolean
377 if Subset
'Address = Of_Set
'Address then
381 if Subset
.Length
> Of_Set
.Length
then
385 -- Per AI05-0022, the container implementation is required to detect
386 -- element tampering by a generic actual subprogram.
389 Lock_Subset
: With_Lock
(Subset
.TC
'Unrestricted_Access);
390 Lock_Of_Set
: With_Lock
(Of_Set
.TC
'Unrestricted_Access);
392 Subset_Node
: Node_Access
;
393 Set_Node
: Node_Access
;
396 Subset_Node
:= Subset
.First
;
397 Set_Node
:= Of_Set
.First
;
399 if Set_Node
= null then
400 return Subset_Node
= null;
403 if Subset_Node
= null then
407 if Is_Less
(Subset_Node
, Set_Node
) then
411 if Is_Less
(Set_Node
, Subset_Node
) then
412 Set_Node
:= Tree_Operations
.Next
(Set_Node
);
414 Set_Node
:= Tree_Operations
.Next
(Set_Node
);
415 Subset_Node
:= Tree_Operations
.Next
(Subset_Node
);
425 function Overlap
(Left
, Right
: Tree_Type
) return Boolean is
427 if Left
'Address = Right
'Address then
428 return Left
.Length
/= 0;
431 -- Per AI05-0022, the container implementation is required to detect
432 -- element tampering by a generic actual subprogram.
435 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
436 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
438 L_Node
: Node_Access
;
439 R_Node
: Node_Access
;
441 L_Node
:= Left
.First
;
442 R_Node
:= Right
.First
;
445 or else R_Node
= null
450 if Is_Less
(L_Node
, R_Node
) then
451 L_Node
:= Tree_Operations
.Next
(L_Node
);
453 elsif Is_Less
(R_Node
, L_Node
) then
454 R_Node
:= Tree_Operations
.Next
(R_Node
);
463 --------------------------
464 -- Symmetric_Difference --
465 --------------------------
467 procedure Symmetric_Difference
468 (Target
: in out Tree_Type
;
474 New_Tgt_Node
: Node_Access
;
475 pragma Warnings
(Off
, New_Tgt_Node
);
480 if Target
'Address = Source
'Address then
489 while Src
/= null loop
494 Dst_Node
=> New_Tgt_Node
);
496 Src
:= Tree_Operations
.Next
(Src
);
506 -- Per AI05-0022, the container implementation is required to detect
507 -- element tampering by a generic actual subprogram.
510 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
511 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
513 if Is_Less
(Tgt
, Src
) then
515 elsif Is_Less
(Src
, Tgt
) then
523 Tgt
:= Tree_Operations
.Next
(Tgt
);
525 elsif Compare
> 0 then
530 Dst_Node
=> New_Tgt_Node
);
532 Src
:= Tree_Operations
.Next
(Src
);
536 X
: Node_Access
:= Tgt
;
538 Tgt
:= Tree_Operations
.Next
(Tgt
);
539 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
543 Src
:= Tree_Operations
.Next
(Src
);
546 end Symmetric_Difference
;
548 function Symmetric_Difference
(Left
, Right
: Tree_Type
) return Tree_Type
is
550 if Left
'Address = Right
'Address then
551 return Tree_Type
'(others => <>); -- Empty set
554 if Right.Length = 0 then
558 if Left.Length = 0 then
562 -- Per AI05-0022, the container implementation is required to detect
563 -- element tampering by a generic actual subprogram.
566 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
567 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
571 L_Node : Node_Access;
572 R_Node : Node_Access;
574 Dst_Node : Node_Access;
575 pragma Warnings (Off, Dst_Node);
578 L_Node := Left.First;
579 R_Node := Right.First;
581 if L_Node = null then
582 while R_Node /= null loop
587 Dst_Node => Dst_Node);
588 R_Node := Tree_Operations.Next (R_Node);
594 if R_Node = null then
595 while L_Node /= null loop
600 Dst_Node => Dst_Node);
602 L_Node := Tree_Operations.Next (L_Node);
608 if Is_Less (L_Node, R_Node) then
613 Dst_Node => Dst_Node);
615 L_Node := Tree_Operations.Next (L_Node);
617 elsif Is_Less (R_Node, L_Node) then
622 Dst_Node => Dst_Node);
624 R_Node := Tree_Operations.Next (R_Node);
627 L_Node := Tree_Operations.Next (L_Node);
628 R_Node := Tree_Operations.Next (R_Node);
636 Delete_Tree (Tree.Root);
639 end Symmetric_Difference;
645 procedure Union (Target : in out Tree_Type; Source : Tree_Type) is
648 procedure Process (Node : Node_Access);
649 pragma Inline (Process);
651 procedure Iterate is new Tree_Operations.Generic_Iteration (Process);
657 procedure Process (Node : Node_Access) is
661 Dst_Hint => Hint, -- use node most recently inserted as hint
666 -- Start of processing for Union
669 if Target'Address = Source'Address then
673 -- Per AI05-0022, the container implementation is required to detect
674 -- element tampering by a generic actual subprogram.
677 Lock_Source : With_Lock (Source.TC'Unrestricted_Access);
683 function Union (Left, Right : Tree_Type) return Tree_Type is
685 if Left'Address = Right'Address then
689 if Left.Length = 0 then
693 if Right.Length = 0 then
698 Lock_Left : With_Lock (Left.TC'Unrestricted_Access);
699 Lock_Right : With_Lock (Right.TC'Unrestricted_Access);
701 Tree : Tree_Type := Copy (Left);
705 procedure Process (Node : Node_Access);
706 pragma Inline (Process);
709 new Tree_Operations.Generic_Iteration (Process);
715 procedure Process (Node : Node_Access) is
719 Dst_Hint => Hint, -- use node most recently inserted as hint
724 -- Start of processing for Union
732 Delete_Tree (Tree.Root);
737 end Ada.Containers.Red_Black_Trees.Generic_Set_Operations;