Result:
found more than 82 distributions - search limited to the first 2001 files matching your query ( run in 1.013129 )


AAAA-Crypt-DH

inc/Devel/CheckLib.pm

# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $

package #
Devel::CheckLib;

use 5.00405; #postfix foreach
use strict;
use vars qw($VERSION @ISA @EXPORT);
$VERSION = '1.09';
use Config qw(%Config);
use Text::ParseWords 'quotewords';

use File::Spec;
use File::Temp;

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(assert_lib check_lib_or_exit check_lib);

# localising prevents the warningness leaking out of this module
local $^W = 1;    # use warnings is a 5.6-ism

_findcc(); # bomb out early if there's no compiler

=head1 NAME

Devel::CheckLib - check that a library is available

=head1 DESCRIPTION

Devel::CheckLib is a perl module that checks whether a particular C
library and its headers are available.

=head1 SYNOPSIS

    use Devel::CheckLib;

    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
  
    # or prompt for path to library and then do this:
    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );

=head1 USING IT IN Makefile.PL or Build.PL

If you want to use this from Makefile.PL or Build.PL, do
not simply copy the module into your distribution as this may cause
problems when PAUSE and search.cpan.org index the distro.  Instead, use
the use-devel-checklib script.

=head1 HOW IT WORKS

You pass named parameters to a function, describing to it how to build
and link to the libraries.

It works by trying to compile some code - which defaults to this:

    int main(int argc, char *argv[]) { return 0; }

and linking it to the specified libraries.  If something pops out the end
which looks executable, it gets executed, and if main() returns 0 we know
that it worked.  That tiny program is
built once for each library that you specify, and (without linking) once
for each header file.

If you want to check for the presence of particular functions in a
library, or even that those functions return particular results, then
you can pass your own function body for main() thus:

    check_lib_or_exit(
        function => 'foo();if(libversion() > 5) return 0; else return 1;'
        incpath  => ...
        libpath  => ...
        lib      => ...
        header   => ...
    );

In that case, it will fail to build if either foo() or libversion() don't
exist, and main() will return the wrong value if libversion()'s return
value isn't what you want.

=head1 FUNCTIONS

All of these take the same named parameters and are exported by default.
To avoid exporting them, C<use Devel::CheckLib ()>.

=head2 assert_lib

This takes several named parameters, all of which are optional, and dies
with an error message if any of the libraries listed can
not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
C<check_lib_or_exit> instead.

The named parameters are:

=over

=item lib

Must be either a string with the name of a single 
library or a reference to an array of strings of library names.  Depending
on the compiler found, library names will be fed to the compiler either as
C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)

=item libpath

a string or an array of strings
representing additional paths to search for libraries.

=item LIBS

a C<ExtUtils::MakeMaker>-style space-separated list of
libraries (each preceded by '-l') and directories (preceded by '-L').

This can also be supplied on the command-line.

=item debug

If true - emit information during processing that can be used for
debugging.

=back

And libraries are no use without header files, so ...

=over

=item header

Must be either a string with the name of a single 
header file or a reference to an array of strings of header file names.

=item incpath

a string or an array of strings
representing additional paths to search for headers.

=item INC

a C<ExtUtils::MakeMaker>-style space-separated list of
incpaths, each preceded by '-I'.

This can also be supplied on the command-line.

=item ccflags

Extra flags to pass to the compiler.

=item ldflags

Extra flags to pass to the linker.

=item analyze_binary

a callback function that will be invoked in order to perform custom
analysis of the generated binary. The callback arguments are the
library name and the path to the binary just compiled.

It is possible to use this callback, for instance, to inspect the
binary for further dependencies.

=back

=head2 check_lib_or_exit

This behaves exactly the same as C<assert_lib()> except that instead of
dieing, it warns (with exactly the same error message) and exits.
This is intended for use in Makefile.PL / Build.PL
when you might want to prompt the user for various paths and
things before checking that what they've told you is sane.

If any library or header is missing, it exits with an exit value of 0 to avoid
causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
result -- which is what you want if an external library dependency is not
available.

=head2 check_lib

This behaves exactly the same as C<assert_lib()> except that it is silent,
returning false instead of dieing, or true otherwise.

=cut

sub check_lib_or_exit {
    eval 'assert_lib(@_)';
    if($@) {
        warn $@;
        exit;
    }
}

sub check_lib {
    eval 'assert_lib(@_)';
    return $@ ? 0 : 1;
}

# borrowed from Text::ParseWords
sub _parse_line {
    my($delimiter, $keep, $line) = @_;
    my($word, @pieces);

    no warnings 'uninitialized';  # we will be testing undef strings

    while (length($line)) {
        # This pattern is optimised to be stack conservative on older perls.
        # Do not refactor without being careful and testing it on very long strings.
        # See Perl bug #42980 for an example of a stack busting input.
        $line =~ s/^
                    (?:
                        # double quoted string
                        (")                             # $quote
                        ((?>[^\\"]*(?:\\.[^\\"]*)*))"   # $quoted
        | # --OR--
                        # singe quoted string
                        (')                             # $quote
                        ((?>[^\\']*(?:\\.[^\\']*)*))'   # $quoted
                    |   # --OR--
                        # unquoted string
                        (                               # $unquoted
                            (?:\\.|[^\\"'])*?
                        )
                        # followed by
                        (                               # $delim
                            \Z(?!\n)                    # EOL
                        |   # --OR--
                            (?-x:$delimiter)            # delimiter
                        |   # --OR--
                            (?!^)(?=["'])               # a quote
                        )
        )//xs or return;    # extended layout
        my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6);

        return() unless( defined($quote) || length($unquoted) || length($delim));

        if ($keep) {
            $quoted = "$quote$quoted$quote";
        }
        else {
            $unquoted =~ s/\\(.)/$1/sg;
            if (defined $quote) {
                $quoted =~ s/\\(.)/$1/sg if ($quote eq '"');
            }
        }
        $word .= substr($line, 0, 0); # leave results tainted
        $word .= defined $quote ? $quoted : $unquoted;

        if (length($delim)) {
            push(@pieces, $word);
            push(@pieces, $delim) if ($keep eq 'delimiters');
            undef $word;
        }
        if (!length($line)) {
            push(@pieces, $word);
        }
    }
    return(@pieces);
}

sub assert_lib {
    my %args = @_;
    my (@libs, @libpaths, @headers, @incpaths);

    # FIXME: these four just SCREAM "refactor" at me
    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
        if $args{lib};
    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
        if $args{libpath};
    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
        if $args{header};
    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
        if $args{incpath};
    my $analyze_binary = $args{analyze_binary};

    my @argv = @ARGV;
    push @argv, _parse_line('\s+', 0, $ENV{PERL_MM_OPT}||'');

    # work-a-like for Makefile.PL's LIBS and INC arguments
    # if given as command-line argument, append to %args
    for my $arg (@argv) {
        for my $mm_attr_key (qw(LIBS INC)) {
            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
            # it is tempting to put some \s* into the expression, but the
            # MM command-line parser only accepts LIBS etc. followed by =,
            # so we should not be any more lenient with whitespace than that
                $args{$mm_attr_key} .= " $mm_attr_value";
            }
        }
    }

    # using special form of split to trim whitespace
    if(defined($args{LIBS})) {
        foreach my $arg (split(' ', $args{LIBS})) {
            die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/);
            push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2);
        }
    }
    if(defined($args{INC})) {
        foreach my $arg (split(' ', $args{INC})) {
            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
            push @incpaths, substr($arg, 2);
        }
    }

    my ($cc, $ld) = _findcc($args{debug}, $args{ccflags}, $args{ldflags});
    my @missing;
    my @wrongresult;
    my @wronganalysis;
    my @use_headers;

    # first figure out which headers we can't find ...
    for my $header (@headers) {
        push @use_headers, $header;
        my($ch, $cfile) = File::Temp::tempfile(
            'assertlibXXXXXXXX', SUFFIX => '.c'
        );
        my $ofile = $cfile;
        $ofile =~ s/\.c$/$Config{_o}/;
        print $ch qq{#include <$_>\n} for @use_headers;
        print $ch qq{int main(void) { return 0; }\n};
        close($ch);
        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
        my @sys_cmd;
        # FIXME: re-factor - almost identical code later when linking
        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
            require Win32;
            @sys_cmd = (
                @$cc,
                $cfile,
                "/Fe$exefile",
                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
		"/link",
		@$ld,
		split(' ', $Config{libs}),
            );
        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
            @sys_cmd = (
                @$cc,
                @$ld,
                (map { "-I$_" } @incpaths),
                "-o$exefile",
                $cfile
            );
        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
            @sys_cmd = (
                @$cc,
                @$ld,
                $cfile,
                (map { "-I$_" } @incpaths),
                "-o", "$exefile"
            );
        }
        warn "# @sys_cmd\n" if $args{debug};
        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
        push @missing, $header if $rv != 0 || ! -x $exefile;
        _cleanup_exe($exefile);
        unlink $cfile;
    }

    # now do each library in turn with headers
    my($ch, $cfile) = File::Temp::tempfile(
        'assertlibXXXXXXXX', SUFFIX => '.c'
    );
    my $ofile = $cfile;
    $ofile =~ s/\.c$/$Config{_o}/;
    print $ch qq{#include <$_>\n} foreach (@headers);
    print $ch "int main(int argc, char *argv[]) { ".($args{function} || 'return 0;')." }\n";
    close($ch);
    for my $lib ( @libs ) {
        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
        my @sys_cmd;
        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
            require Win32;
            my @libpath = map { 
                q{/libpath:} . Win32::GetShortPathName($_)
            } @libpaths; 
            # this is horribly sensitive to the order of arguments
            @sys_cmd = (
                @$cc,
                $cfile,
                "${lib}.lib",
                "/Fe$exefile", 
                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                "/link",
                @$ld,
                split(' ', $Config{libs}),
                (map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths),
            );
        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
            @sys_cmd = (
                @$cc,
                @$ld,
                "-o$exefile",
                (map { "-I$_" } @incpaths),
                (map { "-L$_" } @libpaths),
                "-l$lib",
                $cfile);
        } else {                                     # Unix-ish
                                                     # gcc, Sun, AIX (gcc, cc)
            @sys_cmd = (
                @$cc,
                @$ld,
                $cfile,
                "-o", "$exefile",
                (map { "-I$_" } @incpaths),
                (map { "-L$_" } @libpaths),
                "-l$lib",
            );
        }
        warn "# @sys_cmd\n" if $args{debug};
        local $ENV{LD_RUN_PATH} = join(":", @libpaths).":".$ENV{LD_RUN_PATH} unless $^O eq 'MSWin32';
        local $ENV{PATH} = join(";", @libpaths).";".$ENV{PATH} if $^O eq 'MSWin32';
        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
        if ($rv != 0 || ! -x $exefile) {
            push @missing, $lib;
        }
        else {
            my $absexefile = File::Spec->rel2abs($exefile);
            $absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/;
            if (system($absexefile) != 0) {
                push @wrongresult, $lib;
            }
            else {
                if ($analyze_binary) {
                    push @wronganalysis, $lib if !$analyze_binary->($lib, $exefile)
                }
            }
        }
        _cleanup_exe($exefile);
    } 
    unlink $cfile;

    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
    die("Can't link/include C library $miss_string, aborting.\n") if @missing;
    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
    die("wrong result: $wrong_string\n") if @wrongresult;
    my $analysis_string = join(q{, }, map { qq{'$_'} } @wronganalysis );
    die("wrong analysis: $analysis_string") if @wronganalysis;
}

sub _cleanup_exe {
    my ($exefile) = @_;
    my $ofile = $exefile;
    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
    # List of files to remove
    my @rmfiles;
    push @rmfiles, $exefile, $ofile, "$exefile\.manifest";
    if ( $Config{cc} eq 'cl' ) {
        # MSVC also creates foo.ilk and foo.pdb
        my $ilkfile = $exefile;
        $ilkfile =~ s/$Config{_exe}$/.ilk/;
        my $pdbfile = $exefile;
        $pdbfile =~ s/$Config{_exe}$/.pdb/;
	push @rmfiles, $ilkfile, $pdbfile;
    }
    foreach (@rmfiles) {
	if ( -f $_ ) {
	    unlink $_ or warn "Could not remove $_: $!";
	}
    }
    return
}
    
# return ($cc, $ld)
# where $cc is an array ref of compiler name, compiler flags
# where $ld is an array ref of linker flags
sub _findcc {
    my ($debug, $user_ccflags, $user_ldflags) = @_;
    # Need to use $keep=1 to work with MSWin32 backslashes and quotes
    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
    my @Config_ldflags = ();
    for my $config_val ( @Config{qw(ldflags)} ){
        push @Config_ldflags, $config_val if ( $config_val =~ /\S/ );
    }
    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||'', $user_ccflags||'');
    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags, $user_ldflags||'');
    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
    my @cc = split(/\s+/, $Config{cc});
    if (check_compiler ($cc[0], $debug)) {
	return ( [ @cc, @ccflags ], \@ldflags );
    }
    # Find the extension for executables.
    my $exe = $Config{_exe};
    if ($^O eq 'cygwin') {
	$exe = '';
    }
    foreach my $path (@paths) {
	# Look for "$path/$cc[0].exe"
        my $compiler = File::Spec->catfile($path, $cc[0]) . $exe;
	if (check_compiler ($compiler, $debug)) {
	    return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
	}
        next if ! $exe;
	# Look for "$path/$cc[0]" without the .exe, if necessary.
        $compiler = File::Spec->catfile($path, $cc[0]);
	if (check_compiler ($compiler, $debug)) {
	    return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
	}
    }
    die("Couldn't find your C compiler.\n");
}

sub check_compiler
{
    my ($compiler, $debug) = @_;
    if (-f $compiler && -x $compiler) {
	if ($debug) {
	    warn("# Compiler seems to be $compiler\n");
	}
	return 1;
    }
    return '';
}


# code substantially borrowed from IPC::Run3
sub _quiet_system {
    my (@cmd) = @_;

    # save handles
    local *STDOUT_SAVE;
    local *STDERR_SAVE;
    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
    
    # redirect to nowhere
    local *DEV_NULL;
    open DEV_NULL, ">" . File::Spec->devnull 
        or die "CheckLib: $! opening handle to null device";
    open STDOUT, ">&" . fileno DEV_NULL
        or die "CheckLib: $! redirecting STDOUT to null handle";
    open STDERR, ">&" . fileno DEV_NULL
        or die "CheckLib: $! redirecting STDERR to null handle";

    # run system command
    my $rv = system(@cmd);

    # restore handles
    open STDOUT, ">&" . fileno STDOUT_SAVE
        or die "CheckLib: $! restoring STDOUT handle";
    open STDERR, ">&" . fileno STDERR_SAVE
        or die "CheckLib: $! restoring STDERR handle";

    return $rv;
}

=head1 PLATFORMS SUPPORTED

You must have a C compiler installed.  We check for C<$Config{cc}>,
both literally as it is in Config.pm and also in the $PATH.

It has been tested with varying degrees of rigorousness on:

=over

=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)

=item Sun's compiler tools on Solaris

=item IBM's tools on AIX

=item SGI's tools on Irix 6.5

=item Microsoft's tools on Windows

=item MinGW on Windows (with Strawberry Perl)

=item Borland's tools on Windows

=item QNX

=back

=head1 WARNINGS, BUGS and FEEDBACK

This is a very early release intended primarily for feedback from
people who have discussed it.  The interface may change and it has
not been adequately tested.

Feedback is most welcome, including constructive criticism.
Bug reports should be made using L<http://rt.cpan.org/> or by email.

When submitting a bug report, please include the output from running:

    perl -V
    perl -MDevel::CheckLib -e0

=head1 SEE ALSO

L<Devel::CheckOS>

L<Probe::Perl>

=head1 AUTHORS

David Cantrell E<lt>david@cantrell.org.ukE<gt>

David Golden E<lt>dagolden@cpan.orgE<gt>

Yasuhiro Matsumoto E<lt>mattn@cpan.orgE<gt>

Thanks to the cpan-testers-discuss mailing list for prompting us to write it
in the first place;

to Chris Williams for help with Borland support;

to Tony Cook for help with Microsoft compiler command-line options

=head1 COPYRIGHT and LICENCE

Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.

This module is free-as-in-speech software, and may be used, distributed,
and modified under the same conditions as perl itself.

=head1 CONSPIRACY

This module is also free-as-in-mason software.

=cut

1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

AAAA-Mail-SpamAssassin

lib/AAAA/Mail/SpamAssassin.pm

use strict;
use warnings;
package AAAA::Mail::SpamAssassin;
# git description: v0.001-1-g4fcbc88

BEGIN {
  $AAAA::Mail::SpamAssassin::AUTHORITY = 'cpan:SCHWIGON';
}
{
  $AAAA::Mail::SpamAssassin::VERSION = '0.002';
}
# ABSTRACT: making Mail::SpamAssassin installable

1;



=pod

=encoding utf-8

=head1 NAME

AAAA::Mail::SpamAssassin - making Mail::SpamAssassin installable

=head1 SYNOPSIS

  # in Makefile.PL

  requires 'AAAA::Mail::SpamAssassin';

=head1 DESCRIPTION

For some reason dependency resolution via the CPAN toolchains does not
work very well for L<Mail::SpamAssassin>. To install it without manual
work you need dependencies installed beforehand.

C<AAAA::Mail::SpamAssassin> is a L<Task>-style distribution that makes
sure that dependencies are installed so that L<Mail::SpamAssassin>
installation does not complain.

If you have a dependency on L<Mail::SpamAssassin> add
C<AAAA::Mail::SpamAssassin> as an additional dependency and (only) the
most crucial dependencies will be installed before
L<Mail::SpamAssassin>.

Why the C<'AAAA'>? L<CPAN> and L<CPANPLUS> install prereqs sorted
alphabetically, the C<'AAAA'> ensures that this prereq is installed
before L<Mail::SpamAssassin>. Simples.

=head1 Acknowledgements

Idea shamelessly stolen from Chris C<BinGOs> Williams'
L<AAAA::Crypt::DH|AAAA::Crypt::DH>.

=head1 SEE ALSO

L<Mail::SpamAssassin>

L<AAAA::Crypt::DH>

=head1 AUTHOR

Steffen Schwigon <ss5@renormalist.net>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Steffen Schwigon.

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

=cut


__END__

 view all matches for this distribution
 view on metacpan -  search on metacpan

AAAAAAAAA

aaa/AAAAAAAAA.pm

package AAAAAAAAA;

use strict;
use warnings;

our $VERSION = '1.01';

my @aaaaaaa = ('a'..'z', 'A'..'Z', 0..9);
my %aaaaaaaa_aa_aaaa;
for my $a (0..$#aaaaaaa) {
    my $aaaa = sprintf("%06b", $a);
    $aaaa =~ s{0}{a}g;
    $aaaa =~ s{1}{A}g;
    $aaaaaaaa_aa_aaaa{ $aaaaaaa[$a] } = $aaaa;
}

my %aaaa_aa_aaaaaaaa;
@aaaa_aa_aaaaaaaa{values %aaaaaaaa_aa_aaaa} = keys %aaaaaaaa_aa_aaaa;

sub aaaa {
    open my $aa, "<", $0 or die "Aaa'a aaaa aaa aaaaaa aaaa aaa aaaaaaaaaaa: $!";

    my $aaaa = join "", <$aa>;
    $aaaa =~ s{use\s+AAAAAAAAA\b}{}x;

    # Aaa aaa aaaaaaa
    if( $aaaa =~ /[b-zB-Z0-9]/ ) {
        my $aaaaaaaa_aaaa = $aaaa;
        aaaaaa(\$aaaa);
        eval $aaaaaaaa_aaaa;
    }
    else {
        aaaaaaaa(\$aaaa);
        eval $aaaa;
    }

    exit;
}

