BTRIEVE-SAVE
view release on metacpan or search on metacpan
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $DEBUG $TEST
);
$VERSION = '0.35';
$DEBUG = 0;
require Exporter;
require 5.004;
@ISA = qw(Exporter);
@EXPORT= qw();
@EXPORT_OK= qw();
# Preloaded methods go here.
####################################################################
# This is the constructor method that creates the BTRIEVE object.
# It will attempt to set up info from the config file.
####################################################################
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $config_file= shift ;
my $file = shift ||undef;
my $save_btr = {opt=>{}, array=>[]};
$save_btr->{'opt'}{'config'}=$config_file;
bless $save_btr, $class;
if (-e $config_file) {
$save_btr->config($config_file);
} else {
return $save_btr;
}
if (!$file) {return $save_btr};
$save_btr->{'opt'}{'file'}=$file;
$save_btr->_initbtrieve();
return $save_btr;
}
###################################################################
# _initbtrieve() sets up config and filehandle
###################################################################
sub _initbtrieve {
my $save_btr = shift;
my $config_file = $save_btr->{'opt'}{'config'};
$save_btr->{'opt'}{'increment'} = -1;
my $file = $save_btr->{'opt'}{'file'};
if (not(-e $file)) {carp "File \"$file\" doesn't exist"; return}
open (*file, $file);
binmode *file;
$save_btr->{'opt'}{'handle'}=\*file; #store filehandle in object
}
###################################################################
# config() looks for a config file which tells us where the
# offsets are in the fixed part of the record, their types and
# what to call them locally.
###################################################################
sub config {
my $save_btr = shift;
my $proto_rec = BTRIEVE::SAVE::REC->newconfig($save_btr->{'opt'}{'config'});
$save_btr->{'opt'}{'proto_rec'} = $proto_rec;
}
###################################################################
# parse_file() reads from a BTRIEVE SAVE file. Can do so
# incrementally.
###################################################################
sub parse_file {
my $save_btr = shift;
my $increment = $save_btr->{'opt'}{'increment'}; #pick out increment from the object
my $recordcount = 0;
while ($increment==-1 or $recordcount<$increment) {
my $curr_rec = $save_btr->next_rec;
last unless $curr_rec;
push @{$save_btr->{'array'}},$curr_rec;
$recordcount++;
} #end reading this record
return $recordcount;
}
####################################################################
# Returns a new BTRIEVE::SAVE::REC based on the next bits.
# Returns undef if we have reached the end.
####################################################################
sub next_rec {
my $save_btr=shift;
my ($rec,$eor) = $save_btr->next_recbits;
return undef if $eor eq "\cZ";
return undef unless defined($rec);
my $proto_rec = $save_btr->{'opt'}{'proto_rec'};
my $curr_rec = $proto_rec->copy_struct();
$curr_rec->parse_string($rec);
return $curr_rec;
}
####################################################################
# Reads thru the handle looking for the bits forming the $rec
# and for the bits that should be $eor (end-of-record).
# Returns ($rec,$eor). $eor is undef if the read is at EOF.
# $eor is undef if we are at the DOS EOF ("\cZ") at the
# appropriate defined place.
####################################################################
sub next_recbits {
my $save_btr = shift;
my $handle = $save_btr->{'opt'}{'handle'};
#need to use read to get the right bytes. Bummer.
my $pos= tell($handle);
=item Unix Install
perl Makefile.PL
make
make test
make install
=item Win9x/WinNT/Win2000 Install
perl Makefile.PL
perl test.pl
perl install.pl
=item Test
Once you have installed BTRIEVE::SAVE, you can check if Perl can find
it. Change to some other directory and execute from the command line:
perl -e "use BTRIEVE::SAVE"
If you do not get any response that means everything is OK! If you get
an error like I<Can't locate method "use" via package BTRIEVE::SAVE>
then Perl is not able to find BTRIEVE/SAVE.pm--double check that the
file copied it into the right place during the install.
=back
=head2 Todo
=over 4
=item *
Support for the other 12 documented btrieve data types.
=item *
Help for adding the names column in the config file.
=item *
More detailed warnings/sanity checks on the config file and save file.
=back
=head2 Notes
Please let us know if you run into any difficulties using
BTRIEVE::SAVE--we'd be happy to try to help. Also, please contact us
if you notice any bugs, or if you would like to suggest an
improvement/enhancement. Email addresses are listed at the bottom of
this page. Lane is probably the most interested in making this work, so
may be your best initial bet.
=head2 BTRIEVE::SAVE::REC structure.
A save file record on disk looks like:
__________________________________________
| Fixed, | Fixed, | |
Count[, ] | indexed. | left-over| Variable |\r\n
|___________________|__________|___________|
The Count is the number of "boxed bytes" (excluding the count itself, the
following comma or space, and the final two bytes at the end). Count is
an unpadded ascii integer, like "524".
Count is followed by either a comma or a space. BTRIEVE::SAVE::REC writes
a comma, but reads either comma or space.
The boxes are binary data. BTRIEVE::SAVE::REC will not interpret the
(fixed, left-over) or variable boxes, and will parse the (fixed,
indexed) data into a hash based on a template and names determined from
the config file.
The last two boxes may be empty; if the sum of the lengths is equal to the
fixed_length defined in the config file the (fixed, left-over) box will have no
bytes. Variable will be non-empty if and only if Count > fixed_length.
The number of bytes covered by the first two fields is equal to
fixed_length. (In theory the (fixed, indexed) and (fixed, left-over)
could be intermixed, with possible overlaps. Has anyone seen this?
Docs saying that Pervasive won't support this?)
The final two bytes are unix return and newline bytes.
A save file is a bunch of save file records concatenated with no
intervening bytes followed by "\cZ".
Each BTRIEVE::SAVE::REC has admin information in its {opt} key and
data in its {values} key.
{opt} has keys:
{fixed_defs} keys a ref to an array of hashes with keys:
{len} - length in bytes of the field
{name} - the user-defined name of that field, found from an
extra column in the config file. The config file
cannot use "ZZ" as a field name; one of the {name}s
is always set to "ZZ" to handle fixed length
information which is unaccounted for by btrieve's
keys.
{type} - Btrieve's idea of the type of that field.
The array of hashes is in the order that the defining lines occur
in the config file.
{template} - pack template used for extracting values
{names} - ref to array of names as in fixed_defs.
This is not strictly necessary.
{len} - total length of the fixed part of the record. This
must be at least equal to the sum of the {len}'s in
the {fixed_defs}.
{values} is a ref to an array
[$rhfixed,$rfixed,$rvar]
( run in 0.601 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )