NAME
    IO::Detect - is this a frickin' filehandle or what?!

SYNOPSIS
            use IO::Detect;
        
            if (is_filehandle $fh)
            {
                    my $line = <$fh>;
            }

DESCRIPTION
    It is stupidly complicated to detect whether a given scalar is a
    filehandle (or something filehandle like) in Perl. This module attempts
    to do so, but probably falls short in some cases. The primary advantage
    of using this module is that it gives you somebody to blame (me) if your
    code can't detect a filehandle.

    The main use case for IO::Detect is for when you are writing functions
    and you want to allow the caller to pass a file as an argument without
    being fussy as to whether they pass a file name or a file handle.

  Functions
    Each function takes a single argument, or if called with no argument,
    operates on $_.

    "is_filehandle $thing"
        Theoretically returns true if and only if $thing is a file handle,
        or may be treated as a filehandle. That includes blessed references
        to filehandles, things that inherit from IO::Handle, etc.

        It's never going to work 100%. What Perl allows you to use as a
        filehandle is mysterious and somewhat context-dependent, as the
        following code illustrates.

                my $fh = "STD" . "OUT";
                print $fh "Hello World!\n";

    "is_filename $thing"
        Returns true if $thing is a IO::All object or Path::Class::Entity or
        "any non-reference, non-zero-length string with no line breaks".
        That's because depending on your operating system, virtually
        anything can be used as a filename. (In fact, on many systems,
        including Linux, filenames can contain line breaks. However, this is
        unlikely to be intentional.)

        This function doesn't tell you whether $thing is an existing file on
        your system. It attempts to tell you whether $thing could possibly
        be a filename on some system somewhere.

    "is_fileuri $thing"
        Returns true if $thing is a URI beginning with "file://". It allows
        for URI objects, RDF::Trine::Node::Resource objects, strings and
        objects that overload stringification.

        This function actually returns an "interesting value of true". The
        value returned is a URI::file object.

  Smart Matching
    You can import three constants for use in smart matching:

            use IO::Detect -smartmatch;

    These constants are:

    "FileHandle"
    "FileName"
    "FileUri"

    They can be used like this:

            if ($file ~~ FileHandle)
            {
                    ...
            }

    Note that there does exist a FileHandle package in Perl core. This
    module attempts to do the right thing so that "FileHandle->new" still
    works, but there are conveivably places this could go wrong, or be plain
    old confusing.

  Precedence
    Because there is some overlap/ambiguity between what is a filehandle and
    what is a filename, etc, if you need to detect between them, I recommend
    checking "is_filehandle" first, then "is_fileuri" and falling back to
    "is_filename".

            for ($file)
            {
                    when (FileHandle)  { ... }
                    when (FileUri)     { ... }
                    when (FileName)    { ... }
                    default            { die "$file is not a file!" }
            }

  Duck Typing
    In some cases you might be happy to accept something less than a
    complete file handle. In this case you can import a customised "duck
    type" test...

            use IO::Detect
                    -default,
                    ducktype => {
                            -as     => 'is_slurpable',
                            methods => [qw(getlines close)],
                    };
        
            sub do_something_with_a_file
            {
                    my $f = shift;
                    if ( is_filehandle $f or is_slurpable $f )
                            { ... }
                    elsif ( is_filename $f )
                            { ... }
            }

    Duck type test functions only test that the argument is blessed and can
    do all of the specified methods. They don't test any other aspect of
    "filehandliness".

BUGS
    Please report any bugs to
    <http://rt.cpan.org/Dist/Display.html?Queue=IO-Detect>.

SEE ALSO
    This module is an attempt to capture some of the wisdom from this
    PerlMonks thread <http://www.perlmonks.org/?node_id=980665> into
    executable code.

    Various other modules that may be of interest, in no particular order...
    Scalar::Util, FileHandle, IO::Handle, IO::Handle::Util, IO::All,
    Path::Class, URI::file.

AUTHOR
    Toby Inkster <tobyink@cpan.org>.

COPYRIGHT AND LICENCE
    This software is copyright (c) 2012 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