sub aaaaaa {
    my $aaaa = shift;

    $$aaaa =~ s{([a-zA-Z0-9])}{$aaaaaaaa_aa_aaaa{$1}}gx;

    open my $aa, ">", $0 or die "Aaa'a aaaa aaa aaaaaa aaaa aaa aaaaaaaaaaa: $!";
    print $aa "use AAAAAAAAA";
    print $aa $$aaaa;

    return;
}


sub aaaaaaaa {
    my $aaaa = shift;

    $$aaaa =~ s{ ([Aa]{6}) }{$aaaa_aa_aaaaaaaa{$1}}gx;

    return;
}


aaaa();


=head1 AAAA

AAAAAAAAA - Aaaaaa aaaaa aa aaaaaa Aaaaa aaaa

=head1 AAAAAAAA

    use AAAAAAAAA;

=head1 AAAAAAAAAAA

AAAAAAA AA AAA AAAAAAAAA AAAAA AA AAAAAA AAAAAA, AAAAAAA AA AAAAAA
AAAAAA, AAAAA AAAAAAA AAA! AA AAA AAAA AAAA AAAAAAAA AAAA AA AAAAAA
AAAAA

    AAAA AAAA AAAAAA AA AAA!
    AAA AAAA AAAA AAA!
    AAAAAAA AAAAA AAA!
    AAAAA AAAA AAA!
    AAAA AAAAA AAA!
    AAA AAAAAA "A" AAAA AAA! 

AAAAA AAA AAA, AAAAAAA AAA AAAA, AA AAAAAA AAAAAA, AAAA AAAAA AAA!


AAAA, AA AAAAAA AAAAAA, AAAA AAAA(A) AAA!
AA AAA AAAA AA AAAAA AAAAAAA AAAAAAA?

AAAAAAA AA AAAAAA AAAAAA , AAAAAA AAAAA AA AAAAA AAAA AAA!

AAAAAA, AA AAAAA AAAAAAAAA AAAAAAA, AAA AAAAAAA AAAAAAAA. (AA AAAAAA
AAAAAA-AA, AAAAA AAAA.) AAAA, AA AAAA AAAAA'A AA AAA AAAAA, AAAA AAAA
AA AAA AAA AAAAAAA, AAAAAAAAAAAA AAA AAAAA (AA AAAAAAA AA AA, AA, AA
AAA), AA AAAAA AAAAAA AAAA AAA AA AAA AAA. AA AAAA AA AAA AAA AAAAA
AAAAAA AAAAAAA.  AAAAA AAAAA

AAAAA AAAAA AAA AA AAAAAAA AAAA AAAAAA AAAAAA AAAAAAA

=cut


'A reckless disregard for taste';

 view all matches for this distribution
 view on metacpan -  search on metacpan

AAC-Pvoice

lib/AAC/Pvoice.pm

package AAC::Pvoice;

use strict;
use warnings;

use Wx qw(:everything);
use Wx::Perl::Carp;
use AAC::Pvoice::Bitmap;
use AAC::Pvoice::Input;
use AAC::Pvoice::Row;
use AAC::Pvoice::EditableRow;
use AAC::Pvoice::Panel;
use AAC::Pvoice::Dialog;
use Text::Wrap qw(wrap);

BEGIN {
	use Exporter ();
	use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
	$VERSION     = 0.91;
	@ISA         = qw (Exporter);
	@EXPORT      = qw (MessageBox);
	@EXPORT_OK   = qw ();
	%EXPORT_TAGS = ();
}

