File Coverage

Brotli.xs
Criterion Covered Total %
statement 59 83 71.0
branch 23 42 54.7
condition n/a
subroutine n/a
pod n/a
total 82 125 65.6


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