Convert::yEnc::RC - yEnc file-part database


Convert-yEnc documentation Contained in the Convert-yEnc distribution.

Index


Code Index:

NAME

Top

Convert::yEnc::RC - yEnc file-part database

SYNOPSIS

Top

  use Convert::yEnc::RC;

  	      $rc = new Convert::yEnc::RC;
  	      $rc = new Convert::yEnc::RC $file;

  $ok       = $rc->load;
  $ok 	    = $rc->load($file);

  $ok       = $rc->update  ($line);
  @files    = $rc->files;
  @complete = $rc->complete;
  $complete = $rc->complete($fileName);
  $entry    = $rc->entry   ($fileName);
  $ok       = $rc->drop    ($fileName);

  	      $rc->save;
  	      $rc->save($file);




ABSTRACT

Top

yEnc file-part database

DESCRIPTION

Top

A Convert::yEnc::RC object manages a database of yEnc file parts.

Applications pass the =ybegin, =ypart, and =yend lines from yEncoded files to the object, and it keeps track of the files, parts and bytes as they are received. The object reports errors if the sequence of =y lines is inconsistent.

Applications can query the object to find out what files, parts, and bytes have been received, and whether a given file is complete.

The database can be be saved to and restored from disk.

Database format

The database is stored on disk as a flat ASCII file. There is one line in the database for each yEncoded file.

A line for a single-part file has 3 fields

A line for a multi-part file has 4 fields

Fields are tab-delimited, so that file names may contain whitespace.

Example

    a.jpg	20000	20000
    b.jpg	10000	1-5000	1




Exports

Nothing.

Methods

$rc = new Convert::yEnc::RC
$rc = new Convert::yEnc::RC $file

Creates and returns a new Convert::yEnc::RC object.

If $file is supplied, initializes the database from $file.

If $file is not supplied, or doesn't exist, initializes the database to empty.

$ok = $rc->load($file)

Loads the database in $file into $rc. Any existing data in $rc is discarded. Returns true on success.

If $file can't be opened, load does nothing and returns false.

If $file contains invalid lines, load dies. When this happens, the state of $rc is undefined.

$ok = $rc->update($line)

Updates $rc according to the contents of $line. $line should be a header (=begin), trailer (=end), or part (=part) line from a yEncoded file.

Returns true iff $line is well-formed and consistent with the current state of the database.

@files = $rc->files

Returns a list of all the files in the database.

@complete = $rc->complete

Returns a list of all the files in the database that are complete.

$complete = $rc->complete($fileName)

Returns true iff all parts of ($fileName) have been received.

$entry = $rc->entry($fileName)

Returns the database entry for $fileName. $entry is a Convert::yEnc::Entry object.

If $fileName is not in the database, return undef.

$ok = $rc->drop($fileName)

Deletes the entry for $fileName from the database.

If $fileName is not in the database, return false.

$rc->save

Writes the contents of $newsrc back to the file from which it was loaded.

save dies if there is an error writing the file.

$newsrc->save($file)

Writes the contents of $newsrc to $file. Subsequent calls to save() will write to $file.

save dies if there is an error writing the file.

BUGS

Top

item *

The database doesn't persist the yEnc 1.2 "total" field to disk.

SEE ALSO

Top

AUTHOR

Top

Steven W McDougall, <swmcd@world.std.com>

COPYRIGHT AND LICENSE

Top


Convert-yEnc documentation Contained in the Convert-yEnc distribution.

package Convert::yEnc::RC;

use strict;
use Convert::yEnc::Entry;
use warnings;

use overload 'eq' => \&_eq;


sub new
{
    my ($class, $file) = @_;

    my $rc = { };
    bless $rc, $class;
    $rc->load($file) if $file;

    $rc
}


sub load
{
    my($rc, $file) = @_;
    
    $rc->{file } = $file;
    $rc->{db   } = { };

    no warnings qw(uninitialized);
    open RC, $file or return undef;

    while (my $line = <RC>)
    {
	$line =~ /\S/ or next;
	my($name, $rest) = split "\t", $line, 2;
	my $entry = load Convert::yEnc::Entry $rest;
	$rc->{db}{$name} = $entry;
    }

    close(RC);

    1
}

sub update
{
    my($rc, $line) = @_;

    my($tag, @fields) = split ' ', $line;

    my %field;
    for my $field (@fields)
    {
	my($key, $val) = split /=/, $field;
	$field{$key} = $val;
    }

    $line =~ s(\s+$)();
    my($name) = $line =~ /name=\s*(.*)/;  # Die! Die! Die!
    $field{name} = $name if $name;

    $tag =~ s/^=/_/;
    $rc->can($tag) and $rc->$tag(\%field)
}

sub _ybegin
{
    my($rc, $fields) = @_;

    my $name = $fields->{name};
    $name or return 0;

    my $entry = $rc->{db}{$name};

    if ($entry)
    {
	$rc->{current} = $entry;
	return $entry->ybegin($fields);
    }

    $rc->{current} = $rc->{db}{$name} = new Convert::yEnc::Entry $fields;
}

sub _ypart
{
    my($rc, $fields) = @_;

    my $entry = $rc->{current};
    $entry and $entry->ypart($fields);
}

sub _yend
{
    my($rc, $fields) = @_;

    my $entry = $rc->{current};
    delete $rc->{current};

    $entry and $entry->yend($fields);
}


sub files
{
    my $rc = shift;
    my $db = $rc->{db};
    keys %$db
}

sub complete
{
    my($rc, $name) = @_;

    $name ? $rc->_is_complete($name) : $rc->_complete_files
}

sub _is_complete
{
    my($rc, $name) = @_;
    my $entry = $rc->{db}{$name};
    $entry and $entry->complete;
}

sub _complete_files
{
    my $rc = shift;
    my $db = $rc->{db};

    grep { $db->{$_}->complete($_) } keys %$db
}

sub entry
{
    my($rc, $name) = @_;

    $rc->{db}{$name}
}

sub drop
{
    my($rc, $name) = @_;

    delete $rc->{db}{$name};
}


sub save
{
    my $rc   = shift;
    my $file = shift || $rc->{file} or 
	die ref $rc, "::save: no file\n";
    
    open(RC, "> $file.tmp") or 
	die ref $rc, ": Can't open $file.tmp: $!\n";

    my $db = $rc->{db};

    while (my($name, $entry) = each %$db)
    {
	print RC "$name\t$entry\n";
    }

    close RC;

    rename "$file.tmp", $file or 
	die ref $rc, ": can't rename $file.tmp -> $file: $!\n";

    $rc->{file} = $file;
}


sub _eq
{
    my($a, $b) = @_;

    my $dba = $a->{db};
    my $dbb = $b->{db};

    my @a = keys %$dba;
    my @b = keys %$dbb;

    @a==@b or return 0;

    for my $name (@a)
    {
	$a->{db}{$name} eq $b->{db}{$name} or return 0;
    }

    1
}

1

__END__