aboutsummaryrefslogblamecommitdiff
path: root/src/liblzma/common/common.h
blob: ca9c2f237d7aaf4ec7fbd34508f83c254aacd1b5 (plain) (tree)














































































































































































































































































                                                                               
///////////////////////////////////////////////////////////////////////////////
//
/// \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