File Coverage

blib/lib/IO/Callback.pm
Criterion Covered Total %
statement 208 221 94.1
branch 128 144 88.8
condition 46 51 90.2
subroutine 28 30 93.3
pod 1 20 5.0
total 411 466 88.2


line stmt bran cond sub pod time code
1             package IO::Callback;
2              
3 17     17   3217288 use warnings;
  17         49  
  17         766  
4 17     17   99 use strict;
  17         34  
  17         1642  
5              
6             =head1 NAME
7              
8             IO::Callback - Emulate file interface for a code reference
9              
10             =head1 VERSION
11              
12             Version 1.12
13              
14             =cut
15              
16             our $VERSION = '1.12';
17              
18             =head1 SYNOPSIS
19              
20             C provides an easy way to produce a phoney read-only filehandle that calls back to your own code when it needs data to satisfy a read. This is useful if you want to use a library module that expects to read data from a filehandle, but you want the data to come from some other source and you don't want to read it all into memory and use L.
21              
22             use IO::Callback;
23              
24             my $fh = IO::Callback->new('<', sub { ... ; return $data });
25             my $object = Some::Class->new_from_file($fh);
26              
27             Similarly, IO::Callback allows you to wrap up a coderef as a write-only filehandle, which you can pass to a library module that expects to write its output to a filehandle.
28              
29             my $fh = IO::Callback->new('>', sub { my $data = shift ; ... });
30             $object->dump_to_file($fh);
31              
32              
33             =head1 CONSTRUCTOR
34              
35             =head2 C
36              
37             Returns a filehandle object encapsulating the coderef.
38              
39             MODE must be either C> for a read-only filehandle or C> for a write-only filehandle.
40              
41             For a read-only filehandle, the callback coderef will be invoked in a scalar context each time more data is required to satisfy a read. It must return some more input data (at least one byte) as a string. If there is no more data to be read, then the callback should return either C or the empty string. If ARG values were supplied to the constructor, then they will be passed to the callback each time it is invoked.
42              
43             For a write-only filehandle, the callback will be invoked each time there is data to be written. The first argument will be the data as a string, which will always be at least one byte long. If ARG values were supplied to the constructor, then they will be passed as additional arguments to the callback. When the filehandle is closed, the callback will be invoked once with the empty string as its first argument.
44              
45             To simulate a non-fatal error on the file, the callback should set C<$!> and return the special value C. See examples 6 and 7 below.
46              
47             =head1 EXAMPLES
48              
49             =over 4
50              
51             =item Example 1
52              
53             To generate a filehandle from which an infinite number of C characters can be read:
54              
55             =for test "ex1" begin
56              
57             my $fh = IO::Callback->new('<', sub {"xxxxxxxxxxxxxxxxxxxxxxxxxxx"});
58              
59             my $x = $fh->getc; # $x now contains "x"
60             read $fh, $x, 5; # $x now contains "xxxxx"
61              
62             =for test "ex1" end
63              
64             =item Example 2
65              
66             A filehandle from which 1000 C lines can be read before EOF:
67              
68             =for test "ex2" begin
69              
70             my $count = 0;
71             my $fh = IO::Callback->new('<', sub {
72             return if ++$count > 1000; # EOF
73             return "foo\n";
74             });
75              
76             my $x = <$fh>; # $x now contains "foo\n"
77             read $fh, $x, 2; # $x now contains "fo"
78             read $fh, $x, 2; # $x now contains "o\n"
79             read $fh, $x, 20; # $x now contains "foo\nfoo\nfoo\nfoo\nfoo\n"
80             my @foos = <$fh>; # @foos now contains ("foo\n") x 993
81              
82             =for test "ex2" end
83              
84             The example above uses a C (a special kind of anonymous sub, see L) to allow the callback to keep track of how many lines it has returned. You don't have to use a closure if you don't want to, since C will forward extra constructor arguments to the callback. This example could be re-written as:
85              
86             =for test "ex2a" begin
87              
88             my $count = 0;
89             my $fh = IO::Callback->new('<', \&my_callback, \$count);
90              
91             my $x = <$fh>; # $x now contains "foo\n"
92             read $fh, $x, 2; # $x now contains "fo"
93             read $fh, $x, 2; # $x now contains "o\n"
94             read $fh, $x, 20; # $x now contains "foo\nfoo\nfoo\nfoo\nfoo\n"
95             my @foos = <$fh>; # @foos now contains ("foo\n") x 993
96              
97             sub my_callback {
98             my $count_ref = shift;
99              
100             return if ++$$count_ref > 1000; # EOF
101             return "foo\n";
102             };
103              
104             =for test "ex2a" end
105              
106             =item Example 3
107              
108             To generate a filehandle interface to data drawn from an SQL table:
109              
110             =for test "ex3" begin
111              
112             my $sth = $dbh->prepare("SELECT ...");
113             $sth->execute;
114             my $fh = IO::Callback->new('<', sub {
115             my @row = $sth->fetchrow_array;
116             return unless @row; # EOF
117             return join(',', @row) . "\n";
118             });
119              
120             # ...
121              
122             =for test "ex3" end
123              
124             =item Example 4
125              
126             You want a filehandle to which data can be written, where the data is discarded but an exception is raised if the data includes the string C.
127              
128             =for test "ex4" begin
129              
130             my $buf = '';
131             my $fh = IO::Callback->new('>', sub {
132             $buf .= shift;
133             die "foo written" if $buf =~ /foo/;
134              
135             if ($buf =~ /(fo?)\z/) {
136             # Part way through a "foo", carry over to the next block.
137             $buf = $1;
138             } else {
139             $buf = '';
140             }
141             });
142              
143             =for test "ex4" end
144              
145             =item Example 5
146              
147             You have been given an object with a copy_data_out() method that takes a destination filehandle as an argument. You don't want the data written to a file though, you want it split into 1024-byte blocks and inserted into an SQL database.
148              
149             =for test "ex5" begin
150              
151             my $blocksize = 1024;
152             my $sth = $dbh->prepare('INSERT ...');
153              
154             my $buf = '';
155             my $fh = IO::Callback->new('>', sub {
156             $buf .= shift;
157             while (length $buf >= $blocksize) {
158             $sth->execute(substr $buf, 0, $blocksize, '');
159             }
160             });
161              
162             $thing->copy_data_out($fh);
163              
164             if (length $buf) {
165             # There is a remainder of < $blocksize
166             $sth->execute($buf);
167             }
168              
169             =for test "ex5" end
170              
171             =item Example 6
172              
173             You're testing some code that reads data from a file, you want to check that it behaves as expected if it gets an IO error part way through the file.
174              
175             =for test "ex6" begin
176              
177             use IO::Callback;
178             use Errno qw/EIO/;
179              
180             my $block1 = "x" x 10240;
181             my $block2 = "y" x 10240;
182             my @blocks = ($block1, $block2);
183              
184             my $fh = IO::Callback->new('<', sub {
185             return shift @blocks if @blocks;
186             $! = EIO;
187             return IO::Callback::Error;
188             });
189              
190             # ...
191              
192             =for test "ex6" end
193              
194             =item Example 7
195              
196             You're testing some code that writes data to a file handle, you want to check that it behaves as expected if it gets a C error after it has written the first 100k of data.
197              
198             =for test "ex7" begin
199              
200             use IO::Callback;
201             use Errno qw/ENOSPC/;
202              
203             my $wrote = 0;
204             my $fh = IO::Callback->new('>', sub {
205             $wrote += length $_[0];
206             if ($wrote > 100_000) {
207             $! = ENOSPC;
208             return IO::Callback::Error;
209             }
210             });
211              
212             # ...
213              
214             =for test "ex7" end
215              
216             =back
217              
218             =cut
219              
220 17     17   96 use Carp;
  17         36  
  17         1433  
