// Copyright (C) 2016 Herbert Valerio Riedel
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
#ifndef HS_BROTLI_H_
#define HS_BROTLI_H_
#include
#include
#include
#include
typedef enum HsBrotliState
{ HS_BS_NEEDS_INPUT = 0
, HS_BS_HAS_OUTPUT = 1
, HS_BS_FINISHED = 2
, HS_BS_FAIL = 3
, HS_BS_INTERNAL_ERROR = 4
} HsBrotliState;
static inline HsBrotliState
HsBrotliEncoderCompressStream (BrotliEncoderState* state,
BrotliEncoderOperation op,
size_t* available_in, uint8_t** next_in,
size_t* available_out, uint8_t** next_out,
size_t* total_out)
{
const BROTLI_BOOL ok = BrotliEncoderCompressStream (state, op, available_in, (const uint8_t**) next_in, available_out, next_out, total_out);
switch(ok) {
case BROTLI_FALSE: return HS_BS_FAIL;
case BROTLI_TRUE:
switch(BrotliEncoderHasMoreOutput(state)) {
case BROTLI_TRUE: return HS_BS_HAS_OUTPUT;
case BROTLI_FALSE:
switch(BrotliEncoderIsFinished(state)) {
case BROTLI_TRUE: return HS_BS_FINISHED;
case BROTLI_FALSE: return HS_BS_NEEDS_INPUT;
}
}
}
return HS_BS_INTERNAL_ERROR;
}
static inline HsBrotliState
HsBrotliDecoderDecompressStream (BrotliDecoderState* state,
size_t* available_in, uint8_t** next_in,
size_t* available_out, uint8_t** next_out,
size_t* total_out)
{
const BrotliDecoderResult res = BrotliDecoderDecompressStream (state, available_in, (const uint8_t**) next_in, available_out, next_out, total_out);
switch(res) {
case BROTLI_DECODER_RESULT_ERROR: return HS_BS_FAIL;
case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: return HS_BS_NEEDS_INPUT;
case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: return HS_BS_HAS_OUTPUT;
case BROTLI_DECODER_RESULT_SUCCESS:
// TODO: are all these branches really reachable?
switch(BrotliDecoderHasMoreOutput(state)) {
case BROTLI_TRUE: return HS_BS_HAS_OUTPUT;
case BROTLI_FALSE:
switch(BrotliDecoderIsFinished(state)) {
case BROTLI_TRUE: return HS_BS_FINISHED;
case BROTLI_FALSE: return HS_BS_NEEDS_INPUT;
}
}
}
return HS_BS_INTERNAL_ERROR;
}
static inline HsBrotliState
HsBrotliEncoderTakeOutput (BrotliEncoderState* state, size_t* sizep, uint8_t** buf_out)
{
*buf_out = (uint8_t*) BrotliEncoderTakeOutput(state, sizep);
const size_t size = *sizep;
if (!*buf_out && size != 0) {
*sizep = 0;
return HS_BS_INTERNAL_ERROR;
}
// empty
if (size == 0) {
*buf_out = NULL;
switch(BrotliEncoderIsFinished(state)) {
case BROTLI_TRUE: return HS_BS_FINISHED;
case BROTLI_FALSE: return HS_BS_NEEDS_INPUT;
}
return HS_BS_INTERNAL_ERROR;
}
// non-empty
switch(BrotliEncoderHasMoreOutput(state)) {
case BROTLI_TRUE: return HS_BS_HAS_OUTPUT;
case BROTLI_FALSE:
switch(BrotliEncoderIsFinished(state)) {
case BROTLI_TRUE: return HS_BS_FINISHED;
case BROTLI_FALSE: return HS_BS_NEEDS_INPUT;
}
}
*sizep = 0;
*buf_out = NULL;
return HS_BS_INTERNAL_ERROR;
}
static inline HsBrotliState
HsBrotliDecoderTakeOutput (BrotliDecoderState* state, size_t* sizep, uint8_t** buf_out)
{
*buf_out = (uint8_t*) BrotliDecoderTakeOutput(state, sizep);
const size_t size = *sizep;
if (!*buf_out && size != 0) {
*sizep = 0;
return HS_BS_INTERNAL_ERROR;
}
// empty
if (size == 0) {
*buf_out = NULL;
switch(BrotliDecoderIsFinished(state)) {
case BROTLI_TRUE: return HS_BS_FINISHED;
case BROTLI_FALSE: return HS_BS_NEEDS_INPUT;
}
return HS_BS_INTERNAL_ERROR;
}
// non-empty
switch(BrotliDecoderHasMoreOutput(state)) {
case BROTLI_TRUE: return HS_BS_HAS_OUTPUT;
case BROTLI_FALSE:
switch(BrotliDecoderIsFinished(state)) {
case BROTLI_TRUE: return HS_BS_FINISHED;
case BROTLI_FALSE: return HS_BS_NEEDS_INPUT;
}
}
*sizep = 0;
*buf_out = NULL;
return HS_BS_INTERNAL_ERROR;
}
static inline char*
HsBrotliDecoderErrorString (BrotliDecoderErrorCode c)
{
return (char*) BrotliDecoderErrorString(c);
}
#endif