/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * decompress_common.h - Code shared by the XPRESS and LZX decompressors * * Copyright (C) 2015 Eric Biggers */ #ifndef _LINUX_NTFS3_LIB_DECOMPRESS_COMMON_H #define _LINUX_NTFS3_LIB_DECOMPRESS_COMMON_H #include <linux/string.h> #include <linux/compiler.h> #include <linux/types.h> #include <linux/slab.h> #include <asm/unaligned.h> /* "Force inline" macro (not required, but helpful for performance) */ #define forceinline … /* Enable whole-word match copying on selected architectures */ #if defined(__i386__) || defined(__x86_64__) || defined(__ARM_FEATURE_UNALIGNED) #define FAST_UNALIGNED_ACCESS #endif /* Size of a machine word */ #define WORDBYTES … static forceinline void copy_unaligned_word(const void *src, void *dst) { … } /* Generate a "word" with platform-dependent size whose bytes all contain the * value 'b'. */ static forceinline size_t repeat_byte(u8 b) { … } /* Structure that encapsulates a block of in-memory data being interpreted as a * stream of bits, optionally with interwoven literal bytes. Bits are assumed * to be stored in little endian 16-bit coding units, with the bits ordered high * to low. */ struct input_bitstream { … }; /* Initialize a bitstream to read from the specified input buffer. */ static forceinline void init_input_bitstream(struct input_bitstream *is, const void *buffer, u32 size) { … } /* Ensure the bit buffer variable for the bitstream contains at least @num_bits * bits. Following this, bitstream_peek_bits() and/or bitstream_remove_bits() * may be called on the bitstream to peek or remove up to @num_bits bits. Note * that @num_bits must be <= 16. */ static forceinline void bitstream_ensure_bits(struct input_bitstream *is, u32 num_bits) { … } /* Return the next @num_bits bits from the bitstream, without removing them. * There must be at least @num_bits remaining in the buffer variable, from a * previous call to bitstream_ensure_bits(). */ static forceinline u32 bitstream_peek_bits(const struct input_bitstream *is, const u32 num_bits) { … } /* Remove @num_bits from the bitstream. There must be at least @num_bits * remaining in the buffer variable, from a previous call to * bitstream_ensure_bits(). */ static forceinline void bitstream_remove_bits(struct input_bitstream *is, u32 num_bits) { … } /* Remove and return @num_bits bits from the bitstream. There must be at least * @num_bits remaining in the buffer variable, from a previous call to * bitstream_ensure_bits(). */ static forceinline u32 bitstream_pop_bits(struct input_bitstream *is, u32 num_bits) { … } /* Read and return the next @num_bits bits from the bitstream. */ static forceinline u32 bitstream_read_bits(struct input_bitstream *is, u32 num_bits) { … } /* Read and return the next literal byte embedded in the bitstream. */ static forceinline u8 bitstream_read_byte(struct input_bitstream *is) { … } /* Read and return the next 16-bit integer embedded in the bitstream. */ static forceinline u16 bitstream_read_u16(struct input_bitstream *is) { … } /* Read and return the next 32-bit integer embedded in the bitstream. */ static forceinline u32 bitstream_read_u32(struct input_bitstream *is) { … } /* Read into @dst_buffer an array of literal bytes embedded in the bitstream. * Return either a pointer to the byte past the last written, or NULL if the * read overflows the input buffer. */ static forceinline void *bitstream_read_bytes(struct input_bitstream *is, void *dst_buffer, size_t count) { … } /* Align the input bitstream on a coding-unit boundary. */ static forceinline void bitstream_align(struct input_bitstream *is) { … } extern int make_huffman_decode_table(u16 decode_table[], const u32 num_syms, const u32 num_bits, const u8 lens[], const u32 max_codeword_len, u16 working_space[]); /* Reads and returns the next Huffman-encoded symbol from a bitstream. If the * input data is exhausted, the Huffman symbol is decoded as if the missing bits * are all zeroes. */ static forceinline u32 read_huffsym(struct input_bitstream *istream, const u16 decode_table[], u32 table_bits, u32 max_codeword_len) { … } /* * Copy an LZ77 match at (dst - offset) to dst. * * The length and offset must be already validated --- that is, (dst - offset) * can't underrun the output buffer, and (dst + length) can't overrun the output * buffer. Also, the length cannot be 0. * * @bufend points to the byte past the end of the output buffer. This function * won't write any data beyond this position. * * Returns dst + length. */ static forceinline u8 *lz_copy(u8 *dst, u32 length, u32 offset, const u8 *bufend, u32 min_length) { … } #endif /* _LINUX_NTFS3_LIB_DECOMPRESS_COMMON_H */