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