1 #define PERL_NO_GET_CONTEXT
8 #include <brotli/decode.h>
9 #include <brotli/encode.h>
11 #define BUFFER_SIZE 1048576
13 typedef struct brotli_decoder {
14 BrotliDecoderState *decoder;
15 }* IO__Uncompress__Brotli;
17 typedef struct brotli_encoder {
18 BrotliEncoderState *encoder;
19 }* IO__Compress__Brotli;
22 MODULE = IO::Compress::Brotli PACKAGE = IO::Uncompress::Brotli
26 unbro_given_size(buffer, decoded_size)
31 uint8_t *encoded_buffer, *decoded_buffer;
33 encoded_buffer = (uint8_t*) SvPV(buffer, encoded_size);
34 Newx(decoded_buffer, decoded_size, uint8_t);
35 if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){
36 croak("Error in BrotliDecoderDecompress");
39 sv_usepvn(RETVAL, decoded_buffer, decoded_size);
43 IO::Uncompress::Brotli
47 Newx(RETVAL, 1, struct brotli_decoder);
48 RETVAL->decoder = BrotliDecoderCreateInstance(NULL, NULL, NULL);
54 IO::Uncompress::Brotli self
56 BrotliDecoderDestroyInstance(self->decoder);
61 IO::Uncompress::Brotli self
64 uint8_t *next_in, *next_out, *buffer;
65 size_t available_in, available_out;
66 BrotliDecoderResult result;
68 next_in = (uint8_t*) SvPV(in, available_in);
69 Newx(buffer, BUFFER_SIZE, uint8_t);
70 RETVAL = newSVpv("", 0);
71 result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
72 while(result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
74 available_out=BUFFER_SIZE;
75 result = BrotliDecoderDecompressStream( self->decoder,
77 (const uint8_t**) &next_in,
83 croak("Error in BrotliDecoderDecompressStream");
85 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
92 MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli
96 bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW)
103 uint8_t *encoded_buffer, *decoded_buffer;
106 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
107 croak("Invalid quality value");
109 if( lgwin < BROTLI_MIN_WINDOW_BITS || lgwin > BROTLI_MAX_WINDOW_BITS ) {
110 croak("Invalid window value");
112 decoded_buffer = (uint8_t*) SvPV(buffer, decoded_size);
113 encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
115 croak("Compressed size overflow");
117 Newx(encoded_buffer, encoded_size+1, uint8_t);
118 result = BrotliEncoderCompress( quality,
127 croak("Error in BrotliEncoderCompress");
129 encoded_buffer[encoded_size]=0;
131 sv_usepvn_flags(RETVAL, encoded_buffer, encoded_size, SV_SMAGIC | SV_HAS_TRAILING_NUL);
139 Newx(RETVAL, 1, struct brotli_encoder);
140 RETVAL->encoder = BrotliEncoderCreateInstance(NULL, NULL, NULL);
144 bool BrotliEncoderSetParameter(self, value)
145 IO::Compress::Brotli self
152 BrotliEncoderParameter param;
156 croak("BrotliEncoderSetParameter may not be called directly");
159 if( value < BROTLI_MIN_WINDOW_BITS || value > BROTLI_MAX_WINDOW_BITS ) {
160 croak("Invalid window value");
162 param = BROTLI_PARAM_LGWIN;
165 if( value < BROTLI_MIN_QUALITY || value > BROTLI_MAX_QUALITY ) {
166 croak("Invalid quality value");
168 param = BROTLI_PARAM_QUALITY;
171 /* Validation done on Perl side */
172 param = BROTLI_PARAM_MODE;
175 croak("Impossible ix in BrotliEncoderSetParameter");
179 self->encoder, param, value
182 _compress(self, in = &PL_sv_undef)
183 IO::Compress::Brotli self
190 uint8_t *next_in, *next_out, *buffer;
191 size_t available_in, available_out;
193 BrotliEncoderOperation op;
197 croak("_compress may not be called directly");
200 op = BROTLI_OPERATION_PROCESS;
203 op = BROTLI_OPERATION_FLUSH;
206 op = BROTLI_OPERATION_FINISH;
209 croak("Impossible ix in _compress");
213 Newx(buffer, BUFFER_SIZE, uint8_t);
214 if(in == &PL_sv_undef)
215 next_in = (uint8_t*) buffer, available_in = 0;
217 next_in = (uint8_t*) SvPV(in, available_in);
218 RETVAL = newSVpv("", 0);
221 available_out = BUFFER_SIZE;
222 result = BrotliEncoderCompressStream( self->encoder,
223 (BrotliEncoderOperation) op,
225 (const uint8_t**) &next_in,
231 croak("Error in BrotliEncoderCompressStream");
234 if( available_out != BUFFER_SIZE ) {
235 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
239 BrotliEncoderIsFinished(self->encoder) ||
240 (!available_in && !BrotliEncoderHasMoreOutput(self->encoder))
249 IO::Compress::Brotli self
251 BrotliEncoderDestroyInstance(self->encoder);