sub MessageBox
{
	my ($message, $caption, $style, $parent, $x, $y) = @_;
    $caption ||= 'Message';
	$style   ||= wxOK;
	$x       ||= -1;
	$y       ||= -1;

	$Text::Wrap::columns = 25;
	$message = wrap('','',$message)."\n";
	
    my $width = 0;
    $width = 25 if $style & wxOK;
    $width = 30 if $style & wxYES_NO;
    $width = 60 if $style & wxCANCEL;

	my $p = Wx::Frame->new(undef, -1, 'tmp');
	my $m = Wx::StaticText->new($p, -1, $message, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
	$m->SetFont(Wx::Font->new(  10,                 # font size
                                wxDECORATIVE,       # font family
                                wxNORMAL,           # style
                                wxNORMAL,           # weight
                                0,                  
                                'Comic Sans MS',    # face name
                                wxFONTENCODING_SYSTEM));

	my $h = $m->GetSize->GetHeight;
	$p->Destroy;

	my $d = AAC::Pvoice::Dialog->new(undef, -1, $caption, [$x,$y], [310,100+$h]);
	
	my $messagectrl = Wx::StaticText->new($d->{panel},
                                          -1,
                                          $message,
                                          wxDefaultPosition,
                                          wxDefaultSize,
                                          wxALIGN_CENTRE);
	$messagectrl->SetBackgroundColour($d->{backgroundcolour});
	$messagectrl->SetFont(Wx::Font->new(10,                 # font size
                                        wxDECORATIVE,       # font family
                                        wxNORMAL,           # style
                                        wxNORMAL,           # weight
                                        0,                  
                                        'Comic Sans MS',    # face name
                                        wxFONTENCODING_SYSTEM));

	$d->Append($messagectrl,1);
    my $ok     = [Wx::NewId,AAC::Pvoice::Bitmap->new('',50,25,'OK',    Wx::Colour->new(255, 230, 230)),sub{$d->SetReturnCode(wxOK);    $d->Close()}];
    my $yes    = [Wx::NewId,AAC::Pvoice::Bitmap->new('',50,30,'Yes',   Wx::Colour->new(255, 230, 230)),sub{$d->SetReturnCode(wxYES);   $d->Close()}];
    my $no     = [Wx::NewId,AAC::Pvoice::Bitmap->new('',50,25,'No',    Wx::Colour->new(255, 230, 230)),sub{$d->SetReturnCode(wxNO);    $d->Close()}];
    my $cancel = [Wx::NewId,AAC::Pvoice::Bitmap->new('',50,60,'Cancel',Wx::Colour->new(255, 230, 230)),sub{$d->SetReturnCode(wxCANCEL);$d->Close()}];
    my $items = [];
    push @$items, $ok     if $style & wxOK;
    push @$items, $yes    if $style & wxYES_NO;
    push @$items, $no     if $style & wxYES_NO;
    push @$items, $cancel if $style & wxCANCEL;
	$d->Append(AAC::Pvoice::Row->new($d->{panel},          # parent
                                     scalar(@$items),      # max
                                     $items,               # items
                                     wxDefaultPosition,    # pos
                                     wxDefaultSize,
                                     $width,
                                     25,
                                     $d->{ITEMSPACING},
                                     $d->{backgroundcolour}),
                0); #selectable
	return $d->ShowModal();
}

=pod

=head1 NAME

AAC::Pvoice - Create GUI software for disabled people

=head1 SYNOPSIS

  use AAC::Pvoice
  # this includes all AAC::Pvoice modules


=head1 DESCRIPTION

AAC::Pvoice is a set of modules to create software for people who can't
use a normal mouse and/or keyboard. To see an application that uses this
set of modules, take a look at pVoice (http://www.pvoice.org, or the
sources on http://opensource.pvoice.org). 

AAC::Pvoice is in fact a wrapper around many wxPerl classes, to make it
easier to create applications like pVoice.


=head1 USAGE

=head2 AAC::Pvoice::MessageBox(message, caption, style, parent, x, y)

This function is similar to Wx::MessageBox. It uses the same parameters as
Wx::MessageBox does. Currently the style parameter doesn't support the
icons that can be set on Wx::MessageBox.

See the individual module's documentation

=head1 BUGS

probably a lot, patches welcome!


=head1 AUTHOR

	Jouke Visser
	jouke@pvoice.org
	http://jouke.pvoice.org

=head1 COPYRIGHT

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

The full text of the license can be found in the
LICENSE file included with this module.


=head1 SEE ALSO

perl(1), Wx, AAC::Pvoice::Panel, AAC::Pvoice::Bitmap, AAC::Pvoice::Row
AAC::Pvoice::EditableRow, AAC::Pvoice::Input

=cut


1; 
__END__

 view all matches for this distribution
 view on metacpan -  search on metacpan

ABI

ABI.pm

#$Id: ABI.pm,v 1.3.2.4 2006/11/20 03:18:12 malay Exp $
# Perl module to parse ABI chromatogram file
# Malay <malay@bioinformatics.org>
# Copyright (c) 2002, 2003, 2004, 2005, 2006 Malay Kumar Basu
# You may distribute this module under the same terms as perl itself
# Thanks to David H. Klatte for all the hard work!
package ABI;
use IO::File;
use Carp;
use strict;

=head1 NAME

ABI.pm - Perl module to parse chromatogram files generated by
Applied Biosystems (ABI) automated DNA sequencing machine.

Please cite:
ABI.pm - Perl module to parse chromatogram files generated by
Applied Biosystems (ABI) automated DNA sequencing machine.
by Malay K Basu (malay@bioinformatics.org); source code available at:
http://search.cpan.org/~malay

=head1 VERSION

Version 1.0

=cut

our $VERSION = '1.0';

=head1 SYNOPSIS

  my $abi = ABI->new(-file=>"mysequence.abi");
  my $seq = $abi->get_sequence(); # To get the sequence
  my @trace_a = $abi->get_trace("A"); # Get the raw traces for "A"
  my @trace_g = $abi->get_trace("G"); # Get the raw traces for "G"
  my @base_calls = $abi->get_base_calls(); # Get the base calls

=head1 DESCRIPTION

An ABI chromatogram file is in binary format. It contain several 
information only some of which is required for normal use. This
module only gives access to the most used information stored in
ABI file. All the accesses are read only.

If you have edited the file using a trace editor, then you can use the corresponding 
method to access the edited sequence and base calls.



=head1 CONSTRUCTOR

=head2 new()

  Usage : $abi = ABI->new(-file=>"filename");
          $abi = ABI->new("filename"); # same thing

=cut

sub new {
	my $class = shift;
	my $self  = {};
	bless $self, ref($class) || $class;
	$self->_init(@_);

	#print "****", $self->{_mac_header}, "\n";
	return $self;
}

sub _init {
	my ( $self, @args ) = @_;
	my ($file) = $self->_rearrange( ["FILE"], @args );
	if ( !defined($file) ) {
		croak "Can't open the input file\n";
	} else {
		$self->set_file_handle($file);
	}
	$self->{_sequence}             = "";
	$self->{_sequence_corrected}   = "";
	$self->{_sample}               = "";
	$self->{A}                     = [];
	$self->{T}                     = [];
	$self->{G}                     = [];
	$self->{C}                     = [];
	$self->{_basecalls}            = [];
	$self->{_basecalls_corrected}  = [];
	$self->{_trace_length}         = 0;
	$self->{_seq_length}           = 0;
	$self->{_seq_length_corrected} = 0;
	$self->{_abs_index}            = 26;
	$self->{_index}                = undef;
	$self->{PLOC1}                 = undef;
	$self->{PLOC}                  = undef;
	$self->{_a_start}              = undef;
	$self->{_g_start}              = undef;
	$self->{_c_start}              = undef;
	$self->{_t_start}              = undef;
	$self->{DATA9}                 = undef;
	$self->{DATA10}                = undef;
	$self->{DATA11}                = undef;
	$self->{DATA12}                = undef;
	$self->{PBAS1}                 = undef;
	$self->{PBAS2}                 = undef;
	$self->{FWO}                   = undef;
	$self->{_mac_header}           = 0;
	$self->{_maximum_trace}        = 0;

	if ( $self->_is_abi() ) {

		#print "ABI FILE\n";
		$self->_set_index();
		$self->_set_base_calls();
		$self->_set_corrected_base_calls();
		$self->_set_seq();
		$self->_set_corrected_seq();
		$self->_set_traces();
		$self->_set_max_trace();
		$self->_set_sample_name();
		close( $self->{_fh} );
	}
	return $self;
}

sub set_file_handle {
	my $self = shift;
	my $path = shift;
	my $fh   = IO::File->new();
	if ( $fh->open("< $path") ) {
		binmode($fh);
		$self->{_fh} = $fh;
	} else {
		croak "Could not open $path in ABITrace::set_file_handle\n";
	}
}

sub _rearrange {
	my ( $self, $order, @param ) = @_;
	return unless @param;
	return @param unless ( defined( $param[0] ) && $param[0] =~ /^-/ );
	for ( my $i = 0 ; $i < @param ; $i += 2 ) {
		$param[$i] =~ s/^\-//;
		$param[$i] =~ tr/a-z/A-Z/;
	}

	# Now we'll convert the @params variable into an associative array.
	local ($^W) = 0;    # prevent "odd number of elements" warning with -w.
	my (%param) = @param;
	my (@return_array);

	# What we intend to do is loop through the @{$order} variable,
	# and for each value, we use that as a key into our associative
	# array, pushing the value at that key onto our return array.
	my ($key);
	foreach $key ( @{$order} ) {
		my ($value) = $param{$key};
		delete $param{$key};
		push( @return_array, $value );
	}

#    print "\n_rearrange() after processing:\n";
#    my $i; for ($i=0;$i<@return_array;$i++) { printf "%20s => %s\n", ${$order}[$i], $return_array[$i]; } <STDIN>;
	return (@return_array);
}

sub _is_abi {
	my $self = shift;
	my $fh   = $self->{"_fh"};
	my $buf;
	seek( $fh, 0, 0 );
	read( $fh, $buf, 3 );

	#my $a = unpack("n*", $buf);
	if ( $buf eq "ABI" ) {
		return 1;
	} else {
		seek( $fh, 128, 0 );
		read( $fh, $buf, 3 );
		if ( $buf eq "ABI" ) {
			$self->_set_mac_header();
			return 1;
		} else {
			return 0;
		}
	}
}

sub _set_mac_header {
	my $self = shift;
	$self->{_mac_header} = 128;
}

sub _set_index {
	my $self         = shift;
	my $data_counter = 0;
	my $pbas_counter = 0;
	my $ploc_counter = 0;
	my ( $num_records, $buf );

	#print $self->{_fh}, "\n";
	#print $self->{_mac_header}, "\n";
	seek( $self->{_fh}, $self->{_abs_index} + $self->{_mac_header}, 0 );
	read( $self->{_fh}, $buf, 4 );
	$self->{_index} = unpack( "N", $buf );

	#print $self->{_index};
	seek( $self->{_fh}, $self->{_abs_index} - 8 + $self->{_mac_header}, 0 );
	read( $self->{_fh}, $buf, 4 );
	$num_records = unpack( "N", $buf );
	for ( my $i = 0 ; $i <= $num_records - 1 ; $i++ ) {
		seek( $self->{_fh}, $self->{_index} + ( $i * 28 ), 0 );
		read( $self->{_fh}, $buf, 4 );
		if ( $buf eq "FWO_" ) {
			$self->{FWO} = $self->{_index} + ( $i * 28 ) + 20;
		}
		if ( $buf eq "DATA" ) {
			$data_counter++;
			if ( $data_counter == 9 ) {
				$self->{DATA9} = $self->{_index} + ( $i * 28 ) + 20;
			}
			if ( $data_counter == 10 ) {
				$self->{DATA10} = $self->{_index} + ( $i * 28 ) + 20;
			}
			if ( $data_counter == 11 ) {
				$self->{DATA11} = $self->{_index} + ( $i * 28 ) + 20;
			}
			if ( $data_counter == 12 ) {
				$self->{DATA12} = $self->{_index} + ( $i * 28 ) + 20;
			}
		}
		if ( $buf eq "PBAS" ) {
			$pbas_counter++;
			if ( $pbas_counter == 1 ) {
				$self->{PBAS1} = $self->{_index} + ( $i * 28 ) + 20;
			}
			if ( $pbas_counter == 2 ) {
				$self->{PBAS2} = $self->{_index} + ( $i * 28 ) + 20;
			}
		}
		if ( $buf eq "PLOC" ) {
			$ploc_counter++;
			if ( $ploc_counter == 1 ) {
				$self->{PLOC1} = $self->{_index} + ( $i * 28 ) + 20;
			}
			if ( $ploc_counter == 2 ) {
				$self->{PLOC} = $self->{_index} + ( $i * 28 ) + 20;
			}
		}
		if ( $buf eq "SMPL" ) {
			$self->{SMPL} = $self->{_index} + ( $i * 28 ) + 20;
		}
	}
	seek( $self->{_fh}, $self->{DATA12} - 8, 0 );
	read( $self->{_fh}, $buf, 4 );
	$self->{_trace_length} = unpack( "N", $buf );
	seek( $self->{_fh}, $self->{PBAS2} - 4, 0 );
	read( $self->{_fh}, $buf, 4 );
	$self->{_seq_length} = unpack( "N", $buf );
	seek( $self->{_fh}, $self->{PBAS1} - 4, 0 );
	read( $self->{_fh}, $buf, 4 );
	$self->{_seq_length_corrected} = unpack( "N", $buf );
	$self->{PLOC}   = $self->_get_int( $self->{PLOC} ) + $self->{_mac_header};
	$self->{PLOC1}  = $self->_get_int( $self->{PLOC1} ) + $self->{_mac_header};
	$self->{DATA9}  = $self->_get_int( $self->{DATA9} ) + $self->{_mac_header};
	$self->{DATA10} = $self->_get_int( $self->{DATA10} ) + $self->{_mac_header};
	$self->{DATA11} = $self->_get_int( $self->{DATA11} ) + $self->{_mac_header};
	$self->{DATA12} = $self->_get_int( $self->{DATA12} ) + $self->{_mac_header};
	$self->{PBAS1}  = $self->_get_int( $self->{PBAS1} ) + $self->{_mac_header};
	$self->{PBAS2}  = $self->_get_int( $self->{PBAS2} ) + $self->{_mac_header};
	$self->{SMPL} += $self->{_mac_header};
}

sub _set_base_calls {
	my $self = shift;
	my $buf;
	my $length = $self->{_seq_length} * 2;
	my $fh     = $self->{_fh};
	seek( $fh, $self->{PLOC}, 0 );
	read( $fh, $buf, $length );
	@{ $self->{_basecalls} } = unpack( "n" x $length, $buf );

	# print "@{$self->{_basecalls}}" , "\n";
}

sub _set_corrected_base_calls {
	my $self = shift;
	my $buf;
	my $length = $self->{_seq_length_corrected} * 2;
	my $fh     = $self->{_fh};
	seek( $fh, $self->{PLOC1}, 0 );
	read( $fh, $buf, $length );
	@{ $self->{_basecalls_corrected} } = unpack( "n" x $length, $buf );
}

sub _set_seq {
	my $self = shift;
	my $buf;
	my $length = $self->{_seq_length};
	my $fh     = $self->{_fh};
	seek( $fh, $self->{PBAS2}, 0 );
	read( $fh, $buf, $length );
	$self->{_sequence} = $buf;

	#my @seq = unpack( "C" x $length, $buf);
	#print $buf, "\n";
}

sub _set_corrected_seq {
	my $self = shift;
	my $buf;
	my $length = $self->{_seq_length_corrected};
	my $fh     = $self->{_fh};
	seek( $fh, $self->{PBAS1}, 0 );
	read( $fh, $buf, $length );
	$self->{_sequence_corrected} = $buf;
}

sub _set_traces {
	my $self = shift;
	my $buf;
	my ( @pointers, @A, @G, @C, @T );
	my (@datas) =
	  ( $self->{DATA9}, $self->{DATA10}, $self->{DATA11}, $self->{DATA12} );
	my $fh = $self->{_fh};
	seek( $fh, $self->{FWO}, 0 );
	read( $fh, $buf, 4 );
	my @order = split( //, $buf );

	#print "@order", "\n";
	for ( my $i = 0 ; $i < 4 ; $i++ ) {
		if ( $order[$i] =~ /A/i ) {
			$pointers[0] = $datas[$i];
		} elsif ( $order[$i] =~ /C/i ) {
			$pointers[1] = $datas[$i];
		} elsif ( $order[$i] =~ /G/i ) {
			$pointers[2] = $datas[$i];
		} elsif ( $order[$i] =~ /T/i ) {
			$pointers[3] = $datas[$i];
		} else {
			croak "Wrong traces\n";
		}
	}
	for ( my $i = 0 ; $i < 4 ; $i++ ) {
		seek( $fh, $pointers[$i], 0 );
		read( $fh, $buf, $self->{_trace_length} * 2 );
		if ( $i == 0 ) {
			@A = unpack( "n" x $self->{_trace_length}, $buf );
		}
		if ( $i == 1 ) {
			@C = unpack( "n" x $self->{_trace_length}, $buf );
		}
		if ( $i == 2 ) {
			@G = unpack( "n" x $self->{_trace_length}, $buf );
		}
		if ( $i == 3 ) {
			@T = unpack( "n" x $self->{_trace_length}, $buf );
		}
	}
	@{ $self->{A} } = @A;
	@{ $self->{G} } = @G;
	@{ $self->{T} } = @T;
	@{ $self->{C} } = @C;
}

sub _get_int {
	my $self = shift;
	my $buf;
	my $pos = shift;
	my $fh  = $self->{_fh};
	seek( $fh, $pos, 0 );
	read( $fh, $buf, 4 );
	return unpack( "N", $buf );
}

sub _set_max_trace {
	my $self = shift;
	my @A    = @{ $self->{A} };
	my @T    = @{ $self->{T} };
	my @G    = @{ $self->{G} };
	my @C    = @{ $self->{C} };
	my $max  = 0;
	for ( my $i = 0 ; $i < @T ; $i++ ) {
		if ( $T[$i] > $max ) { $max = $T[$i]; }
		if ( $A[$i] > $max ) { $max = $A[$i]; }
		if ( $G[$i] > $max ) { $max = $G[$i]; }
		if ( $C[$i] > $max ) { $max = $C[$i]; }
	}
	$self->{_maximum_trace} = $max;
}

sub _set_sample_name {
	my $self = shift;
	my $buf;
	my $fh = $self->{_fh};
	seek( $fh, $self->{SMPL}, 0 );
	read( $fh, $buf, 1 );
	my $length = unpack( "C", $buf );
	read( $fh, $buf, $length );
	$self->{_sample} = $buf;
}

=head1 METHODS

=head2 get_max_trace()

  Title    :  get_max_trace()
  Usage    :  $max = $abi->get_max_trace();
  Function :  Returns the maximum trace value of all the traces.
  Args     :  Nothing
  Returns  :  A scalar

=cut

sub get_max_trace {
	my $self = shift;
	return $self->{_maximum_trace};
}

=head2 get_trace()

  Title    :  get_trace()
  Usage    :  my @a = $abi->get_trace("A");
  Function :  Returns the raw traces as array.
  Args     :  "A" or "G" or "C" or "T"
  Returns  :  An array

=cut

sub get_trace {
	my $self   = shift;
	my $symbol = shift;
	if ( $symbol =~ /A/i ) {
		return @{ $self->{A} };
	} elsif ( $symbol =~ /G/i ) {
		return @{ $self->{G} };
	} elsif ( $symbol =~ /C/i ) {
		return @{ $self->{C} };
	} elsif ( $symbol =~ /T/i ) {
		return @{ $self->{T} };
	} else {
		croak "Illegal symbol\n";
	}
}

=head2 get_sequence()

  Title    : get_sequence()
  Usage    : my $seq = $abi->get_sequence();
  Function : Returns the original unedited sequence as string. If you want to access the edited
             sequence use "get_corrected_sequence()" instead.
  Args     : Nothing
  Returns  : A scalar

=cut

sub get_sequence {
	my $self = shift;
	return $self->{_sequence};
}

=head2 get_corrected_sequence()

  Title    : get_corrected_sequence()
  Usage    : my $seq = $abi->get_corrected_sequence();
  Function : Returns the corrected sequence as string. If you want to access the original 
             unedited sequence, use "get_sequence()" instead.
  Args     : Nothing
  Returns  : A scalar

=cut

sub get_corrected_sequence {
	my $self = shift;
	return $self->{_sequence_corrected};
}

=head2 get_sequence_length()

  Title    : get_sequence_length()
  Usage    : my $seq_length = $abi->get_sequence_length();
  Function : Returns the sequence length of the orginal unedited sequence.
  Args     : Nothing
  Returns  : A scalar

=cut

sub get_sequence_length {
	my $self = shift;
	return $self->{_seq_length};
}

=head2 get_corrected_sequence_length()

  Title    : get_corrected_sequence_length()
  Usage    : my $seq_length = $abi->get_corrected_sequence_length();
  Function : Returns the length of the edited sequence. 
  Args     : Nothing
  Returns  : A scalar

=cut

sub get_corrected_sequence_length {
	my $self = shift;

	#print STDERR "**ABI**",$self->{_seq_length_corrected},"\n";
	return $self->{_seq_length_corrected};
}

=head2 get_trace_length()

  Title    : get_trace_length()
  Usage    : my $trace_length = $abi->get_trace_length();
  Function : Returns the trace length
  Args     : Nothing
  Returns  : A scalar

=cut

sub get_trace_length {
	my $self = shift;
	return $self->{_trace_length};
}

=head2 get_base_calls()

  Title    : get_base_calls()
  Usage    : my @base_calls = $abi->get_base_calls();
  Function : Returns the called bases by the base caller. This method will return the unedited 
  	         original basecalls created by the basecaller.
  Args     : Nothing
  Returns  : An array

=cut

sub get_base_calls {
	my $self = shift;
	return @{ $self->{_basecalls} };
}

=head2 get_corrected_base_calls()

  Title    : get_corrected_base_calls()
  Usage    : my @base_calls = $abi->get_corrected_base_calls();
  Function : If you have edited the trace file you can get the corrected base call 
             with this method
  Args     : Nothing
  Returns  : An array

=cut

sub get_corrected_base_calls {
	my $self = shift;
	return @{ $self->{_basecalls_corrected} };
}

=head2 get_sample_name()

  Title    : get_sample_name()
  Usage    : my $sample = $abi->get_sample_name();
  Function : Returns hard coded sample name
  Args     : Nothing
  Returns  : A scalar

=cut

sub get_sample_name {
	my $self = shift;
	return $self->{_sample};
}

=head1 AUTHOR

Malay <malay@bioinformatics.org>

=head1 BUGS

Please report any bugs or feature requests to
C<bug-abi at rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ABI>.
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.

or 

You can directly contact me to my email address.


=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ABI

You can also look for information at:

=over 4

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ABI>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ABI>

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ABI>

=item * Search CPAN

L<http://search.cpan.org/dist/ABI>

=back


=head1 COPYRIGHT & LICENSE

Copyright 2002,2006 Malay, all rights reserved.

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

=cut

1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

ABNF-Grammar

lib/ABNF/Generator.pm

package ABNF::Generator;

=pod

=head1 NAME

B<ABNF::Generator> - abstract base class for ABNF-based generators

=head1 INHERITANCE

B<ABNF::Generator> is the root of the Honest and Liar generators

=head1 DESCRIPTION

B<ABNF::Generator> is the abstract base class for ABNF-based generators.

Also it provides function B<asStrings> to stringified generated sequences

=head1 METHODS

=cut

use 5.014;

use strict;
use warnings;
no warnings "recursion";

use Carp;
use Readonly;
use Method::Signatures;
use Data::Dumper;

use Parse::ABNF;
use List::Util qw(shuffle);

use ABNF::Grammar qw($BASIC_RULES splitRule);
use ABNF::Validator;

use base qw(Exporter);
our @EXPORT_OK = qw($CONVERTERS $BASIC_RULES $RECURSION_LIMIT);

Readonly our $CHOICE_LIMIT => 128;

Readonly our $CONVERTERS => {
	"hex" => sub { hex($_[0]) },
	"bin" => sub { oct($_[0]) },
	"decimal" => sub { int($_[0]) },
};

=pod

=head1 ABNF::Generator->C<new>($grammar, $validator?)

Creates a new B<ABNF::Generator> object.

$grammar isa B<ABNF::Grammar>.

$validator isa B<ABNF::Validator>.

Children classes can get acces for them by $self->{_grammar} and $self->{_validator}

=cut

method new(ABNF::Grammar $grammar, ABNF::Validator $validator?) {
	my $class = ref($self) || $self;

	croak "Cant create instance of abstract class" if $class eq 'ABNF::Generator';

	$self = {
		_cache => {},
		_grammar => $grammar,
		_validator => $validator || ABNF::Validator->new($grammar)
	};

	bless($self, $class);

	$self->_init();

	return $self;
}

method _init() {
	$self->{handlers} = {
		Range => $self->can("_range"),
		String => $self->can("_string"),
		Literal => $self->can("_literal"),
		Repetition => $self->can("_repetition"),
		ProseValue => $self->can("_proseValue"),
		Reference => $self->can("_reference"),
		Group => $self->can("_group"),
		Choice => $self->can("_choice"),
		Rule => $self->can("_rule"),
	};
}

=pod

=head1 $generator->C<_range>($rule, $recursion)

Generates chain for range element.

Abstract method, most of all children must overload it.

$recursion is a structure to controle recursion depth.

=cut

method _range($rule, $recursion) {
	croak "Range handler is undefined yet";
}

=pod

=head1 $generator->C<_string>($rule, $recursion)

Generates chain for string element.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _string($rule, $recursion) {
	croak "String handler is undefined yet";
}

=pod

=head1 $generator->C<_literal>($rule, $recursion)

Generates chain for literal element.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _literal($rule, $recursion) {
	croak "Literal handler is undefined yet";
}

=pod

=head1 $generator->C<_repetition>($rule, $recursion)

Generates chain for repetition element.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _repetition($rule, $recursion) {
	croak "Repetition handler is undefined yet";
}

=pod

=head1 $generator->C<_reference>($rule, $recursion)

Generates chain for reference element.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _reference($rule, $recursion) {
	croak "Reference handler is undefined yet";
}

=pod

=head1 $generator->C<_group>($rule, $recursion)

Generates chain for group element.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _group($rule, $recursion) {
	croak "Group handler is undefined yet";
}

=pod

=head1 $generator->C<_choice>($rule, $recursion)

Generates chain for choce element.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _choice($rule, $recursion) {
	croak "Choice handler is undefined yet";
}

=pod

=head1 $generator->C<_rule>($rule, $recursion)

Generates chain for rule element, usually -- basic element in chain.

Abstract method, most of all children must overload it

$recursion is a structure to controle recursion depth.

=cut

method _rule($rule, $recursion) {
	croak "Rule handler is undefined yet";
}

=pod

=head1 $generator->C<_generateChain>($rule, $recursion)

Generates one chain per different rule in $rule.

$rule is structure that Return from B<ABNF::Grammar::rule> and like in B<Parse::ABNF>.

$rule might be a command name.

$recursion is a structure to controle recursion depth.

at init it have only one key -- level == 0.

You can create new object perl call or use one.

See use example in ABNF::Generator::Honest in method _choice

=cut

method _generateChain($rule, $recursion) {

	my @result = ();

	if ( ref($rule) ) {
		croak "Bad rule " . Dumper($rule) unless UNIVERSAL::isa($rule, "HASH");
	} elsif ( exists($BASIC_RULES->{$rule}) ) {
		$rule = $BASIC_RULES->{$rule};
	} else {
		$rule = $self->{_grammar}->rule($rule);
	}

	$self->{handlers}->{ $rule->{class} }
	or die "Unknown class " . $rule->{class};

	return $self->{handlers}->{ $rule->{class} }->($self, $rule, $recursion);
}

=pod

=head1 $generator->C<generate>($rule, $tail="")

Generates one sequence string for command $rule. 

Using cache $self->{_cache}->{$rule} for this rule, that speeds up this call.

$rule is a command name.

$tail is a string added to result if it absent.

dies if there is no command like $rule.

=cut

method generate(Str $rule, Str $tail="") {
	croak "Unexisted command" unless $self->{_grammar}->hasCommand($rule);

	$self->{_cache}->{$rule} ||= [];
	unless ( @{$self->{_cache}->{$rule}} ) {
		$self->{_cache}->{$rule} = _asStrings( $self->_generateChain($rule, {level => 0}) );
	}
	my $result = pop($self->{_cache}->{$rule});
	
	my $rx = eval { qr/$tail$/ };
	croak "Bad tail" if $@;
	return $result =~ $rx ? $result : $result . $tail;
}

=pod

=head1 $generator->C<withoutArguments>($name, $tail="")

Return an strings starts like command $name and without arguments.

$tail is a string added to a result.

dies if there is no command like $rule.

=cut

method withoutArguments(Str $name, Str $tail="") {
	croak "Unexisted command" unless $self->{_grammar}->hasCommand($name);

	my ($prefix, $args) = splitRule( $self->{_grammar}->rule($name) );
	
	my $rx = eval { qr/$tail$/ };
	croak "Bad tail" if $@;
	return $prefix =~ $rx ? $prefix : $prefix . $tail;
}

=pod

=head1 $generator->C<hasCommand>($name)

Return 1 if there is a $name is command, 0 otherwise

=cut

method hasCommand(Str $name) {
	$self->{_grammar}->hasCommand($name);
}

=pod

=head1 FUNCTIONS

=head1 C<_asStrings>($generated)

Return stringification of genereted sequences from C<_generateChain>.

Uses in generate call to stringify chains.

=cut

func _asStrings($generated) {
	given ( $generated->{class} ) {
		when ( "Atom" ) { return [ $generated->{value} ] }

		when ( "Sequence" ) {
			my $value = $generated->{value};
			return [] unless @$value;

			my $begin = _asStrings($value->[0]);

			for ( my $pos = 1; $pos < @$value; $pos++ ) {
				my @new_begin = ();
				my $ends = _asStrings($value->[$pos]);
				next unless @$ends;

				my @ibegin = splice([shuffle(@$begin)], 0, $CHOICE_LIMIT);
				my @iends = splice([shuffle(@$ends)], 0, $CHOICE_LIMIT);
				foreach my $end ( @iends ) {
					foreach my $begin ( @ibegin ) {
						push(@new_begin, $begin . $end);
					}
				}
		
				$begin = \@new_begin;
			}

			return $begin;
		}

		when ( "Choice" ) {
			return [
				map { @{_asStrings($_)} } @{$generated->{value}}
			];
		}

		default { die "Unknown class " . $generated->{class} . Dumper $generated }
	}
}

1;

=pod

=head1 AUTHOR / COPYRIGHT / LICENSE

Copyright (c) 2013 Arseny Krasikov <nyaapa@cpan.org>.

This module is licensed under the same terms as Perl itself.

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

AC-DC

lib/AC/ConfigFile/Simple.pm

# -*- perl -*-

# Copyright (c) 2008 by AdCopy
# Author: Jeff Weisberg
# Created: 2008-Dec-19 10:12 (EST)
# Function: read simple config file
#
# $Id$

# file:
# keyword value
# ...

package AC::ConfigFile::Simple;
use AC::Misc;
use AC::DC::Debug;
use Socket;
use strict;

my $MINSTAT = 15;

my %CONFIG = (
    include	=> \&include_file,
    debug	=> \&parse_debug,
    allow	=> \&parse_allow,
    _default	=> \&parse_keyvalue,
);


sub new {
    my $class = shift;
    my $file  = shift;

    my $me = bless {
	_laststat	=> $^T,
	_lastconf	=> $^T,
        _configfile	=> $file,
        _files		=> [ ],
	@_,
    }, $class;

    $me->_read();
    return $me;
}

sub check {
    my $me = shift;

    my $now = $^T;
    return if $now - $me->{_laststat} < $MINSTAT;
    $me->{_laststat} = $now;

    my $changed;
    for my $file ( @{$me->{_files}} ){
        my $mtime = (stat($file))[9];
        $changed = 1 if $mtime > $me->{_lastconf};
    }
    return unless $changed;

    verbose("config file changed. reloading");
    $me->{_lastconf} = $now;

    eval {
	$me->_read();
        verbose("installed new config file");
        if( my $f = $me->{onreload} ){
            $f->();
        }
    };
    if(my $e = $@){
        problem("error reading new config file: $e");
        return;
    }

    return 1;
}

sub _read {
    my $me = shift;

    delete $me->{_pending};

    $me->_readfile($me->{_configfile});

    $me->{config} = $me->{_pending};
    delete $me->{_pending};
}

sub _readfile {
    my $me   = shift;
    my $file = shift;

    my $fd;
    open($fd, $file) || die "cannot open file '$file': $!";
    $me->{fd} = $fd;

    push @{$me->{_files}}, $file;

    while( defined(my $l = $me->_nextline()) ){
        my($key, $rest) = split /\s+/, $l, 2;
        $me->handle_config( $key, $rest ) || die "invalid config '$key'\n";
    }

    close $fd;
}

sub handle_config {
    my $me   = shift;
    my $key  = shift;
    my $rest = shift;

    my $fnc = $CONFIG{$key} || $CONFIG{_default};
    return unless $fnc;
    $fnc->($me, $key, $rest);
    return 1;
}

sub _nextline {
    my $me = shift;

    my $line;
    while(1){
        my $fd = $me->{fd};

        my $l = <$fd>;
        return $line unless defined $l;
        chomp $l;

        $l =~ s/\#.*$//;
        $l =~ s/^\s*//;
        $l =~ s/\s+$//;
        next if $l =~ s/^\s*$/; #/;
        $line .= $l;

        if( $line =~ /\\$/ ){
            chop $line;
            next;
        }
        return $line;
    }
}

################################################################

sub include_file {
    my $me   = shift;
    my $key  = shift;
    my $file = shift;

    $file =~ s/^"(.*)"$/$1/;

    if( $file !~ m|^/| ){
        # add path from main config file
        my($path) = $me->{_configfile} =~ m|(.*)/[^/]+$|;
        $file = "$path/$file" if $path;
    }

    my $fd = $me->{fd};
    $me->_readfile($file);
    $me->{fd} = $fd;
}

sub parse_keyvalue {
    my $me    = shift;
    my $key   = shift;
    my $value = shift;

    problem("parameter '$key' redefined") if $me->{_pending}{$key};
    $me->{_pending}{$key} = $value;
}

sub parse_keyarray {
    my $me    = shift;
    my $key   = shift;
    my $value = shift;

    push @{$me->{_pending}{$key}}, $value;
}

sub parse_allow {
    my $me    = shift;
    my $key   = shift;
    my $acl   = shift;

    my($host, $len) = split m|/|, $acl;
    $host ||= $acl;
    $len  ||= 32;

    push @{$me->{_pending}{acl}}, [ inet_aton($host), inet_lton($len) ];
}

sub parse_debug {
    my $me    = shift;
    my $key   = shift;
    my $value = shift;

    $me->{_pending}{debug}{$value} = 1;
}


################################################################

sub config {
    my $me = shift;
    return $me->{config};
}

sub get {
    my $me = shift;
    my $k  = shift;

    return $me->{config}{$k};
}

sub check_acl {
    my $me = shift;
    my $ip = shift;	# ascii

    my $ipn = inet_aton($ip);
    for my $acl ( @{$me->{config}{acl}} ){
        my($net, $mask) = @$acl;
        return 1 if ($ipn & $mask) eq $net;
    }

    return 0;
}


1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

AC-MrGamoo

eg/filelist.pm

# -*- perl -*-
# example filelist

# $Id: filelist.pm,v 1.1 2010/11/01 19:04:21 jaw Exp $

package Local::MrMagoo::FileList;
use AC::ISOTime;
use AC::Yenta::Direct;
use JSON;
use strict;

my $YDBFILE = "/data/files.ydb";

sub get_file_list {
    my $config = shift;

    # get files + metadata from yenta
    my $yenta = AC::Yenta::Direct->new( 'files', $YDBFILE );

    # the job config is asking for files that match:
    my $syst  = $config->{system};
    my $tmax  = $config->{end};		# time_t
    my $tmin  = $config->{start};	# time_t

    # the keys in  yenta are of the form: 20100126150139_[...]
    my $start = isotime($tmin);		# 1286819830       => 20101011T175710Z
    $start =~ s/^(\d+)T(\d+).*/$1$2/;	# 20101011T175710Z => 20101011175710


    my @files = grep {
        # does this file match the request?
        ($_->{subsystem}   eq $syst) &&
        ($_->{end_time}    >= $tmin) &&
        ($_->{start_time}  <= $tmax)
    } map {
        # get meta-data on this file. data is json encoded
        my $d = $yenta->get($_);
        $d = $d ? decode_json($d) : {};
        # convert space seperated locations to arrayref
        $d->{location} = [ (split /\s+/, $d->{location}) ];
        $d;
    } $yenta->getrange($start, undef);	# get all files from $start to now


    return \@files;
}


1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

AC-Yenta

eg/myself.pm

# -*- perl -*-
# example myself

# $Id$

package Local::Yenta::MySelf;
use Sys::Hostname;
use strict;

my $SERVERID;

sub init {
    my $class = shift;
    my $port  = shift;	# our tcp port
    my $id    = shift;  # from cmd line

    $SERVERID = $id;
    unless( $SERVERID ){
        (my $h = hostname()) =~ s/\.example.com//;	# remove domain
        $SERVERID = "yenta/$h";
    }
    verbose("system persistent-id: $SERVERID");
}

sub my_server_id {
    return $SERVERID;
}

1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACH-Generator

lib/ACH/Generator.pm

package ACH::Generator;

$VERSION = '0.01';

use strict;
use warnings;

use ACH;

sub _croak { require Carp; Carp::croak(@_) }

=head1 NAME

ACH::Generator - Generates an ACH formatted file from an ACH perl object
	
=head1 VERSION

Version: 0.01
May 2006

=head1 DESCRIPTION

ACH::Generator is a simple, generic subclass of ACH used to generate ACH files.
It's intentional use is for testing purposes ONLY.  ACH-Generator will allow a 
developer to create an ACH formatted file.

=head1 USING ACH-Generator

	use ACH::Generator;

	my $newACH = new ACH;
	my $newACHfile = 'newACHFile.ACH';	# The name of the ACH file to be generated
	
	...
	
	$newACH->generate($newACHfile);

=head1 METHODS

=head2 generate

Generates an ACH file from the data in the ACH object

=cut

# Generate the ACH file 
sub ACH::generate {
  # Get the file name
  my $self = shift; 
  my $file = shift or _croak "Need an ACH file";
  
  # File data
  my $data = "";
  
  # Iterate through the ACH Data
  foreach my $item (@{$self->{_achData}}) { # Array of ACH file Sections
    my @achSections = map { defined $_ ? $_ : '' } @{$item};
    my $sectionValue = 0;
    
    for (my $y=0; $y < @achSections; $y++) { # Array of ACH file Section data
      my %hash = map { defined $_ ? $_ : '' } %{$achSections[$y]};
      
      # Use the appropriate file Format size for the appropriate ACH file section
      foreach my $hashItem (keys (%hash)) { # Hash containing the ACH field name and value
        chomp $hash{$hashItem};
        my $dataValue = "";

		# Get the section header in the first field, else get the data        
        if ($y == 0) { $dataValue = $sectionValue = $hash{$hashItem}; }
        else { 
          # Get the field length and data
		  my $field = ${$self->{_achFormats}{$sectionValue}}[$y];
          my ($field_length);  while ( my ($key, $value) = each(%$field) ) { $field_length = $value; }
          $dataValue = substr($hash{$hashItem}, 0, $field_length); 
        }
        
        # Store the data in the file data variable
        $data .= $dataValue;
      }
    }
  }
  
  # Open the file
  if ( open(OUTPUT, ">$file") ) {}
  else { print "Error:  Couldn't open file $file\n"; die; }

  # Print data out to ACH file
  print OUTPUT "$data";

  # Close the ACH file
  close (OUTPUT);
}


=head2 CAVEATS

This package is created for testing purposes only.  It shouldn't be used 
for production programs or scripts.  There are other commercial products
out there that may be a more efficient solution for accomplishing your
goals.

All records in an ACH file must be formatted in the following sequence
of records.  IF the file is not formatted in this exact sequence, it
may be rejected.

ACH File Layout:
1 - File Header Record
5 - First Company/Batch Header Record
6 - First Entry Detail Record
7 - First Entry Detail Addenda Record (optional)
	|
Multiples of Entry Detail Records
	|
6 - Last Entry Detail Record
7 - Last Entry Detail Addenda Record (optional)
8 - First Company/Batch Control Record
	|
Multiples of Company/Batches
	|
5 - Last Company/Batch Header Record
6 - First Entry Detail Record
7 - First Entry Detail Addenda Record (optional)
	|
Multiples of Entry Detail Records
	|
6 - Last Entry Detail Record
7 - Last Entry Detail Addenda Record (optional)
8 - Last Company/Batch Control Record
9 - File Control Record
9999...9999 (optional)

=head1 AUTHOR

Author: Christopher Kois
Date: May, 2006
Contact: cpkois@cpan.org

=head1 COPYRIGHTS

The ACH-Generator module is Copyright (c) May, 2006 by Christopher Kois. 
http://www.christopherkois.com All rights reserved.  You may distribute this 
module under the terms of GNU General Public License (GPL). 

=head1 SUPPORT/WARRANTY

ACH-Generator is free Open Source software. IT COMES WITHOUT WARRANTY OR SUPPORT OF ANY KIND.

=head1 KNOWN BUGS

This is version 0.01 of ACH::Generator.  There are currently no known bugs.

=head1 SEE ALSO

L<ACH>. L<ACH::Parser>

=cut

1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACH-Parser

lib/ACH/Parser.pm

package ACH::Parser;

$VERSION = '0.01';

use strict;
use warnings;

use ACH;

sub _croak { require Carp; Carp::croak(@_) }

=head1 NAME

ACH::Parser - Parse an ACH formatted file to ACH perl object
	
=head1 VERSION

Version: 0.01
May 2006

=head1 DESCRIPTION

ACH::Parser is a simple, generic ACH file to ACH object parser.
It's intentional use is for testing purposes ONLY.  ACH-Parser will
allow a developer to look at the particular fields in an ACH formatted
file.

=head1 USING ACH-Parser

	use ACH::Parser;

	my $file = 'RETODC0104A.ACH';
	my $ach = new ACH;
	$ach->parse($file);

=head1 METHODS

=head2 parse

Parses the ACH data into the ACH object

=cut

# Parse the ACH file formatted text into an ACH object
sub ACH::parse {
  # Get the file name
  my $self = shift; 
  my $file = shift or _croak "Need an ACH file";
  
  # Open the file
  if ( open(INPUT, "$file") ) {}
  else { print "Error:  Couldn't open file $file\n"; die; }

  # Get the file contents
  my @data = <INPUT>;
  my $dataline = $data[0];
  my $pos = 0;
  
  # Loop Through all entries
  while ($pos < length($dataline)) {
    # Get the correct ACH format array and store all parsed data in a hash
    my $desc = substr($dataline, $pos, 1);
    my @dataArray = [];

    # Make sure file descriptor is valid
    if ($desc != 1 and $desc != 5 and $desc != 6 and $desc != 7 and $desc != 8 and $desc != 9) {
      die "File Error:  Code: $desc\n";
    }
    
    # Iterate through the appropriate ACH file format array and parse the data
    for (my $x=0; $x < @{$self->{_achFormats}{$desc}}; $x++) {
	  my $field = ${$self->{_achFormats}{$desc}}[$x];
            
	  # Get the field name and length
	  my ($field_name, $field_length);
	  while ( my ($key, $value) = each(%$field) ) { $field_name = $key;  $field_length = $value; }

      # Get the ACH Data from the file
      my $part = substr($dataline, $pos, $field_length);  chomp $part;
      my %hash = ($field_name => $part);
      $dataArray[$x] = \%hash;
      $pos += $field_length;    
    }
    
    # Save data to list
    @{$self->{_achData}}[scalar @{$self->{_achData}}] = \@dataArray; 
  }
  
  # Close the Input file
  close (INPUT);
}


=head2 CAVEATS

This package is created for testing purposes only.  It shouldn't be used 
for production programs or scripts.  There are other commercial products
out there that may be a more efficient solution for accomplishing your
goals.

All records in an ACH file must be formatted in the following sequence
of records.  IF the file is not formatted in this exact sequence, it
may be rejected.

ACH File Layout:
1 - File Header Record
5 - First Company/Batch Header Record
6 - First Entry Detail Record
7 - First Entry Detail Addenda Record (optional)
	|
Multiples of Entry Detail Records
	|
6 - Last Entry Detail Record
7 - Last Entry Detail Addenda Record (optional)
8 - First Company/Batch Control Record
	|
Multiples of Company/Batches
	|
5 - Last Company/Batch Header Record
6 - First Entry Detail Record
7 - First Entry Detail Addenda Record (optional)
	|
Multiples of Entry Detail Records
	|
6 - Last Entry Detail Record
7 - Last Entry Detail Addenda Record (optional)
8 - Last Company/Batch Control Record
9 - File Control Record
9999...9999 (optional)

=head1 AUTHOR

Author: Christopher Kois
Date: May, 2006
Contact: cpkois@cpan.org

=head1 COPYRIGHTS

The ACH-Parser module is Copyright (c) May, 2006 by Christopher Kois. 
http://www.christopherkois.com All rights reserved.  You may distribute this 
module under the terms of GNU General Public License (GPL). 

=head1 SUPPORT/WARRANTY

ACH-Parser is free Open Source software. IT COMES WITHOUT WARRANTY OR SUPPORT OF ANY KIND.

=head1 KNOWN BUGS

This is version 0.01 of ACH::Parser.  There are currently no known bugs.

=head1 SEE ALSO

L<ACH>. L<ACH::Generator>

=cut

1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACH

lib/ACH.pm

package ACH;

$VERSION   = '0.01';		# Version number

use strict;
use warnings;

=head1 NAME

ACH - ACH perl object
	
=head1 VERSION

Version: 0.01
May 2006

=head1 DESCRIPTION

ACH is a simple, generic perl object that contains the data necesary to
create an ACH file.  It's intentional use is for testing purposes ONLY.  
ACH will allow a developer to manipulate specific data fields in an ACH 
formatted object.

=head1 USING ACH

	my $ACH = new ACH;

=cut

### Variables and functions

## Arrays that store sizes of the various records in the ACH file ##
# File Header Format fields and field sizes
my @fileFormat = ({'File Header Record' => 1}, {'Priority Code' => 2}, 
{'Immediate Destination' => 10}, {'Immediate Origin' => 10}, {'File Creation Date' => 6},
{'Creation Time' => 4}, {'File ID Modifier' => 1}, {'Record size' => 3}, {'Blocking Factor' => 2},
{'Format Code' => 1}, {'Destination' => 23}, {'Origin' => 23}, {'Reference Code' => 8});

# Batch Record fields and field sizes
my @batchFormat = ({'Batch Header Record' => 1}, {'Service Class Code' => 3}, 
{'Company Name' => 16}, {'Company Discretionary Data' => 20}, {'Company Identification' => 10}, 
{'Standard Entry Classes' => 3}, {'Company Entry Description' => 10}, 
{'Company Descriptive Date' => 6}, {'Effective Entry Date' => 6}, {'Settlement Date' => 3},
{'Originator Status Code' => 1}, {'Originating DFI Identification' => 8}, {'Batch #' => 7});

# Detail Record fields and field sizes
my @detailFormat = ({'Entry Detail Record' => 1}, {'Transaction Code' => 2}, 
{'Individual Bank ID' => 8}, {'Check Digit' => 1}, {'Bank Acct. Number' => 17}, {'Amount' => 10},
{'Individual ID Number' => 15}, {'Individual Name' => 22}, {'Bank Discretionary Data' => 2},
{'Addenda Record Indicator' => 1}, {'Trace Number' => 15});

# Addenda Format fields and field sizes
my @addendaFormat = ({'Addenda Record' => 1}, {'Addenda Type Code' => 2}, 
{'Payment Related Information' => 80}, {'Special Addenda Sequence Number' => 4},
{'Entry Detail Sequence Number' => 7});

# Batch Control Format fields and field sizes
my @controlFormat = ({'Batch Control Record' => 1}, {'Service Class Codes' => 3},
{'Entry/Addenda Count' => 6}, {'Entry Hash' => 10}, {'Total Debit Entry Dollar Amount' => 12}, 
{'Total Credit Entry Dollar Amount' => 12}, {'Company Identification' => 10}, {'Blank' => 19},
{'Blank' => 6}, {'Originating Financial Institution' => 8}, {'Batch Number' => 7});

# File Control fields and field sizes
my @fileControl = ({'File Control Record' => 1}, {'Batch Count' => 6}, {'Block Count' => 6}, 
{'Entry/Addenda Count' => 8}, {'Entry Hash' => 10}, {'Total Debit Entry Dollar Amount' => 12}, 
{'Total Credit Entry Dollar Amount' => 12}, {'Reserved/Blank' => 39});

# All of the ACH File Formats
my %achFormats = (1 => \@fileFormat, 5 => \@batchFormat, 6 => \@detailFormat, 
7 => \@addendaFormat, 8 => \@controlFormat, 9 => \@fileControl);
##

# ACH data
my @achData;

=head1 METHODS

=head2 new

Creates a new ACH object

=cut

# Create a new ACH object
sub new  { 
    my $class = shift;
    my $self  = {};         # allocate new hash for object
    
    bless {
      _achData         => [],
      _achFormats      => \%achFormats,
    }, $class;
}

=head2 printAllData

Prints all the ACH data

=cut

# Print all data from the ACH object
sub printAllData {
  my $self = shift;
  foreach my $item (@{$self->{_achData}}) { # Array of ACH file Sections
    my @achSections = map { defined $_ ? $_ : '' } @{$item};
    foreach my $section (@achSections) { # Array of ACH file Section data
      my %hash = map { defined $_ ? $_ : '' } %{$section};
      foreach my $hashItem (keys (%hash)) { # Hash containing the ACH field name and value
        print "$hashItem: $hash{$hashItem}\n";
      }
    }
  }
}

=head2 getData

Returns the ACH data

=cut

# Get data
sub getData {
  my $self = shift;
  return \@{$self->{_achData}};
}


=head2 CAVEATS

This package is created for testing purposes only.  It shouldn't be used 
for production programs or scripts.  There are other commercial products
out there that may be a more efficient solution for accomplishing your
goals.

All records in an ACH file must be formatted in the following sequence
of records.  IF the file is not formatted in this exact sequence, it
may be rejected.

ACH File Layout:
1 - File Header Record
5 - First Company/Batch Header Record
6 - First Entry Detail Record
7 - First Entry Detail Addenda Record (optional)
	|
Multiples of Entry Detail Records
	|
6 - Last Entry Detail Record
7 - Last Entry Detail Addenda Record (optional)
8 - First Company/Batch Control Record
	|
Multiples of Company/Batches
	|
5 - Last Company/Batch Header Record
6 - First Entry Detail Record
7 - First Entry Detail Addenda Record (optional)
	|
Multiples of Entry Detail Records
	|
6 - Last Entry Detail Record
7 - Last Entry Detail Addenda Record (optional)
8 - Last Company/Batch Control Record
9 - File Control Record
9999...9999 (optional)

=head1 AUTHOR

Author: Christopher Kois
Date: May, 2006
Contact: cpkois@cpan.org

=head1 COPYRIGHTS

The ACH module is Copyright (c) May, 2006 by Christopher Kois. 
http://www.christopherkois.com All rights reserved.  You may distribute 
this module under the terms of GNU General Public License (GPL). 

=head1 SUPPORT/WARRANTY

ACH is free Open Source software. IT COMES WITHOUT WARRANTY OR SUPPORT OF ANY KIND.

=head1 KNOWN BUGS

This is version 0.01 of ACH.  There are currently no known bugs.

=head1 SEE ALSO

L<ACH::Generator>. L<ACH::Parser>

=cut

1;

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACL-Lite

lib/ACL/Lite.pm

package ACL::Lite;

use 5.006;
use strict;
use warnings;

=head1 NAME

ACL::Lite - Liteweight and flexible ACL checks

=head1 VERSION

Version 0.0004

=cut

our $VERSION = '0.0004';

=head1 SYNOPSIS

    use ACL::Lite;

    $acl = ACL::Lite->new(permissions => 'foo,bar');

    $acl->check('foo');

    if ($ret = $acl->check([qw/baz bar/])) {
        print "Check successful with permission $ret\n";
    }

    unless ($acl->check('baz')) {
        print "Permission denied\n";
    }

    $acl = ACL::Lite->new(uid => 666);

    $acl->check('authenticated');

=head1 DESCRIPTION

C<ACL::Lite> is a simple permission checker without any prerequisites.

C<ACL> stands for "Access Control Lists".

=head2 DEFAULT PERMISSION

The default permission depends on whether you pass a C<uid> (authenticated)
or not (anonymous).

=head1 CONSTRUCTOR

=head2 new

Creates an ACL::Lite object by passing the following parameters:

=over 4

=item uid

User identifier for authenticated users.

=item permissions

Granted permissions.

=item separator

Separator used to parse permission strings. Defaults to C<,>.

=back

=cut

sub new {
	my ($class, $self, $type, %args);
	
	$class = shift;

	%args = @_;
	
	$self = {separator => $args{separator} || ',',
			 permissions => {},
			 uid => $args{uid},
			 volatile => 0};
	
	bless $self, $class;
	
	if (exists $args{permissions}) {
		$type = ref($args{permissions});

		if ($type eq 'ARRAY') {
			for my $perm (@{$args{permissions}}) {
				$self->{permissions}->{$perm} = 1;
			}
		}
		elsif ($type eq 'CODE') {
			$self->{volatile} = 1;
			$self->{sub} = $args{permissions};
		}
		elsif (defined $args{permissions}) {
			my @perms;

			for my $perm (split(/$self->{separator}/, $args{permissions})) {
				$perm =~ s/^\s+//;
				$perm =~ s/\s+$//;
				next unless length($perm);

				$self->{permissions}->{$perm} = 1;
			}
		}
	}

    # add default permissions
    if ($self->{uid}) {
        $self->{permissions}->{authenticated} = 1;
    }
    else {
        $self->{permissions}->{anonymous} = 1;
    }

	return $self;
}

=head2 check $permissions, $uid

Checks whether any of the permissions in $permissions is granted.
Returns first permission which grants access.

=cut

sub check {
	my ($self, $permissions, $uid) = @_;
	my (@check, $user_permissions);

	if (ref($permissions) eq 'ARRAY') {
		@check = @$permissions;
	}
	else {
		@check = ($permissions);
	}

	if ($uid && $uid ne $self->{uid}) {
		# mismatch on user identifier
		return;
	}

    $user_permissions = $self->permissions;

	for my $perm (@check) {
		if (exists $user_permissions->{$perm}) {
			return $perm;
		}
	}

	return;
}

=head2 permissions

Returns permissions as hash reference:

    $perms = $acl->permissions;

Returns permissions as list:

    @perms = $acl->permissions;

=cut

sub permissions {
    my ($self) = @_;

    if ($self->{volatile}) {
        $self->{permissions} = $self->{sub}->();
    }

    if (wantarray) {
        return keys %{$self->{permissions}};
    }

    return $self->{permissions};
}

=head1 CAVEATS

Please anticipate API changes in this early state of development.

=head1 AUTHOR

Stefan Hornburg (Racke), C<racke@linuxia.de>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acl-lite at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACL-Lite>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACL::Lite


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACL-Lite>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACL-Lite>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACL-Lite>

=item * Search CPAN

L<http://search.cpan.org/dist/ACL-Lite/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2011-2013 Stefan Hornburg (Racke).

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of ACL::Lite

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACL-Regex

examples/postifx-policy-server.pl

#!/usr/bin/perl
#
use IO::Socket;
use threads;
use Proc::Daemon;
use Sys::Syslog qw( :DEFAULT setlogsock);

use Data::Dumper;
use lib( "./" );
use ACL;

# Global config settings
my $TC = 1;
my $debug = 1;
my $port = 12345;
our $pidfile = "/var/run/postfix-policy-server.pid";
our %redirectmap;

# Param1: Client socket
# Param2: hash_ref
sub parse_postfix_input( $$ ) {
	my ($socket,$hashref) = @_;

	local $/ = "\r\n";
	while( my $line = <$socket> ){
		chomp( $line );
		$line =~ s/\r//g;
		$line =~ s/\n//g;

		return if $line =~ /^(\r|\n)*$/;
		#print "DEBUG: $line" if $debug;
		if( $line =~ /^(\w+?)=(.+)$/ ){
			$hashref->{$1} = $2;
		}
	}
}

sub convert_hashref_to_acl($){
	my( $hash_ref ) = @_;
	
	my @a;

	for( sort( keys %$hash_ref ) ) {
		my $str = "$_=\[$hash_ref->{$_}\]";
		push( @a, $str );
	}

	return( join( " ", @a ) );
}

sub process_client($){
	my ($socket) = @_;

	# Create some stuff
	my $accept_acl = ACL->new->generate_required( 'required.txt' )->parse_acl_from_file( { Filename => "acl.permit.txt" } );
	my $reject_acl = ACL->new->generate_required( 'required.txt' )->parse_acl_from_file( { Filename => "acl.reject.txt" } );

	ACCEPT: while( my $client = $socket->accept() ){
		my $hash_ref = {};
		parse_postfix_input( $client, $hash_ref );

		my $action = convert_hashref_to_acl( $hash_ref );

		print "Action: " . Dumper($action) . "\n";

		my ($rc,$regex,$comment) = $reject_acl->match( $action );
		print Dumper( $rc ) . Dumper( $regex ) . Dumper( $comment ) . "\n";

		if( $rc ){
			print $client "action=reject $comment\n\n";
			next ACCEPT;
			# Match
		}

		($rc,$regex,$comment) = $accept_acl->match( $action );
		print Dumper( $rc ) . Dumper( $regex ) . Dumper( $comment ) . "\n";
		if( $rc ){
			print $client "action=ok $comment\n\n";
			next ACCEPT;
			# Match
		}

		# Handle any redirects
		print $client "action=dunno\n\n";
	}
}

sub handle_sig_int
{
	unlink( $pidfile );
	exit(0);
}

#openlog('missed-spam-policy', '', 'mail');
#syslog('info', 'launching in daemon mode') if $ARGV[0] eq 'quiet-quick-start';
#Proc::Daemon::Init if $ARGV[0] eq 'quiet-quick-start';

# Attempt to parse in the redirect config

$SIG{INT} = \&handle_sig_int;

# Ignore client disconnects
$SIG{PIPE} = "IGNORE";

open PID, "+>", "$pidfile" or die("Cannot open $pidfile: $!\n");
print PID "$$";
close( PID );

my $server = IO::Socket::INET->new(
    LocalPort => $port,
    Type      => SOCK_STREAM,
    Reuse     => 1,
    Listen    => 10
  )
  or die
  "Couldn't be a tcp server on port $default_config->{serverport} : $@\n";

# Generate a number of listener threads
my @threads = ();
for( 1 .. $TC ){
	my $thread = threads->create( \&process_client, $server );
	push( @threads, $thread );
}

foreach my $thread ( @threads ){
	$thread->join();
}

unlink( $pidfile );
closelog;
exit( 0 );

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-CPANPLUS-Module-With-Core-PreReq

lib/ACME/CPANPLUS/Module/With/Core/PreReq.pm

package ACME::CPANPLUS::Module::With::Core::PreReq;
$ACME::CPANPLUS::Module::With::Core::PreReq::VERSION = '0.06';
#ABSTRACT: Fake module with a prereq that is a core module for testing CPANPLUS

use strict;
use warnings;

qq[Nobody here but us chickens];

__END__

=pod

=encoding UTF-8

=head1 NAME

ACME::CPANPLUS::Module::With::Core::PreReq - Fake module with a prereq that is a core module for testing CPANPLUS

=head1 VERSION

version 0.06

=head1 SYNOPSIS

 # erm

 cpanp -i ACME::CPANPLUS::Module::With::Core::PreReq

=head1 DESCRIPTION

ACME::CPANPLUS::Module::With::Core::PreReq is a fake module that has a prerequisite of a core module
so I can test something in L<CPANPLUS> and L<CPANPLUS::YACSmoke>

No moving parts and nothing to see.

=head1 AUTHOR

Chris Williams <chris@bingosnet.co.uk>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by Chris Williams.

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

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-Error-31337

31337.pm

package ACME::Error::31337;

use strict;
no  strict 'refs';

use vars q[$VERSION];
$VERSION = '0.01';

use Lingua::31337 qw[text231337];

*die_handler = *warn_handler = sub {
  return text231337 @_;
};

1;
__END__

=head1 n4Me

ACME::Error::31337 - ACM3::ERRoR b4ck3ND To tR4NSl4T3 erRorS 7O co0l 74Lk

=head1 sYn0PS1S

  use ACME::Error::31337;

  die "You stink!";

=head1 DEScR1Pt10N

CoNv3R7 y0Ur 3RR0rS 7o 31173 spE3cH.

US3 C<$Lingua::31337::LEVEL> 70 rA1sE OR 10W3r YoUR L3vel of 31I7eNess.

=head1 auTH0R

CAS3y W3ST <f<CaseY@geeKNEst.Com>>

=head1 cOpyRiGH7

COpYRiGht (C) 2002 C4s3Y R. weSt <C4seY@G33kneSt.cOM>.  4l1
r1gH7S ResERVED.  7h1S PR0grAm 1S pHr3E sOPhTW4RE; YoU c4n
red1S7rIBuT3 17 AND/0R m0dIpHy It UnDEr th3 SaMe TeRMS aS
Per1 itSE1F.

=head1 s3e aLSo

p3rl(1), AcM3::eRROr, L1NGu4::31337.

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-Error-Coy

Coy.pm

package ACME::Error::Coy;

use strict;
no  strict 'refs';

use vars q[$VERSION];
$VERSION = '0.01';

use Coy;

*die_handler  = $SIG{__DIE__};
*warn_handler = $SIG{__WARN__};


1;
__END__
# Below is stub documentation for your module. You better edit it!

=head1 NAME

ACME::Error::Coy - Perl extension for blah blah blah

=head1 SYNOPSIS

  use ACME::Error Coy;

=head1 DESCRIPTION

Interface to L<Coy> for printing your errors.

=head1 AUTHOR

Casey West <F<casey@geeknest.com>>

=head1 COPYRIGHT

Copyright (c) 2002 Casey R. West <casey@geeknest.com>.  All
rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as
Perl itself.

=head1 SEE ALSO

perl(1), L<Coy>.

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-Error-HTML

HTML.pm

package ACME::Error::HTML;

use strict;
no  strict 'refs';

use vars q[$VERSION];
$VERSION = '0.01';

use HTML::FromText;

*die_handler = *warn_handler = sub {
  return text2html "@_",
                   paras        => 1,
                   bold         => 1,
                   metachars    => 0,
                   urls         => 1,
                   email        => 1,
                   underline    => 1,
                   blockparas   => 1,
                   numbers      => 1,
                   bullets      => 1;
};

1;
__END__

=head1 NAME

ACME::Error::HTML - ACME::Error Backend to Markup Errors with HTML

=head1 SYNOPSIS

  use ACME::Error HTML;

  warn "blink"; # <p>blink</p>

=head1 DESCRIPTION

Converts your errors to HTML.

=head1 AUTHOR

Casey West <F<casey@geeknest.com>>

=head1 COPYRIGHT

Copyright (c) 2002 Casey R. West <casey@geeknest.com>.  All
rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as
Perl itself.

=head1 SEE ALSO

perl(1), HTML::FromText.

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-Error-IgpayAtinlay

IgpayAtinlay.pm

package ACME::Error::IgpayAtinlay;

use strict;
no  strict 'refs';

use vars q[$VERSION];
$VERSION = '0.01';

use Lingua::Atinlay::Igpay qw[:all];

*die_handler = *warn_handler = sub {
  my @errors = @_;
  return enhay2igpayatinlay @errors;
};

1;
__END__

=head1 AMENAY

ACMEHAY::Errorhay::IgpayAtinlayhay - ACMEHAY::Errorhay Ackendbay otay Onvertcay Errorshay otay Igpay Atinlay

=head1 OPSISSYNAY

  usehay ACMEHAY::Errorhay => IgpayAtinlayhay;

  arnway "Adbay"; # Adbayhay

=head1 ESCRIPTIONDAY

Onvertscay ouryay errorshay otay Igpay Atinlay.

=head1 AUTHORHAY

Aseycay Estway <F<aseycay@eeknestgay.omcay>>

=head1 OPYRIGHTCAY

Opyrightcay (c) 2002 Aseycay R. Estway <aseycay@eeknestgay.omcay>.  Allhay
ightsray eservedray.  Isthay ogrampray ishay eefray oftwaresay; ouyay ancay
edistributeray ithay andhay/orhay odifymay ithay underhay ethay amesay ermstay ashay
Erlpay itselfhay.

=head1 EESAY ALSOHAY

erlpay(1), Ingualay::Atinlayhay::Igpayhay.

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-Error-Translate

Translate.pm

package ACME::Error::Translate;

use strict;
no  strict 'refs';

use vars qw[$VERSION];
$VERSION = '0.01';

use Lingua::Translate;

{
  my $translator = undef;
  sub import {
    my $class = shift;
    $translator = Lingua::Translate->new( src => 'en', dest => shift );
  }

  *die_handler = *warn_handler = sub {
    if ( $translator ) {
      return map $translator->translate( $_ ), @_;
    } else {
      return @_;
    }
  };
}

1;
__END__

=head1 NAME

ACME::Error::Translate - Language Translating Backend for ACME::Error

=head1 SYNOPSIS

  use ACME::Error Translate => de;

  die "Stop!"; # Anschlag!

=head1 DESCRIPTION

Translates error messages from the default English to the language of your
choice using L<Lingua::Translate>.  As long as the backend used by
L<Lingua::Translage> understands your two letter language code, you're ok.

By default the backend is Babelfish.

=head1 AUTHOR

Casey West <F<casey@geeknest.com>>

=head1 SEE ALSO

perl(1), ACME::Error, Lingua::Translate.

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-Error

lib/ACME/Error.pm

package ACME::Error;

use strict;

use vars qw[$VERSION];
$VERSION = '0.03';

sub import {
  my $class = shift;
  if ( my $style = shift ) {
    my $package = qq[ACME::Error::$style];
    my $args    = join q[', '], @_;
    eval qq[use $package '$args'];
    die $@ if $@;
    
    my $nested = -1;

    { no strict 'refs';
      $SIG{__WARN__} = sub {
        local $SIG{__WARN__};
        $nested++;
        my $handler = $package . q[::warn_handler];
        warn &{$handler}(@_) unless $nested;
        warn @_ if $nested;
        $nested--;
      };

      $SIG{__DIE__}  = sub {
        local $SIG{__DIE__};
        $nested++;
        my $handler = $package . q[::die_handler];
        die &{$handler}(@_) unless $nested;
        die @_ if $nested;
        $nested--;
      };
    }

#    $SIG{__WARN__} = sub {
#      my $handler = $package . q[::warn_handler];
#      {
#       no strict 'refs';
#       warn &{$handler} , "\n" if exists &{$handler};
#      }
#    };

#    $SIG{__DIE__}  = sub {
#      my $handler = $package . q[::die_handler];
#      {
#       no strict 'refs';
#       die &{$handler}, "\n" if exists &{$handler};
#      }
#    };
  }
}

1;
__END__

=head1 NAME

ACME::Error - Never have boring errors again!

=head1 SYNOPSIS

  use ACME::Error SHOUT;
  
  warn "Warning"; # WARNING!

=head1 DESCRIPTION

C<ACME::Error> is a front end to Perl error styles.  C<$SIG{__WARN__}> and C<$SIG{__DIE__}>
are intercepted.  Backends are pluggable.  Choose a backend by specifying it when you
C<use ACME::Error SomeStyle>;

=head2 Writing Backends

Writing backends is easy.  See L<ACME::Error::SHOUT> for a simple example.  Basically your
backend needs to be in the C<ACME::Error> namespace and defines just two subroutines, C<warn_handler>
and C<die_handler>.  The arguments passed to your subroutine are the same as those passed to the signal
handlers, see L<perlvar> for more info on that.  You are expected to C<return> what you want to be
C<warn>ed or C<die>d.

You can also run use an C<import> function.  All arguments passed to C<ACME::Error> after
the style to use will be passed to the backend.

=head1 AUTHOR

Casey West <F<casey@geeknest.com>>

=head1 COPYRIGHT

Copyright (c) 2002 Casey R. West <casey@geeknest.com>.  All
rights reserved.  This program is free software; you can
redistribute it and/or modify it under the same terms as
Perl itself.

=head1 SEE ALSO

perl(1).

=cut

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-MBHall

lib/ACME/MBHall.pm

package ACME::MBHall;

use 5.006;
use strict;
use warnings;

=head1 NAME

ACME::MBHall - The great new ACME::MBHall!

=head1 VERSION

Version 0.03

=cut

our $VERSION = '0.03';


=head1 SYNOPSIS

Quick summary of what the module does.

Perhaps a little code snippet.

    use ACME::MBHall;

    my $foo = ACME::MBHall->new();
    ...

=head1 EXPORT

A list of functions that can be exported.  You can delete this section
if you don't export anything, such as for a purely object-oriented module.

=head1 SUBROUTINES/METHODS

=head2 sum( LIST_OF_NUMBERS )

Returns the sum of the numbers.

=cut

sub sum {
	my $sum = 0;
	foreach my $value (@_) {
		$sum+=$value;
	}
	return $sum;
}

=head2 function2

=cut

sub function2 {
}

=head1 AUTHOR

Matthew Hall, C<< <MBHall at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-mbhall at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-MBHall>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::MBHall


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-MBHall>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-MBHall>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-MBHall>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-MBHall/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2012 Matthew Hall.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of ACME::MBHall

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-MSDN-SPUtility

lib/ACME/MSDN/SPUtility.pm

package ACME::MSDN::SPUtility;

use warnings;
use strict;

use Perl6::Say;

=encoding utf8

=head1 NAME

ACME::MSDN::SPUtility - SPUtility.HideTaiwan Method (Microsoft.SharePoint.Utilities)

=head1 VERSION

Version 0.04

=cut

our $VERSION = '0.04';


=head1 SYNOPSIS

This is a Implementation of part of MSDN SPUtility.
L<http://msdn.microsoft.com/en-us/library/ms441219.aspx>

This module does the following things:
Checks whether the Taiwan calendar is hidden based on the specified Web site and locale ID.
Checks if the China Gov really Lost Their Brain based on the specified Web site and locale ID.
Checks if Bill-GAY$ and his 'Stuffz' lost thier Balls at Halloween based on the specified Web site and locale ID.


	use ACME::MSDN::SPUtility;

	my $fool = ACME::MSDN::SPUtility->new( $SPWeb, int $localeId);
	say 'Hello, Taiwan!' if not $fool->HideTaiwan;
	STDERR->say("I can't speak well if I don't have a brain!") if $fool->HideChina;
	say STDERR 'Plz find my balls for me and give it back to me. I lost all of them!' if $fool->HideMicroSoft;

=head1 FUNCTIONS

=head2 new

Get a SPUtility object.

=cut

sub new {
	my $this = shift;
	my $class = ref($this) || $this;
	my $self = {};
	bless $self, $class;
	#$self->initialize();
	return $self;
}

=head2 HideTaiwan

Checks whether the Taiwan calendar is hidden based on the specified Web site and locale ID.

=cut

sub HideTaiwan {
	my $self = shift;
	my ($spWeb, $localeId) = @_;
	
	print "Taiwan is definitely a Contry already, and should never hide. Is china scared by this?";
	return undef;
};

=head2 HideChina

Checks if the China Gov really Lost Their Brain based on the specified Web site and locale ID.

=cut

sub HideChina {
	my $self = shift;
	my ($spWeb, $localeId) = @_;
	
	print "fsck the dumb China gov";
	return 1;
}

=head2 HideMicroSoft

Checks if Bill-GAY$ and his 'Stuffz' lost thier Balls at Halloween based on the specified Web site and locale ID.

=cut

sub HideMicroSoft {
	my $self = shift;
	my ($spWeb, $localeId) = @_;
	
	print 'Bill-Gay$ and Micro$oft Stuff$ lost their Ballz, did you see them?';
	return 1;
}

=head1 AUTHOR

BlueT - Matthew Lien - 練喆明, C<< <BlueT at BlueT.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-msdn-sputility at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-MSDN-SPUtility>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::MSDN::SPUtility


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-MSDN-SPUtility>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-MSDN-SPUtility>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-MSDN-SPUtility>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-MSDN-SPUtility>

=back


=head1 ACKNOWLEDGEMENTS


=head1 COPYRIGHT & LICENSE

Copyright 2009 BlueT - Matthew Lien - 練喆明, all rights reserved.

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


=cut

1; # End of ACME::MSDN::SPUtility

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-MyFirstModule-SETHS

lib/ACME/MyFirstModule/SETHS.pm

package ACME::MyFirstModule::SETHS;

use 5.006;
use strict;
use warnings;


=head1 NAME

ACME::MyFirstModule::SETHS - The great new ACME::MyFirstModule::SETHS!

=head1 VERSION

Version 0.03

=cut

our $VERSION = '0.03';


=head1 SYNOPSIS

Quick summary of what the module does.

Perhaps a little code snippet.

    use ACME::MyFirstModule::SETHS;

    my $foo = ACME::MyFirstModule::SETHS->new();
    ...

=head1 EXPORT

A list of functions that can be exported.  You can delete this section
if you don't export anything, such as for a purely object-oriented module.

=head1 SUBROUTINES/METHODS

=head2 function1

=cut

sub function1 {
}

=head2 function2

=cut

sub function2 {
}

=head1 AUTHOR

Seth Surchin, C<< <sas0199 at gmail.com> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-myfirstmodule-seths at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-MyFirstModule-SETHS>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::MyFirstModule::SETHS


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-MyFirstModule-SETHS>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-MyFirstModule-SETHS>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-MyFirstModule-SETHS>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-MyFirstModule-SETHS/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2015 Seth Surchin.

This program is free software; you can redistribute it and/or modify it
under the terms of the the Artistic License (2.0). You may obtain a
copy of the full license at:

L<http://www.perlfoundation.org/artistic_license_2_0>

Any use, modification, and distribution of the Standard or Modified
Versions is governed by this Artistic License. By using, modifying or
distributing the Package, you accept this license. Do not use, modify,
or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made
by someone other than you, you are nevertheless required to ensure that
your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service
mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge
patent license to make, have made, use, offer to sell, sell, import and
otherwise transfer the Package with respect to any patent claims
licensable by the Copyright Holder that are necessarily infringed by the
Package. If you institute patent litigation (including a cross-claim or
counterclaim) against any party alleging that the Package constitutes
direct or contributory patent infringement, then this Artistic License
to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


=cut

1; # End of ACME::MyFirstModule::SETHS

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-PM-Voronezh

lib/ACME/PM/Voronezh.pm

package ACME::PM::Voronezh;

use warnings;
use strict;

=head1 NAME

ACME::PM::Voronezh - Talks by Voronezh.pm

=head1 VERSION

Version 0.02

=cut

our $VERSION = '0.02';


=head1 SYNOPSIS

Welcome to Voronezh.PM!


=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::PM::Voronezh


You can also look for information at:

=over 4

=item * Voronezh.PM

L<http://voronezh.pm.org/>

=item * Mailing list

L<http://groups.google.com/group/voronezh-pm>

=item * Twitter

L<http://twitter.com/voronezh_pm>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-PM-Voronezh/>

=back


=head1 AUTHOR

Alexander Nusov, C<< <alexander.nusov+cpan at gmail.com> >>


=head1 ACKNOWLEDGEMENTS

I am grateful to Dmitry Degtyarev C<< <degtyarev.dm at gmail.com> >> who inspired the idea of creating the group.


=head1 LICENSE AND COPYRIGHT

Copyright 2010 Alexander Nusov.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of ACME::PM::Voronezh

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-QuoteDB

lib/ACME/QuoteDB.pm

#$Id: QuoteDB.pm,v 1.36 2009/09/30 07:37:09 dinosau2 Exp $
# /* vim:et: set ts=4 sw=4 sts=4 tw=78: */

package ACME::QuoteDB;

use 5.008005;        # require perl 5.8.5, re: DBD::SQLite Unicode
use warnings;
use strict;

#major-version.minor-revision.bugfix
use version; our $VERSION = qv('0.1.2');

#use criticism 'brutal'; # use critic with a ~/.perlcriticrc

use Exporter 'import';
our @EXPORT = qw/quote/; # support one liner

use Carp qw/croak/;
use Data::Dumper qw/Dumper/;
use ACME::QuoteDB::LoadDB;
use aliased 'ACME::QuoteDB::DB::Attribution' => 'Attr';
use aliased 'ACME::QuoteDB::DB::QuoteCatg'  => 'QuoteCatg';
use aliased 'ACME::QuoteDB::DB::Category'  => 'Catg';
use aliased 'ACME::QuoteDB::DB::Quote'    => 'Quote';

binmode STDOUT, ':encoding(utf8)';
binmode STDERR, ':encoding(utf8)';

sub new {
    my $class = shift;
    my $self = bless {}, $class;
    return $self;
}

# provide 1 non OO method for one liners
sub quote {
    my ($arg_ref) = @_;
    return get_quote(q{}, $arg_ref);
}

# list of quote attributions (names) (makes searching easier)
sub list_attr_names {
   return _get_field_all_from('name', Attr->retrieve_all);
}

# list of quote categories
sub list_categories {
   return _get_field_all_from('catg', Catg->retrieve_all);
}

## list of quote sources
sub list_attr_sources {
   return _get_field_all_from('source', Quote->retrieve_all);
}

sub _get_field_all_from {
   my ($field, @all_stored) = @_;

    my $arr_ref = [];
    RECORDS:
    foreach my $f_obj (@all_stored){
        my $s = $f_obj->$field;
        # if doesn't exist and not a dup
        if (! $f_obj->$field || scalar grep {/$s/sm} @{$arr_ref}){
            next RECORDS;
        }
        push @{ $arr_ref }, $f_obj->$field;
    }
    return join "\n", sort @{$arr_ref};
}

sub _get_attribution_ids_from_name {
    my ($attr_name) = @_;

    my $c_ids = [];
    # a bug: what if string starts with what we specify
    #i.e. => %Griffin% doesn' match 'Griffin' (no quotes)
    RESULTS:
    foreach my $c_obj (Attr->search_like(name => "%$attr_name%")){
       next RESULTS unless $c_obj->attr_id;
       push @{ $c_ids }, $c_obj->attr_id;
    }

    if (not scalar @{$c_ids}) {
        croak 'attribution not found';
    }

    return $c_ids;

}

sub _get_quote_id_from_quote {
    my ($quote) = @_;

    my $q_ids = [];
    # a bug: what if string starts with what we specify
    #i.e. => %Griffin% doesn' match 'Griffin' (no quotes)
    RESULTS:
    foreach my $c_obj (Quote->search(quote => $quote)){
       next RESULTS unless $c_obj->quot_id;
       push @{ $q_ids }, $c_obj->quot_id;
    }

    if (not scalar @{$q_ids}) {
        croak 'quote not found';
    }

    return $q_ids;

}

# can handle scalar or array ref
sub _rm_beg_end_space {
    my ($v) = @_;
    return unless $v;
    if (ref $v eq 'ARRAY'){
      my $arr_ref = ();
      foreach my $vl (@{$v}){
          push @{$arr_ref}, _rm_beg_end_space($vl);
      }
      return $arr_ref;
    }
    else {
      $v =~ s/\A\s+//xmsg;
      $v =~ s/\s+\z//xmsg;
      return $v;
    }
  return;
}

sub _get_one_rand_quote_from_all {
    #my $quotes_ref = [];
    #foreach my $q_obj (Quote->retrieve_all){
    #    next unless $q_obj->quote;
    #    my $record = Attr->retrieve($q_obj->attr_id);
    #    my $attr_name = $record->name || q{};
    #    push @{ $quotes_ref }, $q_obj->quote . "\n-- $attr_name";
    #}
    my $quotes_ref = _get_quote_ref_from_all(Quote->retrieve_all);
    return $quotes_ref->[rand scalar @{$quotes_ref}];
}

sub _get_rating_params {
    my ($rating) = @_;
    return unless $rating;

    my ($lower, $upper) = (q{}, q{});
    ($lower, $upper) = split /-/sm, $rating;

    if ($upper && !$lower) { croak 'negative range not permitted'};

    return (_rm_beg_end_space($lower), _rm_beg_end_space($upper));
}

sub _get_if_rating {
    my ($lower, $upper) = @_;

    if ($lower and $upper) { # a range, find within
        $lower =  qq/ AND rating >= '$lower' /;
        $upper =  qq/ AND rating <= '$upper' /;
    }
    elsif ($lower and not $upper) { # not a range, find exact rating
        $lower =  qq/ AND rating = '$lower' /
        #$upper = q{};
    }
    elsif ($upper and not $lower) {
        $upper =  qq/ AND rating = '$upper' /
        #$lower = q{};
    }

    return ($lower, $upper);
}

sub _get_ids_if_catgs_exist {
    my ($catgs) = @_;

    my $catg_ids = ();
    # get category id
    RECS:
    foreach my $c_obj (Catg->retrieve_all){
        next RECS if not $c_obj->catg;

        if (ref $catgs eq 'ARRAY'){
          foreach my $c (@{$catgs}){
            if ($c_obj->catg eq $c){
              # use cat_id if already exists
              push @{$catg_ids}, $c_obj->catg_id;
            }
          }
        }
        else {
          if ($c_obj->catg eq $catgs){
            # use cat_id if already exists
            push @{$catg_ids}, $c_obj->catg_id;
          }
        }
    }
    return $catg_ids;
}

sub _get_quote_id_from_catg_id {
    my ($catg_ids) = @_;

    my $quote_ids = ();
    RECS:
    foreach my $qc_obj (QuoteCatg->retrieve_all){
        next RECS if not $qc_obj->quot_id;

        if (ref $catg_ids eq 'ARRAY'){
          foreach my $c (@{$catg_ids}){
            if ($qc_obj->catg_id eq $c){
              # use cat_id if already exists
              push @{$quote_ids}, $qc_obj->quot_id;
            }
          }
        }
        else {
          if ($qc_obj->catg_id eq $catg_ids){
            # use cat_id if already exists
            push @{$quote_ids}, $qc_obj->quot_id;
          }
        }
    }
    return $quote_ids;
}

sub _untaint_data {
   my ($arr_ref) = @_;
   my $ut_ref = ();
   foreach my $q (@{$arr_ref}){
      if ($q =~ m{\A([0-9]+)\z}sm){
          push @{$ut_ref}, $1;
      }
   }
   return $ut_ref;
}

# TODO fixme: arg list too long
sub _get_rand_quote_for_attribution {
    my ($attr_name, $lower, $upper, $limit, $contain, $source, $catgs) = @_;

    $attr_name ||= q{};
    $lower     ||= q{};
    $upper     ||= q{};
    $limit     ||= q{};
    $contain   ||= q{};
    $source    ||= q{};
    $catgs     ||= q{};

    my $ids = _get_attribution_ids_from_name($attr_name);
    my $phs = _make_correct_num_of_sql_placeholders($ids);

    if ($attr_name) {
        $attr_name =  qq/ attr_id IN ($phs) /;
    }
    else {
        # why would we want this method without a attribution arg?
        # still, let's handle gracefully
        $attr_name =  q/ attr_id IS NOT NULL /;
        $ids = [];
    }

    if ($source) {
        $source =~ s{'}{''}gsm; # sql escape single quote
        $source =  qq/ AND source = '$source' /;
    }
    my $qids =  q{};
    if ($catgs) {
        $catgs  = _get_ids_if_catgs_exist($catgs);
        my $qid_ref = _get_quote_id_from_catg_id($catgs);
        $qids =  join ',', @{_untaint_data($qid_ref)};
        $qids  =  qq/ AND quot_id IN ($qids) /;
    }

    ($lower, $upper) = _get_if_rating($lower, $upper);

    if ($contain) { $contain =  qq/ AND quote LIKE '%$contain%' / }
    if ($limit) { $limit =  qq/ LIMIT '$limit' / };

    my @q = Quote->retrieve_from_sql(
              qq{ $attr_name $lower $upper $source $qids $contain $limit },
              @{$ids}
            );

    # XXX code duplication but smaller footprint
    # choosing not less code duplication, we'll see,...
    #my $quotes_ref = [];
    #foreach my $q_obj ( @q ){
    #    next unless $q_obj->quote;
    #    my $record = Attr->retrieve($q_obj->attr_id);
    #    my $attr_name = $record->name || q{};
    #    push @{ $quotes_ref }, $q_obj->quote . "\n-- $attr_name";
    #}
    #return _get_quote_ref_from_all(\@q);
    # XXX array_ref does not work here!
    return _get_quote_ref_from_all(@q);

    #return $quotes_ref;
}

sub _get_quote_ref_from_all {
    my (@results) = @_;
    #my ($results) = @_;

    my $quotes_ref = [];
    #foreach my $q_obj ( @{$results} ){
    foreach my $q_obj ( @results ){
        next unless $q_obj->quote;
        my $rec = Attr->retrieve($q_obj->attr_id);
        my $attr_name = $rec->name || q{};
        push @{ $quotes_ref }, $q_obj->quote . "\n-- $attr_name";
    }

    return $quotes_ref;
}

sub _args_are_valid {
    my ( $arg_ref, $accepted ) = @_;

    my $arg_ok = 0;
    foreach my $arg ( %{$arg_ref} ) {
        if ( scalar grep { $arg =~ $_ } @{$accepted} ) {
            $arg_ok = 1;
        }
    }

   if (!$arg_ok) {croak 'unsupported argument option passed'}
}

sub add_quote {
    my ( $self, $arg_ref ) = @_;

    _args_are_valid($arg_ref, [qw/Quote AttrName Source Rating Category/]);

    my $load_db = ACME::QuoteDB::LoadDB->new({
                                #verbose => 1,
                  });

    $load_db->set_record(quote  => $arg_ref->{Quote});
    $load_db->set_record(name   => $arg_ref->{AttrName});
    $load_db->set_record(source => $arg_ref->{Source});
    $load_db->set_record(catg   => $arg_ref->{Category});
    $load_db->set_record(rating => $arg_ref->{Rating});

    if ($load_db->get_record('quote') and $load_db->get_record('name')) {
        return $load_db->write_record;
    }
    else {
        croak 'quote and attribution name are mandatory parameters';
    }

    return;
}

# XXX lame, can only get an id from exact quote
sub get_quote_id {
    my ( $self, $arg_ref ) = @_;

    if (not $arg_ref) {croak 'Quote required'}

    _args_are_valid($arg_ref, [qw/Quote/]);

    my $ids = _get_quote_id_from_quote($arg_ref->{'Quote'});

    return join "\n", sort @{$ids};
}

sub update_quote {
    my ( $self, $arg_ref ) = @_;

    if (not $arg_ref) {croak 'QuoteId and Quote required'}

    _args_are_valid($arg_ref, [qw/Quote QuoteId Source 
                                  Category Rating AttrName/]);

    my $q = Quote->retrieve($arg_ref->{'QuoteId'});

    my $atr = Attr->retrieve($q->attr_id);

    # XXX need to support multi categories
    #my $ctg = Catg->retrieve($q->catg_id);
    my $qc = QuoteCatg->retrieve($q->quot_id);

    my $ctg = Catg->retrieve($qc->catg_id);

    $q->quote($arg_ref->{'Quote'});

    if ($arg_ref->{'Source'}){$q->source($arg_ref->{'Source'})}

    if ($arg_ref->{'Rating'}){$q->rating($arg_ref->{'Rating'})};

    if ($arg_ref->{'AttrName'}){$atr->name($arg_ref->{'AttrName'})};

    # XXX need to support multi categories
    if ($arg_ref->{'Category'}){
       $ctg->catg($arg_ref->{'Category'})
    }

    return ($q->update && $atr->update && $ctg->update);
}

sub delete_quote {
    my ( $self, $arg_ref ) = @_;

    if (not $arg_ref) {croak 'QuoteId required'}

    _args_are_valid($arg_ref, [qw/QuoteId/]);

    my $q = Quote->retrieve($arg_ref->{'QuoteId'});

    #$q->quote($arg_ref->{'QuoteId'});

    return $q->delete;

}

sub get_quote {
    my ( $self, $arg_ref ) = @_;

    # default use case, return random quote from all
    if (not $arg_ref) {
        return _get_one_rand_quote_from_all;
    }

    _args_are_valid($arg_ref, [qw/Rating AttrName Source Category/]);

    my ($lower, $upper) = (q{}, q{});
    if ($arg_ref->{'Rating'}) {
        ($lower, $upper) = _get_rating_params($arg_ref->{'Rating'});
    }

    my $attr_name = q{};
    if ( $arg_ref->{'AttrName'} ) {
        $attr_name = _rm_beg_end_space($arg_ref->{'AttrName'});
    }

    my $source = q{};
    if ( $arg_ref->{'Source'} ) {
        $source = _rm_beg_end_space($arg_ref->{'Source'});
    }

    my $catg; # will become scalar or array ref
    if ( $arg_ref->{'Category'} ) {
       $catg = _rm_beg_end_space($arg_ref->{'Category'});
    }

    # use case for attribution, return random quote
    my $quotes_ref =
          _get_rand_quote_for_attribution($attr_name, $lower,
                     $upper, q{}, q{}, $source, $catg);

    # one random from specified pool
    return $quotes_ref->[rand scalar @{$quotes_ref}];

}

# XXX isn't there a method in DBI for this, bind something,...
# TODO follow up 
sub _make_correct_num_of_sql_placeholders {
    my ($ids) = @_;
    # XXX a hack to make a list of '?' placeholders
    my @qms = ();
    for (1..scalar @{$ids}) {
       push @qms, '?';
    }
    return join ',', @qms;
}

sub get_quotes {
    my ( $self, $arg_ref ) = @_;

    # default use case, return random quote from all
    if (not $arg_ref) {
        return _get_one_rand_quote_from_all;
    }

    _args_are_valid($arg_ref, [qw/Rating AttrName Limit Category Source/]);

    my ($lower, $upper) = (q{}, q{});
    if ($arg_ref->{'Rating'}) {
        ($lower, $upper) = _get_rating_params($arg_ref->{'Rating'});
    }

    my $limit = q{};
    if ($arg_ref->{'Limit'}) {
        # specify 'n' amount of quotes to limit by
        $limit = _rm_beg_end_space($arg_ref->{'Limit'});
    }

    my $attribution = q{};
    if ( $arg_ref->{'AttrName'} ) {
        $attribution = _rm_beg_end_space($arg_ref->{'AttrName'});
    }

    my $source = q{};
    if ( $arg_ref->{'Source'} ) {
        $source = _rm_beg_end_space($arg_ref->{'Source'});
    }

    my $catg = q{};
    if ( $arg_ref->{'Category'} ) {
        $catg = _rm_beg_end_space($arg_ref->{'Category'});
    }
    # use case for attribution, return random quote
    return _get_rand_quote_for_attribution($attribution, $lower,
                     $upper, $limit, q{}, $source, $catg);

}


sub get_quotes_contain {
    my ( $self, $arg_ref ) = @_;


    my $contain = q{};
    if ($arg_ref->{'Contain'}) {
        $contain = _rm_beg_end_space($arg_ref->{'Contain'});
    }
    else {
        croak 'Contain is a mandatory parameter';
    }

    _args_are_valid($arg_ref, [qw/Contain Rating AttrName Limit/]);

    my ($lower, $upper) = (q{}, q{});
    if ($arg_ref->{'Rating'}) {
        ($lower, $upper) = _get_rating_params($arg_ref->{'Rating'});
    }

    my $limit = q{};
    if ($arg_ref->{'Limit'}) {
        $limit = _rm_beg_end_space($arg_ref->{'Limit'});
    }

    # default use case for attribution, return random quote
    my $attr_name = q{};
    if ( $arg_ref->{'AttrName'} ) {
        # return 'n' from random from specified pool
        $attr_name = _rm_beg_end_space($arg_ref->{'AttrName'});
    }

    return _get_rand_quote_for_attribution($attr_name, $lower, $upper, $limit, $contain);
}

1 and 'Chief Wiggum: Uh, no, you got the wrong number. This is 9-1... 2.';


__END__

=head1 NAME

ACME::QuoteDB - API implements CRUD for a Collection of Quotes (adages/proverbs/sayings/epigrams, etc)


=head1 VERSION

Version 0.1.2


=head1 SYNOPSIS

Easy access to a collection of quotes (the 'Read' part)

As quick one liner:

    # randomly display one quote from all available. (like motd, 'fortune')
    perl -MACME::QuoteDB -le 'print quote()'

    # Say you have populated your quotes database with some quotes from 
    # 'The Simpsons'
    # randomly display one quote from all available for person 'Ralph'
    perl -MACME::QuoteDB -le 'print quote({AttrName => "ralph"})'

    # example of output
    Prinskipper Skippel... Primdable Skimpsker... I found something!
    -- Ralph Wiggum

    # get 1 quote, only using these categories (you have defined)
    perl -MACME::QuoteDB -le 'print quote({Category => [qw(Humor Cartoon ROTFLMAO)]})'


In a script/module, OO usage:

    use ACME::QuoteDB;

    my $sq = ACME::QuoteDB->new;

    # get random quote from any attribution
    print $sq->get_quote; 

    # get random quote from specified attribution
    print $sq->get_quote({AttrName => 'chief wiggum'}); 

    # example of output
    I hope this has taught you kids a lesson: kids never learn.
    -- Chief Wiggum

    # get all quotes from one source
    print @{$sq->get_quotes({Source => 'THE SimPSoNs'})}; # is case insensitive

    # get 2 quotes, with a low rating that contain a specific string
    print @{$sq->get_quotes_contain({
                  Contain =>  'til the cow',
                  Rating  => '1-5',
                  Limit   => 2
            })};

    # get 5 quotes from given source
    print @{$sq->get_quotes({Source => 'The Simpsons',
                             Limit  => 5
           })};

    # list all sources
    print $sq->list_attr_sources;

    # list all categories
    print $sq->list_categories;


=head1 DESCRIPTION

This module provides an easy to use programmitic interface 
to a database (sqlite3 or mysql) of 'quotes'.  (any content really, 
that can fit into our L<"defined format"|/"record format">)

For simplicty you can think of it as a modern fancy perl version 
of L<fortune|/fortune> 
(with a management interface, remote database
connection support, 
plus additional features and some not (yet) supported)

Originally, this module was designed for a collection of quotes from a well 
known TV show, once I became aware that distributing it as such would be 
L<copyright infringement|/'copyright infringement'>, I generalized the module, so it can be loaded 
with 'any' content. (in the quote-ish L<format|/"record format">)

=head4 Supported actions include: (CRUD)

=over 4

=item 1 Create

       * Adding quote(s)
       * 'Batch' Loading quotes from a file (stream, other database, etc)

=item 1 Read

       * Displaying a single quote, random or based on some criteria
       * Displaying multiple quotes, based on some criteria
       * Displaying a specific number of quotes, based on some search criteria

=item 1 Update

       * Update an existing quote

=item 1 Delete

       * Remove an existing quote

=back


=head4 Examples of L<Read|/Read>

    my $sq = ACME::QuoteDB->new;

    # on Oct 31st, one could get an appropriate (humorous) quote:
    # (providing, of course that you have defined/populated these categories)
    print $sq->get_quote({Category => [qw(Haloween Humor)]}); 

    # get everthing from certain attributor:
    print @{$sq->get_quotes({AttrName => 'comic book guy'})};

    # get all quotes with a certain rating
    $sq->get_quotes({Rating => '7.0'});

    # get all quotes containing some specific text:
    $sq->get_quotes_contain({Contain => 'til the cow'});


=head4 Examples of L<Create|/Create>

(See L<ACME::QuoteDB::LoadDB> for batch loading)
 
    # add a quote to the database
    my $id_of_added = $sq->add_quote({
                          Quote     => 'Hi, I'm Peter,...",
                          AttrName  => 'Peter Griffin',
                          Source    => 'Family American Dad Guy',
                          Rating    => '1.6',
                          Category  => 'TV Humor',
                      });

=head4 Example of L<Update|/Update>

    # update a quote in the database
    my $quote_id = $sq->get_quote_id({Quote => 'Hi, I'm Peter,..."});

    $sq->update_quote({
        QuoteId   => $quote_id,
        Quote     => 'Hi, I'm Peter, and your not!',
        AttrName  => 'Peter Griffin',
        Source    => 'Family Guy',
        Rating    => '5.7',
        Category  => [qw(TV Humor Crude Adolescent)]
    });

    # category/quote is a many to many relationship: 
    # 1 quote can be in many categories. (and of course 1 category can have many quotes)


=head4 Example of L<Delete|/Delete>

    # delete a quote from the database
    $sq->delete_quote({QuoteId => $quote_id});
    

=over 2

=item record format

One full quote database record currently consits of 5 fields:

Quote, AttrName, Source, Rating, Category

    Quote     => 'the quote desired' # mandatory
    AttrName  => 'who said it'       # mandatory
    Source    => 'where was it said'
    Rating    => 'how you rate the quote/if at all',
    Category  => 'what category is the quote in',

For example:

    Quote     => 'Hi, I'm Peter,...",
    AttrName  => 'Peter Griffin',
    Source    => 'Family Guy',
    Rating    => '8.6',
    Category  => 'TV Humor',

=item * NOTE: In order for this module to be useful one has to load some quotes
 to the database.  Hey, just once though :) (see below - L<Loading Quotes|/"LOADING QUOTES">)

=back

=head1 OVERVIEW

Easy, quick auto-CRUD access to a collection of quotes. (which you provide)

Some ideal uses for this module could be:

=over 4

=item 1 

Quotes Website (quotes/movie/lyrics/limerick/proverbs/jokes/etc)

=item 2 

perl replacement for 'fortune'

=item 3 

Dynamic signature generation

=item 4 

international languages (has utf8 support)

=item 5 

convenient storing/sharing collections of quotes

=item 6 

for me to finally have a place to store (and manage) quotes (that can
be easily backed up or even to a remote db if desired)

=item 7 

anywhere perl is supported and 'quotes' are desired.

=item 8

others? (let me know what you do, if you want, if you do)

=back

See L</DESCRIPTION> above

Also see L<ACME::QuoteDB::LoadDB>


=head1 USAGE

    use ACME::QuoteDB;

    my $sq = ACME::QuoteDB->new;

    print $sq->get_quote;

    # examples are based on quotes data in the test database. 
    # (see tests t/data/)

    # get specific quote based on basic text search.
    # search all 'ralph' quotes for string 'wookie'
    print $sq->get_quotes_contain({
                  Contain   => 'wookie', 
                  AttrName => 'ralph',
                  Limit     => 1          # only return 1 quote (if any)
           });
    # output:
    I bent my wookie.
    -- Ralph Wiggums

    # returns all quotes attributed to 'ralph', with a rating between 
    # (and including) 7 to 9
    print join "\n",  @{$sq->get_quotes({
                                          AttrName => 'ralph', 
                                          Rating    => '7-9'
                                        })
                       };
    
    # same thing but limit to 2 results returned
    # (and including) 7 to 9
    print join "\n",  @{$sq->get_quotes({
                                          AttrName => 'ralph', 
                                          Rating    => '7-9',
                                          Limit     => 2
                                         })
                       };

    # get 6 random quotes (any attribution)
    foreach my $q ( @{$sq->get_quotes({Limit => 6})} ) {
        print "$q\n";
    }


    # get list of available attributions (that have quotes provided by this module)
    print $sq->list_attr_names;

    # any unique part of name will work
    # i.e these will all return the same results (because of our limited
    # quotes db data set)
    print $sq->get_quotes({AttrName => 'comic book guy'});
    print $sq->get_quotes({AttrName => 'comic book'});
    print $sq->get_quotes({AttrName => 'comic'});
    print $sq->get_quotes({AttrName => 'book'});
    print $sq->get_quotes({AttrName => 'book guy'});
    print $sq->get_quotes({AttrName => 'guy'});

   # get all quotes, only using these categories (you have defined)
   print @{$sq->get_quotes({ Category => [qw(Humor ROTFLMAO)] })};

   # get all quotes from Futurama
   print @{$sq->get_quotes({Source => Futurama})};


Also see t/02* included with this distribution.
(available from the CPAN if not included on your system)


=head1 SUBROUTINES/METHODS 

For the most part this is an OO module. There is one function (quote) provided
for command line 'one liner' convenience. 

=head2 quote
    
    returns one quote. (is exported).
    this takes identical arguments to 'get_quote'. (see below)
     
    example:

    perl -MACME::QuoteDB -le 'print quote()'

=head2 new

    instantiate a ACME::QuoteDB object.

    takes no arguments

    # example
    my $sq = ACME::QuoteDB->new;

=head2 get_quote
     
    returns one quote

    # get random quote from any attribution
    print $sq->get_quote;

    # get random quote from specified attribution
    print $sq->get_quote({AttrName => 'chief wiggum'});

    Optional arguments, a hash ref.

    available keys: AttrName, Rating

    my $args_ref = {
                     AttrName => 'chief wiggum'
                     Rating    => 7,
                    };

    print $sq->get_quote($args_ref);

    Note: The 'Rating' option is very subjective. 
    It's a 0-10 scale of 'quality' (or whatever you decide it is)

    To get a list of the available AttrNames use the list_attr_names method
    listed below.  
    
    Any unique part of name will work

    Example, for attribution 'comic book guy'

    # these will all return the same results
    print $sq->get_quotes({AttrName => 'comic book guy'});

    print $sq->get_quotes({AttrName => 'comic book'});

    print $sq->get_quotes({AttrName => 'comic'});

    print $sq->get_quotes({AttrName => 'book'});

    print $sq->get_quotes({AttrName => 'book guy'});

    print $sq->get_quotes({AttrName => 'guy'});
 
    # However, keep in mind the less specific the request is the more results
    # are returned, for example the last one would match, 'Comic Book Guy', 
    # 'Buddy Guy' and 'Guy Smiley',...

=begin comment
    
    # XXX this is a bug with sub _get_attribution_ids_from_name 
    #print $sq->get_quotes({AttrName => 'guy'}); would not match 'Guy Smiley'

=end comment

=head2 add_quote
     
    Adds the supplied record to the database

    possible Key arguments consist of:
        Quote, AttrName, Source, Rating, Category  

    with only Quote and AttrName being mandatory (all are useful though):

    For Example: 

      my $q = 'Lois: Peter, what did you promise me?' .
      "\nPeter: That I wouldn't drink at the stag party." .
      "\nLois: And what did you do?" .
      "\nPeter: Drank at the stag pa-- ... Whoa. I almost walked into that one.";
      
      $sq->add_quote({
          Quote     => $q,
          AttrName  => 'Peter Griffin',
          Source    => 'Family Guy',
          Rating    => '8.6',
          Category  => 'TV Humor',
      });


=head2 get_quote_id (very beta)
 
   given a (verbatim) quote, will retrieve that quotes id
   (only useful for then doing an L</update> or L</delete>

   possible Key arguments consist of: Quote

   my $q = 'Lois: Peter, what did you promise me?' .
  "\nPeter: That I wouldn't drink at the stag party." .
  "\nLois: And what did you do?" .
  "\nPeter: Drank at the stag pa-- ... Whoa. I almost walked into that one.";
  
  my $qid = $sq->get_quote_id({Quote => $q});
  print $qid; # 30

=head2 delete_quote (very beta)

    deletes an existing quote in the database
    takes an valid quote id (see L</get_quote_id>)

    possible Key arguments consist of: QuoteId

      $sq->delete_quote({QuoteId => $qid});


=head2 update_quote (very beta)
     
    updates an existing quote in the database

    possible Key arguments consist of: QuoteId, Quote

      my $q = 'Lois: Peter, what did you promise me?' .
      "\nPeter: That I wouldn't drink at the stag party." .
      "\nLois: And what did you do?" .
      "\nPeter: Drank at the stag pa-- ... Whoa. I almost walked into that one.";

      $q =~ s/Lois/Marge/xmsg;
      $q =~ s/Peter/Homer/xmsg;
 
      $sq->update_quote({
          QuoteId   => $qid, # as returned from L</get_quote_id>
          Quote     => $q,
          AttrName  => 'Lois Simpson',
          Source    => 'The Simpsons Guys',
          Rating    => '9.6',
          Category  => 'Sometimes Offensive Humor',
      });


=head2 get_quotes

    returns zero or more quote(s)

    Optional arguments, a hash ref.

    available keys: AttrName, Rating, Limit

    # returns 2 ralph wiggum quotes with a rating between 
    # (and including) 7 to 9
    print join "\n",  @{$sq->get_quotes({
                                          AttrName => 'ralph', 
                                          Rating    => '7-9',
                                          Limit     => 2
                                         })
                       };

    AttrName and Rating work exactely the same as for get_quote (docs above)
    
    Limit specifies the amout of results you would like returned. (just like
    with SQL)


=head2 get_quotes_contain

    returns zero or more quote(s), based on a basic text search.

    # get specific quote based on basic text search.
    # search all ralph wiggum quotes for string 'wookie'
    print $sq->get_quotes_contain({
                  Contain   => 'wookie', 
                  AttrName => 'ralph',
                  Limit     => 1          # only return 1 quote (if any)
           })->[0]; # q{Ralph: I bent my wookie.};


    Optional arguments, a hash ref.

    available keys: AttrName, Contain, Limit

    AttrName and Limit work exactly the same as for get_quotes (docs above)
    
    Contain specifies a text string to search quotes for. If a AttrName
    option is included, search is limited to that attribution.

    Contain is a simple text string only. Regex not supported
    Contain literally becomes: AND quote LIKE '%$contain%'


=head2 list_attr_names

    returns a list of attributions (name) for which we have quotes.

    # get list of available attributions (that have quotes provided by this module)
    print $sq->list_attr_names;


=head2 list_categories

    returns a list of categories defined in the database

    # get list of available categories (that have quotes provided by this module)
    print $sq->list_categories;


=head2 list_attr_sources

    returns a list of attribution sources defined in the database

    # get list of attribution sources (that have quotes provided by this module)
    print $sq->list_attr_sources;


=head1 LOADING QUOTES

In order to actually use this module, one has to load quotes content,
hopefully this is relativly easy,... (see t/01-load_quotes.t in tests)

=over 4

=item 1 add_quote, one record at a time, probably within an iteration loop

see L</add_quote>

=item 1 (Batch Load) load quotes from a csv file. (tested with comma and tab delimiters)

  format of file must be as follows: (headers)
  "Quote", "Attribution Name", "Attribution Source", "Category", "Rating"
 
  for example:
  "Quote", "Attribution Name", "Attribution Source", "Category", "Rating"
  "I hope this has taught you kids a lesson: kids never learn.","Chief Wiggum","The Simpsons","Humor",9
  "Sideshow Bob has no decency. He called me Chief Piggum. (laughs) Oh wait, I get it, he's all right.","Chief Wiggum","The Simpsons","Humor",8

=item 1 if these dont suit your needs, ACME::QuoteDB::LoadDB is sub-classable, 

  so one can extract data anyway they like and populate the db themselves. 
  (there is a test that illustrates overriding the stub method, 'dbload')

   you need to populate a record data structure:

    $self->set_record(quote  => q{}); # mandatory
    $self->set_record(name   => q{}); # mandatory
    $self->set_record(source => q{}); # optional but useful
    $self->set_record(catg   => q{}); # optional but useful
    $self->set_record(rating => q{}); # optional but useful

   # then to write the record you call
   $self->write_record;

   NOTE: this is a record-by-record operation, so one would perform this within a
   loop. there is no bulk (memory dump) write operation currently.


=back


For more see L<ACME::QuoteDB::LoadDB>


=begin comment
 
    keep pod coverage happy.

    # Coverage for ACME::QuoteDB is 71.4%, with 3 naked subroutines:
    # Attr
    # Quote
    # Catg
    # QuoteCatg

    pod tests incorrectly state, Attr, Quote and Catg are subroutines, well they
    are,... (as aliases) but act on a different object. 
    
    TODO: explore the above (is this a bug, if so, who's?, version effected, 
    create use case, etc) 
    
=head2 Attr

=head2 Quote

=head2 Catg

=head2 QuoteCatg

=end comment

=head1 DIAGNOSTICS

An error such as:

C<DBD::SQLite::db prepare_cached failed: no such table: ,...>

probably means that you do not have a database created in the correct format.

basically, you need to create the database, usually, on a first run

you need to add the flag (to the loader):

create_db => 1, # first run, create the db

appending to an existing database is the default behaviour

see L<ACME::QuoteDB::LoadDB/create_db_tables>

=head1 CONFIGURATION AND ENVIRONMENT

if you are running perl > 5.8.5 and have access to
install cpan modules, you should have no problem installing this module
(utf-8 support in DBD::SQLite not avaible until 5.8 - we don't support 'non
utf-8 mode)

=over 1

=item * By default, the quotes database used by this module installs in the 
system path, 'lib', (See L<Module::Build/"INSTALL PATHS">)
as world writable - i.e. 0666 (and probably owned by root)
If you don't like this, you can modify Build.PL to not chmod the file and it
will install as 444/readonly, you can also set a chown in there for whoever
you want to have RW access to the quotes db.

Alternativly, one can specify a location to a quotes database (file) to use.
(Since the local mode is sqlite3, the file doesn't even need to exist, just
needs read/write access to the path on the filesystem)

Set the environmental variable:

$ENV{ACME_QUOTEDB_PATH} (untested on windows)

(this has to be set before trying a database load and also (everytime before 
using this module, obviouly)

Something such as:

BEGIN { 
    # give alternate path to the DB
    # doesn't need to exist, will create
    $ENV{ACME_QUOTEDB_PATH} = '/home/me/my_stuff/my_quote_db'
}

* (NOTE: be sure this (BEGIN) exists *before* the 'use ACME::QuoteDB' lines)

The default is to use sqlite3.

In order to connect to a mysql database, several environmental variables
are required.

BEGIN {
    # have to set this to use remote database
    $ENV{ACME_QUOTEDB_REMOTE} =  'mysql';
    $ENV{ACME_QUOTEDB_DB}     =  'acme_quotedb';
    $ENV{ACME_QUOTEDB_HOST}   =  'localhost';
    $ENV{ACME_QUOTEDB_USER}   =  'acme_user';
    $ENV{ACME_QUOTEDB_PASS}   =  'acme';
}

Set the above in a begin block.

The database connection is transparent. 

Module usage wise, all operations are the same but now
you will be writing to the remote mysql database specified.

(The user will need read/write permissions to the db/tables)
(mysql admin duties are beyond the scope of this module)

The only supported databases at this time are sqlite and mysql.

It is trivial to add support for others

=back

=head1 DEPENDENCIES

L<Carp>

L<Data::Dumper>

L<criticism> (pragma - enforce Perl::Critic if installed)

L<version>(pragma - version numbers)

L<aliased>

L<Test::More>

L<DBD::SQLite>

L<DBI>

L<Class::DBI>

L<File::Basename>

L<Readonly>

L<Cwd>

L<Module::Build>


=head1 INCOMPATIBILITIES

none known of

=head1 SEE ALSO

man fortune (unix/linux)

L<Fortune>

L<fortune>

L<Acme::RandomQuote::Base>

L<WWW::LimerickDB>

=begin comment

    C<Fortune> http://search.cpan.org/~gward/Fortune-0.2/Fortune.pm
    C<fortune> http://search.cpan.org/~cwest/ppt-0.14/bin/fortune
    C<Acme::RandomQuote::Base> http://search.cpan.org/~mangaru/Acme-RandomQuote-Base-0.01/lib/Acme/RandomQuote/Base.pm
    C<WWW::LimerickDB> http://search.cpan.org/~zoffix/WWW-LimerickDB-0.0305/lib/WWW/LimerickDB.pm

=end comment


=head1 AUTHOR

David Wright, C<< <david_v_wright at yahoo.com> >>

=head1 TODO

=over 2

=item 1 if the database cannot be found, no error is printed!!!

or if you have no write access to it!
"you'll just get 'no attribute can be found,,...", which is cryptic to say
the least!

=item 1 add a dump backup to csv

a backup mechanism for your db to a regular text csv file.

=item 1 clean up tests 'skip if module X' not installed

(one of sqlite3 or mysql is required). currently dies if DBD::SQLite not
installed

=item 1 support multiple categories from LoadDB

how to load multipul categories from a csv file? 
(try to avoid somthing ugly in our csv file format). or maybe don't support
this.

=item 1 (possibly) support long/short quotes output (see 'man fortune')

=back


=head1 BUGS AND LIMITATIONS

The CRUD stuff is weak for sure.
(i.e. add_quote, update_quote, delete_quote, get_quote_id)

For example, currently you can only get the quote id from the exact quote

In the future, I may just expose the DBI::Class object directly
to those that need/want it.

=begin comment

get_quotes_contain  uses %search% to do it's pattern mattching, so that will
miss some obvious searches, which it should find.

i.e.
'Bill' will not find 'Bill' , beginning and endings of words will be off.

XXX - look at search_like, instead of what you are doing now

=end comment

currently, I am not encapsulating the record data structure used 
by LoadDB->write. (i.e. it's a typical perl5 ojbect, the blessed hash)

I will for sure be encapsulating all data in a future version.
(so, don't have code that does $self->{record}->{name} = 'value', or you won't
be happy down the road). Instead use $self->get_record('name') (getter) or
$self->set_record(name => 'my attrib') (setter)


When we are using a SQLite database backend ('regular' local usage), we 
should probably be using, ORLite instead of Class::DBI 
(although we have not seen any issues yet).

Please report any bugs or feature requests to C<bug-acme-quotedb at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-QuoteDB>.  
I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::QuoteDB


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-QuoteDB>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-QuoteDB>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-QuoteDB>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-QuoteDB/>

=back

=head1 ACKNOWLEDGEMENTS

The construction of this module was guided by:

Perl Best Practices - Conway

Test Driven Development

Object Oriented Programming

Gnu

vim 

Debian Linux

Mac OSX

The collective wisdom and code of The CPAN

this module was created with module-starter

module-starter --module=ACME::QuoteDB \
        --author="David Wright" --mb --email=david_v_wright@yahoo.com

=head1 ERRATA

    Q: Why did you put it in the ACME namespace?
    A: Seemed appropriate. I emailed modules@cpan.org and didn't get a
       different reaction.

    Q: Why did you write this?
    A: At a past company, a team I worked on a project with had a test suite, 
    in which at the completion of successful tests (100%), a 'wisenheimer' 
    success message would be printed. (Like a quote or joke or the like)
    (Interestingly, it added a 'fun' factor to testing, not that one is needed 
    of course ;). It was hard to justify spending company time to find and 
    add decent content to the hand rolled process, this would have helped.

    Q: Don't you have anything better to do, like some non-trivial work?
    A: Yup

    Q: Hey Dood! why are u uzing Class::DBI as your ORM!?  Haven't your heard 
       of L<DBIx::Class>?
    A: Yup, and I'm aware of 'the new hotness' L<Rose::DB>. If you use this 
       module and are unhappy with the ORM, feel free to change it. 
       So far L<Class::DBI> is working for my needs.


=head1 FOOTNOTES

=over 4

=item fortune 

unix application in 'games' (FreeBSD) type 'man fortune' from the command line

=item copyright infringement 

L<http://www.avvo.com/legal-answers/is-it-copyright-trademark-infringement-to-operate--72508.html>

=item wikiquote

interesting reading, wikiquote fair use doc: L<http://en.wikiquote.org/wiki/Wikiquote:Copyrights>

=back

=head1 LICENSE AND COPYRIGHT

Copyright 2009 David Wright, all rights reserved.

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


=cut

1; # End of ACME::QuoteDB

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-THEDANIEL-Utils

lib/ACME/THEDANIEL/Utils.pm

package ACME::THEDANIEL::Utils;

use 5.006;
use strict;
use warnings;

use Scalar::Util qw( looks_like_number );
use Carp qw ( croak );

=head1 NAME

ACME::THEDANIEL::Utils - The great new ACME::THEDANIEL::Utils!

=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.01';


=head1 SYNOPSIS

Used to complete the Intermediate Perl textbook

=head1 SUBROUTINES/METHODS

=head2 sum

=cut

sub sum {
  my $sum;
  foreach my $num ( @_ ) {
    if ( !looks_like_number( $num ) ) {
      croak "Invalid input: $num"
    }

    $sum += $num;
  }
  return $sum;
}

=head1 AUTHOR

Daniel jones, C<< <dtj at someplace.com> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-thedaniel-utils at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-THEDANIEL-Utils>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.


=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::THEDANIEL::Utils


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-THEDANIEL-Utils>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-THEDANIEL-Utils>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-THEDANIEL-Utils>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-THEDANIEL-Utils/>

=back


=head1 ACKNOWLEDGEMENTS
Intermediate Perl, 2nd Edition.

=head1 LICENSE AND COPYRIGHT

Copyright 2017 Daniel jones.

This program is free software; you can redistribute it and/or modify it
under the terms of the the Artistic License (2.0). You may obtain a
copy of the full license at:

L<http://www.perlfoundation.org/artistic_license_2_0>

Any use, modification, and distribution of the Standard or Modified
Versions is governed by this Artistic License. By using, modifying or
distributing the Package, you accept this license. Do not use, modify,
or distribute the Package, if you do not accept this license.

If your Modified Version has been derived from a Modified Version made
by someone other than you, you are nevertheless required to ensure that
your Modified Version complies with the requirements of this license.

This license does not grant you the right to use any trademark, service
mark, tradename, or logo of the Copyright Holder.

This license includes the non-exclusive, worldwide, free-of-charge
patent license to make, have made, use, offer to sell, sell, import and
otherwise transfer the Package with respect to any patent claims
licensable by the Copyright Holder that are necessarily infringed by the
Package. If you institute patent litigation (including a cross-claim or
counterclaim) against any party alleging that the Package constitutes
direct or contributory patent infringement, then this Artistic License
to you shall terminate on the date that such litigation is filed.

Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


=cut

1; # End of ACME::THEDANIEL::Utils

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-YAPC-NA-2012

lib/ACME/YAPC/NA/2012.pm

package ACME::YAPC::NA::2012;

use 5.006
use strict;
use warnings;

=head1 NAME

ACME::YAPC::NA::2012 - The great new ACME::YAPC::NA::2012!

=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.02';


=head1 SYNOPSIS

Quick summary of what the module does.

Perhaps a little code snippet.

    use ACME::YAPC::NA::2012;

    my $foo = ACME::YAPC::NA::2012->new();
    ...

=head1 EXPORT

A list of functions that can be exported.  You can delete this section
if you don't export anything, such as for a purely object-oriented module.

=head1 SUBROUTINES/METHODS

=head2 function1

=cut

sub function1 {
}

=head2 function2

=cut

sub function2 {
}

=head1 AUTHOR

Jacinta Richardson, C<< <jarich at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-yapc-na-2012 at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-YAPC-NA-2012>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::YAPC::NA::2012


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-YAPC-NA-2012>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-YAPC-NA-2012>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-YAPC-NA-2012>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-YAPC-NA-2012/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2012 Jacinta Richardson.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of ACME::YAPC::NA::2012

 view all matches for this distribution
 view on metacpan -  search on metacpan

ACME-ltharris

lib/ACME/ltharris.pm

package ACME::ltharris;

use 5.006;
use strict;
use warnings;

=head1 NAME

ACME::ltharris - The great new ACME::ltharris!

=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.03'


=head1 SYNOPSIS

Quick summary of what the module does.

Perhaps a little code snippet.

    use ACME::ltharris;

    my $foo = ACME::ltharris->new();
    ...

=head1 EXPORT

A list of functions that can be exported.  You can delete this section
if you don't export anything, such as for a purely object-oriented module.

=head1 SUBROUTINES/METHODS

=head2 function1

=cut

sub function1 {
}

=head2 function2

=cut

sub function2 {
}

=head1 AUTHOR

L.T. Harris, C<< <lth at ltharris.com> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-ltharris at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-ltharris>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc ACME::ltharris


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=ACME-ltharris>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/ACME-ltharris>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/ACME-ltharris>

=item * Search CPAN

L<http://search.cpan.org/dist/ACME-ltharris/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

Copyright 2012 L.T. Harris.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.


=cut

1; # End of ACME::ltharris

 view all matches for this distribution
 view on metacpan -  search on metacpan

ADAMK-Release

inc/Module/Install.pm

#line 1
package Module::Install;

# For any maintainers:
# The load order for Module::Install is a bit magic.
# It goes something like this...
#
# IF ( host has Module::Install installed, creating author mode ) {
#     1. Makefile.PL calls "use inc::Module::Install"
#     2. $INC{inc/Module/Install.pm} set to installed version of inc::Module::Install
#     3. The installed version of inc::Module::Install loads
#     4. inc::Module::Install calls "require Module::Install"
#     5. The ./inc/ version of Module::Install loads
# } ELSE {
#     1. Makefile.PL calls "use inc::Module::Install"
#     2. $INC{inc/Module/Install.pm} set to ./inc/ version of Module::Install
#     3. The ./inc/ version of Module::Install loads
# }

use 5.005;
use strict 'vars';
use Cwd        ();
use File::Find ();
use File::Path ();

use vars qw{$VERSION $MAIN};
BEGIN {
	# All Module::Install core packages now require synchronised versions.
	# This will be used to ensure we don't accidentally load old or
	# different versions of modules.
	# This is not enforced yet, but will be some time in the next few
	# releases once we can make sure it won't clash with custom
	# Module::Install extensions.
	$VERSION = '1.06';

	# Storage for the pseudo-singleton
	$MAIN    = undef;

	*inc::Module::Install::VERSION = *VERSION;
	@inc::Module::Install::ISA     = __PACKAGE__;

}

sub import {
	my $class = shift;
	my $self  = $class->new(@_);
	my $who   = $self->_caller;

	#-------------------------------------------------------------
	# all of the following checks should be included in import(),
	# to allow "eval 'require Module::Install; 1' to test
	# installation of Module::Install. (RT #51267)
	#-------------------------------------------------------------

	# Whether or not inc::Module::Install is actually loaded, the
	# $INC{inc/Module/Install.pm} is what will still get set as long as
	# the caller loaded module this in the documented manner.
	# If not set, the caller may NOT have loaded the bundled version, and thus
	# they may not have a MI version that works with the Makefile.PL. This would
	# result in false errors or unexpected behaviour. And we don't want that.
	my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
	unless ( $INC{$file} ) { die <<"END_DIE" }

Please invoke ${\__PACKAGE__} with:

	use inc::${\__PACKAGE__};

not:

	use ${\__PACKAGE__};

END_DIE

	# This reportedly fixes a rare Win32 UTC file time issue, but
	# as this is a non-cross-platform XS module not in the core,
	# we shouldn't really depend on it. See RT #24194 for detail.
	# (Also, this module only supports Perl 5.6 and above).
	eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006;

	# If the script that is loading Module::Install is from the future,
	# then make will detect this and cause it to re-run over and over
	# again. This is bad. Rather than taking action to touch it (which
	# is unreliable on some platforms and requires write permissions)
	# for now we should catch this and refuse to run.
	if ( -f $0 ) {
		my $s = (stat($0))[9];

		# If the modification time is only slightly in the future,
		# sleep briefly to remove the problem.
		my $a = $s - time;
		if ( $a > 0 and $a < 5 ) { sleep 5 }

		# Too far in the future, throw an error.
		my $t = time;
		if ( $s > $t ) { die <<"END_DIE" }

Your installer $0 has a modification time in the future ($s > $t).

This is known to create infinite loops in make.

Please correct this, then run $0 again.

END_DIE
	}


	# Build.PL was formerly supported, but no longer is due to excessive
	# difficulty in implementing every single feature twice.
	if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" }

Module::Install no longer supports Build.PL.

It was impossible to maintain duel backends, and has been deprecated.

Please remove all Build.PL files and only use the Makefile.PL installer.

END_DIE

	#-------------------------------------------------------------

	# To save some more typing in Module::Install installers, every...
	# use inc::Module::Install
	# ...also acts as an implicit use strict.
	$^H |= strict::bits(qw(refs subs vars));

	#-------------------------------------------------------------

	unless ( -f $self->{file} ) {
		foreach my $key (keys %INC) {
			delete $INC{$key} if $key =~ /Module\/Install/;
		}

		local $^W;
		require "$self->{path}/$self->{dispatch}.pm";
		File::Path::mkpath("$self->{prefix}/$self->{author}");
		$self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
		$self->{admin}->init;
		@_ = ($class, _self => $self);
		goto &{"$self->{name}::import"};
	}

	local $^W;
	*{"${who}::AUTOLOAD"} = $self->autoload;
	$self->preload;

	# Unregister loader and worker packages so subdirs can use them again
	delete $INC{'inc/Module/Install.pm'};
	delete $INC{'Module/Install.pm'};

	# Save to the singleton
	$MAIN = $self;

	return 1;
}

sub autoload {
	my $self = shift;
	my $who  = $self->_caller;
	my $cwd  = Cwd::cwd();
	my $sym  = "${who}::AUTOLOAD";
	$sym->{$cwd} = sub {
		my $pwd = Cwd::cwd();
		if ( my $code = $sym->{$pwd} ) {
			# Delegate back to parent dirs
			goto &$code unless $cwd eq $pwd;
		}
		unless ($$sym =~ s/([^:]+)$//) {
			# XXX: it looks like we can't retrieve the missing function
			# via $$sym (usually $main::AUTOLOAD) in this case.
			# I'm still wondering if we should slurp Makefile.PL to
			# get some context or not ...
			my ($package, $file, $line) = caller;
			die <<"EOT";
Unknown function is found at $file line $line.
Execution of $file aborted due to runtime errors.

If you're a contributor to a project, you may need to install
some Module::Install extensions from CPAN (or other repository).
If you're a user of a module, please contact the author.
EOT
		}
		my $method = $1;
		if ( uc($method) eq $method ) {
			# Do nothing
			return;
		} elsif ( $method =~ /^_/ and $self->can($method) ) {
			# Dispatch to the root M:I class
			return $self->$method(@_);
		}

		# Dispatch to the appropriate plugin
		unshift @_, ( $self, $1 );
		goto &{$self->can('call')};
	};
}

sub preload {
	my $self = shift;
	unless ( $self->{extensions} ) {
		$self->load_extensions(
			"$self->{prefix}/$self->{path}", $self
		);
	}

	my @exts = @{$self->{extensions}};
	unless ( @exts ) {
		@exts = $self->{admin}->load_all_extensions;
	}

	my %seen;
	foreach my $obj ( @exts ) {
		while (my ($method, $glob) = each %{ref($obj) . '::'}) {
			next unless $obj->can($method);
			next if $method =~ /^_/;
			next if $method eq uc($method);
			$seen{$method}++;
		}
	}

	my $who = $self->_caller;
	foreach my $name ( sort keys %seen ) {
		local $^W;
		*{"${who}::$name"} = sub {
			${"${who}::AUTOLOAD"} = "${who}::$name";
			goto &{"${who}::AUTOLOAD"};
		};
	}
}

sub new {
	my ($class, %args) = @_;

	delete $INC{'FindBin.pm'};
	{
		# to suppress the redefine warning
		local $SIG{__WARN__} = sub {};
		require FindBin;
	}

	# ignore the prefix on extension modules built from top level.
	my $base_path = Cwd::abs_path($FindBin::Bin);
	unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
		delete $args{prefix};
	}
	return $args{_self} if $args{_self};

	$args{dispatch} ||= 'Admin';
	$args{prefix}   ||= 'inc';
	$args{author}   ||= ($^O eq 'VMS' ? '_author' : '.author');
	$args{bundle}   ||= 'inc/BUNDLES';
	$args{base}     ||= $base_path;
	$class =~ s/^\Q$args{prefix}\E:://;
	$args{name}     ||= $class;
	$args{version}  ||= $class->VERSION;
	unless ( $args{path} ) {
		$args{path}  = $args{name};
		$args{path}  =~ s!::!/!g;
	}
	$args{file}     ||= "$args{base}/$args{prefix}/$args{path}.pm";
	$args{wrote}      = 0;

	bless( \%args, $class );
}

sub call {
	my ($self, $method) = @_;
	my $obj = $self->load($method) or return;
        splice(@_, 0, 2, $obj);
	goto &{$obj->can($method)};
}

sub load {
	my ($self, $method) = @_;

	$self->load_extensions(
		"$self->{prefix}/$self->{path}", $self
	) unless $self->{extensions};

	foreach my $obj (@{$self->{extensions}}) {
		return $obj if $obj->can($method);
	}

	my $admin = $self->{admin} or die <<"END_DIE";
The '$method' method does not exist in the '$self->{prefix}' path!
Please remove the '$self->{prefix}' directory and run $0 again to load it.
END_DIE

	my $obj = $admin->load($method, 1);
	push @{$self->{extensions}}, $obj;

	$obj;
}

sub load_extensions {
	my ($self, $path, $top) = @_;

	my $should_reload = 0;
	unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) {
		unshift @INC, $self->{prefix};
		$should_reload = 1;
	}

	foreach my $rv ( $self->find_extensions($path) ) {
		my ($file, $pkg) = @{$rv};
		next if $self->{pathnames}{$pkg};

		local $@;
		my $new = eval { local $^W; require $file; $pkg->can('new') };
		unless ( $new ) {
			warn $@ if $@;
			next;
		}
		$self->{pathnames}{$pkg} =
			$should_reload ? delete $INC{$file} : $INC{$file};
		push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
	}

	$self->{extensions} ||= [];
}

sub find_extensions {
	my ($self, $path) = @_;

	my @found;
	File::Find::find( sub {
		my $file = $File::Find::name;
		return unless $file =~ m!^\Q$path\E/(.+)\.pm\Z!is;
		my $subpath = $1;
		return if lc($subpath) eq lc($self->{dispatch});

		$file = "$self->{path}/$subpath.pm";
		my $pkg = "$self->{name}::$subpath";
		$pkg =~ s!/!::!g;

		# If we have a mixed-case package name, assume case has been preserved
		# correctly.  Otherwise, root through the file to locate the case-preserved
		# version of the package name.
		if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
			my $content = Module::Install::_read($subpath . '.pm');
			my $in_pod  = 0;
			foreach ( split //, $content ) {
				$in_pod = 1 if /^=\w/;
				$in_pod = 0 if /^=cut/;
				next if ($in_pod || /^=cut/);  # skip pod text
				next if /^\s*#/;               # and comments
				if ( m/^\s*package\s+($pkg)\s*;/i ) {
					$pkg = $1;
					last;
				}
			}
		}

		push @found, [ $file, $pkg ];
	}, $path ) if -d $path;

	@found;
}





#####################################################################
# Common Utility Functions

sub _caller {
	my $depth = 0;
	my $call  = caller($depth);
	while ( $call eq __PACKAGE__ ) {
		$depth++;
		$call = caller($depth);
	}
	return $call;
}

# Done in evals to avoid confusing Perl::MinimumVersion
eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@;
sub _read {
	local *FH;
	open( FH, '<', $_[0] ) or die "open($_[0]): $!";
	my $string = do { local $/; <FH> };
	close FH or die "close($_[0]): $!";
	return $string;
}
END_NEW
sub _read {
	local *FH;
	open( FH, "< $_[0]"  ) or die "open($_[0]): $!";
	my $string = do { local $/; <FH> };
	close FH or die "close($_[0]): $!";
	return $string;
}
END_OLD

sub _readperl {
	my $string = Module::Install::_read($_[0]);
	$string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg;
	$string =~ s/(\n)\n*__(?:DATA|END)__\b.*\z/$1/s;
	$string =~ s/\n\n=\w+.+?\n\n=cut\b.+?\n+/\n\n/sg;
	return $string;
}

sub _readpod {
	my $string = Module::Install::_read($_[0]);
	$string =~ s/(?:\015{1,2}\012|\015|\012)/\n/sg;
	return $string if $_[0] =~ /\.pod\z/;
	$string =~ s/(^|\n=cut\b.+?\n+)[^=\s].+?\n(\n=\w+|\z)/$1$2/sg;
	$string =~ s/\n*=pod\b[^\n]*\n+/\n\n/sg;
	$string =~ s/\n*=cut\b[^\n]*\n+/\n\n/sg;
	$string =~ s/^\n+//s;
	return $string;
}

# Done in evals to avoid confusing Perl::MinimumVersion
eval( $] >= 5.006 ? <<'END_NEW' : <<'END_OLD' ); die $@ if $@;
sub _write {
	local *FH;
	open( FH, '>', $_[0] ) or die "open($_[0]): $!";
	foreach ( 1 .. $#_ ) {
		print FH $_[$_] or die "print($_[0]): $!";
	}
	close FH or die "close($_[0]): $!";
}
END_NEW
sub _write {
	local *FH;
	open( FH, "> $_[0]"  ) or die "open($_[0]): $!";
	foreach ( 1 .. $#_ ) {
		print FH $_[$_] or die "print($_[0]): $!";
	}
	close FH or die "close($_[0]): $!";
}
END_OLD

# _version is for processing module versions (eg, 1.03_05) not
# Perl versions (eg, 5.8.1).
sub _version ($) {
	my $s = shift || 0;
	my $d =()= $s =~ /(\.)/g;
	if ( $d >= 2 ) {
		# Normalise multipart versions
		$s =~ s/(\.)(\d{1,3})/sprintf("$1%03d",$2)/eg;
	}
	$s =~ s/^(\d+)\.?//;
	my $l = $1 || 0;
	my @v = map {
		$_ . '0' x (3 - length $_)
	} $s =~ /(\d{1,3})\D?/g;
	$l = $l . '.' . join '', @v if @v;
	return $l + 0;
}

sub _cmp ($$) {
	_version($_[1]) <=> _version($_[2]);
}

# Cloned from Params::Util::_CLASS
sub _CLASS ($) {
	(
		defined $_[0]
		and
		! ref $_[0]
		and
		$_[0] =~ m/^[^\W\d]\w*(?:::\w+)*\z/s
	) ? $_[0] : undef;
}

1;

# Copyright 2008 - 2012 Adam Kennedy.

 view all matches for this distribution
 view on metacpan -  search on metacpan

( run in 1.013129 second using v1.00-cache-1.03-grep-61e7a6e-cpan-77cd5a4d78a )