require Carp; require Carp::Heavy; use APR::Util (); use overload nomethod => \&fatal, 'bool' => \&str, '==' => \&num_cmp, '!=' => \&num_cmp_not, '0+' => \&num, '""' => \&str; sub fatal { die __PACKAGE__ . ": Can't handle '$_[3]'" } # normally the object is created on the C side, but if you want to # create one from Perl, you can. just pass a hash with args: # rc, file, line, func sub new { my $class = shift; my %args = @_; bless \%args, $class; } # # - even though most of the time the error id is not useful to the end # users, developers may need to know it. For example in case of a # non-english user locale setting, the error string could be # incomprehensible to a developer, but by having the error id it's # possible to find the english equivalent # - the filename and line number are needed because perl doesn't # provide that info when exception objects are involved sub str { return sprintf "%s: (%d) %s at %s line %d", $_[0]->{func}, $_[0]->{rc}, APR::Error::strerror($_[0]->{rc}), $_[0]->{file}, $_[0]->{line}; } sub num { $_[0]->{rc} } sub num_cmp { $_[0]->{rc} == $_[1] } sub num_cmp_not { $_[0]->{rc} != $_[1] } # skip the wrappers from this package from the long callers trace $Carp::CarpInternal{+__PACKAGE__}++; # XXX: Carp::(confess|cluck) see no calls stack when Perl_croak is # called with (char *)NULL (which is the way exception objects are # returned), so we fixup it here (doesn't quite work for croak # caller). sub cluck { if (ref $_[0] eq __PACKAGE__) { Carp::cluck("$_[0]->{func}: ($_[0]->{rc}) " . APR::Error::strerror($_[0]->{rc})); } else { &Carp::cluck; } } sub confess { if (ref $_[0] eq __PACKAGE__) { Carp::confess("$_[0]->{func}: ($_[0]->{rc}) " . APR::Error::strerror($_[0]->{rc})); } else { &Carp::confess; } }