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