File Coverage

blib/lib/EBook/Ishmael/Decode.pm
Criterion Covered Total %
statement 19 37 51.3
branch 1 10 10.0
condition n/a
subroutine 7 8 87.5
pod 1 2 50.0
total 28 57 49.1


line stmt bran cond sub pod time code
1             package EBook::Ishmael::Decode;
2 17     17   292 use 5.016;
  17         59  
3 17     17   96 use strict;
  17         48  
  17         363  
4 17     17   62 use warnings;
  17         66  
  17         1180  
5             our $VERSION;
6              
7 17     17   94 use Exporter qw(import);
  17         41  
  17         911  
8             our @EXPORT_OK = qw(palmdoc_decode);
9              
10 17     17   85 use XSLoader;
  17         43  
  17         2030  
11              
12             my $CAN_XS = 0;
13              
14             my $decode_sub;
15              
16             BEGIN {
17 17     17   107 $VERSION = '2.03';
18 17         47 $CAN_XS = eval { XSLoader::load('EBook::Ishmael', $VERSION) };
  17         12696  
19 17 50       5502 $decode_sub = $CAN_XS ? \&xs_palmdoc_decode : \&pp_palmdoc_decode;
20             }
21              
22 201     201 1 11634 sub palmdoc_decode { $decode_sub->(@_); }
23              
24             # https://wiki.mobileread.com/wiki/PalmDOC#PalmDoc_byte_pair_compression
25             sub pp_palmdoc_decode {
26              
27 0     0 0   my $encode = shift;
28              
29 0           my $len = length $encode;
30 0           my $p = 0;
31              
32 0           my $decode = '';
33              
34 0           while ($p < $len) {
35              
36 0           my $b = ord substr $encode, $p++, 1;
37              
38             # space + xor byte with 0x80
39 0 0         if ($b >= 0xc0) {
    0          
    0          
    0          
40 0           $decode .= ' ';
41 0           $decode .= chr($b ^ 0x80);
42             # length-distance pair: get next byte, strip 2 leading bits, split byte
43             # into 11 bits of distance and 3 bits of length + 3
44             } elsif ($b >= 0x80) {
45 0           $b = ($b << 8) + ord substr $encode, $p++, 1;
46 0           my $d = ($b & 0x3fff) >> 3;
47 0           my $l = ($b & 0x0007) + 3;
48 0           $decode .= substr $decode, -$d, 1 while $l--;
49             # literal copy
50             } elsif ($b >= 0x09) {
51 0           $decode .= chr $b;
52             # copy next 1-8 bytes
53             } elsif ($b >= 0x01) {
54 0           $decode .= substr $encode, $p, $b;
55 0           $p += $b;
56             # copy null byte
57             } else {
58 0           $decode .= "\0";
59             }
60              
61             }
62              
63 0           return $decode;
64              
65             }
66              
67             1;
68              
69             =head1 NAME
70              
71             EBook::Ishmael::Decode - Ebook decoding routines
72              
73             =head1 SYNOPSIS
74              
75             use App::Ishmael::Decode qw(palmdoc_decode);
76              
77             my $decode = palmdoc_decode($data);
78              
79             =head1 DESCRIPTION
80              
81             B is a module that provides subroutines for decoding
82             various kinds of encoded ebook text. For L user documentation, you
83             should consult its manual (this is developer documentation).
84              
85             =head1 SUBROUTINES
86              
87             B does not export any subroutines by default.
88              
89             =head2 $d = palmdoc_decode($data)
90              
91             Decodes PalmDoc lz77-encoded C<$data>, returning the decoded data.
92              
93             =head1 AUTHOR
94              
95             Written by Samuel Young, Esamyoung12788@gmail.comE.
96              
97             This project's source can be found on its
98             L. Comments and pull
99             requests are welcome!
100              
101             =head1 COPYRIGHT
102              
103             Copyright (C) 2025-2026 Samuel Young
104              
105             This program is free software: you can redistribute it and/or modify
106             it under the terms of the GNU General Public License as published by
107             the Free Software Foundation, either version 3 of the License, or
108             (at your option) any later version.
109              
110             =cut