package Convert::yEnc::Entry; use strict; use Set::IntSpan; use warnings; sub new { my($class, $fields) = @_; $fields->{part} ? new Convert::yEnc::EntryM $fields : new Convert::yEnc::EntryS $fields } sub load { my($class, $line) = @_; my($size, $bytes, $parts) = split "\t", $line; $parts ? load Convert::yEnc::EntryM $size, $bytes, $parts : load Convert::yEnc::EntryS $size, $bytes } package Convert::yEnc::EntryS; use base qw(Convert::yEnc::Entry); use overload '""' => \&to_string, 'eq' => \&_eq; sub new { my($class, $fields) = @_; my $size = $fields->{size}; $size or return undef; my $entry = { state => 'ybegin', size => $size, bytes => 0 }; bless $entry, $class } sub load { my($class, $size, $bytes) = @_; my $entry = { state => 'yend', size => $size, bytes => $bytes }; bless $entry, $class } sub ybegin { 0 } sub ypart { 0 } sub yend { my($entry, $fields) = @_; $entry->{state} eq 'ybegin' or return 0; $entry->{state} = 'yend'; my $size = $fields->{size}; $entry->{bytes} = $size; $size and $size == $entry->{size} } sub complete { my $entry = shift; $entry->{state} eq 'yend' } sub to_string { my $entry = shift; my $size = $entry->{size} || 0; my $bytes = $entry->{bytes} || 0; "$size\t$bytes" } sub _eq { no warnings qw(uninitialized); my($a, $b) = $_; $a->{size }==$b->{size } and $a->{bytes}==$b->{bytes} } package Convert::yEnc::EntryM; use base qw(Convert::yEnc::Entry); use overload '""' => \&to_string, 'eq' => \&_eq; sub new { my($class, $fields) = @_; defined $fields->{size} or return undef; my $entry = { state => 'ybegin', fSize => $fields->{size}, part => $fields->{part}, total => $fields->{total}, parts => (new Set::IntSpan), bytes => (new Set::IntSpan) }; bless $entry, $class } sub load { my($class, $size, $bytes, $parts) = @_; my $entry = { state => 'yend', fSize => $size, bytes => (new Set::IntSpan $bytes), parts => (new Set::IntSpan $parts) }; bless $entry, $class } sub ypart { my($entry, $fields) = @_; $entry->{state} eq 'ybegin' or return 0; $entry->{state} = 'ypart'; my $begin = $fields->{begin}; my $end = $fields->{end }; $begin and $end or return 0; $entry->{begin} = $begin; $entry->{end } = $end; $entry->{pSize} = $end - $begin + 1; } sub yend { my($entry, $fields) = @_; $entry->{state} eq 'ypart' or return 0; $entry->{state} = 'yend'; my $pSize = $fields->{size}; defined $pSize or return 0; my $part = $fields->{part}; $part == $entry->{part} or return 0; $entry->{parts}->insert($part); my $begin = $entry->{begin}; my $end = $entry->{end }; my $bytes = "$begin-$end"; valid Set::IntSpan $bytes or return 0; $entry->{bytes} = $entry->{bytes}->union($bytes); 1 } sub ybegin { my($entry, $fields) = @_; $entry->{state} eq 'yend' or return 0; $entry->{state} = 'ybegin'; $fields->{size}==$entry->{fSize} or return 0; my $total = $fields->{total}; defined $total and defined $entry->{total} and $total != $entry->{total} and return 0; my $part = $fields->{part}; defined $part or return 0; $entry->{part} = $part; 1 } sub complete { my $entry = shift; $entry->{fSize} == $entry->{bytes}->cardinality; } sub to_string { my $entry = shift; my $size = $entry->{fSize}; my $bytes = $entry->{bytes}->run_list; my $parts = $entry->{parts}->run_list; "$size\t$bytes\t$parts" } sub _eq { my($a, $b) = @_; $a->{fSize}==$b->{fSize} and $a->{bytes}->equal($b->{bytes}) and $a->{parts}->equal($b->{parts}) } 1 __END__ =head1 NAME Convert::yEnc::Entry - an entry in a Convert::yEnc::RC database =head1 SYNOPSIS use Convert::yEnc::Entry; $entry = new Convert::yEnc::Entry { size => 10000 }; $entry = new Convert::yEnc::Entry { size => 50000, part => 1 }; $entry = load Convert::yEnc::Entry "10000\t10000"; $entry = load Convert::yEnc::Entry "20000\t1-20000\t1-2"; $ok = $entry->ybegin( { size=>10000 } ); $ok = $entry->ypart ( { begin=>1, end=>10000 } ); $ok = $entry->yend ( { size=>10000 } ); $entry->complete and ... print "$entry\n"; =head1 ABSTRACT An entry in a Convert::yEnc::RC database =head1 DESCRIPTION C manages a single entry in a Convert::yEnc::RC database =head2 Exports Nothing. =head2 Methods =over 4 =item I<$entry> = C C \I<%ybegin> Creates and returns a new C object. I<%ybegin> is a hash of key => value pairs from a C<=ybegin> line. =item I<$entry> = C C I<$fields> Creates and returns a new C object. I<$fields> is the portion of a line from an RC database following the file name. =item I<$ok> = I<$entry>->C(\I<%ybegin>) =item I<$ok> = I<$entry>->C(\I<%ypart>) =item I<$ok> = I<$entry>->C(\I<%yend>) Updates I<$entry> according to the contents of a C<=ybegin>, C<=ypart> or C<=yend> control line. The argument is a reference to a hash of key => value pairs from the control line. Returns true iff the control line is consistent with the current state of I<$entry>. =item I<$entry>->C Returns true iff all parts of the file described by I<$entry> have been received. =back =head2 Overloads =over 4 =item C<""> (stringify) Serializes a C object for storage in an RC database. =back =head1 SEE ALSO L =head1 AUTHOR Steven W McDougall, Eswmcd@world.std.comE =head1 COPYRIGHT AND LICENSE Copyright (c) 2002-2008 by Steven McDougall. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.