1 /* Brotli encoding (ENCODING_BROTLI) backend */
13 #include <brotli/decode.h>
18 #include "encoding/brotli.h"
19 #include "encoding/encoding.h"
20 #include "util/math.h"
21 #include "util/memory.h"
23 #define ELINKS_BROTLI_BUFFER_LENGTH 4096
26 BrotliDecoderState
*state
;
28 const uint8_t *next_in
;
35 /* The file descriptor from which we read. */
39 unsigned char buf
[ELINKS_BROTLI_BUFFER_LENGTH
];
43 brotli_open(struct stream_encoded
*stream
, int fd
)
45 struct br_enc_data
*data
= mem_calloc(1, sizeof(*data
));
51 data
->state
= BrotliDecoderCreateInstance(NULL
, NULL
, NULL
);
65 brotli_read(struct stream_encoded
*stream
, unsigned char *buf
, int len
)
67 struct br_enc_data
*data
= (struct br_enc_data
*) stream
->data
;
74 if (data
->last_read
) return 0;
76 data
->avail_out
= len
;
80 if (data
->avail_in
== 0) {
81 int l
= safe_read(data
->fdread
, data
->buf
,
82 ELINKS_BROTLI_BUFFER_LENGTH
);
88 return -1; /* I/O error */
90 /* EOF. It is error: we wait for more bytes */
94 data
->next_in
= data
->buf
;
98 err
= BrotliDecoderDecompressStream(data
->state
, &data
->avail_in
, &data
->next_in
,
99 &data
->avail_out
, &data
->next_out
, &data
->total_out
);
101 if (err
== BROTLI_DECODER_RESULT_SUCCESS
) {
104 } else if (err
== BROTLI_DECODER_RESULT_ERROR
) {
107 } while (data
->avail_out
> 0);
109 assert(len
- data
->avail_out
== data
->next_out
- buf
);
110 return len
- data
->avail_out
;
113 static unsigned char *
114 brotli_decode_buffer(struct stream_encoded
*st
, unsigned char *data
, int len
, int *new_len
)
116 struct br_enc_data
*enc_data
= (struct br_enc_data
*)st
->data
;
117 BrotliDecoderState
*state
= enc_data
->state
;
118 unsigned char *buffer
= NULL
;
121 *new_len
= 0; /* default, left there if an error occurs */
123 if (!len
) return NULL
;
125 enc_data
->next_in
= data
;
126 enc_data
->avail_in
= len
;
127 enc_data
->total_out
= 0;
130 unsigned char *new_buffer
;
131 size_t size
= enc_data
->total_out
+ ELINKS_BROTLI_BUFFER_LENGTH
;
133 new_buffer
= mem_realloc(buffer
, size
);
136 error
= BROTLI_DECODER_RESULT_ERROR
;
141 enc_data
->next_out
= buffer
+ enc_data
->total_out
;
142 enc_data
->avail_out
= ELINKS_BROTLI_BUFFER_LENGTH
;
144 error
= BrotliDecoderDecompressStream(state
, &enc_data
->avail_in
, &enc_data
->next_in
,
145 &enc_data
->avail_out
, &enc_data
->next_out
, &enc_data
->total_out
);
147 if (error
== BROTLI_DECODER_RESULT_SUCCESS
) {
148 *new_len
= enc_data
->total_out
;
149 enc_data
->after_end
= 1;
153 } while (error
== BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT
);
160 brotli_close(struct stream_encoded
*stream
)
162 struct br_enc_data
*data
= (struct br_enc_data
*) stream
->data
;
165 if (data
->state
) BrotliDecoderDestroyInstance(data
->state
);
166 if (data
->fdread
!= -1) {
174 static const unsigned char *const brotli_extensions
[] = { ".br", NULL
};
176 const struct decoding_backend brotli_decoding_backend
= {
181 brotli_decode_buffer
,