CGI-MultiValuedHash

 view release on metacpan or  search on metacpan

lib/CGI/MultiValuedHash.pm  view on Meta::CPAN

This method returns an ARRAY ref containing the new records (as MVHs) on success,
even if the end-of-file is reached before we find any records.  It returns undef
on a file-system error, even if some records were read first.

=cut

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

sub batch_from_file {
	my $class = CORE::shift( @_ );
	my $fh = CORE::shift( @_ );
	my $case_inse = CORE::shift( @_ );
	my $max_obj_num = CORE::shift( @_ );  # if <= 0, read all records
	my $use_empty = $_[3];  # fourth remaining argument

	ref( $fh ) eq 'GLOB' or return( undef );

	my @mvh_list = ();
	my $remaining_obj_count = ($max_obj_num <= 0) ? -1 : $max_obj_num;

	GET_ANOTHER_REC: {
		eof( $fh ) and last;

		my $mvh = CGI::MultiValuedHash->new( $case_inse );

		defined( $mvh->from_file( $fh, @_ ) ) or return( undef );

		CORE::push( @mvh_list, $mvh );

		--$remaining_obj_count != 0 and redo GET_ANOTHER_REC;
	}

	# if file is of nonzero length and contains no records, or if it has a 
	# record separator followed by no records, then we would end up with an 
	# empty last record in our list even if empty records aren't allowed, 
	# so we get rid of said disallowed here
	if( !$use_empty and @mvh_list and !$mvh_list[-1]->keys_count() ) {
		CORE::pop( @mvh_list );
	}

	return( \@mvh_list );
}

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

1;
__END__

=head1 THE DEFAULT URL-ENCODED FORMAT

When the to_url_encoded_string() and from_url_encoded_string() methods and their 
derivatives are used with the fewest number of arguments, they default to an 
encoding format used in query strings, such as $ENV{QUERY_STRING}.  Normal query 
strings look like this:

	name=name&type=textfield&visible_title=What%27s+your+name%3f

Here's another example with a multi-valued field (it is actually a single line, 
but appears on two here for clarity:

	name=color&type=popup_menu&values=red&values=green&values=blue&
	values=chartreuse&visible_title=What%27s+your+favorite+colour%3f

Some query strings are the result of ISINDEX queries, and they look different:

	tell&me&about&stuff

Cookie strings such as $ENV{HTTP_COOKIE} are different yet and look like:

	name=color; type=popup_menu; values=red&green&blue&chartreuse

In the argument lists for the above methods, DELIM refers to the "&" in normal 
query strings and the "; " in cookies, whereas VALSEP is meaningless with normal 
query strings and is the "&" in "isindex" queries and cookie strings.

=head1 THE DEFAULT FILE FORMAT

When the to_file() and from_file() methods and their derivatives are used with 
the fewest number of arguments, they default to an encoding format that is quite 
easy for humans to read.  This common format is capable of storing an ordered 
list of variable-length records where the fields of each record are stored in 
name=value pairs, one field value per line.

Each record can have different fields from the others, and each field can have
either one or several values.  In the latter case, the field name is repeated for
each value.  Records are delimited by lines that contain only a "=" and are
otherwise empty.  The order of individual fields in the file doesn't matter, but
the order of parts of multivalued fields does; this order is preserved.  

All field names and values are url-escaped, so we are capable of storing binary
data without corrupting it.

The following example shows 4 MVH objects encoded in the default format:

	=
	name=name
	type=textfield
	visible_title=What%27s+your+name%3f
	=
	default=eenie
	default=minie
	name=words
	type=checkbox_group
	values=eenie
	values=meenie
	values=minie
	values=moe
	visible_title=What%27s+the+combination%3f
	=
	name=color
	type=popup_menu
	values=red
	values=green
	values=blue
	values=chartreuse
	visible_title=What%27s+your+favorite+colour%3f
	=
	type=submit

This file format is identical to that used by CGI.pm when saving its state, so 
such files could be used and manipulated by either that class or this one as you 
see fit.  Furthermore, this format is identical to that used by the Whitehead
Genome Center's data exchange format, and can be manipulated and even databased
using Boulderio utilities.  (That may not be url-escaped, however.)  See
"http://www.genome.wi.mit.edu/genome_software/other/boulder.html" for further
details.  However, this compatability does not extend to all of Boulderio's 
features, so Boulderio can store more complex data structures than this class.

=head2 SOME DEVELOPMENT HISTORY

The file default format in question became known to me during a programming
exercise where I was given an example file containing usernames and passwords and
had to parse it.  I was informed at the time that this file format was common.  

This functionality was created for my own use, as I stored html form descriptions 
and user input from my CGI scripts in the file format.  Through independent
development, my module gained the ability to store binary data safely through
url-encoding (preserving white-space formatting among other benefits), and could
store everything from multi-valued fields.

=head1 AUTHOR

Copyright (c) 1999-2004, Darren R. Duncan.  All rights reserved.  This module
is free software; you can redistribute it and/or modify it under the same terms
as Perl itself.  However, I do request that this copyright information and
credits remain attached to the file.  If you modify this module and
redistribute a changed version then please attach a note listing the
modifications.  This module is available "as-is" and the author can not be held
accountable for any problems resulting from its use.

I am always interested in knowing how my work helps others, so if you put this
module to use in any of your own products or services then I would appreciate
(but not require) it if you send me the website url for said product or
service, so I know who you are.  Also, if you make non-proprietary changes to
the module because it doesn't work the way you need, and you are willing to
make these freely available, then please send me a copy so that I can roll
desirable changes into the main release.

Address comments, suggestions, and bug reports to B<perl@DarrenDuncan.net>.

=head1 CREDITS

Thanks to Johan Vromans <jvromans@squirrel.nl> for suggesting the split of my old
module "CGI::HashOfArrays" into the two current ones, "Data::MultiValuedHash" and
"CGI::MultiValuedHash".  This took care of a longstanding logistical problem
concerning whether the module was a generic data structure or a tool for
encoding/decoding CGI data.

Thanks to Steve Benson <steve.benson@stanford.edu> for suggesting POD
improvements in regards to the case-insensitivity feature, so the documentation
is easier to understand.



( run in 1.324 second using v1.01-cache-2.11-cpan-364913b4093 )