File Coverage

lib/Class/STL/Algorithms.pm
Criterion Covered Total %
statement 53 419 12.6
branch 4 166 2.4
condition 0 190 0.0
subroutine 16 57 28.0
pod 0 39 0.0
total 73 871 8.3


line stmt bran cond sub pod time code
1             # vim:ts=4 sw=4
2             # ----------------------------------------------------------------------------------------------------
3             # Name : Class::STL::Alogorithms.pm
4             # Created : 22 February 2006
5             # Author : Mario Gaffiero (gaffie)
6             #
7             # Copyright 2006-2007 Mario Gaffiero.
8             #
9             # This file is part of Class::STL::Containers(TM).
10             #
11             # Class::STL::Containers is free software; you can redistribute it and/or modify
12             # it under the terms of the GNU General Public License as published by
13             # the Free Software Foundation; version 2 of the License.
14             #
15             # Class::STL::Containers is distributed in the hope that it will be useful,
16             # but WITHOUT ANY WARRANTY; without even the implied warranty of
17             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18             # GNU General Public License for more details.
19             #
20             # You should have received a copy of the GNU General Public License
21             # along with Class::STL::Containers; if not, write to the Free Software
22             # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23             # ----------------------------------------------------------------------------------------------------
24             # Modification History
25             # When Version Who What
26             # ----------------------------------------------------------------------------------------------------
27             # TO DO:
28             # ----------------------------------------------------------------------------------------------------
29             require 5.005_62;
30 7     7   40 use strict;
  7         19  
  7         337  
31 7     7   6628 use attributes qw(get reftype);
  7         17701  
  7         52  
32 7     7   893 use warnings;
  7         19  
  7         484  
33 7     7   47 use vars qw($VERSION $BUILD);
  7         20  
  7         620  
