File Coverage

blib/lib/Digest/ED2K.pm
Criterion Covered Total %
statement 45 45 100.0
branch 8 10 80.0
condition 3 6 50.0
subroutine 13 13 100.0
pod 7 7 100.0
total 76 81 93.8


line stmt bran cond sub pod time code
1             package Digest::ED2K;
2 1     1   54788 use common::sense;
  1         3  
  1         6  
3 1     1   462 use Digest::MD4 ();
  1         700  
  1         22  
4 1     1   5 use Exporter 'import';
  1         2  
  1         49  
5             our @EXPORT_OK = qw(ed2k ed2k_hex ed2k_base64);
6              
7 1     1   6 use Digest::base 1.03;
  1         18  
  1         44  
8 1     1   33 BEGIN { push @Digest::ED2K::ISA, 'Digest::base' }
9              
10 1     1   368 use version 0.077; our $VERSION = version->declare('v1.1.1');
  1         1544  
  1         7  
11              
12             sub CHUNK_SIZE() { 9728000 }
13              
14             sub new {
15 13     13 1 4492 my $class = shift;
16 13   33     26892 bless { chunk_ctx => Digest::MD4->new }, ref $class || $class;
17             }
18              
19             sub clone {
20 1     1 1 6 my $self = shift;
21             bless {
22             ($self->{ctx} ? (ctx => $self->{ctx}->clone) : ()),
23             chunk_ctx => $self->{chunk_ctx}->clone,
24             chunk_length => $self->{chunk_length},
25 1 50       10 }, ref $self;
26             }
27              
28             sub add {
29 17 100   17 1 69 return shift->add(join '', @_) if @_ > 2;
30              
31 14         22 my $self = shift;
32              
33             # Adding buffer won't cross chunk border.
34             # Avoid copying.
35 14 100       56 if (CHUNK_SIZE - $self->{chunk_length} > length $_[0]) {
36 12         32 $self->{chunk_ctx}->add($_[0]);
37 12         18 $self->{chunk_length} += length $_[0];
38              
39 12         496 return $self;
40             }
41              
42             # Buffer intersects chunk border, copy for modification.
43 2         13 my $buffer = shift;
44              
45 2         10 while ($buffer) {
46 3         16 my $need_length = CHUNK_SIZE - $self->{chunk_length};
47              
48 3         27184 my $substr = substr $buffer, 0, $need_length;
49 3         47797 $self->{chunk_ctx}->add($substr);
50 3         20 $self->{chunk_length} += length $substr;
51              
52             # Completed chunk
53 3 50       18 if ($self->{chunk_length} == CHUNK_SIZE) {
54 3   66     48 my $ctx = $self->{ctx} ||= Digest::MD4->new;
55              
56 3         24 $ctx->add($self->{chunk_ctx}->digest);
57 3         11 $self->{chunk_length} = 0;
58             }
59              
60 3         8732 $buffer = substr $buffer, $need_length;
61             }
62              
63 2         24 return $self;
64             }
65              
66             sub digest {
67 15     15 1 652 my $self = shift;
68 15         38 my ($ctx) = delete @$self{qw( ctx chunk_length )};
69              
70             # One chunk
71 15 100       124 return $self->{chunk_ctx}->digest unless $ctx;
72              
73             # Multi chunk
74 2         34 $ctx->add($self->{chunk_ctx}->digest)->digest;
75             }
76              
77             sub ed2k(@) {
78 2     2 1 8 Digest::ED2K->new->add(@_)->digest;
79             }
80              
81             sub ed2k_hex(@) {
82 2     2 1 6 Digest::ED2K->new->add(@_)->hexdigest;
83             }
84              
85             sub ed2k_base64(@) {
86 2     2 1 6 Digest::ED2K->new->add(@_)->b64digest;
87             }
88              
89             0x6B63;
90             __END__