This is Info file pm.info, produced by Makeinfo version 1.68 from the
input file bigpm.texi.


File: pm.info,  Node: Data/FixedFormat,  Next: Data/Flow,  Prev: Data/Dumper,  Up: Module List

converter between fixed-fields and hashes
*****************************************

NAME
====

   Data::FixedFormat - converter between fixed-fields and hashes

SYNOPSIS
========

     use Data::FixedFormat;

     my $tarhdr = new Data::FixedFormat [ 'name:a100', 'mode:a8', 'uid:a8',
     			        'gid:a8', 'size:a12', 'mtime:a12',
     				'chksum:a8', 'typeflag:a1',
     				'linkname:a100', 'magic:a6',
     				'version:a2', 'uname:a32',
     				'gname:a32', 'devmajor:a8',
     				'devminor:a8', 'prefix:a155' ];
     my $buf;
     read TARFILE, $buf, 512;

     # create a hash from the buffer read from the file
     my $hdr = $tarhdr->unformat($buf);   # $hdr gets a hash ref

     # create a flat record from a hash reference
     my $buf = $tarhdr->format($hdr);     # $hdr is a hash ref

DESCRIPTION
===========

   *Data::FixedFormat* can be used to convert between a buffer with fixed
field definitions and a hash with named entries for each field.

   First, load the Data::FixedFormat module:

     use Data::FixedFormat;

   To create a converter, invoke the new method with a reference to an
array of field specifications:

     my $cvt = new Data::FixedFormat [ 'field-name:descriptor:count', ... ];

field-name
     This is the name of the field and will be used as the hash index.

descriptor
     This describes the content and size of the field.  All of the
     descriptors get strung together and passed to pack and unpack as part
     of the template argument.  See *perldoc -f pack* for information on
     what can be specified here.

count
     This specifies a repeat count for the field.  If not specified, it
     defaults to 1.  If greater than 1, this field's entry in the resultant
     hash will be an array reference instead of a scalar.

   To convert a buffer of data into a hash, pass the buffer to the
*unformat* method:

     $hashref = $cvt->unformat($buf);

   Data::FixedFormat applies the format to the buffer and creates a hash
containing an element for each field.  Fields can now be accessed by name
though the hash:

     print $hashref->{field-name};
     print $hashref->{array-field}[3];

   To convert the hash back into a fixed-format buffer, pass the hash
reference to the format method:

     $buf = $cvt->format($hashref);

   Variant record formats are supported.  Instead of passing an array
reference to the new method, pass a hash reference containing the
following elements:

Chooser
     When converting a buffer to a hash, this subroutine is invoked after
     applying the first format to the buffer.  The hash reference is passed
     to this routine.  Any field names specified in the first format are
     available to be used in making a decision on which format to use to
     decipher the buffer.  This routine should return the index of the
     proper format specification.

     When converting a hash to a buffer, this subroutine is invoked to
     first to choose a packing format.  Since the same function is used for
     both conversions, this function should restrict itself to field names
     that exist in format 0 and those fields should exist in the same place
     in all formats.

Formats
     This is a reference to an array of references to formats.

   For example:

     my $cvt = new Data::FixedFormat {
         Chooser => sub { $_[0]->{RecordType} eq '0' ? 1 : 2 },
     	Format => [ [ 'RecordType:A1' ],
     		    [ 'RecordType:A1', 'FieldA:A6', 'FieldB:A4:4' ],
     		    [ 'RecordType:A1', 'FieldC:A4', 'FieldD:A18' ] ]
         };
     my $rec0 = $cvt->unformat("0FieldAB[0]B[1]B[2]B[3]");
     my $rec1 = $cvt->unformat("1FldC<-----FieldD----->");

   Each Data::FixedFormat instance also contains the following attributes:

Names
     Names contains a list of lists of field names indexed as [record
     variant, field number].  For example, to find the third field name in
     a non-variant record, use `$cvt-'{Names}[0][2]>.

Count
     Count contains a list of list of occurrence counts.  This is used to
     indicate which fields contain arrays.

Format
     Format contains a list of template strings for the Perl pack and
     unpack functions.

AUTHOR
======

   Data::FixedFormat was written by Thomas Pfau <pfau@eclipse.net>
http://www.eclipse.net/~pfau/.

COPYRIGHT
=========

   Copyright (C) 2000 Thomas Pfau.  All rights reserved.

   This module is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.

   This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
License for more details.

   You should have received a copy of the GNU General Public License along
with this progam; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.


File: pm.info,  Node: Data/Flow,  Next: Data/Grove,  Prev: Data/FixedFormat,  Up: Module List

Perl extension for simple-minded recipe-controlled build of data.
*****************************************************************

NAME
====

   Data::Flow - Perl extension for simple-minded recipe-controlled build
of data.

SYNOPSIS
========

     use Data::Flow;
     $recipes = { path  => { default => './MANIFEST'},
     	       contents => { prerequisites => ['path', 'x'] ,
     			     process =>
     			     sub {
     			       my $data = shift;
     			       $data->{ shift() } = `cat $data->get('path')`
     				 x $data->get('x');
     			     }
     			   },
     	     };

     $request = new Data::Flow $recipes;
     $request->set( x => 1);
     print $request->get('contents');

     tie %request, Data::Flow, $recipes;
     $request{x} = 1;
     print $request{contents};

DESCRIPTION
===========

   The module Data::Flow provides its services via objects. The objects may
be obtained by the usual

     $request = new Data::Flow $recipes;

   paradigm. The argument $recipes is a hash reference, which provides the
rules for request processing. The objects support two methods, set() and
get(). The first one is used to provide input data for processing, the
second one to obtain the output.

   The unit of requested information is a field. The method set() takes a
pair `field => value', the method get() takes one argument: the field.

   Every object is created without any fields filled, but it knows how to
*construct* fields basing on other fields or some global into. This
knowledge is provided in the argument $recipe of the new() function. This
is a reference to a hash, keyed by fields. The values of this hash are
hash references themselves, which describe how to acquire the field which
is the corresponding key of the initial hash.

   The internal hashes may have the following keys:

default
     describes the default value for the key, if none is provided by
     set(). The value becomes the value of the field of the object. No
     additional processing is performed. Example:

          default => $Config{installdir}

`prerequisites'
     gives the fields which are needed for the construction of the given
     field. The corresponding value is an array references. The array
     contains the required fields.

     If defaults did not satisfy the request for a field, but
     `$recipe->{field}{prerequisites}' exists, the required fields are
     build before any further processing is done. Example:

          prerequisites => [ qw(prefix arch) ]

process
     contains the rule to build the field. The value is a reference to a
     subroutine taking 2 arguments: the object $request, and the name of
     the required field. It is up to the subroutine to actually fill the
     corresponding field of $data, an error condition is raised if it did
     not. Example:

          process => sub { my $data = shift;
          		   $data->set( time => localtime(time) ) }

output
     the corresponing value has the same meaning as for process, but the
     return value of the subroutine is used as the value of the field.
     Example:

          output => sub { localtime(time) }

filter
     contains the rule to build the field basing on other fields. The value
     is a reference to an array. The first element of the array is a
     reference to a subroutine, the rest contains names of the fields. When
     the subroutine is called, the arguments are the values of fields of
     the object $request which appear in the array (in the same order). The
     return value of the subroutine is used as the value of the field.
     Example:

          filter => [ sub { shift + shift },
          	      'first_half', 'second_half' ]

     Note that the mentioned field will be automatically marked as
     prerequisites.

`class_filter'
     is similar to filter, but the first argument is the name of the
     method to call, second one is the name of the package to use for the
     method invocation. The rest contains names of field to provide as
     method arguments. Example:

          class_filter => [ 'new', 'FileHandle', 'filename' ]

`method_filter'
     is similar to `class_filter', but the second argument is the name of
     the field which is used to call the method upon. Example:

          method_filter => [ 'show', 'widget_name', 'current_display' ]

Tied interface
--------------

   The access to the same functionality is available via tied hash
interface.

AUTHOR
======

   Ilya Zakharevich, ilya@math.ohio-state.edu

SEE ALSO
========

   perl(1), make(1).


File: pm.info,  Node: Data/Grove,  Next: Data/Grove/Parent,  Prev: Data/Flow,  Up: Module List

support for deeply nested structures
************************************

NAME
====

   Data::Grove - support for deeply nested structures

SYNOPSIS
========

     use Data::Grove;

     $object = MyPackage->new;

     package MyPackage;
     @ISA = qw{Data::Grove};

DESCRIPTION
===========

   `Data::Grove' provides support for deeply nested tree or graph
