mirror of
https://github.com/google/brotli.git
synced 2024-11-21 19:20:09 +00:00
Decoder API: added API to attach metadata blocks callbacks
PiperOrigin-RevId: 505734532
This commit is contained in:
parent
04f294b18a
commit
b2c86d1871
@ -341,6 +341,11 @@ static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
|
||||
return TO_BROTLI_BOOL(pad_bits == 0);
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {
|
||||
br->avail_in -= num;
|
||||
br->next_in += num;
|
||||
}
|
||||
|
||||
/* Copies remaining input bytes stored in the bit reader to the output. Value
|
||||
|num| may not be larger than BrotliGetRemainingBytes. The bit reader must be
|
||||
warmed up again after this. */
|
||||
@ -352,9 +357,10 @@ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
|
||||
++dest;
|
||||
--num;
|
||||
}
|
||||
memcpy(dest, br->next_in, num);
|
||||
br->avail_in -= num;
|
||||
br->next_in += num;
|
||||
if (num > 0) {
|
||||
memcpy(dest, br->next_in, num);
|
||||
BrotliDropBytes(br, num);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
@ -1354,6 +1354,57 @@ static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
static BrotliDecoderErrorCode BROTLI_NOINLINE
|
||||
SkipMetadataBlock(BrotliDecoderState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
|
||||
if (s->meta_block_remaining_len == 0) {
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
BROTLI_DCHECK((BrotliGetAvailableBits(br) & 7) == 0);
|
||||
|
||||
/* Drain accumulator. */
|
||||
if (BrotliGetAvailableBits(br) >= 8) {
|
||||
uint8_t buffer[8];
|
||||
int nbytes = (int)(BrotliGetAvailableBits(br)) >> 3;
|
||||
BROTLI_DCHECK(nbytes <= 8);
|
||||
if (nbytes > s->meta_block_remaining_len) {
|
||||
nbytes = s->meta_block_remaining_len;
|
||||
}
|
||||
BrotliCopyBytes(buffer, br, (size_t)nbytes);
|
||||
if (s->metadata_chunk_func) {
|
||||
s->metadata_chunk_func(s->metadata_callback_opaque, buffer,
|
||||
(size_t)nbytes);
|
||||
}
|
||||
s->meta_block_remaining_len -= nbytes;
|
||||
if (s->meta_block_remaining_len == 0) {
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Direct access to metadata is possible. */
|
||||
int nbytes = (int)BrotliGetRemainingBytes(br);
|
||||
if (nbytes > s->meta_block_remaining_len) {
|
||||
nbytes = s->meta_block_remaining_len;
|
||||
}
|
||||
if (nbytes > 0) {
|
||||
if (s->metadata_chunk_func) {
|
||||
s->metadata_chunk_func(s->metadata_callback_opaque, br->next_in,
|
||||
(size_t)nbytes);
|
||||
}
|
||||
BrotliDropBytes(br, (size_t)nbytes);
|
||||
s->meta_block_remaining_len -= nbytes;
|
||||
if (s->meta_block_remaining_len == 0) {
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
BROTLI_DCHECK(BrotliGetRemainingBytes(br) == 0);
|
||||
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
|
||||
static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
|
||||
size_t* available_out, uint8_t** next_out, size_t* total_out,
|
||||
BrotliDecoderState* s) {
|
||||
@ -2414,6 +2465,10 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
||||
}
|
||||
if (s->is_metadata) {
|
||||
s->state = BROTLI_STATE_METADATA;
|
||||
if (s->metadata_start_func) {
|
||||
s->metadata_start_func(s->metadata_callback_opaque,
|
||||
(size_t)s->meta_block_remaining_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (s->meta_block_remaining_len == 0) {
|
||||
@ -2506,17 +2561,11 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
||||
}
|
||||
|
||||
case BROTLI_STATE_METADATA:
|
||||
for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
|
||||
uint32_t bits;
|
||||
/* Read one byte and ignore it. */
|
||||
if (!BrotliSafeReadBits(br, 8, &bits)) {
|
||||
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == BROTLI_DECODER_SUCCESS) {
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
result = SkipMetadataBlock(s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
break;
|
||||
|
||||
case BROTLI_STATE_METABLOCK_HEADER_2: {
|
||||
@ -2785,6 +2834,15 @@ uint32_t BrotliDecoderVersion(void) {
|
||||
return BROTLI_VERSION;
|
||||
}
|
||||
|
||||
void BrotliDecoderSetMetadataCallbacks(
|
||||
BrotliDecoderState* state,
|
||||
brotli_decoder_metadata_start_func start_func,
|
||||
brotli_decoder_metadata_chunk_func chunk_func, void* opaque) {
|
||||
state->metadata_start_func = start_func;
|
||||
state->metadata_chunk_func = chunk_func;
|
||||
state->metadata_callback_opaque = opaque;
|
||||
}
|
||||
|
||||
/* Escalate internal functions visibility; for testing purposes only. */
|
||||
#if defined(BROTLI_TEST)
|
||||
BROTLI_BOOL SafeReadSymbolForTest(
|
||||
|
@ -89,6 +89,10 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
|
||||
BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);
|
||||
if (!s->dictionary) return BROTLI_FALSE;
|
||||
|
||||
s->metadata_start_func = NULL;
|
||||
s->metadata_chunk_func = NULL;
|
||||
s->metadata_callback_opaque = 0;
|
||||
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef BROTLI_DEC_STATE_H_
|
||||
#define BROTLI_DEC_STATE_H_
|
||||
|
||||
#include <brotli/decode.h>
|
||||
#include <brotli/shared_dictionary.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
@ -322,6 +323,10 @@ struct BrotliDecoderStateStruct {
|
||||
|
||||
/* Less used attributes are at the end of this struct. */
|
||||
|
||||
brotli_decoder_metadata_start_func metadata_start_func;
|
||||
brotli_decoder_metadata_chunk_func metadata_chunk_func;
|
||||
void* metadata_callback_opaque;
|
||||
|
||||
/* For reporting. */
|
||||
uint64_t used_input; /* how many bytes of input are consumed */
|
||||
|
||||
|
@ -361,6 +361,47 @@ BROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);
|
||||
*/
|
||||
BROTLI_DEC_API uint32_t BrotliDecoderVersion(void);
|
||||
|
||||
/**
|
||||
* Callback to fire on metadata block start.
|
||||
*
|
||||
* After this callback is fired, if @p size is not @c 0, it is followed by
|
||||
* ::brotli_decoder_metadata_chunk_func as more metadata block contents become
|
||||
* accessible.
|
||||
*
|
||||
* @param opaque callback handle
|
||||
* @param size size of metadata block
|
||||
*/
|
||||
typedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size);
|
||||
|
||||
/**
|
||||
* Callback to fire on metadata block chunk becomes available.
|
||||
*
|
||||
* This function can be invoked multiple times per metadata block; block should
|
||||
* be considered finished when sum of @p size matches the announced metadata
|
||||
* block size. Chunks contents pointed by @p data are transient and shouln not
|
||||
* be accessed after leaving the callback.
|
||||
*
|
||||
* @param opaque callback handle
|
||||
* @param data pointer to metadata contents
|
||||
* @param size size of metadata block chunk, at least @c 1
|
||||
*/
|
||||
typedef void (*brotli_decoder_metadata_chunk_func)(void* opaque,
|
||||
const uint8_t* data,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* Sets callback for receiving metadata blocks.
|
||||
*
|
||||
* @param state decoder instance
|
||||
* @param start_func callback on metadata block start
|
||||
* @param chunk_func callback on metadata block chunk
|
||||
* @param opaque callback handle
|
||||
*/
|
||||
BROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks(
|
||||
BrotliDecoderState* state,
|
||||
brotli_decoder_metadata_start_func start_func,
|
||||
brotli_decoder_metadata_chunk_func chunk_func, void* opaque);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@ -23,6 +23,14 @@ decode.h \- API for Brotli decompression\&.
|
||||
|
||||
.in +1c
|
||||
.ti -1c
|
||||
.RI "typedef void(* \fBbrotli_decoder_metadata_chunk_func\fP) (void *opaque, const uint8_t *data, size_t size)"
|
||||
.br
|
||||
.RI "\fICallback to fire on metadata block chunk becomes available\&. \fP"
|
||||
.ti -1c
|
||||
.RI "typedef void(* \fBbrotli_decoder_metadata_start_func\fP) (void *opaque, size_t size)"
|
||||
.br
|
||||
.RI "\fICallback to fire on metadata block start\&. \fP"
|
||||
.ti -1c
|
||||
.RI "typedef enum \fBBrotliDecoderParameter\fP \fBBrotliDecoderParameter\fP"
|
||||
.br
|
||||
.RI "\fIOptions to be used with \fBBrotliDecoderSetParameter\fP\&. \fP"
|
||||
@ -76,6 +84,10 @@ decode.h \- API for Brotli decompression\&.
|
||||
.br
|
||||
.RI "\fIChecks if instance has already consumed input\&. \fP"
|
||||
.ti -1c
|
||||
.RI "void \fBBrotliDecoderSetMetadataCallbacks\fP (\fBBrotliDecoderState\fP *state, \fBbrotli_decoder_metadata_start_func\fP start_func, \fBbrotli_decoder_metadata_chunk_func\fP chunk_func, void *opaque)"
|
||||
.br
|
||||
.RI "\fISets callback for receiving metadata blocks\&. \fP"
|
||||
.ti -1c
|
||||
.RI "\fBBROTLI_BOOL\fP \fBBrotliDecoderSetParameter\fP (\fBBrotliDecoderState\fP *state, \fBBrotliDecoderParameter\fP param, uint32_t value)"
|
||||
.br
|
||||
.RI "\fISets the specified parameter to the given decoder instance\&. \fP"
|
||||
@ -123,6 +135,34 @@ BROTLI_DECODER_ERROR_CODES_LIST(CASE_, NEWLINE_)
|
||||
The value of the last error code, negative integer\&. All other error code values are in the range from \fBBROTLI_LAST_ERROR_CODE\fP to \fC-1\fP\&. There are also 4 other possible non-error codes \fC0\fP \&.\&. \fC3\fP in \fBBrotliDecoderErrorCode\fP enumeration\&.
|
||||
.SH "Typedef Documentation"
|
||||
.PP
|
||||
.SS "typedef void(* brotli_decoder_metadata_chunk_func) (void *opaque, const uint8_t *data, size_t size)"
|
||||
|
||||
.PP
|
||||
Callback to fire on metadata block chunk becomes available\&. This function can be invoked multiple times per metadata block; block should be considered finished when sum of \fCsize\fP matches the announced metadata block size\&. Chunks contents pointed by \fCdata\fP are transient and shouln not be accessed after leaving the callback\&.
|
||||
.PP
|
||||
\fBParameters:\fP
|
||||
.RS 4
|
||||
\fIopaque\fP callback handle
|
||||
.br
|
||||
\fIdata\fP pointer to metadata contents
|
||||
.br
|
||||
\fIsize\fP size of metadata block chunk, at least \fC1\fP
|
||||
.RE
|
||||
.PP
|
||||
|
||||
.SS "typedef void(* brotli_decoder_metadata_start_func) (void *opaque, size_t size)"
|
||||
|
||||
.PP
|
||||
Callback to fire on metadata block start\&. After this callback is fired, if \fCsize\fP is not \fC0\fP, it is followed by \fBbrotli_decoder_metadata_chunk_func\fP as more metadata block contents become accessible\&.
|
||||
.PP
|
||||
\fBParameters:\fP
|
||||
.RS 4
|
||||
\fIopaque\fP callback handle
|
||||
.br
|
||||
\fIsize\fP size of metadata block
|
||||
.RE
|
||||
.PP
|
||||
|
||||
.SS "typedef enum \fBBrotliDecoderParameter\fP \fBBrotliDecoderParameter\fP"
|
||||
|
||||
.PP
|
||||
@ -378,6 +418,23 @@ Checks if instance has already consumed input\&. Instance that returns \fBBROTLI
|
||||
.RE
|
||||
.PP
|
||||
|
||||
.SS "void BrotliDecoderSetMetadataCallbacks (\fBBrotliDecoderState\fP * state, \fBbrotli_decoder_metadata_start_func\fP start_func, \fBbrotli_decoder_metadata_chunk_func\fP chunk_func, void * opaque)"
|
||||
|
||||
.PP
|
||||
Sets callback for receiving metadata blocks\&.
|
||||
.PP
|
||||
\fBParameters:\fP
|
||||
.RS 4
|
||||
\fIstate\fP decoder instance
|
||||
.br
|
||||
\fIstart_func\fP callback on metadata block start
|
||||
.br
|
||||
\fIchunk_func\fP callback on metadata block chunk
|
||||
.br
|
||||
\fIopaque\fP callback handle
|
||||
.RE
|
||||
.PP
|
||||
|
||||
.SS "\fBBROTLI_BOOL\fP BrotliDecoderSetParameter (\fBBrotliDecoderState\fP * state, \fBBrotliDecoderParameter\fP param, uint32_t value)"
|
||||
|
||||
.PP
|
||||
|
Loading…
Reference in New Issue
Block a user