1 #define PERL_NO_GET_CONTEXT
8 #include <dec/decode.h>
9 #include <enc/encode.h>
10 #include <common/dictionary.h>
12 #define BUFFER_SIZE 1048576
14 typedef struct brotli_decoder {
15 BrotliDecoderState *decoder;
16 }* IO__Uncompress__Brotli;
18 typedef struct brotli_encoder {
19 BrotliEncoderState *encoder;
20 }* IO__Compress__Brotli;
23 MODULE = IO::Compress::Brotli PACKAGE = IO::Uncompress::Brotli
32 uint8_t *encoded_buffer, *decoded_buffer;
34 encoded_buffer = (uint8_t*) SvPV(buffer, encoded_size);
35 if(!BrotliDecompressedSize(encoded_size, encoded_buffer, &decoded_size)){
36 croak("Error in BrotliDecompressedSize");
38 Newx(decoded_buffer, decoded_size+1, uint8_t);
39 decoded_buffer[decoded_size]=0;
40 if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){
41 croak("Error in BrotliDecoderDecompress");
44 sv_usepvn_flags(RETVAL, decoded_buffer, decoded_size, SV_HAS_TRAILING_NUL);
48 IO::Uncompress::Brotli
52 Newx(RETVAL, 1, struct brotli_decoder);
53 RETVAL->decoder = BrotliDecoderCreateInstance(NULL, NULL, NULL);
59 IO::Uncompress::Brotli self
61 BrotliDecoderDestroyInstance(self->decoder);
66 IO::Uncompress::Brotli self
69 uint8_t *next_in, *next_out, *buffer;
70 size_t available_in, available_out;
71 BrotliDecoderResult result;
73 next_in = (uint8_t*) SvPV(in, available_in);
74 Newx(buffer, BUFFER_SIZE, uint8_t);
75 RETVAL = newSVpv("", 0);
76 result = BROTLI_RESULT_NEEDS_MORE_OUTPUT;
77 while(result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) {
79 available_out=BUFFER_SIZE;
80 result = BrotliDecoderDecompressStream( self->decoder,
82 (const uint8_t**) &next_in,
88 croak("Error in BrotliDecoderDecompressStream");
90 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
97 set_dictionary(self, dict)
98 IO::Uncompress::Brotli self
104 data = SvPV(dict, size);
105 BrotliDecoderSetCustomDictionary(self->decoder, size, data);
108 MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli
112 bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW)
119 uint8_t *encoded_buffer, *decoded_buffer;
122 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
123 croak("Invalid quality value");
125 if( lgwin < kBrotliMinWindowBits || lgwin > kBrotliMaxWindowBits ) {
126 croak("Invalid window value");
128 decoded_buffer = (uint8_t*) SvPV(buffer, decoded_size);
129 encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
131 croak("Compressed size overflow");
133 Newx(encoded_buffer, encoded_size+1, uint8_t);
134 result = BrotliEncoderCompress( quality,
143 croak("Error in BrotliEncoderCompress");
145 encoded_buffer[encoded_size]=0;
147 sv_usepvn_flags(RETVAL, encoded_buffer, encoded_size, SV_SMAGIC | SV_HAS_TRAILING_NUL);
155 Newx(RETVAL, 1, struct brotli_encoder);
156 RETVAL->encoder = BrotliEncoderCreateInstance(NULL, NULL, NULL);
162 IO::Compress::Brotli self
165 if( window < kBrotliMinWindowBits || window > kBrotliMaxWindowBits ) {
166 croak("Invalid window value");
168 if( BrotliEncoderSetParameter(self->encoder, BROTLI_PARAM_LGWIN, window) )
176 quality(self, quality)
177 IO::Compress::Brotli self
180 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
181 croak("Invalid quality value");
183 if( BrotliEncoderSetParameter(self->encoder, BROTLI_PARAM_QUALITY, quality) )
192 IO::Compress::Brotli self
195 if( BrotliEncoderSetParameter(self->encoder, BROTLI_PARAM_MODE, mode) )
204 IO::Compress::Brotli self
213 XPUSHs(newSVuv(BROTLI_OPERATION_PROCESS));
216 call_method("_compress", G_SCALAR);
221 SvREFCNT_inc(RETVAL);
231 IO::Compress::Brotli self
238 XPUSHs(newSVpv("", 0));
239 XPUSHs(newSVuv(BROTLI_OPERATION_FLUSH));
242 call_method("_compress", G_SCALAR);
247 SvREFCNT_inc(RETVAL);
257 IO::Compress::Brotli self
264 XPUSHs(newSVpv("", 0));
265 XPUSHs(newSVuv(BROTLI_OPERATION_FINISH));
268 call_method("_compress", G_SCALAR);
273 SvREFCNT_inc(RETVAL);
282 _compress(self, in, op)
283 IO::Compress::Brotli self
287 uint8_t *next_in, *next_out, *buffer;
288 size_t available_in, available_out;
291 next_in = (uint8_t*) SvPV(in, available_in);
292 Newx(buffer, BUFFER_SIZE, uint8_t);
293 RETVAL = newSVpv("", 0);
296 available_out = BUFFER_SIZE;
297 result = BrotliEncoderCompressStream( self->encoder,
298 (BrotliEncoderOperation) op,
300 (const uint8_t**) &next_in,
306 croak("Error in BrotliEncoderCompressStream");
309 if( available_out != BUFFER_SIZE ) {
310 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
314 BrotliEncoderIsFinished(self->encoder) ||
315 (!available_in && !BrotliEncoderHasMoreOutput(self->encoder))
324 IO::Compress::Brotli self
326 BrotliEncoderDestroyInstance(self->encoder);
329 set_dictionary(self, dict)
330 IO::Compress::Brotli self
336 data = SvPV(dict, size);
337 BrotliEncoderSetCustomDictionary(self->encoder, size, data);