File Coverage

Ishmael.xs
Criterion Covered Total %
statement 41 53 77.3
branch 22 34 64.7
condition n/a
subroutine n/a
pod n/a
total 63 87 72.4


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #include "ppport.h"
7              
8             #define DECODE_BUF_SIZE 8192
9              
10             /* https://wiki.mobileread.com/wiki/PalmDOC#PalmDoc_byte_pair_compression */
11             int
12 201           c_palmdoc_decode(
13             const unsigned char* input, STRLEN inlen,
14             unsigned char* output, STRLEN outlen,
15             STRLEN* decoded
16             ) {
17              
18 201           unsigned int b = 0;
19 201           unsigned int ld = 0;
20 201           unsigned int l, d = 0;
21 201           STRLEN outp = 0;
22              
23 201           *decoded = 0;
24              
25 263154 100         for (STRLEN i = 0; i < inlen;) {
26 262953           b = input[i++];
27             /* space + xor byte with 0x80 */
28 262953 100         if (b >= 0xc0) {
29 11467 50         if (outp >= outlen) {
30 0           return -1;
31             }
32 11467           output[outp++] = ' ';
33 11467 50         if (outp >= outlen) {
34 0           return -1;
35             }
36 11467           output[outp++] = b ^ 0x80;
37             /* length-distance pair: get next byte, strip 2 leading bits, split
38             byte into 11 bits of distance and 3 bits of length + 3 */
39 251486 100         } else if (b >= 0x80) {
40 113855 50         if (i + 1 >= inlen) {
41 0           return -1;
42             }
43 113855           ld = (b << 8) + input[i++];
44 113855           d = (ld >> 3) & 0x7ff;
45 113855           l = (ld & 0x0007) + 3;
46 113855 50         if (d > outp) {
47 0           return -1;
48             }
49 113855 50         if (l > outlen - outp - 1) {
50 0           return -1;
51             }
52 736503 100         while (l != 0) {
53 622648           output[outp] = output[outp - d];
54 622648           outp++;
55 622648           l--;
56             }
57             /* literal copy */
58 137631 100         } else if (b >= 0x09) {
59 136922 50         if (outp >= outlen) {
60 0           return -1;
61             }
62 136922           output[outp++] = b;
63             /* copy next 1-8 bytes */
64 709 50         } else if (b >= 0x01) {
65 709 50         if (i + b > inlen) {
66 0           return -1;
67             }
68 709 50         if (outp + b > outlen) {
69 0           return -1;
70             }
71 2681 100         while (b != 0) {
72 1972           output[outp++] = input[i++];
73 1972           b--;
74             }
75             /* copy null byte */
76             } else {
77 0 0         if (outp >= outlen) {
78 0           return -1;
79             }
80 0           output[outp++] = '\0';
81             }
82             }
83              
84             assert(outp <= outlen);
85              
86 201           *decoded = outp;
87 201           return 0;
88              
89             }
90              
91             MODULE = EBook::Ishmael PACKAGE = EBook::Ishmael::Decode
92              
93             PROTOTYPES: DISABLE
94              
95             SV*
96             xs_palmdoc_decode(encode)
97             SV * encode
98             INIT:
99             STRLEN enclen;
100             SV * outsv;
101             unsigned char output[DECODE_BUF_SIZE];
102             STRLEN declen;
103             int s;
104             CODE:
105 201           enclen = sv_len_utf8(encode);
106 201           s = c_palmdoc_decode(
107 201           (unsigned char*) SvPVbyte_nolen(encode), enclen,
108             output, DECODE_BUF_SIZE,
109             &declen
110             );
111             assert(declen <= DECODE_BUF_SIZE);
112 201 50         if (s != 0) {
113 0           croak("Invalid LZ77-encoded PalmDOC data stream\n");
114             }
115 201           outsv = newSVpvn_flags(output, declen, 0);
116 201           RETVAL = outsv;
117             OUTPUT:
118             RETVAL