X-Git-Url: http://git.ieval.ro/?p=io-compress-brotli.git;a=blobdiff_plain;f=Brotli.xs;h=4e030a750b7cae5a5280c62bfe09b2029c765a2e;hp=c4660198661c43425f6498c351733c26e82b4875;hb=799b2a343f40ccc586481aa7b269da5f0abf513f;hpb=aaed23cfe7fa81d408dea0653bee3cbc908919b2 diff --git a/Brotli.xs b/Brotli.xs index c466019..4e030a7 100644 --- a/Brotli.xs +++ b/Brotli.xs @@ -5,49 +5,60 @@ #include "ppport.h" -#include -#include -#include +#include +#include #define BUFFER_SIZE 1048576 +typedef struct brotli_decoder { + BrotliDecoderState *decoder; +}* IO__Uncompress__Brotli; + +typedef struct brotli_encoder { + BrotliEncoderState *encoder; +}* IO__Compress__Brotli; + + MODULE = IO::Compress::Brotli PACKAGE = IO::Uncompress::Brotli PROTOTYPES: ENABLE -SV* unbro(buffer) +SV* +unbro_given_size(buffer, decoded_size) SV* buffer + size_t decoded_size PREINIT: - size_t decoded_size; STRLEN encoded_size; uint8_t *encoded_buffer, *decoded_buffer; CODE: encoded_buffer = (uint8_t*) SvPV(buffer, encoded_size); - if(!BrotliDecompressedSize(encoded_size, encoded_buffer, &decoded_size)){ - croak("Error in BrotliDecompressedSize"); - } - Newx(decoded_buffer, decoded_size+1, uint8_t); - decoded_buffer[decoded_size]=0; + Newx(decoded_buffer, decoded_size, uint8_t); if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){ croak("Error in BrotliDecoderDecompress"); } RETVAL = newSV(0); - sv_usepvn_flags(RETVAL, decoded_buffer, decoded_size, SV_HAS_TRAILING_NUL); + sv_usepvn(RETVAL, decoded_buffer, decoded_size); OUTPUT: RETVAL -SV* BrotliDecoderCreateInstance() +IO::Uncompress::Brotli +create(class) + SV* class CODE: - RETVAL = newSViv((IV)BrotliDecoderCreateInstance(NULL, NULL, NULL)); + Newx(RETVAL, 1, struct brotli_decoder); + RETVAL->decoder = BrotliDecoderCreateInstance(NULL, NULL, NULL); OUTPUT: RETVAL -void BrotliDecoderDestroyInstance(state) - SV* state +void +DESTROY(self) + IO::Uncompress::Brotli self CODE: - BrotliDecoderDestroyInstance((BrotliDecoderState*)SvIV(state)); + BrotliDecoderDestroyInstance(self->decoder); + Safefree(self); -SV* BrotliDecoderDecompressStream(state, in) - SV* state +SV* +decompress(self, in) + IO::Uncompress::Brotli self SV* in PREINIT: uint8_t *next_in, *next_out, *buffer; @@ -57,11 +68,11 @@ SV* BrotliDecoderDecompressStream(state, in) next_in = (uint8_t*) SvPV(in, available_in); Newx(buffer, BUFFER_SIZE, uint8_t); RETVAL = newSVpv("", 0); - result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; - while(result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; + while(result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { next_out = buffer; available_out=BUFFER_SIZE; - result = BrotliDecoderDecompressStream( (BrotliDecoderState*) SvIV(state), + result = BrotliDecoderDecompressStream( self->decoder, &available_in, (const uint8_t**) &next_in, &available_out, @@ -77,21 +88,12 @@ SV* BrotliDecoderDecompressStream(state, in) OUTPUT: RETVAL -void BrotliDecoderSetCustomDictionary(state, dict) - SV* state - SV* dict - PREINIT: - size_t size; - uint8_t *data; - CODE: - data = SvPV(dict, size); - BrotliDecoderSetCustomDictionary((BrotliDecoderState*) SvIV(state), size, data); - MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli PROTOTYPES: ENABLE -SV* bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW) +SV* +bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW) SV* buffer U32 quality U32 lgwin @@ -102,7 +104,10 @@ SV* bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW) BROTLI_BOOL result; CODE: if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) { - croak("Invalid quality value"); + croak("Invalid quality value"); + } + if( lgwin < BROTLI_MIN_WINDOW_BITS || lgwin > BROTLI_MAX_WINDOW_BITS ) { + croak("Invalid window value"); } decoded_buffer = (uint8_t*) SvPV(buffer, decoded_size); encoded_size = BrotliEncoderMaxCompressedSize(decoded_size); @@ -127,64 +132,94 @@ SV* bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW) OUTPUT: RETVAL -SV* BrotliEncoderCreateInstance() +IO::Compress::Brotli +create(class) + SV* class CODE: - RETVAL = newSViv((IV)BrotliEncoderCreateInstance(NULL, NULL, NULL)); + Newx(RETVAL, 1, struct brotli_encoder); + RETVAL->encoder = BrotliEncoderCreateInstance(NULL, NULL, NULL); OUTPUT: RETVAL -SV* BrotliEncoderSetWindow(state, window) - SV* state - U32 window - CODE: - if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_LGWIN, window) ) - RETVAL = newSVuv(1); - else - RETVAL = newSVuv(0); - OUTPUT: - RETVAL - -SV* BrotliEncoderSetQuality(state, quality) - SV* state - U32 quality - CODE: - if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) { - croak("Invalid quality value"); +bool BrotliEncoderSetParameter(self, value) + IO::Compress::Brotli self + U32 value + ALIAS: + window = 1 + quality = 2 + _mode = 3 + PREINIT: + BrotliEncoderParameter param; + INIT: + switch(ix){ + case 0: + croak("BrotliEncoderSetParameter may not be called directly"); + break; + case 1: + if( value < BROTLI_MIN_WINDOW_BITS || value > BROTLI_MAX_WINDOW_BITS ) { + croak("Invalid window value"); + } + param = BROTLI_PARAM_LGWIN; + break; + case 2: + if( value < BROTLI_MIN_QUALITY || value > BROTLI_MAX_QUALITY ) { + croak("Invalid quality value"); + } + param = BROTLI_PARAM_QUALITY; + break; + case 3: + /* Validation done on Perl side */ + param = BROTLI_PARAM_MODE; + break; + default: + croak("Impossible ix in BrotliEncoderSetParameter"); + break; } - if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_QUALITY, quality) ) - RETVAL = newSVuv(1); - else - RETVAL = newSVuv(0); - OUTPUT: - RETVAL + C_ARGS: + self->encoder, param, value -SV* BrotliEncoderSetMode(state, mode) - SV* state - U32 mode - CODE: - if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_MODE, mode) ) - RETVAL = newSVuv(1); - else - RETVAL = newSVuv(0); - OUTPUT: - RETVAL - -SV* BrotliEncoderCompressStream(state, in, op) - SV* state +SV* +_compress(self, in = &PL_sv_undef) + IO::Compress::Brotli self SV* in - U8 op + ALIAS: + compress = 1 + flush = 2 + finish = 3 PREINIT: uint8_t *next_in, *next_out, *buffer; size_t available_in, available_out; BROTLI_BOOL result; + BrotliEncoderOperation op; CODE: - next_in = (uint8_t*) SvPV(in, available_in); + switch(ix) { + case 0: + croak("_compress may not be called directly"); + break; + case 1: + op = BROTLI_OPERATION_PROCESS; + break; + case 2: + op = BROTLI_OPERATION_FLUSH; + break; + case 3: + op = BROTLI_OPERATION_FINISH; + break; + default: + croak("Impossible ix in _compress"); + break; + } + Newx(buffer, BUFFER_SIZE, uint8_t); + if(in == &PL_sv_undef) + next_in = (uint8_t*) buffer, available_in = 0; + else + next_in = (uint8_t*) SvPV(in, available_in); RETVAL = newSVpv("", 0); while(1) { next_out = buffer; available_out = BUFFER_SIZE; - result = BrotliEncoderCompressStream( (BrotliEncoderState*) SvIV(state), + result = BrotliEncoderCompressStream( self->encoder, (BrotliEncoderOperation) op, &available_in, (const uint8_t**) &next_in, @@ -201,25 +236,17 @@ SV* BrotliEncoderCompressStream(state, in, op) } if( - BrotliEncoderIsFinished((BrotliEncoderState*) SvIV(state)) || - (!available_in && !BrotliEncoderHasMoreOutput((BrotliEncoderState*) SvIV(state))) + BrotliEncoderIsFinished(self->encoder) || + (!available_in && !BrotliEncoderHasMoreOutput(self->encoder)) ) break; } Safefree(buffer); OUTPUT: RETVAL -void BrotliEncoderDestroyInstance(state) - SV* state - CODE: - BrotliEncoderDestroyInstance((BrotliEncoderState*)SvIV(state)); - -void BrotliEncoderSetCustomDictionary(state, dict) - SV* state - SV* dict - PREINIT: - size_t size; - uint8_t *data; +void +DESTROY(self) + IO::Compress::Brotli self CODE: - data = SvPV(dict, size); - BrotliEncoderSetCustomDictionary((BrotliEncoderState*) SvIV(state), size, data); + BrotliEncoderDestroyInstance(self->encoder); + Safefree(self);