| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Bio::Root::IO; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 276 |  |  | 276 |  | 2128 | use strict; | 
|  | 276 |  |  |  |  | 579 |  | 
|  | 276 |  |  |  |  | 6579 |  | 
| 4 | 276 |  |  | 276 |  | 1133 | use Symbol; | 
|  | 276 |  |  |  |  | 483 |  | 
|  | 276 |  |  |  |  | 13466 |  | 
| 5 | 276 |  |  | 276 |  | 1314 | use IO::Handle; | 
|  | 276 |  |  |  |  | 564 |  | 
|  | 276 |  |  |  |  | 9047 |  | 
| 6 | 276 |  |  | 276 |  | 75098 | use File::Copy; | 
|  | 276 |  |  |  |  | 501009 |  | 
|  | 276 |  |  |  |  | 13275 |  | 
| 7 | 276 |  |  | 276 |  | 1628 | use Fcntl; | 
|  | 276 |  |  |  |  | 444 |  | 
|  | 276 |  |  |  |  | 51876 |  | 
| 8 | 276 |  |  | 276 |  | 1570 | use base qw(Bio::Root::Root); | 
|  | 276 |  |  |  |  | 431 |  | 
|  | 276 |  |  |  |  | 128231 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | # as of 2016, worked on most systems, but will test this in a RC | 
| 11 |  |  |  |  |  |  | my %modes = ( 0 => 'r', 1 => 'w', 2 => 'rw' ); | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | # Use stream I/O in your module | 
| 16 |  |  |  |  |  |  | $self->{'io'} = Bio::Root::IO->new(-file => "myfile"); | 
| 17 |  |  |  |  |  |  | $self->{'io'}->_print("some stuff"); | 
| 18 |  |  |  |  |  |  | my $line = $self->{'io'}->_readline(); | 
| 19 |  |  |  |  |  |  | $self->{'io'}->_pushback($line); | 
| 20 |  |  |  |  |  |  | $self->{'io'}->close(); | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # obtain platform-compatible filenames | 
| 23 |  |  |  |  |  |  | $path = Bio::Root::IO->catfile($dir, $subdir, $filename); | 
| 24 |  |  |  |  |  |  | # obtain a temporary file (created in $TEMPDIR) | 
| 25 |  |  |  |  |  |  | ($handle) = $io->tempfile(); | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | This module provides methods that will usually be needed for any sort | 
| 30 |  |  |  |  |  |  | of file- or stream-related input/output, e.g., keeping track of a file | 
| 31 |  |  |  |  |  |  | handle, transient printing and reading from the file handle, a close | 
| 32 |  |  |  |  |  |  | method, automatically closing the handle on garbage collection, etc. | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | To use this for your own code you will either want to inherit from | 
| 35 |  |  |  |  |  |  | this module, or instantiate an object for every file or stream you are | 
| 36 |  |  |  |  |  |  | dealing with. In the first case this module will most likely not be | 
| 37 |  |  |  |  |  |  | the first class off which your class inherits; therefore you need to | 
| 38 |  |  |  |  |  |  | call _initialize_io() with the named parameters in order to set file | 
| 39 |  |  |  |  |  |  | handle, open file, etc automatically. | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | Most methods start with an underscore, indicating they are private. In | 
| 42 |  |  |  |  |  |  | OO speak, they are not private but protected, that is, use them in | 
| 43 |  |  |  |  |  |  | your module code, but a client code of your module will usually not | 
| 44 |  |  |  |  |  |  | want to call them (except those not starting with an underscore). | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | In addition this module contains a couple of convenience methods for | 
| 47 |  |  |  |  |  |  | cross-platform safe tempfile creation and similar tasks. There are | 
| 48 |  |  |  |  |  |  | some CPAN modules related that may not be available on all | 
| 49 |  |  |  |  |  |  | platforms. At present, File::Spec and File::Temp are attempted. This | 
| 50 |  |  |  |  |  |  | module defines $PATHSEP, $TEMPDIR, and $ROOTDIR, which will always be set, | 
| 51 |  |  |  |  |  |  | and $OPENFLAGS, which will be set if either of File::Spec or File::Temp fails. | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | The -noclose boolean (accessed via the noclose method) prevents a | 
| 54 |  |  |  |  |  |  | filehandle from being closed when the IO object is cleaned up.  This | 
| 55 |  |  |  |  |  |  | is special behavior when a object like a parser might share a | 
| 56 |  |  |  |  |  |  | filehandle with an object like an indexer where it is not proper to | 
| 57 |  |  |  |  |  |  | close the filehandle as it will continue to be reused until the end of the | 
| 58 |  |  |  |  |  |  | stream is reached.  In general you won't want to play with this flag. | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | =head1 AUTHOR Hilmar Lapp | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | =cut | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | our ($FILESPECLOADED,   $FILETEMPLOADED, | 
| 65 |  |  |  |  |  |  | $FILEPATHLOADED,   $TEMPDIR, | 
| 66 |  |  |  |  |  |  | $PATHSEP,          $ROOTDIR, | 
| 67 |  |  |  |  |  |  | $OPENFLAGS,        $VERBOSE, | 
| 68 |  |  |  |  |  |  | $ONMAC,            $HAS_EOL,       ); | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | my $TEMPCOUNTER; | 
| 71 |  |  |  |  |  |  | my $HAS_WIN32 = 0; | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | BEGIN { | 
| 74 | 276 |  |  | 276 |  | 853 | $TEMPCOUNTER = 0; | 
| 75 | 276 |  |  |  |  | 410 | $FILESPECLOADED = 0; | 
| 76 | 276 |  |  |  |  | 388 | $FILETEMPLOADED = 0; | 
| 77 | 276 |  |  |  |  | 407 | $FILEPATHLOADED = 0; | 
| 78 | 276 |  |  |  |  | 404 | $VERBOSE = 0; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | # try to load those modules that may cause trouble on some systems | 
| 81 | 276 |  |  |  |  | 402 | eval { | 
| 82 | 276 |  |  |  |  | 1300 | require File::Path; | 
| 83 | 276 |  |  |  |  | 478 | $FILEPATHLOADED = 1; | 
| 84 |  |  |  |  |  |  | }; | 
| 85 | 276 | 50 |  |  |  | 1013 | if( $@ ) { | 
| 86 | 0 | 0 |  |  |  | 0 | print STDERR "Cannot load File::Path: $@" if( $VERBOSE > 0 ); | 
| 87 |  |  |  |  |  |  | # do nothing | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | # If on Win32, attempt to find Win32 package | 
| 91 | 276 | 50 |  |  |  | 1434 | if($^O =~ /mswin/i) { | 
| 92 | 0 |  |  |  |  | 0 | eval { | 
| 93 | 0 |  |  |  |  | 0 | require Win32; | 
| 94 | 0 |  |  |  |  | 0 | $HAS_WIN32 = 1; | 
| 95 |  |  |  |  |  |  | }; | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | # Try to provide a path separator. Why doesn't File::Spec export this, | 
| 99 |  |  |  |  |  |  | # or did I miss it? | 
| 100 | 276 | 50 |  |  |  | 1257 | if ($^O =~ /mswin/i) { | 
|  |  | 50 |  |  |  |  |  | 
| 101 | 0 |  |  |  |  | 0 | $PATHSEP = "\\"; | 
| 102 |  |  |  |  |  |  | } elsif($^O =~ /macos/i) { | 
| 103 | 0 |  |  |  |  | 0 | $PATHSEP = ":"; | 
| 104 |  |  |  |  |  |  | } else { # unix | 
| 105 | 276 |  |  |  |  | 518 | $PATHSEP = "/"; | 
| 106 |  |  |  |  |  |  | } | 
| 107 | 276 |  |  |  |  | 431 | eval { | 
| 108 | 276 |  |  |  |  | 895 | require File::Spec; | 
| 109 | 276 |  |  |  |  | 425 | $FILESPECLOADED = 1; | 
| 110 | 276 |  |  |  |  | 22481 | $TEMPDIR = File::Spec->tmpdir(); | 
| 111 | 276 |  |  |  |  | 2097 | $ROOTDIR = File::Spec->rootdir(); | 
| 112 | 276 |  |  |  |  | 1191 | require File::Temp; # tempfile creation | 
| 113 | 276 |  |  |  |  | 608 | $FILETEMPLOADED = 1; | 
| 114 |  |  |  |  |  |  | }; | 
| 115 | 276 | 50 |  |  |  | 867 | if( $@ ) { | 
| 116 | 0 | 0 |  |  |  | 0 | if(! defined($TEMPDIR)) { # File::Spec failed | 
| 117 |  |  |  |  |  |  | # determine tempdir | 
| 118 | 0 | 0 | 0 |  |  | 0 | if (defined $ENV{'TEMPDIR'} && -d $ENV{'TEMPDIR'} ) { | 
|  |  | 0 | 0 |  |  |  |  | 
| 119 | 0 |  |  |  |  | 0 | $TEMPDIR = $ENV{'TEMPDIR'}; | 
| 120 |  |  |  |  |  |  | } elsif( defined $ENV{'TMPDIR'} && -d $ENV{'TMPDIR'} ) { | 
| 121 | 0 |  |  |  |  | 0 | $TEMPDIR = $ENV{'TMPDIR'}; | 
| 122 |  |  |  |  |  |  | } | 
| 123 | 0 | 0 |  |  |  | 0 | if($^O =~ /mswin/i) { | 
|  |  | 0 |  |  |  |  |  | 
| 124 | 0 | 0 |  |  |  | 0 | $TEMPDIR = 'C:\TEMP' unless $TEMPDIR; | 
| 125 | 0 |  |  |  |  | 0 | $ROOTDIR = 'C:'; | 
| 126 |  |  |  |  |  |  | } elsif($^O =~ /macos/i) { | 
| 127 | 0 | 0 |  |  |  | 0 | $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs? | 
| 128 | 0 |  |  |  |  | 0 | $ROOTDIR = ""; # what is reasonable?? | 
| 129 |  |  |  |  |  |  | } else { # unix | 
| 130 | 0 | 0 |  |  |  | 0 | $TEMPDIR = "/tmp" unless $TEMPDIR; | 
| 131 | 0 |  |  |  |  | 0 | $ROOTDIR = "/"; | 
| 132 |  |  |  |  |  |  | } | 
| 133 | 0 | 0 | 0 |  |  | 0 | if (!( -d $TEMPDIR && -w $TEMPDIR )) { | 
| 134 | 0 |  |  |  |  | 0 | $TEMPDIR = '.'; # last resort | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  | } | 
| 137 |  |  |  |  |  |  | # File::Temp failed (alone, or File::Spec already failed) | 
| 138 |  |  |  |  |  |  | # determine open flags for tempfile creation using Fcntl | 
| 139 | 0 |  |  |  |  | 0 | $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR; | 
| 140 | 0 |  |  |  |  | 0 | for my $oflag (qw/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){ | 
| 141 | 0 |  |  |  |  | 0 | my ($bit, $func) = (0, "Fcntl::O_" . $oflag); | 
| 142 | 276 |  |  | 276 |  | 2184 | no strict 'refs'; | 
|  | 276 |  |  |  |  | 479 |  | 
|  | 276 |  |  |  |  | 24548 |  | 
| 143 | 0 | 0 |  |  |  | 0 | $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 }; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  | } | 
| 146 | 276 |  |  |  |  | 192937 | $ONMAC = "\015" eq "\n"; | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | =head2 new | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | Title   : new | 
| 153 |  |  |  |  |  |  | Usage   : my $io = Bio::Root::IO->new( -file => 'data.txt' ); | 
| 154 |  |  |  |  |  |  | Function: Create new class instance. It automatically calls C<_initialize_io>. | 
| 155 |  |  |  |  |  |  | Args    : Same named parameters as C<_initialize_io>. | 
| 156 |  |  |  |  |  |  | Returns : A Bio::Root::IO object | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | =cut | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | sub new { | 
| 161 | 9117 |  |  | 9117 | 1 | 21994 | my ($caller, @args) = @_; | 
| 162 | 9117 |  |  |  |  | 21889 | my $self = $caller->SUPER::new(@args); | 
| 163 | 9117 |  |  |  |  | 22976 | $self->_initialize_io(@args); | 
| 164 | 9110 |  |  |  |  | 16156 | return $self; | 
| 165 |  |  |  |  |  |  | } | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | =head2 _initialize_io | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | Title   : _initialize_io | 
| 171 |  |  |  |  |  |  | Usage   : $io->_initialize_io(@params); | 
| 172 |  |  |  |  |  |  | Function: Initializes filehandle and other properties from the parameters. | 
| 173 |  |  |  |  |  |  | Args    : The following named parameters are currently recognized: | 
| 174 |  |  |  |  |  |  | -file     name of file to read or write to | 
| 175 |  |  |  |  |  |  | -fh       file handle to read or write to (mutually exclusive | 
| 176 |  |  |  |  |  |  | with -file and -string) | 
| 177 |  |  |  |  |  |  | -input    name of file, or filehandle (GLOB or IO::Handle object) | 
| 178 |  |  |  |  |  |  | to read of write to | 
| 179 |  |  |  |  |  |  | -string   string to read from (will be converted to filehandle) | 
| 180 |  |  |  |  |  |  | -url      name of URL to open | 
| 181 |  |  |  |  |  |  | -flush    boolean flag to autoflush after each write | 
| 182 |  |  |  |  |  |  | -noclose  boolean flag, when set to true will not close a | 
| 183 |  |  |  |  |  |  | filehandle (must explicitly call close($io->_fh) | 
| 184 |  |  |  |  |  |  | -retries  number of times to try a web fetch before failure | 
| 185 |  |  |  |  |  |  | -ua_parms when using -url, hashref of key => value parameters | 
| 186 |  |  |  |  |  |  | to pass to LWP::UserAgent->new(). A useful value might | 
| 187 |  |  |  |  |  |  | be, for example, {timeout => 60 } (ua defaults to 180s) | 
| 188 |  |  |  |  |  |  | Returns : True | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | =cut | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | sub _initialize_io { | 
| 193 | 10736 |  |  | 10736 |  | 17894 | my($self, @args) = @_; | 
| 194 |  |  |  |  |  |  |  | 
| 195 | 10736 |  |  |  |  | 31062 | $self->_register_for_cleanup(\&_io_cleanup); | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 10736 |  |  |  |  | 40614 | my ($input, $noclose, $file, $fh, $string, | 
| 198 |  |  |  |  |  |  | $flush, $url, $retries, $ua_parms) = | 
| 199 |  |  |  |  |  |  | $self->_rearrange([qw(INPUT NOCLOSE FILE FH STRING FLUSH URL RETRIES UA_PARMS)], | 
| 200 |  |  |  |  |  |  | @args); | 
| 201 |  |  |  |  |  |  |  | 
| 202 | 10736 |  |  |  |  | 18589 | my $mode; | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 10736 | 50 |  |  |  | 18276 | if ($url) { | 
| 205 | 0 |  | 0 |  |  | 0 | $retries ||= 5; | 
| 206 |  |  |  |  |  |  |  | 
| 207 | 0 |  |  |  |  | 0 | require LWP::UserAgent; | 
| 208 | 0 |  |  |  |  | 0 | my $ua = LWP::UserAgent->new(%$ua_parms); | 
| 209 | 0 |  |  |  |  | 0 | my $http_result; | 
| 210 | 0 |  |  |  |  | 0 | my ($handle, $tempfile) = $self->tempfile(); | 
| 211 | 0 |  |  |  |  | 0 | CORE::close($handle); | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 0 |  |  |  |  | 0 | for (my $try = 1 ; $try <= $retries ; $try++) { | 
| 214 | 0 |  |  |  |  | 0 | $http_result = $ua->get($url, ':content_file' => $tempfile); | 
| 215 | 0 | 0 |  |  |  | 0 | $self->warn("[$try/$retries] tried to fetch $url, but server ". | 
| 216 |  |  |  |  |  |  | "threw ". $http_result->code . ".  retrying...") | 
| 217 |  |  |  |  |  |  | if !$http_result->is_success; | 
| 218 | 0 | 0 |  |  |  | 0 | last if $http_result->is_success; | 
| 219 |  |  |  |  |  |  | } | 
| 220 | 0 | 0 |  |  |  | 0 | $self->throw("Failed to fetch $url, server threw ".$http_result->code) | 
| 221 |  |  |  |  |  |  | if !$http_result->is_success; | 
| 222 |  |  |  |  |  |  |  | 
| 223 | 0 |  |  |  |  | 0 | $file = $tempfile; | 
| 224 | 0 |  |  |  |  | 0 | $mode = '>'; | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 | 10736 |  |  |  |  | 13655 | delete $self->{'_readbuffer'}; | 
| 228 | 10736 |  |  |  |  | 15215 | delete $self->{'_filehandle'}; | 
| 229 | 10736 | 100 |  |  |  | 19336 | $self->noclose( $noclose) if defined $noclose; | 
| 230 |  |  |  |  |  |  | # determine whether the input is a file(name) or a stream | 
| 231 | 10736 | 100 |  |  |  | 18080 | if ($input) { | 
| 232 | 23 | 50 | 0 |  |  | 63 | if (ref(\$input) eq 'SCALAR') { | 
|  |  | 0 | 0 |  |  |  |  | 
| 233 |  |  |  |  |  |  | # we assume that a scalar is a filename | 
| 234 | 23 | 100 | 100 |  |  | 54 | if ($file && ($file ne $input)) { | 
| 235 | 1 |  |  |  |  | 11 | $self->throw("Input file given twice: '$file' and '$input' disagree"); | 
| 236 |  |  |  |  |  |  | } | 
| 237 | 22 |  |  |  |  | 31 | $file = $input; | 
| 238 |  |  |  |  |  |  | } elsif (ref($input) && | 
| 239 |  |  |  |  |  |  | ((ref($input) eq 'GLOB') || $input->isa('IO::Handle'))) { | 
| 240 |  |  |  |  |  |  | # input is a stream | 
| 241 | 0 |  |  |  |  | 0 | $fh = $input; | 
| 242 |  |  |  |  |  |  | } else { | 
| 243 |  |  |  |  |  |  | # let's be strict for now | 
| 244 | 0 |  |  |  |  | 0 | $self->throw("Unable to determine type of input $input: ". | 
| 245 |  |  |  |  |  |  | "not string and not GLOB"); | 
| 246 |  |  |  |  |  |  | } | 
| 247 |  |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  |  | 
| 249 | 10735 | 100 | 100 |  |  | 23457 | if (defined($file) && defined($fh)) { | 
| 250 | 2 |  |  |  |  | 8 | $self->throw("Providing both a file and a filehandle for reading - ". | 
| 251 |  |  |  |  |  |  | "only one please!"); | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  |  | 
| 254 | 10733 | 100 |  |  |  | 17265 | if ($string) { | 
| 255 | 47 | 100 | 100 |  |  | 193 | if (defined($file) || defined($fh)) { | 
| 256 | 3 |  |  |  |  | 14 | $self->throw("File or filehandle provided with -string, ". | 
| 257 |  |  |  |  |  |  | "please unset if you are using -string as a file"); | 
| 258 |  |  |  |  |  |  | } | 
| 259 | 44 | 50 |  | 4 |  | 746 | open $fh, '<', \$string or $self->throw("Could not read string: $!"); | 
|  | 4 |  |  |  |  | 22 |  | 
|  | 4 |  |  |  |  | 55 |  | 
|  | 4 |  |  |  |  | 34 |  | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  |  | 
| 262 | 10730 | 100 | 100 |  |  | 26823 | if (defined($file) && ($file ne '')) { | 
| 263 | 1143 |  |  |  |  | 4585 | $self->file($file); | 
| 264 | 1143 |  |  |  |  | 3508 | ($mode, $file) = $self->cleanfile; | 
| 265 | 1143 |  | 100 |  |  | 4734 | $mode ||= '<'; | 
| 266 | 1143 | 100 |  |  |  | 3348 | my $action = ($mode =~ m/>/) ? 'write' : 'read'; | 
| 267 | 1143 |  |  |  |  | 5117 | $fh = Symbol::gensym(); | 
| 268 | 1143 | 100 |  |  |  | 83110 | open $fh, $mode, $file or $self->throw("Could not $action file '$file': $!"); | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 | 10729 | 100 |  |  |  | 19281 | if (defined $fh) { | 
| 272 |  |  |  |  |  |  | # check filehandle to ensure it's one of: | 
| 273 |  |  |  |  |  |  | # a GLOB reference, as in: open(my $fh, "myfile"); | 
| 274 |  |  |  |  |  |  | # an IO::Handle or IO::String object | 
| 275 |  |  |  |  |  |  | # the UNIVERSAL::can added to fix Bug2863 | 
| 276 | 1835 | 50 | 66 |  |  | 20438 | unless (   ( ref $fh and ( ref $fh eq 'GLOB' ) ) | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 277 |  |  |  |  |  |  | or ( ref $fh and ( UNIVERSAL::can( $fh, 'can' ) ) | 
| 278 |  |  |  |  |  |  | and (   $fh->isa('IO::Handle') | 
| 279 |  |  |  |  |  |  | or $fh->isa('IO::String') ) ) | 
| 280 |  |  |  |  |  |  | ) { | 
| 281 | 0 |  |  |  |  | 0 | $self->throw("Object $fh does not appear to be a file handle"); | 
| 282 |  |  |  |  |  |  | } | 
| 283 | 1835 | 50 |  |  |  | 4776 | if ($HAS_EOL) { | 
| 284 | 0 |  |  |  |  | 0 | binmode $fh, ':raw:eol(LF-Native)'; | 
| 285 |  |  |  |  |  |  | } | 
| 286 | 1835 |  |  |  |  | 6842 | $self->_fh($fh); # if $fh not provided, defaults to STDIN and STDOUT | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  |  | 
| 289 | 10729 | 50 |  |  |  | 33782 | $self->_flush_on_write(defined $flush ? $flush : 1); | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 10729 |  |  |  |  | 17360 | return 1; | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | =head2 _fh | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | Title   : _fh | 
| 298 |  |  |  |  |  |  | Usage   : $io->_fh($newval); | 
| 299 |  |  |  |  |  |  | Function: Get or set the file handle for the stream encapsulated. | 
| 300 |  |  |  |  |  |  | Args    : Optional filehandle to use | 
| 301 |  |  |  |  |  |  | Returns : Filehandle for the stream | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | =cut | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | sub _fh { | 
| 306 | 422518 |  |  | 422518 |  | 453365 | my ($self, $value) = @_; | 
| 307 | 422518 | 100 |  |  |  | 532893 | if ( defined $value) { | 
| 308 | 1867 |  |  |  |  | 4045 | $self->{'_filehandle'} = $value; | 
| 309 |  |  |  |  |  |  | } | 
| 310 | 422518 |  |  |  |  | 712499 | return $self->{'_filehandle'}; | 
| 311 |  |  |  |  |  |  | } | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | =head2 mode | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | Title   : mode | 
| 317 |  |  |  |  |  |  | Usage   : $io->mode(); | 
| 318 |  |  |  |  |  |  | $io->mode(-force => 1); | 
| 319 |  |  |  |  |  |  | Function: Determine if the object was opened for reading or writing | 
| 320 |  |  |  |  |  |  | Args    : -force: Boolean. Once mode() has been called, the mode is cached for | 
| 321 |  |  |  |  |  |  | further calls to mode(). Use this argument to override this | 
| 322 |  |  |  |  |  |  | behavior and re-check the object's mode. | 
| 323 |  |  |  |  |  |  | Returns : Mode of the object: | 
| 324 |  |  |  |  |  |  | 'r'  for readable | 
| 325 |  |  |  |  |  |  | 'w'  for writable | 
| 326 |  |  |  |  |  |  | 'rw' for readable and writable | 
| 327 |  |  |  |  |  |  | '?'  if mode could not be determined (e.g. for a -url) | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | =cut | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | sub mode { | 
| 332 | 8 |  |  | 8 | 1 | 20 | my ($self, %arg) = @_; | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | # Method 1: IO::Handle::fdopen | 
| 335 |  |  |  |  |  |  | #    my $iotest = new IO::Handle; | 
| 336 |  |  |  |  |  |  | #    $iotest->fdopen( dup(fileno($fh)) , 'r' ); | 
| 337 |  |  |  |  |  |  | #    if ($iotest->error == 0) { ... } | 
| 338 |  |  |  |  |  |  | # It did not actually seem to work under any platform, since there would no | 
| 339 |  |  |  |  |  |  | # error if the filehandle had been opened writable only. It could not be | 
| 340 |  |  |  |  |  |  | # hacked around when dealing with unseekable (piped) filehandles. | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | # Method 2: readline, a.k.a. the <> operator | 
| 343 |  |  |  |  |  |  | #    no warnings "io"; | 
| 344 |  |  |  |  |  |  | #    my $line = <$fh>; | 
| 345 |  |  |  |  |  |  | #    if (defined $line) { | 
| 346 |  |  |  |  |  |  | #       $self->{'_mode'} = 'r'; | 
| 347 |  |  |  |  |  |  | #    ... | 
| 348 |  |  |  |  |  |  | # It did not work well either because <> returns undef, i.e. querying the | 
| 349 |  |  |  |  |  |  | # mode() after having read an entire file returned 'w'. | 
| 350 |  |  |  |  |  |  |  | 
| 351 | 8 | 50 | 33 |  |  | 38 | if ( $arg{-force} || not exists $self->{'_mode'} ) { | 
| 352 |  |  |  |  |  |  | # Determine stream mode | 
| 353 | 8 |  |  |  |  | 8 | my $mode; | 
| 354 | 8 |  |  |  |  | 14 | my $fh = $self->_fh; | 
| 355 | 8 | 50 |  |  |  | 17 | if (defined $fh) { | 
| 356 |  |  |  |  |  |  | # use fcntl if not Windows-based | 
| 357 | 8 | 50 |  |  |  | 23 | if ($^O !~ /MSWin32/) { | 
| 358 | 8 |  |  |  |  | 30 | my $m = fcntl($fh, F_GETFL, 0); | 
| 359 | 8 | 50 |  |  |  | 37 | $mode = exists $modes{$m & 3}  ? $modes{$m & 3} : '?'; | 
| 360 |  |  |  |  |  |  | } else { | 
| 361 |  |  |  |  |  |  | # Determine read/write status of filehandle | 
| 362 | 276 |  |  | 276 |  | 1898 | no warnings 'io'; | 
|  | 276 |  |  |  |  | 477 |  | 
|  | 276 |  |  |  |  | 695928 |  | 
| 363 | 0 | 0 |  |  |  | 0 | if ( defined( read $fh, my $content, 0 ) ) { | 
| 364 |  |  |  |  |  |  | # Successfully read 0 bytes | 
| 365 | 0 |  |  |  |  | 0 | $mode = 'r' | 
| 366 |  |  |  |  |  |  | } | 
| 367 | 0 | 0 |  |  |  | 0 | if ( defined( syswrite $fh, '') ) { | 
| 368 |  |  |  |  |  |  | # Successfully wrote 0 bytes | 
| 369 | 0 |  | 0 |  |  | 0 | $mode ||= ''; | 
| 370 | 0 |  |  |  |  | 0 | $mode  .= 'w'; | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  | } | 
| 373 |  |  |  |  |  |  | } else { | 
| 374 |  |  |  |  |  |  | # Stream does not have a filehandle... cannot determine mode | 
| 375 | 0 |  |  |  |  | 0 | $mode = '?'; | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  | # Save mode for future use | 
| 378 | 8 |  |  |  |  | 18 | $self->{'_mode'} = $mode; | 
| 379 |  |  |  |  |  |  | } | 
| 380 | 8 |  |  |  |  | 35 | return $self->{'_mode'}; | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | =head2 file | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | Title   : file | 
| 387 |  |  |  |  |  |  | Usage   : $io->file('>'.$file); | 
| 388 |  |  |  |  |  |  | my $file = $io->file; | 
| 389 |  |  |  |  |  |  | Function: Get or set the name of the file to read or write. | 
| 390 |  |  |  |  |  |  | Args    : Optional file name (including its mode, e.g. '<' for reading or '>' | 
| 391 |  |  |  |  |  |  | for writing) | 
| 392 |  |  |  |  |  |  | Returns : A string representing the filename and its mode. | 
| 393 |  |  |  |  |  |  |  | 
| 394 |  |  |  |  |  |  | =cut | 
| 395 |  |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | sub file { | 
| 397 | 1149 |  |  | 1149 | 1 | 2462 | my ($self, $value) = @_; | 
| 398 | 1149 | 100 |  |  |  | 2680 | if ( defined $value) { | 
| 399 | 1143 |  |  |  |  | 2324 | $self->{'_file'} = $value; | 
| 400 |  |  |  |  |  |  | } | 
| 401 | 1149 |  |  |  |  | 1735 | return $self->{'_file'}; | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | =head2 cleanfile | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | Title   : cleanfile | 
| 408 |  |  |  |  |  |  | Usage   : my ($mode, $file) = $io->cleanfile; | 
| 409 |  |  |  |  |  |  | Function: Get the name of the file to read or write, stripped of its mode | 
| 410 |  |  |  |  |  |  | ('>', '<', '+>', '>>', etc). | 
| 411 |  |  |  |  |  |  | Args    : None | 
| 412 |  |  |  |  |  |  | Returns : In array context, an array of the mode and the clean filename. | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | =cut | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | sub cleanfile { | 
| 417 | 1149 |  |  | 1149 | 1 | 1984 | my ($self) = @_; | 
| 418 | 1149 |  |  |  |  | 8217 | return ($self->{'_file'} =~ m/^ (\+?[><]{1,2})?\s*(.*) $/x); | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | =head2 format | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | Title   : format | 
| 425 |  |  |  |  |  |  | Usage   : $io->format($newval) | 
| 426 |  |  |  |  |  |  | Function: Get the format of a Bio::Root::IO sequence file or filehandle. Every | 
| 427 |  |  |  |  |  |  | object inheriting Bio::Root::IO is guaranteed to have a format. | 
| 428 |  |  |  |  |  |  | Args    : None | 
| 429 |  |  |  |  |  |  | Returns : Format of the file or filehandle, e.g. fasta, fastq, genbank, embl. | 
| 430 |  |  |  |  |  |  |  | 
| 431 |  |  |  |  |  |  | =cut | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | sub format { | 
| 434 | 12 |  |  | 12 | 1 | 82 | my ($self) = @_; | 
| 435 | 12 |  |  |  |  | 50 | my $format = (split '::', ref($self))[-1]; | 
| 436 | 12 |  |  |  |  | 56 | return $format; | 
| 437 |  |  |  |  |  |  | } | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | =head2 variant | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | Title   : format | 
| 443 |  |  |  |  |  |  | Usage   : $io->format($newval) | 
| 444 |  |  |  |  |  |  | Function: Get the variant of a Bio::Root::IO sequence file or filehandle. | 
| 445 |  |  |  |  |  |  | The format variant depends on the specific format used. Note that | 
| 446 |  |  |  |  |  |  | not all formats have variants. Also, the Bio::Root::IO-implementing | 
| 447 |  |  |  |  |  |  | modules that require access to variants need to define a global hash | 
| 448 |  |  |  |  |  |  | that has the allowed variants as its keys. | 
| 449 |  |  |  |  |  |  | Args    : None | 
| 450 |  |  |  |  |  |  | Returns : Variant of the file or filehandle, e.g. sanger, solexa or illumina for | 
| 451 |  |  |  |  |  |  | the fastq format, or undef for formats that do not have variants. | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | =cut | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | sub variant { | 
| 456 | 70151 |  |  | 70151 | 1 | 71029 | my ($self, $variant) = @_; | 
| 457 | 70151 | 100 |  |  |  | 74353 | if (defined $variant) { | 
| 458 | 70 |  |  |  |  | 121 | $variant = lc $variant; | 
| 459 | 70 |  |  |  |  | 165 | my $var_name = '%'.ref($self).'::variant'; | 
| 460 | 70 |  |  |  |  | 3829 | my %ok_variants = eval $var_name; # e.g. %Bio::Assembly::IO::ace::variant | 
| 461 | 70 | 50 |  |  |  | 316 | if (scalar keys %ok_variants == 0) { | 
| 462 | 0 |  |  |  |  | 0 | $self->throw("Could not validate variant because global variant ". | 
| 463 |  |  |  |  |  |  | "$var_name was not set or was empty\n"); | 
| 464 |  |  |  |  |  |  | } | 
| 465 | 70 | 50 |  |  |  | 168 | if (not exists $ok_variants{$variant}) { | 
| 466 | 0 |  |  |  |  | 0 | $self->throw("$variant is not a valid variant of the " . | 
| 467 |  |  |  |  |  |  | $self->format . ' format'); | 
| 468 |  |  |  |  |  |  | } | 
| 469 | 70 |  |  |  |  | 246 | $self->{variant} = $variant; | 
| 470 |  |  |  |  |  |  | } | 
| 471 | 70151 |  |  |  |  | 135085 | return $self->{variant}; | 
| 472 |  |  |  |  |  |  | } | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | =head2 _print | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | Title   : _print | 
| 478 |  |  |  |  |  |  | Usage   : $io->_print(@lines) | 
| 479 |  |  |  |  |  |  | Function: Print lines of text to the IO stream object. | 
| 480 |  |  |  |  |  |  | Args    : List of strings to print | 
| 481 |  |  |  |  |  |  | Returns : True on success, undef on failure | 
| 482 |  |  |  |  |  |  |  | 
| 483 |  |  |  |  |  |  | =cut | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | sub _print { | 
| 486 | 27585 |  |  | 27585 |  | 26275 | my $self = shift; | 
| 487 | 27585 |  | 50 |  |  | 31262 | my $fh = $self->_fh() || \*STDOUT; | 
| 488 | 27585 |  |  |  |  | 53028 | my $ret = print $fh @_; | 
| 489 | 27585 |  |  |  |  | 58645 | return $ret; | 
| 490 |  |  |  |  |  |  | } | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | =head2 _insert | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | Title   : _insert | 
| 496 |  |  |  |  |  |  | Usage   : $io->_insert($string,1) | 
| 497 |  |  |  |  |  |  | Function: Insert some text in a file at the given line number (1-based). | 
| 498 |  |  |  |  |  |  | Args    : * string to write in file | 
| 499 |  |  |  |  |  |  | * line number to insert the string at | 
| 500 |  |  |  |  |  |  | Returns : True | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | =cut | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | sub _insert { | 
| 505 | 2 |  |  | 2 |  | 7 | my ($self, $string, $line_num) = @_; | 
| 506 |  |  |  |  |  |  | # Line number check | 
| 507 | 2 | 50 |  |  |  | 10 | if ($line_num < 1) { | 
| 508 | 0 |  |  |  |  | 0 | $self->throw("Could not insert text at line $line_num: the minimum ". | 
| 509 |  |  |  |  |  |  | "line number possible is 1."); | 
| 510 |  |  |  |  |  |  | } | 
| 511 |  |  |  |  |  |  | # File check | 
| 512 | 2 |  |  |  |  | 8 | my ($mode, $file) = $self->cleanfile; | 
| 513 | 2 | 50 |  |  |  | 8 | if (not defined $file) { | 
| 514 | 0 |  |  |  |  | 0 | $self->throw('Could not insert a line: IO object was initialized with '. | 
| 515 |  |  |  |  |  |  | 'something else than a file.'); | 
| 516 |  |  |  |  |  |  | } | 
| 517 |  |  |  |  |  |  | # Everything that needs to be written is written before we read it | 
| 518 | 2 |  |  |  |  | 10 | $self->flush; | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | # Edit the file line by line (no slurping) | 
| 521 | 2 |  |  |  |  | 5 | $self->close; | 
| 522 | 2 |  |  |  |  | 4 | my $temp_file; | 
| 523 | 2 |  |  |  |  | 4 | my $number = 0; | 
| 524 | 2 |  |  |  |  | 84 | while (-e "$file.$number.temp") { | 
| 525 | 0 |  |  |  |  | 0 | $number++; | 
| 526 |  |  |  |  |  |  | } | 
| 527 | 2 |  |  |  |  | 7 | $temp_file = "$file.$number.temp"; | 
| 528 | 2 |  |  |  |  | 10 | copy($file, $temp_file); | 
| 529 | 2 | 50 |  |  |  | 445 | open my $fh1, '<', $temp_file or $self->throw("Could not read temporary file '$temp_file': $!"); | 
| 530 | 2 | 50 |  |  |  | 781 | open my $fh2, '>', $file      or $self->throw("Could not write file '$file': $!"); | 
| 531 | 2 |  |  |  |  | 30 | while (my $line = <$fh1>) { | 
| 532 | 2 | 100 |  |  |  | 10 | if ($. == $line_num) { # right line for new data | 
| 533 | 1 |  |  |  |  | 7 | print $fh2 $string . $line; | 
| 534 |  |  |  |  |  |  | } | 
| 535 |  |  |  |  |  |  | else { | 
| 536 | 1 |  |  |  |  | 7 | print $fh2 $line; | 
| 537 |  |  |  |  |  |  | } | 
| 538 |  |  |  |  |  |  | } | 
| 539 | 2 |  |  |  |  | 10 | CORE::close $fh1; | 
| 540 | 2 |  |  |  |  | 45 | CORE::close $fh2; | 
| 541 | 2 | 50 |  |  |  | 74 | unlink $temp_file or $self->throw("Could not delete temporary file '$temp_file': $!"); | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | # Line number check (again) | 
| 544 | 2 | 50 | 33 |  |  | 17 | if ( $. > 0 && $line_num > $. ) { | 
| 545 | 0 |  |  |  |  | 0 | $self->throw("Could not insert text at line $line_num: there are only ". | 
| 546 |  |  |  |  |  |  | "$. lines in file '$file'"); | 
| 547 |  |  |  |  |  |  | } | 
| 548 |  |  |  |  |  |  | # Re-open the file in append mode to be ready to add text at the end of it | 
| 549 |  |  |  |  |  |  | # when the next _print() statement comes | 
| 550 | 2 | 50 |  |  |  | 51 | open my $new_fh, '>>', $file or $self->throw("Could not append to file '$file': $!"); | 
| 551 | 2 |  |  |  |  | 10 | $self->_fh($new_fh); | 
| 552 |  |  |  |  |  |  | # If file is empty and we're inserting at line 1, simply append text to file | 
| 553 | 2 | 100 | 66 |  |  | 16 | if ( $. == 0 && $line_num == 1 ) { | 
| 554 | 1 |  |  |  |  | 6 | $self->_print($string); | 
| 555 |  |  |  |  |  |  | } | 
| 556 | 2 |  |  |  |  | 18 | return 1; | 
| 557 |  |  |  |  |  |  | } | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | =head2 _readline | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | Title   : _readline | 
| 563 |  |  |  |  |  |  | Usage   : local $Bio::Root::IO::HAS_EOL = 1; | 
| 564 |  |  |  |  |  |  | my $io = Bio::Root::IO->new(-file => 'data.txt'); | 
| 565 |  |  |  |  |  |  | my $line = $io->_readline(); | 
| 566 |  |  |  |  |  |  | $io->close; | 
| 567 |  |  |  |  |  |  | Function: Read a line of input and normalize all end of line characters. | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | End of line characters are typically "\n" on Linux platforms, "\r\n" | 
| 570 |  |  |  |  |  |  | on Windows and "\r" on older Mac OS. By default, the _readline() | 
| 571 |  |  |  |  |  |  | method uses the value of $/, Perl's input record separator, to | 
| 572 |  |  |  |  |  |  | detect the end of each line. This means that you will not get the | 
| 573 |  |  |  |  |  |  | expected lines if your input has Mac-formatted end of line characters. | 
| 574 |  |  |  |  |  |  | Also, note that the current implementation does not handle pushed | 
| 575 |  |  |  |  |  |  | back input correctly unless the pushed back input ends with the | 
| 576 |  |  |  |  |  |  | value of $/. For each line parsed, its line ending, e.g. "\r\n" is | 
| 577 |  |  |  |  |  |  | converted to "\n", unless you provide the -raw argument. | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | Altogether it is easier to let the PerlIO::eol module automatically | 
| 580 |  |  |  |  |  |  | detect the proper end of line character and normalize it to "\n". Do | 
| 581 |  |  |  |  |  |  | so by setting $Bio::Root::IO::HAS_EOL to 1. | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | Args    : -raw : Avoid converting end of line characters to "\n" This option | 
| 584 |  |  |  |  |  |  | has no effect when using $Bio::Root::IO::HAS_EOL = 1. | 
| 585 |  |  |  |  |  |  | Returns : Line of input, or undef when there is nothing to read anymore | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | =cut | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | sub _readline { | 
| 590 | 379112 |  |  | 379112 |  | 467924 | my ($self, %param) = @_; | 
| 591 | 379112 | 100 |  |  |  | 450794 | my $fh = $self->_fh or return; | 
| 592 | 379100 |  |  |  |  | 356386 | my $line; | 
| 593 |  |  |  |  |  |  |  | 
| 594 |  |  |  |  |  |  | # if the buffer been filled by _pushback then return the buffer | 
| 595 |  |  |  |  |  |  | # contents, rather than read from the filehandle | 
| 596 | 379100 | 100 |  |  |  | 324471 | if( @{$self->{'_readbuffer'} || [] } ) { | 
|  | 379100 | 100 |  |  |  | 808859 |  | 
| 597 | 1483 |  |  |  |  | 1637 | $line = shift @{$self->{'_readbuffer'}}; | 
|  | 1483 |  |  |  |  | 3041 |  | 
| 598 |  |  |  |  |  |  | } else { | 
| 599 | 377617 |  |  |  |  | 644650 | $line = <$fh>; | 
| 600 |  |  |  |  |  |  | } | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | # Note: In Windows the "-raw" parameter has no effect, because Perl already discards | 
| 603 |  |  |  |  |  |  | # the '\r' from the line when reading in text mode from the filehandle | 
| 604 |  |  |  |  |  |  | # ($line = <$fh>), and put it back automatically when printing | 
| 605 | 379100 | 100 | 66 |  |  | 1194565 | if( !$HAS_EOL && !$param{-raw} && (defined $line) ) { | 
|  |  |  | 100 |  |  |  |  | 
| 606 |  |  |  |  |  |  | # don't strip line endings if -raw or $HAS_EOL is specified | 
| 607 | 378525 |  |  |  |  | 494364 | $line =~ s/\015\012/\012/g;         # Change all CR/LF pairs to LF | 
| 608 | 378525 | 50 |  |  |  | 573891 | $line =~ tr/\015/\n/ unless $ONMAC; # Change all single CRs to NEWLINE | 
| 609 |  |  |  |  |  |  | } | 
| 610 | 379100 |  |  |  |  | 944091 | return $line; | 
| 611 |  |  |  |  |  |  | } | 
| 612 |  |  |  |  |  |  |  | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | =head2 _pushback | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | Title   : _pushback | 
| 617 |  |  |  |  |  |  | Usage   : $io->_pushback($newvalue) | 
| 618 |  |  |  |  |  |  | Function: Puts a line previously read with _readline back into a buffer. | 
| 619 |  |  |  |  |  |  | buffer can hold as many lines as system memory permits. | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | Note that this is only supported for pushing back data ending with | 
| 622 |  |  |  |  |  |  | the current, localized value of $/. Using this method to push | 
| 623 |  |  |  |  |  |  | modified data back onto the buffer stack is not supported; see bug | 
| 624 |  |  |  |  |  |  | 843. | 
| 625 |  |  |  |  |  |  |  | 
| 626 |  |  |  |  |  |  | Args    : newvalue | 
| 627 |  |  |  |  |  |  | Returns : True | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | =cut | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | # fix for bug 843, this reveals some unsupported behavior | 
| 632 |  |  |  |  |  |  |  | 
| 633 |  |  |  |  |  |  | #sub _pushback { | 
| 634 |  |  |  |  |  |  | #    my ($self, $value) = @_; | 
| 635 |  |  |  |  |  |  | #    if (index($value, $/) >= 0) { | 
| 636 |  |  |  |  |  |  | #        push @{$self->{'_readbuffer'}}, $value; | 
| 637 |  |  |  |  |  |  | #    } else { | 
| 638 |  |  |  |  |  |  | #        $self->throw("Pushing modifed data back not supported: $value"); | 
| 639 |  |  |  |  |  |  | #    } | 
| 640 |  |  |  |  |  |  | #} | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | sub _pushback { | 
| 643 | 1504 |  |  | 1504 |  | 2757 | my ($self, $value) = @_; | 
| 644 | 1504 | 100 |  |  |  | 2846 | return unless $value; | 
| 645 | 1502 |  |  |  |  | 1881 | unshift @{$self->{'_readbuffer'}}, $value; | 
|  | 1502 |  |  |  |  | 3779 |  | 
| 646 | 1502 |  |  |  |  | 2711 | return 1; | 
| 647 |  |  |  |  |  |  | } | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  |  | 
| 650 |  |  |  |  |  |  | =head2 close | 
| 651 |  |  |  |  |  |  |  | 
| 652 |  |  |  |  |  |  | Title   : close | 
| 653 |  |  |  |  |  |  | Usage   : $io->close() | 
| 654 |  |  |  |  |  |  | Function: Closes the file handle associated with this IO instance, | 
| 655 |  |  |  |  |  |  | excepted if -noclose was specified. | 
| 656 |  |  |  |  |  |  | Args    : None | 
| 657 |  |  |  |  |  |  | Returns : True | 
| 658 |  |  |  |  |  |  |  | 
| 659 |  |  |  |  |  |  | =cut | 
| 660 |  |  |  |  |  |  |  | 
| 661 |  |  |  |  |  |  | sub close { | 
| 662 | 11077 |  |  | 11077 | 1 | 16324 | my ($self) = @_; | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | # do not close if we explicitly asked not to | 
| 665 | 11077 | 100 |  |  |  | 21553 | return if $self->noclose; | 
| 666 |  |  |  |  |  |  |  | 
| 667 | 11028 | 100 |  |  |  | 24249 | if( defined( my $fh = $self->{'_filehandle'} )) { | 
| 668 | 1617 |  |  |  |  | 5591 | $self->flush; | 
| 669 | 1617 | 50 | 66 |  |  | 11664 | return if ref $fh eq 'GLOB' && ( | 
|  |  |  | 66 |  |  |  |  | 
| 670 |  |  |  |  |  |  | \*STDOUT == $fh || \*STDERR == $fh || \*STDIN  == $fh | 
| 671 |  |  |  |  |  |  | ); | 
| 672 |  |  |  |  |  |  |  | 
| 673 |  |  |  |  |  |  | # don't close IO::Strings | 
| 674 | 1616 | 100 | 66 |  |  | 29180 | CORE::close $fh unless ref $fh && $fh->isa('IO::String'); | 
| 675 |  |  |  |  |  |  | } | 
| 676 | 11027 |  |  |  |  | 17582 | $self->{'_filehandle'} = undef; | 
| 677 | 11027 |  |  |  |  | 13687 | delete $self->{'_readbuffer'}; | 
| 678 | 11027 |  |  |  |  | 23422 | return 1; | 
| 679 |  |  |  |  |  |  | } | 
| 680 |  |  |  |  |  |  |  | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | =head2 flush | 
| 683 |  |  |  |  |  |  |  | 
| 684 |  |  |  |  |  |  | Title   : flush | 
| 685 |  |  |  |  |  |  | Usage   : $io->flush() | 
| 686 |  |  |  |  |  |  | Function: Flushes the filehandle | 
| 687 |  |  |  |  |  |  | Args    : None | 
| 688 |  |  |  |  |  |  | Returns : True | 
| 689 |  |  |  |  |  |  |  | 
| 690 |  |  |  |  |  |  | =cut | 
| 691 |  |  |  |  |  |  |  | 
| 692 |  |  |  |  |  |  | sub flush { | 
| 693 | 2278 |  |  | 2278 | 1 | 4125 | my ($self) = shift; | 
| 694 |  |  |  |  |  |  |  | 
| 695 | 2278 | 50 |  |  |  | 6185 | if( !defined $self->{'_filehandle'} ) { | 
| 696 | 0 |  |  |  |  | 0 | $self->throw("Flush failed: no filehandle was active"); | 
| 697 |  |  |  |  |  |  | } | 
| 698 |  |  |  |  |  |  |  | 
| 699 | 2278 | 100 |  |  |  | 11485 | if( ref($self->{'_filehandle'}) =~ /GLOB/ ) { | 
| 700 | 1225 |  |  |  |  | 5060 | my $oldh = select($self->{'_filehandle'}); | 
| 701 | 1225 |  |  |  |  | 8149 | $| = 1; | 
| 702 | 1225 |  |  |  |  | 4012 | select($oldh); | 
| 703 |  |  |  |  |  |  | } else { | 
| 704 | 1053 |  |  |  |  | 5570 | $self->{'_filehandle'}->flush(); | 
| 705 |  |  |  |  |  |  | } | 
| 706 | 2278 |  |  |  |  | 5443 | return 1; | 
| 707 |  |  |  |  |  |  | } | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  |  | 
| 710 |  |  |  |  |  |  | =head2 noclose | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | Title   : noclose | 
| 713 |  |  |  |  |  |  | Usage   : $io->noclose($newval) | 
| 714 |  |  |  |  |  |  | Function: Get or set the NOCLOSE flag - setting this to true will prevent a | 
| 715 |  |  |  |  |  |  | filehandle from being closed when an object is cleaned up or | 
| 716 |  |  |  |  |  |  | explicitly closed. | 
| 717 |  |  |  |  |  |  | Args    : Optional new value (a scalar or undef) | 
| 718 |  |  |  |  |  |  | Returns : Value of noclose (a scalar) | 
| 719 |  |  |  |  |  |  |  | 
| 720 |  |  |  |  |  |  | =cut | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | sub noclose { | 
| 723 | 11110 |  |  | 11110 | 1 | 13909 | my $self = shift; | 
| 724 | 11110 | 100 |  |  |  | 20830 | return $self->{'_noclose'} = shift if @_; | 
| 725 | 11077 |  |  |  |  | 22981 | return $self->{'_noclose'}; | 
| 726 |  |  |  |  |  |  | } | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  |  | 
| 729 |  |  |  |  |  |  | =head2 _io_cleanup | 
| 730 |  |  |  |  |  |  |  | 
| 731 |  |  |  |  |  |  | =cut | 
| 732 |  |  |  |  |  |  |  | 
| 733 |  |  |  |  |  |  | sub _io_cleanup { | 
| 734 | 9404 |  |  | 9404 |  | 14372 | my ($self) = @_; | 
| 735 | 9404 |  |  |  |  | 22467 | $self->close(); | 
| 736 | 9404 |  |  |  |  | 19262 | my $v = $self->verbose; | 
| 737 |  |  |  |  |  |  |  | 
| 738 |  |  |  |  |  |  | # we are planning to cleanup temp files no matter what | 
| 739 | 9404 | 50 | 66 |  |  | 22294 | if (    exists($self->{'_rootio_tempfiles'}) | 
|  |  |  | 66 |  |  |  |  | 
| 740 |  |  |  |  |  |  | and ref($self->{'_rootio_tempfiles'}) =~ /array/i | 
| 741 |  |  |  |  |  |  | and not $self->save_tempfiles | 
| 742 |  |  |  |  |  |  | ) { | 
| 743 | 34 | 50 |  |  |  | 59 | if( $v > 0 ) { | 
| 744 |  |  |  |  |  |  | warn( "going to remove files ", | 
| 745 | 0 |  |  |  |  | 0 | join(",",  @{$self->{'_rootio_tempfiles'}}), | 
|  | 0 |  |  |  |  | 0 |  | 
| 746 |  |  |  |  |  |  | "\n"); | 
| 747 |  |  |  |  |  |  | } | 
| 748 | 34 |  |  |  |  | 37 | unlink  (@{$self->{'_rootio_tempfiles'}} ); | 
|  | 34 |  |  |  |  | 557 |  | 
| 749 |  |  |  |  |  |  | } | 
| 750 |  |  |  |  |  |  | # cleanup if we are not using File::Temp | 
| 751 | 9404 | 0 | 33 |  |  | 48981 | if (    $self->{'_cleanuptempdir'} | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 752 |  |  |  |  |  |  | and exists($self->{'_rootio_tempdirs'}) | 
| 753 |  |  |  |  |  |  | and ref($self->{'_rootio_tempdirs'}) =~ /array/i | 
| 754 |  |  |  |  |  |  | and not $self->save_tempfiles | 
| 755 |  |  |  |  |  |  | ) { | 
| 756 | 0 | 0 |  |  |  | 0 | if( $v > 0 ) { | 
| 757 |  |  |  |  |  |  | warn( "going to remove dirs ", | 
| 758 | 0 |  |  |  |  | 0 | join(",",  @{$self->{'_rootio_tempdirs'}}), | 
|  | 0 |  |  |  |  | 0 |  | 
| 759 |  |  |  |  |  |  | "\n"); | 
| 760 |  |  |  |  |  |  | } | 
| 761 | 0 |  |  |  |  | 0 | $self->rmtree( $self->{'_rootio_tempdirs'}); | 
| 762 |  |  |  |  |  |  | } | 
| 763 |  |  |  |  |  |  | } | 
| 764 |  |  |  |  |  |  |  | 
| 765 |  |  |  |  |  |  |  | 
| 766 |  |  |  |  |  |  | =head2 exists_exe | 
| 767 |  |  |  |  |  |  |  | 
| 768 |  |  |  |  |  |  | Title   : exists_exe | 
| 769 |  |  |  |  |  |  | Usage   : $exists = $io->exists_exe('clustalw'); | 
| 770 |  |  |  |  |  |  | $exists = Bio::Root::IO->exists_exe('clustalw') | 
| 771 |  |  |  |  |  |  | $exists = Bio::Root::IO::exists_exe('clustalw') | 
| 772 |  |  |  |  |  |  | Function: Determines whether the given executable exists either as file | 
| 773 |  |  |  |  |  |  | or within the path environment. The latter requires File::Spec | 
| 774 |  |  |  |  |  |  | to be installed. | 
| 775 |  |  |  |  |  |  | On Win32-based system, .exe is automatically appended to the program | 
| 776 |  |  |  |  |  |  | name unless the program name already ends in .exe. | 
| 777 |  |  |  |  |  |  | Args    : Name of the executable | 
| 778 |  |  |  |  |  |  | Returns : 1 if the given program is callable as an executable, and 0 otherwise | 
| 779 |  |  |  |  |  |  |  | 
| 780 |  |  |  |  |  |  | =cut | 
| 781 |  |  |  |  |  |  |  | 
| 782 |  |  |  |  |  |  | sub exists_exe { | 
| 783 | 3 |  |  | 3 | 1 | 8 | my ($self, $exe) = @_; | 
| 784 | 3 | 50 |  |  |  | 7 | $self->throw("Must pass a defined value to exists_exe") unless defined $exe; | 
| 785 | 3 | 50 | 33 |  |  | 9 | $exe = $self if (!(ref($self) || $exe)); | 
| 786 | 3 | 50 | 33 |  |  | 14 | $exe .= '.exe' if(($^O =~ /mswin/i) && ($exe !~ /\.(exe|com|bat|cmd)$/i)); | 
| 787 | 3 | 100 | 100 |  |  | 36 | return $exe if ( -f $exe && -x $exe ); # full path and exists | 
| 788 |  |  |  |  |  |  |  | 
| 789 |  |  |  |  |  |  | # Ewan's comment. I don't think we need this. People should not be | 
| 790 |  |  |  |  |  |  | # asking for a program with a pathseparator starting it | 
| 791 |  |  |  |  |  |  | # $exe =~ s/^$PATHSEP//; | 
| 792 |  |  |  |  |  |  |  | 
| 793 |  |  |  |  |  |  | # Not a full path, or does not exist. Let's see whether it's in the path. | 
| 794 | 2 | 50 |  |  |  | 6 | if($FILESPECLOADED) { | 
| 795 | 2 |  |  |  |  | 49 | for my $dir (File::Spec->path()) { | 
| 796 | 18 |  |  |  |  | 49 | my $f = Bio::Root::IO->catfile($dir, $exe); | 
| 797 | 18 | 50 | 33 |  |  | 348 | return $f if( -f $f && -x $f ); | 
| 798 |  |  |  |  |  |  | } | 
| 799 |  |  |  |  |  |  | } | 
| 800 | 2 |  |  |  |  | 12 | return 0; | 
| 801 |  |  |  |  |  |  | } | 
| 802 |  |  |  |  |  |  |  | 
| 803 |  |  |  |  |  |  |  | 
| 804 |  |  |  |  |  |  | =head2 tempfile | 
| 805 |  |  |  |  |  |  |  | 
| 806 |  |  |  |  |  |  | Title   : tempfile | 
| 807 |  |  |  |  |  |  | Usage   : my ($handle,$tempfile) = $io->tempfile(); | 
| 808 |  |  |  |  |  |  | Function: Create a temporary filename and a handle opened for reading and | 
| 809 |  |  |  |  |  |  | writing. | 
| 810 |  |  |  |  |  |  | Caveats: If you do not have File::Temp on your system you should | 
| 811 |  |  |  |  |  |  | avoid specifying TEMPLATE and SUFFIX. | 
| 812 |  |  |  |  |  |  | Args    : Named parameters compatible with File::Temp: DIR (defaults to | 
| 813 |  |  |  |  |  |  | $Bio::Root::IO::TEMPDIR), TEMPLATE, SUFFIX. | 
| 814 |  |  |  |  |  |  | Returns : A 2-element array, consisting of temporary handle and temporary | 
| 815 |  |  |  |  |  |  | file name. | 
| 816 |  |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | =cut | 
| 818 |  |  |  |  |  |  |  | 
| 819 |  |  |  |  |  |  | sub tempfile { | 
| 820 | 40 |  |  | 40 | 1 | 1931 | my ($self, @args) = @_; | 
| 821 | 40 |  |  |  |  | 54 | my ($tfh, $file); | 
| 822 | 40 |  |  |  |  | 130 | my %params = @args; | 
| 823 |  |  |  |  |  |  |  | 
| 824 |  |  |  |  |  |  | # map between naming with and without dash | 
| 825 | 40 |  |  |  |  | 98 | for my $key (keys(%params)) { | 
| 826 | 51 | 50 |  |  |  | 110 | if( $key =~ /^-/  ) { | 
| 827 | 0 |  |  |  |  | 0 | my $v = $params{$key}; | 
| 828 | 0 |  |  |  |  | 0 | delete $params{$key}; | 
| 829 | 0 |  |  |  |  | 0 | $params{uc(substr($key,1))} = $v; | 
| 830 |  |  |  |  |  |  | } else { | 
| 831 |  |  |  |  |  |  | # this is to upper case | 
| 832 | 51 |  |  |  |  | 71 | my $v = $params{$key}; | 
| 833 | 51 |  |  |  |  | 62 | delete $params{$key}; | 
| 834 | 51 |  |  |  |  | 116 | $params{uc($key)} = $v; | 
| 835 |  |  |  |  |  |  | } | 
| 836 |  |  |  |  |  |  | } | 
| 837 | 40 | 100 |  |  |  | 130 | $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'})); | 
| 838 | 40 | 100 | 66 |  |  | 140 | unless (exists $params{'UNLINK'} && | 
|  |  |  | 66 |  |  |  |  | 
| 839 |  |  |  |  |  |  | defined $params{'UNLINK'} && | 
| 840 |  |  |  |  |  |  | ! $params{'UNLINK'} ) { | 
| 841 | 35 |  |  |  |  | 78 | $params{'UNLINK'} = 1; | 
| 842 |  |  |  |  |  |  | } else { | 
| 843 | 5 |  |  |  |  | 8 | $params{'UNLINK'} = 0; | 
| 844 |  |  |  |  |  |  | } | 
| 845 |  |  |  |  |  |  |  | 
| 846 | 40 | 50 |  |  |  | 64 | if($FILETEMPLOADED) { | 
| 847 | 40 | 100 |  |  |  | 73 | if(exists($params{'TEMPLATE'})) { | 
| 848 | 4 |  |  |  |  | 6 | my $template = $params{'TEMPLATE'}; | 
| 849 | 4 |  |  |  |  | 4 | delete $params{'TEMPLATE'}; | 
| 850 | 4 |  |  |  |  | 14 | ($tfh, $file) = File::Temp::tempfile($template, %params); | 
| 851 |  |  |  |  |  |  | } else { | 
| 852 | 36 |  |  |  |  | 122 | ($tfh, $file) = File::Temp::tempfile(%params); | 
| 853 |  |  |  |  |  |  | } | 
| 854 |  |  |  |  |  |  | } else { | 
| 855 | 0 |  |  |  |  | 0 | my $dir = $params{'DIR'}; | 
| 856 |  |  |  |  |  |  | $file = $self->catfile( | 
| 857 |  |  |  |  |  |  | $dir, | 
| 858 |  |  |  |  |  |  | (exists($params{'TEMPLATE'}) ? | 
| 859 |  |  |  |  |  |  | $params{'TEMPLATE'} : | 
| 860 | 0 | 0 | 0 |  |  | 0 | sprintf( "%s.%s.%s", $ENV{USER} || 'unknown', $$, $TEMPCOUNTER++)) | 
| 861 |  |  |  |  |  |  | ); | 
| 862 |  |  |  |  |  |  |  | 
| 863 |  |  |  |  |  |  | # sneakiness for getting around long filenames on Win32? | 
| 864 | 0 | 0 |  |  |  | 0 | if( $HAS_WIN32 ) { | 
| 865 | 0 |  |  |  |  | 0 | $file = Win32::GetShortPathName($file); | 
| 866 |  |  |  |  |  |  | } | 
| 867 |  |  |  |  |  |  |  | 
| 868 |  |  |  |  |  |  | # Try to make sure this will be marked close-on-exec | 
| 869 |  |  |  |  |  |  | # XXX: Win32 doesn't respect this, nor the proper fcntl, | 
| 870 |  |  |  |  |  |  | #      but may have O_NOINHERIT. This may or may not be in Fcntl. | 
| 871 | 0 |  |  |  |  | 0 | local $^F = 2; | 
| 872 |  |  |  |  |  |  | # Store callers umask | 
| 873 | 0 |  |  |  |  | 0 | my $umask = umask(); | 
| 874 |  |  |  |  |  |  | # Set a known umaskr | 
| 875 | 0 |  |  |  |  | 0 | umask(066); | 
| 876 |  |  |  |  |  |  | # Attempt to open the file | 
| 877 | 0 | 0 |  |  |  | 0 | if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) { | 
| 878 |  |  |  |  |  |  | # Reset umask | 
| 879 | 0 |  |  |  |  | 0 | umask($umask); | 
| 880 |  |  |  |  |  |  | } else { | 
| 881 | 0 |  |  |  |  | 0 | $self->throw("Could not write temporary file '$file': $!"); | 
| 882 |  |  |  |  |  |  | } | 
| 883 |  |  |  |  |  |  | } | 
| 884 |  |  |  |  |  |  |  | 
| 885 | 40 | 100 |  |  |  | 10986 | if(  $params{'UNLINK'} ) { | 
| 886 | 35 |  |  |  |  | 46 | push @{$self->{'_rootio_tempfiles'}}, $file; | 
|  | 35 |  |  |  |  | 89 |  | 
| 887 |  |  |  |  |  |  | } | 
| 888 |  |  |  |  |  |  |  | 
| 889 | 40 | 100 |  |  |  | 178 | return wantarray ? ($tfh,$file) : $tfh; | 
| 890 |  |  |  |  |  |  | } | 
| 891 |  |  |  |  |  |  |  | 
| 892 |  |  |  |  |  |  |  | 
| 893 |  |  |  |  |  |  | =head2  tempdir | 
| 894 |  |  |  |  |  |  |  | 
| 895 |  |  |  |  |  |  | Title   : tempdir | 
| 896 |  |  |  |  |  |  | Usage   : my ($tempdir) = $io->tempdir(CLEANUP=>1); | 
| 897 |  |  |  |  |  |  | Function: Creates and returns the name of a new temporary directory. | 
| 898 |  |  |  |  |  |  |  | 
| 899 |  |  |  |  |  |  | Note that you should not use this function for obtaining "the" | 
| 900 |  |  |  |  |  |  | temp directory. Use $Bio::Root::IO::TEMPDIR for that. Calling this | 
| 901 |  |  |  |  |  |  | method will in fact create a new directory. | 
| 902 |  |  |  |  |  |  |  | 
| 903 |  |  |  |  |  |  | Args    : args - ( key CLEANUP ) indicates whether or not to cleanup | 
| 904 |  |  |  |  |  |  | dir on object destruction, other keys as specified by File::Temp | 
| 905 |  |  |  |  |  |  | Returns : The name of a new temporary directory. | 
| 906 |  |  |  |  |  |  |  | 
| 907 |  |  |  |  |  |  | =cut | 
| 908 |  |  |  |  |  |  |  | 
| 909 |  |  |  |  |  |  | sub tempdir { | 
| 910 | 31 |  |  | 31 | 1 | 62 | my ($self, @args) = @_; | 
| 911 | 31 | 50 | 33 |  |  | 275 | if ($FILETEMPLOADED && File::Temp->can('tempdir')) { | 
| 912 | 31 |  |  |  |  | 94 | return File::Temp::tempdir(@args); | 
| 913 |  |  |  |  |  |  | } | 
| 914 |  |  |  |  |  |  |  | 
| 915 |  |  |  |  |  |  | # we have to do this ourselves, not good | 
| 916 |  |  |  |  |  |  | # we are planning to cleanup temp files no matter what | 
| 917 | 0 |  |  |  |  | 0 | my %params = @args; | 
| 918 | 0 |  |  |  |  | 0 | print "cleanup is " . $params{CLEANUP} . "\n"; | 
| 919 |  |  |  |  |  |  | $self->{'_cleanuptempdir'} = ( defined $params{CLEANUP} && | 
| 920 | 0 |  | 0 |  |  | 0 | $params{CLEANUP} == 1); | 
| 921 |  |  |  |  |  |  | my $tdir = $self->catfile( $TEMPDIR, | 
| 922 |  |  |  |  |  |  | sprintf("dir_%s-%s-%s", | 
| 923 | 0 |  | 0 |  |  | 0 | $ENV{USER} || 'unknown', | 
| 924 |  |  |  |  |  |  | $$, | 
| 925 |  |  |  |  |  |  | $TEMPCOUNTER++)); | 
| 926 | 0 |  |  |  |  | 0 | mkdir($tdir, 0755); | 
| 927 | 0 |  |  |  |  | 0 | push @{$self->{'_rootio_tempdirs'}}, $tdir; | 
|  | 0 |  |  |  |  | 0 |  | 
| 928 | 0 |  |  |  |  | 0 | return $tdir; | 
| 929 |  |  |  |  |  |  | } | 
| 930 |  |  |  |  |  |  |  | 
| 931 |  |  |  |  |  |  |  | 
| 932 |  |  |  |  |  |  | =head2 catfile | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  | Title   : catfile | 
| 935 |  |  |  |  |  |  | Usage   : $path = Bio::Root::IO->catfile(@dirs, $filename); | 
| 936 |  |  |  |  |  |  | Function: Constructs a full pathname in a cross-platform safe way. | 
| 937 |  |  |  |  |  |  |  | 
| 938 |  |  |  |  |  |  | If File::Spec exists on your system, this routine will merely | 
| 939 |  |  |  |  |  |  | delegate to it. Otherwise it tries to make a good guess. | 
| 940 |  |  |  |  |  |  |  | 
| 941 |  |  |  |  |  |  | You should use this method whenever you construct a path name | 
| 942 |  |  |  |  |  |  | from directory and filename. Otherwise you risk cross-platform | 
| 943 |  |  |  |  |  |  | compatibility of your code. | 
| 944 |  |  |  |  |  |  |  | 
| 945 |  |  |  |  |  |  | You can call this method both as a class and an instance method. | 
| 946 |  |  |  |  |  |  |  | 
| 947 |  |  |  |  |  |  | Args    : components of the pathname (directories and filename, NOT an | 
| 948 |  |  |  |  |  |  | extension) | 
| 949 |  |  |  |  |  |  | Returns : a string | 
| 950 |  |  |  |  |  |  |  | 
| 951 |  |  |  |  |  |  | =cut | 
| 952 |  |  |  |  |  |  |  | 
| 953 |  |  |  |  |  |  | sub catfile { | 
| 954 | 8868 |  |  | 8868 | 1 | 22699 | my ($self, @args) = @_; | 
| 955 |  |  |  |  |  |  |  | 
| 956 | 8868 | 50 |  |  |  | 107309 | return File::Spec->catfile(@args) if $FILESPECLOADED; | 
| 957 |  |  |  |  |  |  | # this is clumsy and not very appealing, but how do we specify the | 
| 958 |  |  |  |  |  |  | # root directory? | 
| 959 | 0 | 0 |  |  |  | 0 | if($args[0] eq '/') { | 
| 960 | 0 |  |  |  |  | 0 | $args[0] = $ROOTDIR; | 
| 961 |  |  |  |  |  |  | } | 
| 962 | 0 |  |  |  |  | 0 | return join($PATHSEP, @args); | 
| 963 |  |  |  |  |  |  | } | 
| 964 |  |  |  |  |  |  |  | 
| 965 |  |  |  |  |  |  |  | 
| 966 |  |  |  |  |  |  | =head2 rmtree | 
| 967 |  |  |  |  |  |  |  | 
| 968 |  |  |  |  |  |  | Title   : rmtree | 
| 969 |  |  |  |  |  |  | Usage   : Bio::Root::IO->rmtree($dirname ); | 
| 970 |  |  |  |  |  |  | Function: Remove a full directory tree | 
| 971 |  |  |  |  |  |  |  | 
| 972 |  |  |  |  |  |  | If File::Path exists on your system, this routine will merely | 
| 973 |  |  |  |  |  |  | delegate to it. Otherwise it runs a local version of that code. | 
| 974 |  |  |  |  |  |  |  | 
| 975 |  |  |  |  |  |  | You should use this method to remove directories which contain | 
| 976 |  |  |  |  |  |  | files. | 
| 977 |  |  |  |  |  |  |  | 
| 978 |  |  |  |  |  |  | You can call this method both as a class and an instance method. | 
| 979 |  |  |  |  |  |  |  | 
| 980 |  |  |  |  |  |  | Args    : roots - rootdir to delete or reference to list of dirs | 
| 981 |  |  |  |  |  |  |  | 
| 982 |  |  |  |  |  |  | verbose - a boolean value, which if TRUE will cause | 
| 983 |  |  |  |  |  |  | C to print a message each time it | 
| 984 |  |  |  |  |  |  | examines a file, giving the name of the file, and | 
| 985 |  |  |  |  |  |  | indicating whether it's using C or | 
| 986 |  |  |  |  |  |  | C to remove it, or that it's skipping it. | 
| 987 |  |  |  |  |  |  | (defaults to FALSE) | 
| 988 |  |  |  |  |  |  |  | 
| 989 |  |  |  |  |  |  | safe - a boolean value, which if TRUE will cause C | 
| 990 |  |  |  |  |  |  | to skip any files to which you do not have delete | 
| 991 |  |  |  |  |  |  | access (if running under VMS) or write access (if | 
| 992 |  |  |  |  |  |  | running under another OS).  This will change in the | 
| 993 |  |  |  |  |  |  | future when a criterion for 'delete permission' | 
| 994 |  |  |  |  |  |  | under OSs other than VMS is settled.  (defaults to | 
| 995 |  |  |  |  |  |  | FALSE) | 
| 996 |  |  |  |  |  |  | Returns : number of files successfully deleted | 
| 997 |  |  |  |  |  |  |  | 
| 998 |  |  |  |  |  |  | =cut | 
| 999 |  |  |  |  |  |  |  | 
| 1000 |  |  |  |  |  |  | # taken straight from File::Path VERSION = "1.0403" | 
| 1001 |  |  |  |  |  |  | sub rmtree { | 
| 1002 | 0 |  |  | 0 | 1 | 0 | my ($self, $roots, $verbose, $safe) = @_; | 
| 1003 | 0 | 0 |  |  |  | 0 | if ( $FILEPATHLOADED ) { | 
| 1004 | 0 |  |  |  |  | 0 | return File::Path::rmtree ($roots, $verbose, $safe); | 
| 1005 |  |  |  |  |  |  | } | 
| 1006 |  |  |  |  |  |  |  | 
| 1007 | 0 |  | 0 |  |  | 0 | my $force_writable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32' || | 
| 1008 |  |  |  |  |  |  | $^O eq 'amigaos' || $^O eq 'cygwin'); | 
| 1009 | 0 |  |  |  |  | 0 | my $Is_VMS = $^O eq 'VMS'; | 
| 1010 |  |  |  |  |  |  |  | 
| 1011 | 0 |  |  |  |  | 0 | my @files; | 
| 1012 | 0 |  |  |  |  | 0 | my $count = 0; | 
| 1013 | 0 |  | 0 |  |  | 0 | $verbose ||= 0; | 
| 1014 | 0 |  | 0 |  |  | 0 | $safe    ||= 0; | 
| 1015 | 0 | 0 | 0 |  |  | 0 | if ( defined($roots) && length($roots) ) { | 
| 1016 | 0 | 0 |  |  |  | 0 | $roots = [$roots] unless ref $roots; | 
| 1017 |  |  |  |  |  |  | } else { | 
| 1018 | 0 |  |  |  |  | 0 | $self->warn("No root path(s) specified\n"); | 
| 1019 | 0 |  |  |  |  | 0 | return 0; | 
| 1020 |  |  |  |  |  |  | } | 
| 1021 |  |  |  |  |  |  |  | 
| 1022 | 0 |  |  |  |  | 0 | my $root; | 
| 1023 | 0 |  |  |  |  | 0 | for $root (@{$roots}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 1024 | 0 |  |  |  |  | 0 | $root =~ s#/\z##; | 
| 1025 | 0 | 0 |  |  |  | 0 | (undef, undef, my $rp) = lstat $root or next; | 
| 1026 | 0 |  |  |  |  | 0 | $rp &= 07777;   # don't forget setuid, setgid, sticky bits | 
| 1027 | 0 | 0 |  |  |  | 0 | if ( -d _ ) { | 
| 1028 |  |  |  |  |  |  | # notabene: 0777 is for making readable in the first place, | 
| 1029 |  |  |  |  |  |  | # it's also intended to change it to writable in case we have | 
| 1030 |  |  |  |  |  |  | # to recurse in which case we are better than rm -rf for | 
| 1031 |  |  |  |  |  |  | # subtrees with strange permissions | 
| 1032 | 0 | 0 | 0 |  |  | 0 | chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root)) | 
|  |  | 0 |  |  |  |  |  | 
| 1033 |  |  |  |  |  |  | or $self->warn("Could not make directory '$root' read+writable: $!") | 
| 1034 |  |  |  |  |  |  | unless $safe; | 
| 1035 | 0 | 0 |  |  |  | 0 | if (opendir DIR, $root){ | 
| 1036 | 0 |  |  |  |  | 0 | @files = readdir DIR; | 
| 1037 | 0 |  |  |  |  | 0 | closedir DIR; | 
| 1038 |  |  |  |  |  |  | } else { | 
| 1039 | 0 |  |  |  |  | 0 | $self->warn("Could not read directory '$root': $!"); | 
| 1040 | 0 |  |  |  |  | 0 | @files = (); | 
| 1041 |  |  |  |  |  |  | } | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  | # Deleting large numbers of files from VMS Files-11 filesystems | 
| 1044 |  |  |  |  |  |  | # is faster if done in reverse ASCIIbetical order | 
| 1045 | 0 | 0 |  |  |  | 0 | @files = reverse @files if $Is_VMS; | 
| 1046 | 0 | 0 |  |  |  | 0 | ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS; | 
| 1047 | 0 |  |  |  |  | 0 | @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files); | 
| 1048 | 0 |  |  |  |  | 0 | $count += $self->rmtree([@files],$verbose,$safe); | 
| 1049 | 0 | 0 | 0 |  |  | 0 | if ($safe && | 
|  |  | 0 |  |  |  |  |  | 
| 1050 |  |  |  |  |  |  | ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) { | 
| 1051 | 0 | 0 |  |  |  | 0 | print "skipped '$root'\n" if $verbose; | 
| 1052 | 0 |  |  |  |  | 0 | next; | 
| 1053 |  |  |  |  |  |  | } | 
| 1054 | 0 | 0 | 0 |  |  | 0 | chmod 0777, $root | 
| 1055 |  |  |  |  |  |  | or $self->warn("Could not make directory '$root' writable: $!") | 
| 1056 |  |  |  |  |  |  | if $force_writable; | 
| 1057 | 0 | 0 |  |  |  | 0 | print "rmdir '$root'\n" if $verbose; | 
| 1058 | 0 | 0 |  |  |  | 0 | if (rmdir $root) { | 
| 1059 | 0 |  |  |  |  | 0 | ++$count; | 
| 1060 |  |  |  |  |  |  | } | 
| 1061 |  |  |  |  |  |  | else { | 
| 1062 | 0 |  |  |  |  | 0 | $self->warn("Could not remove directory '$root': $!"); | 
| 1063 | 0 | 0 |  |  |  | 0 | chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root)) | 
|  |  | 0 |  |  |  |  |  | 
| 1064 |  |  |  |  |  |  | or $self->warn("and can't restore permissions to " | 
| 1065 |  |  |  |  |  |  | . sprintf("0%o",$rp) . "\n"); | 
| 1066 |  |  |  |  |  |  | } | 
| 1067 |  |  |  |  |  |  | } | 
| 1068 |  |  |  |  |  |  | else { | 
| 1069 | 0 | 0 | 0 |  |  | 0 | if (     $safe | 
|  |  | 0 | 0 |  |  |  |  | 
| 1070 |  |  |  |  |  |  | and ($Is_VMS ? !&VMS::Filespec::candelete($root) | 
| 1071 |  |  |  |  |  |  | : !(-l $root || -w $root)) | 
| 1072 |  |  |  |  |  |  | ) { | 
| 1073 | 0 | 0 |  |  |  | 0 | print "skipped '$root'\n" if $verbose; | 
| 1074 | 0 |  |  |  |  | 0 | next; | 
| 1075 |  |  |  |  |  |  | } | 
| 1076 | 0 | 0 | 0 |  |  | 0 | chmod 0666, $root | 
| 1077 |  |  |  |  |  |  | or $self->warn( "Could not make file '$root' writable: $!") | 
| 1078 |  |  |  |  |  |  | if $force_writable; | 
| 1079 | 0 | 0 |  |  |  | 0 | warn "unlink '$root'\n" if $verbose; | 
| 1080 |  |  |  |  |  |  | # delete all versions under VMS | 
| 1081 | 0 |  |  |  |  | 0 | for (;;) { | 
| 1082 | 0 | 0 |  |  |  | 0 | unless (unlink $root) { | 
| 1083 | 0 |  |  |  |  | 0 | $self->warn("Could not unlink file '$root': $!"); | 
| 1084 | 0 | 0 |  |  |  | 0 | if ($force_writable) { | 
| 1085 | 0 | 0 |  |  |  | 0 | chmod $rp, $root | 
| 1086 |  |  |  |  |  |  | or $self->warn("and can't restore permissions to " | 
| 1087 |  |  |  |  |  |  | . sprintf("0%o",$rp) . "\n"); | 
| 1088 |  |  |  |  |  |  | } | 
| 1089 | 0 |  |  |  |  | 0 | last; | 
| 1090 |  |  |  |  |  |  | } | 
| 1091 | 0 |  |  |  |  | 0 | ++$count; | 
| 1092 | 0 | 0 | 0 |  |  | 0 | last unless $Is_VMS && lstat $root; | 
| 1093 |  |  |  |  |  |  | } | 
| 1094 |  |  |  |  |  |  | } | 
| 1095 |  |  |  |  |  |  | } | 
| 1096 |  |  |  |  |  |  |  | 
| 1097 | 0 |  |  |  |  | 0 | return $count; | 
| 1098 |  |  |  |  |  |  | } | 
| 1099 |  |  |  |  |  |  |  | 
| 1100 |  |  |  |  |  |  |  | 
| 1101 |  |  |  |  |  |  | =head2 _flush_on_write | 
| 1102 |  |  |  |  |  |  |  | 
| 1103 |  |  |  |  |  |  | Title   : _flush_on_write | 
| 1104 |  |  |  |  |  |  | Usage   : $io->_flush_on_write($newval) | 
| 1105 |  |  |  |  |  |  | Function: Boolean flag to indicate whether to flush | 
| 1106 |  |  |  |  |  |  | the filehandle on writing when the end of | 
| 1107 |  |  |  |  |  |  | a component is finished (Sequences, Alignments, etc) | 
| 1108 |  |  |  |  |  |  | Args    : Optional new value | 
| 1109 |  |  |  |  |  |  | Returns : Value of _flush_on_write | 
| 1110 |  |  |  |  |  |  |  | 
| 1111 |  |  |  |  |  |  | =cut | 
| 1112 |  |  |  |  |  |  |  | 
| 1113 |  |  |  |  |  |  | sub _flush_on_write { | 
| 1114 | 11388 |  |  | 11388 |  | 18028 | my ($self, $value) = @_; | 
| 1115 | 11388 | 100 |  |  |  | 21076 | if (defined $value) { | 
| 1116 | 10730 |  |  |  |  | 17771 | $self->{'_flush_on_write'} = $value; | 
| 1117 |  |  |  |  |  |  | } | 
| 1118 | 11388 |  |  |  |  | 16803 | return $self->{'_flush_on_write'}; | 
| 1119 |  |  |  |  |  |  | } | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  |  | 
| 1122 |  |  |  |  |  |  | =head2 save_tempfiles | 
| 1123 |  |  |  |  |  |  |  | 
| 1124 |  |  |  |  |  |  | Title   : save_tempfiles | 
| 1125 |  |  |  |  |  |  | Usage   : $io->save_tempfiles(1) | 
| 1126 |  |  |  |  |  |  | Function: Boolean flag to indicate whether to retain tempfiles/tempdir | 
| 1127 |  |  |  |  |  |  | Args    : Value evaluating to TRUE or FALSE | 
| 1128 |  |  |  |  |  |  | Returns : Boolean value : 1 = save tempfiles/tempdirs, 0 = remove (default) | 
| 1129 |  |  |  |  |  |  |  | 
| 1130 |  |  |  |  |  |  | =cut | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 |  |  |  |  |  |  | sub save_tempfiles { | 
| 1133 | 34 |  |  | 34 | 1 | 50 | my $self = shift; | 
| 1134 | 34 | 50 |  |  |  | 65 | if (@_) { | 
| 1135 | 0 |  |  |  |  | 0 | my $value = shift; | 
| 1136 | 0 | 0 |  |  |  | 0 | $self->{save_tempfiles} = $value ? 1 : 0; | 
| 1137 |  |  |  |  |  |  | } | 
| 1138 | 34 |  | 50 |  |  | 135 | return $self->{save_tempfiles} || 0; | 
| 1139 |  |  |  |  |  |  | } | 
| 1140 |  |  |  |  |  |  |  | 
| 1141 |  |  |  |  |  |  |  | 
| 1142 |  |  |  |  |  |  | 1; |