structures.  `Data::Grove' is intended primarily for Perl module authors
writing modules with many types or classes of objects that need to be
manipulated and extended in a consistent and flexible way.

   `Data::Grove' is best used by creating a core set of "data" classes and
then incrementally adding functionality to the core data classes by using
"extension" modules.  One reason for this design is so that the data
classes can be swapped out and the extension modules can work with new
data sources.  For example, these other data sources could be disk-based,
network-based or built on top of a relational database.

   Two extension modules that come with `Data::Grove' are
`Data::Grove::Parent' and `Data::Grove::Visitor'.  `Data::Grove::Parent'
adds a `Parent' property to grove objects and implements a `root' method
to grove objects to return the root node of the tree from anywhere in the
tree and a ``rootpath'' method to return a list of nodes between the root
node and "this" node.  `Data::Grove::Visitor' adds callback methods
`accept' and ``accept_name'' that call your handler or receiver module
back by object type name or the object's name.

   `Data::Grove' objects do not contain parent references, Perl garbage
collection will delete them when no longer referenced and sub-structures
can be shared among several structures.  `Data::Grove::Parent' is used to
create temporary objects with parent pointers.

   Properties of data classes are accessed directly using Perl's hash
functions (i.e. ``$object->{Property}'').  Extension modules may also
define properties that they support or use, for example
Data::Grove::Parent adds `Parent' and `Raw' properties and Visitor depends
on `Name' and `Content' properties.

   See the module XML::Grove for an example implementation of
`Data::Grove'.

METHODS
=======

new( PROPERTIES )
     Return a new object blessed into the SubClass, with the given
     properties.  PROPERTIES may either be a list of key/value pairs, a
     single hash containing key/value pairs, or an existing `Data::Grove'
     object.  If an existing `Data::Grove' is passed to `new()', a shallow
     copy of that object will be returned.  A shallow copy means that you
     are returned a new object, but all of the objects underneath still
     refer to the original objects.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1)


File: pm.info,  Node: Data/Grove/Parent,  Next: Data/Grove/Visitor,  Prev: Data/Grove,  Up: Module List

provide parent properties to Data::Grove objects
************************************************

NAME
====

   Data::Grove::Parent - provide parent properties to Data::Grove objects

SYNOPSIS
========

     use Data::Grove::Parent;

     $root = $object->root;
     $rootpath = $object->rootpath;
     $tied = $object->add_magic([ $parent ]);

     $node = Data::Grove::Parent->new($hash [, $parent]);
     $node_list = Data::Grove::ParentList->new($array [, $parent]);

DESCRIPTION
===========

   Data::Grove::Parent is an extension to Data::Grove that adds `Parent'
and `Raw' properties to Data::Grove objects and methods for returning the
root node of a grove, a list of nodes between and including the root node
and the current node, and a method that creates parented nodes.

   Data::Grove::Parent works by creating a Perl "tied" object that