221 17     17   25661 use Errno qw/EBADF/;
  17         26010  
  17         2886  
222 17     17   17091 use IO::String;
  17         98730  
  17         642  
223 17     17   169 use base qw/IO::String/;
  17         36  
  17         54478  
224              
225             sub open
226             {
227 3528     3528 1 3075232 my $self = shift;
228 3528 50       11399 return $self->new(@_) unless ref($self);
229              
230 3528 100       12081 my $mode = shift or croak "mode missing in IO::Callback::new";
231 3522 100       9521 if ($mode eq '<') {
    100          
232 2893         7745 *$self->{R} = 1;
233             } elsif ($mode eq '>') {
234 621         1545 *$self->{W} = 1;
235             } else {
236 8         83 croak qq{invalid mode "$mode" in IO::Callback::new};
237             }
238              
239 3514 100       9682 my $code = shift or croak "coderef missing in IO::Callback::new";
240 3510 100       14829 ref $code eq "CODE" or croak "non-coderef second argument in IO::Callback::new";
241              
242 3508         5476 my $buf = '';
243 3508         7638 *$self->{Buf} = \$buf;
244 3508         7403 *$self->{Pos} = 0;
245 3508         5929 *$self->{Err} = 0;
246 3508         5144 *$self->{lno} = 0;
247              
248 3508 100       7246 if (@_) {
249 2829         6012 my @args = @_;
250 2829     2253   17505 *$self->{Code} = sub { $code->(@_, @args) };
  2253         6248  
251             } else {
252 679         2050 *$self->{Code} = $code;
253             }
254             }
255              
256             sub close
257             {
258 43     43 0 2482 my $self = shift;
259 43 100       173 return unless defined *$self->{Code};
260 35 100       100 return if *$self->{Err};
261 34 100       85 if (*$self->{W}) {
262 25         77 my $ret = *$self->{Code}('');
263 25 100 100     225 if ($ret and ref $ret eq 'IO::Callback::ErrorMarker') {
264 1         3 *$self->{Err} = 1;
265 1         13 return;
266             }
267             }
268 33         120 foreach my $key (qw/Code Buf Eof R W Pos lno/) {
269 231         424 delete *$self->{$key};
270             }
271 33         65 *$self->{Err} = -1;
272 33 50       121 undef *$self if $] eq "5.008"; # cargo culted from IO::String
273 33         230 return 1;
274             }
275              
276             sub opened
277             {
278 36     36 0 378 my $self = shift;
279 36   100     252 return defined *$self->{R} || defined *$self->{W};
280             }
281              
282             sub getc
283             {
284 29     29 0 263 my $self = shift;
285 29 100       82 *$self->{R} or return $self->_ebadf;
286 25         29 my $buf;
287 25 100       64 return $buf if $self->read($buf, 1);
288 23         92 return undef;
289             }
290              
291             sub ungetc
292             {
293 2     2 0 65 my ($self, $char) = @_;
294 2 100       10 *$self->{R} or return $self->_ebadf;
295 1         2 my $buf = *$self->{Buf};
296 1         4 $$buf = chr($char) . $$buf;
297 1         2 --*$self->{Pos};
298 1         2 delete *$self->{Eof};
299 1         15 return 1;
300             }
301              
302             sub eof
303             {
304 2     2 0 12 my $self = shift;
305 2         9 return *$self->{Eof};
306             }
307              
308             # Use something very distinctive for the error return code, since write callbacks
309             # may pay no attention to what they are returning, and it would be bad to mistake
310             # returned noise for an error indication.
311             sub Error () {
312 21     21 0 3068 return bless {}, 'IO::Callback::ErrorMarker';
313             }
314              
315             sub _doread {
316 3613     3613   5039 my $self = shift;
317              
318 3613 50       9420 return unless *$self->{Code};
319 3613         7135 my $newbit = *$self->{Code}();
320 3613 100       31772 if (defined $newbit) {
321 3567 100       7061 if (ref $newbit) {
322 9 100       28 if (ref $newbit eq 'IO::Callback::ErrorMarker') {
323 8         11 *$self->{Err} = 1;
324 8         35 return;
325             } else {
326 1         27 confess "unexpected reference type ".ref($newbit)." returned by callback";
327             }
328             }
329 3558 100       7112 if (length $newbit) {
330 2557         14465 ${*$self->{Buf}} .= $newbit;
  2557         7343  
331 2557         22364 return 1;
332             }
333             }
334              
335             # fall-through for both undef and ''
336 1047         5705 delete *$self->{Code};
337 1047         4259 return;
338             }
339              
340             sub getline
341             {
342 71     71 0 1370 my $self = shift;
343              
344 71 100       176 *$self->{R} or return $self->_ebadf;
345 69 100 100     450 return if *$self->{Eof} || *$self->{Err};
346 37         59 my $buf = *$self->{Buf};
347 37         78 $. = *$self->{lno};
348              
349 37 100       99 unless (defined $/) { # slurp
350 4         10 1 while $self->_doread;
351 4 100       17 return if *$self->{Err};
352 2         10 *$self->{Pos} += length $$buf;
353 2         4 *$self->{Eof} = 1;
354 2         4 *$self->{Buf} = \(my $newbuf = '');
355 2         3 $. = ++ *$self->{lno};
356 2         9 return $$buf;
357             }
358              
359 33 100       94 my $rs = length $/ ? $/ : "\n\n";
360 33         95 for (;;) {
361             # In paragraph mode, discard extra newlines.
362 66 50 66     223 if ($/ eq '' and $$buf =~ s/^(\n+)//) {
363 0         0 *$self->{Pos} += length $1;
364             }
365 66         417 my $pos = index $$buf, $rs;
366 66 100       138 if ($pos >= 0) {
367 19         32 *$self->{Pos} += $pos+length($rs);
368 19         44 my $ret = substr $$buf, 0, $pos+length($rs), '';
369 19 100       53 unless (length $/) {
370             # paragraph mode, discard extra trailing newlines
371 6 100       23 $$buf =~ s/^(\n+)// and *$self->{Pos} += length $1;
372 6   100     43 while (*$self->{Code} and length $$buf == 0) {
373 2         6 $self->_doread;
374 2 50       7 return if *$self->{Err};
375 2 50       11 $$buf =~ s/^(\n+)// and *$self->{Pos} += length $1;
376             }
377             }
378 19   100     202 $self->_doread while *$self->{Code} and length $$buf == 0 and not *$self->{Err};
      66        
379 19 100 66     69 if (length $$buf == 0 and not *$self->{Code}) {
380 5         11 *$self->{Eof} = 1;
381             }
382 19         45 $. = ++ *$self->{lno};
383 19         137 return $ret;
384             }
385 47 100       105 if (*$self->{Code}) {
386 37         86 $self->_doread;
387 37 100       120 return if *$self->{Err};
388             } else {
389             # EOL not in buffer and no more data to come - the last line is missing its EOL.
390 10         20 *$self->{Eof} = 1;
391 10         21 *$self->{Pos} += length $$buf;
392 10         22 *$self->{Buf} = \(my $newbuf = '');
393 10 50       42 $. = ++ *$self->{lno} if length $$buf;
394 10 50       112 return $$buf if length $$buf;
395 0         0 return;
396             }
397             }
398             }
399              
400             sub getlines
401             {
402 33 100   33 0 233 croak "getlines() called in scalar context" unless wantarray;
403 32         42 my $self = shift;
404              
405 32 100       82 *$self->{R} or return $self->_ebadf;
406 30 100 100     261 return if *$self->{Err} || *$self->{Eof};
407              
408             # To exactly match Perl's behavior on real files, getlines() should not
409             # increment $. if there is no more input, but getline() should. I won't
410             # call getline() until I've established that there is more input.
411 11         20 my $buf = *$self->{Buf};
412 11 50       39 unless (length $$buf) {
413 11         28 $self->_doread;
414 11 50       31 return unless length $$buf;
415             }
416              
417 11         14 my($line, @lines);
418 11         51 push(@lines, $line) while defined($line = $self->getline);
419 11         91 return @lines;
420             }
421              
422             sub READLINE
423             {
424 65 100   65   13245 goto &getlines if wantarray;
425 37         105 goto &getline;
426             }
427              
428             sub read
429             {
430 3828     3828 0 130533 my $self = shift;
431              
432 3828 100       10679 *$self->{R} or return $self->_ebadf;
433 3823   100     13149 my $len = $_[1]||0;
434              
435 3823 100       70039 croak "Negative length" if $len < 0;
436 3423 50       8206 return if *$self->{Err};
437 3423 100       8277 return 0 if *$self->{Eof};
438 3421         6092 my $buf = *$self->{Buf};
439              
440 3421   100     23673 1 while *$self->{Code} and $len > length $$buf and $self->_doread;
      100        
441 3420 100       8334 return if *$self->{Err};
442 3418 100       8569 if ($len > length $$buf) {
443 1035         1440 $len = length $$buf;
444 1035 100       3376 *$self->{Eof} = 1 unless $len;
445             }
446              
447 3418 100       7064 if (@_ > 2) { # read offset
448 2281   100     5420 my $offset = $_[2]||0;
449 2281 100       6050 if ($offset < -1 * length $_[0]) {
450 480         79540 croak "Offset outside string";
451             }
452 1801 100       9448 if ($offset > length $_[0]) {
453 480         1835 $_[0] .= "\0" x ($offset - length $_[0]);
454             }
455 1801         6097 substr($_[0], $offset) = substr($$buf, 0, $len, '');
456             }
457             else {
458 1137         6222 $_[0] = substr($$buf, 0, $len, '');
459             }
460 2938         6202 *$self->{Pos} += $len;
461 2938         8960 return $len;
462             }
463              
464             *sysread = \&read;
465             *syswrite = \&write;
466              
467             sub stat {
468 0     0 0 0 my $self = shift;
469 0 0       0 return unless $self->opened;
470 0 0       0 return 1 unless wantarray;
471              
472 0         0 my @stat = $self->SUPER::stat();
473              
474             # size unknown, report 0
475 0         0 $stat[7] = 0;
476 0         0 $stat[12] = 1;
477              
478 0         0 return @stat;
479             }
480              
481             sub print
482             {
483 54     54 0 7358 my $self = shift;
484              
485 54         71 my $result;
486 54 100       130 if (defined $\) {
487 2 100       5 if (defined $,) {
488 1         5 $result = $self->write(join($,, @_).$\);
489             }
490             else {
491 1         7 $result = $self->write(join("",@_).$\);
492             }
493             }
494             else {
495 52 50       5447 if (defined $,) {
496 0         0 $result = $self->write(join($,, @_));
497             }
498             else {
499 52         566 $result = $self->write(join("",@_));
500             }
501             }
502              
503 54 100       316 return unless defined $result;
504 24         105 return 1;
505             }
506             *printflush = \*print;
507              
508             sub printf
509             {
510 62     62 0 14143 my $self = shift;
511 62         106 my $fmt = shift;
512 62         240 my $result = $self->write(sprintf($fmt, @_));
513 62 100       468 return unless defined $result;
514 14         90 return 1;
515             }
516              
517             sub getpos
518             {
519 0     0 0 0 my $self = shift;
520              
521 0         0 $. = *$self->{lno};
522 0         0 return *$self->{Pos};
523             }
524             *tell = \&getpos;
525             *pos = \&getpos;
526              
527             sub setpos
528             {
529 1     1 0 796 croak "setpos not implemented for IO::Callback";
530             }
531              
532             sub truncate
533             {
534 1     1 0 781 croak "truncate not implemented for IO::Callback";
535             }
536              
537             sub seek
538             {
539 1     1 0 824 croak "Illegal seek";
540             }
541             *sysseek = \&seek;
542              
543             sub write
544             {
545 729     729 0 22237 my $self = shift;
546              
547 729 100       1898 *$self->{W} or return $self->_ebadf;
548 706 100       1973 return if *$self->{Err};
549              
550 625         874 my $slen = length($_[0]);
551 625         667 my $len = $slen;
552 625         692 my $off = 0;
553 625 100       1408 if (@_ > 1) {
554 573 100       1013 my $xlen = defined $_[1] ? $_[1] : 0;
555 573 100       1248 $len = $xlen if $xlen < $len;
556 573 100       11609 croak "Negative length" if $len < 0;
557 493 100       1175 if (@_ > 2) {
558 460   100     1100 $off = $_[2] || 0;
559 460 100 100     2944 if ( $off >= $slen and $off > 0 and ($] < 5.011 or $off > $slen) ) {
      66        
      66        
560 120         18082 croak "Offset outside string";
561             }
562 340 100       725 if ($off < 0) {
563 193         245 $off += $slen;
564 193 100       21677 croak "Offset outside string" if $off < 0;
565             }
566 220         349 my $rem = $slen - $off;
567 220 100       547 $len = $rem if $rem < $len;
568             }
569             }
570 305 100       992 return $len if $len == 0;
571 188         843 my $ret = *$self->{Code}(substr $_[0], $off, $len);
572 188 100 100     1710 if (defined $ret and ref $ret eq 'IO::Callback::ErrorMarker') {
573 12         26 *$self->{Err} = 1;
574 12         95 return;
575             }
576 176         361 *$self->{Pos} += $len;
577 176         508 return $len;
578             }
579              
580             sub error {
581 2885     2885 0 1770437 my $self = shift;
582              
583 2885         23256 return *$self->{Err};
584             }
585              
586             sub clearerr {
587 33     33 0 27806 my $self = shift;
588              
589 33         116 *$self->{Err} = 0;
590             }
591              
592             sub _ebadf {
593 37     37   47 my $self = shift;
594              
595 37         67 $! = EBADF;
596 37         56 *$self->{Err} = -1;
597 37         540 return;
598             }
599              
600             *GETC = \&getc;
601             *PRINT = \&print;
602             *PRINTF = \&printf;
603             *READ = \&read;
604             *WRITE = \&write;
605             *SEEK = \&seek;
606             *TELL = \&getpos;
607             *EOF = \&eof;
608             *CLOSE = \&close;
609              
610             =head1 AUTHOR
611              
612             Dave Taylor, C<< >>
613              
614             =head1 BUGS AND LIMITATIONS
615              
616             Fails to inter-operate with some library modules that read or write filehandles from within XS code. I am aware of the following specific cases, please let me know if you run into any others:
617              
618             =over 4
619              
620             =item C
621              
622             =back
623              
624             Please report any other bugs or feature requests to C, or through
625             the web interface at L. I will be notified, and then you'll
626             automatically be notified of progress on your bug as I make changes.
627              
628             =head1 SUPPORT
629              
630             You can find documentation for this module with the perldoc command.
631              
632             perldoc IO::Callback
633              
634             You can also look for information at:
635              
636             =over 4
637              
638             =item * RT: CPAN's request tracker
639              
640             L
641              
642             =item * AnnoCPAN: Annotated CPAN documentation
643              
644             L
645              
646             =item * CPAN Ratings
647              
648             L
649              
650             =item * Search CPAN
651              
652             L
653              
654             =back
655              
656             =head1 SEE ALSO
657              
658             L, L, L
659              
660             =head1 ACKNOWLEDGEMENTS
661              
662             Adapted from code in L by Gisle Aas.
663              
664             =head1 MANITAINER
665              
666             This module is currently being maintained by Toby Inkster (TOBYINK)
667             for bug fixes. No substantial changes or new features are planned.
668              
669             =head1 COPYRIGHT & LICENSE
670              
671             Copyright 1998-2005 Gisle Aas.
672              
673             Copyright 2009-2010 Dave Taylor.
674              
675             This program is free software; you can redistribute it and/or modify it
676             under the same terms as Perl itself.
677              
678             =cut
679              
680             1; # End of IO::Callback