From d3f7abb9b3f9f7d60a2de0f5018b837b2db4ba4f Mon Sep 17 00:00:00 2001 From: Quim Rovira Date: Tue, 16 Aug 2016 23:40:55 +0200 Subject: [PATCH] Use typemaps instead of manually managing the SVs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Ævar suggested that using typemaps quite a bit of code could be cleaned up and have some of the default sanity checks for free (see generated C code in Brotli.c). This also allows removing some of the perl sub wrappers, althought there are some more cleanups that could be done on that, and the impact is arguably low-to-none. --- Brotli.xs | 98 ++++++++++++++++++++++++------------- MANIFEST | 1 + lib/IO/Compress/Brotli.pm | 35 ++----------- lib/IO/Uncompress/Brotli.pm | 22 --------- typemap | 2 + 5 files changed, 70 insertions(+), 88 deletions(-) create mode 100644 typemap diff --git a/Brotli.xs b/Brotli.xs index 8de3dd5..dff0a63 100644 --- a/Brotli.xs +++ b/Brotli.xs @@ -11,10 +11,20 @@ #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(buffer) SV* buffer PREINIT: size_t decoded_size; @@ -35,19 +45,25 @@ SV* unbro(buffer) 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; @@ -61,7 +77,7 @@ SV* BrotliDecoderDecompressStream(state, in) while(result == BROTLI_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 +93,23 @@ SV* BrotliDecoderDecompressStream(state, in) OUTPUT: RETVAL -void BrotliDecoderSetCustomDictionary(state, dict) - SV* state +void +set_dictionary(self, dict) + IO::Uncompress::Brotli self SV* dict PREINIT: size_t size; uint8_t *data; CODE: data = SvPV(dict, size); - BrotliDecoderSetCustomDictionary((BrotliDecoderState*) SvIV(state), size, data); + BrotliDecoderSetCustomDictionary(self->decoder, 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 @@ -130,53 +148,60 @@ 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 +SV* +window(self, window) + IO::Compress::Brotli self U32 window CODE: if( window < kBrotliMinWindowBits || window > kBrotliMaxWindowBits ) { croak("Invalid window value"); } - if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_LGWIN, window) ) + if( BrotliEncoderSetParameter(self->encoder, BROTLI_PARAM_LGWIN, window) ) RETVAL = newSVuv(1); else RETVAL = newSVuv(0); OUTPUT: RETVAL -SV* BrotliEncoderSetQuality(state, quality) - SV* state +SV* +quality(self, quality) + IO::Compress::Brotli self U32 quality CODE: if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) { croak("Invalid quality value"); } - if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_QUALITY, quality) ) + if( BrotliEncoderSetParameter(self->encoder, BROTLI_PARAM_QUALITY, quality) ) RETVAL = newSVuv(1); else RETVAL = newSVuv(0); OUTPUT: RETVAL -SV* BrotliEncoderSetMode(state, mode) - SV* state +SV* +_mode(self, mode) + IO::Compress::Brotli self U32 mode CODE: - if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_MODE, mode) ) + if( BrotliEncoderSetParameter(self->encoder, BROTLI_PARAM_MODE, mode) ) RETVAL = newSVuv(1); else RETVAL = newSVuv(0); OUTPUT: RETVAL -SV* BrotliEncoderCompressStream(state, in, op) - SV* state +SV* +_compress(self, in, op) + IO::Compress::Brotli self SV* in U8 op PREINIT: @@ -190,7 +215,7 @@ SV* BrotliEncoderCompressStream(state, in, op) 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, @@ -207,25 +232,28 @@ 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 +void +DESTROY(self) + IO::Compress::Brotli self CODE: - BrotliEncoderDestroyInstance((BrotliEncoderState*)SvIV(state)); + BrotliEncoderDestroyInstance(self->encoder); -void BrotliEncoderSetCustomDictionary(state, dict) - SV* state +void +set_dictionary(self, dict) + IO::Compress::Brotli self SV* dict PREINIT: size_t size; uint8_t *data; CODE: data = SvPV(dict, size); - BrotliEncoderSetCustomDictionary((BrotliEncoderState*) SvIV(state), size, data); + BrotliEncoderSetCustomDictionary(self->encoder, size, data); + diff --git a/MANIFEST b/MANIFEST index 4c2ccc2..cfb48b1 100644 --- a/MANIFEST +++ b/MANIFEST @@ -178,3 +178,4 @@ ppport.h t/00-load.t t/01-uncompress.t t/02-roundtrip.t +typemap diff --git a/lib/IO/Compress/Brotli.pm b/lib/IO/Compress/Brotli.pm index 9117f70..ed7fbf4 100644 --- a/lib/IO/Compress/Brotli.pm +++ b/lib/IO/Compress/Brotli.pm @@ -13,27 +13,6 @@ our @EXPORT_OK = @EXPORT; our $VERSION = '0.001001'; -sub create { - my ($class) = @_; - my $state = BrotliEncoderCreateInstance(); - bless \$state, $class -} - -sub DESTROY { - my ($self) = @_; - BrotliEncoderDestroyInstance($$self) -} - -sub quality { - my ($self, $quality) = @_; - BrotliEncoderSetQuality($$self, $quality) -} - -sub window { - my ($self, $window) = @_; - BrotliEncoderSetWindow($$self, $window) -} - my %BROTLI_ENCODER_MODE = ( generic => 0, text => 1, font => 2 ); sub mode { my ($self, $mode) = @_; @@ -41,7 +20,7 @@ sub mode { die "Invalid encoder mode" unless $BROTLI_ENCODER_MODE{$mode}; - BrotliEncoderSetMode($$self, $mode) + _mode($$self, $mode) } use constant { @@ -51,23 +30,17 @@ use constant { }; sub compress { my ($self, $data) = @_; - BrotliEncoderCompressStream($$self, $data, BROTLI_OPERATION_PROCESS ) + $self->_compress($data, BROTLI_OPERATION_PROCESS ) } sub flush { my ($self) = @_; - BrotliEncoderCompressStream($$self, '', BROTLI_OPERATION_FLUSH ) + $self->_compress('', BROTLI_OPERATION_FLUSH ) } sub finish { my ($self) = @_; - BrotliEncoderCompressStream($$self, '', BROTLI_OPERATION_FINISH ) -} - -# Untested, probably not working -sub set_dictionary { - my ($self, $dict) = @_; - BrotliEncoderSetCustomDictionary($$self, $dict) + $self->_compress('', BROTLI_OPERATION_FINISH ) } 1; diff --git a/lib/IO/Uncompress/Brotli.pm b/lib/IO/Uncompress/Brotli.pm index f4b8bdb..f4230ef 100644 --- a/lib/IO/Uncompress/Brotli.pm +++ b/lib/IO/Uncompress/Brotli.pm @@ -13,28 +13,6 @@ our $VERSION = '0.001001'; require XSLoader; XSLoader::load('IO::Compress::Brotli', $VERSION); -sub create { - my ($class) = @_; - my $state = BrotliDecoderCreateInstance(); - bless \$state, $class -} - -sub DESTROY { - my ($self) = @_; - BrotliDecoderDestroyInstance($$self) -} - -sub decompress { - my ($self, $data) = @_; - BrotliDecoderDecompressStream($$self, $data) -} - -# Untested, probably not working -sub set_dictionary { - my ($self, $dict) = @_; - BrotliDecoderSetCustomDictionary($$self, $dict) -} - 1; __END__ diff --git a/typemap b/typemap new file mode 100644 index 0000000..196ec90 --- /dev/null +++ b/typemap @@ -0,0 +1,2 @@ +IO::Compress::Brotli T_PTROBJ +IO::Uncompress::Brotli T_PTROBJ -- 2.30.2