aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/liblzma/common/common.h')
-rw-r--r--src/liblzma/common/common.h271
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