Replace File::Slurp with File::Slurper
[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
09cf7186
QR
91
92MODULE = IO::Compress::Brotli PACKAGE = IO::Compress::Brotli
93PROTOTYPES: ENABLE
94
d3f7abb9
QR
95SV*
96bro(buffer, quality=BROTLI_DEFAULT_QUALITY, lgwin=BROTLI_DEFAULT_WINDOW)
09cf7186
QR
97 SV* buffer
98 U32 quality
99 U32 lgwin
100 PREINIT:
101 size_t encoded_size;
102 STRLEN decoded_size;
103 uint8_t *encoded_buffer, *decoded_buffer;
104 BROTLI_BOOL result;
105 CODE:
106 if( quality < BROTLI_MIN_QUALITY || quality > BROTLI_MAX_QUALITY ) {
9d6eec24
QR
107 croak("Invalid quality value");
108 }
56bfd9c0 109 if( lgwin < BROTLI_MIN_WINDOW_BITS || lgwin > BROTLI_MAX_WINDOW_BITS ) {
9d6eec24 110 croak("Invalid window value");
09cf7186
QR
111 }
112 decoded_buffer = (uint8_t*) SvPV(buffer, decoded_size);
113 encoded_size = BrotliEncoderMaxCompressedSize(decoded_size);
114 if(!encoded_size){
115 croak("Compressed size overflow");
116 }
117 Newx(encoded_buffer, encoded_size+1, uint8_t);
118 result = BrotliEncoderCompress( quality,
119 lgwin,
120 BROTLI_DEFAULT_MODE,
121 decoded_size,
122 decoded_buffer,
123 &encoded_size,
124 encoded_buffer );
125 if(!result){
aaed23cf 126 Safefree(buffer);
09cf7186
QR
127 croak("Error in BrotliEncoderCompress");
128 }
129 encoded_buffer[encoded_size]=0;
130 RETVAL = newSV(0);
131 sv_usepvn_flags(RETVAL, encoded_buffer, encoded_size, SV_SMAGIC | SV_HAS_TRAILING_NUL);
132 OUTPUT:
133 RETVAL
134
d3f7abb9
QR
135IO::Compress::Brotli
136create(class)
137 SV* class
09cf7186 138 CODE:
d3f7abb9
QR
139 Newx(RETVAL, 1, struct brotli_encoder);
140 RETVAL->encoder = BrotliEncoderCreateInstance(NULL, NULL, NULL);
09cf7186
QR
141 OUTPUT:
142 RETVAL
143
2574e61c 144bool BrotliEncoderSetParameter(self, value)
d3f7abb9 145 IO::Compress::Brotli self
2574e61c
MG
146 U32 value
147 ALIAS:
148 window = 1
149 quality = 2
150 _mode = 3
151 PREINIT:
152 BrotliEncoderParameter param;
153 INIT:
154 switch(ix){
155 case 0:
156 croak("BrotliEncoderSetParameter may not be called directly");
157 break;
158 case 1:
56bfd9c0 159 if( value < BROTLI_MIN_WINDOW_BITS || value > BROTLI_MAX_WINDOW_BITS ) {
2574e61c
MG
160 croak("Invalid window value");
161 }
162 param = BROTLI_PARAM_LGWIN;
163 break;
164 case 2:
165 if( value < BROTLI_MIN_QUALITY || value > BROTLI_MAX_QUALITY ) {
166 croak("Invalid quality value");
167 }
168 param = BROTLI_PARAM_QUALITY;
169 break;
170 case 3:
171 /* Validation done on Perl side */
172 param = BROTLI_PARAM_MODE;
173 break;
174 default:
175 croak("Impossible ix in BrotliEncoderSetParameter");
176 break;
09cf7186 177 }
2574e61c
MG
178 C_ARGS:
179 self->encoder, param, value
09cf7186 180
0cea41a5 181SV*
bcdfc2c8 182_compress(self, in = &PL_sv_undef)
0cea41a5
ÆAB
183 IO::Compress::Brotli self
184 SV* in
bcdfc2c8
MG
185 ALIAS:
186 compress = 1
187 flush = 2
188 finish = 3
09cf7186
QR
189 PREINIT:
190 uint8_t *next_in, *next_out, *buffer;
191 size_t available_in, available_out;
192 BROTLI_BOOL result;
bcdfc2c8 193 BrotliEncoderOperation op;
09cf7186 194 CODE:
bcdfc2c8
MG
195 switch(ix) {
196 case 0:
197 croak("_compress may not be called directly");
198 break;
199 case 1:
200 op = BROTLI_OPERATION_PROCESS;
201 break;
202 case 2:
203 op = BROTLI_OPERATION_FLUSH;
204 break;
205 case 3:
206 op = BROTLI_OPERATION_FINISH;
207 break;
208 default:
209 croak("Impossible ix in _compress");
210 break;
211 }
212
09cf7186 213 Newx(buffer, BUFFER_SIZE, uint8_t);
bcdfc2c8
MG
214 if(in == &PL_sv_undef)
215 next_in = (uint8_t*) buffer, available_in = 0;
216 else
217 next_in = (uint8_t*) SvPV(in, available_in);
09cf7186
QR
218 RETVAL = newSVpv("", 0);
219 while(1) {
220 next_out = buffer;
221 available_out = BUFFER_SIZE;
d3f7abb9 222 result = BrotliEncoderCompressStream( self->encoder,
09cf7186
QR
223 (BrotliEncoderOperation) op,
224 &available_in,
225 (const uint8_t**) &next_in,
226 &available_out,
227 &next_out,
228 NULL );
229 if(!result) {
230 Safefree(buffer);
231 croak("Error in BrotliEncoderCompressStream");
232 }
233
234 if( available_out != BUFFER_SIZE ) {
235 sv_catpvn(RETVAL, (const char*)buffer, BUFFER_SIZE-available_out);
236 }
237
238 if(
d3f7abb9
QR
239 BrotliEncoderIsFinished(self->encoder) ||
240 (!available_in && !BrotliEncoderHasMoreOutput(self->encoder))
09cf7186
QR
241 ) break;
242 }
243 Safefree(buffer);
244 OUTPUT:
245 RETVAL
246
d3f7abb9
QR
247void
248DESTROY(self)
249 IO::Compress::Brotli self
09cf7186 250 CODE:
d3f7abb9 251 BrotliEncoderDestroyInstance(self->encoder);
21c71a39 252 Safefree(self);
This page took 0.027695 seconds and 4 git commands to generate.