mirror of
https://git.tukaani.org/xz.git
synced 2024-04-04 12:36:23 +02:00
272 lines
7.3 KiB
C
272 lines
7.3 KiB
C
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
/// \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
|