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 86           encoded_buffer = (uint8_t*) SvPVbyte(buffer, encoded_size);
34 86           Newx(decoded_buffer, decoded_size, uint8_t);
35 86 50         if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){
36 0           croak("Error in BrotliDecoderDecompress");
37             }
38 86           RETVAL = newSV(0);
39 86           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 172           Newx(RETVAL, 1, struct brotli_decoder);
48 172           RETVAL->decoder = BrotliDecoderCreateInstance(NULL, NULL, NULL);
49             OUTPUT:
50             RETVAL
51              
52             void
53             DESTROY(self)
54             IO::Uncompress::Brotli self
55             CODE:
56 172           BrotliDecoderDestroyInstance(self->decoder);
57 172           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 9475           next_in = (uint8_t*) SvPVbyte(in, available_in);
69 9475           Newx(buffer, BUFFER_SIZE, uint8_t);
70 9475           RETVAL = newSVpv("", 0);
71 9475           result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
72 18950 100         while(result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
73 9475           next_out = buffer;
74 9475           available_out=BUFFER_SIZE;
75 9475           result = BrotliDecoderDecompressStream( self->decoder,
76             &available_in,
77             (const uint8_t**) &next_in,
78             &available_out,
79             &next_out,
80             NULL );
81 9475 50         if(!result){
82 0           Safefree(buffer);
83 0           croak("Error in BrotliDecoderDecompressStream");
84             }
85 9475           sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
86             }
87 9475           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 42 50         if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
107 0           croak("Invalid quality value");
108             }
109 42 50         if( lgwin < BROTLI_MIN_WINDOW_BITS || lgwin > BROTLI_MAX_WINDOW_BITS ) {
    50          
110 0           croak("Invalid window value");
111             }
112 42           decoded_buffer = (uint8_t*) SvPVbyte(buffer, decoded_size);
113 42           encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
114 42 50         if(!encoded_size){
115 0           croak("Compressed size overflow");
116             }
117 42           Newx(encoded_buffer, encoded_size+1, uint8_t);
118 42           result = BrotliEncoderCompress( quality,
119             lgwin,
120             BROTLI_DEFAULT_MODE,
121             decoded_size,
122             decoded_buffer,
123             &encoded_size,
124             encoded_buffer );
125 42 50         if(!result){
126 0           Safefree(buffer);
127 0           croak("Error in BrotliEncoderCompress");
128             }
129 42           encoded_buffer[encoded_size]=0;
130 42           RETVAL = newSV(0);
131 42           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 84           Newx(RETVAL, 1, struct brotli_encoder);
140 84           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 84           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 84           case 2:
165 84 50         if( value < BROTLI_MIN_QUALITY || value > BROTLI_MAX_QUALITY ) {
166 0           croak("Invalid quality value");
167             }
168 84           param = BROTLI_PARAM_QUALITY;
169 84           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 168           switch(ix) {
196 0           case 0:
197 0           croak("_compress may not be called directly");
198             break;
199 84           case 1:
200 84           op = BROTLI_OPERATION_PROCESS;
201 84           break;
202 0           case 2:
203 0           op = BROTLI_OPERATION_FLUSH;
204 0           break;
205 84           case 3:
206 84           op = BROTLI_OPERATION_FINISH;
207 84           break;
208 0           default:
209 0           croak("Impossible ix in _compress");
210             break;
211             }
212              
213 168           Newx(buffer, BUFFER_SIZE, uint8_t);
214 168 100         if(in == &PL_sv_undef)
215 84           next_in = (uint8_t*) buffer, available_in = 0;
216             else
217 84           next_in = (uint8_t*) SvPVbyte(in, available_in);
218 168           RETVAL = newSVpv("", 0);
219             while(1) {
220 168           next_out = buffer;
221 168           available_out = BUFFER_SIZE;
222 168           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 168 50         if(!result) {
230 0           Safefree(buffer);
231 0           croak("Error in BrotliEncoderCompressStream");
232             }
233              
234 168 100         if( available_out != BUFFER_SIZE ) {
235 104           sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
236             }
237              
238 168 100         if(
239 168           BrotliEncoderIsFinished(self->encoder) ||
240 84 50         (!available_in && !BrotliEncoderHasMoreOutput(self->encoder))
    50          
241             ) break;
242             }
243 168           Safefree(buffer);
244             OUTPUT:
245             RETVAL
246              
247             void
248             DESTROY(self)
249             IO::Compress::Brotli self
250             CODE:
251 84           BrotliEncoderDestroyInstance(self->encoder);
252 84           Safefree(self);