|
|
|
import sys |
|
|
|
from cffi import FFI |
|
ffi = FFI() |
|
|
|
libraries = ['libbrotli'] |
|
if 'win32' not in str(sys.platform).lower(): |
|
libraries.append('stdc++') |
|
|
|
|
|
ffi.set_source( |
|
"_brotli", |
|
"""#include <brotli/decode.h> |
|
#include <brotli/encode.h> |
|
""", |
|
libraries=libraries, |
|
include_dirs=["libbrotli", "libbrotli/include"] |
|
) |
|
|
|
ffi.cdef(""" |
|
/* common/types.h */ |
|
typedef bool BROTLI_BOOL; |
|
#define BROTLI_TRUE ... |
|
#define BROTLI_FALSE ... |
|
|
|
/* dec/state.h */ |
|
/* Allocating function pointer. Function MUST return 0 in the case of |
|
failure. Otherwise it MUST return a valid pointer to a memory region of |
|
at least size length. Neither items nor size are allowed to be 0. |
|
opaque argument is a pointer provided by client and could be used to |
|
bind function to specific object (memory pool). */ |
|
typedef void* (*brotli_alloc_func)(void* opaque, size_t size); |
|
|
|
/* Deallocating function pointer. Function SHOULD be no-op in the case the |
|
address is 0. */ |
|
typedef void (*brotli_free_func)(void* opaque, void* address); |
|
|
|
/* dec/decode.h */ |
|
|
|
typedef enum { |
|
/* Decoding error, e.g. corrupt input or memory allocation problem */ |
|
BROTLI_DECODER_RESULT_ERROR = 0, |
|
/* Decoding successfully completed */ |
|
BROTLI_DECODER_RESULT_SUCCESS = 1, |
|
/* Partially done; should be called again with more input */ |
|
BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2, |
|
/* Partially done; should be called again with more output */ |
|
BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3 |
|
} BrotliDecoderResult; |
|
|
|
typedef enum {...} BrotliDecoderErrorCode; |
|
typedef ... BrotliDecoderState; |
|
|
|
/* Creates the instance of BrotliDecoderState and initializes it. |
|
|alloc_func| and |free_func| MUST be both zero or both non-zero. In the |
|
case they are both zero, default memory allocators are used. |opaque| is |
|
passed to |alloc_func| and |free_func| when they are called. */ |
|
BrotliDecoderState* BrotliDecoderCreateInstance(brotli_alloc_func, |
|
brotli_free_func, |
|
void *); |
|
|
|
/* Deinitializes and frees BrotliDecoderState instance. */ |
|
void BrotliDecoderDestroyInstance(BrotliDecoderState* state); |
|
|
|
/* Decompresses the data. Supports partial input and output. |
|
|
|
Must be called with an allocated input buffer in |*next_in| and an |
|
allocated output buffer in |*next_out|. The values |*available_in| and |
|
|*available_out| must specify the allocated size in |*next_in| and |
|
|*next_out| respectively. |
|
|
|
After each call, |*available_in| will be decremented by the amount of |
|
input bytes consumed, and the |*next_in| pointer will be incremented by |
|
that amount. Similarly, |*available_out| will be decremented by the |
|
amount of output bytes written, and the |*next_out| pointer will be |
|
incremented by that amount. |total_out|, if it is not a null-pointer, |
|
will be set to the number of bytes decompressed since the last state |
|
initialization. |
|
|
|
Input is never overconsumed, so |next_in| and |available_in| could be |
|
passed to the next consumer after decoding is complete. */ |
|
BrotliDecoderResult BrotliDecoderDecompressStream(BrotliDecoderState* s, |
|
size_t* available_in, |
|
const uint8_t** next_in, |
|
size_t* available_out, |
|
uint8_t** next_out, |
|
size_t* total_out); |
|
|
|
/* Fills the new state with a dictionary for LZ77, warming up the |
|
ringbuffer, e.g. for custom static dictionaries for data formats. |
|
Not to be confused with the built-in transformable dictionary of Brotli. |
|
|size| should be less or equal to 2^24 (16MiB), otherwise the dictionary |
|
will be ignored. The dictionary must exist in memory until decoding is |
|
done and is owned by the caller. To use: |
|
1) Allocate and initialize state with BrotliCreateInstance |
|
2) Use BrotliSetCustomDictionary |
|
3) Use BrotliDecompressStream |
|
4) Clean up and free state with BrotliDestroyState |
|
*/ |
|
void BrotliDecoderSetCustomDictionary( |
|
BrotliDecoderState* s, size_t size, const uint8_t* dict); |
|
|
|
/* Returns true, if decoder has some unconsumed output. |
|
Otherwise returns false. */ |
|
BROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState* s); |
|
|
|
/* Returns true, if decoder has already received some input bytes. |
|
Otherwise returns false. */ |
|
BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s); |
|
|
|
/* Returns true, if decoder is in a state where we reached the end of the |
|
input and produced all of the output; returns false otherwise. */ |
|
BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s); |
|
|
|
/* Returns detailed error code after BrotliDecompressStream returns |
|
BROTLI_DECODER_RESULT_ERROR. */ |
|
BrotliDecoderErrorCode BrotliDecoderGetErrorCode( |
|
const BrotliDecoderState* s); |
|
|
|
const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c); |
|
|
|
/* enc/encode.h */ |
|
typedef ... BrotliEncoderState; |
|
|
|
typedef enum BrotliEncoderParameter { |
|
BROTLI_PARAM_MODE = 0, |
|
/* Controls the compression-speed vs compression-density tradeoffs. The |
|
higher the quality, the slower the compression. Range is 0 to 11. */ |
|
BROTLI_PARAM_QUALITY = 1, |
|
/* Base 2 logarithm of the sliding window size. Range is 10 to 24. */ |
|
BROTLI_PARAM_LGWIN = 2, |
|
/* Base 2 logarithm of the maximum input block size. Range is 16 to 24. |
|
If set to 0, the value will be set based on the quality. */ |
|
BROTLI_PARAM_LGBLOCK = 3 |
|
} BrotliEncoderParameter; |
|
|
|
typedef enum BrotliEncoderMode { |
|
/* Default compression mode. The compressor does not know anything in |
|
advance about the properties of the input. */ |
|
BROTLI_MODE_GENERIC = 0, |
|
/* Compression mode for UTF-8 format text input. */ |
|
BROTLI_MODE_TEXT = 1, |
|
/* Compression mode used in WOFF 2.0. */ |
|
BROTLI_MODE_FONT = 2 |
|
} BrotliEncoderMode; |
|
|
|
int BROTLI_DEFAULT_QUALITY = 11; |
|
int BROTLI_DEFAULT_WINDOW = 22; |
|
#define BROTLI_DEFAULT_MODE ... |
|
|
|
typedef enum BrotliEncoderOperation { |
|
BROTLI_OPERATION_PROCESS = 0, |
|
/* Request output stream to flush. Performed when input stream is |
|
depleted and there is enough space in output stream. */ |
|
BROTLI_OPERATION_FLUSH = 1, |
|
/* Request output stream to finish. Performed when input stream is |
|
depleted and there is enough space in output stream. */ |
|
BROTLI_OPERATION_FINISH = 2 |
|
} BrotliEncoderOperation; |
|
|
|
/* Creates the instance of BrotliEncoderState and initializes it. |
|
|alloc_func| and |free_func| MUST be both zero or both non-zero. In the |
|
case they are both zero, default memory allocators are used. |opaque| is |
|
passed to |alloc_func| and |free_func| when they are called. */ |
|
BrotliEncoderState* BrotliEncoderCreateInstance(brotli_alloc_func, |
|
brotli_free_func, |
|
void *); |
|
|
|
/* Deinitializes and frees BrotliEncoderState instance. */ |
|
void BrotliEncoderDestroyInstance(BrotliEncoderState* state); |
|
|
|
/* Compresses the data in |input_buffer| into |encoded_buffer|, and sets |
|
|*encoded_size| to the compressed length. |
|
BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW and BROTLI_DEFAULT_MODE |
|
should be used as |quality|, |lgwin| and |mode| if there are no specific |
|
requirements to encoder speed and compression ratio. |
|
If compression fails, |*encoded_size| is set to 0. |
|
If BrotliEncoderMaxCompressedSize(|input_size|) is not zero, then |
|
|*encoded_size| is never set to the bigger value. |
|
Returns false if there was an error and true otherwise. */ |
|
BROTLI_BOOL BrotliEncoderCompress(int quality, |
|
int lgwin, |
|
BrotliEncoderMode mode, |
|
size_t input_size, |
|
const uint8_t* input_buffer, |
|
size_t* encoded_size, |
|
uint8_t* encoded_buffer); |
|
|
|
BROTLI_BOOL BrotliEncoderCompressStream(BrotliEncoderState* s, |
|
BrotliEncoderOperation op, |
|
size_t* available_in, |
|
const uint8_t** next_in, |
|
size_t* available_out, |
|
uint8_t** next_out, |
|
size_t* total_out); |
|
|
|
BROTLI_BOOL BrotliEncoderSetParameter(BrotliEncoderState* state, |
|
BrotliEncoderParameter p, |
|
uint32_t value); |
|
|
|
/* Fills the new state with a dictionary for LZ77, warming up the |
|
ringbuffer, e.g. for custom static dictionaries for data formats. |
|
Not to be confused with the built-in transformable dictionary of Brotli. |
|
To decode, use BrotliSetCustomDictionary() of the decoder with the same |
|
dictionary. */ |
|
void BrotliEncoderSetCustomDictionary(BrotliEncoderState* state, |
|
size_t size, |
|
const uint8_t* dict); |
|
|
|
/* Check if encoder is in "finished" state, i.e. no more input is |
|
acceptable and no more output will be produced. |
|
Works only with BrotliEncoderCompressStream workflow. |
|
Returns 1 if stream is finished and 0 otherwise. */ |
|
BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s); |
|
|
|
/* Check if encoder has more output bytes in internal buffer. |
|
Works only with BrotliEncoderCompressStream workflow. |
|
Returns 1 if has more output (in internal buffer) and 0 otherwise. */ |
|
BROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s); |
|
""") |
|
|
|
if __name__ == '__main__': |
|
ffi.compile() |
|
|