diff options
Diffstat (limited to 'src/liblzma/common/common.h')
-rw-r--r-- | src/liblzma/common/common.h | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h new file mode 100644 index 00000000..ca9c2f23 --- /dev/null +++ b/src/liblzma/common/common.h @@ -0,0 +1,271 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file common.h +/// \brief Definitions common to the whole liblzma library +// +// Copyright (C) 2007 Lasse Collin +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef LZMA_COMMON_H +#define LZMA_COMMON_H + +#include "sysdefs.h" + +// Don't use ifdef... +#if HAVE_VISIBILITY +# define LZMA_API __attribute__((__visibility__("default"))) +#else +# define LZMA_API +#endif + + +/// Size of temporary buffers needed in some filters +#define LZMA_BUFFER_SIZE 4096 + + +/// Internal helper filter used by Subblock decoder. It is mapped to an +/// otherwise invalid Filter ID, which is impossible to get from any input +/// file (even if malicious file). +#define LZMA_FILTER_SUBBLOCK_HELPER (UINT64_MAX - 2) + + +/////////// +// Types // +/////////// + +typedef struct lzma_coder_s lzma_coder; + +typedef struct lzma_next_coder_s lzma_next_coder; + +typedef struct lzma_filter_info_s lzma_filter_info; + + +typedef lzma_ret (*lzma_init_function)( + lzma_next_coder *next, lzma_allocator *allocator, + const lzma_filter_info *filters); + +typedef lzma_ret (*lzma_code_function)( + lzma_coder *coder, lzma_allocator *allocator, + const uint8_t *restrict in, size_t *restrict in_pos, + size_t in_size, uint8_t *restrict out, + size_t *restrict out_pos, size_t out_size, + lzma_action action); + +typedef void (*lzma_end_function)( + lzma_coder *coder, lzma_allocator *allocator); + + +/// Hold data and function pointers of the next filter in the chain. +struct lzma_next_coder_s { + /// Pointer to coder-specific data + lzma_coder *coder; + + /// "Pointer" to init function. This is never called here. + /// We need only to detect if we are initializing a coder + /// that was allocated earlier. See code.c and next_coder.c. + uintptr_t init; + + /// Pointer to function to do the actual coding + lzma_code_function code; + + /// Pointer to function to free lzma_next_coder.coder + lzma_end_function end; +}; + +#define LZMA_NEXT_CODER_INIT \ + (lzma_next_coder){ \ + .coder = NULL, \ + .init = 0, \ + .code = NULL, \ + .end = NULL, \ + } + + +struct lzma_internal_s { + lzma_next_coder next; + + enum { + ISEQ_RUN, + ISEQ_SYNC_FLUSH, + ISEQ_FULL_FLUSH, + ISEQ_FINISH, + ISEQ_END, + ISEQ_ERROR, + } sequence; + + bool supported_actions[4]; + bool allow_buf_error; + size_t avail_in; +}; + + +struct lzma_filter_info_s { + /// Pointer to function used to initialize the filter. + /// This is NULL to indicate end of array. + lzma_init_function init; + + /// Pointer to filter's options structure + void *options; + + /// Uncompressed size of the filter, or LZMA_VLI_VALUE_UNKNOWN + /// if unknown. + lzma_vli uncompressed_size; +}; + + +/* +typedef struct { + lzma_init_function init; + uint32_t (*input_alignment)(lzma_vli id, const void *options); + uint32_t (*output_alignment)(lzma_vli id, const void *options); + bool changes_uncompressed_size; + bool supports_eopm; +} lzma_filter_hook; +*/ + + +/////////////// +// Functions // +/////////////// + +/// Allocates memory +extern void *lzma_alloc(size_t size, lzma_allocator *allocator) + lzma_attribute((malloc)); + +/// Frees memory +extern void lzma_free(void *ptr, lzma_allocator *allocator); + +/// Initializes lzma_stream FIXME desc +extern lzma_ret lzma_strm_init(lzma_stream *strm); + +/// +extern lzma_ret lzma_next_filter_init(lzma_next_coder *next, + lzma_allocator *allocator, const lzma_filter_info *filters); + +/// +extern void lzma_next_coder_end(lzma_next_coder *next, + lzma_allocator *allocator); + + +extern lzma_ret lzma_filter_flags_decoder_init(lzma_next_coder *next, + lzma_allocator *allocator, lzma_options_filter *options); + +extern lzma_ret lzma_block_header_decoder_init(lzma_next_coder *next, + lzma_allocator *allocator, lzma_options_block *options); + +extern lzma_ret lzma_stream_encoder_single_init(lzma_next_coder *next, + lzma_allocator *allocator, const lzma_options_stream *options); + +extern lzma_ret lzma_stream_decoder_init( + lzma_next_coder *next, lzma_allocator *allocator, + lzma_extra **header, lzma_extra **footer); + + +/// \brief Wrapper for memcpy() +/// +/// This function copies as much data as possible from in[] to out[] and +/// updates *in_pos and *out_pos accordingly. +/// +static inline size_t +bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, + uint8_t *restrict out, size_t *restrict out_pos, + size_t out_size) +{ + const size_t in_avail = in_size - *in_pos; + const size_t out_avail = out_size - *out_pos; + const size_t copy_size = MIN(in_avail, out_avail); + + memcpy(out + *out_pos, in + *in_pos, copy_size); + + *in_pos += copy_size; + *out_pos += copy_size; + + return copy_size; +} + + +/// \brief Initializing the next coder +/// +/// lzma_next_coder can point to different types of coders. The existing +/// coder may be different than what we are initializing now. In that case +/// we must git rid of the old coder first. Otherwise we reuse the existing +/// coder structure. +/// +#define lzma_next_coder_init2(next, allocator, cmpfunc, func, ...) \ +do { \ + if ((uintptr_t)(&cmpfunc) != (next)->init) \ + lzma_next_coder_end(next, allocator); \ + const lzma_ret ret = func(next, __VA_ARGS__); \ + if (ret == LZMA_OK) { \ + (next)->init = (uintptr_t)(&cmpfunc); \ + assert((next)->code != NULL); \ + assert((next)->end != NULL); \ + } else { \ + lzma_next_coder_end(next, allocator); \ + } \ + return ret; \ +} while (0) + +/// \brief Initializing lzma_next_coder +/// +/// Call the initialization function, which must take at least one +/// argument in addition to lzma_next_coder and lzma_allocator. +#define lzma_next_coder_init(func, next, allocator, ...) \ + lzma_next_coder_init2(next, allocator, \ + func, func, allocator, __VA_ARGS__) + + +/// \brief Initializing lzma_stream +/// +/// lzma_strm initialization with more detailed options. +#define lzma_next_strm_init2(strm, cmpfunc, func, ...) \ +do { \ + lzma_ret ret = lzma_strm_init(strm); \ + if (ret != LZMA_OK) \ + return ret; \ + if ((uintptr_t)(&cmpfunc) != (strm)->internal->next.init) \ + lzma_next_coder_end(\ + &(strm)->internal->next, (strm)->allocator); \ + ret = func(&(strm)->internal->next, __VA_ARGS__); \ + if (ret != LZMA_OK) { \ + lzma_end(strm); \ + return ret; \ + } \ + (strm)->internal->next.init = (uintptr_t)(&cmpfunc); \ + assert((strm)->internal->next.code != NULL); \ + assert((strm)->internal->next.end != NULL); \ +} while (0) + +/// \brief Initializing lzma_stream +/// +/// Call the initialization function, which must take at least one +/// argument in addition to lzma_next_coder and lzma_allocator. +#define lzma_next_strm_init(strm, func, ...) \ + lzma_next_strm_init2(strm, func, func, (strm)->allocator, __VA_ARGS__) + + +/// \brief Return if expression doesn't evaluate to LZMA_OK +/// +/// There are several situations where we want to return immediatelly +/// with the value of expr if it isn't LZMA_OK. This macro shortens +/// the code a bit. +/// +#define return_if_error(expr) \ +do { \ + const lzma_ret ret_ = expr; \ + if (ret_ != LZMA_OK) \ + return ret_; \ +} while (0) + +#endif |