Use typemaps instead of manually managing the SVs
authorQuim Rovira <quim@rovira.cat>
Tue, 16 Aug 2016 21:40:55 +0000 (23:40 +0200)
committerQuim Rovira <quim@rovira.cat>
Tue, 16 Aug 2016 21:43:51 +0000 (23:43 +0200)
Æ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
MANIFEST
lib/IO/Compress/Brotli.pm
lib/IO/Uncompress/Brotli.pm
typemap [new file with mode: 0644]

index 8de3dd525c6cf371c2fce2cde24096e05b7d829a..dff0a63f3b6017564e51b6582f683e28bcb19053 100644 (file)
--- a/Brotli.xs
+++ b/Brotli.xs
 
 #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);
+
index 4c2ccc217e67461fda65a255e3273ba6b0cc5955..cfb48b196392d616f00e62c0664899b415758702 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -178,3 +178,4 @@ ppport.h
 t/00-load.t
 t/01-uncompress.t
 t/02-roundtrip.t
+typemap
index 9117f704d3a571aa8cfd238d0435b8843fb17ccb..ed7fbf43e4f87c85513a1ef928590f7bec262204 100644 (file)
@@ -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;
index f4b8bdb0eb6f566d2fbd9c68783eaa48a49c5b8e..f4230ef2650670b63c7af8c99b94dcc5766aea6c 100644 (file)
@@ -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 (file)
index 0000000..196ec90
--- /dev/null
+++ b/typemap
@@ -0,0 +1,2 @@
+IO::Compress::Brotli    T_PTROBJ
+IO::Uncompress::Brotli  T_PTROBJ
This page took 0.017615 seconds and 4 git commands to generate.