34             $VERSION = '0.21';
35             $BUILD = 'Monday May 8 23:08:34 GMT 2006';
36             # ----------------------------------------------------------------------------------------------------
37             {
38             package Class::STL::Algorithms;
39 7     7   42 use UNIVERSAL qw(isa can);
  7         19  
  7         53  
40 7     7   3500 use vars qw( @EXPORT_OK %EXPORT_TAGS );
  7         19  
  7         595  
41 7     7   43 use Exporter;
  7         14  
  7         772  
42             my @export_names = qw(
43             find
44             find_if
45             for_each
46             transform
47             count
48             count_if
49             copy
50             copy_backward
51             remove
52             remove_if
53             remove_copy
54             remove_copy_if
55             replace
56             replace_if
57             replace_copy
58             replace_copy_if
59             generate
60             generate_n
61             fill
62             fill_n
63             equal
64             reverse
65             reverse_copy
66             rotate
67             rotate_copy
68             partition
69             stable_partition
70             min_element
71             max_element
72             unique
73             unique_copy
74             adjacent_find
75             _sort
76             stable_sort
77             qsort
78             stable_qsort
79             accumulate
80             );
81             @EXPORT_OK = (@export_names);
82             %EXPORT_TAGS = ( all => [@export_names] );
83             sub new
84             {
85 7     7   40 use Carp qw(confess);
  7         19  
  7         3254  
86 0     0 0   confess "@{[ __PACKAGE__ ]} contains STATIC functions only!\n";
  0            
87             }
88             sub accumulate # (iterator-start, iterator-finish, element [, binary-function ] )
89             {
90 0     0 0   my $iter_start = shift;
91 0           my $iter_finish = shift;
92 0           my $element = shift;
93 0   0       my $binary_op = shift || undef;
94 0           $element = $iter_start->p_container()->factory($element);
95 0 0         defined($binary_op)
96             ? _usage_check('accumulate', 'IIEB', $iter_start, $iter_finish, $element, $binary_op)
97             : _usage_check('accumulate', 'IIE', $iter_start, $iter_finish, $element);
98 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
99             {
100 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
101             {
102 0           accumulate($iter->p_element()->begin(), $iter->p_element()->end(), $element, $binary_op); # its a tree -- recurse
103             }
104             else
105             {
106 0 0         defined($binary_op)
107             ? $element = $binary_op->function_operator($element, $iter->p_element())
108             : $element->add($iter->p_element());
109             }
110             }
111 0           return $element;
112             }
113             sub BEGIN
114             {
115 7     7   965 eval "use sort qw(stable)";
  7     7   6729  
  7         4950  
  7         46  
116 7         207 my $have_sort = !$@;
117 7         19 my $eval =
118             "
119             sub qsort # (iterator-start, iterator-finish [, binary-function ] )
120             {
121 7 50       61 @{[ $have_sort ? 'use sort qw(_qsort);' : '' ]}
  7 50       49  
122             _sort(\@_);
123             }
124             sub stable_qsort # (iterator-start, iterator-finish [, binary-function ] )
125             {
126 7 50       46 @{[ $have_sort ? 'use sort qw(stable _qsort);' : '' ]}
127             _sort(\@_);
128             }
129             sub stable_sort # (iterator-start, iterator-finish [, binary-function ] )
130             {
131             @{[ $have_sort ? 'use sort qw(stable);' : '' ]}
132             _sort(\@_);
133             }
134             "
135             ;
136 7     7 0 578 eval($eval);
  7     7 0 44  
  7     7 0 17  
  7     0   33  
  7     0   704  
  7     0   17  
  7         33  
  7         651  
  7         16  
  7         76  
  0            
  0            
  0            
137 7 50       486 confess "@{[ __PACKAGE__ ]} Invalid sort pragma usage!\n" if ($@);
  0         0  
138            
139             }
140             sub _sort # (iterator-start, iterator-finish [, binary-function ] )
141             {
142 7     7   45 use Class::STL::Iterators qw(distance);
  7         29  
  7         197  
143 0 0   0     int(@_) == 2 ? _usage_check('sort(1)', 'II', @_) : _usage_check('sort(2)', 'IIB', @_);
144 0           my $iter_start = shift;
145 0           my $iter_finish = shift;
146 0   0       my $binary_op = shift || undef;
147 0           defined($binary_op)
148 0           ? CORE::splice(@{$iter_start->p_container()->data()}, $iter_start->arr_idx(), distance($iter_start, $iter_finish)+1,
149 0           CORE::sort { $binary_op->function_operator($a, $b) }
150 0           (@{$iter_start->p_container()->data()}[$iter_start->arr_idx()..$iter_finish->arr_idx()]))
151 0           : CORE::splice(@{$iter_start->p_container()->data()}, $iter_start->arr_idx(), distance($iter_start, $iter_finish)+1,
152 0           CORE::sort { $a->cmp($b) }
153 0 0         (@{$iter_start->p_container()->data()}[$iter_start->arr_idx()..$iter_finish->arr_idx()]));
154 0           return; # void
155             }
156             sub transform
157             {
158 0 0   0 0   return @_ == 5 ? transform_2(@_) : transform_1(@_);
159             }
160             sub transform_1 # (iterator-start, iterator-finish, iterator-result, unary-function-object)
161             {
162 0     0 0   _usage_check('transform(1)', 'IIIU', @_);
163 0           my $iter_start = shift;
164 0           my $iter_finish = shift;
165 0           my $iter_result = shift;
166 0           my $unary_op = shift; # unary-function
167 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
168             {
169 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::AbstracTree'))
    0          
170             {
171 0           transform_1($iter->p_element()->begin(), $iter->p_element()->end(), $iter_result, $unary_op); # its a tree -- recurse
172             }
173             elsif ($unary_op->isa('Class::STL::Utilities::FunctionObject::UnaryPredicate'))
174             {
175             # Need to check this!
176 0           my $e = $iter->p_element()->clone();
177 0 0         $e->data($unary_op->function_operator($iter->p_element()) ? 1 : 0);
178 0           $iter_result->p_container()->insert($iter_result, $e);
179             }
180             else # $unary_op->isa('Class::STL::Utilities::FunctionObject::UnaryFunction')
181             {
182 0           $iter_result->p_container()->insert($iter_result,
183             $unary_op->function_operator($iter->p_element()));
184             }
185             }
186 0           return;
187             }
188             sub transform_2 # (iterator-start, iterator-finish, iterator-start2, iterator-result, binary-function-object)
189             {
190 0     0 0   _usage_check('transform(2)', 'IIIIB', @_);
191 0           my $iter_start = shift;
192 0           my $iter_finish = shift;
193 0           my $iter_start2 = shift;
194 0           my $iter_result = shift;
195 0           my $binary_op = shift; # binary-function
196 0   0       for
197             (
198             my $iter=$iter_start->clone(), my $iter2=$iter_start2->clone();
199             $iter <= $iter_finish && !$iter2->at_end();
200             ++$iter, ++$iter2
201             )
202             {
203 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::AbstracTree'))
    0          
204             {
205 0           transform_2($iter->p_element()->begin(), $iter->p_element()->end(), $iter_start2, $iter_result, $binary_op); # its a tree -- recurse
206             }
207             elsif ($binary_op->isa('Class::STL::Utilities::FunctionObject::BinaryPredicate'))
208             {
209 0           my $e = $iter->p_element()->clone();
210             #> $e->negate($binary_op->function_operator($iter->p_element(), $iter2->p_element()) ? 0 : 1);
211 0 0         $e->data($binary_op->function_operator($iter->p_element(), $iter2->p_element()) ? 1 : 0);
212 0           $iter_result->p_container()->insert($iter_result, $e);
213             }
214             else # $binary_op->isa('Class::STL::Utilities::FunctionObject::BinaryFunction')
215             {
216 0           $iter_result->p_container()->insert($iter_result,
217             $binary_op->function_operator($iter->p_element(), $iter2->p_element()));
218             }
219             }
220 0           return;
221             }
222             sub unique # (iterator, iterator [, binary-predicate ] ) -- static function
223             {
224 0 0   0 0   int(@_) == 2 ? _usage_check('unique(1)', 'II', @_) : _usage_check('unique(2)', 'IIB', @_);
225 0           my $iter_start = shift;
226 0           my $iter_finish = shift;
227 0   0       my $binary_op = shift || undef;
228 0           my $iter_prev = $iter_start->clone();
229 0   0       for (my $iter = $iter_start->clone()+1; $iter != $iter_prev && $iter <= $iter_finish; )
230             {
231 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0 0        
      0        
      0        
232             {
233 0           unique($iter->p_element()->begin(), $iter->p_element()->end(), $binary_op); # its a tree -- recurse
234 0           ++$iter;
235 0           ++$iter_prev;
236             }
237             elsif
238             (
239             (defined($binary_op) && $binary_op->function_operator($iter_prev->p_element(), $iter->p_element()))
240             || (!defined($binary_op) && $iter_prev->p_element()->eq($iter->p_element()))
241             )
242             {
243 0           $iter = $iter->p_container()->erase($iter)
244             }
245             else
246             {
247 0           ++$iter;
248 0           ++$iter_prev;
249             }
250             }
251 0           return $iter_finish; # iterator
252             }
253             sub unique_copy # (iterator, iterator, iterator [, binary-predicate ] ) -- static function
254             {
255 0 0   0 0   int(@_) == 3 ? _usage_check('unique_copy(1)', 'III', @_) : _usage_check('unique_copy(2)', 'IIIB', @_);
256 0           my $iter_start = shift;
257 0           my $iter_finish = shift;
258 0           my $iter_result = shift;
259 0   0       my $binary_op = shift || undef;
260 0           my $iter_prev = $iter_start->clone();
261 0           $iter_result->p_container()->insert($iter_result, 1, $iter_prev->p_element());
262 0   0       for (my $iter = $iter_start->clone()+1; $iter != $iter_prev && $iter <= $iter_finish; ++$iter, ++$iter_prev)
263             {
264 0 0 0       if
      0        
      0        
265             (
266             (defined($binary_op) && !$binary_op->function_operator($iter_prev->p_element(), $iter->p_element()))
267             || (!defined($binary_op) && !$iter_prev->p_element()->eq($iter->p_element()))
268             )
269             {
270 0           $iter_result->p_container()->insert($iter_result, 1, $iter->p_element());
271             }
272             }
273 0           return $iter_result-1; # iterator
274             }
275             sub adjacent_find # (iterator, iterator [, binary-predicate ] ) -- static function
276             {
277 0 0   0 0   int(@_) == 2 ? _usage_check('adjacent_find(1)', 'II', @_) : _usage_check('adjacent_find(2)', 'IIB', @_);
278 0           my $iter_start = shift;
279 0           my $iter_finish = shift;
280 0   0       my $binary_op = shift || undef;
281 0           my $iter_next = $iter_start->clone()+1;
282 0           for (my $iter = $iter_start->clone(); $iter_next <= $iter_finish; ++$iter, ++$iter_next)
283             {
284 0 0 0       return $iter
      0        
      0        
285             if
286             (
287             (defined($binary_op) && $binary_op->function_operator($iter->p_element(), $iter_next->p_element()))
288             || (!defined($binary_op) && $iter_next->p_element()->eq($iter->p_element()))
289             );
290             }
291 0           return $iter_finish; # iterator
292             }
293             sub partition # (iterator, iterator, unary-predicate) -- static function
294             {
295 0     0 0   stable_partition(@_);
296             }
297             sub stable_partition # (iterator, iterator, unary-predicate) -- static function
298             {
299 0     0 0   _usage_check('stable_partition', 'IIU', @_);
300 0           my $iter_start = shift;
301 0           my $iter_finish = shift;
302 0           my $function = shift;
303 0           my $position = $iter_start->clone();
304 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
305             {
306 0 0         if ($function->function_operator($iter->p_element()))
307             {
308 0           $iter->p_container()->insert($position, 1, $iter->p_element());
309 0           $iter->p_container()->erase($iter+1);
310             }
311             }
312 0           return;
313             }
314             sub min_element # (iterator, iterator, [, binary-function] ) -- static function
315             {
316 0 0   0 0   int(@_) == 3 ? _usage_check('min_element(1)', 'IIB', @_) : _usage_check('min_element(2)', 'II', @_);
317 0           my $iter_start = shift;
318 0           my $iter_finish = shift;
319 0   0       my $binary_op = shift || undef;
320 0           my $iter_min = $iter_start;
321 0           for (my $iter=$iter_start->clone(); $iter <= $iter_finish; ++$iter)
322             {
323 0 0 0       $iter_min = $iter
      0        
      0        
324             if
325             (
326             (defined($binary_op) && $binary_op->function_operator($iter->p_element(), $iter_min->p_element()))
327             || (!defined($binary_op) && $iter->p_element()->lt($iter_min->p_element()))
328             );
329             }
330 0           return $iter_min;
331             }
332             sub max_element # (iterator, iterator, [, binary-function] ) -- static function
333             {
334 0 0   0 0   int(@_) == 3 ? _usage_check('max_element(1)', 'IIB', @_) : _usage_check('max_element(2)', 'II', @_);
335 0           my $iter_start = shift;
336 0           my $iter_finish = shift;
337 0   0       my $binary_op = shift || undef;
338 0           my $iter_min = $iter_start;
339 0           for (my $iter=$iter_start->clone(); $iter <= $iter_finish; ++$iter)
340             {
341 0 0 0       $iter_min = $iter
      0        
      0        
342             if
343             (
344             (defined($binary_op) && !$binary_op->function_operator($iter->p_element(), $iter_min->p_element()))
345             || (!defined($binary_op) && !$iter->p_element()->lt($iter_min->p_element()))
346             );
347             }
348 0           return $iter_min;
349             }
350             sub equal # (iterator, iterator, iterator [, binary-function] ) -- static function
351             {
352 0 0   0 0   int(@_) == 3 ? _usage_check('equal(1)', 'III', @_) : _usage_check('equal(2)', 'IIIB', @_);
353 0           my $iter_start = shift;
354 0           my $iter_finish = shift;
355 0           my $iter_start2 = shift;
356 0   0       my $binary_op = shift || undef;
357 0           for
358             (
359             my $iter=$iter_start->clone(), my $iter2=$iter_start2->clone();
360             $iter <= $iter_finish;
361             ++$iter, ++$iter2
362             )
363             {
364 0 0 0       return 0 if # bool false
      0        
      0        
      0        
365             (
366             $iter2->at_end()
367             || (defined($binary_op) && $binary_op->function_operator($iter->p_element(), $iter2->p_element()) == 0)
368             || (!defined($binary_op) && $iter->p_element()->eq($iter2->p_element()) == 0)
369             );
370             }
371 0           return 1; # bool true
372             }
373             sub rotate_copy # (iterator, iterator, iterator, iterator) -- static function
374             {
375 0     0 0   _usage_check('rotate_copy', 'IIII', @_);
376 0           my $iter_start = shift;
377 0           my $iter_mid = shift;
378 0           my $iter_finish = shift;
379 0           my $iter_result = shift;
380 0           copy($iter_mid, $iter_finish, $iter_result);
381 0           copy($iter_start, $iter_mid-1, $iter_result);
382 0           return;
383             }
384             sub rotate # (iterator, iterator, iterator) -- static function
385             {
386 0     0 0   _usage_check('rotate', 'III', @_);
387 0           my $iter_start = shift;
388 0           my $iter_mid = shift;
389 0           my $iter_finish = shift;
390 0           my $iter_end = $iter_finish; ++$iter_end;
  0            
391 0           for (my $iter = $iter_start->clone(); $iter < $iter_mid; ++$iter)
392             {
393 0           $iter->p_container()->insert($iter_end, 1, $iter->p_element());
394             }
395 0           $iter_start->p_container()->erase($iter_start, --$iter_mid);
396 0           return;
397             }
398             sub reverse # (iterator, iterator) -- static function
399             {
400 0     0 0   _usage_check('reverse', 'II', @_);
401 0           my $iter_start = shift;
402 0           my $iter_finish = shift;
403 0           for (my $i1=$iter_start->clone(), my $i2=$iter_finish->clone(); $i1 < $i2; ++$i1, --$i2)
404             {
405 0           $i1->p_element()->swap($i2->p_element());
406             }
407 0           return;
408             }
409             sub reverse_copy # (iterator, iterator, iterator) -- static function
410             {
411 0     0 0   _usage_check('reverse_copy', 'III', @_);
412 0           my $iter_start = shift;
413 0           my $iter_finish = shift;
414 0           my $iter_result = shift;
415 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
416             {
417 0           $iter_result->p_container()->insert($iter_result, 1, $iter->p_element());
418 0           $iter_result--;
419             }
420 0           return;
421             }
422             sub for_each # (iterator, iterator, unary-function-object) -- static function
423             {
424 0     0 0   _usage_check('for_each', 'IIF', @_);
425 0           my $iter_start = shift;
426 0           my $iter_finish = shift;
427 0           my $function = shift; # unary-function
428 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
429             {
430 0 0 0       ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
431             ? for_each($iter->p_element()->begin(), $iter->p_element()->end(), $function) # its a tree -- recurse
432             : $function->function_operator($iter->p_element());
433             }
434 0           return;
435             }
436             sub generate # (iterator, iterator, generator-function-object) -- static function
437             {
438 0     0 0   _usage_check('generate', 'IIG', @_);
439 0           my $iter_start = shift;
440 0           my $iter_finish = shift;
441 0           my $function = shift; # generator-function
442 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
443             {
444 0 0 0       ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
445             ? generate($iter->p_element()->begin(), $iter->p_element()->end(), $function) # its a tree -- recurse
446             : $iter->p_element()->swap($function->function_operator());
447             }
448 0           return;
449             }
450             sub generate_n # (iterator, size, generator-function-object) -- static function
451             {
452 0     0 0   _usage_check('generate_n', 'ISG', @_);
453 0           my $iter_start = shift;
454 0           my $size = shift;
455 0           my $function = shift; # generator-function
456 0           my $iter = $iter_start->clone();
457 0           my $start_idx = $iter->arr_idx();
458 0           for (; $iter->arr_idx() - $start_idx < $size; ++$iter)
459             {
460 0 0 0       ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
461             ? generate_n($iter->p_element()->begin(), $size, $function) # its a tree -- recurse
462             : $iter->p_element()->swap($function->function_operator());
463             }
464 0           return;
465             }
466             sub fill # (iterator, iterator, element-ref) -- static function
467             {
468 0     0 0   my $iter_start = shift;
469 0           my $iter_finish = shift;
470 0           my $element = shift;
471 0 0 0       $element = $iter_start->p_container()->factory(data => $element)
472             unless (ref($element) && $element->isa('Class::STL::Element'));
473 0           _usage_check('fill', 'IIE', $iter_start, $iter_finish, $element);
474 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
475             {
476 0 0 0       ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
477             ? fill($iter->p_element()->begin(), $iter->p_element()->end(), $element) # its a tree -- recurse
478             : $iter->p_element()->swap($element->clone());
479             }
480 0           return;
481             }
482             sub fill_n # (iterator, size, element-ref) -- static function
483             {
484 0     0 0   my $iter_start = shift;
485 0           my $size = shift;
486 0           my $element = shift;
487 0 0 0       $element = $iter_start->p_container()->factory(data => $element)
488             unless (ref($element) && $element->isa('Class::STL::Element'));
489 0           _usage_check('fill_n', 'ISE', $iter_start, $size, $element);
490 0           my $iter = $iter_start->clone();
491 0           my $start_idx = $iter->arr_idx();
492 0           for (; $iter->arr_idx() - $start_idx < $size; ++$iter)
493             {
494 0 0 0       ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
495             ? fill_n($iter->p_element()->begin(), $size, $element) # its a tree -- recurse
496             : $iter->p_element()->swap($element->clone());
497             }
498 0           return;
499             }
500             sub find_if # (iterator, iterator, unary-function-object) -- static function
501             {
502 0     0 0   _usage_check('find_if', 'IIF', @_);
503 0           my $iter_start = shift;
504 0           my $iter_finish = shift;
505 0           my $function = shift; # unary-function
506 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
507             {
508 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0          
509             { # its a tree -- recurse
510 0 0         if (my $i = find_if($iter->p_element()->begin(), $iter->p_element()->end(), $function))
511             {
512 0           return $i; # Need to check this !!
513             }
514             }
515             elsif ($function->function_operator($iter->p_element()))
516             {
517 0           return $iter->clone(); # iterator
518             }
519             }
520 0           return 0;
521             }
522             sub find # (iterator, iterator, element-ref) -- static function
523             {
524 0     0 0   my $iter_start = shift;
525 0           my $iter_finish = shift;
526 0           my $element = shift; # element-ref
527 0 0 0       $element = $iter_start->p_container()->factory(data => $element)
528             unless (ref($element) && $element->isa('Class::STL::Element'));
529 0           _usage_check('find', 'IIE', $iter_start, $iter_finish, $element);
530 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
531             {
532 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0          
533             {
534 0 0         if (my $i = find($iter->p_element()->begin(), $iter->p_element()->end(), $element)) # its a tree -- recurse
535             {
536 0           return $i;
537             }
538             }
539             elsif ($element->eq($iter->p_element()))
540             {
541 0           return $iter->clone();
542             }
543             }
544 0           return 0;
545             }
546             sub count_if # (iterator, iterator, unary-function-object) -- static function
547             {
548 0     0 0   _usage_check('count_if', 'IIF', @_);
549 0           my $iter_start = shift;
550 0           my $iter_finish = shift;
551 0           my $function = shift; # unary-function
552 0           my $count=0;
553 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
554             {
555 0 0 0       $count +=
    0          
556             ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
557             ? count_if($iter->p_element()->begin(), $iter->p_element()->end(), $function) # its a tree -- recurse
558             : ($function->function_operator($iter->p_element()) ? 1 : 0);
559             }
560 0           return $count;
561             }
562             sub count # (iterator, iterator, element-ref) -- static function
563             {
564 0     0 0   my $iter_start = shift;
565 0           my $iter_finish = shift;
566 0           my $element = shift;
567 0 0 0       $element = $iter_start->p_container()->factory(data => $element)
568             unless (ref($element) && $element->isa('Class::STL::Element'));
569 0           _usage_check('count', 'IIE', $iter_start, $iter_finish, $element);
570 0           my $count=0;
571 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
572             {
573 0 0 0       $count +=
    0          
574             ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree')
575             ? count($iter->p_element()->begin(), $iter->p_element()->end(), $element) # its a tree -- recurse
576             : ($element->eq($iter->p_element()) ? 1 : 0);
577             }
578 0           return $count;
579             }
580             sub remove_if # (iterator, iterator, unary-function-object) -- static function
581             {
582 0     0 0   _usage_check('remove_if', 'IIF', @_);
583 0           my $iter_start = shift;
584 0           my $iter_finish = shift;
585 0           my $function = shift; # unary-function or class-member-name
586 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; )
587             {
588 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
589             {
590 0           remove_if($iter->p_element()->begin(), $iter->p_element()->end(), $function); # its a tree -- recurse
591 0           ++$iter;
592 0           next;
593             }
594 0 0         $function->function_operator($iter->p_element())
595             ? $iter->p_container()->erase($iter)
596             : ++$iter;
597             }
598 0           return;
599             }
600             sub remove # (iterator, iterator, element-ref) -- static function
601             {
602 0     0 0   my $iter_start = shift;
603 0           my $iter_finish = shift;
604 0           my $element = shift; # element-ref
605 0 0 0       $element = $iter_start->p_container()->factory(data => $element)
606             unless (ref($element) && $element->isa('Class::STL::Element'));
607 0           _usage_check('remove', 'IIE', $iter_start, $iter_finish, $element);
608 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; )
609             {
610 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
611             {
612 0           remove($iter->p_element()->begin(), $iter->p_element()->end(), $element); # its a tree -- recurse
613 0           ++$iter;
614 0           next;
615             }
616 0 0         $element->eq($iter->p_element())
617             ? $iter->p_container()->erase($iter)
618             : ++$iter;
619             }
620 0           return;
621             }
622             sub remove_copy_if # (iterator, iterator, iterator, unary-function-object) -- static function
623             {
624 0     0 0   _usage_check('remove_copy_if', 'IIIF', @_);
625 0           my $iter_start = shift;
626 0           my $iter_finish = shift;
627 0           my $iter_result = shift;
628 0           my $function = shift; # unary-function or class-member-name
629 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
630             {
631 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0          
632             {
633 0           remove_copy_if($iter->p_element()->begin(), $iter->p_element()->end(), $iter_result, $function); # its a tree -- recurse
634             }
635             elsif (!$function->function_operator($iter->p_element()))
636             {
637 0           $iter_result->p_container()->insert($iter_result, 1, $iter->p_element());
638             }
639             }
640 0           return;
641             }
642             sub remove_copy # (iterator, iterator, iterator, element-ref) -- static function
643             {
644 0     0 0   my $iter_start = shift;
645 0           my $iter_finish = shift;
646 0           my $iter_result = shift;
647 0           my $element = shift; # element-ref
648 0 0 0       $element = $iter_start->p_container()->factory(data => $element)
649             unless (ref($element) && $element->isa('Class::STL::Element'));
650 0           _usage_check('remove_copy', 'IIIE', $iter_start, $iter_finish, $iter_result, $element);
651 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
652             {
653 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0          
654             {
655 0           remove_copy($iter->p_element()->begin(), $iter->p_element()->end(), $iter_result, $element); # its a tree -- recurse
656             }
657             elsif (!$element->eq($iter->p_element()))
658             {
659 0           $iter_result->p_container()->insert($iter_result, 1, $iter->p_element());
660             }
661             }
662 0           return;
663             }
664             sub copy # (iterator, iterator, iterator) -- static function
665             {
666 0     0 0   _usage_check('copy', 'III', @_);
667 0           my $iter_start = shift;
668 0           my $iter_finish = shift;
669 0           my $iter_result = shift;
670 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
671             {
672 0           $iter_result->p_container()->insert($iter_result, 1, $iter->p_element());
673             }
674 0           return;
675             }
676             sub copy_backward # (iterator, iterator, iterator) -- static function
677             {
678 0     0 0   _usage_check('copy_backward', 'III', @_);
679 0           my $iter_start = shift;
680 0           my $iter_finish = shift;
681 0           my $iter_result = shift;
682 0           for (my $iter = $iter_finish->clone(); $iter >= $iter_start; --$iter)
683             {
684 0           $iter_result->p_container()->insert($iter_result, 1, $iter->p_element());
685             }
686 0           return;
687             }
688             sub replace_if # (iterator, iterator, unary-function, element-ref) -- static function
689             {
690 0     0 0   my $iter_start = shift;
691 0           my $iter_finish = shift;
692 0           my $function = shift;
693 0           my $new_element = shift; # element-ref
694 0 0 0       $new_element = $iter_start->p_container()->factory(data => $new_element)
695             unless (ref($new_element) && $new_element->isa('Class::STL::Element'));
696 0           _usage_check('replace_if', 'IIFE', $iter_start, $iter_finish, $function, $new_element);
697 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; )
698             {
699 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0          
700             {
701 0           replace_if($iter->p_element()->begin(), $iter->p_element()->end(), $function, $new_element); # its a tree -- recurse
702             }
703             elsif ($function->function_operator($iter->p_element()))
704             {
705 0           $iter->p_container()->erase($iter);
706 0           $iter->p_container()->insert($iter, 1, $new_element);
707             }
708             else
709             {
710 0           ++$iter;
711             }
712             }
713 0           return;
714             }
715             sub replace # (iterator, iterator, element-ref, element-ref) -- static function
716             {
717 0     0 0   my $iter_start = shift;
718 0           my $iter_finish = shift;
719 0           my $old_element = shift; # element-ref
720 0           my $new_element = shift; # element-ref
721 0 0 0       $old_element = $iter_start->p_container()->factory(data => $old_element)
722             unless (ref($old_element) && $old_element->isa('Class::STL::Element'));
723 0 0 0       $new_element = $iter_start->p_container()->factory(data => $new_element)
724             unless (ref($new_element) && $new_element->isa('Class::STL::Element'));
725 0           _usage_check('replace', 'IIEE', $iter_start, $iter_finish, $old_element, $new_element);
726 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; )
727             {
728 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
    0          
729             {
730 0           replace($iter->p_element()->begin(), $iter->p_element()->end(), $old_element, $new_element); # its a tree -- recurse
731             }
732             elsif ($iter->p_element()->eq($old_element))
733             {
734 0           $iter->p_container()->erase($iter);
735 0           $iter->p_container()->insert($iter, 1, $new_element);
736             }
737             else
738             {
739 0           ++$iter;
740             }
741             }
742 0           return;
743             }
744             sub replace_copy_if # (iterator, iterator, iterator, unary-function, element-ref) -- static function
745             {
746 0     0 0   my $iter_start = shift;
747 0           my $iter_finish = shift;
748 0           my $iter_result = shift;
749 0           my $function = shift;
750 0           my $new_element = shift; # element-ref
751 0 0 0       $new_element = $iter_start->p_container()->factory(data => $new_element)
752             unless (ref($new_element) && $new_element->isa('Class::STL::Element'));
753 0           _usage_check('replace_copy_if', 'IIIFE', $iter_start, $iter_finish, $iter_result, $function, $new_element);
754 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
755             {
756 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
757             {
758             #? Insert tree here???
759 0           replace_copy_if($iter->p_element()->begin(), $iter->p_element()->end(), $iter_result, $function, $new_element); # its a tree -- recurse
760             }
761             else
762             {
763 0 0         $iter_result->p_container()->insert($iter_result, 1,
764             ($function->function_operator($iter->p_element()) ? $new_element : $iter->p_element()));
765             }
766             }
767 0           return;
768             }
769             sub replace_copy # (iterator, iterator, iterator, element-ref, element-ref) -- static function
770             {
771 0     0 0   my $iter_start = shift;
772 0           my $iter_finish = shift;
773 0           my $iter_result = shift;
774 0           my $old_element = shift; # element-ref
775 0           my $new_element = shift; # element-ref
776 0 0 0       $old_element = $iter_start->p_container()->factory(data => $old_element)
777             unless (ref($old_element) && $old_element->isa('Class::STL::Element'));
778 0 0 0       $new_element = $iter_start->p_container()->factory(data => $new_element)
779             unless (ref($new_element) && $new_element->isa('Class::STL::Element'));
780 0           _usage_check('replace_copy', 'IIIEE', $iter_start, $iter_finish, $iter_result, $old_element, $new_element);
781 0           for (my $iter = $iter_start->clone(); $iter <= $iter_finish; ++$iter)
782             {
783 0 0 0       if (ref($iter->p_element()) && $iter->p_element()->isa('Class::STL::Containers::Tree'))
784             {
785 0           replace_copy($iter->p_element()->begin(), $iter->p_element()->end(), $iter_result, $old_element, $new_element); # its a tree -- recurse
786             }
787             else
788             {
789 0 0         $iter_result->p_container()->insert($iter_result, 1,
790             ($iter->p_element()->eq($old_element) ? $new_element : $iter->p_element()));
791             }
792             }
793 0           return;
794             }
795             #TODO:sub sort
796             #TODO:{
797             #TODO:}
798             #TODO:sub random_shuffle # ( [ random_number_generator ] )
799             #TODO:{
800             #TODO:}
801             #TODO:sub lower_bound
802             #TODO:{
803             #TODO:}
804             #TODO:sub upper_bound
805             #TODO:{
806             #TODO:}
807             sub _usage_check
808             {
809 7     7   49040 use Carp qw(confess);
  7         34  
  7         2253  
810 0     0     my $function_name = shift;
811 0           my @format = split(//, shift);
812 0           my $check=0;
813 0           foreach my $arg (0..$#_) {
814 0 0 0       confess "Undefined arg $arg"
815             if ($format[$arg] ne 'S' && !ref($_[$arg]));
816 0 0 0       ++$check
      0        
817             if
818             (
819             defined($_[$arg])
820             &&
821             (
822             ($format[$arg] eq 'I' && $_[$arg]->isa('Class::STL::Iterators::Abstract'))
823             || ($format[$arg] eq 'F' && $_[$arg]->isa('Class::STL::Utilities::FunctionObject'))
824             || ($format[$arg] eq 'B' && $_[$arg]->isa('Class::STL::Utilities::FunctionObject::BinaryFunction'))
825             || ($format[$arg] eq 'U' && $_[$arg]->isa('Class::STL::Utilities::FunctionObject::UnaryFunction'))
826             || ($format[$arg] eq 'G' && $_[$arg]->isa('Class::STL::Utilities::FunctionObject::Generator'))
827             || ($format[$arg] eq 'E' && $_[$arg]->isa('Class::STL::Element'))
828             || ($format[$arg] eq 'S' && !ref($_[$arg])) # Scalar
829             )
830             )
831             }
832 0 0         if ($check != int(@_)) {
833 7     7   60 use Carp qw(confess);
  7         15  
  7         2591  
834 0           my @anames;
835 0           foreach (@format) {
836 0 0         push(@anames, 'scalar') if (/S/);
837 0 0         push(@anames, 'iterator') if (/I/);
838 0 0         push(@anames, 'function-object') if (/F/);
839 0 0         push(@anames, 'unary-function-object') if (/U/);
840 0 0         push(@anames, 'generator-function-object') if (/G/);
841 0 0         push(@anames, 'binary-function-object') if (/B/);
842 0 0         push(@anames, 'element-ref') if (/E/);
843             }
844 0           confess "@{[ __PACKAGE__]}::$function_name usage:\n$function_name( @{[ join(', ', @anames) ]});\n"
  0            
  0            
845             }
846 0           return 1;
847             }
848             }
849             # ----------------------------------------------------------------------------------------------------
850             1;