1 /* Brotli encoding (ENCODING_BROTLI) backend */
13 #ifdef HAVE_BROTLI_DEC_DECODE_H
14 #include <brotli/dec/decode.h>
21 #include "encoding/brotli.h"
22 #include "encoding/encoding.h"
23 #include "util/math.h"
24 #include "util/memory.h"
27 BrotliState br_stream
;
37 /* The file descriptor from which we read. */
44 brotli_open(struct stream_encoded
*stream
, int fd
)
46 struct br_enc_data
*data
= mem_calloc(1, sizeof(*data
));
54 BrotliStateInit(&data
->br_stream
);
61 brotli_read_function_fd(void *data
, uint8_t *buf
, size_t len
)
63 struct br_enc_data
*enc_data
= (struct br_enc_data
*)data
;
65 return safe_read(enc_data
->fdread
, buf
, len
);
69 brotli_read_function(void *data
, uint8_t *buf
, size_t len
)
71 struct br_enc_data
*enc_data
= (struct br_enc_data
*)data
;
72 size_t l
= MIN(len
, enc_data
->input_length
- enc_data
->input_pos
);
74 memcpy(buf
, enc_data
->input
+ enc_data
->input_pos
, l
);
75 enc_data
->input_pos
+= l
;
80 brotli_write_function(void *data
, const uint8_t *buf
, size_t len
)
82 struct br_enc_data
*enc_data
= (struct br_enc_data
*)data
;
84 enc_data
->output
= mem_alloc(len
);
85 if (!enc_data
->output
) {
88 memcpy(enc_data
->output
, buf
, len
);
89 enc_data
->output_length
= len
;
94 brotli_read(struct stream_encoded
*stream
, unsigned char *buf
, int len
)
96 struct br_enc_data
*enc_data
= (struct br_enc_data
*) stream
->data
;
103 if (!enc_data
) return -1;
104 s
= &enc_data
->br_stream
;
108 if (enc_data
->after_end
) {
109 l
= MIN(len
, enc_data
->output_length
- enc_data
->output_pos
);
110 memcpy(buf
, enc_data
->output
+ enc_data
->output_pos
, l
);
111 enc_data
->output_pos
+= l
;
115 enc_data
->input
= NULL
;
116 enc_data
->input_length
= 0;
117 enc_data
->output
= NULL
;
118 enc_data
->output_length
= 0;
119 enc_data
->output_pos
= 0;
120 inp
.data_
= enc_data
;
121 outp
.data_
= enc_data
;
122 inp
.cb_
= brotli_read_function_fd
;
123 outp
.cb_
= brotli_write_function
;
125 error
= BrotliDecompressStreaming(inp
, outp
, 1, s
);
127 case BROTLI_RESULT_ERROR
:
129 case BROTLI_RESULT_SUCCESS
:
130 enc_data
->after_end
= 1;
131 case BROTLI_RESULT_NEEDS_MORE_INPUT
:
133 enc_data
->need_free
= 1;
134 l
= MIN(len
, enc_data
->output_length
- enc_data
->output_pos
);
135 memcpy(buf
, enc_data
->output
+ enc_data
->output_pos
, l
);
136 enc_data
->output_pos
+= l
;
141 static unsigned char *
142 brotli_decode_buffer(struct stream_encoded
*st
, unsigned char *data
, int len
, int *new_len
)
144 struct br_enc_data
*enc_data
= (struct br_enc_data
*)st
->data
;
147 BrotliState
*stream
= &enc_data
->br_stream
;
149 int finish
= (len
== 0);
151 *new_len
= 0; /* default, left there if an error occurs */
152 enc_data
->input
= data
;
153 enc_data
->input_length
= len
;
154 enc_data
->input_pos
= 0;
155 enc_data
->output
= NULL
;
156 enc_data
->output_length
= 0;
157 enc_data
->output_pos
= 0;
158 inp
.data_
= enc_data
;
159 outp
.data_
= enc_data
;
160 inp
.cb_
= brotli_read_function
;
161 outp
.cb_
= brotli_write_function
;
162 error
= BrotliDecompressStreaming(inp
, outp
, finish
, stream
);
165 case BROTLI_RESULT_ERROR
:
167 case BROTLI_RESULT_SUCCESS
:
168 enc_data
->after_end
= 1;
169 case BROTLI_RESULT_NEEDS_MORE_INPUT
:
171 *new_len
= enc_data
->output_length
;
172 return enc_data
->output
;
177 brotli_close(struct stream_encoded
*stream
)
179 struct br_enc_data
*data
= (struct br_enc_data
*) stream
->data
;
182 BrotliStateCleanup(&data
->br_stream
);
183 if (data
->fdread
!= -1) {
186 if (data
->need_free
) {
187 mem_free_if(data
->output
);
194 static const unsigned char *const brotli_extensions
[] = { ".br", NULL
};
196 const struct decoding_backend brotli_decoding_backend
= {
201 brotli_decode_buffer
,