File Coverage

blib/lib/Script/Toolbox/Util/Formatter.pm
Criterion Covered Total %
statement 224 320 70.0
branch 75 110 68.1
condition 7 9 77.7
subroutine 28 41 68.2
pod 0 7 0.0
total 334 487 68.5


line stmt bran cond sub pod time code
1             package Script::Toolbox::Util::Formatter;
2              
3 10     10   57 use strict;
  10         14  
  10         268  
4 10     10   42 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  10         14  
  10         32590  
5             #use Script::Toolbox::Util qw(Log);
6              
7             require Exporter;
8              
9             @ISA = qw(Exporter);
10             # Items to export into callers namespace by default. Note: do not export
11             # names by default without a very good reason. Use EXPORT_OK instead.
12             # Do not simply export all your public functions/methods/constants.
13             @EXPORT = qw(
14            
15             );
16             #$VERSION = '0.03';
17              
18              
19             # Preloaded methods go here.
20              
21             #-----------------------------------------------------------------------------
22             #-----------------------------------------------------------------------------
23             sub new
24             {
25 10     10 0 24 my $classname = shift;
26 10         14 my $self = {};
27 10         21 bless( $self, $classname );
28 10         25 $self->_init( @_ );
29 10         20 return $self;
30             }
31              
32             #-----------------------------------------------------------------------------
33             #-----------------------------------------------------------------------------
34             sub _init
35             {
36 10     10   15 my ($self, $container) = @_;
37              
38             $self->{'title'}= defined $container->{'title'} ?
39 10 100       45 $container->{'title'} :
40             'Title';
41              
42 10 100       27 if( ref $container->{'data'} eq 'ARRAY' ) {
43 9 100       21 $self->_initHashArray ( $container ) if( ref $container->{'data'}[0] eq 'HASH' );
44 9 100       29 $self->_initArray ( $container ) if( ref $container->{'data'}[0] eq 'ARRAY');
45             }
46              
47 10 100       22 if( ref $container->{'data'} eq 'HASH' ) {
48 1 50       11 $self->_initHashHash ( $container ) if( ref $container->{'data'} eq 'HASH' );
49             }
50              
51             $self->{'head'} = defined $container->{'head'} ?
52 10 100       33 $container->{'head'} :
53             _getDefaultHeader($container);
54              
55              
56             }
57              
58             #------------------------------------------------------------------------------
59             # Extract column keys from first data row.
60             # 'data' => {
61             # key1 => {F1=>'aaa', F2=>'bb ', F3=>3}
62             # key2 => {F1=>11111, F2=>2222222, F3=>3}
63             # }
64             #------------------------------------------------------------------------------
65             sub _getHeadsFromFirstRow($)
66             {
67 1     1   3 my ($data) = @_;
68 1         1 my @H;
69 1         6 push( @H, "KEY" );
70 1         2 foreach my $d ( values %{$data} )
  1         6  
71             {
72 1         2 map{ push( @H, $_ ) } sort keys %{$d};
  3         14  
  1         9  
73 1         3 last;
74             }
75             #return \@H;
76 1         5 return @H;
77             }
78              
79             #------------------------------------------------------------------------------
80             # 'title' => 'Test1',
81             # 'head' => ['RowKey', Field1', 'Field2', 'Field3'],
82             # 'data' => {
83             # key1 => {F1=>'aaa', F2=>'bb ', F3=>3}
84             # key2 => {F1=>11111, F2=>2222222, F3=>3}
85             # }
86             #------------------------------------------------------------------------------
87             sub _initHashHash($$)
88             {
89 1     1   6 my ($self,$container) = @_;
90              
91 1 50       5 if( ref $container->{'data'} eq 'HASH' )
92             {
93 1         4 @{$self->{'head'}} = _getHeadsFromFirstRow( $container->{'data'} );
  1         4  
94 1         4 my @D;
95 1         3 foreach my $lk ( sort keys %{$container->{'data'}} )
  1         7  
96             {
97 2         4 my $l = $container->{'data'}{$lk};
98 2         3 my @L;
99 2         2 foreach my $k ( @{$self->{'head'}} )
  2         4  
100             {
101             # auto generated meta column
102 8 100       14 if( $k eq 'KEY' ) { push @L,$lk; next }
  2         3  
  2         4  
103              
104 6 50       10 $self->_logit( $k, $l ) if( !defined $l->{$k} );
105 6         9 push @L, $l->{$k};
106             }
107 2         5 push @D, \@L;
108             }
109 1         3 $self->{data} = \@D;
110             }
111             }
112              
113             #------------------------------------------------------------------------------
114             # 'title' => 'Test1',
115             # 'head' => ['Feld1', 'Feld2', 'Feld3'],
116             # 'data' => [
117             # [ 'aaa', 'bb ', 'cc ' ],
118             # [ 11111, 2222222, 3 ]
119             # ]
120             # OR data part
121             # 'data' => [
122             # {F1=>'aaa', F2=>'bb ', F3=>3}
123             # {F1=>11111, F2=>2222222, F3=>3}
124             # ]
125             #------------------------------------------------------------------------------
126             sub _initHashArray($$)
127             {
128 1     1   2 my ($self,$container) = @_;
129 1         4 $self->{'data'} = $self->_getData($container);
130             }
131              
132             #------------------------------------------------------------------------------
133             # [
134             # 'title',
135             # ['COL-HEAD','COL-HEAD2','COL-HEAD3'],
136             # [1, 2, 3],
137             # [4, 5, 6],
138             # ]
139             # OR:
140             # [
141             # [1, 2, 3],
142             # [4, 5, 6],
143             # ]
144             # OR:
145             # 'data' => [
146             # {F1=>'aaa', F2=>'bb ', F3=>3}
147             # {F1=>11111, F2=>2222222, F3=>3}
148             # ]
149             #------------------------------------------------------------------------------
150             sub _initArray($$)
151             {
152 7     7   13 my ($self,$container) = @_;
153              
154 7         11 $self->{'data'} = $container->{'data'};
155             }
156              
157             #------------------------------------------------------------------------------
158             #------------------------------------------------------------------------------
159             sub _getData($$)
160             {
161 1     1   3 my ($self, $container) = @_;
162              
163 1 50       3 return [] if( !defined $container->{'data'}[0] );
164 1 50       4 return $container if( ref($container->{'data'}[0]) eq 'ARRAY' );
165 1 50       13 if( ref($container->{'data'}[0]) eq 'HASH' )
166             {
167 1         3 @{$self->{'head'}} = sort keys %{$container->{'data'}[0]};
  1         7  
  1         5  
168 1         8 my @D;
169 1         2 foreach my $l ( @{$container->{'data'}} )
  1         6  
170             {
171 2         4 my @L;
172 2         3 foreach my $k ( @{$self->{'head'}} )
  2         3  
173             {
174 6 50       14 $self->_logit( $k, $l ) if( !defined $l->{$k} );
175 6         10 push @L, $l->{$k};
176             }
177 2         4 push @D, \@L;
178             }
179 1         3 return \@D;
180             }
181             }
182              
183             #------------------------------------------------------------------------------
184             #------------------------------------------------------------------------------
185             sub _logit($$)
186             {
187 0     0   0 my ($self,$k,$line) = @_;
188              
189             print STDERR
190             "Warning: inconsistent data hash, missing key $k in line: " .
191 0         0 join ";", each %{$line};
  0         0  
192             }
193             #------------------------------------------------------------------------------
194             #------------------------------------------------------------------------------
195             sub _getDefaultHeader($)
196             {
197 6     6   11 my ($cont) = @_;
198 6         7 my @hd;
199              
200 6 100       14 if( ref $cont->{'data'} eq 'ARRAY' ) {
201 5 100       11 if( ref $cont->{'data'}[0] eq 'HASH' ) {
202 1         2 foreach my $h ( sort keys %{$cont->{'data'}[0]} ) { push @hd, $h; }
  1         7  
  3         7  
203             }
204 5 100       12 if( ref $cont->{'data'}[0] eq 'ARRAY') {
205 4         16 for( my $i=0; $i <= $#{$cont->{'data'}[0]}; $i++ ) { push @hd, "Col-$i"; }
  12         35  
  16         39  
206             }
207             }
208              
209             # 'data' => {
210             # 'line1' => { 'F1' => 'aaaa', 'F2' => 'bbb ', 'F3' => 'c' },
211             # 'line2' => { 'F1' => 'dddd', 'F2' => 'eee ', 'F3' => 'f' }
212             # }
213 6 100       17 if( ref $cont->{'data'} eq 'HASH' ) {
214 1         2 foreach my $line ( values %{$cont->{'data'}} )
  1         2  
215             {
216 1         6 push @hd, "KEY";
217 1         15 foreach my $fldName ( sort keys %{$line} )
  1         4  
218             {
219 3         6 push @hd, $fldName;
220             }
221 1         2 last;
222             }
223             }
224              
225 6         16 return \@hd;
226             }
227              
228             #-----------------------------------------------------------------------------
229             #-----------------------------------------------------------------------------
230             sub matrix
231             {
232 10     10 0 19 my ($self) = @_;
233 10 100       28 return [] if( !defined $self->{'data'} );
234 9 50       13 return [] if( scalar @{$self->{'data'}} == 0 );
  9         25  
235              
236 9         16 my @result;
237 9         31 $self->_matrix( \@result );
238 9         39 return \@result ;
239             }
240              
241             #-----------------------------------------------------------------------------
242             #-----------------------------------------------------------------------------
243             sub _matrix
244             {
245 9     9   12 my ($self, $result) = @_;
246              
247 9         22 my @maxColW = $self->_maxColWidth();
248 9         21 my $format = $self->_getFormat( \@maxColW );
249 9         14 my $formatHd= $format;
250 9         43 $formatHd=~ s/([.]\d*)?[df]/s/g;
251              
252 9         12 push @{$result}, sprintf "== %s ==", $self->{'title'};
  9         33  
253 9         12 push @{$result}, sprintf $formatHd, @{$self->{'head'}};
  9         14  
  9         26  
254 9         13 push @{$result}, _underline( @maxColW );
  9         21  
255              
256 24         31 map { push @{$result},
  24         42  
257 9         10 sprintf $format, _getLineArray($_); } @{$self->{'data'}};
  9         17  
258             }
259              
260             #-----------------------------------------------------------------------------
261             #-----------------------------------------------------------------------------
262             sub _underline
263             {
264 9     9   34 my (@maxColWidth) = @_;
265              
266 9         12 my $x;
267 9         16 map { $_ =~s/([.]\d+)?[fds]$//;
  28         97  
268 28         57 $_ =~s/-//;
269 28         105 $x .= sprintf "%s ", '-' x $_ } @maxColWidth;
270              
271 9         25 $x =~ s/\s$//;
272 9         21 return $x;
273             }
274             #-----------------------------------------------------------------------------
275             #-----------------------------------------------------------------------------
276             sub _getLineArray
277             {
278 24     24   39 my ($line) = @_;
279              
280 24 50       46 return @{$line} if( ref $line eq 'ARRAY' );
  24         152  
281              
282 0 0       0 if( ref $line eq 'HASH' )
283             {
284 0         0 my @R;
285 0         0 foreach my $key ( sort keys %{$line} ) {
  0         0  
286 0         0 push @R, ${$line}{$key};
  0         0  
287             }
288 0         0 return @R;
289             }
290             }
291              
292             #-----------------------------------------------------------------------------
293             #-----------------------------------------------------------------------------
294             sub _getFormat
295             {
296 9     9   15 my ($self, $maxColWidth ) = @_;
297              
298 9         21 my $form='';
299 9         22 _mkFloatLen( $maxColWidth );
300 9         13 foreach my $f ( @{$maxColWidth} )
  9         18  
301             {
302 28 100       83 $f = '-' . $f if( $f =~ /s$/ );
303 28         70 $form .= sprintf "%%%s ", $f;
304             }
305 9         38 $form =~ s/\s$//;
306 9         21 return $form;
307             }
308              
309             #------------------------------------------------------------------------------
310             #------------------------------------------------------------------------------
311             sub _mkFloatLen($)
312             {
313 9     9   12 my ($maxColRef) = @_;
314              
315 9         10 for( my $i=@{$maxColRef}-1; $i >= 0; $i-- )
  9         25  
316             {
317 28 100       32 if( ${$maxColRef}[$i] =~ /(\d+)[.](\d+)f$/ )
  28         71  
318             {
319 6         11 my $len = $1;
320 6         9 my $dig = $2;
321 6         12 ${$maxColRef}[$i] = $len+$dig+1 .'.'. $dig .'f';
  6         13  
322             }
323             }
324             }
325              
326             #-----------------------------------------------------------------------------
327             #-----------------------------------------------------------------------------
328             sub _maxColWidth
329             {
330 9     9   13 my ($self) = @_;
331 9         15 my @maxColWidth;
332              
333             my @X;
334 9         19 push @X, $self->{'head'};
335 9         11 map { push @X, $_ } @{$self->{'data'}};
  24         35  
  9         22  
336 9         14 my $i=0;
337 9         19 foreach my $line ( @X )
338             {
339 33 100       58 next if( $i++ == 0 );
340 24 50       38 _maxColHashLine( $line, \@maxColWidth ) if( ref $line eq 'HASH' );
341 24 50       64 _maxColArrayLine($line, \@maxColWidth ) if( ref $line eq 'ARRAY');
342             }
343 9         21 _checkMaxHeader( $X[0], \@maxColWidth );
344 9         28 return @maxColWidth;
345             }
346              
347             #------------------------------------------------------------------------------
348             #------------------------------------------------------------------------------
349             sub _checkMaxHeader($$)
350             {
351 9     9   12 my ($line, $maxColWidth) = @_;
352              
353 9         27 for( my $i=0; $i<= $#{$line}; $i++ )
  37         63  
354             {
355 28         34 _trimBlanks( \${$line}[$i] );
  28         56  
356 28         56 ${$maxColWidth}[$i] = _getMaxColWidthHead(${$maxColWidth}[$i],
  28         37  
357 28         33 ${$line}[$i] );
  28         39  
358             }
359             }
360              
361             #------------------------------------------------------------------------------
362             #------------------------------------------------------------------------------
363             sub _getMaxColWidthHead($$)
364             {
365 28     28   45 my ($old,$new) = @_;
366              
367 28         41 my $nl= length( $new );
368 28         75 $old =~ /(\d+)[.]?(\d*)([fds])/; my ($ol,$od, $ot) = ($1,$2,$3);
  28         76  
369              
370 28 100       53 return stringType($nl,$ol) if($ot eq 's' );
371 12 100       25 return floatType($nl,0,$ol,$od) if($ot eq 'f');
372 6 50       12 return intType($nl,$ol) if($ot eq 'd' );
373              
374 0         0 printf STDERR "ERROR format\n";
375 0         0 return 0;
376             }
377              
378              
379             #-----------------------------------------------------------------------------
380             #-----------------------------------------------------------------------------
381             sub _maxColArrayLine
382             {
383 24     24   37 my ($line, $maxColWidth) = @_;
384 24         32 for( my $i=0; $i<= $#{$line}; $i++ )
  98         183  
385             {
386 74         87 _trimBlanks( \${$line}[$i] );
  74         161  
387 74         86 my $type= _getTypeLen( ${$line}[$i] );
  74         124  
388 74         93 ${$maxColWidth}[$i] = _getMaxColWidth(${$maxColWidth}[$i], $type);
  74         142  
  74         125  
389             }
390             }
391              
392             #------------------------------------------------------------------------------
393             #------------------------------------------------------------------------------
394             sub _getMaxColWidth($$)
395             {
396 74     74   126 my ($old,$new) = @_;
397              
398 74         184 $new =~ /(\d+)[.]?(\d*)([fds])/; my ($nl,$nd, $nt) = ($1,$2,$3);
  74         189  
399 74 100       120 $old = $new if( !defined $old );
400 74         145 $old =~ /(\d+)[.]?(\d*)([fds])/; my ($ol,$od, $ot) = ($1,$2,$3);
  74         141  
401              
402 74 100 100     203 return stringType($nl,$ol) if($nt eq 's' || $ot eq 's' );
403 36 100 100     90 return floatType($nl,$nd,$ol,$od) if($nt eq 'f' || $ot eq 'f');
404 24 50 33     81 return intType($nl,$ol) if($nt eq 'd' && $ot eq 'd' );
405              
406 0         0 printf STDERR "ERROR format\n";
407 0         0 return 0;
408             }
409              
410             #------------------------------------------------------------------------------
411             #------------------------------------------------------------------------------
412             sub intType($$)
413             {
414 30     30 0 48 my ($nl,$ol) = @_;
415 30 100       50 my $len = $nl > $ol ? $nl : $ol;
416 30         58 return $len . 'd';
417             }
418             #------------------------------------------------------------------------------
419             #------------------------------------------------------------------------------
420             sub floatType($$$$$$)
421             {
422 18     18 0 32 my ($nl,$nd,$ol,$od) = @_;
423 18 50       29 $nl = $nl eq '' ? 0 : $nl;
424 18 100       27 $nd = $nd eq '' ? 0 : $nd;
425 18 100       23 $od = $od eq '' ? 0 : $od;
426 18 50       23 $ol = $ol eq '' ? 0 : $ol;
427 18 100       30 my $len = $nl > $ol ? $nl : $ol;
428 18 100       45 my $dig = $nd > $od ? $nd : $od;
429              
430 18         42 return $len .'.'. $dig .'f';
431             }
432              
433             #------------------------------------------------------------------------------
434             #------------------------------------------------------------------------------
435             sub stringType($$)
436             {
437 54     54 0 83 my ($nl,$ol) = @_;
438 54 100       93 my $len = $nl > $ol ? $nl : $ol;
439              
440 54         105 return $len .'s';
441             }
442              
443             #------------------------------------------------------------------------------
444             #------------------------------------------------------------------------------
445             sub _getTypeLen($)
446             {
447 74     74   104 my ($field) = @_;
448              
449 74         79 my $type;
450 74 100       99 $type = _isFloat($field); return $type if( defined $type );
  74         121  
451 68 100       85 $type = _isInt($field); return $type if( defined $type );
  68         131  
452              
453 29         65 return length($field) .'s';
454             }
455              
456             #------------------------------------------------------------------------------
457             #------------------------------------------------------------------------------
458             sub _isInt($)
459             {
460 68     68   101 my ($field) = @_;
461 68 100       196 return undef if( $field !~ /^[-]?\d+$/ );
462 39         83 return length($field) .'d';
463             }
464              
465             #------------------------------------------------------------------------------
466             #------------------------------------------------------------------------------
467             sub _isFloat($)
468             {
469 74     74   103 my ($field) = @_;
470 74 100       177 return undef if( $field !~ /^[-]?(\d+)[.](\d*)$/ );
471              
472 6         11 my $int = $1; my $li = length($int);
  6         60  
473 6         9 my $frac= $2; my $lf = length($frac);
  6         9  
474              
475 6         48 my $form= $li+$lf+1 .'.'. $lf .'f';
476              
477 6         19 return $form;
478             }
479             #-----------------------------------------------------------------------------
480             #-----------------------------------------------------------------------------
481             sub _maxColHashLine
482             {
483 0     0   0 my ($line, $maxColWidth) = @_;
484 0         0 my $i=0;
485 0         0 foreach my $key ( sort keys %{$line} )
  0         0  
486             {
487 0         0 _trimBlanks( \${$line}{$key} );
  0         0  
488 0         0 my $type= _getTypeLen( ${$line}{$key} );
  0         0  
489 0         0 ${$maxColWidth}[$i] = _getMaxColWidth(${$maxColWidth}[$i], $type);
  0         0  
  0         0  
490 0         0 $i++;
491             }
492             }
493             #-----------------------------------------------------------------------------
494             #-----------------------------------------------------------------------------
495             sub _trimBlanks
496             {
497 102     102   128 my ($field) = @_;
498              
499 102         227 $$field =~ s/^\s+//;
500 102         187 $$field =~ s/\s+$//;
501              
502 102         134 return length( $$field );
503             }
504              
505             #------------------------------------------------------------------------------
506             #------------------------------------------------------------------------------
507             sub sumBy()
508             {
509 0     0 0   my ($self, $raw, $colIdxRef, $notGroupBy) = @_;
510 0           my $colIdx = $colIdxRef->[0]; #FIXME may be more than one colum in future
511              
512 0           my @LEN = _getColLen( $raw->[2] );
513 0           my $fmt = _getSumFormat( $raw->[3],$colIdx,@LEN );
514 0           my $pattern = _getSplitPattern(@LEN);
515 0           my $sum = 0;
516 0           my $gSum= _getSumField( $raw->[3],$pattern, $colIdx );
517              
518 0           my $old = $raw->[3];
519 0           my @NEW = @{$raw}[0..3];
  0            
520              
521 0           for( my $i=4; $i <= $#{$raw}; $i++ )
  0            
522             {
523 0 0         push @NEW, _endGroup(\$gSum,$fmt,\$sum)
524             if( _isGroupEnd($raw,$i,$colIdx,$pattern,$notGroupBy));
525 0           $gSum += _getSumField( $raw->[$i],$pattern, $colIdx );
526 0           push @NEW, $raw->[$i];
527             }
528 0           push @NEW, sprintf $fmt, $gSum;
529 0           push @NEW, sprintf $fmt, $sum;
530 0           return \@NEW;
531             }
532              
533             #------------------------------------------------------------------------------
534             #------------------------------------------------------------------------------
535             sub _endGroup($$)
536             {
537 0     0     my ($sumRef, $fmt, $totSumRef) = @_;
538            
539 0           my $line = sprintf $fmt, $$sumRef;
540 0           $$totSumRef += $$sumRef;
541 0           $$sumRef = 0;
542              
543 0           return $line;
544             }
545              
546             #------------------------------------------------------------------------------
547             #------------------------------------------------------------------------------
548             sub _isGroupEnd($$$$)
549             {
550 0     0     my ($raw,$currIdx,$colIdx,$pattern,$notGroupBy) = @_;
551              
552 0           my @PREV = _getSplitedLine($raw->[$currIdx-1],$pattern);
553 0           my @CURR = _getSplitedLine($raw->[$currIdx], $pattern);
554 0           for( my $i=0; $i <= $#CURR; $i++ )
555             {
556 0 0         next if( _noGroupCol($i,$colIdx,$notGroupBy) );
557 0 0         return 1 if( $PREV[$i] ne $CURR[$i] );
558             }
559 0           return 0;
560             }
561              
562             #------------------------------------------------------------------------------
563             #------------------------------------------------------------------------------
564             sub _noGroupCol($$$)
565             {
566 0     0     my ($idx,$sumIdx,$notGroupBy) = @_;
567              
568 0 0         return 1 if( $idx == $sumIdx );
569 0 0         return 0 if( !defined $notGroupBy );
570              
571 0 0         foreach my $col ( @{$notGroupBy} ) { return 1 if( $col == $idx ); }
  0            
  0            
572 0           return 0;
573             }
574             #------------------------------------------------------------------------------
575             #------------------------------------------------------------------------------
576             sub _getSumField($$$)
577             {
578 0     0     my ($line,$pattern,$idx) = @_;
579              
580 0           my @L = _getSplitedLine($line,$pattern);
581 0           return $L[$idx];
582             }
583              
584             #------------------------------------------------------------------------------
585             #------------------------------------------------------------------------------
586             sub _getSumFormat($$@)
587             {
588 0     0     my ($line, $colIdx, @LEN) = @_;
589              
590 0           my $form='';
591 0           for( my $i=0; $i <= $#LEN; $i++ )
592             {
593 0 0         if( $i == $colIdx ) { $form .= _getSumColForm($line, $colIdx, @LEN); }
  0            
594 0           else { $form .= sprintf "%s ", ' ' x $LEN[$i]; }
595             }
596 0           return $form;
597             }
598              
599             #------------------------------------------------------------------------------
600             #------------------------------------------------------------------------------
601             sub _getSumColForm($$@)
602             {
603 0     0     my ($line, $colIdx, @LEN) = @_;
604              
605 0           my $pattern = _getSplitPattern(@LEN);
606 0           my @splited = _getSplitedLine($line,$pattern);
607 0           my $sumField= $splited[$colIdx];
608 0           my @I = $sumField =~ /(\d+)([.]?)(\d*)/;
609 0           my $decimal = $I[2];
610              
611 0 0         return '%'. $LEN[$colIdx] .
612             '.'. length($decimal) .'f' if( $I[1] eq '.' );
613              
614 0           return '%'. $LEN[$colIdx] .'d';
615             }
616              
617             #------------------------------------------------------------------------------
618             #------------------------------------------------------------------------------
619             sub _getSplitedLine($$)
620             {
621 0     0     my ($line,$pattern) = @_;
622 0           return $line =~ m/$pattern/;
623             }
624              
625             #------------------------------------------------------------------------------
626             #------------------------------------------------------------------------------
627             sub _getSplitPattern(@)
628             {
629 0     0     my (@LEN) = @_;
630              
631 0           return join ' ', map { '(.{'. $_ .'})' } @LEN;
  0            
632             }
633              
634             #------------------------------------------------------------------------------
635             #------------------------------------------------------------------------------
636             sub _getColLen
637             {
638 0     0     my ($cols) = @_;
639              
640 0           my @len;
641 0           foreach my $col ( split /\s+/, $cols )
642             {
643 0           push @len, length $col;
644             }
645 0           return @len;
646             }
647              
648             #------------------------------------------------------------------------------
649             #------------------------------------------------------------------------------
650             sub newGroup($$$)
651             {
652 0     0 0   my ($O, $L, $idx) = @_;
653              
654 0           foreach my $i ( @{$idx} )
  0            
655             {
656 0 0         return 1 if( $O->[$i] ne $L->[$i] );
657             }
658 0           return 0;
659             }
660              
661             1;
662             __END__