File Coverage

blib/lib/Sort/Key/Merger.pm
Criterion Covered Total %
statement 118 121 97.5
branch 21 30 70.0
condition 2 4 50.0
subroutine 23 24 95.8
pod 4 4 100.0
total 168 183 91.8


line stmt bran cond sub pod time code
1             package Sort::Key::Merger;
2              
3             our $VERSION = '0.08';
4              
5 2     2   56344 use strict;
  2         5  
  2         156  
6 2     2   11 use warnings;
  2         5  
  2         60  
7 2     2   18 use Carp;
  2         10  
  2         332  
8              
9             require Exporter;
10             our @ISA = qw(Exporter);
11             our @EXPORT_OK = qw(keymerger nkeymerger
12             filekeymerger nfilekeymerger);
13              
14             require XSLoader;
15             XSLoader::load('Sort::Key::Merger', $VERSION);
16              
17 2     2   10 use constant STR_SORT => 0;
  2         2  
  2         132  
18 2     2   15 use constant LOC_STR_SORT => 1;
  2         4  
  2         93  
19 2     2   10 use constant NUM_SORT => 2;
  2         4  
  2         222  
20 2     2   78 use constant INT_SORT => 3;
  2         6  
  2         78  
21              
22 2     2   9 use constant KEY => 0;
  2         4  
  2         94  
23 2     2   11 use constant KEY1 => 1;
  2         3  
  2         86  
24 2     2   24 use constant VALUE => 2;
  2         3  
  2         74  
25 2     2   9 use constant FILE => 3;
  2         4  
  2         82  
26 2     2   12 use constant SCRATCHPAD => 4;
  2         3  
  2         131  
27 2     2   10 use constant RS => 4;
  2         3  
  2         185  
28              
29             my ($int_hints, $locale_hints);
30             BEGIN {
31 2     2   2311 use integer;
  2         20  
  2         10  
32 2   50 2   132 $int_hints = $integer::hint_bits || 0x1;
33              
34 2     2   2127 use locale;
  2         499  
  2         9  
35 2   50     2404 $locale_hints = $locale::hint_bits || 0x4;
36              
37             # print STDERR "locale: $locale_hints, int: $int_hints\n";
38             }
39              
40             sub _merger_maker {
41 48     48   337 my ($cmp, $sub, @args)=@_;
42 48         89 my @src;
43 48         77 my $i=0;
44 48         109 for (@args) {
45 2028         3904 my $scratchpad;
46 2028 100       2098 if (my ($k, $v) = &{$sub}($scratchpad)) {
  2028         3712  
47 1390         11516 unshift @src, [$k, $i++, $v, $_, $scratchpad];
48 1390         12193 _resort($cmp, \@src);
49             }
50             }
51 48         140 my $gen;
52             $gen = sub {
53 42572 100   42572   62668 if (wantarray) {
54 48         62 my @all;
55             my $next;
56 48         200 while(defined($next = &$gen)) {
57 42476         77817 push @all, $next;
58             }
59 48         10213 return @all;
60             }
61             else {
62 42524         38910 my $old_v;
63 42524 100       74529 if (@src) {
64 42476         45594 my $src=$src[KEY];
65 42476         50120 $old_v=$src->[VALUE];
66 42476         66997 for ($src[0][FILE]) {
67 42476 100       49614 if (my @kv = &{$sub}($src->[SCRATCHPAD])) {
  42476         90131  
68 41086 50       308493 @kv == 2 or croak 'wrong number of return values from merger callback';
69 41086         46923 @{$src}[KEY, VALUE] = @kv;
  41086         66767  
70 41086         435244 _resort($cmp, \@src);
71             }
72             else {
73 1390         8521 shift @src;
74             }
75             }
76             }
77 42524         137101 return $old_v;
78             }
79 48         516 };
80             }
81              
82             sub keymerger (&@) {
83 16 50   16 1 289295 my $sort = ((caller(0))[8] & $locale_hints)
84             ? LOC_STR_SORT : STR_SORT;
85 16         76 _merger_maker( $sort, @_ )
86             }
87              
88             sub nkeymerger (&@) {
89 32 100   32 1 888112 my $sort = ((caller(0))[8] & $int_hints)
90             ? INT_SORT : NUM_SORT;
91 32         154 _merger_maker( $sort, @_ )
92             }
93              
94              
95              
96             sub _file_merger_maker {
97 2     2   5 my ($cmp, $sub, @args)=@_;
98 2         21 my @src;
99 2         3 my $i = 0;
100 2         3 for my $file (@args) {
101 4         4 my $fh;
102 4 50       15 if (UNIVERSAL::isa($file, 'GLOB')) {
103 0         0 $fh=$file;
104             }
105             else {
106 4 50       118 open $fh, '<', $file
107             or croak "unable to open '$file'";
108             }
109 4         13 local $/ = $/;
110 4         5 local $_;
111 4         72 while(<$fh>) {
112 4 50       4 if (defined(my $k = &{$sub})) {
  4         11  
113 4         29 unshift @src, [$k, $i++, $_, $fh, $/];
114 4         12 _resort($cmp, \@src);
115 4         13 last;
116             }
117             }
118             }
119              
120             # print Dumper(\@src);
121              
122 2         2 my $gen;
123             $gen = sub {
124 62 100   62   18482 if (wantarray) {
125 1         1 my @all;
126 1         6 while(@src) {
127 30         45 push @all, scalar(&$gen);
128             }
129 1         19 return @all;
130             }
131             else {
132 61 100       117 if (@src) {
133 60         61 my $src=$src[0];
134 60         83 my $old_v=$src->[VALUE];
135 60         79 local *_ = \($src->[VALUE]);
136 60         67 local */ = \($src->[RS]); # emacs syntax higlighting breaks here/;
137 60         57 my $fh=$src->[FILE];
138 60         158 while(<$fh>) {
139 56 50       50 if (defined ($src->[KEY]=&{$sub})) {
  56         105  
140 56         282 _resort($cmp, \@src);
141 56         166 return $old_v;
142             }
143             }
144 4         7 shift @src;
145 4         63 return $old_v;
146             }
147             return undef
148 1         3 }
149 2         18 };
150             }
151              
152              
153             sub filekeymerger (&@) {
154 0 0   0 1 0 my $sort = ((caller(0))[8] & $locale_hints)
155             ? LOC_STR_SORT : STR_SORT;
156 0         0 _file_merger_maker( $sort, @_ )
157             }
158              
159             sub nfilekeymerger (&@) {
160 2 50   2 1 31 my $sort = ((caller(0))[8] & $int_hints)
161             ? INT_SORT : NUM_SORT;
162 2         6 _file_merger_maker( $sort, @_ )
163             }
164              
165              
166             1;
167             __END__