Update brotli to v0.6.0
[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
56bfd9c0
MG
8#include <brotli/decode.h>
9#include <brotli/encode.h>
f9995f31
MG
10
11#define BUFFER_SIZE 1048576
f9995f31 12
d3f7abb9
QR
13typedef struct brotli_decoder {
14 BrotliDecoderState *decoder;
15}* IO__Uncompress__Brotli;
16
17typedef struct brotli_encoder {
18 BrotliEncoderState *encoder;
19}* IO__Compress__Brotli;
20
21
f9995f31
MG
22MODULE = IO::Compress::Brotli PACKAGE = IO::Uncompress::Brotli
23PROTOTYPES: ENABLE
24
d3f7abb9 25SV*
56bfd9c0 26unbro(buffer, decoded_size)
f9995f31 27 SV* buffer
56bfd9c0 28 size_t decoded_size
f9995f31 29 PREINIT:
f9995f31
MG
30 STRLEN encoded_size;
31 uint8_t *encoded_buffer, *decoded_buffer;
32 CODE:
33 encoded_buffer = (uint8_t*) SvPV(buffer, encoded_size);
56bfd9c0 34 Newx(decoded_buffer, decoded_size, uint8_t);
ea94b872
QR
35 if(!BrotliDecoderDecompress(encoded_size, encoded_buffer, &decoded_size, decoded_buffer)){
36 croak("Error in BrotliDecoderDecompress");
f9995f31
MG
37 }
38 RETVAL = newSV(0);
56bfd9c0 39 sv_usepvn(RETVAL, decoded_buffer, decoded_size);
f9995f31
MG
40 OUTPUT:
41 RETVAL
42
d3f7abb9
QR
43IO::Uncompress::Brotli
44create(class)
45 SV* class
f9995f31 46 CODE:
d3f7abb9
QR
47 Newx(RETVAL, 1, struct brotli_decoder);
48 RETVAL->decoder = BrotliDecoderCreateInstance(NULL, NULL, NULL);
f9995f31
MG
49 OUTPUT:
50 RETVAL
51
d3f7abb9
QR
52void
53DESTROY(self)
54 IO::Uncompress::Brotli self
f9995f31 55 CODE:
d3f7abb9
QR
56 BrotliDecoderDestroyInstance(self->decoder);
57 Safefree(self);
f9995f31 58
d3f7abb9
QR
59SV*
60decompress(self, in)
61 IO::Uncompress::Brotli self
f9995f31
MG
62 SV* in
63 PREINIT:
261eae0a 64 uint8_t *next_in, *next_out, *buffer;
29037568 65 size_t available_in, available_out;
ea94b872 66 BrotliDecoderResult result;
f9995f31
MG
67 CODE:
68 next_in = (uint8_t*) SvPV(in, available_in);
261eae0a 69 Newx(buffer, BUFFER_SIZE, uint8_t);
f9995f31 70 RETVAL = newSVpv("", 0);
56bfd9c0
MG
71 result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
72 while(result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
f9995f31
MG
73 next_out = buffer;
74 available_out=BUFFER_SIZE;
d3f7abb9 75 result = BrotliDecoderDecompressStream( self->decoder,
782ccd86
QR
76 &available_in,
77 (const uint8_t**) &next_in,
78 &available_out,
79 &next_out,
29037568 80 NULL );
f9995f31 81 if(!result){
261eae0a
QR
82 Safefree(buffer);
83 croak("Error in BrotliDecoderDecompressStream");
f9995f31
MG
84 }
85 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
86 }
261eae0a 87 Safefree(buffer);
f9995f31
MG
88 OUTPUT:
89 RETVAL
90
d3f7abb9
QR
91void
92set_dictionary(self, dict)
93 IO::Uncompress::Brotli self
f9995f31
MG
94 SV* dict
95 PREINIT:
96 size_t size;
97 uint8_t *data;
98 CODE:
99 data = SvPV(dict, size);
d3f7abb9 100 BrotliDecoderSetCustomDictionary(self->decoder, size, data);
09cf7186
QR
101
102
103MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli
104PROTOTYPES: ENABLE
105
d3f7abb9
QR
106SV*
107bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW)
09cf7186
QR
108 SV* buffer
109 U32 quality
110 U32 lgwin
111 PREINIT:
112 size_t encoded_size;
113 STRLEN decoded_size;
114 uint8_t *encoded_buffer, *decoded_buffer;
115 BROTLI_BOOL result;
116 CODE:
117 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
9d6eec24
QR
118 croak("Invalid quality value");
119 }
56bfd9c0 120 if( lgwin < BROTLI_MIN_WINDOW_BITS || lgwin > BROTLI_MAX_WINDOW_BITS ) {
9d6eec24 121 croak("Invalid window value");
09cf7186
QR
122 }
123 decoded_buffer = (uint8_t*) SvPV(buffer, decoded_size);
124 encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
125 if(!encoded_size){
126 croak("Compressed size overflow");
127 }
128 Newx(encoded_buffer, encoded_size+1, uint8_t);
129 result = BrotliEncoderCompress( quality,
130 lgwin,
131 BROTLI_DEFAULT_MODE,
132 decoded_size,
133 decoded_buffer,
134 &encoded_size,
135 encoded_buffer );
136 if(!result){
aaed23cf 137 Safefree(buffer);
09cf7186
QR
138 croak("Error in BrotliEncoderCompress");
139 }
140 encoded_buffer[encoded_size]=0;
141 RETVAL = newSV(0);
142 sv_usepvn_flags(RETVAL, encoded_buffer, encoded_size, SV_SMAGIC | SV_HAS_TRAILING_NUL);
143 OUTPUT:
144 RETVAL
145
d3f7abb9
QR
146IO::Compress::Brotli
147create(class)
148 SV* class
09cf7186 149 CODE:
d3f7abb9
QR
150 Newx(RETVAL, 1, struct brotli_encoder);
151 RETVAL->encoder = BrotliEncoderCreateInstance(NULL, NULL, NULL);
09cf7186
QR
152 OUTPUT:
153 RETVAL
154
2574e61c 155bool BrotliEncoderSetParameter(self, value)
d3f7abb9 156 IO::Compress::Brotli self
2574e61c
MG
157 U32 value
158 ALIAS:
159 window = 1
160 quality = 2
161 _mode = 3
162 PREINIT:
163 BrotliEncoderParameter param;
164 INIT:
165 switch(ix){
166 case 0:
167 croak("BrotliEncoderSetParameter may not be called directly");
168 break;
169 case 1:
56bfd9c0 170 if( value < BROTLI_MIN_WINDOW_BITS || value > BROTLI_MAX_WINDOW_BITS ) {
2574e61c
MG
171 croak("Invalid window value");
172 }
173 param = BROTLI_PARAM_LGWIN;
174 break;
175 case 2:
176 if( value < BROTLI_MIN_QUALITY || value > BROTLI_MAX_QUALITY ) {
177 croak("Invalid quality value");
178 }
179 param = BROTLI_PARAM_QUALITY;
180 break;
181 case 3:
182 /* Validation done on Perl side */
183 param = BROTLI_PARAM_MODE;
184 break;
185 default:
186 croak("Impossible ix in BrotliEncoderSetParameter");
187 break;
09cf7186 188 }
2574e61c
MG
189 C_ARGS:
190 self->encoder, param, value
09cf7186 191
0cea41a5 192SV*
bcdfc2c8 193_compress(self, in = &PL_sv_undef)
0cea41a5
ÆAB
194 IO::Compress::Brotli self
195 SV* in
bcdfc2c8
MG
196 ALIAS:
197 compress = 1
198 flush = 2
199 finish = 3
09cf7186
QR
200 PREINIT:
201 uint8_t *next_in, *next_out, *buffer;
202 size_t available_in, available_out;
203 BROTLI_BOOL result;
bcdfc2c8 204 BrotliEncoderOperation op;
09cf7186 205 CODE:
bcdfc2c8
MG
206 switch(ix) {
207 case 0:
208 croak("_compress may not be called directly");
209 break;
210 case 1:
211 op = BROTLI_OPERATION_PROCESS;
212 break;
213 case 2:
214 op = BROTLI_OPERATION_FLUSH;
215 break;
216 case 3:
217 op = BROTLI_OPERATION_FINISH;
218 break;
219 default:
220 croak("Impossible ix in _compress");
221 break;
222 }
223
09cf7186 224 Newx(buffer, BUFFER_SIZE, uint8_t);
bcdfc2c8
MG
225 if(in == &PL_sv_undef)
226 next_in = (uint8_t*) buffer, available_in = 0;
227 else
228 next_in = (uint8_t*) SvPV(in, available_in);
09cf7186
QR
229 RETVAL = newSVpv("", 0);
230 while(1) {
231 next_out = buffer;
232 available_out = BUFFER_SIZE;
d3f7abb9 233 result = BrotliEncoderCompressStream( self->encoder,
09cf7186
QR
234 (BrotliEncoderOperation) op,
235 &available_in,
236 (const uint8_t**) &next_in,
237 &available_out,
238 &next_out,
239 NULL );
240 if(!result) {
241 Safefree(buffer);
242 croak("Error in BrotliEncoderCompressStream");
243 }
244
245 if( available_out != BUFFER_SIZE ) {
246 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
247 }
248
249 if(
d3f7abb9
QR
250 BrotliEncoderIsFinished(self->encoder) ||
251 (!available_in && !BrotliEncoderHasMoreOutput(self->encoder))
09cf7186
QR
252 ) break;
253 }
254 Safefree(buffer);
255 OUTPUT:
256 RETVAL
257
d3f7abb9
QR
258void
259DESTROY(self)
260 IO::Compress::Brotli self
09cf7186 261 CODE:
d3f7abb9 262 BrotliEncoderDestroyInstance(self->encoder);
21c71a39 263 Safefree(self);
09cf7186 264
d3f7abb9
QR
265void
266set_dictionary(self, dict)
267 IO::Compress::Brotli self
09cf7186
QR
268 SV* dict
269 PREINIT:
270 size_t size;
271 uint8_t *data;
272 CODE:
273 data = SvPV(dict, size);
d3f7abb9 274 BrotliEncoderSetCustomDictionary(self->encoder, size, data);
This page took 0.029499 seconds and 4 git commands to generate.