package Safe::Caller;

use strict;
use warnings;
use boolean qw(true false);

use Carp qw(croak);

our $VERSION = '0.09';

use constant FRAMES => 1;

sub new
{
    my $class = shift;
    my ($frames) = @_;
    $frames ||= FRAMES;

    my $caller = sub
    {
        my ($f, $elem) = @_;
        my $frames = defined $f ? $f : $frames;
        return (caller($frames + 2))[$elem] || '';
    };

    # All fields required because we need
    # to retain backwards compatibility.
    my @sets = (
        [qw(package pkg)],
        [qw(filename file)],
        'line',
        [qw(subroutine sub)],
        'hasargs',
        'wantarray',
        'evaltext',
        'is_require',
        'hints',
        'bitmask'
    );

    my %fields;
    my $i = 0;
    foreach my $set (@sets) {
        foreach my $name (ref $set eq 'ARRAY' ? @$set : $set) {
            $fields{$name} = $i;
        }
        $i++;
    }

    my $accessors = {};
    foreach my $name (keys %fields) {
        $accessors->{$name} = sub
        {
            my $frames = shift;
            return $caller->($frames, $fields{$name});
        };
    }
    $accessors->{_frames} = $frames;

    return bless $accessors, ref($class) || $class;
}

sub called_from_package
{
    my $self = shift;
    my ($called_from_package) = @_;
    croak q(Usage: $caller->called_from_package('Package');)
      unless defined $called_from_package;

    return $self->{package}->() eq $called_from_package
      ? true : false;
}

sub called_from_filename
{
    my $self = shift;
    my ($called_from_filename) = @_;
    croak q(Usage: $caller->called_from_filename('file');)
      unless defined $called_from_filename;

    return $self->{filename}->() eq $called_from_filename
      ? true : false;
}

sub called_from_line
{
    my $self = shift;
    my ($called_from_line) = @_;
    croak q(Usage: $caller->called_from_line(42);)
      unless defined $called_from_line && $called_from_line =~ /^\d+$/;

    return $self->{line}->() == $called_from_line
      ? true : false;
}

sub called_from_subroutine
{
    my $self = shift;
    my ($called_from_subroutine) = @_;
    croak q(Usage: $caller->called_from_subroutine('Package::sub');)
      unless defined $called_from_subroutine;

    return $self->{subroutine}->($self->{_frames} + 1) eq $called_from_subroutine
      ? true : false;
}

# backwards compatibility (deprecated)
*called_from_pkg  = \&called_from_package;
*called_from_file = \&called_from_filename;
*called_from_sub  = \&called_from_subroutine;

1;
__END__

=head1 NAME

Safe::Caller - Control code execution based upon caller()

=head1 SYNOPSIS

 package abc;

 use Safe::Caller;

 $caller = Safe::Caller->new;

 a();

 sub a { b() }

 sub b {
     if ($caller->called_from_subroutine('abc::a')) { # do stuff }
     print $caller->{subroutine}->();
 }

=head1 DESCRIPTION

=head1 CONSTRUCTOR

=head2 new

 $caller = Safe::Caller->new(1);

Providing how many frames to go back while running L<perlfunc/caller> is optional.
By default (if no suitable value is provided) 1 will be assumed. The default
will be shared among all accessors and verification routines; the accessors
may optionally accept a frame as argument, whereas verification routines
(C<called_from_*()>) don't.

=head1 METHODS

=head2 called_from_package

Checks whether the current sub was called within the given package.

 $caller->called_from_package('Package');

Returns true on success, false on failure.

=head2 called_from_filename

Checks whether the current sub was called within the given filename.

 $caller->called_from_filename('file');

Returns true on success, false on failure.

=head2 called_from_line

Checks whether the current sub was called on the given line.

 $caller->called_from_line(42);

Returns true on success, false on failure.

=head2 called_from_subroutine

Checks whether the current sub was called by the given subroutine.

 $caller->called_from_subroutine('Package::sub');

Returns true on success, false on failure.

=head1 ACCESSORS

 $caller->{package}->();
 $caller->{filename}->();
 $caller->{line}->();
 $caller->{subroutine}->();
 $caller->{hasargs}->();
 $caller->{wantarray}->();
 $caller->{evaltext}->();
 $caller->{is_require}->();
 $caller->{hints}->();
 $caller->{bitmask}->();

See L<perlfunc/caller> for the values they are supposed to return.

=head1 SEE ALSO

L<perlfunc/caller>, L<Perl6::Caller>, L<Devel::Caller>, L<Sub::Caller>

=head1 AUTHOR

Steven Schubiger <schubiger@cpan.org>

=head1 LICENSE

This program is free software; you may redistribute it and/or
modify it under the same terms as Perl itself.

See L<http://dev.perl.org/licenses/>

=cut
