Fix leak of encoded_buffer on bro() spotted by mattia
[io-compress-brotli.git] / Brotli.xs
CommitLineData
f9995f31
MG
1#define PERL_NO_GET_CONTEXT
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
6#include "ppport.h"
7
8#include <dec/decode.h>
09cf7186 9#include <enc/encode.h>
fd0f6b13 10#include <common/dictionary.h>
f9995f31
MG
11
12#define BUFFER_SIZE 1048576
f9995f31
MG
13
14MODULE = IO::Compress::Brotli PACKAGE = IO::Uncompress::Brotli
15PROTOTYPES: ENABLE
16
17SV* unbro(buffer)
18 SV* buffer
19 PREINIT:
20 size_t decoded_size;
21 STRLEN encoded_size;
22 uint8_t *encoded_buffer, *decoded_buffer;
23 CODE:
24 encoded_buffer = (uint8_t*) SvPV(buffer, encoded_size);
25 if(!BrotliDecompressedSize(encoded_size, encoded_buffer, &decoded_size)){
26 croak("Error in BrotliDecompressedSize");
27 }
28 Newx(decoded_buffer, decoded_size+1, uint8_t);
29 decoded_buffer[decoded_size]=0;
ea94b872
QR
30 if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){
31 croak("Error in BrotliDecoderDecompress");
f9995f31
MG
32 }
33 RETVAL = newSV(0);
34 sv_usepvn_flags(RETVAL, decoded_buffer, decoded_size, SV_HAS_TRAILING_NUL);
35 OUTPUT:
36 RETVAL
37
ea94b872 38SV* BrotliDecoderCreateInstance()
f9995f31 39 CODE:
ea94b872 40 RETVAL = newSViv((IV)BrotliDecoderCreateInstance(NULL, NULL, NULL));
f9995f31
MG
41 OUTPUT:
42 RETVAL
43
ea94b872 44void BrotliDecoderDestroyInstance(state)
f9995f31
MG
45 SV* state
46 CODE:
ea94b872 47 BrotliDecoderDestroyInstance((BrotliDecoderState*)SvIV(state));
f9995f31 48
ea94b872 49SV* BrotliDecoderDecompressStream(state, in)
f9995f31
MG
50 SV* state
51 SV* in
52 PREINIT:
261eae0a 53 uint8_t *next_in, *next_out, *buffer;
29037568 54 size_t available_in, available_out;
ea94b872 55 BrotliDecoderResult result;
f9995f31
MG
56 CODE:
57 next_in = (uint8_t*) SvPV(in, available_in);
261eae0a 58 Newx(buffer, BUFFER_SIZE, uint8_t);
f9995f31
MG
59 RETVAL = newSVpv("", 0);
60 result = BROTLI_RESULT_NEEDS_MORE_OUTPUT;
61 while(result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) {
62 next_out = buffer;
63 available_out=BUFFER_SIZE;
782ccd86
QR
64 result = BrotliDecoderDecompressStream( (BrotliDecoderState*) SvIV(state),
65 &available_in,
66 (const uint8_t**) &next_in,
67 &available_out,
68 &next_out,
29037568 69 NULL );
f9995f31 70 if(!result){
261eae0a
QR
71 Safefree(buffer);
72 croak("Error in BrotliDecoderDecompressStream");
f9995f31
MG
73 }
74 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
75 }
261eae0a 76 Safefree(buffer);
f9995f31
MG
77 OUTPUT:
78 RETVAL
79
5f975f9c 80void BrotliDecoderSetCustomDictionary(state, dict)
f9995f31
MG
81 SV* state
82 SV* dict
83 PREINIT:
84 size_t size;
85 uint8_t *data;
86 CODE:
87 data = SvPV(dict, size);
ea94b872 88 BrotliDecoderSetCustomDictionary((BrotliDecoderState*) SvIV(state), size, data);
09cf7186
QR
89
90
91MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli
92PROTOTYPES: ENABLE
93
94SV* bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW)
95 SV* buffer
96 U32 quality
97 U32 lgwin
98 PREINIT:
99 size_t encoded_size;
100 STRLEN decoded_size;
101 uint8_t *encoded_buffer, *decoded_buffer;
102 BROTLI_BOOL result;
103 CODE:
104 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
105 croak("Invalid quality value");
106 }
107 decoded_buffer = (uint8_t*) SvPV(buffer, decoded_size);
108 encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
109 if(!encoded_size){
110 croak("Compressed size overflow");
111 }
112 Newx(encoded_buffer, encoded_size+1, uint8_t);
113 result = BrotliEncoderCompress( quality,
114 lgwin,
115 BROTLI_DEFAULT_MODE,
116 decoded_size,
117 decoded_buffer,
118 &encoded_size,
119 encoded_buffer );
120 if(!result){
aaed23cf 121 Safefree(buffer);
09cf7186
QR
122 croak("Error in BrotliEncoderCompress");
123 }
124 encoded_buffer[encoded_size]=0;
125 RETVAL = newSV(0);
126 sv_usepvn_flags(RETVAL, encoded_buffer, encoded_size, SV_SMAGIC | SV_HAS_TRAILING_NUL);
127 OUTPUT:
128 RETVAL
129
130SV* BrotliEncoderCreateInstance()
131 CODE:
132 RETVAL = newSViv((IV)BrotliEncoderCreateInstance(NULL, NULL, NULL));
133 OUTPUT:
134 RETVAL
135
136SV* BrotliEncoderSetWindow(state, window)
137 SV* state
138 U32 window
139 CODE:
140 if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_LGWIN, window) )
141 RETVAL = newSVuv(1);
142 else
143 RETVAL = newSVuv(0);
144 OUTPUT:
145 RETVAL
146
147SV* BrotliEncoderSetQuality(state, quality)
148 SV* state
149 U32 quality
150 CODE:
151 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
152 croak("Invalid quality value");
153 }
154 if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_QUALITY, quality) )
155 RETVAL = newSVuv(1);
156 else
157 RETVAL = newSVuv(0);
158 OUTPUT:
159 RETVAL
160
161SV* BrotliEncoderSetMode(state, mode)
162 SV* state
163 U32 mode
164 CODE:
165 if( BrotliEncoderSetParameter((BrotliEncoderState*) SvIV(state), BROTLI_PARAM_MODE, mode) )
166 RETVAL = newSVuv(1);
167 else
168 RETVAL = newSVuv(0);
169 OUTPUT:
170 RETVAL
171
172SV* BrotliEncoderCompressStream(state, in, op)
173 SV* state
174 SV* in
175 U8 op
176 PREINIT:
177 uint8_t *next_in, *next_out, *buffer;
178 size_t available_in, available_out;
179 BROTLI_BOOL result;
180 CODE:
181 next_in = (uint8_t*) SvPV(in, available_in);
182 Newx(buffer, BUFFER_SIZE, uint8_t);
183 RETVAL = newSVpv("", 0);
184 while(1) {
185 next_out = buffer;
186 available_out = BUFFER_SIZE;
187 result = BrotliEncoderCompressStream( (BrotliEncoderState*) SvIV(state),
188 (BrotliEncoderOperation) op,
189 &available_in,
190 (const uint8_t**) &next_in,
191 &available_out,
192 &next_out,
193 NULL );
194 if(!result) {
195 Safefree(buffer);
196 croak("Error in BrotliEncoderCompressStream");
197 }
198
199 if( available_out != BUFFER_SIZE ) {
200 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
201 }
202
203 if(
204 BrotliEncoderIsFinished((BrotliEncoderState*) SvIV(state)) ||
205 (!available_in && !BrotliEncoderHasMoreOutput((BrotliEncoderState*) SvIV(state)))
206 ) break;
207 }
208 Safefree(buffer);
209 OUTPUT:
210 RETVAL
211
212void BrotliEncoderDestroyInstance(state)
213 SV* state
214 CODE:
215 BrotliEncoderDestroyInstance((BrotliEncoderState*)SvIV(state));
216
217void BrotliEncoderSetCustomDictionary(state, dict)
218 SV* state
219 SV* dict
220 PREINIT:
221 size_t size;
222 uint8_t *data;
223 CODE:
224 data = SvPV(dict, size);
225 BrotliEncoderSetCustomDictionary((BrotliEncoderState*) SvIV(state), size, data);
This page took 0.023368 seconds and 4 git commands to generate.