contains a parent reference (`Parent') and a reference to the original
Data::Grove object (`Raw').  Tying-magic is used so that every time you
reference the Data::Grove::Parent object it actually references the
underlying raw object.

   When you retrieve a list or a property of the Raw object,
Data::Grove::Parent automatically adds magic to the returned list or node.
This means you only call `add_magic()' once to create the first
Data::Grove::Parent object and then use the grove objects like you
normally would.

   The most obvious use of this is so you don't have to call a `delete'
method when you want to release a grove or part of a grove; since
Data::Grove and Data::Grove::Parent objects have no cyclic references,
Perl can garbage collect them normally.

   A secondary use is to allow you to reuse grove or property set
fragments in multiple trees.  WARNING: Data::Grove currently does not
protect you from creating your *own* cyclic references!  This could lead
to infinite loops if you don't take care to avoid them.

METHODS
=======

$object->root()
$object->rootpath()
     `root()' returns the root node if `$object' is a
     ``Data::Grove::Parent'' object.  ``rootpath()'' returns an array of
     all the nodes between and including the root node and `$object'.

$tied = $object->add_magic([ $parent ])
     ``add_magic()'' returns a `Data::Grove::Parent' object with `$object'
     as it's `Raw' object.  If ``$parent'' is given, that becomes the tied
     object's parent object.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Data::Grove(3)


File: pm.info,  Node: Data/Grove/Visitor,  Next: Data/HexDump,  Prev: Data/Grove/Parent,  Up: Module List

add visitor/callback methods to Data::Grove objects
***************************************************

NAME
====

   Data::Grove::Visitor - add visitor/callback methods to Data::Grove
objects

SYNOPSIS
========

     use Data::Grove::Visitor;

     @results = $object->accept ($visitor, ...);
     @results = $object->accept_name ($visitor, ...);
     @results = $object->children_accept ($visitor, ...);
     @results = $object->children_accept_name ($visitor, ...);

DESCRIPTION
===========

   Data::Grove::Visitor adds visitor methods (callbacks) to Data::Grove
objects.  A "visitor" is a class (a package) you write that has methods
(subs) corresponding to the objects in the classes being visited.  You use
the visitor methods by creating an instance of your visitor class, and
then calling ``accept($my_visitor)'' on the top-most object you want to
visit, that object will in turn call your visitor back with
``visit_*OBJECT*'', where OBJECT is the type of object.

   There are several forms of `accept'.  Simply calling `accept' calls
your package back using the object type of the object you are visiting.
Calling ``accept_name'' on an element object calls you back with
``visit_name_*NAME*'' where NAME is the tag name of the element, on all
other objects it's as if you called `accept'.

   All of the forms of `accept' return a concatenated list of the result
of all `visit' methods.

   ``children_accept'' calls `accept' on each of the children of the
element.  This is generally used in element callbacks to recurse down into
the element's children, you don't need to get the element's contents and
call `accept' on each item.  ``children_accept_name'' does the same but
calling ``accept_name'' on each of the children.  ``attr_accept'' calls
`accept' on each of the objects in the named attribute.

   Refer to the documentation of the classes you are visiting (XML::Grove,
etc.) for the type names (``element'', ``document'', etc.) of the objects
it implements.

RESERVED NAMES
==============

   The hash keys `Contents' and `Name' are used to indicate objects with
children (for ``children_accept'') and named objects (for ``accept_name'').

NOTES
=====

   These are random ideas that haven't been implemented yet:

   * Several objects fall into subclasses, or you may want to be able to
     subclass a visited object and still be able to tell the difference.
     In SGML::Grove I had used the package name in the callback
     (``visit_SGML_Element'') instead of a generic name
     (``visit_element'').  The idea here would be to try calling
     ``visit_*PACKAGE*'' with the most specific class first, then try
     superclasses, and lastly to try the generic.

AUTHOR
======

   Ken MacLeod, ken@bitsko.slc.ut.us

SEE ALSO
========

   perl(1), Data::Grove

   Extensible Markup Language (XML) <http://www.w3c.org/XML>


File: pm.info,  Node: Data/HexDump,  Next: Data/Hexdumper,  Prev: Data/Grove/Visitor,  Up: Module List

Hexadecial Dumper
*****************

NAME
====

   Data::HexDump - Hexadecial Dumper

SYNOPSIS
========

     use Data::HexDump;

     my $buf = "foo\0bar";
     print HexDump $buf;

     or

     my $f = new Data::HexDump;
     $f->data($buf);
     print $f->dump;

     or

     my $fh = new FileHandle $file2dump;
     my $f = new Data::HexDump;
     $f->fh($fh);
     $f->block_size(1024);
     print while $_ = $f->dump;
     close $fh;

     or

     my $f = new Data::HexDump;
     $f->file($file2dump);
     $f->block_size(1024);
     print while $_ = $f->dump;

DESCRIPTION
===========

   Dump in hexadecimal the content of a scalar. The result is returned in a
string. Each line of the result consists of the offset in the source in
the leftmost column of each line, followed by one or more columns of data
from the source in hexadecimal. The rightmost column of each line shows
the printable characters (all others are shown as single dots).

COPYRIGHT
=========

   Copyright (c) 1998-1999 Fabien Tassin. All rights reserved.  This
program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

AUTHOR
======

   Fabien Tassin <fta@oleane.net>

VERSION
=======

   0.02 - Second release (September 1999)

SEE ALSO
========

   perl(1)


File: pm.info,  Node: Data/Hexdumper,  Next: Data/JavaScript,  Prev: Data/HexDump,  Up: Module List

A module for displaying binary data in a readable format
********************************************************

NAME
====

   Hexdumper - A module for displaying binary data in a readable format

SYNOPSIS
========

   use Data::Hexdumper; Data::Hexdumper::dump(     data => $data,
# what to dump     number_format => 'S',   # display as unsigned 'shorts'
  start_position => 100,  # start at this offset ...      end_position =>
148     # ... and end at this offset );

DESCRIPTION
===========

   `Data::Hexdumper' provides a simple way to format and display arbitary
binary data in a way similar to how some debuggers do for lesser languages.
It gives the programmer a considerable degree of flexibility in how the
data is formatted, with sensible defaults.  It is envisaged that it will
primarily be of use for those wrestling alligators in the swamp of binary
file formats, which is why it was written in the first place.

   `Data::Hexdumper' provides the following subroutine:

Hexdump
     Does everything :-)  Takes a hash of parameters, one of which is
     mandatory, the rest having sensible defaults if not specified.
     Available parameters are:

    data
          A scalar containing the binary data we're interested in.  This is
          mandatory.

    start_position
          An integer telling us where in data to start dumping.  Defaults
          to the beginning of data.

    end_position
          An integer telling us where in data to stop dumping.  Defaults
          to the end of data.

    number_format
          A character specifying how to format the data.  This tells us
          whether the data consists of bytes, shorts (16-bit values),
          longs (32-bit values), and whether they are big- or
          little-endian.  The permissible values are C, S, n, v, L, N, and
          V, having exactly the same meanings as they do in unpack.  It
          defaults to 'C'.

SEE ALSO
========

   *Note Data/Dumper: Data/Dumper,

   *Note Data/HexDump: Data/HexDump, if your needs are simple

   perldoc -f unpack

   perldoc -f pack

BUGS
====

   If displaying data in 'short' or 'long' formats, the last element
displayed may be screwed up if it does not end on the boundary of a short
or a long - eg, if you try to display 39 bytes as longs.

AUTHOR
======

   David Cantrell (david@cantrell.org.uk).

HISTORY
=======

Version 0.01
     Original version.


File: pm.info,  Node: Data/JavaScript,  Next: Data/JavaScript/LiteObject,  Prev: Data/Hexdumper,  Up: Module List

Perl extension for dumping structures into JavaScript code
**********************************************************

NAME
====

   Data::JavaScript - Perl extension for dumping structures into JavaScript
code

SYNOPSIS
========

     use Data::JavaScript;
     
     @code = jsdump($array_ref, 'my_array');
     $code = jsdump($hash_ref, 'my_object');
     $code = hjsdump($array_ref B<or> $hash_ref, 'my_stuff');

DESCRIPTION
===========

   This module is aimed mainly for CGI programming, when a perl script
generates a page with client side JavaScript code that needs access to
structures created on the server.

   It works by creating one line of JavaScript code per datum. Therefore,
structures cannot be created anonymously and needed to be assigned to
variables. This enables dumping big structures.

   The first arguement is a hashref or arrayref. Structures can be nested,
circular referrencing is supported EXPERIMENTALLY only.  The second
argument is the name of JavaScript object to create.

   hsdump also dumps HTML tags to embed the scriplet inside an HTML page.

   When called in array context, the functions return an array of code
lines. When called in scalar context, it returns one chunk of lines
delimited by line fields.

AUTHOR
======

   Ariel Brosh, schop@cpan.org. Inspired by WDDX.pm JavaScript support.

SEE ALSO
========

   perl(1), *Note WDDX: WDDX,.


File: pm.info,  Node: Data/JavaScript/LiteObject,  Next: Data/Locations,  Prev: Data/JavaScript,  Up: Module List

Perl package to provide lightweight data dumping
************************************************

NAME
====

   Data::JavaScript::LiteObject - Perl package to provide lightweight data
dumping

SYNOPSIS
========

     use Data::JavaScript:LiteObject;

     jsodump("user", \%users);

DESCRIPTION
===========

   This module was inspired by *Note Data/JavaScript: Data/JavaScript,,
which while incredibly versatile, seems rather brute force and inelegant
for certain forms of data. Specifically a series of objects of the same
class, which it seems is a likely use for this kind of feature. So this
module was created to provide a lightweight means of producing
configurable, clean and compact output.

   *LiteObject* is used to format and output an array or hash of objects;
that is hash references. The referenced hashes may contain values that are
scalars, or references to arrays containing scalars.

   *LiteObject* contains one function; jsodump; which takes a list of named
parameters. Two of which are required, the rest being optional.

Required parameters
-------------------

`protoName'
     The name to be used for the prototype object function.

`dataRef'
     A reference to an array or hash of hashes to dump.

Optional parameters
-------------------

attributes
     A reference to an array containing a list of the object attributes
     (hash keys). This is useful if every object does not necessarily
     posses a value for each attributes; exists fails. e.g.

          %A = (a=>1, z=>26);
          %B = (b=>2, y=>25);

          jsodump("example", \(%A, %B), \('a', 'b', 'y', 'z'));

     This could also be used to explicitly prevent certain data from being
     dumped.

explode
     The default; false; produces output with one object per line.  If
     true, the output is one *attribute* per line.

`lineIN'
     If true, output is numbered every 5 lines. The value provided should
     be the number of lines printed before this output.  For example if a
     CGI script included:

          C<print q(<html>
          	    <head>
          	    <title>Pthbb!!</title>
          	    <script language=javascript>);>
          jsdump(protoName=>"object", dataRef=>\@objects, lineIN=>4);

     The client might see:

          <html>
          <head>
          <title>Pthbb!!</title>
          <script language=javascript>
          // 5
          function object (x, y, z) {
                  this.x = x; this.y = y; this.z = z; }
          object0 = new object(1, 0, 0 );
          object1 = new object(0, 1, 0 );
          // 10
          object2 = new object(0, 0, 1 );

     making it easier to read and/or debug.

`lineOUT'
     A scalar reference. jsodump will set it's value to the number of the
     last line of numbered output produced when lineIN is specified. This
     way you may pass the scalar to a subsequent call to jsdump as the
     value of lineIn for continuous numbering.  For example:

          C<jsdump(protoName=>"object", dataRef=>\@objects, lineIN=>4, lineOUT=>\$.);>

          ...

          C<jsdump(protoName=>"object", dataRef=>\@objects, lineIN=>$.);>

`listObjects'
     If true, the parameters value is used as the name of an array to be
     output contaning a list of all the objects dumped. This way, your
     client side code need not know as much about the data, but simply to
     traverse an array of your choosing.

     For example:

          C<jsdump(protoName=>"object", dataRef=>\@objects, listObjects=>"objects");>

     would return

          objects = new Array('object0', 'object1', 'object2');

CAVEATS
=======

   All of the objects in a given hash or array reference should contain
the same keys. Explicit undefined values should be used for instances of
an object that do not posess a certain value.  For example:

     C<%hash0 = (alpha=>undef, beta=>1);>
     C<%hash1 = (beta=>1);>

   %hash0 is safe, since exists($hash0{alpha}) is true.  However
exists($hash1{alpha}) is false, and %hash1 would cause problems.

   Deep structures are not dumped. That is anything beyond a scalar or a
scalar within an Array as an attribute value. It is not entirely clear
that it's necessary, but if you require it `SEE ALSO' in this node

BUGS
====

   Nothing that am I aware of.

SEE ALSO
========

   *Note Data/JavaScript: Data/JavaScript,

AUTHOR
======

   Jerrad Pierce *belg4mit@mit.edu*, *webmaster@pthbb.org*.
`http://pthbb.org/'


File: pm.info,  Node: Data/Locations,  Next: Data/MagicTie,  Prev: Data/JavaScript/LiteObject,  Up: Module List

magic insertion points in your data
***********************************

NAME
====

   Data::Locations - magic insertion points in your data

PREFACE
=======

   Did you already encounter the problem that you had to produce some data
in a particular order, but that some piece of the data was still
unavailable at the point in the sequence where it belonged and where it
should have been produced?

   Did you also have to resort to cumbersome and tedious measures such as
storing the first and the last part of your data separately, then
producing the missing middle part, and finally putting it all together?

   In this simple case, involving only one deferred insertion, you might
still put up with this solution.

   But if there is more than one deferred insertion, requiring the handling
of many fragments of data, you will probably get annoyed and frustrated.

   You might even have to struggle with limitations of the file system of
your operating system, or handling so many files might considerably slow
down your application due to excessive file input/output.

   And if you don't know exactly beforehand how many deferred insertions
there will be (if this depends dynamically on the data being processed),
and/or if the pieces of data you need to insert need additional (nested)
insertions themselves, things will get really tricky, messy and
troublesome.

   In such a case you might wonder if there wasn't an elegant solution to
this problem.

   This is where the "`Data::Locations'" module comes in: It handles such
insertion points automatically for you, no matter how many and how deeply
nested, purely in memory, requiring no (inherently slower) file
input/output operations.

   (The underlying operating system will automatically take care if the
amount of data becomes too large to be handled fully in memory, though, by
swapping out unneeded parts.)

   Moreover, it also allows you to insert the same fragment of data into
SEVERAL different places.

   This increases space efficiency because the same data is stored in
memory only once, but used multiple times.

   Potential infinite recursion loops are detected automatically and
refused.

   In order to better understand the underlying concept, think of
"`Data::Locations'" as virtual files with almost random access: You can
write data to them, you can say "reserve some space here which I will fill
in later", and continue writing data.

   And you can of course also read from these virtual files, at any time,
in order to see the data that a given virtual file currently contains.

   When you are finished filling in all the different parts of your virtual
file, you can write out its contents in flattened form to a physical, real
file this time, or process it otherwise (purely in memory, if you wish).

   You can also think of "`Data::Locations'" as bubbles and bubbles inside
of other bubbles. You can inflate these bubbles in any arbitrary order you
like through a straw (i.e., the bubble's object reference).

   Note that this module handles your data completely transparently, which
means that you can use it equally well for text AND binary data.

   You might also be interested in knowing that this module and its concept
have already been heavily used in the automatic code generation of large
software projects.

SYNOPSIS
========

     use Data::Locations;

     new
         $toplocation = Data::Locations->new();
         $toplocation = Data::Locations->new($filename);
         $sublocation = $location->new();
         $sublocation = $location->new($filename);

     filename
         $location->filename($filename);
         $filename = $location->filename();
         $oldfilename = $location->filename($newfilename);

     toplevel
         $flag = $location->toplevel();

     print
         $location->print(@items);
         print $location @items;

     printf
         $location->printf($format, @items);
         printf $location $format, @items;

     println
         $location->println(@items);

     read
         $item = $location->read();
         $item = <$location>;
         @list = $location->read();
         @list = <$location>;

     reset
         $location->reset();

     traverse
         $location->traverse(\&callback_function);

     dump
         $ok = $location->dump();
         $ok = $location->dump($filename);

     delete
         $location->delete();

     tie
         $location->tie('FILEHANDLE');
         $location->tie(*FILEHANDLE);
         $location->tie(\*FILEHANDLE);
         $location->tie(*{FILEHANDLE});
         $location->tie(\*{FILEHANDLE});
         $location->tie($filehandle);
         tie(  *FILEHANDLE,  "Data::Locations", $location);
         tie(*{$filehandle}, "Data::Locations", $location);

     tied
         $location = tied   *FILEHANDLE;
         $location = tied *{$filehandle};

     untie
         untie   *FILEHANDLE;
         untie *{$filehandle};

     select
         $filehandle = select();
         select($location);
         $oldfilehandle = select($newlocation);

IMPORTANT NOTES
===============

  1. Although "`Data::Locations'" behave like normal Perl file handles in
     most circumstances, opening a location with "open()" should be
     avoided: The corresponding file or pipe will actually be created, but
     subsequently data will nevertheless be sent to (and read from) the
     given location instead.

     There is also no need to switch from read to write mode (or
     vice-versa), since locations are ALWAYS open BOTH for reading AND
     writing.

     If you want to rewind a location to start reading at the beginning
     again (usually achieved by closing and re-opening a file), use the
     method "reset()" instead (see farther below for a description).

     Likewise, closing a location with "close()" will have no other effect
     than to produce a warning message (under Perl 5.005 and if the "-w"
     switch is set) saying "operation ignored", and should therefore be
     avoided, too.

  2. "`Data::Locations'" are rather delicate objects; they are valid Perl
     file handles AS WELL AS valid Perl objects AT THE SAME TIME.

     As a consequence, *YOU CANNOT INHERIT* from the "`Data::Locations'"
     class, i.e., it is NOT possible to create a derived class or subclass
     of the "`Data::Locations'" class!

     Trying to do so will cause many severe malfunctions, most of which
     will not be apparent immediately.

     Chances are also great that by adding new attributes to a
     "`Data::Locations'" object you will clobber its (quite tricky) data
     structure.

     Therefore, use embedding and delegation instead, rather than
     inheritance, as shown below:

          package My::Class;
          use Data::Locations;
          use Carp;

          sub new
          {
              my($self) = shift;
              my($location,$object);
              if (ref($self)) { $location = $self->{'delegate'}->new(); }
              else            { $location =     Data::Locations->new(); }
              $object =
                  {
                      'delegate'   => $location,
                      'attribute1' => $whatever,  ##  add your own
                      'attribute2' => $whatelse
                  };
              bless($object, ref($self) || $self || __PACKAGE__);
          }

          sub AUTOLOAD
          {
              my($i,@args);
              $AUTOLOAD =~ s/^.*:://;
              return if ($AUTOLOAD eq 'DESTROY');
              $AUTOLOAD = 'Data::Locations::' . $AUTOLOAD;
              if (defined &$AUTOLOAD)
              {
                  for ( $i = 0; $i < @_; $i++ )
                  {
                      if (ref($_[$i]) eq __PACKAGE__)
                      {
                          $args[$i] = $_[$i]->{'delegate'};
                      }
                      else
                      {
                          $args[$i] = $_[$i];
                      }
                  }
                  @_ = @args;
                  goto &$AUTOLOAD;
              }
              else
              {
                  croak("$AUTOLOAD(): no such method");
              }
          }

          1;

     Note that using this scheme, all methods available for
     "`Data::Locations'" objects are also (automatically and directly)
     available for "`My::Class'" objects, i.e.,

          use My::Class;
          $obj = My::Class->new();
          $obj->filename('test.txt');
          $obj->print("This is ");
          $sub = $obj->new();
          $obj->print("information.");
          @items = $obj->read();
          print "<", join('|', @items), ">\n";
          $sub->print("an additional piece of ");
          $obj->reset();
          @items = $obj->read();
          print "<", join('|', @items), ">\n";
          $obj->dump();

     will work as expected (unless you redefine these methods in
     "`My::Class'").

     Moreover, with this scheme, you are free to add new methods and/or
     attributes as you please.

     The class "`My::Class'" can also be subclassed without any
     restrictions.

     However, "`My::Class'" objects are NOT valid Perl file handles;
     therefore, they cannot be used as such in combination with Perl's
     built-in operators for file access.


DESCRIPTION
===========

   * `use Data::Locations;'

     Enables the use of locations in your program.

   * `$toplocation = Data::Locations->new();'

     The CLASS METHOD "new()" creates a new top-level location.

     A "top-level" location is a location which isn't embedded (nested) in
     any other location.

     Note that CLASS METHODS are invoked using the NAME of their respective
     class, i.e., "`Data::Locations'" in this case, in contrast to OBJECT
     METHODS which are invoked using an OBJECT REFERENCE such as returned
     by the class's object constructor method (which "new()" happens to
     be).

     Any location that you intend to dump to a file later on in your
     program needs to have a filename associated with it, which you can
     either specify using the "new()" method (where you can optionally
     supply a filename, as shown below), or by setting this filename using
     the method "filename()" (see further below), or by specifying an
     explicit filename when invoking the "dump()" method itself (see also
     further below).

   * `$toplocation = Data::Locations->new($filename);'

     This variant of the CLASS METHOD "new()" creates a new top-level
     location (where "top-level" means a location which isn't embedded in
     any other location) and assigns a default filename to it.

     Note that this filename is simply passed through to the Perl "open()"
     function later on (which is called internally when you dump your
     locations to a file), which means that any legal Perl filename may be
     used such as ">-" (for writing to STDOUT) and "| more", to give you
     just two of the more exotic examples.

     See the section on "open()" in `perlfunc(1)' in this node for more
     details.

   * `$sublocation = $location->new();'

     The OBJECT METHOD "new()" creates a new location which is embedded in
     the given location "`$location'" at the current position (defined by
     what has been printed to the embedding location till this moment).

     Such a nested location usually does not need a filename associated
     with it (because it will be dumped to the same file as the location
     in which it is embedded anyway), unless you want to additionally dump
     this location to a file of its own.

     In the latter case use the variant of the "new()" method shown
     immediately below, or the method "filename()" (see below) to set this
     filename, or call the method "dump()" (described further below) with
     an appropriate filename argument.

   * `$sublocation = $location->new($filename);'

     This variant of the OBJECT METHOD "new()" creates a new location
     which is embedded in the given location "`$location'" at the current
     position (defined by what has been printed to the embedding location
     till this moment) and assigns a default filename to it.

     See the section on "open()" in `perlfunc(1)' in this node for details
     about the exact syntax of Perl filenames (this includes opening pipes
     to other programs as a very interesting and useful application, for
     instance).

   * `$oldfilename = $location->filename($newfilename);'

     If the optional parameter is given, this method stores its argument as
     the default filename along with the given location.

     This filename also serves as an auto-dump flag. If it is set to a
     non-empty string, auto-dumping (i.e., an automatic call of the
     "dump()" method) occurs when your last reference of the location in
     question goes out of scope, or at shutdown time of your script
     (whichever comes first). See also the description of the "dump()"
     method further below for more details.

     When a location is auto-dumped, its associated filename is used as the
     filename of the file into which the location's contents are dumped.

     This method returns the filename that was associated with the given
     location before this method call (i.e., the filename given to the
     "new()" method or to a previous call of this method), or the empty
     string if there was no filename associated with the given location.

   * `$flag = $location->toplevel();'

     Use this method to check wether the given location is a "top-level"
     location, i.e., if the given location is NOT embedded in any other
     location.

     Note that locations created by the CLASS METHOD "new()" all start
     their life-cycle as top-level locations, whereas locations which are
     embedded in some other location by using the OBJECT METHOD "new()"
     (or the method "print()"; see further below for details) are NOT, by
     definition, top-level locations.

     Whenever a top-level location is embedded in another location (using
     the method "print()" - see further below for more details), it
     automatically loses its "top-level" status.

     When you throw away the contents of a location (using the method
     "delete()" - see further below for details), however, the locations
     that may have been embedded in the deleted location can become
     "orphans" which have no "parents" anymore, i.e., they may not be
     embedded in any other location anymore. These "orphan" locations will
     automatically become "top-level" locations.

     The method returns "true" ("1") if the given location is a top-level
     location, and "false" ("0") otherwise.

   * `$location->print(@items);'

     This method prints the given list of arguments to the indicated
     location, i.e., appends the given items to the given location.

     IMPORTANT FEATURE:

     Note that you can EMBED any given location IN MORE THAN ONE
     surrounding location using this method!

     Simply use a statement similar to this one:

          $location->print($sublocation);

     This embeds location "`$sublocation'" in location "`$location'" at
     the current position (defined by what has been printed to location
     "`$location'" till this moment).

     (Note that the name "`$sublocation'" above only refers to the fact
     that this location is going to be embedded in the location
     "`$location'".  "`$sublocation'" may actually be ANY location you
     like, even a top-level location. Note though that a top-level
     location will automatically lose its "top-level" status by doing so.)

     This is especially useful if you are generating data once in your
     program which you need to include at several places in your output.

     This saves a lot of memory because only a reference of the embedded
     location is stored in every embedding location, instead of all the
     data, which is stored in memory only once.

     Note that other references than "Data::Locations" object references
     are illegal, trying to "print" such a reference to a location will
     result in a warning message (if the "-w" switch is set) and the
     reference in question will simply be ignored.

     Note also that potential infinite recursions (which would occur when a
     given location contained itself, directly or indirectly) are detected
     automatically and refused (with an appropriate error message and
     program abortion).

     Because of the necessity for this check, it is more efficient to embed
     locations using the object method "new()", where possible, rather
     than with this mechanism, because embedding an empty new location (as
     with "new()") is always possible without checking.

     Remember that in order to minimize the number of "print()" method
     calls in your program (remember that lazyness is a programmer's
     virtue! `;-)') you can always use the "here-document" syntax:

          $location->print(<<"VERBATIM");
          Article: $article
            Price: $price
            Stock: $stock
          VERBATIM

     Remember also that the type of quotes (single/double) around the
     terminating string ("VERBATIM" in this example) determines wether
     variables inside the given text will be interpolated or not!  (See
     `perldata(1)' in this node for more details.)

   * `print $location @items;'

     Note that you can also use Perl's built-in operator "print" to print
     data to a given location.

   * `$location->printf($format, @items);'

     This method is an analogue of the Perl (and C library) function
     "printf()".

     See the section on "printf()" in `perlfunc(1)' in this node and
     `printf(3)' in this node (or `sprintf(3)' in this node) on your
     system for a description.

   * `printf $location $format, @items;'

     Note that you can also use Perl's built-in operator "printf" to print
     data to a given location.

   * `$location->println(@items);'

     This is (in principle) the same method as the "print()" method
     described further above, except that it always appends a "newline"
     character ("\n") to the list of items being printed to the given
     location.

     Note that this newline character is NOT appended to (i.e.,
     concatenated with) the last item of the given list of items, but that
     it is rather stored as an item of its own.

     This is mainly because the last item of the given list could be a
     reference (of another location), and also to make sure that the data
     (which could be binary data) being stored in the given location is
     not altered (i.e., falsified) in any way.

     This also allows the given list of items to be empty (in that case,
     there wouldn't be a "last item" anyway to which the newline character
     could be appended).

   * `$item = $location->read();'

     In "scalar" context, the method "read()" returns the next item of
     data from the given location.

     If that item happens to have the value "undef", this method returns
     the empty string instead.

     If you have never read from this particular location before, "read()"
     will automatically start reading at the beginning of the given
     location.

     Otherwise each call of "read()" will return successive items from the
     given location, thereby traversing the given location recursively
     through all embedded locations (which it may or may not contain), thus
     returning the contents of the given location (and any locations
     embedded therein) in a "flattened" way.

     To start reading at the beginning of the given location again, invoke
     the method "reset()" (see a little further below for its description)
     on that location.

     The method returns "undef" when there is no more data to read.

     Calling "read()" again thereafter will simply continue to return
     "undef", even if you print some more data to the given location in
     the meantime.

     However, if you have read the last item from the given location, but
     you haven't got the "undef" return value yet, it is possible to print
     more data to the location in question and to subsequently continue to
     read this new data.

     Remember to use "reset()" if you want to read data from the beginning
     of the given location again.

     Finally, note that you can read from two (or any number of) different
     locations at the same time, even if any of them is embedded (directly
     or indirectly) in any other of the locations you are currently reading
     from, without any interference.

     This is because the state information associated with each "read()"
     operation is stored along with the (given) location for which the
     "read()" method has been called, and NOT with the locations the
     "read()" visits during its recursive descent.

   * `$item = <$location>;'

     Note that you can also use Perl's diamond operator syntax ("`<>'") in
     order to read data from the given location.

     BEWARE that unlike reading from a file, reading from a location in
     this manner will return the items that have been stored in the given
     location in EXACTLY the same way as they have been written previously
     to that location, i.e., the data is NOT read back line by line, with
     "\n" as the line separator, but item by item, whatever these items
     are!

     (Note that you can also store binary data in locations, which will
     likewise be read back in exactly the same way as it has been stored
     previously.)

   * `@list = $location->read();'

     In "array" or "list" context, the method "read()" returns the rest of
     the contents of the given location, starting where the last "read()"
     left off, or from the beginning of the given location if you never
     read from this particular location before or if you called the method
     "reset()" (see a little further below for its description) for this
     location just before calling "read()".

     The method returns a single (possibly very long!) list containing all
     the items of data the given location and all of its embedded
     locations (if any) contain - in other words, the data contained in
     all these nested locations is returned in a "flattened" way (in
     "infix" order, for the mathematically inclined).

     If any of the items in the list happens to have the value "undef", it
     is replaced by an empty string.

     The method returns an empty list if the given location is empty or if
     a previous "read()" read past the end of the data in the given
     location.

     Remember to use "reset()" whenever you want to be sure to read the
     contents of the given location from the very beginning!

     For an explanation of "scalar" versus "array" or "list" context, see
     the section on "Context" in `perldata(1)' in this node.

   * `@list = <$location>;'

     Note that you can also use Perl's diamond operator syntax ("`<>'") in
     order to read data from the given location.

     BEWARE that unlike reading from a file, reading from a location in
     this manner will return the list of items that have been stored in
     the given location in EXACTLY the same way as they have been written
     previously to that location, i.e., the data is NOT read back as a
     list of lines, with "\n" as the line separator, but as a list of
     items, whatever these items are!

     (Note that you can also store binary data in locations, which will
     likewise be read back in exactly the same way as it has been stored
     previously.)

   * `$location->reset();'

     The method "reset()" deletes the state information associated with
     the given location which is used by the "read()" method in order to
     determine the next item of data to be returned.

     After using "reset()" on a given location, any subsequent "read()" on
     the same location will start reading at the beginning of that
     location.

     This method has no other (side) effects whatsoever.

     The method does nothing if there is no state information associated
     with the given location, i.e., if the location has never been accessed
     before using the "read()" method or if "reset()" has already been
     called previously.

   * `$location->traverse(\&callback_function);'

     The method "traverse()" performs a recursive descent on the given
     location just as the methods "read()" and "dump()" do internally, but
     instead of immediately returning the items of data contained in the
     location or printing them to a file, this method calls the callback
     function you specify as a parameter once for each item stored in the
     location.

     Expect one parameter handed over to your callback function which
     consists of the next item of data contained in the given location (or
     the locations embedded therein).

     Note that unlike the "read()" method, items returned by this method
     which happen to have the value "undef" are NOT replaced by the empty
     string, i.e., the parameter your callback function receives might be
     undefined. You should therefore take appropriate measures in your
     callback function to handle this special case.

     Moreover, since callback functions can do a lot of unwanted things,
     use this method with precaution!

     Please refer to the "examples" section at the bottom of this document
     for an example of how to use this method.

     Using the method "traverse()" is actually an alternate way of reading
     back the contents of a given location (besides using the method
     "read()") completely in memory (i.e., without writing the contents of
     the given location to a file and reading that file back in).

     Note that the method "traverse()" is completely independent from the
     method "read()" and from the state information associated with the
     "read()" method (the one which can be reset to point to the beginning
     of the location using the method "reset()").

     This means that you can "traverse()" and "read()" (and "reset()") the
     same location at the same time without any interference.

   * `$ok = $location->dump();'

     The method "dump()" (without parameters) dumps the contents of the
     given location to its associated default file (whose filename must
     have been stored along with the given location previously using the
     method "new()" or "filename()").

     Note that a warning message will be printed (if the "-w" switch is
     set) if the location happens to lack a default filename and that the
     location will simply not be dumped to a file in that case. Moreover,
     the method returns "false" ("0") to indicate the failure.

     Should any other problem arise while attempting to dump the given
     location (for instance an invalid filename or an error while trying
     to open or close the specified file), a corresponding warning message
     will be printed to the screen (provided that the "-w" switch is set)
     and the method will also return "false" ("0").

     The method returns "true" ("1") if and only if the given location has
     been successfully written to its respective file.

     Note that a ">" is prepended to the default filename just before
     opening the file if the default filename does not begin with ">", "|"
     or "+" (leading white space is ignored).

     This does NOT change the filename which is stored along with the given
     location, however.

     Finally, note that this method does not affect the contents of the
     location being dumped.

     If you want to delete the contents of the given location once they
     have been dumped, call the method "delete()" (explained further below)
     thereafter.

     If you want to dump and immediately afterwards destroy a location, you
     don't need to call the method "dump()" explicitly. It suffices to
     store a filename along with the location in question using the method
     "new()" or "filename()" and then to make sure that all references to
     this location are destroyed (this happens for instance whenever the
     last "my" variable containing a reference to the location in question
     goes out of scope - provided there are no global variables containing
     references to the location in question).

     This will automatically cause the location to be dumped (by calling
     the "dump()" method internally) and then to be destroyed. (This
     feature is called "auto-dump".)

     Auto-dumping also occurs at shutdown time of your Perl script or
     program: All locations that have a non-empty filename associated with
     them will automatically be dumped (by calling the "dump()" method
     internally) before the global garbage collection (i.e., the
     destruction of all data variables) takes place.

     In order to prevent auto-dumping, just make sure that there is no
     filename associated with the location in question at the time when
     its last reference goes out of scope or at shutdown time.

     You can ensure this by calling the "filename()" method with an empty
     string ("") as argument.

   * `$ok = $location->dump($filename);'

     The method "dump()" (with a filename argument) in principle does
     exactly the same as the variant without arguments described
     immediately above, except that it temporarily overrides the default
     filename associated with the given location and that it uses the
     given filename instead.

     Note that the location's associated filename is just being temporarily
     overridden, BUT NOT CHANGED.

     I.e., if you call the method "dump()" again later without a filename
     argument, the filename stored along with the given location will be
     used, and not the filename specified here.

     Should any problem arise while attempting to dump the given location
     (for instance if the given filename is invalid or empty or if Perl is
     unable to open or close the specified file), a corresponding warning
     message will be printed to the screen (provided that the "-w" switch
     is set) and the method returns "false" ("0").

     The method returns "true" ("1") if and only if the given location has
     been successfully written to the specified file.

     (Note that if the given filename is empty or contains only white
     space, the method does NOT fall back to the filename previously
     stored along with the given location, because doing so could
     overwrite valuable data.)

     Note also that a ">" is prepended to the given filename if it does not
     begin with ">", "|" or "+" (leading white space is ignored).

     Finally, note that this method does not affect the contents of the
     location being dumped.

     If you want to delete the given location once it has been dumped, you
     need to call the method "delete()" (explained below) explicitly.

   * `$location->delete();'

     The method "delete()" deletes the CONTENTS of the given location -
     the location CONTINUES TO EXIST and REMAINS EMBEDDED where it was!

     The associated filename stored along with the given location is also
     NOT AFFECTED by this method.

     BEWARE that any locations which were previously embedded in the given
     location might go out of scope by invoking this method!

     Note that in order to actually DESTROY a location altogether it
     suffices to simply let the last reference to the location in question
     go out of scope, or to set the variable containing the last reference
     to a new value (e.g. `$ref = 0;').

   * `$location->tie('FILEHANDLE');'

   * `$location->tie(*FILEHANDLE);'

   * `$location->tie(\*FILEHANDLE);'

   * `$location->tie(*{FILEHANDLE});'

   * `$location->tie(\*{FILEHANDLE});'

     Although locations behave like file handles themselves, i.e., even
     though they allow you to use Perl's built-in operators "print",
     "printf" and the diamond operator "`<>'" in order to write data to and
     read data from them, it is sometimes desirable to be able to redirect
     the output which is sent to other file handles (such as STDOUT and
     STDERR, for example) to some location instead (rather than the
     screen, for instance).

     It may also be useful to be able to read data from a location via some
     other file handle (such as STDIN, for example, which allows you to
     "remote-control" a program which reads commands from standard input
     by redirecting STDIN and then spoon-feeding the program as desired).

     (Note that on the Windows NT/95 platform, tying is probably the only
     way of redirecting output sent to STDERR, since the command shell
     won't allow you to do so!)

     The method "tie()" (be careful not to confuse the METHOD "tie()" and
     the Perl built-in OPERATOR "tie"!) provides an easy way for doing
     this.

     Simply invoke the method "tie()" for the location which should be
     "tied" to a file handle, and provide either the name, a typeglob or a
     typeglob reference of the file handle in question as the (only)
     parameter to this method.

     After that, printing data to this file handle will actually send this
     data to its associated ("tied") location, and reading from this file
     handle will actually read the data from the tied location instead.

     Note that you don't need to explicitly "open()" or "close()" such a
     tied file handle in order to be able to access its associated location
     (regardless wether you want to read from or write to the location or
     both), even if this file handle has never been explicitly (or
     implicitly) opened (or even used) before.

     The physical file or terminal the tied file handle may have been
     connected to previously is simply put on hold, i.e., it is NOT written
     to or read from anymore, until you "untie" the connection between the
     file handle and the location (see further below for more details
     about "untie").

     Note also that if you do not "untie" the file handle before your
     program ends, Perl will try to close it for you, which under Perl
     5.005 will lead to a warning message (provided that the "-w" switch
     is set) saying that the attempted "close()" operation was ignored.
     This is because under Perl 5.005, a "close()" on a tied file handle
     is forwarded to the associated (i.e., tied) object instead.

     Under Perl 5.004, the behaviour of "close()" is different: When used
     on a location it is simply ignored (without any warning message), and
     a close on a tied file handle will close the underlying file or pipe
     (if there is one).

     Finally, note that you don't need to qualify the built-in file handles
     STDIN, STDOUT and STDERR, which are enforced by Perl to be in package
     "main", and file handles belonging to your own package, but that it
     causes no harm if you do (provided that you supply the correct
     package name).

     The only file handles you need to qualify are custom file handles
     belonging to packages other than the one in which the method "tie()"
     is called.

     Some examples:

          $location->tie('STDOUT');
          $location->tie('MYFILE');
          $location->tie('My::Class::FILE');
          $location->tie(*STDERR);
          $location->tie(\*main::TEMP);

     Please also refer to the example given at the bottom of this document
     for more details about tying file handles to locations (especially
     for STDERR).

     See `perlfunc(1)' in this node and `perltie(1)' in this node for more
     details about "tying" in general.

   * `$location->tie($filehandle);'

     Note that you can also tie file handles to locations which have been
     created by using the standard Perl modules "FileHandle" and
     "IO::File":

          use FileHandle;
          $fh = FileHandle->new();
          $location->tie($fh);

          use IO::File;
          $fh = IO::File->new();
          $location->tie($fh);

   * `tie(*FILEHANDLE, "Data::Locations", $location);'

   * `tie(*{$filehandle}, "Data::Locations", $location);'

     Finally, note that you are not forced to use the METHOD "tie()", and
     that you can of course also use the OPERATOR "tie" directly, as shown
     in the two examples above.

   * `$location = tied *FILEHANDLE;'

   * `$location = tied *{$filehandle};'

     The Perl operator "tied" can be used to get back a reference to the
     object the given file handle is "tied" to.

     This can be used to invoke methods for this object, as follows:

          (tied   *FILEHANDLE)->method();
          (tied *{$filehandle})->method();

     Note that "`tied *{$location}'" is identical with "`$location'"
     itself.

     See `perlfunc(1)' in this node and `perltie(1)' in this node for more
     details.

   * `untie *FILEHANDLE;'

   * `untie *{$filehandle};'

     The Perl operator "untie" is used to "cut" the magic connection
     between a file handle and its associated object.

     Note that a warning message such as

          untie attempted while 1 inner references still exist

     will be issued (provided the "-w" switch is set) whenever you try to
     "untie" a file handle from a location.

     To get rid of this warning message, use the following approach:

          {
              local($^W) = 0;     ##  Temporarily disable the "-w" switch
              untie *FILEHANDLE;
          }

     (Note the surrounding braces which limit the effect of disabling the
     "-w" switch.)

     See `perlfunc(1)' in this node and `perltie(1)' in this node for more
     details.

   * `$filehandle = select();'

   * `select($location);'

   * `$oldfilehandle = select($newlocation);'

     Remember that you can define the default output file handle using
     Perl's built-in function "select()".

     "print" and "printf" statements without explicit file handle (note
     that "`println'" ALWAYS needs an explicit location where to send its
     output to!) always send their output to the currently selected default
     file handle (which is usually "STDOUT").

     "select()" always returns the current default file handle and allows
     you to define a new default file handle at the same time.

     By selecting a location as the default file handle, all subsequent
     "print" and "printf" statements (without explicit file handle) will
     send their output to that location:

          select($location);
          print "Hello, World!\n";  ##  prints to "$location"

     See the section on "select()" in `perlfunc(1)' in this node for more
     details.

EXAMPLE #1
==========

     #!/sw/bin/perl -w

     use Data::Locations;

     use strict;
     no strict "vars";

     $head = Data::Locations->new();  ##  E.g. for interface definitions
     $body = Data::Locations->new();  ##  E.g. for implementation

     $head->filename("example.h");
     $body->filename("example.c");

     $common = $head->new();    ##  Embed a new location in "$head"
     $body->print($common);     ##  Embed this same location in "$body"

     ##  Create some more locations...

     $copyright = Data::Locations->new();
     $includes  = Data::Locations->new();
     $prototype = Data::Locations->new();

     ##  ...and embed them in location "$common":

     $common->print($copyright,$includes,$prototype);

     ##  Note that the above is just to show you an alternate
     ##  (but less efficient) way! Normally you would use:
     ##
     ##      $copyright = $common->new();
     ##      $includes  = $common->new();
     ##      $prototype = $common->new();

     $head->println(";");  ##  The final ";" after a function prototype
     $body->println();     ##  Just a newline after a function header

     $body->println("{");
     $body->println('    printf("Hello, world!\n");');
     $body->println("}");

     $includes->print("#include <");
     $library = $includes->new();     ##  Nesting even deeper still...
     $includes->println(">");

     $prototype->print("void hello(void)");

     $copyright->println("/*");
     $copyright->println("    Copyright (c) 1997, 1998, 1999 by Steffen Beyer.");
     $copyright->println("    All rights reserved.");
     $copyright->println("*/");

     $library->print("stdio.h");

     $copyright->filename("default.txt");

     $copyright->dump(">-");

     print "default filename = '", $copyright->filename(), "'\n";

     $copyright->filename("");

     __END__

   When executed, this example will print

     /*
         Copyright (c) 1997, 1998, 1999 by Steffen Beyer.
         All rights reserved.
     */
     default filename = 'default.txt'

   to the screen and create the following two files:

     ::::::::::::::
     example.c
     ::::::::::::::
     /*
         Copyright (c) 1997, 1998, 1999 by Steffen Beyer.
         All rights reserved.
     */
     #include <stdio.h>
     void hello(void)
     {
         printf("Hello, world!\n");
     }

     ::::::::::::::
     example.h
     ::::::::::::::
     /*
         Copyright (c) 1997, 1998, 1999 by Steffen Beyer.
         All rights reserved.
     */
     #include <stdio.h>
     void hello(void);

EXAMPLE #2
==========

     #!/sw/bin/perl -w

     use Data::Locations;

     use strict;
     no strict "vars";

     $html = Data::Locations->new("example.html");

     $html->println("<HTML>");
     $head = $html->new();
     $body = $html->new();
     $html->println("</HTML>");

     $head->println("<HEAD>");
     $tohead = $head->new();
     $head->println("</HEAD>");

     $body->println("<BODY>");
     $tobody = $body->new();
     $body->println("</BODY>");

     $tohead->print("<TITLE>");
     $title = $tohead->new();
     $tohead->println("</TITLE>");

     $tohead->print('<META NAME="description" CONTENT="');
     $description = $tohead->new();
     $tohead->println('">');

     $tohead->print('<META NAME="keywords" CONTENT="');
     $keywords = $tohead->new();
     $tohead->println('">');

     $tobody->println("<CENTER>");

     $tobody->print("<H1>");
     $tobody->print($title);      ##  Re-using this location!!
     $tobody->println("</H1>");

     $contents = $tobody->new();

     $tobody->println("</CENTER>");

     $title->print("'Data::Locations' Example HTML-Page");

     $description->println("Example for generating HTML pages");
     $description->print("using 'Data::Locations'");

     $keywords->print("locations, magic, insertion points,\n");
     $keywords->print("nested, recursive");

     $contents->println("This page was generated using the");
     $contents->println("<P>");
     $contents->println("&quot;<B>Data::Locations</B>&quot;");
     $contents->println("<P>");
     $contents->println("module for Perl.");

     __END__

   When executed, this example will produce the following file
("example.html"):

     <HTML>
     <HEAD>
     <TITLE>'Data::Locations' Example HTML-Page</TITLE>
     <META NAME="description" CONTENT="Example for generating HTML pages
     using 'Data::Locations'">
     <META NAME="keywords" CONTENT="locations, magic, insertion points,
     nested, recursive">
     </HEAD>
     <BODY>
     <CENTER>
     <H1>'Data::Locations' Example HTML-Page</H1>
     This page was generated using the
     <P>
     &quot;<B>Data::Locations</B>&quot;
     <P>
     module for Perl.
     </CENTER>
     </BODY>
     </HTML>

EXAMPLE #3
==========

     #!/sw/bin/perl -w

     ##  Note that this example only works as described if the "-w" switch
     ##  is set!

     package Non::Sense;

     ##  (This is to demonstrate that this example works with ANY package)

     use Data::Locations;
     use FileHandle;

     use strict;
     use vars qw($level0 $level1 $level2 $level3 $fh $fake);

     ##  Create the topmost location:

     $level0 = Data::Locations->new("level0.txt");

     print $level0 <<'VERBATIM';
     Printing first line to location 'level0' via OPERATOR 'print'.
     VERBATIM

     ##  Create an embedded location (nested 1 level deep):

     $level1 = $level0->new();

     $level0->print(<<'VERBATIM');
     Printing last line to location 'level0' via METHOD 'print'.
     VERBATIM

     ##  Now "tie" the embedded location to file handle STDOUT:

     $level1->tie('STDOUT');

     print "Printing to location 'level1' via STDOUT.\n";

     ##  Create another location (which will be embedded later):

     $level2 = Data::Locations->new();

     ##  Create a file handle ("IO::Handle" works equally well):

     $fh = FileHandle->new();

     ##  Now "tie" the location "$level2" to this file handle "$fh":

     $level2->tie($fh);

     ##  And select "$fh" as the default output file handle:

     select($fh);

     print "Printing to location 'level2' via default file handle '\$fh'.\n";

     ##  Embed location "$level2" in location "$level1":

     print $level1 $level2;

     ##  (Automatically removes "toplevel" status from location "$level2")

     print STDOUT "Printing to location 'level1' explicitly via STDOUT.\n";

     ##  Create a third embedded location (nested 3 levels deep):

     $level3 = $level2->new();

     ##  Restore STDOUT as the default output file handle:

     select(STDOUT);

     print $fh "Printing to location 'level2' via file handle '\$fh'.\n";

     ##  Trap all warnings:

     $SIG{__WARN__} = sub
     {
         print STDERR "WARNING intercepted:\n", @_, "End Of Warning.\n";
     };

     ##  Note that WITHOUT this trap, warnings would go to the system
     ##  standard error device DIRECTLY, WITHOUT passing through the
     ##  file handle STDERR!

     ##  Now "tie" location "$level3" to file handle STDERR:

     $level3->tie(*STDERR);

     ##  Provoke a warning message (don't forget the "-w" switch!):

     $fake = \$fh;
     $level3->print($fake);

     ##  Provoke another warning message (don't forget the "-w" switch!):

     $level3->dump();

     {
         ##  Silence warning that reference count of location is still > 0:

     local($^W) = 0;

     ##  And untie file handle STDOUT from location "$level1":

     untie *STDOUT;
       }

     print "Now STDOUT goes to the screen again.\n";

     ##  Read from location "$level3":

     while (<STDERR>)  ##  Copy warning messages to the screen:
     {
         if (/^.*?\bData::Locations::[a-z]+\(\):\s+(.+?)(?=\s+at\s|\n)/)
         {
             print "Warning: $1\n";
         }
     }

     while (<STDERR>) { print; }

     ##  (Prints nothing because location was already read past its end)

     ##  Reset the internal reading mark:

     (tied *{STDERR})->reset();

     ##  (You should usually use "$level3->reset();", though!)

     while (<STDERR>) { print; }

     ##  (Copies the contents of location "$level3" to the screen)

     ##  Write output file "level0.txt":

     __END__

   When running this example, the following text will be printed to the
screen (provided that you did use the "-w" switch):

     Now STDOUT goes to the screen again.
     Warning: REF reference ignored
     Warning: filename missing or empty
     WARNING intercepted:
     Data::Locations::print(): REF reference ignored at test.pl line 92
     End Of Warning.
     WARNING intercepted:
     Data::Locations::dump(): filename missing or empty at test.pl line 96
     End Of Warning.

   The example also produces an output file named "level0.txt" with the
following contents:

     Printing first line to location 'level0' via OPERATOR 'print'.
     Printing to location 'level1' via STDOUT.
     Printing to location 'level2' via default file handle '$fh'.
     WARNING intercepted:
     Data::Locations::print(): REF reference ignored at test.pl line 92
     End Of Warning.
     WARNING intercepted:
     Data::Locations::dump(): filename missing or empty at test.pl line 96
     End Of Warning.
     Printing to location 'level2' via file handle '$fh'.
     Printing to location 'level1' explicitly via STDOUT.
     Printing last line to location 'level0' via METHOD 'print'.

EXAMPLE #4
==========

     #!/sw/bin/perl -w

     use Data::Locations;

     use strict;
     no strict "vars";

     $loc = Data::Locations->new();

     print $loc "Thi";
     print $loc "s is an ex";
     print $loc "treme";
     print $loc "ly long and ted";
     print $loc "ious line o";
     print $loc "f text con";
     print $loc "taining on";
     print $loc "ly meaning";
     print $loc "less gibberish.";

     $string = '';

     $loc->traverse( sub { $string .= $_[0]; } );

     print "'$string'\n";

     __END__

   This example will print:

   'This is an extremely long and tedious line of text containing only
meaningless gibberish.'

SEE ALSO
========

   perl(1), perldata(1), perlfunc(1), perlsub(1), perlmod(1), perlref(1),
perlobj(1), perlbot(1), perltoot(1), perltie(1), printf(3), sprintf(3).

VERSION
=======

   This man page documents "Data::Locations" version 5.2.

AUTHOR
======

     Steffen Beyer
     Ainmillerstr. 5 / App. 513
     D-80801 Munich
     Germany

     mailto:sb@engelschall.com
     http://www.engelschall.com/u/sb/download/

     (Contact by e-mail preferred)

COPYRIGHT
=========

   Copyright (c) 1997, 1998, 1999 by Steffen Beyer.  All rights reserved.

LICENSE
=======

   This package is free software; you can redistribute it and/or modify it
under the same terms as Perl itself, i.e., under the terms of the
"Artistic License" or the "GNU General Public License".

   Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this
distribution for details.

DISCLAIMER
==========

   This package is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

   See the "GNU General Public License" for more details.


