1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_BOUNDED_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_Bounded_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 function Copy
(Source
: Set_Type
) return Set_Type
;
48 function Copy
(Source
: Set_Type
) return Set_Type
is
50 return Target
: Set_Type
(Source
.Length
) do
51 Assign
(Target
=> Target
, Source
=> Source
);
59 procedure Set_Difference
(Target
: in out Set_Type
; Source
: Set_Type
) is
60 Tgt
, Src
: Count_Type
;
62 TN
: Nodes_Type
renames Target
.Nodes
;
63 SN
: Nodes_Type
renames Source
.Nodes
;
68 if Target
'Address = Source
'Address then
71 Tree_Operations
.Clear_Tree
(Target
);
75 if Source
.Length
= 0 then
92 -- Per AI05-0022, the container implementation is required to detect
93 -- element tampering by a generic actual subprogram.
96 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
97 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
99 if Is_Less
(TN
(Tgt
), SN
(Src
)) then
101 elsif Is_Less
(SN
(Src
), TN
(Tgt
)) then
109 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
111 elsif Compare
> 0 then
112 Src
:= Tree_Operations
.Next
(Source
, Src
);
116 X
: constant Count_Type
:= Tgt
;
118 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
120 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
121 Tree_Operations
.Free
(Target
, X
);
124 Src
:= Tree_Operations
.Next
(Source
, Src
);
129 function Set_Difference
(Left
, Right
: Set_Type
) return Set_Type
is
131 if Left
'Address = Right
'Address then
132 return S
: Set_Type
(0); -- Empty set
135 if Left
.Length
= 0 then
136 return S
: Set_Type
(0); -- Empty set
139 if Right
.Length
= 0 then
143 return Result
: Set_Type
(Left
.Length
) do
144 -- Per AI05-0022, the container implementation is required to detect
145 -- element tampering by a generic actual subprogram.
148 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
149 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
154 Dst_Node
: Count_Type
;
155 pragma Warnings
(Off
, Dst_Node
);
158 L_Node
:= Left
.First
;
159 R_Node
:= Right
.First
;
166 while L_Node
/= 0 loop
170 Src_Node
=> Left
.Nodes
(L_Node
),
171 Dst_Node
=> Dst_Node
);
173 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
179 if Is_Less
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
183 Src_Node
=> Left
.Nodes
(L_Node
),
184 Dst_Node
=> Dst_Node
);
186 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
188 elsif Is_Less
(Right
.Nodes
(R_Node
), Left
.Nodes
(L_Node
)) then
189 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
192 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
193 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
204 procedure Set_Intersection
205 (Target
: in out Set_Type
;
214 if Target
'Address = Source
'Address then
218 TC_Check
(Target
.TC
);
220 if Source
.Length
= 0 then
221 Tree_Operations
.Clear_Tree
(Target
);
230 -- Per AI05-0022, the container implementation is required to detect
231 -- element tampering by a generic actual subprogram.
234 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
235 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
237 if Is_Less
(Target
.Nodes
(Tgt
), Source
.Nodes
(Src
)) then
239 elsif Is_Less
(Source
.Nodes
(Src
), Target
.Nodes
(Tgt
)) then
248 X
: constant Count_Type
:= Tgt
;
250 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
252 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
253 Tree_Operations
.Free
(Target
, X
);
256 elsif Compare
> 0 then
257 Src
:= Tree_Operations
.Next
(Source
, Src
);
260 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
261 Src
:= Tree_Operations
.Next
(Source
, Src
);
267 X
: constant Count_Type
:= Tgt
;
269 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
271 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
272 Tree_Operations
.Free
(Target
, X
);
275 end Set_Intersection
;
277 function Set_Intersection
(Left
, Right
: Set_Type
) return Set_Type
is
279 if Left
'Address = Right
'Address then
283 return Result
: Set_Type
(Count_Type
'Min (Left
.Length
, Right
.Length
)) do
285 -- Per AI05-0022, the container implementation is required to detect
286 -- element tampering by a generic actual subprogram.
289 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
290 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
295 Dst_Node
: Count_Type
;
296 pragma Warnings
(Off
, Dst_Node
);
299 L_Node
:= Left
.First
;
300 R_Node
:= Right
.First
;
310 if Is_Less
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
311 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
313 elsif Is_Less
(Right
.Nodes
(R_Node
), Left
.Nodes
(L_Node
)) then
314 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
320 Src_Node
=> Left
.Nodes
(L_Node
),
321 Dst_Node
=> Dst_Node
);
323 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
324 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
329 end Set_Intersection
;
337 Of_Set
: Set_Type
) return Boolean
340 if Subset
'Address = Of_Set
'Address then
344 if Subset
.Length
> Of_Set
.Length
then
348 -- Per AI05-0022, the container implementation is required to detect
349 -- element tampering by a generic actual subprogram.
352 Lock_Subset
: With_Lock
(Subset
.TC
'Unrestricted_Access);
353 Lock_Of_Set
: With_Lock
(Of_Set
.TC
'Unrestricted_Access);
355 Subset_Node
: Count_Type
;
356 Set_Node
: Count_Type
;
358 Subset_Node
:= Subset
.First
;
359 Set_Node
:= Of_Set
.First
;
362 return Subset_Node
= 0;
365 if Subset_Node
= 0 then
369 if Is_Less
(Subset
.Nodes
(Subset_Node
),
370 Of_Set
.Nodes
(Set_Node
))
375 if Is_Less
(Of_Set
.Nodes
(Set_Node
),
376 Subset
.Nodes
(Subset_Node
))
378 Set_Node
:= Tree_Operations
.Next
(Of_Set
, Set_Node
);
380 Set_Node
:= Tree_Operations
.Next
(Of_Set
, Set_Node
);
381 Subset_Node
:= Tree_Operations
.Next
(Subset
, Subset_Node
);
391 function Set_Overlap
(Left
, Right
: Set_Type
) return Boolean is
393 if Left
'Address = Right
'Address then
394 return Left
.Length
/= 0;
397 -- Per AI05-0022, the container implementation is required to detect
398 -- element tampering by a generic actual subprogram.
401 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
402 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
407 L_Node
:= Left
.First
;
408 R_Node
:= Right
.First
;
416 if Is_Less
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
417 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
418 elsif Is_Less
(Right
.Nodes
(R_Node
), Left
.Nodes
(L_Node
)) then
419 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
427 --------------------------
428 -- Symmetric_Difference --
429 --------------------------
431 procedure Set_Symmetric_Difference
432 (Target
: in out Set_Type
;
438 New_Tgt_Node
: Count_Type
;
439 pragma Warnings
(Off
, New_Tgt_Node
);
444 if Target
'Address = Source
'Address then
445 Tree_Operations
.Clear_Tree
(Target
);
457 Src_Node
=> Source
.Nodes
(Src
),
458 Dst_Node
=> New_Tgt_Node
);
460 Src
:= Tree_Operations
.Next
(Source
, Src
);
470 -- Per AI05-0022, the container implementation is required to detect
471 -- element tampering by a generic actual subprogram.
474 Lock_Target
: With_Lock
(Target
.TC
'Unrestricted_Access);
475 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
477 if Is_Less
(Target
.Nodes
(Tgt
), Source
.Nodes
(Src
)) then
479 elsif Is_Less
(Source
.Nodes
(Src
), Target
.Nodes
(Tgt
)) then
487 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
489 elsif Compare
> 0 then
493 Src_Node
=> Source
.Nodes
(Src
),
494 Dst_Node
=> New_Tgt_Node
);
496 Src
:= Tree_Operations
.Next
(Source
, Src
);
500 X
: constant Count_Type
:= Tgt
;
502 Tgt
:= Tree_Operations
.Next
(Target
, Tgt
);
504 Tree_Operations
.Delete_Node_Sans_Free
(Target
, X
);
505 Tree_Operations
.Free
(Target
, X
);
508 Src
:= Tree_Operations
.Next
(Source
, Src
);
511 end Set_Symmetric_Difference
;
513 function Set_Symmetric_Difference
514 (Left
, Right
: Set_Type
) return Set_Type
517 if Left
'Address = Right
'Address then
518 return S
: Set_Type
(0); -- Empty set
521 if Right
.Length
= 0 then
525 if Left
.Length
= 0 then
529 return Result
: Set_Type
(Left
.Length
+ Right
.Length
) do
531 -- Per AI05-0022, the container implementation is required to detect
532 -- element tampering by a generic actual subprogram.
535 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
536 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
541 Dst_Node
: Count_Type
;
542 pragma Warnings
(Off
, Dst_Node
);
545 L_Node
:= Left
.First
;
546 R_Node
:= Right
.First
;
549 while R_Node
/= 0 loop
553 Src_Node
=> Right
.Nodes
(R_Node
),
554 Dst_Node
=> Dst_Node
);
556 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
563 while L_Node
/= 0 loop
567 Src_Node
=> Left
.Nodes
(L_Node
),
568 Dst_Node
=> Dst_Node
);
570 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
576 if Is_Less
(Left
.Nodes
(L_Node
), Right
.Nodes
(R_Node
)) then
580 Src_Node
=> Left
.Nodes
(L_Node
),
581 Dst_Node
=> Dst_Node
);
583 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
585 elsif Is_Less
(Right
.Nodes
(R_Node
), Left
.Nodes
(L_Node
)) then
589 Src_Node
=> Right
.Nodes
(R_Node
),
590 Dst_Node
=> Dst_Node
);
592 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
595 L_Node
:= Tree_Operations
.Next
(Left
, L_Node
);
596 R_Node
:= Tree_Operations
.Next
(Right
, R_Node
);
601 end Set_Symmetric_Difference
;
607 procedure Set_Union
(Target
: in out Set_Type
; Source
: Set_Type
) is
608 Hint
: Count_Type
:= 0;
610 procedure Process
(Node
: Count_Type
);
611 pragma Inline
(Process
);
613 procedure Iterate
is new Tree_Operations
.Generic_Iteration
(Process
);
619 procedure Process
(Node
: Count_Type
) is
624 Src_Node
=> Source
.Nodes
(Node
),
628 -- Start of processing for Union
631 if Target
'Address = Source
'Address then
635 -- Per AI05-0022, the container implementation is required to detect
636 -- element tampering by a generic actual subprogram.
639 Lock_Source
: With_Lock
(Source
.TC
'Unrestricted_Access);
641 -- Note that there's no way to decide a priori whether the target has
642 -- enough capacity for the union with source. We cannot simply
643 -- compare the sum of the existing lengths to the capacity of the
644 -- target, because equivalent items from source are not included in
651 function Set_Union
(Left
, Right
: Set_Type
) return Set_Type
is
653 if Left
'Address = Right
'Address then
657 if Left
.Length
= 0 then
661 if Right
.Length
= 0 then
665 return Result
: Set_Type
(Left
.Length
+ Right
.Length
) do
667 Lock_Left
: With_Lock
(Left
.TC
'Unrestricted_Access);
668 Lock_Right
: With_Lock
(Right
.TC
'Unrestricted_Access);
670 Assign
(Target
=> Result
, Source
=> Left
);
672 Insert_Right
: declare
673 Hint
: Count_Type
:= 0;
675 procedure Process
(Node
: Count_Type
);
676 pragma Inline
(Process
);
679 new Tree_Operations
.Generic_Iteration
(Process
);
685 procedure Process
(Node
: Count_Type
) is
690 Src_Node
=> Right
.Nodes
(Node
),
694 -- Start of processing for Insert_Right
703 end Ada
.Containers
.Red_Black_Trees
.Generic_Bounded_Set_Operations
;