Archive::Builder::Generators - Default generators, and writing your own


Archive-Builder documentation Contained in the Archive-Builder distribution.

Index


Code Index:

NAME

Top

Archive::Builder::Generators - Default generators, and writing your own

SYNOPSIS

Top

  # Our own useless generator
  sub generator {
      my $File = isa( $_[0], 'Archive::Builder::File' )
          ? shift : return undef;

      # Create the file contents
      my $contents = 'Something trivial';

      return \$contents;
  }

DESCRIPTION

Top

This documentation outlines the default generators available to you, and how to write generators of your own to extend Archive::Builder.

DEFAULT GENERATORS

Top

A limited set of generators for the most common situation are provided for you.

The 'string' Generator

The 'string' default generator is a simple pass-through for when you already have the contents of the file, generated by another method. The generator takes one argument, which can be either a scalar containing the file contents, or a reference to a scalar containing the file contents

The 'file' Generator

The 'file' generator takes as an argument of a file name, and slurps in the file as the contents. It should be used when the builder file already exists on disk, and just needs to be used directly. Most commonly used for binary files like images and such, that might need to be included, but not modified.

The 'handle' Generator

The 'handle' generator takes as argument a single object of an IO::Handle object. It allows you use something the can only easily be accessed as an IO handle easily.

The generator will read from the handle until an EOF is reached and then returns the results.

The 'template' Generator

The 'template' generator hooks in to the power of Template Toolkit. It takes three arguments.

The first is a valid Template object. You would be expected to use the same Template object for multiple files, and can do so without ill effect. The generator does not modify the Template object.

The second and third arguments are the path of the template file to process and a reference to a hash containing the values to provide to the template, using the same values as you would for the normal Template process method.

And error will be caught and passed on, and becomes available from $Archive::Builder::errstr or one of the errstr methods.

WRITING GENERATORS

Top

Writing a generator is fairly simple. It consist of a single function, residing in a module. It takes some arguments, builds the contents of a file in a single scalar, and then returns a reference to that scalar.

A typical function will look something like this ( you may cut and paste ).

  sub generator {
      # Get the file argument
      my $File = UNIVERSAL::isa( $_[0], 'Archive::Builder::File' )
          ? shift : return undef;

      # Get and check any other arguments
      my $argument = shift;
      return $File->_error( 'Bad argument' ) unless defined $argument;

      # Build the contents
      my $contents = "Something: $argument";

      # Returns the contents
      return \$contents;
  }

Arguments

The function takes as its first argument the Archive::Builder::File object it is part of. The first few lines of the function should look Any remaining arguments are passed as recieved from the File object constructor. You should do your own checking on the validity of the arguments.

Returning the Contents

The contents of the file MUST be returned as a reference to a scalar. For example.

  my $contents = "This\n";
  $content .= "That\n";
  return \$content;

Returning an Error

The Archive::Builder::File argument we recieve gives us the ability to set an error that can be retrieved later from the $Archive::Builder::errstr variable, or through one of the errstr methods.

The method _error( message ) sets the error string to the value of message, and returns a value of undef. Thus, an easy way to say "Return this error" is simply to write.

  return $File->_error( 'This is an error' );

The _error method will return undef, which will be returned to our caller, signalling an error.

USING OUR GENERATOR

Top

To use our new generator, assuming it's in package Our::New, simply pass its fullyt referenced name as a string.

  $Section->new_file( 'file/path', 'Our::New::generator', $argument );

If the Our::New package is loaded already, the generator will be called normally. If the Our::New package is NOT loaded, Archive::Builder will attempt to load the package Our::New before calling the generator function.

TO DO

Top

Some more interesting default generators, as needed or requested.

SUPPORT

Top

Bugs should always be submitted via the CPAN bug tracker.

http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Archive-Builder

For other issues, contact the maintainer.

AUTHOR

Top

Adam Kennedy <adamk@cpan.org>

SEE ALSO

Top

Archive::Builder, Archive::Builder::Archive Archive::Tar, Archive::Zip.

COPYRIGHT

Top


Archive-Builder documentation Contained in the Archive-Builder distribution.

package Archive::Builder::Generators;

# This package contains a set of default generators 
# for the most common cases.

use strict;
use Params::Util     qw{ _INSTANCE _SCALAR0 _HASH0 };
use Archive::Builder ();

use vars qw{$VERSION};
BEGIN {
	$VERSION = '1.16';
}





#####################################################################
# Trvial Generators

# Recieves as an argument the exact string the file should contain
sub string {
	my $File   = _INSTANCE(shift, 'Archive::Builder::File' ) or return undef;
	my $string = shift;
	return _SCALAR0($string) ? $string
		: ref $string ? undef
		: defined $string ? \$string
		: undef;
};

# Recieves as an argument the name of a file
sub file {
	my $File     = _INSTANCE(shift, 'Archive::Builder::File') or return undef;
	my $filename = -f $_[0] ? shift : return undef;

	# Slurp in the file
	File::Flat->slurp( $filename )
		or $File->_error( "Failed to load file '$filename'" );
}

# Takes any object derived from class IO::Handle, reads it in
# and returns it. An optional second argument is the number of bytes 
# to read in at a time ( the chunk size ). Default is 8192 ( 8 kilobytes )
sub handle {
        my $File = _INSTANCE(shift, 'Archive::Builder::File') or return undef;

	# Get and check the handle
	my $handle = _INSTANCE(shift, 'IO::Handle')
		or return $File->_error( 'Was not passed an IO::Handle argument' );
	my $chunk_size = shift || (8 * 1024);

	# Read in everything
	my $contents = '';
	my ($rv, $buffer);
	while ( $rv = $handle->sysread( $buffer, $chunk_size ) ) {
		$contents .= $buffer;
	}

	defined $rv ? \$contents
		: $File->_error( 'Error while reading from handle' );
}	





#####################################################################
# Common Advanced Generators

# The template generator will only work if the Template Toolkit is installed.
# The first argument is an instantiation of a Template object.
# The second argument is the file name withing the Template object.
# The third argument is the hash reference to pass to the template.
sub template {
	my $File = _INSTANCE(shift, 'Archive::Builder::File' ) or return undef;

	# Before beginning, test to see if Template toolkit is installed
	unless ( Class::Autouse->load( 'Template' ) ) {
		return $File->_error( 'Template Toolkit is not installed, or could not be loaded' );
	}
	
	# Get and check the arguments
	my $Template = _INSTANCE(shift, 'Template' )
		or return $File->_error( 'First argument was not a Template object' );
	my $toparse = shift
		or return $File->_error( 'You did not specify something to parse' );
	my $args = (_HASH0($_[0]) || ! defined $_[0]) ? shift
		: return $File->_error( 'Invalid argument hashref for Template' );
	
	# Create a string to capture the output into.
	my $output = '';
	
	# Process the template
	$Template->process( $toparse, $args, \$output ) ? \$output
		: $File->_error( "Template Error: " . $Template->error );
}

1;

__END__