File Coverage

Brotli.xs
Criterion Covered Total %
statement 62 92 67.3
branch 19 34 55.8
condition n/a
subroutine n/a
pod n/a
total 81 126 64.2


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             #include
9             #include
10              
11             #define BUFFER_SIZE 1048576
12              
13             typedef struct brotli_decoder {
14             BrotliDecoderState *decoder;
15             }* IO__Uncompress__Brotli;
16              
17             typedef struct brotli_encoder {
18             BrotliEncoderState *encoder;
19             }* IO__Compress__Brotli;
20              
21              
22             MODULE = IO::Compress::Brotli PACKAGE = IO::Uncompress::Brotli
23             PROTOTYPES: ENABLE
24              
25             SV*
26             unbro_given_size(buffer, decoded_size)
27             SV* buffer
28             size_t decoded_size
29             PREINIT:
30             STRLEN encoded_size;
31             uint8_t *encoded_buffer, *decoded_buffer;
32             CODE:
33 89           encoded_buffer = (uint8_t*) SvPVbyte(buffer, encoded_size);
34 89           Newx(decoded_buffer, decoded_size, uint8_t);
35 89 50         if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){
36 0           croak("Error in BrotliDecoderDecompress");
37             }
38 89           RETVAL = newSV(0);
39 89           sv_usepvn(RETVAL, (char *) decoded_buffer, decoded_size);
40             OUTPUT:
41             RETVAL
42              
43             IO::Uncompress::Brotli
44             create(class)
45             SV* class
46             CODE:
47 178           Newx(RETVAL, 1, struct brotli_decoder);
48 178           RETVAL->decoder = BrotliDecoderCreateInstance(NULL, NULL, NULL);
49             OUTPUT:
50             RETVAL
51              
52             void
53             DESTROY(self)
54             IO::Uncompress::Brotli self
55             CODE:
56 178           BrotliDecoderDestroyInstance(self->decoder);
57 178           Safefree(self);
58              
59             SV*
60             decompress(self, in)
61             IO::Uncompress::Brotli self
62             SV* in
63             PREINIT:
64             uint8_t *next_in, *next_out, *buffer;
65             size_t available_in, available_out;
66             BrotliDecoderResult result;
67             CODE:
68 9482           next_in = (uint8_t*) SvPVbyte(in, available_in);
69 9482           Newx(buffer, BUFFER_SIZE, uint8_t);
70 9482           RETVAL = newSVpv("", 0);
71 9482           result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
72 18964 100         while(result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
73 9482           next_out = buffer;
74 9482           available_out=BUFFER_SIZE;
75 9482           result = BrotliDecoderDecompressStream( self->decoder,
76             &available_in,
77             (const uint8_t**) &next_in,
78             &available_out,
79             &next_out,
80             NULL );
81 9482 50         if(!result){
82 0           Safefree(buffer);
83 0           croak("Error in BrotliDecoderDecompressStream");
84             }
85 9482           sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
86             }
87 9482           Safefree(buffer);
88             OUTPUT:
89             RETVAL
90              
91              
92             MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli
93             PROTOTYPES: ENABLE
94              
95             SV*
96             bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW)
97             SV* buffer
98             U32 quality
99             U32 lgwin
100             PREINIT:
101             size_t encoded_size;
102             STRLEN decoded_size;
103             uint8_t *encoded_buffer, *decoded_buffer;
104             BROTLI_BOOL result;
105             CODE:
106 44 50         if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
107 0           croak("Invalid quality value");
108             }
109 44 50         if( lgwin < BROTLI_MIN_WINDOW_BITS || lgwin > BROTLI_MAX_WINDOW_BITS ) {
    50          
110 0           croak("Invalid window value");
111             }
112 44           decoded_buffer = (uint8_t*) SvPVbyte(buffer, decoded_size);
113 44           encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
114 44 50         if(!encoded_size){
115 0           croak("Compressed size overflow");
116             }
117 44           Newx(encoded_buffer, encoded_size+1, uint8_t);
118 44           result = BrotliEncoderCompress( quality,
119             lgwin,
120             BROTLI_DEFAULT_MODE,
121             decoded_size,
122             decoded_buffer,
123             &encoded_size,
124             encoded_buffer );
125 44 50         if(!result){
126 0           Safefree(buffer);
127 0           croak("Error in BrotliEncoderCompress");
128             }
129 44           encoded_buffer[encoded_size]=0;
130 44           RETVAL = newSV(0);
131 44           sv_usepvn_flags(RETVAL, (char *) encoded_buffer, encoded_size, SV_SMAGIC | SV_HAS_TRAILING_NUL);
132             OUTPUT:
133             RETVAL
134              
135             IO::Compress::Brotli
136             create(class)
137             SV* class
138             CODE:
139 88           Newx(RETVAL, 1, struct brotli_encoder);
140 88           RETVAL->encoder = BrotliEncoderCreateInstance(NULL, NULL, NULL);
141             OUTPUT:
142             RETVAL
143              
144             bool BrotliEncoderSetParameter(self, value)
145             IO::Compress::Brotli self
146             U32 value
147             ALIAS:
148             window = 1
149             quality = 2
150             _mode = 3
151             PREINIT:
152             BrotliEncoderParameter param;
153             INIT:
154 88           switch(ix){
155 0           case 0:
156 0           croak("BrotliEncoderSetParameter may not be called directly");
157             break;
158 0           case 1:
159 0 0         if( value < BROTLI_MIN_WINDOW_BITS || value > BROTLI_MAX_WINDOW_BITS ) {
    0          
160 0           croak("Invalid window value");
161             }
162 0           param = BROTLI_PARAM_LGWIN;
163 0           break;
164 88           case 2:
165 88 50         if( value < BROTLI_MIN_QUALITY || value > BROTLI_MAX_QUALITY ) {
166 0           croak("Invalid quality value");
167             }
168 88           param = BROTLI_PARAM_QUALITY;
169 88           break;
170 0           case 3:
171             /* Validation done on Perl side */
172 0           param = BROTLI_PARAM_MODE;
173 0           break;
174 0           default:
175 0           croak("Impossible ix in BrotliEncoderSetParameter");
176             break;
177             }
178             C_ARGS:
179             self->encoder, param, value
180              
181             SV*
182             _compress(self, in = &PL_sv_undef)
183             IO::Compress::Brotli self
184             SV* in
185             ALIAS:
186             compress = 1
187             flush = 2
188             finish = 3
189             PREINIT:
190             uint8_t *next_in, *next_out, *buffer;
191             size_t available_in, available_out;
192             BROTLI_BOOL result;
193             BrotliEncoderOperation op;
194             CODE:
195 176           switch(ix) {
196 0           case 0:
197 0           croak("_compress may not be called directly");
198             break;
199 88           case 1:
200 88           op = BROTLI_OPERATION_PROCESS;
201 88           break;
202 0           case 2:
203 0           op = BROTLI_OPERATION_FLUSH;
204 0           break;
205 88           case 3:
206 88           op = BROTLI_OPERATION_FINISH;
207 88           break;
208 0           default:
209 0           croak("Impossible ix in _compress");
210             break;
211             }
212              
213 176           Newx(buffer, BUFFER_SIZE, uint8_t);
214 176 100         if(in == &PL_sv_undef)
215 88           next_in = (uint8_t*) buffer, available_in = 0;
216             else
217 88           next_in = (uint8_t*) SvPVbyte(in, available_in);
218 176           RETVAL = newSVpv("", 0);
219             while(1) {
220 176           next_out = buffer;
221 176           available_out = BUFFER_SIZE;
222 176           result = BrotliEncoderCompressStream( self->encoder,
223             (BrotliEncoderOperation) op,
224             &available_in,
225             (const uint8_t**) &next_in,
226             &available_out,
227             &next_out,
228             NULL );
229 176 50         if(!result) {
230 0           Safefree(buffer);
231 0           croak("Error in BrotliEncoderCompressStream");
232             }
233              
234 176 100         if( available_out != BUFFER_SIZE ) {
235 109           sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
236             }
237              
238 176 100         if(
239 176           BrotliEncoderIsFinished(self->encoder) ||
240 88 50         (!available_in && !BrotliEncoderHasMoreOutput(self->encoder))
    50          
241             ) break;
242             }
243 176           Safefree(buffer);
244             OUTPUT:
245             RETVAL
246              
247             void
248             DESTROY(self)
249             IO::Compress::Brotli self
250             CODE:
251 88           BrotliEncoderDestroyInstance(self->encoder);
252 88           Safefree(self);