148 Commits

Author SHA1 Message Date
Lasse Collin
beeb810608 Prevent LZ encoder from hanging with known uncompressed
size. The "fix" breaks LZMA_SYNC_FLUSH at end of stream
with known uncompressed size, but since it currently seems
likely that support for encoding with known uncompressed
size will go away anyway, I'm not fixing this problem now.
2008-04-25 15:39:50 +03:00
Lasse Collin
c324325f9f Removed src/liblzma/common/sysdefs.h symlink, which was
annoying, because "make dist" put two copies of sysdefs.h
into the tarball instead of the symlink.
2008-04-25 13:58:56 +03:00
Lasse Collin
d3ba30243c Added memusage.c to debug directory. 2008-04-25 13:41:29 +03:00
Lasse Collin
8f804c29aa Bumped version number to 4.999.3alpha. It will become 5.0.0
once we have a stable release (won't be very soon). The
version number is no longer related to version of LZMA SDK.

Made some small Automake-related changes to toplevel
Makefile.am and configure.ac.
2008-04-25 13:32:35 +03:00
Lasse Collin
c99037ea10 Fix a memory leak by calling free(extra->data) in
lzma_extra_free().
2008-04-24 20:25:39 +03:00
Lasse Collin
22ba3b0b50 Make unlzma and lzcat symlinks. 2008-04-24 20:23:05 +03:00
Lasse Collin
17c36422d4 Fixed a bug in command line option parsing. 2008-04-24 20:20:27 +03:00
Lasse Collin
283f939974 Added two assert()s. 2008-04-24 20:19:20 +03:00
Lasse Collin
eb348a60b6 Switch to uint16_t as the type of range coder probabilities. 2008-04-24 19:22:53 +03:00
Lasse Collin
6c5306e312 Fix wrong return type (uint32_t -> bool). 2008-04-24 18:39:57 +03:00
Lasse Collin
712cfe3ebf Fix data corruption in LZ encoder with LZMA_SYNC_FLUSH. 2008-04-24 18:38:00 +03:00
Lasse Collin
bc04486e36 Fix fastpos problem in Makefile.am when built with --enable-small. 2008-04-24 17:33:01 +03:00
Lasse Collin
7ab493924e Use 64-bit integer as range encoder's cache size. This fixes a
theoretical data corruption, which should be very hard to trigger
even intentionally.
2008-04-24 17:30:51 +03:00
Lasse Collin
641998c3e1 Replaced the range decoder optimization that used arithmetic
right shift with as fast version that doesn't need
arithmetic right shift. Removed the related check from
configure.ac.
2008-03-24 16:38:40 +02:00
Lasse Collin
ad999efd27 Take advantage of arithmetic right shift in range decoder. 2008-03-22 14:39:34 +02:00
Lasse Collin
03e0e8a0d7 Added autoconf check to detect if we can use arithmetic
right shift for optimizations.
2008-03-22 14:18:29 +02:00
Lasse Collin
7521bbdc83 Update a comment to use the variable name rep_len_decoder.
(And BTW, the previous commit actually did change the
program logic slightly.)
2008-03-22 01:26:36 +02:00
Lasse Collin
63b74d000e Demystified the "state" variable in LZMA code. Use the
word literal instead of char for better consistency.
There are still some names with _char instead of _literal
in lzma_optimum, these may be changed later.

Renamed length coder variables.

This commit doesn't change the program logic.
2008-03-22 00:57:33 +02:00
Lasse Collin
e6eb0a2675 Fix data corruption in LZMA encoder. Note that this bug was
specific to liblzma and was *not* present in LZMA SDK.
2008-03-14 23:16:11 +02:00
Lasse Collin
7d516f5129 Fix a comment API header. 2008-03-14 21:32:37 +02:00
Lasse Collin
748d6e4274 Make lzma_stream.next_in const. Let's see if anyone complains. 2008-03-12 23:14:50 +02:00
Lasse Collin
bfde3b24a5 Apply a minor speed optimization to LZMA decoder. 2008-03-11 15:35:34 +02:00
Lasse Collin
f310c50286 Initialize the last byte of the dictionary to zero so that
lz_get_byte(lz, 0) returns zero. This was broken by
1a3b218598.
2008-03-11 15:17:16 +02:00
Lasse Collin
5ead36cf7f Really fix the price count initialization. 2008-03-10 15:57:55 +02:00
Lasse Collin
d4d7feb83d Updated THANKS. 2008-03-10 13:47:17 +02:00
Lasse Collin
0541c5ea63 Initialize align_price_count and match_price_count in
lzma_encoder_init.c. While we don't call
fill_distances_prices() and fill_align_prices() in
lzma_lzma_encoder_init(), we still need to initialize
these two variables so that the fill functions get
called in lzma_encoder_getoptimum.c in the beginning
of a stream.
2008-03-10 13:46:48 +02:00
Lasse Collin
596fa1fac7 Always initialize lz->temp_size in lz_decoder.c. temp_size did
get initialized as a side-effect after allocating a new decoder,
but not when the decoder was reused.
2008-03-10 13:44:29 +02:00
Lasse Collin
45e43e1695 Don't fill allocated memory with 0xFD when debugging is
enabled. It hides errors from Valgrind.
2008-03-10 13:41:25 +02:00
Lasse Collin
c0e19e0662 Remove two redundant validity checks from the LZMA decoder.
These are already checked elsewhere, so omitting these
gives (very) tiny speed up.
2008-02-28 10:24:31 +02:00
Lasse Collin
de74858062 Tiny clean up to file-format.txt. 2008-02-06 13:25:32 +02:00
Lasse Collin
1a3b218598 Don't memzero() the history buffer when initializing LZ
decoder. There's no danger of information leak here, so
it isn't required. Doing memzero() takes a lot of time
with large dictionaries, which could make it easier to
construct DoS attack to consume too much CPU time.
2008-02-02 14:51:06 +02:00
Lasse Collin
7e796e312b Do uncompressed size validation in raw encoder. This way
it gets done for not only raw encoder, but also Block
and LZMA_Alone encoders.
2008-02-01 08:39:26 +02:00
Lasse Collin
7dd48578a3 Avoid unneeded function call in raw_common.c. 2008-02-01 08:32:05 +02:00
Lasse Collin
b596fac963 Updated THANKS. 2008-01-26 21:42:38 +02:00
Lasse Collin
e9f6e9c075 Added note.GNU-stack to x86 assembler files. It is needed
when using non-executable stack.
2008-01-26 21:40:23 +02:00
Lasse Collin
4c7ad179c7 Added api/lzma/easy.h. I had forgot to add this to the
git repo. Thanks to Stephan Kulow.
2008-01-26 19:12:50 +02:00
Lasse Collin
288b232f54 Added more test files. 2008-01-26 11:09:17 +02:00
Lasse Collin
c467b0defc Added more test files. 2008-01-26 10:47:55 +02:00
Lasse Collin
f9842f7127 Return LZMA_HEADER_ERROR if LZMA_SYNC_FLUSH is used with any
of the so called simple filters. If there is demand, limited
support for LZMA_SYNC_FLUSH may be added in future.

After this commit, using LZMA_SYNC_FLUSH shouldn't cause
undefined behavior in any situation.
2008-01-26 00:25:34 +02:00
Lasse Collin
e988ea1d1a Added more Multi-Block test files. Improved some
descriptions in the test files' README.
2008-01-25 23:50:35 +02:00
Lasse Collin
4441e00418 Combine lzma_options_block validation needed by both Block
encoder and decoder, and put the shared things to
block_private.h. Improved the checks a little so that
they may detect too big Compressed Size at initialization
time if lzma_options_block.total_size or .total_limit is
known.

Allow encoding and decoding Blocks with combinations of
fields that are not allowed by the file format specification.
Doing this requires that the application passes such a
combination in lzma_options_lzma; liblzma doesn't do that,
but it's not impossible that someone could find them useful
in some custom file format.
2008-01-25 23:12:36 +02:00
Lasse Collin
bf4200c818 Added test_memlimit.c. 2008-01-25 19:21:22 +02:00
Lasse Collin
7b8fc7e6b5 Improved the memory limitter:
- Added lzma_memlimit_max() and lzma_memlimit_reached()
    API functions.
  - Added simple estimation of malloc()'s memory usage
    overhead.
  - Fixed integer overflow detection in lzma_memlimit_alloc().
  - Made some white space cleanups and added more comments.

The description of lzma_memlimit_max() in memlimit.h is bad
and should be improved.
2008-01-25 19:20:28 +02:00
Lasse Collin
e0c3d0043d Use more parenthesis in succeed() macro in tests/tests.h. 2008-01-25 13:55:52 +02:00
Lasse Collin
1fd76d4881 Added more Multi-Block Stream test files. 2008-01-24 14:49:34 +02:00
Lasse Collin
6e27b1098a Added bunch of test files containing Multi-Block Streams. 2008-01-24 00:46:05 +02:00
Lasse Collin
db9df0a960 Fix decoding of empty Metadata Blocks, that don't have
even the Metadata Flags field. Earlier the code allowed
such files; now they are prohibited as the file format
specification requires.
2008-01-23 23:43:00 +02:00
Lasse Collin
765f0b05f6 Fix a bug related to 99e12af4e2.
lzma_metadata.header_metadata_size was not properly set to
zero if the Metadata had only the Metadata Flags field.
2008-01-23 23:38:18 +02:00
Lasse Collin
3a7cc5c3de Fix decoding of Extra Records that have empty Data. 2008-01-23 23:35:49 +02:00
Lasse Collin
e5fdec93e2 Add the trailing '\0' to lzma_extra.data as the API header
already documents.
2008-01-23 22:02:38 +02:00
Lasse Collin
ed40dc5a2c Added debug/full_flush.c. 2008-01-23 21:21:21 +02:00
Lasse Collin
ae0cd09a66 Return LZMA_STREAM_END instead of LZMA_OK if
LZMA_SYNC_FLUSH or LZMA_FULL_FLUSH is used when
there's no unfinished Block open.
2008-01-23 21:05:33 +02:00
Lasse Collin
0e80ded13d Added bad-single-none-footer_filter_flags.lzma and
bad-single-none-too_long_vli.lzma.
2008-01-23 20:05:01 +02:00
Lasse Collin
8c8eb14055 Fixed a typo. 2008-01-23 13:42:35 +02:00
Lasse Collin
980f65a9a1 Fix a memory leak in the Subblock encoder. 2008-01-23 13:40:45 +02:00
Lasse Collin
99e12af4e2 Fix Size of Header Metadata Block handling. Now
lzma_metadata.header_metadata_size == LZMA_VLI_VALUE_UNKNOWN
is not allowed at all. To indicate missing Header Metadata
Block, header_metadata_size must be set to zero. This is
what Metadata decoder does after this patch too.

Note that other missing fields in lzma_metadata are still
indicated with LZMA_VLI_VALUE_UNKNOWN. This isn't as
illogical as it sounds at first, because missing Size of
Header Metadata Block means that Header Metadata Block is
not present in the Stream. With other Metadata fields,
a missing field means only that the value is unknown.
2008-01-23 13:36:07 +02:00
Lasse Collin
58b78ab20c Fix a memory leak in metadata_decoder.c. 2008-01-23 13:15:55 +02:00
Lasse Collin
4d8cdbdab4 Fix the fix 863028cb7a which
just moved to problem. Now it's really fixed.
2008-01-23 13:13:58 +02:00
Lasse Collin
67321de963 Take advantage of return_if_error() macro in
lzma_info_metadata_set() in info.c.
2008-01-23 00:21:04 +02:00
Lasse Collin
863028cb7a Fixed a dangling pointer that caused invalid free(). 2008-01-23 00:18:32 +02:00
Lasse Collin
cf49f42a6b Added lzma_easy_* functions. These should make using
liblzma as easy as using zlib, because the easy API
don't require developers to know any fancy LZMA options.

Note that Multi-Block Stream encoding is currently broken.
The easy API should be OK, the bug(s) are elsewhere.
2008-01-22 22:49:24 +02:00
Lasse Collin
1747b85a43 Fix Multi-Block Stream encoder's EOPM usage. 2008-01-22 21:16:22 +02:00
Lasse Collin
0ed6f1adce Made lzma_extra pointers const in lzma_options_stream. 2008-01-22 00:15:11 +02:00
Lasse Collin
305afa38f6 Updated debug/sync_flush.c. 2008-01-20 20:15:21 +02:00
Lasse Collin
d53e9b7705 Added debug/repeat.c. 2008-01-20 20:14:26 +02:00
Lasse Collin
107259e306 Fix alignment handling bugs in Subblock encoder.
This leaves one known alignment bug unfixed: If repeat count
doesn't fit into 28-bit integer, the encoder has to split
this to multiple Subblocks with Subblock Type `Repeating Data'.
The extra Subblocks may have wrong alignment. Correct alignment
is restored after the split Repeating Data has been completely
written out.

Since the encoder doesn't even try to fix the alignment unless
the size of Data is at least 4 bytes, to trigger this bug you
need at least 4 GiB of repeating data with sequence length of
4 or more bytes. Since the worst thing done by this bug is
misaligned data (no data corruption), this bug simply isn't
worth fixing, because a proper fix isn't simple.
2008-01-20 20:12:58 +02:00
Lasse Collin
e141fe1895 Implemented LZMA_SYNC_FLUSH support to the Subblock encoder.
The API for handing Subfilters was changed to make it
consistent with LZMA_SYNC_FLUSH.

A few sanity checks were added for Subfilter handling. Some
small bugs were fixed. More comments were added.
2008-01-19 21:16:33 +02:00
Lasse Collin
23c227a864 Revised the Delta filter implementation. The initialization
function is still shared between encoder and decoder, but the
actual coding is in separate files for encoder and decoder.

There are now separate functions for the actual delta
calculation depending on if Delta is the last filter in the
chain or not. If it is the last, the new code copies the
data from input to output buffer and does the delta
calculation at the same time. The old code first copied the
data, then did the delta in the target buffer, which required
reading through the data twice.

Support for LZMA_SYNC_FLUSH was added to the Delta encoder.
This doesn't change anything in the file format.
2008-01-19 15:19:21 +02:00
Lasse Collin
61dc82f3e3 Added the debug directory and the first debug tool
(sync_flush). These tools are not built unless the
user runs "make" in the debug directory.
2008-01-18 20:18:08 +02:00
Lasse Collin
0ae3208db9 Added test files to test usage of flush marker in LZMA. 2008-01-18 20:13:00 +02:00
Lasse Collin
ab5feaf1fc Fix LZMA_SYNC_FLUSH handling in LZ and LZMA encoders.
That code is now almost completely in LZ coder, where
it can be shared with other LZ77-based algorithms in
future.
2008-01-18 20:02:52 +02:00
Lasse Collin
079c4f7fc2 Don't add -g to CFLAGS when --enable-debug is specified.
It's the job of the user to put that in CFLAGS.
2008-01-18 17:21:24 +02:00
Lasse Collin
61d1784d8f Set stdin and stdout to binary mode on Windows. This patch is
a forward port of b7b22fcb979a16d3a47c8001f058c9f7d4416068
from lzma-utils-legacy.git. I don't know if the new code base
builds on Windows, but this is a start.
2008-01-18 14:17:37 +02:00
Lasse Collin
c9cba97691 Added test_compress.sh and bunch of files needed by it.
This new set of tests compress and decompress several
test files with many different compression options.
This set of tests will be extended later.
2008-01-18 00:50:29 +02:00
Lasse Collin
33be3c0e24 Subblock decoder: Don't exit the main loop in decode_buffer()
too early if we hit End of Input while decoding a Subblock of
type Repeating Data. To keep the loop termination condition
elegant, the order of enumerations in coder->sequence were
changed.

To keep the case-labels in roughly the same order as the
enumerations in coder->sequence, large chunks of code was
moved around. This made the diff big and ugly compared to
the amount of the actual changes made.
2008-01-17 18:56:53 +02:00
Lasse Collin
b254bd97b1 Fix wrong too small size of argument unfiltered_max
in ia64_coder_init(). It triggered assert() in
simple_coder.c, and could have caused a buffer overflow.

This error was probably a copypaste mistake, since most
of the simple filters use unfiltered_max = 4.
2008-01-17 17:39:42 +02:00
Lasse Collin
8f5794c8f1 Added --delta to the output of "lzma --help". 2008-01-17 17:27:45 +02:00
Lasse Collin
f88590e001 Fix Subblock docoder: If Subblock filter was used with known
Uncompressed Size, and the last output byte was from RLE,
the code didn't stop decoding as it should have done.
2008-01-17 13:14:20 +02:00
Lasse Collin
bc0b945ca3 Tiny non-technical edits to file-format.txt. 2008-01-16 16:33:37 +02:00
Lasse Collin
7599bb7064 Plugged a memory leak in stream_decoder.c. 2008-01-16 14:48:04 +02:00
Lasse Collin
0b58153931 Added memory leak detection to lzmadec.c. 2008-01-16 14:47:27 +02:00
Lasse Collin
5b5b13c7bb Added lzma_memlimit_count(). 2008-01-16 14:46:50 +02:00
Lasse Collin
19389f2b82 Added ARRAY_SIZE(array) macro. 2008-01-16 14:31:44 +02:00
Lasse Collin
9bc33a54cb Make Uncompresed Size validation more strict
in alone_decoder.c.
2008-01-16 13:27:03 +02:00
Lasse Collin
01d71d60b7 Free the allocated memory in lzmadec if debugging is
enabled. This should make it possible to detect possible
memory leaks with Valgrind.
2008-01-15 17:46:59 +02:00
Lasse Collin
8235e6e5b2 Fix memory leaks from test_block_header.c. 2008-01-15 16:25:38 +02:00
Lasse Collin
f10fc6a69d Use fastpos.h when encoding LZMA dictionary size in
Filter Flags encoder.
2008-01-15 14:23:35 +02:00
Lasse Collin
e5728142a2 Revised the fastpos code. It now uses the slightly faster
table-based version from LZMA SDK 4.57. This should be
fast on most systems.

A simpler and smaller alternative version is also provided.
On some CPUs this can be even a little faster than the
default table-based version (see comments in fastpos.h),
but on most systems the table-based code is faster.
2008-01-15 14:02:22 +02:00
Lasse Collin
10437b5b56 Added bsr.h. 2008-01-15 13:32:13 +02:00
Lasse Collin
f3c88e8b8d Fixed assembler detection in configure.ac, and added
detection for x86_64.
2008-01-15 13:29:14 +02:00
Lasse Collin
54ec204f58 Omit invalid space from printf() format string
in price_table_gen.c.
2008-01-15 12:20:41 +02:00
Lasse Collin
01b4b19f49 Removed a few unused macros from lzma_common.h. 2008-01-15 09:54:34 +02:00
Lasse Collin
19bd7f3cf2 Fix a typo in lzma_encoder.c. 2008-01-15 08:37:42 +02:00
Lasse Collin
9f9b198301 Convert bittree_get_price() and bittree_reverse_get_price()
from macros to inline functions.
2008-01-15 08:36:25 +02:00
Lasse Collin
78e85cb1a7 Fix CRC code in case --enable-small is used. 2008-01-15 07:44:59 +02:00
Lasse Collin
949d4346e2 Fix typo in test_index.c. 2008-01-15 07:41:39 +02:00
Lasse Collin
d13d693155 Added precomputed range coder probability price table. 2008-01-15 07:40:21 +02:00
Lasse Collin
362dc3843b Remove RC_BUFFER_SIZE from lzma_encoder_private.h
and replace it with a sanity check.
2008-01-14 13:42:43 +02:00
Lasse Collin
e22b37968d Major changes to LZ encoder, LZMA encoder, and range encoder.
These changes implement support for LZMA_SYNC_FLUSH in LZMA
encoder, and move the temporary buffer needed by range encoder
from lzma_range_encoder structure to lzma_lz_encoder.
2008-01-14 13:39:54 +02:00
Lasse Collin
b59ef39737 Added one assert() to process.c of the command line tool. 2008-01-14 13:34:29 +02:00
Lasse Collin
9547e734a0 Don't use coder->lz.stream_end_was_reached in assertions
in match_c.h.
2008-01-14 12:09:52 +02:00
Lasse Collin
3e09e1c058 In lzma_read_match_distances(), don't use
coder->lz.stream_end_was_reached. That variable
will be removed, and the check isn't required anyway.
Rearrange the check so that it doesn't make one to
think that there could be an integer overflow.
2008-01-14 12:08:02 +02:00
Lasse Collin
a670fec802 Small LZMA_SYNC_FLUSH fixes to Block and Single-Stream encoders. 2008-01-14 11:56:41 +02:00
Lasse Collin
3599dba957 More fixes to LZMA decoder's flush marker handling. 2008-01-14 11:54:56 +02:00
Lasse Collin
f73c2ab607 Eliminate lzma_lz_encoder.must_move_pos. It's needed
only in one place which isn't performance criticial.
2008-01-10 17:13:42 +02:00
Lasse Collin
382808514a Define HAVE_ASM_X86 when x86 assembler optimizations are
used. This #define will be useful for inline assembly.
2008-01-09 20:05:57 +02:00
Lasse Collin
0e70fbe403 Added good-single-none-empty_3.lzma and
bad-single-none-empty.lzma.
2008-01-09 12:06:46 +02:00
Lasse Collin
379fbbe84d Take advantage of return_if_error() in block_decoder.c. 2008-01-08 23:11:59 +02:00
Lasse Collin
97d5fa8207 Updated tests/files/README. 2008-01-08 23:10:57 +02:00
Lasse Collin
3bb9bb3109 Added test files with empty Compressed Data. 2008-01-08 23:05:40 +02:00
Lasse Collin
7054c5f588 Fix decoding of Blocks that have only Block Header. 2008-01-08 22:58:42 +02:00
Lasse Collin
753e4d95cd Added good-single-subblock_implicit.lzma. 2008-01-08 22:27:46 +02:00
Lasse Collin
faeac7b7ac Disable CRC32 from Block Headers when --check=none
has been specified.
2008-01-08 18:50:30 +02:00
Lasse Collin
a751126dbb Fixed encoding of empty files. Arguments to is_size_valid()
were in wrong order in block_encoder.c.
2008-01-08 13:36:29 +02:00
Lasse Collin
9080267603 Added a few test files. 2008-01-08 13:35:36 +02:00
Lasse Collin
b4943ccf73 Avoid using ! in test_files.sh, because that doesn't work
with some ancient /bin/sh versions.
2008-01-08 12:29:58 +02:00
Lasse Collin
e2417b2b91 More pre-C99 inttypes.h compatibility fixes. Now the code
should work even if the system has no inttypes.h.
2008-01-08 00:48:30 +02:00
Lasse Collin
5d227e51c2 Updated fi.po although it's currently pretty much crap. 2008-01-07 23:25:32 +02:00
Lasse Collin
c7189d981a Test for $GCC = yes instead of if it is non-empty. This
way it is possible to use ac_cv_c_compiler_gnu=no to
force configure to think it is using non-GNU C compiler.
2008-01-07 23:14:25 +02:00
Lasse Collin
3dbbea82b7 Added test_files.sh to tests/Makefile.am so it gets
included in the tarball with "make dist".
2008-01-07 21:49:41 +02:00
Lasse Collin
2fd2d18154 Cosmetic edit to test_files.sh. 2008-01-07 18:22:24 +02:00
Lasse Collin
9a71d57310 Added tests/files/README. 2008-01-07 18:09:44 +02:00
Lasse Collin
47f48fe993 Tell in COPYING that everything in tests/files is
public domain.
2008-01-07 14:20:57 +02:00
Lasse Collin
3502b3e1d0 Cleaned up the tests/files directory. 2008-01-07 14:19:05 +02:00
Lasse Collin
908b2ac604 Added test_files.sh to test decoding of the files in
the tests/files directory. It doesn't test the malicious
files yet.
2008-01-07 13:49:19 +02:00
Lasse Collin
ecb2a6548f Updated README regarding the assembler optimizations. 2008-01-07 11:23:13 +02:00
Lasse Collin
eacb805043 Updated THANKS. 2008-01-07 10:58:00 +02:00
Lasse Collin
1239649f96 Cosmetic changes to configure.ac. 2008-01-06 21:47:17 +02:00
Lasse Collin
88ee301ec2 Automatically disable assembler code on Darwin x86.
Darwin has different ABI than GNU+Linux and Solaris,
thus the assembler code doesn't assemble on Darwin.
2008-01-06 19:46:38 +02:00
Lasse Collin
c15a7abf66 With printf(), use PRIu64 with a cast to uint64_t instead
of %zu, because some pre-C99 libc versions don't support %zu.
2008-01-06 19:45:27 +02:00
Lasse Collin
4e7e54c4c5 Introduced compatibility with systems that have pre-C99
or no inttypes.h. This is useful when the compiler has
good enough support for C99, but libc headers don't.

Changed liblzma API so that sys/types.h and inttypes.h
have to be #included before #including lzma.h. On systems
that don't have C99 inttypes.h, it's the problem of the
applications to provide the required types and macros
before #including lzma.h.

If lzma.h defined the missing types and macros, it could
conflict with third-party applications whose configure
has detected that the types are missing and defined them
in config.h already. An alternative would have been
introducing lzma_uint32 and similar types, but that would
just be an extra pain on modern systems.
2008-01-06 16:27:41 +02:00
Lasse Collin
a71864f77d Fix typo in comment (INT64_MAX -> UINT64_MAX). 2008-01-05 19:57:00 +02:00
Lasse Collin
072927905a Rearranged testing of GCC-specific flags. 2008-01-05 19:42:04 +02:00
Lasse Collin
d160ee3259 Another bug fix for flush marker detection. 2008-01-05 01:20:24 +02:00
Lasse Collin
fc67f79f60 Fix stupid bugs in flush marker detection. 2008-01-04 21:37:01 +02:00
Lasse Collin
0029cbbabe Added support for flush marker, which will be in files
that use LZMA_SYNC_FLUSH with encoder (not implemented
yet). This is a new feature in the raw LZMA format,
which isn't supported by old decoders. This shouldn't
be a problem in practice, since lzma_alone_encoder()
will not allow LZMA_SYNC_FLUSH, and thus not allow
creating files on decodable with old decoders.

Made lzma_decoder.c to require tab width of 4 characters
if one wants to fit the code in 80 columns. This makes
the code easier to read.
2008-01-04 21:30:33 +02:00
Lasse Collin
bbfd1f6ab0 Moved range decoder initialization (reading the first
five input bytes) from LZMA decoder to range decoder
header. Did the same for decoding of direct bits.
2008-01-04 20:45:05 +02:00
Lasse Collin
5db745cd2a Added a note to README that --disable-assembler
must be used on Darwin.
2007-12-14 11:15:21 +02:00
Lasse Collin
44b333d461 Use the filename suffix .S instead of .s for assembler files
so that the preprocessor removes the /* */ style comments,
which are not supported by some non-GNU assemblers (Solaris)
that otherwise work with this code.
2007-12-14 10:07:10 +02:00
Lasse Collin
ec1c82b2e8 Fixed wrong symbol name in crc64_x86.s. 2007-12-14 09:59:05 +02:00
Lasse Collin
2881570df6 Use .globl instead of .global in x86 assembler code for
better portability. Still needs fixing the commenting.
2007-12-14 09:53:24 +02:00
Lasse Collin
698470b8f3 Fixed a few short options that take an argument.
short_opts[] was missing colons to indicate
required argument. Thanks to Fabio Pedretti for
the bug report.
2007-12-13 20:14:37 +02:00
Lasse Collin
918bcb0e07 Removed uncompressed size tracking from Delta encoder too. 2007-12-11 17:08:04 +02:00
Lasse Collin
3e16d51dd6 Remove uncompressed size tracking from the filter encoders.
It's not strictly needed there, and just complicates the
code. LZ encoder never even had this feature.

The primary reason to have uncompressed size tracking in
filter encoders was validating that the application
doesn't give different amount of input that it had
promised. A side effect was to validate internal workings
of liblzma.

Uncompressed size tracking is still present in the Block
encoder. Maybe it should be added to LZMA_Alone and raw
encoders too. It's simpler to have one coder just to
validate the uncompressed size instead of having it
in every filter.
2007-12-11 16:49:19 +02:00
Lasse Collin
5286723e0d Get rid of no-NLS gnulib. I don't know how to get it
working with Automake. People who want smaller lzmadec
should use --disable-nls on non-GNU systems.
2007-12-11 14:10:53 +02:00
Lasse Collin
ce8b036a6c Fixed a typo in tests/Makefile.am which prevented
building the tests if gnulib was needed.
2007-12-11 14:09:35 +02:00
Lasse Collin
7c1ad41eb6 Fixed wrong type of flags_size in Subblock encoder. 2007-12-11 11:18:58 +02:00
Lasse Collin
ce64df7162 Bumped version number to 4.42.3alpha. 2007-12-10 20:44:16 +02:00
177 changed files with 4966 additions and 1515 deletions

View File

@@ -5,7 +5,8 @@ LZMA Utils Licenses
Different licenses apply to different files in this package. Here
is a rough summary of which license apply to which parts of this
package (but check the individual files to be sure!):
- Everything under src/liblzma/check is public domain.
- Everything under src/liblzma/check and tests/files is public
domain.
- Everything else under the src directory is under the GNU LGPL
2.1 or (at your opinion) any later version.
- Outside the src directory, there are some files that are under

View File

@@ -12,6 +12,7 @@
## Lesser General Public License for more details.
##
DIST_SUBDIRS = lib src po tests debug
SUBDIRS =
if COND_GNULIB
@@ -20,7 +21,6 @@ endif
SUBDIRS += src po tests
EXTRA_DIST = \
m4 \
config.rpath \
@@ -32,4 +32,8 @@ EXTRA_DIST = \
COPYING.LGPLv2.1
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign
# This works with GNU tar and gives cleaner package than normal 'make dist'.
mydist:
TAR_OPTIONS='--owner=0 --group=0 --numeric-owner --mode=u+rw,go+r-w' \
$(MAKE) dist-gzip

35
README
View File

@@ -59,6 +59,35 @@ Supported platforms
in C89 or C++.
Version numbering
Starting from LZMA Utils 5, the version number of LZMA Utils has
absolutely nothing to do with the version number of LZMA SDK or
7-Zip. The new version number format of LZMA Utils is X.Y.ZS:
- X is the major version. When this is incremented, the library
API and ABI break.
- Y is the minor version. It is incremented when new features are
added without breaking existing API or ABI. Even Y indicates
stable release and odd Y indicates unstable (alpha or beta
version).
- Z is the revision. This has different meaning for stable and
unstable releases:
* Stable: Z is incremented when bugs get fixed without adding
any new features.
* Unstable: Z is just a counter. API or ABI of features added
in earlier unstable releases having the same X.Y may break.
- S indicates stability of the release. It is missing from the
stable releases where Y is an even number. When Y is odd, S
is either "alpha" or "beta" to make it very clear that such
versions are not stable releases. The same X.Y.Z combination is
not used for more than one stability level i.e. after X.Y.Zalpha,
the next version can be X.Y.(Z+1)beta but not X.Y.Zbeta.
configure options
If you are not familiar with `configure' scripts, read the file
@@ -113,7 +142,11 @@ configure options
All the assembler code in liblzma is position-independent
code, which is suitable for use in shared libraries and
position-independent executables.
position-independent executables. So far only i386
instructions are used, but the code is optimized for i686
class CPUs. If you are compiling liblzma exclusively for
pre-i686 systems, you may want to disable the assembler
code.
--enable-small
Omits precomputed tables. This makes liblzma a few KiB

3
THANKS
View File

@@ -6,17 +6,20 @@ Some people have helped more, some less, some don't even know they have
been helpful, but nevertheless everyone's help has been important. :-)
In alphabetical order:
- Mark Adler
- Nelson H. F. Beebe
- Anders F. Björklund
- İsmail Dönmez
- Jean-loup Gailly
- Per Øyvind Karlsen
- Ville Koskinen
- Stephan Kulow
- Jim Meyering
- Igor Pavlov
- Mikko Pouru
- Alexandre Sauvé
- Julian Seward
- Mohammed Adnène Trojette
- Andreas Zieringer
Also thanks to all the people who have participated the Tukaani project
and others who I have forgot.

View File

@@ -26,7 +26,7 @@ AC_PREREQ(2.61)
# [LZMA] instead of [LZMA utils] since I prefer to have lzma-version.tar.gz
# instead of lzma-utils-version.tar.gz.
AC_INIT([LZMA], [4.42.2alpha], [lasse.collin@tukaani.org])
AC_INIT([LZMA], [4.999.3alpha], [lasse.collin@tukaani.org])
AC_CONFIG_SRCDIR([src/liblzma/common/common.h])
AC_CONFIG_HEADER([config.h])
@@ -47,7 +47,6 @@ AC_MSG_CHECKING([if debugging code should be compiled])
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [Enable debugging code.]),
[], enable_debug=no)
if test "x$enable_debug" = xyes; then
CFLAGS="-g $CFLAGS"
AC_MSG_RESULT([yes])
else
AC_DEFINE(NDEBUG, 1, [Define to disable debugging code.])
@@ -299,11 +298,27 @@ AC_ARG_ENABLE(assembler, AC_HELP_STRING([--disable-assembler],
if test "x$enable_assembler" = xyes; then
case $host_cpu in
i?86) enable_assembler=x86 ;;
x86_64) enable_assembler=x86_64 ;;
*) enable_assembler=no ;;
esac
# Darwin has different ABI than GNU+Linux and Solaris,
# and the assembler code doesn't assemble.
case $host_os in
darwin*) enable_assembler=no ;;
*) ;;
esac
fi
case $enable_assembler in
x86|no) ;;
x86)
AC_DEFINE([HAVE_ASM_X86], 1,
[Define to 1 if using x86 assembler optimizations.])
;;
x86_64)
AC_DEFINE([HAVE_ASM_X86_64], 1,
[Define to 1 if using x86_64 assembler optimizations.])
;;
no)
;;
*)
AC_MSG_RESULT([])
AC_MSG_ERROR([--enable-assembler accepts only \`yes', \`no', or \`x86'.])
@@ -328,6 +343,10 @@ fi
AC_MSG_RESULT([$enable_small])
AM_CONDITIONAL(COND_SMALL, test "x$enable_small" = xyes)
###############################################################################
# Checks for programs.
###############################################################################
echo
echo "Initializing Automake:"
@@ -335,17 +354,11 @@ echo "Initializing Automake:"
CXX=no
F77=no
AM_INIT_AUTOMAKE
AC_USE_SYSTEM_EXTENSIONS
###############################################################################
# Checks for programs.
###############################################################################
AM_INIT_AUTOMAKE([1.10 foreign tar-v7 filename-length-max=99])
AC_PROG_LN_S
AM_PROG_CC_C_O
AM_PROG_AS
AC_PROG_LN_S
AC_USE_SYSTEM_EXTENSIONS
echo
echo "Threading support:"
@@ -392,10 +405,21 @@ AC_CHECK_HEADERS([assert.h errno.h byteswap.h sys/param.h sys/sysctl.h],
# Checks for typedefs, structures, and compiler characteristics.
###############################################################################
AC_HEADER_STDBOOL
AC_C_INLINE
AC_C_RESTRICT
AC_HEADER_STDBOOL
AC_TYPE_UINT8_T
AC_TYPE_INT32_T
AC_TYPE_UINT32_T
AC_TYPE_INT64_T
AC_TYPE_UINT64_T
AC_TYPE_UINTPTR_T
AC_CHECK_SIZEOF([unsigned long])
AC_CHECK_SIZEOF([size_t])
# The command line tool can copy high resolution timestamps if such
# information is availabe in struct stat. Otherwise one second accuracy
# is used. Most systems seem to have st_xtim but BSDs have st_xtimespec.
@@ -516,7 +540,7 @@ main()
Wno_uninitialized=no
if test -n "$GCC" ; then
if test "x$GCC" = xyes ; then
echo
echo "GCC extensions:"
gl_VISIBILITY
@@ -545,13 +569,29 @@ if test -n "$GCC" ; then
# * -Winline, -Wdisabled-optimization, -Wunsafe-loop-optimizations
# don't seem so useful here; at least the last one gives some
# warnings which are not bugs.
for NEW_FLAG in -Wextra -Wformat=2 -Winit-self -Wstrict-aliasing=2 \
-Wfloat-equal -Wshadow -Wpointer-arith \
-Wbad-function-cast -Wwrite-strings \
-Waggregate-return -Wstrict-prototypes \
-Wold-style-definition -Wmissing-prototypes \
-Wmissing-declarations -Wmissing-noreturn \
-Wredundant-decls
#
# The flags are in reverse order below so they end up in "beautiful"
# order on the actual command line.
for NEW_FLAG in \
-Wredundant-decls \
-Wmissing-noreturn \
-Wmissing-declarations \
-Wmissing-prototypes \
-Wold-style-definition \
-Wstrict-prototypes \
-Waggregate-return \
-Wwrite-strings \
-Wbad-function-cast \
-Wpointer-arith \
-Wshadow \
-Wfloat-equal \
-Wstrict-aliasing=2 \
-Winit-self \
-Wformat=2 \
-Wextra \
-Wall \
-pedantic \
-std=c99
do
AC_MSG_CHECKING([if $CC accepts $NEW_FLAG])
OLD_CFLAGS="$CFLAGS"
@@ -571,9 +611,6 @@ if test -n "$GCC" ; then
if test "x$enable_werror" = "xyes"; then
CFLAGS="-Werror $CFLAGS"
fi
# IIRC these work with all GCC versions that support -std=c99:
CFLAGS="-std=c99 -pedantic -Wall $CFLAGS"
fi
AM_CONDITIONAL([COND_WNO_UNINITIALIZED], test "x$Wno_uninitialized" = "xyes")
@@ -609,6 +646,7 @@ AC_CONFIG_FILES([
src/lzmadec/Makefile
src/scripts/Makefile
tests/Makefile
debug/Makefile
])
AC_OUTPUT

33
debug/Makefile.am Normal file
View File

@@ -0,0 +1,33 @@
##
## Copyright (C) 2008 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.
##
noinst_PROGRAMS = \
repeat \
sync_flush \
full_flush \
memusage
AM_CPPFLAGS = \
-I@top_srcdir@/src/common \
-I@top_srcdir@/src/liblzma/api
AM_LDFLAGS = -static
LDADD = \
@top_builddir@/src/liblzma/liblzma.la \
@LTLIBINTL@
if COND_GNULIB
LDADD += @top_builddir@/lib/libgnu.a
endif

17
debug/README Normal file
View File

@@ -0,0 +1,17 @@
Debug tools
-----------
This directory contains a few tiny programs that may be helpful when
debugging LZMA Utils.
These tools are not meant to be installed. Often one needs to edit
the source code a little to make the programs do the wanted things.
If you don't know how these programs could help you, it is likely
that they really are useless to you.
These aren't intended to be used as example programs. They take some
shortcuts here and there, which correct programs should not do. Many
possible errors (especially I/O errors) are ignored. Don't report
bugs or send patches to fix this kind of bugs.

105
debug/full_flush.c Normal file
View File

@@ -0,0 +1,105 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file full_flush.c
/// \brief Encode files using LZMA_FULL_FLUSH
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "sysdefs.h"
#include <stdio.h>
static lzma_stream strm = LZMA_STREAM_INIT;
static FILE *file_in;
static void
encode(size_t size, lzma_action action)
{
static const size_t CHUNK = 64;
uint8_t in[CHUNK];
uint8_t out[CHUNK];
lzma_ret ret;
do {
if (strm.avail_in == 0 && size > 0) {
const size_t amount = MIN(size, CHUNK);
strm.avail_in = fread(in, 1, amount, file_in);
strm.next_in = in;
size -= amount; // Intentionally not using avail_in.
}
strm.next_out = out;
strm.avail_out = CHUNK;
ret = lzma_code(&strm, size == 0 ? action : LZMA_RUN);
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
fprintf(stderr, "%s:%u: %s: ret == %d\n",
__FILE__, __LINE__, __func__, ret);
exit(1);
}
fwrite(out, 1, CHUNK - strm.avail_out, stdout);
} while (size > 0 || strm.avail_out == 0);
if ((action == LZMA_RUN && ret != LZMA_OK)
|| (action != LZMA_RUN && ret != LZMA_STREAM_END)) {
fprintf(stderr, "%s:%u: %s: ret == %d\n",
__FILE__, __LINE__, __func__, ret);
exit(1);
}
}
int
main(int argc, char **argv)
{
lzma_init_encoder();
file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
// Config
lzma_options_stream opt_stream = {
.check = LZMA_CHECK_CRC32,
.has_crc32 = true,
.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
.alignment = 0,
};
opt_stream.filters[0].id = LZMA_VLI_VALUE_UNKNOWN;
opt_stream.metadata_filters[0].id = LZMA_VLI_VALUE_UNKNOWN;
opt_stream.header = NULL;
opt_stream.footer = NULL;
// Init
if (lzma_stream_encoder_multi(&strm, &opt_stream) != LZMA_OK) {
fprintf(stderr, "init failed\n");
exit(1);
}
// Encoding
encode(0, LZMA_FULL_FLUSH);
encode(6, LZMA_FULL_FLUSH);
encode(0, LZMA_FULL_FLUSH);
encode(7, LZMA_FULL_FLUSH);
encode(0, LZMA_FULL_FLUSH);
encode(0, LZMA_FINISH);
// Clean up
lzma_end(&strm);
return 0;
}

55
debug/memusage.c Normal file
View File

@@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file memusage.c
/// \brief Calculates memory usage using lzma_memory_usage()
///
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "sysdefs.h"
#include <stdio.h>
int
main(void)
{
lzma_options_lzma lzma = {
.dictionary_size = (1 << 27) + (1 << 26),
.literal_context_bits = 3,
.literal_pos_bits = 0,
.pos_bits = 2,
.preset_dictionary = NULL,
.preset_dictionary_size = 0,
.mode = LZMA_MODE_BEST,
.fast_bytes = 48,
.match_finder = LZMA_MF_BT4,
.match_finder_cycles = 0,
};
/*
lzma_options_filter filters[] = {
{ LZMA_FILTER_LZMA,
(lzma_options_lzma *)&lzma_preset_lzma[6 - 1] },
{ UINT64_MAX, NULL }
};
*/
lzma_options_filter filters[] = {
{ LZMA_FILTER_LZMA, &lzma },
{ UINT64_MAX, NULL }
};
printf("%u MiB\n", lzma_memory_usage(filters, true));
return 0;
}

43
debug/repeat.c Normal file
View File

@@ -0,0 +1,43 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file repeat.c
/// \brief Repeats given string given times
///
/// This program can be useful when debugging run-length encoder in
/// the Subblock filter, especially the condition when repeat count
/// doesn't fit into 28-bit integer.
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "sysdefs.h"
#include <stdio.h>
int
main(int argc, char **argv)
{
if (argc != 3) {
fprintf(stderr, "Usage: %s COUNT STRING\n", argv[0]);
exit(1);
}
unsigned long long count = strtoull(argv[1], NULL, 10);
const size_t size = strlen(argv[2]);
while (count-- != 0)
fwrite(argv[2], 1, size, stdout);
return !!(ferror(stdout) || fclose(stdout));
}

138
debug/sync_flush.c Normal file
View File

@@ -0,0 +1,138 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file sync_flush.c
/// \brief Encode files using LZMA_SYNC_FLUSH
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "sysdefs.h"
#include <stdio.h>
static lzma_stream strm = LZMA_STREAM_INIT;
static FILE *file_in;
static void
encode(size_t size, lzma_action action)
{
static const size_t CHUNK = 64;
uint8_t in[CHUNK];
uint8_t out[CHUNK];
lzma_ret ret;
do {
if (strm.avail_in == 0 && size > 0) {
const size_t amount = MIN(size, CHUNK);
strm.avail_in = fread(in, 1, amount, file_in);
strm.next_in = in;
size -= amount; // Intentionally not using avail_in.
}
strm.next_out = out;
strm.avail_out = CHUNK;
ret = lzma_code(&strm, size == 0 ? action : LZMA_RUN);
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
fprintf(stderr, "%s:%u: %s: ret == %d\n",
__FILE__, __LINE__, __func__, ret);
exit(1);
}
fwrite(out, 1, CHUNK - strm.avail_out, stdout);
} while (size > 0 || strm.avail_out == 0);
if ((action == LZMA_RUN && ret != LZMA_OK)
|| (action != LZMA_RUN && ret != LZMA_STREAM_END)) {
fprintf(stderr, "%s:%u: %s: ret == %d\n",
__FILE__, __LINE__, __func__, ret);
exit(1);
}
}
int
main(int argc, char **argv)
{
lzma_init_encoder();
file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
// Config
lzma_options_lzma opt_lzma = {
.dictionary_size = 1 << 16,
.literal_context_bits = LZMA_LITERAL_CONTEXT_BITS_DEFAULT,
.literal_pos_bits = LZMA_LITERAL_POS_BITS_DEFAULT,
.pos_bits = LZMA_POS_BITS_DEFAULT,
.preset_dictionary = NULL,
.mode = LZMA_MODE_BEST,
.fast_bytes = 32,
.match_finder = LZMA_MF_BT3,
.match_finder_cycles = 0,
};
lzma_options_delta opt_delta = {
.distance = 16
};
lzma_options_subblock opt_subblock = {
.allow_subfilters = true,
.alignment = 8, // LZMA_SUBBLOCK_ALIGNMENT_DEFAULT,
.subblock_data_size = LZMA_SUBBLOCK_DATA_SIZE_DEFAULT,
.rle = 1, // LZMA_SUBBLOCK_RLE_OFF,
.subfilter_mode = LZMA_SUBFILTER_SET,
};
opt_subblock.subfilter_options.id = LZMA_FILTER_LZMA;
opt_subblock.subfilter_options.options = &opt_lzma;
opt_subblock.subfilter_options.id = LZMA_FILTER_DELTA;
opt_subblock.subfilter_options.options = &opt_delta;
lzma_options_stream opt_stream = {
.check = LZMA_CHECK_NONE,
.has_crc32 = false,
.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
.alignment = 0,
};
opt_stream.filters[0].id = LZMA_FILTER_SUBBLOCK;
opt_stream.filters[0].options = &opt_subblock;
opt_stream.filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
// Init
if (lzma_stream_encoder_single(&strm, &opt_stream) != LZMA_OK) {
fprintf(stderr, "init failed\n");
exit(1);
}
// Encoding
encode(0, LZMA_SYNC_FLUSH);
encode(6, LZMA_SYNC_FLUSH);
encode(0, LZMA_SYNC_FLUSH);
encode(6, LZMA_SYNC_FLUSH);
encode(0, LZMA_SYNC_FLUSH);
encode(0, LZMA_FINISH);
// Clean up
lzma_end(&strm);
return 0;
// Prevent useless warnings so we don't need to have special CFLAGS
// to disable -Werror.
(void)opt_lzma;
(void)opt_subblock;
(void)opt_delta;
}

View File

@@ -86,7 +86,7 @@ The .lzma File Format
This document describes the .lzma file format (filename suffix
`.lzma', MIME type `application/x-lzma'). It is intended that
this format replace the format used by the LZMA_Alone tool
included in LZMA SDK up to and including version 4.43.
included in LZMA SDK up to and including version 4.57.
IMPORTANT: The version described in this document is a
draft, NOT a final, official version. Changes
@@ -112,7 +112,7 @@ The .lzma File Format
0.2. Changes
Last modified: 2007-12-02 22:40+0200
Last modified: 2008-02-01 19:25+0200
(A changelog will be kept once the first official version
is made.)
@@ -812,8 +812,8 @@ The .lzma File Format
When a filter that cannot embed End of Payload Marker is the
last filter in the chain, Subblock filter is appended to the
chain as an implicit filter. In the simplest case, this occurs
when no filters are specified, and Uncompressed Size is unknown
or the End of Payload Marker bit is set in Block Flags.
when no filters are specified, and the End of Payload Marker
bit is set in Block Flags.
4.1.3. With End of Payload Marker
@@ -1197,7 +1197,7 @@ The .lzma File Format
4.3.4.1. LZMA Properties
The LZMA Properties bits contain three properties. An
The LZMA Properties field contains three properties. An
abbreviation is given in parentheses, followed by the value
range of the property. The field consists of

View File

@@ -5,8 +5,14 @@ Introduction to liblzma
Writing applications to work with liblzma
liblzma API is split in several subheaders to improve readability and
maintainance. The subheaders must not be #included directly; simply
use `#include <lzma.h>' instead.
maintainance. The subheaders must not be #included directly. lzma.h
requires that certain integer types and macros are available when
the header is #included. On systems that have inttypes.h that conforms
to C99, the following will work:
#include <sys/types.h>
#include <inttypes.h>
#include <lzma.h>
Those who have used zlib should find liblzma's API easy to use.
To developers who haven't used zlib before, I recommend learning

View File

@@ -15,19 +15,11 @@
## Not using gnulib-tool, at least for now. Less mess this way.
## We need two builds of libgnu: one with NLS and one without.
## This is because lzma uses NLS but lzmadec doesn't, while
## both need GNU getopt_long().
noinst_LIBRARIES = libgnu.a libgnu_nls.a
noinst_LIBRARIES = libgnu.a
libgnu_a_SOURCES =
libgnu_a_DEPENDENCIES = $(LIBOBJS)
libgnu_a_LIBADD = $(LIBOBJS)
libgnu_a_CPPFLAGS = -DDISABLE_NLS=1
libgnu_nls_a_SOURCES =
libgnu_nls_a_DEPENDENCIES = $(LIBOBJS)
libgnu_nls_a_LIBADD = $(LIBOBJS)
EXTRA_DIST = gettext.h getopt_.h getopt.c getopt1.c getopt_int.h
BUILT_SOURCES = $(GETOPT_H)

View File

@@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fi\n"
"Report-Msgid-Bugs-To: lasse.collin@tukaani.org\n"
"POT-Creation-Date: 2007-12-10 14:34+0200\n"
"POT-Creation-Date: 2008-01-07 21:30+0200\n"
"PO-Revision-Date: 2007-08-09 22:14+0300\n"
"Last-Translator: Lasse Collin <lasse.collin@tukaani.org>\n"
"Language-Team: Finnish\n"
@@ -124,14 +124,14 @@ msgstr ""
msgid "With no FILE, or when FILE is -, read standard input.\n"
msgstr "Jos TIEDOSTOa ei ole annettu, tai se on \"-\", luetaan vakiosyötettä.\n"
#: src/lzma/help.c:143
#: src/lzma/help.c:144
msgid "On this system and configuration, the tool will use"
msgstr "Tässä järjestelmässä näillä asetuksilla, tämä työkalu käyttää"
#: src/lzma/help.c:144
#: src/lzma/help.c:145
#, c-format
msgid " * roughly %zu MiB of memory at maximum; and\n"
msgstr " * korkeintaan %zu MiB keskusmuistia (suurpiirteinen rajoitus); ja\n"
msgid " * roughly %<PRIu64> MiB of memory at maximum; and\n"
msgstr " * korkeintaan %<PRIu64> MiB keskusmuistia (suurpiirteinen rajoitus); ja\n"
#: src/lzma/help.c:147
msgid ""
@@ -141,7 +141,7 @@ msgstr ""
" * korkeintaan yhtä säiettä pakkaukseen tai purkuun.\n"
"\n"
#: src/lzma/help.c:151
#: src/lzma/help.c:152
#, c-format
msgid "Report bugs to <%s> (in English or Finnish).\n"
msgstr ""

View File

@@ -14,17 +14,6 @@
#ifndef PHYSMEM_H
#define PHYSMEM_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <inttypes.h>
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#if defined(HAVE_PHYSMEM_SYSCTL) || defined(HAVE_NCPU_SYSCTL)
# ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>

View File

@@ -31,7 +31,62 @@
# include <config.h>
#endif
#include "lzma.h"
#include <sys/types.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
// Be more compatible with systems that have non-conforming inttypes.h.
// We assume that int is 32-bit and that long is either 32-bit or 64-bit.
// Full Autoconf test could be more correct, but this should work well enough.
#ifndef UINT32_C
# define UINT32_C(n) n ## U
#endif
#ifndef UINT32_MAX
# define UINT32_MAX UINT32_C(4294967295)
#endif
#ifndef PRIu32
# define PRIu32 "u"
#endif
#ifndef PRIX32
# define PRIX32 "X"
#endif
#if SIZEOF_UNSIGNED_LONG == 4
# ifndef UINT64_C
# define UINT64_C(n) n ## ULL
# endif
# ifndef PRIu64
# define PRIu64 "llu"
# endif
# ifndef PRIX64
# define PRIX64 "llX"
# endif
#else
# ifndef UINT64_C
# define UINT64_C(n) n ## UL
# endif
# ifndef PRIu64
# define PRIu64 "lu"
# endif
# ifndef PRIX64
# define PRIX64 "lX"
# endif
#endif
#ifndef UINT64_MAX
# define UINT64_MAX UINT64_C(18446744073709551615)
#endif
#ifndef SIZE_MAX
# if SIZEOF_SIZE_T == 4
# define SIZE_MAX UINT32_MAX
# else
# define SIZE_MAX UINT64_MAX
# endif
#endif
#include <stdlib.h>
@@ -70,6 +125,8 @@ typedef unsigned char _Bool;
# include <memory.h>
#endif
#include "lzma.h"
////////////
// Macros //
@@ -97,4 +154,8 @@ typedef unsigned char _Bool;
# define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif
#endif

View File

@@ -22,6 +22,7 @@ nobase_include_HEADERS = \
lzma/check.h \
lzma/copy.h \
lzma/delta.h \
lzma/easy.h \
lzma/extra.h \
lzma/filter.h \
lzma/index.h \

View File

@@ -17,25 +17,37 @@
* 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.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Before #including this file, you must make the following types available:
* - size_t
* - uint8_t
* - int32_t
* - uint32_t
* - int64_t
* - uint64_t
*
* Before #including this file, you must make the following macros available:
* - UINT32_C(n)
* - UINT64_C(n)
* - UINT32_MAX
* - UINT64_MAX
*
* Easiest way to achieve the above is to #include sys/types.h and inttypes.h
* before #including lzma.h. However, some pre-C99 libc headers don't provide
* all the required types in inttypes.h (that file may even be missing).
* Portable applications need to provide these types themselves. This way
* liblzma API can use the standard types instead of defining its own
* (e.g. lzma_uint32).
*
* Note that the API still has lzma_bool, because using stdbool.h would
* break C89 and C++ programs on many systems.
*/
#ifndef LZMA_H
#define LZMA_H
/********************
* External headers *
********************/
/* size_t */
#include <sys/types.h>
/* NULL */
#include <stddef.h>
/* uint8_t, uint32_t, uint64_t, UINT32_C, UINT64_C, UINT64_MAX. */
#include <inttypes.h>
/******************
* GCC extensions *
******************/
@@ -99,6 +111,7 @@ extern "C" {
#include "lzma/alone.h"
#include "lzma/raw.h"
#include "lzma/auto.h"
#include "lzma/easy.h"
/* Advanced features */
#include "lzma/info.h"

View File

@@ -315,7 +315,7 @@ typedef struct lzma_internal_s lzma_internal;
* Application must not touch the `internal' pointer.
*/
typedef struct {
uint8_t *next_in; /**< Pointer to the next input byte. */
const uint8_t *next_in; /**< Pointer to the next input byte. */
size_t avail_in; /**< Number of available input bytes in next_in. */
uint64_t total_in; /**< Total number of bytes read by liblzma. */

174
src/liblzma/api/lzma/easy.h Normal file
View File

@@ -0,0 +1,174 @@
/**
* \file lzma/easy.h
* \brief Easy to use encoder initialization
*
* \author Copyright (C) 1999-2006 Igor Pavlov
* \author Copyright (C) 2008 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_H_INTERNAL
# error Never include this file directly. Use <lzma.h> instead.
#endif
/**
* \brief Compression level names for lzma_easy_* functions
*
* At the moment, all the compression levels support LZMA_SYNC_FLUSH.
* In future there may be levels that don't support LZMA_SYNC_FLUSH.
* However, the LZMA_SYNC_FLUSH support won't be removed from the
* existing compression levels.
*
* \note If liblzma is built without encoder support, or with some
* filters disabled, some of the compression levels may be
* unsupported. In that case, the initialization functions
* will return LZMA_HEADER_ERROR.
*/
typedef enum {
LZMA_EASY_COPY,
/**<
* No compression; the data is just wrapped into .lzma
* container.
*/
LZMA_EASY_LZMA_1,
/**<
* LZMA filter with fast compression (fast in terms of LZMA).
* If you are interested in the exact options used, see
* lzma_preset_lzma[0]. Note that the exact options may
* change between liblzma versions.
*
* At the moment, the command line tool uses these settings
* when `lzma -1' is used. In future, the command line tool
* may default to some more complex way to determine the
* settings used e.g. the type of files being compressed.
*
* LZMA_EASY_LZMA_2 is equivalent to lzma_preset_lzma[1]
* and so on.
*/
LZMA_EASY_LZMA_2,
LZMA_EASY_LZMA_3,
LZMA_EASY_LZMA_4,
LZMA_EASY_LZMA_5,
LZMA_EASY_LZMA_6,
LZMA_EASY_LZMA_7,
LZMA_EASY_LZMA_8,
LZMA_EASY_LZMA_9,
} lzma_easy_level;
/**
* \brief Default compression level for Data Blocks
*
* Data Blocks contain the actual compressed data. It's not straightforward
* to recommend a default level, because in some cases keeping the resource
* usage relatively low is more important that getting the maximum
* compression ratio.
*/
#define LZMA_EASY_DEFAULT LZMA_EASY_LZMA_7
/**
* \brief Default compression level for Metadata Blocks
*
* Metadata Blocks are present only in Multi-Block Streams. Metadata Blocks
* contain the Extra Records (if any) and some book-keeping data that is
* used by decoders.
*/
#define LZMA_EASY_METADATA_DEFAULT LZMA_EASY_LZMA_3
/**
* \brief Calculates rough memory requirements of a compression level
*
* This function is a wrapper for lzma_memory_usage(), which is declared
* in lzma/filter.h.
*
* \return Approximate memory usage of the encoder with the given
* compression level in mebibytes (value * 1024 * 1024 bytes).
* On error (e.g. compression level is not supported),
* UINT32_MAX is returned.
*/
extern uint32_t lzma_easy_memory_usage(lzma_easy_level level);
/**
* \brief Initializes Single-Block .lzma Stream encoder
*
* This function is intended for those who just want to use the basic LZMA
* features (that is, most developers out there). Lots of assumptions are
* made, which are correct for most situations or at least good enough.
*
* \param strm Pointer to lzma_stream that is at least initialized
* with LZMA_STREAM_INIT.
* \param level Compression level to use. This selects a set of
* compression settings from a list of compression
* presets.
*
* \return - LZMA_OK: Initialization succeeded. Use lzma_code() to
* encode your data.
* - LZMA_MEM_ERROR: Memory allocation failed. All memory
* previously allocated for *strm is now freed.
* - LZMA_HEADER_ERROR: The given compression level is not
* supported by this build of liblzma.
*
* If initialization succeeds, use lzma_code() to do the actual encoding.
* Valid values for `action' (the second argument of lzma_code()) are
* LZMA_RUN, LZMA_SYNC_FLUSH, and LZMA_FINISH. In future, there may be
* compression levels that don't support LZMA_SYNC_FLUSH.
*/
extern lzma_ret lzma_easy_encoder_single(
lzma_stream *strm, lzma_easy_level level);
/**
* \brief Initializes Multi-Block .lzma Stream encoder
*
* If you want to be able to store Extra Records or want to be able to use
* LZMA_FULL_FLUSH, you need to create a Multi-Block Stream.
*
* \param strm Pointer to lzma_stream that is at least initialized
* with LZMA_STREAM_INIT.
* \param level Compression level to use for the data being encoded.
* \param metadata_level
* Compression level to use for Metadata Blocks.
* Metadata Blocks contain the Extra Records (if any)
* and some book-keeping data that is used by decoders.
* \param header Pointer to a list of Extra Records to be stored to
* the Header Metadata Block. Set this to NULL to omit
* Header Metadata Block completely. The list must be
* kept available until the encoding has finished.
* \param footer Pointer to a list of Extra Records to be stored to
* the Footer Metadata Block. Set this to NULL if you
* don't want to store any Extra Records (the Footer
* Metadata Block will still be written for other
* reasons.) The list must be kept available until
* the encoding has finished.
*
* \return - LZMA_OK: Initialization succeeded. Use lzma_code() to
* encode your data.
* - LZMA_MEM_ERROR: Memory allocation failed. All memory
* previously allocated for *strm is now freed.
* - LZMA_HEADER_ERROR: The given compression level is not
* supported by this build of liblzma.
*
* If initialization succeeds, use lzma_code() to do the actual encoding.
* Valid values for `action' (the second argument of lzma_code()) are
* LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
* there may be compression levels that don't support LZMA_SYNC_FLUSH.
* LZMA_FULL_FLUSH will always work with all compression levels.
*/
extern lzma_ret lzma_easy_encoder_multi(lzma_stream *strm,
lzma_easy_level level, lzma_easy_level metadata_level,
const lzma_extra *header, const lzma_extra *footer);

View File

@@ -302,7 +302,7 @@ extern const lzma_match_finder *const lzma_available_match_finders;
/**
* \brief Table of presets for the LZMA filter
*
* lzma_presets[0] is the fastest and lzma_preset_lzma[8] is the slowest.
* lzma_preset_lzma[0] is the fastest and lzma_preset_lzma[8] is the slowest.
* These presets match the switches -1 .. -9 of the lzma command line tool
*
* The preset values are subject to changes between liblzma versions.

View File

@@ -92,6 +92,51 @@ extern size_t lzma_memlimit_get(const lzma_memlimit *mem);
extern size_t lzma_memlimit_used(const lzma_memlimit *mem);
/**
* \brief Gets the maximum amount of memory required in total
*
* Returns how much memory was or would have been allocated at the same time.
* If lzma_memlimit_alloc() was requested so much memory that the limit
* would have been exceeded or malloc() simply ran out of memory, the
* requested amount is still included to the value returned by
* lzma_memlimit_max(). This may be used as a hint how much bigger memory
* limit would have been needed.
*
* If the clear flag is set, the internal variable holding the maximum
* value is set to the current memory usage (the same value as returned
* by lzma_memlimit_used()).
*
* \note Usually liblzma needs to allocate many chunks of memory, and
* displaying a message like "memory usage limit reached, at
* least 1024 bytes would have been needed" may be confusing,
* because the next allocation could have been e.g. 8 MiB.
*
* \todo The description of this function is unclear.
*/
extern size_t lzma_memlimit_max(lzma_memlimit *mem, lzma_bool clear);
/**
* \brief Checks if memory limit was reached at some point
*
* This function is useful to find out if the reason for LZMA_MEM_ERROR
* was running out of memory or hitting the memory usage limit imposed
* by lzma_memlimit_alloc(). If the clear argument is true, the internal
* flag, that indicates that limit was reached, is cleared.
*/
extern lzma_bool lzma_memlimit_reached(lzma_memlimit *mem, lzma_bool clear);
/**
* \brief Gets the number of allocations owned by the memory limitter
*
* The count does not include the helper structures; if no memory has
* been allocated with lzma_memlimit_alloc() or all memory allocated
* has been freed or detached, this will return zero.
*/
extern size_t lzma_memlimit_count(const lzma_memlimit *mem);
/**
* \brief Allocates memory with malloc() if memory limit allows
*

View File

@@ -64,6 +64,15 @@
*
* If options with non-default values have been specified when encoding,
* the same options must also be specified when decoding.
*
* \note At the moment, none of the simple filters support
* LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified,
* LZMA_HEADER_ERROR will be returned. If there is need,
* partial support for LZMA_SYNC_FLUSH can be added in future.
* Partial means that flushing would be possible only at
* offsets that are multiple of 2, 4, or 16 depending on
* the filter, except x86 which cannot be made to support
* LZMA_SYNC_FLUSH predictably.
*/
typedef struct {
/**

View File

@@ -111,7 +111,7 @@ typedef struct {
/**
* \brief Extra information in the Header Metadata Block
*/
lzma_extra *header;
const lzma_extra *header;
/**
* \brief Extra information in the Footer Metadata Block
@@ -119,7 +119,7 @@ typedef struct {
* It is enough to set this pointer any time before calling
* lzma_code() with LZMA_FINISH as the second argument.
*/
lzma_extra *footer;
const lzma_extra *footer;
} lzma_options_stream;

View File

@@ -95,9 +95,10 @@ typedef struct {
* input_offset % alignment == output_offset % alignment
*
* The Subblock filter assumes that the first output byte will be
* written to a position in the output stream that is properly aligned.
*
* FIXME desc
* written to a position in the output stream that is properly
* aligned. This requirement is automatically met when the start
* offset of the Stream or Block is correctly told to Block or
* Stream encoder.
*/
uint32_t alignment;
# define LZMA_SUBBLOCK_ALIGNMENT_MIN 1
@@ -161,16 +162,17 @@ typedef struct {
*
* When subfilter_mode is LZMA_SUBFILTER_NONE, the application may
* put Subfilter options to subfilter_options structure, and then
* set subfilter_mode to LZMA_SUBFILTER_SET. This implies setting
* flush to true. No new input data will be read until the Subfilter
* has been enabled. Once the Subfilter has been enabled, liblzma
* will set subfilter_mode to LZMA_SUBFILTER_RUN.
* set subfilter_mode to LZMA_SUBFILTER_SET. No new input data will
* be read until the Subfilter has been enabled. Once the Subfilter
* has been enabled, liblzma will set subfilter_mode to
* LZMA_SUBFILTER_RUN.
*
* When subfilter_mode is LZMA_SUBFILTER_RUN, the application may
* set subfilter_mode to LZMA_SUBFILTER_FINISH. No new input data
* will be read until the Subfilter has been finished. Once the
* Subfilter has been finished, liblzma will set subfilter_mode
* to LZMA_SUBFILTER_NONE.
* set subfilter_mode to LZMA_SUBFILTER_FINISH. All the input
* currently available will be encoded before unsetting the
* Subfilter. Application must not change the amount of available
* input until the Subfilter has finished. Once the Subfilter has
* finished, liblzma will set subfilter_mode to LZMA_SUBFILTER_NONE.
*
* If the intent is to have Subfilter enabled to the very end of
* the data, it is not needed to separately disable Subfilter with
@@ -178,6 +180,11 @@ typedef struct {
* of lzma_code() will make the Subblock encoder to disable the
* Subfilter once all the data has been ran through the Subfilter.
*
* After the first call with LZMA_SYNC_FLUSH or LZMA_FINISH, the
* application must not change subfilter_mode until LZMA_STREAM_END.
* Setting LZMA_SUBFILTER_SET/LZMA_SUBFILTER_FINISH and
* LZMA_SYNC_FLUSH/LZMA_FINISH _at the same time_ is fine.
*
* \note This variable is ignored if allow_subfilters is false.
*/
lzma_subfilter_mode subfilter_mode;

View File

@@ -24,14 +24,18 @@
/**
* \brief Compile-time version number
*
* The version number is of format xyyyuuus where
* - x is the major LZMA SDK version
* - yyy is the minor LZMA SDK version
* - uuu is LZMA Utils version (reset to zero every time SDK version
* is incremented)
* The version number is of format xyyyzzzs where
* - x = major
* - yyy = minor
* - zzz = revision
* - s indicates stability: 0 = alpha, 1 = beta, 2 = stable
*
* See the README file for details about the version numbering.
*
* \note The version number of LZMA Utils (and thus liblzma)
* has nothing to with the version number of LZMA SDK.
*/
#define LZMA_VERSION UINT32_C(40420010)
#define LZMA_VERSION UINT32_C(49990030)
/**
@@ -49,11 +53,5 @@ extern const uint32_t lzma_version_number;
*
* This function may be useful if you want to display which version of
* libilzma your application is currently using.
*
* \return Returns a pointer to a statically allocated string constant,
* which contains the version number of liblzma. The format of
* the version string is usually (but not necessarily) x.y.z
* e.g. "4.42.1". Alpha and beta versions contain a suffix
* ("4.42.0alpha").
*/
extern const char *const lzma_version_string;

View File

@@ -154,7 +154,7 @@ typedef uint64_t lzma_vli;
* The encoding scheme encodes seven bits to every byte, using minimum
* number of bytes required to represent the given value. In other words,
* it puts 7-63 bits into 1-9 bytes. This implementation limits the number
* of bits used to 63, thus num must be at maximum of INT64_MAX / 2. You
* of bits used to 63, thus num must be at maximum of UINT64_MAX / 2. You
* may use LZMA_VLI_VALUE_MAX for clarity.
*
* \param vli Integer to be encoded

View File

@@ -23,7 +23,7 @@ libcheck_la_CPPFLAGS = \
if COND_CHECK_CRC32
if COND_ASM_X86
libcheck_la_SOURCES += crc32_x86.s
libcheck_la_SOURCES += crc32_x86.S
else
libcheck_la_SOURCES += crc32.c
endif
@@ -40,7 +40,7 @@ endif
if COND_CHECK_CRC64
if COND_ASM_X86
libcheck_la_SOURCES += crc64_x86.s
libcheck_la_SOURCES += crc64_x86.S
else
libcheck_la_SOURCES += crc64.c
endif

View File

@@ -13,12 +13,9 @@
///////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include <config.h>
# include "check.h"
#endif
#include <sys/types.h>
#include <inttypes.h>
#ifdef WORDS_BIGENDIAN
# include "check_byteswap.h"
#endif

View File

@@ -11,9 +11,7 @@
//
///////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "common.h"
#ifdef WORDS_BIGENDIAN
# include "crc32_table_be.h"

View File

@@ -1,7 +1,5 @@
/* This file has been automatically generated by crc32_tablegen.c. */
#include <inttypes.h>
const uint32_t lzma_crc32_table[8][256] = {
{
0x00000000, 0x96300777, 0x2C610EEE, 0xBA510999,

View File

@@ -1,7 +1,5 @@
/* This file has been automatically generated by crc32_tablegen.c. */
#include <inttypes.h>
const uint32_t lzma_crc32_table[8][256] = {
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,

View File

@@ -3,7 +3,7 @@
/// \file crc32_tablegen.c
/// \brief Generates CRC32 crc32_table.c
///
/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c crc32_init.c
/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c
/// Add -DWORDS_BIGENDIAN to generate big endian table.
//
// This code has been put into the public domain.
@@ -18,10 +18,7 @@
#include <inttypes.h>
#include <stdio.h>
extern void lzma_crc32_init(void);
extern uint32_t lzma_crc32_table[8][256];
#include "crc32_init.c"
int
@@ -31,7 +28,6 @@ main()
printf("/* This file has been automatically generated by "
"crc32_tablegen.c. */\n\n"
"#include <inttypes.h>\n\n"
"const uint32_t lzma_crc32_table[8][256] = {\n\t{");
for (size_t s = 0; s < 8; ++s) {

View File

@@ -45,7 +45,7 @@ init_table(void)
*/
.text
.global lzma_crc32
.globl lzma_crc32
.type lzma_crc32, @function
.align 16
@@ -215,3 +215,12 @@ lzma_crc32:
ret
.size lzma_crc32, .-lzma_crc32
/*
* This is needed to support non-executable stack. It's ugly to
* use __linux__ here, but I don't know a way to detect when
* we are using GNU assembler.
*/
#if defined(__ELF__) && defined(__linux__)
.section .note.GNU-stack,"",@progbits
#endif

View File

@@ -13,12 +13,9 @@
///////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include <config.h>
# include "check.h"
#endif
#include <sys/types.h>
#include <inttypes.h>
#ifdef WORDS_BIGENDIAN
# include "check_byteswap.h"
#endif

View File

@@ -11,9 +11,7 @@
//
///////////////////////////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "common.h"
#ifdef WORDS_BIGENDIAN
# include "crc64_table_be.h"

View File

@@ -1,7 +1,5 @@
/* This file has been automatically generated by crc64_tablegen.c. */
#include <inttypes.h>
const uint64_t lzma_crc64_table[4][256] = {
{
UINT64_C(0x0000000000000000), UINT64_C(0x6F5FA703BE4C2EB3),

View File

@@ -1,7 +1,5 @@
/* This file has been automatically generated by crc64_tablegen.c. */
#include <inttypes.h>
const uint64_t lzma_crc64_table[4][256] = {
{
UINT64_C(0x0000000000000000), UINT64_C(0xB32E4CBE03A75F6F),

View File

@@ -3,7 +3,7 @@
/// \file crc64_tablegen.c
/// \brief Generates CRC64 crc64_table.c
///
/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c crc64_init.c
/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c
/// Add -DWORDS_BIGENDIAN to generate big endian table.
//
// This code has been put into the public domain.
@@ -18,10 +18,7 @@
#include <inttypes.h>
#include <stdio.h>
extern void lzma_crc64_init(void);
extern uint64_t lzma_crc64_table[4][256];
#include "crc64_init.c"
int
@@ -31,7 +28,6 @@ main()
printf("/* This file has been automatically generated by "
"crc64_tablegen.c. */\n\n"
"#include <inttypes.h>\n\n"
"const uint64_t lzma_crc64_table[4][256] = {\n\t{");
for (size_t s = 0; s < 4; ++s) {

View File

@@ -38,7 +38,7 @@ init_table(void)
*/
.text
.global lzma_crc64
.globl lzma_crc64
.type lzma_crc64, @function
.align 16
@@ -200,4 +200,13 @@ lzma_crc64:
popl %ebx
ret
.size lzma_crc32, .-lzma_crc32
.size lzma_crc64, .-lzma_crc64
/*
* This is needed to support non-executable stack. It's ugly to
* use __linux__ here, but I don't know a way to detect when
* we are using GNU assembler.
*/
#if defined(__ELF__) && defined(__linux__)
.section .note.GNU-stack,"",@progbits
#endif

View File

@@ -23,7 +23,7 @@ libcommon_la_CPPFLAGS = \
-I@top_srcdir@/src/liblzma/rangecoder
libcommon_la_SOURCES = \
common.h \
sysdefs.h \
bsr.h \
allocator.c \
block_private.h \
extra.c \
@@ -47,8 +47,18 @@ endif
if COND_FILTER_DELTA
libcommon_la_SOURCES += \
delta_coder.c \
delta_coder.h
delta_common.c \
delta_common.h
if COND_MAIN_ENCODER
libcommon_la_SOURCES += \
delta_encoder.c \
delta_encoder.h
endif
if COND_MAIN_DECODER
libcommon_la_SOURCES += \
delta_decoder.c \
delta_decoder.h
endif
endif
if COND_MAIN_ENCODER
@@ -59,6 +69,10 @@ libcommon_la_SOURCES += \
block_encoder.c \
block_encoder.h \
block_header_encoder.c \
easy_common.c \
easy_common.h \
easy_single.c \
easy_multi.c \
filter_flags_encoder.c \
init_encoder.c \
metadata_encoder.c \
@@ -69,6 +83,7 @@ libcommon_la_SOURCES += \
stream_common.h \
stream_encoder_single.c \
stream_encoder_multi.c \
stream_encoder_multi.h \
stream_flags_encoder.c \
vli_encoder.c
endif

View File

@@ -36,9 +36,10 @@ lzma_alloc(size_t size, lzma_allocator *allocator)
ptr = malloc(size);
#if !defined(NDEBUG) && defined(HAVE_MEMSET)
// This helps to catch some stupid mistakes.
if (ptr != NULL)
memset(ptr, 0xFD, size);
// This helps to catch some stupid mistakes, but also hides them from
// Valgrind. Uncomment when useful.
// if (ptr != NULL)
// memset(ptr, 0xFD, size);
#endif
return ptr;

View File

@@ -75,7 +75,8 @@ alone_decode(lzma_coder *coder,
& (UINT32_C(1) << i))
++count;
if (count > 1)
if (count != 1 || coder->options.lzma.dictionary_size
> LZMA_DICTIONARY_SIZE_MAX)
return LZMA_DATA_ERROR;
coder->pos = 0;

View File

@@ -152,7 +152,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
const size_t in_start = *in_pos;
const size_t out_start = *out_pos;
lzma_ret ret = coder->next.code(coder->next.coder,
const lzma_ret ret = coder->next.code(coder->next.coder,
allocator, in, in_pos, in_size,
out, out_pos, out_size, action);
@@ -174,9 +174,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
if (ret != LZMA_STREAM_END)
return ret;
ret = update_sequence(coder);
if (ret != LZMA_OK)
return ret;
return_if_error(update_sequence(coder));
break;
}
@@ -213,10 +211,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
++*in_pos;
if (++coder->pos == lzma_check_sizes[coder->options->check]) {
const lzma_ret ret = update_sequence(coder);
if (ret != LZMA_OK)
return ret;
return_if_error(update_sequence(coder));
coder->pos = 0;
}
@@ -225,7 +220,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_UNCOMPRESSED_SIZE: {
const size_t in_start = *in_pos;
lzma_ret ret = lzma_vli_decode(&coder->tmp,
const lzma_ret ret = lzma_vli_decode(&coder->tmp,
&coder->pos, in, in_pos, in_size);
if (update_size(&coder->total_size, *in_pos - in_start,
@@ -241,9 +236,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->pos = 0;
coder->tmp = 0;
ret = update_sequence(coder);
if (ret != LZMA_OK)
return ret;
return_if_error(update_sequence(coder));
break;
}
@@ -251,7 +244,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_BACKWARD_SIZE: {
const size_t in_start = *in_pos;
lzma_ret ret = lzma_vli_decode(&coder->tmp,
const lzma_ret ret = lzma_vli_decode(&coder->tmp,
&coder->pos, in, in_pos, in_size);
const size_t in_used = *in_pos - in_start;
@@ -269,9 +262,7 @@ block_decode(lzma_coder *coder, lzma_allocator *allocator,
- coder->size_of_backward_size)
return LZMA_DATA_ERROR;
ret = update_sequence(coder);
if (ret != LZMA_OK)
return ret;
return_if_error(update_sequence(coder));
break;
}
@@ -305,8 +296,8 @@ block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
}
extern lzma_ret
lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
static lzma_ret
block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_options_block *options)
{
// This is pretty similar to lzma_block_encoder_init().
@@ -322,51 +313,15 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->next = LZMA_NEXT_CODER_INIT;
}
if (!lzma_vli_is_valid(options->total_size)
|| !lzma_vli_is_valid(options->compressed_size)
|| !lzma_vli_is_valid(options->uncompressed_size)
|| !lzma_vli_is_valid(options->total_size)
|| !lzma_vli_is_valid(options->total_limit)
|| !lzma_vli_is_valid(options->uncompressed_limit)
|| (options->uncompressed_size
!= LZMA_VLI_VALUE_UNKNOWN
&& options->uncompressed_size
> options->uncompressed_limit)
|| (options->total_size != LZMA_VLI_VALUE_UNKNOWN
&& options->total_size
> options->total_limit)
|| (!options->has_eopm && options->uncompressed_size
== LZMA_VLI_VALUE_UNKNOWN)
|| options->header_size > options->total_size
|| (options->handle_padding
&& (options->has_uncompressed_size_in_footer
|| options->has_backward_size)))
if (validate_options_1(options))
return LZMA_PROG_ERROR;
if (validate_options_2(options))
return LZMA_DATA_ERROR;
return_if_error(lzma_check_init(&next->coder->check, options->check));
if (!options->has_eopm && options->uncompressed_size == 0) {
if (!is_size_valid(0, options->compressed_size))
return LZMA_PROG_ERROR;
if (options->check != LZMA_CHECK_NONE) {
lzma_check_finish(&next->coder->check, options->check);
next->coder->sequence = SEQ_CHECK;
} else if (options->handle_padding) {
next->coder->sequence = SEQ_PADDING;
} else {
next->coder->sequence = SEQ_END;
}
} else {
next->coder->sequence = SEQ_CODE;
}
return_if_error(lzma_raw_decoder_init(&next->coder->next, allocator,
options->filters, options->has_eopm
? LZMA_VLI_VALUE_UNKNOWN
: options->uncompressed_size,
true));
next->coder->sequence = SEQ_CODE;
next->coder->options = options;
next->coder->pos = 0;
next->coder->total_size = options->header_size;
@@ -379,14 +334,34 @@ lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->tmp = 0;
next->coder->size_of_backward_size = 0;
return LZMA_OK;
if (!options->has_eopm && options->uncompressed_size == 0) {
// The Compressed Data field is empty, thus we skip SEQ_CODE
// phase completely.
const lzma_ret ret = update_sequence(next->coder);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
return LZMA_PROG_ERROR;
}
return lzma_raw_decoder_init(&next->coder->next, allocator,
options->filters, options->has_eopm
? LZMA_VLI_VALUE_UNKNOWN
: options->uncompressed_size,
true);
}
extern lzma_ret
lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_options_block *options)
{
lzma_next_coder_init(block_decoder_init, next, allocator, options);
}
extern LZMA_API lzma_ret
lzma_block_decoder(lzma_stream *strm, lzma_options_block *options)
{
lzma_next_strm_init(strm, lzma_block_decoder_init, options);
lzma_next_strm_init(strm, block_decoder_init, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;

View File

@@ -94,7 +94,7 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
// Main loop
while (*out_pos < out_size
&& (*in_pos < in_size || action == LZMA_FINISH))
&& (*in_pos < in_size || action != LZMA_RUN))
switch (coder->sequence) {
case SEQ_CODE: {
const size_t in_start = *in_pos;
@@ -121,7 +121,7 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
lzma_check_update(&coder->check, coder->options->check,
in + in_start, in_used);
if (ret != LZMA_STREAM_END)
if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
return ret;
assert(*in_pos == in_size);
@@ -232,10 +232,8 @@ block_encode(lzma_coder *coder, lzma_allocator *allocator,
case SEQ_PADDING:
if (coder->options->handle_padding) {
assert(!coder->options
->has_uncompressed_size_in_footer);
assert(!coder->options->has_backward_size);
assert(coder->options->total_size != LZMA_VLI_VALUE_UNKNOWN);
assert(coder->options->total_size
!= LZMA_VLI_VALUE_UNKNOWN);
if (coder->total_size < coder->options->total_size) {
out[*out_pos] = 0x00;
@@ -284,27 +282,9 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_options_block *options)
{
// Validate some options.
if (options == NULL
|| !lzma_vli_is_valid(options->total_size)
|| !lzma_vli_is_valid(options->compressed_size)
|| !lzma_vli_is_valid(options->uncompressed_size)
|| !lzma_vli_is_valid(options->total_size)
|| !lzma_vli_is_valid(options->total_limit)
|| !lzma_vli_is_valid(options->uncompressed_limit)
|| (options->uncompressed_size
!= LZMA_VLI_VALUE_UNKNOWN
&& options->uncompressed_size
> options->uncompressed_limit)
|| (options->total_size != LZMA_VLI_VALUE_UNKNOWN
&& options->total_size
> options->total_limit)
|| (!options->has_eopm && options->uncompressed_size
== LZMA_VLI_VALUE_UNKNOWN)
|| (options->handle_padding && (options->total_size
== LZMA_VLI_VALUE_UNKNOWN
|| options->has_uncompressed_size_in_footer
|| options->has_backward_size))
|| options->header_size > options->total_size)
if (validate_options_1(options) || validate_options_2(options)
|| (options->handle_padding && options->total_size
== LZMA_VLI_VALUE_UNKNOWN))
return LZMA_PROG_ERROR;
// Allocate and initialize *next->coder if needed.
@@ -325,9 +305,9 @@ block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Compressed Data is empty. That is, we don't call the encoder at all.
// We initialize it though; it allows detecting invalid options.
if (!options->has_eopm && options->uncompressed_size == 0) {
// Also Compressed Size must also be zero if it has been
// Also Compressed Size must be zero if it has been
// given to us.
if (!is_size_valid(options->compressed_size, 0))
if (!is_size_valid(0, options->compressed_size))
return LZMA_PROG_ERROR;
next->coder->sequence = SEQ_CHECK_FINISH;

View File

@@ -43,4 +43,54 @@ is_size_valid(lzma_vli size, lzma_vli reference)
return reference == LZMA_VLI_VALUE_UNKNOWN || reference == size;
}
/// If any of these tests fail, the caller has to return LZMA_PROG_ERROR.
static inline bool
validate_options_1(const lzma_options_block *options)
{
return options == NULL
|| !lzma_vli_is_valid(options->compressed_size)
|| !lzma_vli_is_valid(options->uncompressed_size)
|| !lzma_vli_is_valid(options->total_size)
|| !lzma_vli_is_valid(options->total_limit)
|| !lzma_vli_is_valid(options->uncompressed_limit);
}
/// If any of these tests fail, the encoder has to return LZMA_PROG_ERROR
/// because something is going horribly wrong if such values get passed
/// to the encoder. In contrast, the decoder has to return LZMA_DATA_ERROR,
/// since these tests failing indicate that something is wrong in the Stream.
static inline bool
validate_options_2(const lzma_options_block *options)
{
if ((options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN
&& options->uncompressed_size
> options->uncompressed_limit)
|| (options->total_size != LZMA_VLI_VALUE_UNKNOWN
&& options->total_size
> options->total_limit)
|| (!options->has_eopm && options->uncompressed_size
== LZMA_VLI_VALUE_UNKNOWN)
|| options->header_size > options->total_size)
return true;
if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
// Calculate a rough minimum possible valid Total Size of
// this Block, and check that total_size and total_limit
// are big enough. Note that the real minimum size can be
// bigger due to the Check, Uncompressed Size, Backwards
// Size, pr Padding being present. A rough check here is
// enough for us to catch the most obvious errors as early
// as possible.
const lzma_vli total_min = options->compressed_size
+ (lzma_vli)(options->header_size);
if (total_min > options->total_size
|| total_min > options->total_limit)
return true;
}
return false;
}
#endif

61
src/liblzma/common/bsr.h Normal file
View File

@@ -0,0 +1,61 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file bsr.h
/// \brief Bit scan reverse
//
// This code has been put into the public domain.
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef LZMA_BSR_H
#define LZMA_BSR_H
// NOTE: Both input and output variables for lzma_bsr must be uint32_t.
#if defined(__GNUC__) && (defined (HAVE_ASM_X86) || defined(HAVE_ASM_X86_64))
# define lzma_bsr(dest, n) \
__asm__("bsrl %1, %0" : "=r" (dest) : "rm" (n))
#else
# define lzma_bsr(dest, n) dest = lzma_bsr_helper(n)
static inline uint32_t
lzma_bsr_helper(uint32_t n)
{
assert(n != 0);
uint32_t i = 31;
if ((n & UINT32_C(0xFFFF0000)) == 0) {
n <<= 16;
i = 15;
}
if ((n & UINT32_C(0xFF000000)) == 0) {
n <<= 8;
i -= 8;
}
if ((n & UINT32_C(0xF0000000)) == 0) {
n <<= 4;
i -= 4;
}
if ((n & UINT32_C(0xC0000000)) == 0) {
n <<= 2;
i -= 2;
}
if ((n & UINT32_C(0x80000000)) == 0)
--i;
return i;
}
#endif
#endif

View File

@@ -20,7 +20,7 @@
#ifndef LZMA_COMMON_H
#define LZMA_COMMON_H
#include "sysdefs.h"
#include "../../common/sysdefs.h"
// Don't use ifdef...
#if HAVE_VISIBILITY

View File

@@ -42,33 +42,12 @@ copy_encode(lzma_coder *coder, lzma_allocator *allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
// If we get here, we are the last filter in the chain.
assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
const size_t in_avail = in_size - *in_pos;
// Check that we don't have too much input.
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
return LZMA_DATA_ERROR;
// Check that once LZMA_FINISH has been given, the amount of input
// matches uncompressed_size, which is always known.
if (action == LZMA_FINISH
&& coder->uncompressed_size != (lzma_vli)(in_avail))
return LZMA_DATA_ERROR;
// We are the last coder in the chain.
// Just copy as much data as possible.
const size_t in_used = bufcpy(
in, in_pos, in_size, out, out_pos, out_size);
// Update uncompressed_size if it is known.
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->uncompressed_size -= in_used;
bufcpy(in, in_pos, in_size, out, out_pos, out_size);
// LZMA_SYNC_FLUSH and LZMA_FINISH are the same thing for us.
if ((action != LZMA_RUN && *in_pos == in_size)
|| coder->uncompressed_size == 0)
if (action != LZMA_RUN && *in_pos == in_size)
return LZMA_STREAM_END;
return LZMA_OK;

View File

@@ -1,204 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_coder.c
/// \brief Encoder and decoder for the Delta filter
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "delta_coder.h"
struct lzma_coder_s {
/// Next coder in the chain
lzma_next_coder next;
/// Uncompressed size - This is needed when we are the last
/// filter in the chain.
lzma_vli uncompressed_size;
/// Delta distance
size_t distance;
/// True if we are encoding; false if decoding
bool is_encoder;
/// Position in history[]
uint8_t pos;
/// Buffer to hold history of the original data
uint8_t history[LZMA_DELTA_DISTANCE_MAX];
};
static void
encode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
{
const size_t distance = coder->distance;
for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos--] = buffer[i];
buffer[i] -= tmp;
}
return;
}
static void
decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
{
const size_t distance = coder->distance;
for (size_t i = 0; i < size; ++i) {
buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
coder->history[coder->pos--] = buffer[i];
}
return;
}
static lzma_ret
delta_code(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)
{
const size_t out_start = *out_pos;
size_t size;
lzma_ret ret;
if (coder->next.code == NULL) {
const size_t in_avail = in_size - *in_pos;
if (coder->is_encoder) {
// Check that we don't have too much input.
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
return LZMA_DATA_ERROR;
// Check that once LZMA_FINISH has been given, the
// amount of input matches uncompressed_size if it
// is known.
if (action == LZMA_FINISH && coder->uncompressed_size
!= LZMA_VLI_VALUE_UNKNOWN
&& coder->uncompressed_size
!= (lzma_vli)(in_avail))
return LZMA_DATA_ERROR;
} else {
// Limit in_size so that we don't copy too much.
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
in_size = *in_pos + (size_t)(
coder->uncompressed_size);
}
size = bufcpy(in, in_pos, in_size, out, out_pos, out_size);
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->uncompressed_size -= size;
// action can be LZMA_FINISH only in the encoder.
ret = (action == LZMA_FINISH && *in_pos == in_size)
|| coder->uncompressed_size == 0
? LZMA_STREAM_END : LZMA_OK;
} else {
ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
return ret;
size = *out_pos - out_start;
}
if (coder->is_encoder)
encode_buffer(coder, out + out_start, size);
else
decode_buffer(coder, out + out_start, size);
return ret;
}
static void
delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
{
lzma_next_coder_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
static lzma_ret
delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
// Allocate memory for the decoder if needed.
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
return LZMA_MEM_ERROR;
next->code = &delta_code;
next->end = &delta_coder_end;
next->coder->next = LZMA_NEXT_CODER_INIT;
}
// Copy Uncompressed Size which is used to limit the output size.
next->coder->uncompressed_size = filters[0].uncompressed_size;
// The coder acts slightly differently as encoder and decoder.
next->coder->is_encoder = is_encoder;
// Set the delta distance.
if (filters[0].options == NULL)
return LZMA_PROG_ERROR;
next->coder->distance = ((lzma_options_delta *)(filters[0].options))
->distance;
if (next->coder->distance < LZMA_DELTA_DISTANCE_MIN
|| next->coder->distance > LZMA_DELTA_DISTANCE_MAX)
return LZMA_HEADER_ERROR;
// Initialize the rest of the variables.
next->coder->pos = 0;
memzero(next->coder->history, LZMA_DELTA_DISTANCE_MAX);
// Initialize the next decoder in the chain, if any.
return lzma_next_filter_init(&next->coder->next,
allocator, filters + 1);
}
#ifdef HAVE_ENCODER
extern lzma_ret
lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return delta_coder_init(next, allocator, filters, true);
}
#endif
#ifdef HAVE_DECODER
extern lzma_ret
lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return delta_coder_init(next, allocator, filters, false);
}
#endif

View File

@@ -0,0 +1,70 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_common.c
/// \brief Common stuff for Delta encoder and decoder
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "delta_common.h"
static void
delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
{
lzma_next_coder_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
extern lzma_ret
lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters, lzma_code_function code)
{
// Allocate memory for the decoder if needed.
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
return LZMA_MEM_ERROR;
// End function is the same for encoder and decoder.
next->end = &delta_coder_end;
next->coder->next = LZMA_NEXT_CODER_INIT;
}
// Coding function is different for encoder and decoder.
next->code = code;
// Copy Uncompressed Size which is used to limit the output size
// in the Delta decoder.
next->coder->uncompressed_size = filters[0].uncompressed_size;
// Set the delta distance.
if (filters[0].options == NULL)
return LZMA_PROG_ERROR;
next->coder->distance = ((lzma_options_delta *)(filters[0].options))
->distance;
if (next->coder->distance < LZMA_DELTA_DISTANCE_MIN
|| next->coder->distance > LZMA_DELTA_DISTANCE_MAX)
return LZMA_HEADER_ERROR;
// Initialize the rest of the variables.
next->coder->pos = 0;
memzero(next->coder->history, LZMA_DELTA_DISTANCE_MAX);
// Initialize the next decoder in the chain, if any.
return lzma_next_filter_init(&next->coder->next,
allocator, filters + 1);
}

View File

@@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_common.h
/// \brief Common stuff for Delta encoder and decoder
//
// 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_DELTA_COMMON_H
#define LZMA_DELTA_COMMON_H
#include "common.h"
struct lzma_coder_s {
/// Next coder in the chain
lzma_next_coder next;
/// Uncompressed size - This is needed when we are the last
/// filter in the chain.
lzma_vli uncompressed_size;
/// Delta distance
size_t distance;
/// Position in history[]
uint8_t pos;
/// Buffer to hold history of the original data
uint8_t history[LZMA_DELTA_DISTANCE_MAX];
};
extern lzma_ret lzma_delta_coder_init(
lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters, lzma_code_function code);
#endif

View File

@@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_decoder.c
/// \brief Delta filter decoder
//
// Copyright (C) 2007, 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "delta_decoder.h"
#include "delta_common.h"
/// Copies and decodes the data at the same time. This is used when Delta
/// is the last filter in the chain.
static void
copy_and_decode(lzma_coder *coder,
const uint8_t *restrict in, uint8_t *restrict out, size_t size)
{
const size_t distance = coder->distance;
for (size_t i = 0; i < size; ++i) {
out[i] = in[i] + coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = out[i];
}
}
/// Decodes the data in place. This is used when we are not the last filter
/// in the chain.
static void
decode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
{
const size_t distance = coder->distance;
for (size_t i = 0; i < size; ++i) {
buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = buffer[i];
}
}
static lzma_ret
delta_decode(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)
{
lzma_ret ret;
if (coder->next.code == NULL) {
// Limit in_size so that we don't copy too much.
if ((lzma_vli)(in_size - *in_pos) > coder->uncompressed_size)
in_size = *in_pos + (size_t)(coder->uncompressed_size);
const size_t in_avail = in_size - *in_pos;
const size_t out_avail = out_size - *out_pos;
const size_t size = MIN(in_avail, out_avail);
copy_and_decode(coder, in + *in_pos, out + *out_pos, size);
*in_pos += size;
*out_pos += size;
assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
coder->uncompressed_size -= size;
ret = coder->uncompressed_size == 0
? LZMA_STREAM_END : LZMA_OK;
} else {
const size_t out_start = *out_pos;
ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
decode_in_place(coder, out + out_start, *out_pos - out_start);
}
return ret;
}
extern lzma_ret
lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return lzma_delta_coder_init(next, allocator, filters, &delta_decode);
}

View File

@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_coder.h
/// \brief The Delta filter encoder and decoder
/// \file delta_decoder.h
/// \brief Delta filter decoder
//
// Copyright (C) 2007 Lasse Collin
//
@@ -17,14 +17,11 @@
//
///////////////////////////////////////////////////////////////////////////////
#ifndef LZMA_DELTA_CODER_H
#define LZMA_DELTA_CODER_H
#ifndef LZMA_DELTA_DECODER_H
#define LZMA_DELTA_DECODER_H
#include "common.h"
extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters);
extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters);

View File

@@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_encoder.c
/// \brief Delta filter encoder
//
// Copyright (C) 2007, 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "delta_encoder.h"
#include "delta_common.h"
/// Copies and encodes the data at the same time. This is used when Delta
/// is the last filter in the chain.
static void
copy_and_encode(lzma_coder *coder,
const uint8_t *restrict in, uint8_t *restrict out, size_t size)
{
const size_t distance = coder->distance;
for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = in[i];
out[i] = in[i] - tmp;
}
}
/// Encodes the data in place. This is used when we are not the last filter
/// in the chain.
static void
encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
{
const size_t distance = coder->distance;
for (size_t i = 0; i < size; ++i) {
const uint8_t tmp = coder->history[
(distance + coder->pos) & 0xFF];
coder->history[coder->pos-- & 0xFF] = buffer[i];
buffer[i] -= tmp;
}
}
static lzma_ret
delta_encode(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)
{
lzma_ret ret;
if (coder->next.code == NULL) {
const size_t in_avail = in_size - *in_pos;
const size_t out_avail = out_size - *out_pos;
const size_t size = MIN(in_avail, out_avail);
copy_and_encode(coder, in + *in_pos, out + *out_pos, size);
*in_pos += size;
*out_pos += size;
ret = action != LZMA_RUN && *in_pos == in_size
? LZMA_STREAM_END : LZMA_OK;
} else {
const size_t out_start = *out_pos;
ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size,
action);
encode_in_place(coder, out + out_start, *out_pos - out_start);
}
return ret;
}
extern lzma_ret
lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters)
{
return lzma_delta_coder_init(next, allocator, filters, &delta_encode);
}

View File

@@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file delta_encoder.h
/// \brief Delta filter encoder
//
// 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_DELTA_ENCODER_H
#define LZMA_DELTA_ENCODER_H
#include "common.h"
extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_filter_info *filters);
#endif

View File

@@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file easy_common.c
/// \brief Shared stuff for easy encoder initialization functions
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "easy_common.h"
extern bool
lzma_easy_set_filters(lzma_options_filter *filters, uint32_t level)
{
bool error = false;
if (level == 0) {
filters[0].id = LZMA_VLI_VALUE_UNKNOWN;
#ifdef HAVE_FILTER_LZMA
} else if (level <= 9) {
filters[0].id = LZMA_FILTER_LZMA;
filters[0].options = (void *)(&lzma_preset_lzma[level - 1]);
filters[1].id = LZMA_VLI_VALUE_UNKNOWN;
#endif
} else {
error = true;
}
return error;
}
extern LZMA_API uint32_t
lzma_easy_memory_usage(lzma_easy_level level)
{
lzma_options_filter filters[8];
if (lzma_easy_set_filters(filters, level))
return UINT32_MAX;
return lzma_memory_usage(filters, true);
}

View File

@@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file easy_common.c
/// \brief Shared stuff for easy encoder initialization functions
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "common.h"
#ifndef LZMA_EASY_COMMON_H
#define LZMA_EASY_COMMON_H
extern bool lzma_easy_set_filters(
lzma_options_filter *filters, uint32_t level);
#endif

View File

@@ -0,0 +1,103 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file easy_multi.c
/// \brief Easy Multi-Block Stream encoder initialization
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "easy_common.h"
#include "stream_encoder_multi.h"
struct lzma_coder_s {
lzma_next_coder encoder;
lzma_options_stream options;
};
static lzma_ret
easy_encode(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)
{
return coder->encoder.code(coder->encoder.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size, action);
}
static void
easy_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
lzma_next_coder_end(&coder->encoder, allocator);
lzma_free(coder, allocator);
return;
}
static lzma_ret
easy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
lzma_easy_level level, lzma_easy_level metadata_level,
const lzma_extra *header, const lzma_extra *footer)
{
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
return LZMA_MEM_ERROR;
next->code = &easy_encode;
next->end = &easy_encoder_end;
next->coder->encoder = LZMA_NEXT_CODER_INIT;
}
next->coder->options = (lzma_options_stream){
.check = LZMA_CHECK_CRC32,
.has_crc32 = true,
.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
.alignment = 0,
.header = header,
.footer = footer,
};
if (lzma_easy_set_filters(next->coder->options.filters, level)
|| lzma_easy_set_filters(
next->coder->options.metadata_filters,
metadata_level))
return LZMA_HEADER_ERROR;
return lzma_stream_encoder_multi_init(&next->coder->encoder,
allocator, &next->coder->options);
}
extern LZMA_API lzma_ret
lzma_easy_encoder_multi(lzma_stream *strm,
lzma_easy_level level, lzma_easy_level metadata_level,
const lzma_extra *header, const lzma_extra *footer)
{
// This is more complicated than lzma_easy_encoder_single(),
// because lzma_stream_encoder_multi() wants that the options
// structure is available until the encoding is finished.
lzma_next_strm_init(strm, easy_encoder_init,
level, metadata_level, header, footer);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;
}

View File

@@ -0,0 +1,37 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file easy_single.c
/// \brief Easy Single-Block Stream encoder initialization
//
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "easy_common.h"
extern LZMA_API lzma_ret
lzma_easy_encoder_single(lzma_stream *strm, lzma_easy_level level)
{
lzma_options_stream opt_stream = {
.check = LZMA_CHECK_CRC32,
.has_crc32 = true,
.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
.alignment = 0,
};
if (lzma_easy_set_filters(opt_stream.filters, level))
return LZMA_HEADER_ERROR;
return lzma_stream_encoder_single(strm, &opt_stream);
}

View File

@@ -25,6 +25,7 @@ lzma_extra_free(lzma_extra *extra, lzma_allocator *allocator)
{
while (extra != NULL) {
lzma_extra *tmp = extra->next;
lzma_free(extra->data, allocator);
lzma_free(extra, allocator);
extra = tmp;
}

View File

@@ -19,6 +19,7 @@
#include "common.h"
#include "lzma_encoder.h"
#include "fastpos.h"
/// \brief Calculates the size of the Filter Properties field
@@ -204,35 +205,32 @@ properties_lzma(uint8_t *out, size_t *out_pos, size_t out_size,
// Dictionary flags
//
// Dictionary size is encoded using six bits of
// which one is mantissa and five are exponent.
// Dictionary size is encoded using similar encoding that is used
// internally by LZMA.
//
// There are some limits that must hold to keep
// this coding working.
# if LZMA_DICTIONARY_SIZE_MAX > UINT32_MAX / 2
# error LZMA_DICTIONARY_SIZE_MAX is too big.
# endif
// This won't work if dictionary size can be zero:
# if LZMA_DICTIONARY_SIZE_MIN < 1
# error LZMA_DICTIONARY_SIZE_MIN cannot be zero.
# endif
uint32_t d = options->dictionary_size;
// Validate it:
if (options->dictionary_size < LZMA_DICTIONARY_SIZE_MIN
|| options->dictionary_size > LZMA_DICTIONARY_SIZE_MAX)
if (d < LZMA_DICTIONARY_SIZE_MIN || d > LZMA_DICTIONARY_SIZE_MAX)
return LZMA_HEADER_ERROR;
if (options->dictionary_size == 1) {
// Special case
out[*out_pos] = 0x00;
} else {
// TODO This could be more elegant.
uint32_t i = 1;
while (((2 | ((i + 1) & 1)) << ((i - 1) / 2))
< options->dictionary_size)
++i;
out[*out_pos] = i;
}
// Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
// one is the next:
--d;
d |= d >> 2;
d |= d >> 3;
d |= d >> 4;
d |= d >> 8;
d |= d >> 16;
++d;
// Get the highest two bits using the proper encoding:
out[*out_pos] = get_pos_slot(d) - 1;
++*out_pos;
return LZMA_OK;

View File

@@ -367,7 +367,7 @@ lzma_info_metadata_set(lzma_info *info, lzma_allocator *allocator,
lzma_bool eat_index)
{
// Validate *metadata.
if (!lzma_vli_is_valid(metadata->header_metadata_size)
if (metadata->header_metadata_size > LZMA_VLI_VALUE_MAX
|| !lzma_vli_is_valid(metadata->total_size)
|| !lzma_vli_is_valid(metadata->uncompressed_size)) {
if (eat_index) {
@@ -385,6 +385,10 @@ lzma_info_metadata_set(lzma_info *info, lzma_allocator *allocator,
const lzma_ret ret = lzma_info_index_set(
info, allocator, metadata->index, eat_index);
if (eat_index)
metadata->index = NULL;
if (ret != LZMA_OK)
return ret;
@@ -399,34 +403,21 @@ lzma_info_metadata_set(lzma_info *info, lzma_allocator *allocator,
}
// Size of Header Metadata
if (!is_header_metadata) {
// If it is marked unknown in Metadata, it means that
// it's not present.
const lzma_vli size = metadata->header_metadata_size
!= LZMA_VLI_VALUE_UNKNOWN
? metadata->header_metadata_size : 0;
const lzma_ret ret = lzma_info_size_set(
info, LZMA_INFO_HEADER_METADATA, size);
if (ret != LZMA_OK)
return ret;
}
if (!is_header_metadata)
return_if_error(lzma_info_size_set(
info, LZMA_INFO_HEADER_METADATA,
metadata->header_metadata_size));
// Total Size
if (metadata->total_size != LZMA_VLI_VALUE_UNKNOWN) {
const lzma_ret ret = lzma_info_size_set(info,
LZMA_INFO_TOTAL, metadata->total_size);
if (ret != LZMA_OK)
return ret;
}
if (metadata->total_size != LZMA_VLI_VALUE_UNKNOWN)
return_if_error(lzma_info_size_set(info,
LZMA_INFO_TOTAL, metadata->total_size));
// Uncompressed Size
if (metadata->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
const lzma_ret ret = lzma_info_size_set(info,
if (metadata->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
return_if_error(lzma_info_size_set(info,
LZMA_INFO_UNCOMPRESSED,
metadata->uncompressed_size);
if (ret != LZMA_OK)
return ret;
}
metadata->uncompressed_size));
return LZMA_OK;
}

View File

@@ -25,9 +25,7 @@ lzma_init_decoder(void)
{
// So far there's no decoder-specific stuff to initialize.
#ifdef HAVE_CHECK
lzma_init_check();
#endif
return;
}

View File

@@ -29,14 +29,10 @@ lzma_init_encoder(void)
if (already_initialized)
return;
#ifdef HAVE_CHECK
lzma_init_check();
#endif
// FIXME TODO Create precalculated tables.
#if defined(HAVE_ENCODER) && defined(HAVE_FILTER_LZMA)
#if defined(HAVE_SMALL) && defined(HAVE_ENCODER) && defined(HAVE_FILTER_LZMA)
lzma_rc_init();
lzma_fastpos_init();
#endif
already_initialized = true;

View File

@@ -25,9 +25,16 @@
((num) + (((multiple) - ((num) % (multiple))) % (multiple)))
/// Rounds upwards to the next multiple of 2 * sizeof(void*).
/// malloc() tends to align allocations this way.
#define malloc_ceil(num) my_ceil(num, 2 * sizeof(void *))
/// Add approximated overhead of malloc() to size and round upwards to the
/// next multiple of 2 * sizeof(size_t). I suppose that most malloc()
/// implementations align small allocations this way, but the overhead
/// varies due to several reasons (free lists, mmap() usage etc.).
///
/// This doesn't need to be exact at all. It's enough to take into account
/// that there is some overhead. That way our memory usage count won't be
/// horribly wrong if we are used to allocate lots of small memory chunks.
#define malloc_ceil(size) \
my_ceil((size) + 2 * sizeof(void *), 2 * sizeof(size_t))
typedef struct lzma_memlimit_list_s lzma_memlimit_list;
@@ -39,24 +46,44 @@ struct lzma_memlimit_list_s {
struct lzma_memlimit_s {
size_t used;
size_t limit;
/// List of allocated memory chunks
lzma_memlimit_list *list;
/// Number of bytes currently allocated; this includes the memory
/// needed for the helper structures.
size_t used;
/// Memory usage limit
size_t limit;
/// Maximum amount of memory that have been or would have been needed.
/// That is, this is updated also if memory allocation fails, letting
/// the application check how much memory was tried to be allocated
/// in total.
size_t max;
/// True if lzma_memlimit_alloc() has returned NULL due to memory
/// usage limit.
bool limit_reached;
};
extern LZMA_API lzma_memlimit *
lzma_memlimit_create(size_t limit)
{
if (limit < sizeof(lzma_memlimit))
const size_t base_size = malloc_ceil(sizeof(lzma_memlimit));
if (limit < base_size)
return NULL;
lzma_memlimit *mem = malloc(sizeof(lzma_memlimit));
if (mem != NULL) {
mem->used = sizeof(lzma_memlimit);
mem->limit = limit;
mem->list = NULL;
mem->used = base_size;
mem->limit = limit;
mem->max = base_size;
mem->limit_reached = false;
}
return mem;
@@ -85,6 +112,49 @@ lzma_memlimit_used(const lzma_memlimit *mem)
}
extern LZMA_API size_t
lzma_memlimit_max(lzma_memlimit *mem, lzma_bool clear)
{
const size_t ret = mem->max;
if (clear)
mem->max = mem->used;
return ret;
}
extern LZMA_API lzma_bool
lzma_memlimit_reached(lzma_memlimit *mem, lzma_bool clear)
{
const bool ret = mem->limit_reached;
if (clear)
mem->limit_reached = false;
return ret;
}
extern LZMA_API size_t
lzma_memlimit_count(const lzma_memlimit *mem)
{
// This is slow; we could have a counter in lzma_memlimit
// for fast version. I expect the primary use of this
// function to be limited to easy checking of memory leaks,
// in which this implementation is just fine.
size_t count = 0;
const lzma_memlimit_list *record = mem->list;
while (record != NULL) {
++count;
record = record->next;
}
return count;
}
extern LZMA_API void
lzma_memlimit_end(lzma_memlimit *mem, lzma_bool free_allocated)
{
@@ -121,18 +191,36 @@ lzma_memlimit_alloc(lzma_memlimit *mem, size_t nmemb, size_t size)
size = 1;
// Calculate how much memory we are going to allocate in reality.
// TODO: We should add some rough estimate how much malloc() needs
// for its internal structures.
const size_t total_size = malloc_ceil(size)
+ malloc_ceil(sizeof(lzma_memlimit_list));
// Integer overflow protection
if (SIZE_MAX - size <= total_size)
// Integer overflow protection for total_size and mem->used.
if (total_size <= size || SIZE_MAX - total_size < mem->used) {
mem->max = SIZE_MAX;
mem->limit_reached = true;
return NULL;
}
if (mem->limit < mem->used || mem->limit - mem->used < total_size)
// Update the maximum memory requirement counter if needed. This
// is updated even if memory allocation would fail or limit would
// be reached.
if (mem->used + total_size > mem->max)
mem->max = mem->used + total_size;
// Check if we would stay in the memory usage limits. We need to
// check also that the current usage is in the limits, because
// the application could have decreased the limit between calls
// to this function.
if (mem->limit < mem->used || mem->limit - mem->used < total_size) {
mem->limit_reached = true;
return NULL;
}
// Allocate separate memory chunks for lzma_memlimit_list and the
// actual requested memory. Optimizing this to use only one
// allocation is not a good idea, because applications may want to
// detach lzma_extra structures that have been allocated with
// lzma_memlimit_alloc().
lzma_memlimit_list *record = malloc(sizeof(lzma_memlimit_list));
void *ptr = malloc(size);

View File

@@ -127,6 +127,8 @@ process(lzma_coder *coder, lzma_allocator *allocator)
if (coder->buffer[coder->buffer_pos] & 0x70)
return LZMA_HEADER_ERROR;
coder->todo_count = 0;
// If Size of Header Metadata is present, prepare the
// variable for variable-length integer decoding. Otherwise
// set it to LZMA_VLI_VALUE_UNKNOWN to indicate that the
@@ -350,7 +352,18 @@ process(lzma_coder *coder, lzma_allocator *allocator)
case SEQ_EXTRA_SIZE:
case SEQ_EXTRA_DUMMY_SIZE:
read_vli(coder->tmp);
++coder->sequence;
if (coder->tmp == 0) {
// We have no Data in the Extra Record. Don't
// allocate any memory for it. Go back to
// SEQ_EXTRA_ALLOC or SEQ_EXTRA_DUMMY_ALLOC.
coder->tmp = 0;
coder->sequence -= 2;
coder->todo_count = 0;
} else {
++coder->sequence;
}
break;
case SEQ_EXTRA_DATA_ALLOC: {
@@ -360,7 +373,8 @@ process(lzma_coder *coder, lzma_allocator *allocator)
coder->extra_tail->size = (size_t)(coder->tmp);
coder->tmp = 0;
uint8_t *d = lzma_alloc((size_t)(coder->extra_tail->size),
// We reserve space for the trailing '\0' too.
uint8_t *d = lzma_alloc((size_t)(coder->extra_tail->size) + 1,
allocator);
if (d == NULL)
return LZMA_MEM_ERROR;
@@ -377,6 +391,7 @@ process(lzma_coder *coder, lzma_allocator *allocator)
(size_t)(coder->extra_tail->size));
if ((size_t)(coder->extra_tail->size) == coder->pos) {
coder->extra_tail->data[coder->pos] = '\0';
coder->pos = 0;
coder->todo_count = 0;
coder->sequence = SEQ_EXTRA_ALLOC;
@@ -475,6 +490,13 @@ metadata_decode(lzma_coder *coder, lzma_allocator *allocator,
if (coder->todo_count != 0)
return LZMA_DATA_ERROR;
// If Size of Header Metadata Block was not
// present, we use zero as its size instead
// of LZMA_VLI_VALUE_UNKNOWN.
if (coder->metadata->header_metadata_size
== LZMA_VLI_VALUE_UNKNOWN)
coder->metadata->header_metadata_size = 0;
return LZMA_STREAM_END;
}
}
@@ -484,6 +506,7 @@ metadata_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
metadata_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
lzma_next_coder_end(&coder->block_decoder, allocator);
lzma_free(coder, allocator);
return;
}
@@ -514,7 +537,7 @@ metadata_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
metadata->extra = NULL;
next->coder->sequence = SEQ_FLAGS;
next->coder->todo_count = 0;
next->coder->todo_count = 1;
next->coder->pos = 0;
next->coder->tmp = 0;
next->coder->metadata = metadata;

View File

@@ -87,8 +87,7 @@ process(lzma_coder *coder)
case SEQ_FLAGS:
coder->buffer[coder->buffer_size] = 0;
if (coder->metadata.header_metadata_size
!= LZMA_VLI_VALUE_UNKNOWN)
if (coder->metadata.header_metadata_size != 0)
coder->buffer[coder->buffer_size] |= 0x01;
if (coder->metadata.total_size != LZMA_VLI_VALUE_UNKNOWN)
@@ -109,8 +108,7 @@ process(lzma_coder *coder)
break;
case SEQ_HEADER_METADATA_SIZE:
if (coder->metadata.header_metadata_size
!= LZMA_VLI_VALUE_UNKNOWN)
if (coder->metadata.header_metadata_size != 0)
write_vli(coder->metadata.header_metadata_size);
coder->sequence = SEQ_TOTAL_SIZE;
@@ -373,13 +371,14 @@ lzma_metadata_size(const lzma_metadata *metadata)
lzma_vli size = 1; // Metadata Flags
// Validate header_metadata_size, total_size, and uncompressed_size.
if (!lzma_vli_is_valid(metadata->header_metadata_size)
if (metadata->header_metadata_size > LZMA_VLI_VALUE_MAX
|| !lzma_vli_is_valid(metadata->total_size)
|| metadata->total_size == 0
|| !lzma_vli_is_valid(metadata->uncompressed_size))
return 0;
// Add the sizes of these three fields.
if (metadata->header_metadata_size != LZMA_VLI_VALUE_UNKNOWN)
if (metadata->header_metadata_size != 0)
size += lzma_vli_size(metadata->header_metadata_size);
if (metadata->total_size != LZMA_VLI_VALUE_UNKNOWN)

View File

@@ -28,7 +28,7 @@
/// \return true if error occurred, false on success.
///
static bool
prepare(lzma_vli *id, lzma_vli *uncompressed_size, bool implicit)
prepare(lzma_vli *id, lzma_vli *uncompressed_size, bool allow_implicit)
{
bool needs_end_of_input = false;
@@ -62,17 +62,19 @@ prepare(lzma_vli *id, lzma_vli *uncompressed_size, bool implicit)
// Is this the last filter in the chain?
if (id[1] == LZMA_VLI_VALUE_UNKNOWN) {
if (!needs_end_of_input || !implicit || uncompressed_size[0]
!= LZMA_VLI_VALUE_UNKNOWN)
return false;
if (needs_end_of_input && allow_implicit
&& uncompressed_size[0]
== LZMA_VLI_VALUE_UNKNOWN) {
// Add implicit Subblock filter.
id[1] = LZMA_FILTER_SUBBLOCK;
uncompressed_size[1] = LZMA_VLI_VALUE_UNKNOWN;
id[2] = LZMA_VLI_VALUE_UNKNOWN;
}
// Add implicit Subblock filter.
id[1] = LZMA_FILTER_SUBBLOCK;
uncompressed_size[1] = LZMA_VLI_VALUE_UNKNOWN;
id[2] = LZMA_VLI_VALUE_UNKNOWN;
return false;
}
return prepare(id + 1, uncompressed_size + 1, implicit);
return prepare(id + 1, uncompressed_size + 1, allow_implicit);
}

View File

@@ -22,7 +22,7 @@
#include "simple_coder.h"
#include "subblock_decoder.h"
#include "subblock_decoder_helper.h"
#include "delta_coder.h"
#include "delta_decoder.h"
#include "lzma_decoder.h"
#include "metadata_decoder.h"

View File

@@ -21,10 +21,16 @@
#include "copy_coder.h"
#include "simple_coder.h"
#include "subblock_encoder.h"
#include "delta_coder.h"
#include "delta_encoder.h"
#include "lzma_encoder.h"
struct lzma_coder_s {
lzma_next_coder next;
lzma_vli uncompressed_size;
};
static lzma_init_function
get_function(lzma_vli id)
{
@@ -84,22 +90,78 @@ get_function(lzma_vli id)
}
static lzma_ret
raw_encode(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)
{
// Check that our amount of input stays in proper limits.
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
if (action == LZMA_FINISH) {
if (coder->uncompressed_size != in_size - *in_pos)
return LZMA_PROG_ERROR;
} else {
if (coder->uncompressed_size < in_size - *in_pos)
return LZMA_PROG_ERROR;
}
}
const size_t in_start = *in_pos;
const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size, out, out_pos, out_size, action);
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->uncompressed_size -= *in_pos - in_start;
return ret;
}
static void
raw_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
lzma_next_coder_end(&coder->next, allocator);
lzma_free(coder, allocator);
return;
}
static lzma_ret
raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *options,
lzma_vli uncompressed_size, bool allow_implicit)
{
if (next->coder == NULL) {
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
if (next->coder == NULL)
return LZMA_MEM_ERROR;
next->code = &raw_encode;
next->end = &raw_encoder_end;
next->coder->next = LZMA_NEXT_CODER_INIT;
}
next->coder->uncompressed_size = uncompressed_size;
// lzma_raw_coder_init() accesses get_function() via function pointer,
// because this way linker doesn't statically link both encoder and
// decoder functions if user needs only encoder or decoder.
return lzma_raw_coder_init(&next->coder->next, allocator,
options, uncompressed_size,
&get_function, allow_implicit, true);
}
extern lzma_ret
lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_options_filter *options,
lzma_vli uncompressed_size, bool allow_implicit)
{
// lzma_raw_coder_init() accesses get_function() via function pointer,
// because this way linker doesn't statically link both encoder and
// decoder functions if user needs only encoder or decoder.
const lzma_ret ret = lzma_raw_coder_init(next, allocator,
options, uncompressed_size, &get_function,
allow_implicit, true);
if (ret != LZMA_OK)
lzma_next_coder_end(next, allocator);
return ret;
lzma_next_coder_init(raw_encoder_init, next, allocator,
options, uncompressed_size, allow_implicit);
}
@@ -107,18 +169,12 @@ extern LZMA_API lzma_ret
lzma_raw_encoder(lzma_stream *strm, const lzma_options_filter *options,
lzma_vli uncompressed_size, lzma_bool allow_implicit)
{
return_if_error(lzma_strm_init(strm));
lzma_next_strm_init(strm, raw_encoder_init,
options, uncompressed_size, allow_implicit);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
const lzma_ret ret = lzma_raw_coder_init(&strm->internal->next,
strm->allocator, options, uncompressed_size,
&get_function, allow_implicit, true);
if (ret != LZMA_OK)
lzma_end(strm);
return ret;
return LZMA_OK;
}

View File

@@ -204,6 +204,14 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
coder->block_options.check = coder->header_flags.check;
coder->block_options.has_crc32 = coder->header_flags.has_crc32;
for (size_t i = 0;
i < ARRAY_SIZE(coder->block_options.filters);
++i) {
lzma_free(coder->block_options.filters[i].options,
allocator);
coder->block_options.filters[i].options = NULL;
}
return_if_error(lzma_block_header_decoder_init(
&coder->block_header_decoder, allocator,
&coder->block_options));
@@ -359,6 +367,9 @@ stream_decode(lzma_coder *coder, lzma_allocator *allocator,
static void
stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
{
for (size_t i = 0; i < ARRAY_SIZE(coder->block_options.filters); ++i)
lzma_free(coder->block_options.filters[i].options, allocator);
lzma_next_coder_end(&coder->block_decoder, allocator);
lzma_next_coder_end(&coder->block_header_decoder, allocator);
lzma_next_coder_end(&coder->flags_decoder, allocator);
@@ -389,6 +400,11 @@ stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->metadata.index = NULL;
next->coder->metadata.extra = NULL;
} else {
for (size_t i = 0; i < ARRAY_SIZE(
next->coder->block_options.filters); ++i)
lzma_free(next->coder->block_options
.filters[i].options, allocator);
lzma_index_free(next->coder->metadata.index, allocator);
next->coder->metadata.index = NULL;
@@ -396,6 +412,10 @@ stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->metadata.extra = NULL;
}
for (size_t i = 0; i < ARRAY_SIZE(next->coder->block_options.filters);
++i)
next->coder->block_options.filters[i].options = NULL;
next->coder->info = lzma_info_init(next->coder->info, allocator);
if (next->coder->info == NULL)
return LZMA_MEM_ERROR;

View File

@@ -18,6 +18,7 @@
///////////////////////////////////////////////////////////////////////////////
#include "stream_common.h"
#include "stream_encoder_multi.h"
#include "block_encoder.h"
#include "metadata_encoder.h"
@@ -79,7 +80,7 @@ block_header_encode(lzma_coder *coder, lzma_allocator *allocator,
coder->block_options = (lzma_options_block){
.check = coder->stream_options->check,
.has_crc32 = coder->stream_options->has_crc32,
.has_eopm = true,
.has_eopm = uncompressed_size == LZMA_VLI_VALUE_UNKNOWN,
.is_metadata = type != BLOCK_DATA,
.has_uncompressed_size_in_footer = false,
.has_backward_size = type == BLOCK_FOOTER_METADATA,
@@ -220,7 +221,11 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
.uncompressed_size = coder->stream_options
->uncompressed_size,
.index = NULL,
.extra = coder->stream_options->header,
// Metadata encoder doesn't modify this, but since
// the lzma_extra structure is used also when decoding
// Metadata, the pointer is not const, and we need
// to cast the constness away in the encoder.
.extra = (lzma_extra *)(coder->stream_options->header),
};
return_if_error(metadata_encoder_init(coder, allocator,
@@ -238,7 +243,7 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
.total_size = LZMA_VLI_VALUE_UNKNOWN,
.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
.index = lzma_info_index_get(coder->info, false),
.extra = coder->stream_options->footer,
.extra = (lzma_extra *)(coder->stream_options->footer),
};
return_if_error(metadata_encoder_init(coder, allocator,
@@ -271,8 +276,12 @@ stream_encode(lzma_coder *coder, lzma_allocator *allocator,
// Don't create an empty Block unless it would be
// the only Data Block.
if (*in_pos == in_size) {
// If we are LZMA_SYNC_FLUSHing or LZMA_FULL_FLUSHing,
// return LZMA_STREAM_END since there's nothing to
// flush.
if (action != LZMA_FINISH)
return LZMA_OK;
return action == LZMA_RUN
? LZMA_OK : LZMA_STREAM_END;
if (lzma_info_index_count_get(coder->info) != 0) {
if (lzma_info_index_finish(coder->info))
@@ -413,14 +422,12 @@ stream_encoder_init(lzma_next_coder *next,
}
/*
extern lzma_ret
lzma_stream_encoder_multi_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_options_stream *options)
{
lzma_next_coder_init(stream_encoder_init, next, allocator, options);
}
*/
extern LZMA_API lzma_ret

View File

@@ -0,0 +1,26 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file stream_encoder_multi.h
/// \brief Encodes Multi-Block .lzma files
//
// 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_STREAM_ENCODER_MULTI_H
#define LZMA_STREAM_ENCODER_MULTI_H
extern lzma_ret lzma_stream_encoder_multi_init(lzma_next_coder *next,
lzma_allocator *allocator, const lzma_options_stream *options);
#endif

View File

@@ -212,6 +212,7 @@ lzma_stream_encoder_single(
lzma_next_strm_init(strm, stream_encoder_init, options);
strm->internal->supported_actions[LZMA_RUN] = true;
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
strm->internal->supported_actions[LZMA_FINISH] = true;
return LZMA_OK;

View File

@@ -1 +0,0 @@
../../common/sysdefs.h

View File

@@ -429,20 +429,21 @@ lzma_lz_decoder_reset(lzma_lz_decoder *lz, lzma_allocator *allocator,
return LZMA_MEM_ERROR;
}
// Clean up the buffers to make it very sure that there are
// no information leaks when multiple steams are decoded
// with the same decoder structures.
memzero(lz->dict, dict_real_size);
memzero(lz->temp, LZMA_BUFFER_SIZE);
// Reset the variables so that lz_get_byte(lz, 0) will return '\0'.
lz->pos = 0;
lz->start = 0;
lz->end = dict_real_size;
lz->dict[dict_real_size - 1] = 0;
lz->is_full = false;
lz->eopm_detected = false;
lz->next_finished = false;
lz->this_finished = false;
lz->temp_size = 0;
// Clean up the temporary buffer to make it very sure that there are
// no information leaks when multiple steams are decoded with the
// same decoder structures.
memzero(lz->temp, LZMA_BUFFER_SIZE);
// Set the process function pointer.
lz->process = process;

View File

@@ -47,7 +47,7 @@
/// Calculate certain match finder properties and validate the calculated
/// values. This is as its own function, because *num_items is needed to
/// calculate memory requirements in common/memory.c.
extern uint32_t
extern bool
lzma_lz_encoder_hash_properties(lzma_match_finder match_finder,
uint32_t history_size, uint32_t *restrict hash_mask,
uint32_t *restrict hash_size_sum, uint32_t *restrict num_items)
@@ -141,8 +141,9 @@ lzma_lz_encoder_reset(lzma_lz_encoder *lz, lzma_allocator *allocator,
const uint8_t *preset_dictionary,
size_t preset_dictionary_size)
{
// Set uncompressed size.
lz->sequence = SEQ_START;
lz->uncompressed_size = uncompressed_size;
lz->temp_size = 0;
///////////////
// In Window //
@@ -179,17 +180,15 @@ lzma_lz_encoder_reset(lzma_lz_encoder *lz, lzma_allocator *allocator,
}
}
// Allocation successful. Store the new size and calculate
// must_move_pos.
// Allocation successful. Store the new size.
lz->size = buffer_size;
lz->must_move_pos = lz->size - lz->keep_size_after;
// Reset in window variables.
lz->offset = 0;
lz->read_pos = 0;
lz->read_limit = 0;
lz->write_pos = 0;
lz->stream_end_was_reached = false;
lz->pending = 0;
//////////////////
@@ -370,35 +369,59 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
size_t *in_pos, size_t in_size, lzma_action action)
{
assert(coder->lz.read_pos <= coder->lz.write_pos);
lzma_ret ret;
// Move the sliding window if needed.
if (coder->lz.read_pos >= coder->lz.must_move_pos)
if (coder->lz.read_pos >= coder->lz.size - coder->lz.keep_size_after)
move_window(&coder->lz);
size_t in_used;
lzma_ret ret;
if (coder->next.code == NULL) {
// Not using a filter, simply memcpy() as much as possible.
bufcpy(in, in_pos, in_size, coder->lz.buffer,
in_used = bufcpy(in, in_pos, in_size, coder->lz.buffer,
&coder->lz.write_pos, coder->lz.size);
if (action == LZMA_FINISH && *in_pos == in_size)
if (action != LZMA_RUN && *in_pos == in_size)
ret = LZMA_STREAM_END;
else
ret = LZMA_OK;
} else {
const size_t in_start = *in_pos;
ret = coder->next.code(coder->next.coder, allocator,
in, in_pos, in_size,
coder->lz.buffer, &coder->lz.write_pos,
coder->lz.size, action);
in_used = *in_pos - in_start;
}
// If end of stream has been reached, we allow the encoder to process
// all the input (that is, read_pos is allowed to reach write_pos).
// Otherwise we keep keep_size_after bytes available as prebuffer.
assert(coder->lz.uncompressed_size >= in_used);
if (coder->lz.uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->lz.uncompressed_size -= in_used;
// If end of stream has been reached or flushing completed, we allow
// the encoder to process all the input (that is, read_pos is allowed
// to reach write_pos). Otherwise we keep keep_size_after bytes
// available as prebuffer.
if (ret == LZMA_STREAM_END) {
coder->lz.stream_end_was_reached = true;
assert(*in_pos == in_size);
coder->lz.read_limit = coder->lz.write_pos;
ret = LZMA_OK;
switch (action) {
case LZMA_SYNC_FLUSH:
coder->lz.sequence = SEQ_FLUSH;
break;
case LZMA_FINISH:
coder->lz.sequence = SEQ_FINISH;
break;
default:
assert(0);
ret = LZMA_PROG_ERROR;
break;
}
} else if (coder->lz.write_pos > coder->lz.keep_size_after) {
// This needs to be done conditionally, because if we got
@@ -408,6 +431,39 @@ fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
- coder->lz.keep_size_after;
}
// Switch to finishing mode if we have got all the input data.
// lzma_lz_encode() won't return LZMA_STREAM_END until LZMA_FINISH
// is used.
//
// NOTE: When LZMA is used together with other filters, it is possible
// that coder->lz.sequence gets set to SEQ_FINISH before the next
// encoder has returned LZMA_STREAM_END. This is somewhat ugly, but
// works correctly, because the next encoder cannot have any more
// output left to be produced. If it had, then our known Uncompressed
// Size would be invalid, which would mean that we have a bad bug.
// if (ret == LZMA_OK && coder->lz.uncompressed_size == 0)
// coder->lz.sequence = SEQ_FINISH;
// The above breaks normal encoding with known uncompressed size
// if input chunk size is a multiple of uncompressed size. Commenting
// the above out breaks LZMA_SYNC_FLUSH at end of stream whose
// uncompressed size is known. Support for encoding with known
// uncompressed may get dropped completely so I won't fix this now.
// Restart the match finder after finished LZMA_SYNC_FLUSH.
if (coder->lz.pending > 0
&& coder->lz.read_pos < coder->lz.read_limit) {
// Match finder may update coder->pending and expects it to
// start from zero, so use a temporary variable.
const size_t pending = coder->lz.pending;
coder->lz.pending = 0;
// Rewind read_pos so that the match finder can hash
// the pending bytes.
assert(coder->lz.read_pos >= pending);
coder->lz.read_pos -= pending;
coder->lz.skip(&coder->lz, pending);
}
return ret;
}
@@ -419,20 +475,99 @@ lzma_lz_encode(lzma_coder *coder, lzma_allocator *allocator,
uint8_t *restrict out, size_t *restrict out_pos,
size_t out_size, lzma_action action)
{
while (*out_pos < out_size
&& (*in_pos < in_size || action == LZMA_FINISH)) {
// Fill the input window if there is no more usable data.
if (!coder->lz.stream_end_was_reached && coder->lz.read_pos
>= coder->lz.read_limit) {
const lzma_ret ret = fill_window(coder, allocator,
in, in_pos, in_size, action);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
return ret;
// Flush the temporary output buffer, which may be used when the
// encoder runs of out of space in primary output buffer (the out,
// *out_pos, and out_size variables).
if (coder->lz.temp_size > 0) {
const size_t out_avail = out_size - *out_pos;
if (out_avail < coder->lz.temp_size) {
// Cannot copy everything. Copy as much as possible
// and move the data in lz.temp to the beginning of
// that buffer.
memcpy(out + *out_pos, coder->lz.temp, out_avail);
*out_pos += out_avail;
memmove(coder->lz.temp, coder->lz.temp + out_avail,
coder->lz.temp_size - out_avail);
coder->lz.temp_size -= out_avail;
return LZMA_OK;
}
// Encode
if (coder->lz.process(coder, out, out_pos, out_size))
// We can copy everything from coder->lz.temp to out.
memcpy(out + *out_pos, coder->lz.temp, coder->lz.temp_size);
*out_pos += coder->lz.temp_size;
coder->lz.temp_size = 0;
}
switch (coder->lz.sequence) {
case SEQ_START:
assert(coder->lz.read_pos == coder->lz.write_pos);
// If there is no new input data and LZMA_SYNC_FLUSH is used
// immediatelly after previous LZMA_SYNC_FLUSH finished or
// at the very beginning of the input stream, we return
// LZMA_STREAM_END immediatelly. Writing a flush marker
// to the very beginning of the stream or right after previous
// flush marker is not allowed by the LZMA stream format.
if (*in_pos == in_size && action == LZMA_SYNC_FLUSH)
return LZMA_STREAM_END;
coder->lz.sequence = SEQ_RUN;
break;
case SEQ_FLUSH_END:
// During an earlier call to this function, flushing was
// otherwise finished except some data was left pending
// in coder->lz.buffer. Now we have copied all that data
// to the output buffer and can return LZMA_STREAM_END.
coder->lz.sequence = SEQ_START;
assert(action == LZMA_SYNC_FLUSH);
return LZMA_STREAM_END;
case SEQ_END:
// This is like the above flushing case, but for finishing
// the encoding.
//
// NOTE: action is not necesarily LZMA_FINISH; it can
// be LZMA_RUN or LZMA_SYNC_FLUSH too in case it is used
// at the end of the stream with known Uncompressed Size.
return action != LZMA_RUN ? LZMA_STREAM_END : LZMA_OK;
default:
break;
}
while (*out_pos < out_size
&& (*in_pos < in_size || action != LZMA_RUN)) {
// Read more data to coder->lz.buffer if needed.
if (coder->lz.sequence == SEQ_RUN
&& coder->lz.read_pos >= coder->lz.read_limit)
return_if_error(fill_window(coder, allocator,
in, in_pos, in_size, action));
// Encode
if (coder->lz.process(coder, out, out_pos, out_size)) {
if (coder->lz.sequence == SEQ_FLUSH) {
assert(action == LZMA_SYNC_FLUSH);
if (coder->lz.temp_size == 0) {
// Flushing was finished successfully.
coder->lz.sequence = SEQ_START;
} else {
// Flushing was otherwise finished,
// except that some data was left
// into coder->lz.buffer.
coder->lz.sequence = SEQ_FLUSH_END;
}
} else {
// NOTE: action may be LZMA_RUN here in case
// Uncompressed Size is known and we have
// processed all the data already.
assert(coder->lz.sequence == SEQ_FINISH);
coder->lz.sequence = SEQ_END;
}
return action != LZMA_RUN && coder->lz.temp_size == 0
? LZMA_STREAM_END : LZMA_OK;
}
}
return LZMA_OK;

View File

@@ -24,11 +24,16 @@
#include "common.h"
#define LZMA_LZ_TEMP_SIZE 64
typedef struct lzma_lz_encoder_s lzma_lz_encoder;
struct lzma_lz_encoder_s {
enum {
SEQ_INIT,
SEQ_START,
SEQ_RUN,
SEQ_FLUSH,
SEQ_FLUSH_END,
SEQ_FINISH,
SEQ_END
} sequence;
@@ -36,8 +41,15 @@ struct lzma_lz_encoder_s {
bool (*process)(lzma_coder *coder, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size);
/// Uncompressed Size or LZMA_VLI_VALUE_UNKNOWN if using EOPM. We need
/// to track Uncompressed Size to prevent writing flush marker to the
/// very end of stream that doesn't use EOPM.
lzma_vli uncompressed_size;
/// Temporary buffer for range encoder.
uint8_t temp[LZMA_LZ_TEMP_SIZE];
size_t temp_size;
///////////////
// In Window //
///////////////
@@ -72,9 +84,9 @@ struct lzma_lz_encoder_s {
/// to buffer[write_pos].
size_t write_pos;
/// When read_pos >= must_move_pos, move_window() must be called
/// to make more space for the input data.
size_t must_move_pos;
/// Number of bytes not hashed before read_pos. This is needed to
/// restart the match finder after LZMA_SYNC_FLUSH.
size_t pending;
/// Number of bytes that must be kept available in our input history.
/// That is, once keep_size_before bytes have been processed,
@@ -88,10 +100,6 @@ struct lzma_lz_encoder_s {
/// is allowed to reach write_pos).
size_t keep_size_after;
/// This is set to true once the last byte of the input data has
/// been copied to buffer.
bool stream_end_was_reached;
//////////////////
// Match Finder //
//////////////////
@@ -124,7 +132,7 @@ struct lzma_lz_encoder_s {
/// Calculates
extern uint32_t lzma_lz_encoder_hash_properties(lzma_match_finder match_finder,
extern bool lzma_lz_encoder_hash_properties(lzma_match_finder match_finder,
uint32_t history_size, uint32_t *restrict hash_mask,
uint32_t *restrict hash_size_sum,
uint32_t *restrict num_items);

View File

@@ -104,6 +104,14 @@ do { \
} while (0)
#define move_pending() \
do { \
++lz->read_pos; \
assert(lz->read_pos <= lz->write_pos); \
++lz->pending; \
} while (0)
//////////////////////
// Global constants //
//////////////////////
@@ -122,15 +130,16 @@ LZMA_GET_MATCHES(LZMA_MATCH_FINDER_NAME_LOWER)
if (lz->read_pos + lz->match_max_len <= lz->write_pos) {
len_limit = lz->match_max_len;
} else {
assert(lz->stream_end_was_reached);
len_limit = lz->write_pos - lz->read_pos;
if (len_limit < MIN_MATCH_CHECK) {
if (len_limit < MIN_MATCH_CHECK || lz->sequence == SEQ_FLUSH) {
distances[0] = 0;
move_pos();
move_pending();
return;
}
}
assert(lz->pending == 0);
int32_t offset = 1;
const uint32_t match_min_pos
= lz->read_pos + lz->offset > lz->cyclic_buffer_size
@@ -292,7 +301,7 @@ LZMA_SKIP(LZMA_MATCH_FINDER_NAME_LOWER)
do {
#ifdef IS_HASH_CHAIN
if (lz->write_pos - lz->read_pos < NUM_HASH_BYTES) {
move_pos();
move_pending();
continue;
}
#else
@@ -300,10 +309,10 @@ LZMA_SKIP(LZMA_MATCH_FINDER_NAME_LOWER)
if (lz->read_pos + lz->match_max_len <= lz->write_pos) {
len_limit = lz->match_max_len;
} else {
assert(lz->stream_end_was_reached == true);
len_limit = lz->write_pos - lz->read_pos;
if (len_limit < MIN_MATCH_CHECK) {
move_pos();
if (len_limit < MIN_MATCH_CHECK
|| lz->sequence == SEQ_FLUSH) {
move_pending();
continue;
}
}
@@ -313,6 +322,8 @@ LZMA_SKIP(LZMA_MATCH_FINDER_NAME_LOWER)
: 0;
#endif
assert(lz->pending == 0);
const uint8_t *cur = lz->buffer + lz->read_pos;
#ifdef HASH_ARRAY_2

View File

@@ -12,6 +12,8 @@
## Lesser General Public License for more details.
##
EXTRA_DIST = fastpos_tablegen.c
noinst_LTLIBRARIES = liblzma4.la
liblzma4_la_CPPFLAGS = \
-I@top_srcdir@/src/liblzma/api \
@@ -26,6 +28,7 @@ liblzma4_la_SOURCES = \
if COND_MAIN_ENCODER
liblzma4_la_SOURCES += \
fastpos.h \
lzma_encoder.h \
lzma_encoder.c \
lzma_encoder_presets.c \
@@ -34,6 +37,10 @@ liblzma4_la_SOURCES += \
lzma_encoder_features.c \
lzma_encoder_getoptimum.c \
lzma_encoder_getoptimumfast.c
if !COND_SMALL
liblzma4_la_SOURCES += fastpos_table.c
endif
endif
if COND_MAIN_DECODER

156
src/liblzma/lzma/fastpos.h Normal file
View File

@@ -0,0 +1,156 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file fastpos.h
/// \brief Kind of two-bit version of bit scan reverse
//
// Copyright (C) 1999-2007 Igor Pavlov
// Copyright (C) 2008 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_FASTPOS_H
#define LZMA_FASTPOS_H
// LZMA encodes match distances (positions) by storing the highest two
// bits using a six-bit value [0, 63], and then the missing lower bits.
// Dictionary size is also stored using this encoding in the new .lzma
// file format header.
//
// fastpos.h provides a way to quickly find out the correct six-bit
// values. The following table gives some examples of this encoding:
//
// pos return
// 0 0
// 1 1
// 2 2
// 3 3
// 4 4
// 5 4
// 6 5
// 7 5
// 8 6
// 11 6
// 12 7
// ... ...
// 15 7
// 16 8
// 17 8
// ... ...
// 23 8
// 24 9
// 25 9
// ... ...
//
//
// Provided functions or macros
// ----------------------------
//
// get_pos_slot(pos) is the basic version. get_pos_slot_2(pos)
// assumes that pos >= FULL_DISTANCES, thus the result is at least
// FULL_DISTANCES_BITS * 2. Using get_pos_slot(pos) instead of
// get_pos_slot_2(pos) would give the same result, but get_pos_slot_2(pos)
// should be tiny bit faster due to the assumption being made.
//
//
// Size vs. speed
// --------------
//
// With some CPUs that have fast BSR (bit scan reverse) instruction, the
// size optimized version is slightly faster than the bigger table based
// approach. Such CPUs include Intel Pentium Pro, Pentium II, Pentium III
// and Core 2 (possibly others). AMD K7 seems to have slower BSR, but that
// would still have speed roughly comparable to the table version. Older
// x86 CPUs like the original Pentium have very slow BSR; on those systems
// the table version is a lot faster.
//
// On some CPUs, the table version is a lot faster when using position
// dependent code, but with position independent code the size optimized
// version is slightly faster. This occurs at least on 32-bit SPARC (no
// ASM optimizations).
//
// I'm making the table version the default, because that has good speed
// on all systems I have tried. The size optimized version is sometimes
// slightly faster, but sometimes it is a lot slower.
//
// Finally, this code isn't a major bottle neck in LZMA encoding anyway.
#ifdef HAVE_SMALL
# include "bsr.h"
# define get_pos_slot(pos) ((pos) <= 4 ? (pos) : get_pos_slot_2(pos))
static inline uint32_t
get_pos_slot_2(uint32_t pos)
{
uint32_t i;
lzma_bsr(i, pos);
return (i + i) + ((pos >> (i - 1)) & 1);
}
#else
#define FASTPOS_BITS 13
extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS];
#define fastpos_shift(extra, n) \
((extra) + (n) * (FASTPOS_BITS - 1))
#define fastpos_limit(extra, n) \
(UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
#define fastpos_result(pos, extra, n) \
lzma_fastpos[(pos) >> fastpos_shift(extra, n)] \
+ 2 * fastpos_shift(extra, n)
static inline uint32_t
get_pos_slot(uint32_t pos)
{
// If it is small enough, we can pick the result directly from
// the precalculated table.
if (pos < fastpos_limit(0, 0))
return lzma_fastpos[pos];
if (pos < fastpos_limit(0, 1))
return fastpos_result(pos, 0, 1);
return fastpos_result(pos, 0, 2);
}
#ifdef FULL_DISTANCES_BITS
static inline uint32_t
get_pos_slot_2(uint32_t pos)
{
// FIXME: This assert() cannot be enabled at the moment, because
// lzma_getoptimum.c calls this function so that this assertion
// fails; however, it ignores the result of this function when
// this assert() would have failed.
// assert(pos >= FULL_DISTANCES);
if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 0);
if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 1);
return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 2);
}
#endif
#endif
#endif

View File

@@ -0,0 +1,519 @@
/* This file has been automatically generated by fastpos_tablegen.c. */
#include "common.h"
#include "fastpos.h"
const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25
};

View File

@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file fastpos_tablegen.c
/// \brief Generates the lzma_fastpos[] lookup table
//
// Copyright (C) 1999-2007 Igor Pavlov
// Copyright (C) 2008 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.
//
///////////////////////////////////////////////////////////////////////////////
#include <sys/types.h>
#include <inttypes.h>
#include <stdio.h>
#include "fastpos.h"
int
main(void)
{
uint8_t fastpos[1 << FASTPOS_BITS];
const uint8_t fast_slots = 2 * FASTPOS_BITS;
uint32_t c = 2;
fastpos[0] = 0;
fastpos[1] = 1;
for (uint8_t slot_fast = 2; slot_fast < fast_slots; ++slot_fast) {
const uint32_t k = 1 << ((slot_fast >> 1) - 1);
for (uint32_t j = 0; j < k; ++j, ++c)
fastpos[c] = slot_fast;
}
printf("/* This file has been automatically generated "
"by fastpos_tablegen.c. */\n\n"
"#include \"common.h\"\n"
"#include \"fastpos.h\"\n\n"
"const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {");
for (size_t i = 0; i < (1 << FASTPOS_BITS); ++i) {
if (i % 16 == 0)
printf("\n\t");
printf("%3u", (unsigned int)(fastpos[i]));
if (i != (1 << FASTPOS_BITS) - 1)
printf(",");
}
printf("\n};\n");
return 0;
}

View File

@@ -31,8 +31,6 @@
///////////////
#define REP_DISTANCES 4
#define STATES 12
#define LIT_STATES 7
#define POS_SLOT_BITS 6
#define DICT_LOG_SIZE_MAX 30
@@ -55,13 +53,10 @@
#define END_POS_MODEL_INDEX 14
#define POS_MODELS (END_POS_MODEL_INDEX - START_POS_MODEL_INDEX)
#define FULL_DISTANCES (1 << (END_POS_MODEL_INDEX / 2))
#define FULL_DISTANCES_BITS (END_POS_MODEL_INDEX / 2)
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
#define LIT_POS_STATES_BITS_MAX LZMA_LITERAL_POS_BITS_MAX
#define LIT_CONTEXT_BITS_MAX LZMA_LITERAL_CONTEXT_BITS_MAX
#define POS_STATES_BITS_MAX LZMA_POS_BITS_MAX
#define POS_STATES_MAX (1 << POS_STATES_BITS_MAX)
#define POS_STATES_MAX (1 << LZMA_POS_BITS_MAX)
// Length coder & Length price table encoder
@@ -79,7 +74,11 @@
#define LEN_CODER_TOTAL_PROBS (LEN_HIGH_CODER + LEN_HIGH_SYMBOLS)
// Price table size of Len Encoder
#define LEN_PRICES (LEN_SYMBOLS << POS_STATES_BITS_MAX)
#define LEN_PRICES (LEN_SYMBOLS << LZMA_POS_BITS_MAX)
// Special lengths used together with distance == UINT32_MAX
#define LEN_SPECIAL_EOPM MATCH_MIN_LEN
#define LEN_SPECIAL_FLUSH (LEN_SPECIAL_EOPM + 1)
// Optimal - Number of entries in the optimum array.
@@ -104,25 +103,62 @@
// State //
///////////
// Used for updating strm->data->state in both encoder and decoder.
/// This enum is used to track which events have occurred most recently and
/// in which order. This information is used to predict the next event.
///
/// Events:
/// - Literal: One 8-bit byte
/// - Match: Repeat a chunk of data at some distance
/// - Long repeat: Multi-byte match at a recently seen distance
/// - Short repeat: One-byte repeat at a recently seen distance
///
/// The event names are in from STATE_oldest_older_previous. REP means
/// either short or long repeated match, and NONLIT means any non-literal.
typedef enum {
STATE_LIT_LIT,
STATE_MATCH_LIT_LIT,
STATE_REP_LIT_LIT,
STATE_SHORTREP_LIT_LIT,
STATE_MATCH_LIT,
STATE_REP_LIT,
STATE_SHORTREP_LIT,
STATE_LIT_MATCH,
STATE_LIT_LONGREP,
STATE_LIT_SHORTREP,
STATE_NONLIT_MATCH,
STATE_NONLIT_REP,
} lzma_lzma_state;
#define update_char(index) \
index = ((index) < 4 \
? 0 \
: ((index) < 10 \
? (index) - 3 \
: (index) - 6))
#define update_match(index) \
index = ((index) < LIT_STATES ? 7 : 10)
/// Total number of states
#define STATES 12
#define update_rep(index) \
index = ((index) < LIT_STATES ? 8 : 11)
/// The lowest 7 states indicate that the previous state was a literal.
#define LIT_STATES 7
#define update_short_rep(index) \
index = ((index) < LIT_STATES ? 9 : 11)
#define is_char_state(index) \
((index) < LIT_STATES)
/// Indicate that the latest state was a literal.
#define update_literal(state) \
state = ((state) <= STATE_SHORTREP_LIT_LIT \
? STATE_LIT_LIT \
: ((state) <= STATE_LIT_SHORTREP \
? (state) - 3 \
: (state) - 6))
/// Indicate that the latest state was a match.
#define update_match(state) \
state = ((state) < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH)
/// Indicate that the latest state was a long repeated match.
#define update_long_rep(state) \
state = ((state) < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP)
/// Indicate that the latest state was a short match.
#define update_short_rep(state) \
state = ((state) < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP)
/// Test if the previous state was a literal.
#define is_literal_state(state) \
((state) < LIT_STATES)
#endif

View File

@@ -18,6 +18,9 @@
//
///////////////////////////////////////////////////////////////////////////////
// NOTE: If you want to keep the line length in 80 characters, set
// tab width to 4 or less in your editor when editing this file.
#include "lzma_common.h"
#include "lzma_decoder.h"
#include "lz_decoder.h"
@@ -44,21 +47,17 @@ do { \
if_bit_0(len_decoder.choice) { \
update_bit_0(len_decoder.choice); \
target = MATCH_MIN_LEN; \
bittree_decode(target, \
len_decoder.low[pos_state], LEN_LOW_BITS); \
bittree_decode(target, len_decoder.low[pos_state], LEN_LOW_BITS); \
} else { \
update_bit_1(len_decoder.choice); \
if_bit_0(len_decoder.choice2) { \
update_bit_0(len_decoder.choice2); \
target = MATCH_MIN_LEN + LEN_LOW_SYMBOLS; \
bittree_decode(target, len_decoder.mid[pos_state], \
LEN_MID_BITS); \
bittree_decode(target, len_decoder.mid[pos_state], LEN_MID_BITS); \
} else { \
update_bit_1(len_decoder.choice2); \
target = MATCH_MIN_LEN + LEN_LOW_SYMBOLS \
+ LEN_MID_SYMBOLS; \
bittree_decode(target, len_decoder.high, \
LEN_HIGH_BITS); \
target = MATCH_MIN_LEN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \
bittree_decode(target, len_decoder.high, LEN_HIGH_BITS); \
} \
} \
} while (0)
@@ -76,15 +75,12 @@ do { \
if_bit_0(len_decoder.choice2) { \
update_bit_0_dummy(); \
target = MATCH_MIN_LEN + LEN_LOW_SYMBOLS; \
bittree_decode_dummy(target, \
len_decoder.mid[pos_state], \
bittree_decode_dummy(target, len_decoder.mid[pos_state], \
LEN_MID_BITS); \
} else { \
update_bit_1_dummy(); \
target = MATCH_MIN_LEN + LEN_LOW_SYMBOLS \
+ LEN_MID_SYMBOLS; \
bittree_decode_dummy(target, len_decoder.high, \
LEN_HIGH_BITS); \
target = MATCH_MIN_LEN + LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \
bittree_decode_dummy(target, len_decoder.high, LEN_HIGH_BITS); \
} \
} \
} while (0)
@@ -110,7 +106,7 @@ struct lzma_coder_s {
lzma_range_decoder rc;
// State
uint32_t state;
lzma_lzma_state state;
uint32_t rep0; ///< Distance of the latest match
uint32_t rep1; ///< Distance of second latest match
uint32_t rep2; ///< Distance of third latest match
@@ -139,7 +135,7 @@ struct lzma_coder_s {
probability is_rep2[STATES];
/// If 1, the repeated match has length of one byte. Otherwise
/// the length is decoded from rep_match_len_decoder.
/// the length is decoded from rep_len_decoder.
probability is_rep0_long[STATES][POS_STATES_MAX];
probability pos_slot_decoder[LEN_TO_POS_STATES][1 << POS_SLOT_BITS];
@@ -147,14 +143,14 @@ struct lzma_coder_s {
probability pos_align_decoder[1 << ALIGN_BITS];
/// Length of a match
lzma_length_decoder len_decoder;
lzma_length_decoder match_len_decoder;
/// Length of a repeated match.
lzma_length_decoder rep_match_len_decoder;
lzma_length_decoder rep_len_decoder;
/// The first five bytes of LZMA compressed data are treated
/// specially. Once they are read, this stays at zero.
size_t init_bytes_left;
/// True when we have produced at least one byte of output since the
/// beginning of the stream or the latest flush marker.
bool has_produced_output;
};
@@ -166,7 +162,7 @@ struct lzma_coder_s {
static bool lzma_attribute((pure))
decode_dummy(const lzma_coder *restrict coder,
const uint8_t *restrict in, size_t in_pos_local,
const size_t in_size, uint32_t rc_range, uint32_t rc_code,
const size_t in_size, lzma_range_decoder rc,
uint32_t state, uint32_t rep0, const uint32_t now_pos)
{
uint32_t rc_bound;
@@ -180,50 +176,44 @@ decode_dummy(const lzma_coder *restrict coder,
update_bit_0_dummy();
const probability *subcoder = literal_get_subcoder(
coder->literal_coder,
now_pos, lz_get_byte(coder->lz, 0));
coder->literal_coder, now_pos, lz_get_byte(coder->lz, 0));
uint32_t symbol = 1;
if (!is_char_state(state)) {
// Decode literal with match byte.
if (is_literal_state(state)) {
// Decode literal without match byte.
do {
if_bit_0(subcoder[symbol]) {
update_bit_0_dummy();
symbol <<= 1;
} else {
update_bit_1_dummy();
symbol = (symbol << 1) | 1;
}
} while (symbol < 0x100);
assert(rep0 != UINT32_MAX);
uint32_t match_byte
= lz_get_byte(coder->lz, rep0);
} else {
// Decode literal with match byte.
uint32_t match_byte = lz_get_byte(coder->lz, rep0);
uint32_t subcoder_offset = 0x100;
do {
match_byte <<= 1;
const uint32_t match_bit
= match_byte & 0x100;
const uint32_t subcoder_index = 0x100
+ match_bit + symbol;
const uint32_t match_bit = match_byte & subcoder_offset;
const uint32_t subcoder_index
= subcoder_offset + match_bit + symbol;
if_bit_0(subcoder[subcoder_index]) {
update_bit_0_dummy();
symbol <<= 1;
if (match_bit != 0)
break;
subcoder_offset &= ~match_bit;
} else {
update_bit_1_dummy();
symbol = (symbol << 1) | 1;
if (match_bit == 0)
break;
subcoder_offset &= match_bit;
}
} while (symbol < 0x100);
}
// Decode literal without match byte. This is also
// the tail of the with-match-byte function.
while (symbol < 0x100) {
if_bit_0(subcoder[symbol]) {
update_bit_0_dummy();
symbol <<= 1;
} else {
update_bit_1_dummy();
symbol = (symbol << 1) | 1;
}
}
break;
}
@@ -232,14 +222,12 @@ decode_dummy(const lzma_coder *restrict coder,
if_bit_0(coder->is_rep[state]) {
update_bit_0_dummy();
length_decode_dummy(len, coder->len_decoder, pos_state);
update_match(state);
length_decode_dummy(len, coder->match_len_decoder, pos_state);
const uint32_t len_to_pos_state
= get_len_to_pos_state(len);
const uint32_t len_to_pos_state = get_len_to_pos_state(len);
uint32_t pos_slot = 0;
bittree_decode_dummy(pos_slot, coder->pos_slot_decoder[
len_to_pos_state], POS_SLOT_BITS);
bittree_decode_dummy(pos_slot,
coder->pos_slot_decoder[len_to_pos_state], POS_SLOT_BITS);
assert(pos_slot <= 63);
if (pos_slot >= START_POS_MODEL_INDEX) {
@@ -251,41 +239,25 @@ decode_dummy(const lzma_coder *restrict coder,
assert(direct_bits <= 5);
rep0 <<= direct_bits;
assert(rep0 <= 96);
// -1 is fine, because
// bittree_reverse_decode()
// starts from table index [1]
// (not [0]).
assert((int32_t)(rep0 - pos_slot - 1)
>= -1);
assert((int32_t)(rep0 - pos_slot - 1)
<= 82);
// -1 is fine, because bittree_reverse_decode()
// starts from table index [1] (not [0]).
assert((int32_t)(rep0 - pos_slot - 1) >= -1);
assert((int32_t)(rep0 - pos_slot - 1) <= 82);
// We add the result to rep0, so rep0
// must not be part of second argument
// of the macro.
const int32_t offset
= rep0 - pos_slot - 1;
bittree_reverse_decode_dummy(
coder->pos_decoders + offset,
direct_bits);
const int32_t offset = rep0 - pos_slot - 1;
bittree_reverse_decode_dummy(coder->pos_decoders + offset,
direct_bits);
} else {
// Decode direct bits
assert(pos_slot >= 14);
assert(direct_bits >= 6);
direct_bits -= ALIGN_BITS;
assert(direct_bits >= 2);
do {
rc_normalize();
rc_range >>= 1;
const uint32_t t
= (rc_code - rc_range)
>> 31;
rc_code -= rc_range & (t - 1);
} while (--direct_bits > 0);
rep0 <<= ALIGN_BITS;
rc_decode_direct_dummy(direct_bits);
bittree_reverse_decode_dummy(
coder->pos_align_decoder,
ALIGN_BITS);
bittree_reverse_decode_dummy(coder->pos_align_decoder,
ALIGN_BITS);
}
}
@@ -295,8 +267,7 @@ decode_dummy(const lzma_coder *restrict coder,
if_bit_0(coder->is_rep0[state]) {
update_bit_0_dummy();
if_bit_0(coder->is_rep0_long[state][
pos_state]) {
if_bit_0(coder->is_rep0_long[state][pos_state]) {
update_bit_0_dummy();
break;
} else {
@@ -319,18 +290,13 @@ decode_dummy(const lzma_coder *restrict coder,
}
}
length_decode_dummy(len, coder->rep_match_len_decoder,
pos_state);
length_decode_dummy(len, coder->rep_len_decoder, pos_state);
}
} while (0);
rc_normalize();
// Validate the buffer position.
if (in_pos_local > in_size)
return false;
return true;
return in_pos_local <= in_size;
}
@@ -342,15 +308,8 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
// Initialization //
////////////////////
while (coder->init_bytes_left > 0) {
if (*in_pos == in_size)
return false;
coder->rc.code = (coder->rc.code << 8) | in[*in_pos];
++*in_pos;
--coder->init_bytes_left;
}
if (!rc_read_init(&coder->rc, in, in_pos, in_size))
return false;
///////////////
// Variables //
@@ -371,6 +330,7 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
// Misc
uint32_t now_pos = coder->now_pos;
bool has_produced_output = coder->has_produced_output;
// Variables derived from decoder settings
const uint32_t pos_mask = coder->pos_mask;
@@ -383,10 +343,10 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
in_limit = in_size - REQUIRED_IN_BUFFER_SIZE;
while (coder->lz.pos < coder->lz.limit && (in_pos_local < in_limit
|| (has_safe_buffer && decode_dummy(
coder, in, in_pos_local, in_size,
rc_range, rc_code, state, rep0, now_pos)))) {
while (coder->lz.pos < coder->lz.limit
&& (in_pos_local < in_limit || (has_safe_buffer
&& decode_dummy(coder, in, in_pos_local, in_size,
rc, state, rep0, now_pos)))) {
/////////////////////
// Actual decoding //
@@ -399,58 +359,56 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
// It's a literal i.e. a single 8-bit byte.
probability *subcoder = literal_get_subcoder(
coder->literal_coder,
probability *subcoder = literal_get_subcoder(coder->literal_coder,
now_pos, lz_get_byte(coder->lz, 0));
uint32_t symbol = 1;
if (!is_char_state(state)) {
// Decode literal with match byte.
if (is_literal_state(state)) {
// Decode literal without match byte.
do {
if_bit_0(subcoder[symbol]) {
update_bit_0(subcoder[symbol]);
symbol <<= 1;
} else {
update_bit_1(subcoder[symbol]);
symbol = (symbol << 1) | 1;
}
} while (symbol < 0x100);
assert(rep0 != UINT32_MAX);
uint32_t match_byte
= lz_get_byte(coder->lz, rep0);
} else {
// Decode literal with match byte.
//
// The usage of subcoder_offset allows omitting some
// branches, which should give tiny speed improvement on
// some CPUs. subcoder_offset gets set to zero if match_bit
// didn't match.
uint32_t match_byte = lz_get_byte(coder->lz, rep0);
uint32_t subcoder_offset = 0x100;
do {
match_byte <<= 1;
const uint32_t match_bit
= match_byte & 0x100;
const uint32_t subcoder_index = 0x100
+ match_bit + symbol;
const uint32_t match_bit = match_byte & subcoder_offset;
const uint32_t subcoder_index
= subcoder_offset + match_bit + symbol;
if_bit_0(subcoder[subcoder_index]) {
update_bit_0(subcoder[
subcoder_index]);
update_bit_0(subcoder[subcoder_index]);
symbol <<= 1;
if (match_bit != 0)
break;
subcoder_offset &= ~match_bit;
} else {
update_bit_1(subcoder[
subcoder_index]);
update_bit_1(subcoder[subcoder_index]);
symbol = (symbol << 1) | 1;
if (match_bit == 0)
break;
subcoder_offset &= match_bit;
}
} while (symbol < 0x100);
}
// Decode literal without match byte. This is also
// the tail of the with-match-byte function.
while (symbol < 0x100) {
if_bit_0(subcoder[symbol]) {
update_bit_0(subcoder[symbol]);
symbol <<= 1;
} else {
update_bit_1(subcoder[symbol]);
symbol = (symbol << 1) | 1;
}
}
// Put the decoded byte to the dictionary, update the
// decoder state, and start a new decoding loop.
coder->lz.dict[coder->lz.pos++] = (uint8_t)(symbol);
++now_pos;
update_char(state);
update_literal(state);
has_produced_output = true;
continue;
}
@@ -467,79 +425,101 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
// Not a repeated match
//
// We will decode a new distance and store
// the value to rep0.
// The latest three match distances are kept in
// memory in case there are repeated matches.
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
// the value to distance.
// Decode the length of the match.
length_decode(len, coder->len_decoder, pos_state);
length_decode(len, coder->match_len_decoder, pos_state);
update_match(state);
const uint32_t len_to_pos_state
= get_len_to_pos_state(len);
const uint32_t len_to_pos_state = get_len_to_pos_state(len);
uint32_t pos_slot = 0;
bittree_decode(pos_slot, coder->pos_slot_decoder[
len_to_pos_state], POS_SLOT_BITS);
bittree_decode(pos_slot,
coder->pos_slot_decoder[len_to_pos_state], POS_SLOT_BITS);
assert(pos_slot <= 63);
if (pos_slot >= START_POS_MODEL_INDEX) {
uint32_t direct_bits = (pos_slot >> 1) - 1;
assert(direct_bits >= 1 && direct_bits <= 30);
rep0 = 2 | (pos_slot & 1);
uint32_t distance = 2 | (pos_slot & 1);
if (pos_slot < END_POS_MODEL_INDEX) {
assert(direct_bits <= 5);
rep0 <<= direct_bits;
assert(rep0 <= 96);
distance <<= direct_bits;
assert(distance <= 96);
// -1 is fine, because
// bittree_reverse_decode()
// starts from table index [1]
// (not [0]).
assert((int32_t)(rep0 - pos_slot - 1)
>= -1);
assert((int32_t)(rep0 - pos_slot - 1)
<= 82);
// We add the result to rep0, so rep0
assert((int32_t)(distance - pos_slot - 1) >= -1);
assert((int32_t)(distance - pos_slot - 1) <= 82);
// We add the result to distance, so distance
// must not be part of second argument
// of the macro.
const int32_t offset
= rep0 - pos_slot - 1;
bittree_reverse_decode(rep0,
coder->pos_decoders + offset,
direct_bits);
const int32_t offset = distance - pos_slot - 1;
bittree_reverse_decode(distance, coder->pos_decoders + offset,
direct_bits);
} else {
// Decode direct bits
assert(pos_slot >= 14);
assert(direct_bits >= 6);
direct_bits -= ALIGN_BITS;
assert(direct_bits >= 2);
do {
rc_normalize();
rc_range >>= 1;
const uint32_t t
= (rc_code - rc_range)
>> 31;
rc_code -= rc_range & (t - 1);
rep0 = (rep0 << 1) | (1 - t);
} while (--direct_bits > 0);
rep0 <<= ALIGN_BITS;
rc_decode_direct(distance, direct_bits);
distance <<= ALIGN_BITS;
bittree_reverse_decode(rep0,
coder->pos_align_decoder,
ALIGN_BITS);
bittree_reverse_decode(distance, coder->pos_align_decoder,
ALIGN_BITS);
if (rep0 == UINT32_MAX) {
// End of Payload Marker found.
coder->lz.eopm_detected = true;
break;
if (distance == UINT32_MAX) {
if (len == LEN_SPECIAL_EOPM) {
// End of Payload Marker found.
coder->lz.eopm_detected = true;
break;
} else if (len == LEN_SPECIAL_FLUSH) {
// Flush marker detected. We must have produced
// at least one byte of output since the previous
// flush marker or the beginning of the stream.
// This is to prevent hanging the decoder with
// malicious input files.
if (!has_produced_output)
return true;
has_produced_output = false;
// We know that we have enough input to call
// this macro, because it is tested at the
// end of decode_dummy().
rc_normalize();
rc_reset(rc);
// If we don't have enough input here, we jump
// out of the loop. Note that while there is a
// useless call to rc_normalize(), it does nothing
// since we have just reset the range decoder.
if (!rc_read_init(&rc, in, &in_pos_local, in_size))
break;
continue;
} else {
return true;
}
}
}
// The latest three match distances are kept in
// memory in case there are repeated matches.
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
rep0 = distance;
} else {
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
rep0 = pos_slot;
}
@@ -558,39 +538,24 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
// The distance is rep0.
if_bit_0(coder->is_rep0_long[state][
pos_state]) {
update_bit_0(coder->is_rep0_long[
state][pos_state]);
// Repeating exactly one byte. For
// simplicity, it is done here inline
// instead of at the end of the main
// loop.
if_bit_0(coder->is_rep0_long[state][pos_state]) {
update_bit_0(coder->is_rep0_long[state][pos_state]);
update_short_rep(state);
// Security/sanity checks. See the end
// of the main loop for explanation
// of these.
if ((rep0 >= coder->lz.pos
&& !coder->lz.is_full)
|| in_pos_local
> in_size)
goto error;
// Repeat one byte and start a new
// decoding loop.
// Repeat exactly one byte and start a new decoding loop.
// Note that rep0 is known to have a safe value, thus we
// don't need to check if we are wrapping the dictionary
// when it isn't full yet.
coder->lz.dict[coder->lz.pos]
= lz_get_byte(
coder->lz, rep0);
= lz_get_byte(coder->lz, rep0);
++coder->lz.pos;
++now_pos;
has_produced_output = true;
continue;
} else {
update_bit_1(coder->is_rep0_long[
state][pos_state]);
update_bit_1(coder->is_rep0_long[state][pos_state]);
// Repeating more than one byte at
// distance of rep0.
@@ -613,12 +578,10 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
update_bit_1(coder->is_rep1[state]);
if_bit_0(coder->is_rep2[state]) {
update_bit_0(coder->is_rep2[
state]);
update_bit_0(coder->is_rep2[state]);
distance = rep2;
} else {
update_bit_1(coder->is_rep2[
state]);
update_bit_1(coder->is_rep2[state]);
distance = rep3;
rep3 = rep2;
}
@@ -630,11 +593,10 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
rep0 = distance;
}
// Decode the length of the repeated match.
length_decode(len, coder->rep_match_len_decoder,
pos_state);
update_long_rep(state);
update_rep(state);
// Decode the length of the repeated match.
length_decode(len, coder->rep_len_decoder, pos_state);
}
@@ -648,15 +610,11 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
assert(len <= MATCH_MAX_LEN);
now_pos += len;
// Validate the buffer position to avoid buffer overflows
// on corrupted input data.
if (in_pos_local > in_size)
goto error;
has_produced_output = true;
// Repeat len bytes from distance of rep0.
if (!lzma_lz_out_repeat(&coder->lz, rep0, len))
goto error;
return true;
}
rc_normalize();
@@ -678,12 +636,10 @@ decode_real(lzma_coder *restrict coder, const uint8_t *restrict in,
// Misc
coder->now_pos = now_pos;
coder->has_produced_output = has_produced_output;
*in_pos = in_pos_local;
return false;
error:
return true;
}
@@ -762,7 +718,6 @@ lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->pos_bits = options->pos_bits;
next->coder->pos_mask = (1 << next->coder->pos_bits) - 1;
next->coder->now_pos = 0;
next->coder->init_bytes_left = 5;
// Range decoder
rc_reset(next->coder->rc);
@@ -790,25 +745,27 @@ lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
// Len decoders (also bit/bittree)
const uint32_t num_pos_states = 1 << next->coder->pos_bits;
bit_reset(next->coder->len_decoder.choice);
bit_reset(next->coder->len_decoder.choice2);
bit_reset(next->coder->rep_match_len_decoder.choice);
bit_reset(next->coder->rep_match_len_decoder.choice2);
bit_reset(next->coder->match_len_decoder.choice);
bit_reset(next->coder->match_len_decoder.choice2);
bit_reset(next->coder->rep_len_decoder.choice);
bit_reset(next->coder->rep_len_decoder.choice2);
for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
bittree_reset(next->coder->len_decoder.low[pos_state],
bittree_reset(next->coder->match_len_decoder.low[pos_state],
LEN_LOW_BITS);
bittree_reset(next->coder->len_decoder.mid[pos_state],
bittree_reset(next->coder->match_len_decoder.mid[pos_state],
LEN_MID_BITS);
bittree_reset(next->coder->rep_match_len_decoder.low[
pos_state], LEN_LOW_BITS);
bittree_reset(next->coder->rep_match_len_decoder.mid[
pos_state], LEN_MID_BITS);
bittree_reset(next->coder->rep_len_decoder.low[pos_state],
LEN_LOW_BITS);
bittree_reset(next->coder->rep_len_decoder.mid[pos_state],
LEN_MID_BITS);
}
bittree_reset(next->coder->len_decoder.high, LEN_HIGH_BITS);
bittree_reset(next->coder->rep_match_len_decoder.high, LEN_HIGH_BITS);
bittree_reset(next->coder->match_len_decoder.high, LEN_HIGH_BITS);
bittree_reset(next->coder->rep_len_decoder.high, LEN_HIGH_BITS);
next->coder->has_produced_output = false;
// Initialize the next decoder in the chain, if any.
{

View File

@@ -23,6 +23,7 @@
#include "lzma_encoder_private.h"
#include "fastpos.h"
////////////
@@ -70,7 +71,7 @@ do { \
#define length_encode(length_encoder, symbol, pos_state, update_price) \
do { \
\
assert((symbol) <= MATCH_MAX_LEN); \
if ((symbol) < LEN_LOW_SYMBOLS) { \
bit_encode_0((length_encoder).choice); \
bittree_encode((length_encoder).low[pos_state], \
@@ -101,7 +102,7 @@ do { \
/// \brief Updates price table of the length encoder
///
/// All all the other prices in LZMA, these are used by lzma_get_optimum().
/// Like all the other prices in LZMA, these are used by lzma_get_optimum().
///
extern void
lzma_length_encoder_update_table(lzma_length_encoder *lencoder,
@@ -116,23 +117,18 @@ lzma_length_encoder_update_table(lzma_length_encoder *lencoder,
uint32_t *prices = lencoder->prices[pos_state];
uint32_t i = 0;
for (i = 0; i < num_symbols && i < LEN_LOW_SYMBOLS; ++i) {
prices[i] = a0;
bittree_get_price(prices[i], lencoder->low[pos_state],
for (i = 0; i < num_symbols && i < LEN_LOW_SYMBOLS; ++i)
prices[i] = a0 + bittree_get_price(lencoder->low[pos_state],
LEN_LOW_BITS, i);
}
for (; i < num_symbols && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; ++i) {
prices[i] = b0;
bittree_get_price(prices[i], lencoder->mid[pos_state],
for (; i < num_symbols && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; ++i)
prices[i] = b0 + bittree_get_price(lencoder->mid[pos_state],
LEN_MID_BITS, i - LEN_LOW_SYMBOLS);
}
for (; i < num_symbols; ++i) {
prices[i] = b1;
bittree_get_price(prices[i], lencoder->high, LEN_HIGH_BITS,
for (; i < num_symbols; ++i)
prices[i] = b1 + bittree_get_price(
lencoder->high, LEN_HIGH_BITS,
i - LEN_LOW_SYMBOLS - LEN_MID_SYMBOLS);
}
lencoder->counters[pos_state] = num_symbols;
@@ -149,20 +145,11 @@ extern bool
lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size)
{
// Flush the range encoder's temporary buffer to out[].
// Return immediatelly if not everything could be flushed.
if (rc_flush_buffer(&coder->rc, out, out_pos, out_size))
return false;
// Return immediatelly if we have already finished our work.
if (coder->lz.stream_end_was_reached
&& coder->is_initialized
&& coder->lz.read_pos == coder->lz.write_pos
&& coder->additional_offset == 0)
return true;
#define rc_buffer coder->lz.temp
#define rc_buffer_size coder->lz.temp_size
// Local copies
rc_to_local(coder->rc);
lzma_range_encoder rc = coder->rc;
size_t out_pos_local = *out_pos;
const uint32_t pos_mask = coder->pos_mask;
const bool best_compression = coder->best_compression;
@@ -170,14 +157,12 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
// Initialize the stream if no data has been encoded yet.
if (!coder->is_initialized) {
if (coder->lz.read_pos == coder->lz.read_limit) {
// Cannot initialize, because there is no input data.
if (!coder->lz.stream_end_was_reached)
return false;
if (coder->lz.sequence == SEQ_RUN)
return false; // We cannot do anything.
// If we get here, we are encoding an empty file.
// Initialization is skipped completely.
// We are finishing (we cannot get here when flushing).
assert(coder->lz.write_pos == coder->lz.read_pos);
assert(coder->lz.sequence == SEQ_FINISH);
} else {
// Do the actual initialization.
uint32_t len;
@@ -185,7 +170,7 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
lzma_read_match_distances(coder, &len, &num_distance_pairs);
bit_encode_0(coder->is_match[coder->state][0]);
update_char(coder->state);
update_literal(coder->state);
const uint8_t cur_byte = coder->lz.buffer[
coder->lz.read_pos - coder->additional_offset];
@@ -214,9 +199,10 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
// Check that there is some input to process.
if (coder->lz.read_pos >= coder->lz.read_limit) {
// If end of input has been reached, we must keep
// encoding until additional_offset becomes zero.
if (!coder->lz.stream_end_was_reached
// If flushing or finishing, we must keep encoding
// until additional_offset becomes zero to make
// all the input available at output.
if (coder->lz.sequence == SEQ_RUN
|| coder->additional_offset == 0)
break;
}
@@ -224,7 +210,7 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
assert(coder->lz.read_pos <= coder->lz.write_pos);
#ifndef NDEBUG
if (coder->lz.stream_end_was_reached) {
if (coder->lz.sequence != SEQ_RUN) {
assert(coder->lz.read_limit == coder->lz.write_pos);
} else {
assert(coder->lz.read_limit + coder->lz.keep_size_after
@@ -258,7 +244,7 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
probability *subcoder = literal_get_subcoder(coder->literal_coder,
coder->now_pos, coder->previous_byte);
if (is_char_state(coder->state)) {
if (is_literal_state(coder->state)) {
literal_encode(subcoder, cur_byte);
} else {
const uint8_t match_byte = coder->lz.buffer[
@@ -268,7 +254,7 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
literal_encode_matched(subcoder, match_byte, cur_byte);
}
update_char(coder->state);
update_literal(coder->state);
coder->previous_byte = cur_byte;
} else {
@@ -308,16 +294,16 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
if (len == 1) {
update_short_rep(coder->state);
} else {
length_encode(coder->rep_match_len_encoder,
length_encode(coder->rep_len_encoder,
len - MATCH_MIN_LEN, pos_state,
best_compression);
update_rep(coder->state);
update_long_rep(coder->state);
}
} else {
bit_encode_0(coder->is_rep[coder->state]);
update_match(coder->state);
length_encode(coder->len_encoder, len - MATCH_MIN_LEN,
length_encode(coder->match_len_encoder, len - MATCH_MIN_LEN,
pos_state, best_compression);
pos -= REP_DISTANCES;
@@ -363,20 +349,24 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
// Check if everything is done.
bool all_done = false;
if (coder->lz.stream_end_was_reached
if (coder->lz.sequence != SEQ_RUN
&& coder->lz.read_pos == coder->lz.write_pos
&& coder->additional_offset == 0) {
// Write end of stream marker. It is encoded as a match with
// distance of UINT32_MAX. Match length is needed but it is
// ignored by the decoder.
if (coder->lz.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN) {
assert(coder->longest_match_was_found == false);
if (coder->lz.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN
|| coder->lz.sequence == SEQ_FLUSH) {
// Write special marker: flush marker or end of payload
// marker. Both are encoded as a match with distance of
// UINT32_MAX. The match length codes the type of the marker.
const uint32_t pos_state = coder->now_pos & pos_mask;
bit_encode_1(coder->is_match[coder->state][pos_state]);
bit_encode_0(coder->is_rep[coder->state]);
update_match(coder->state);
const uint32_t len = MATCH_MIN_LEN; // MATCH_MAX_LEN;
length_encode(coder->len_encoder, len - MATCH_MIN_LEN,
const uint32_t len = coder->lz.sequence == SEQ_FLUSH
? LEN_SPECIAL_FLUSH : LEN_SPECIAL_EOPM;
length_encode(coder->match_len_encoder, len - MATCH_MIN_LEN,
pos_state, best_compression);
const uint32_t pos_slot = (1 << POS_SLOT_BITS) - 1;
@@ -398,15 +388,16 @@ lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out,
// the range coder to the output buffer.
rc_flush();
rc_reset(rc);
// All done. Note that some output bytes might be
// pending in coder->buffer. lzma_encode() will
// pending in coder->lz.temp. lzma_lz_encode() will
// take care of those bytes.
if (rc_buffer_size == 0)
all_done = true;
all_done = true;
}
// Store local variables back to *coder.
rc_from_local(coder->rc);
coder->rc = rc;
*out_pos = out_pos_local;
return all_done;

View File

@@ -27,6 +27,7 @@
#include "lzma_encoder_private.h"
#include "fastpos.h"
#define length_get_price(length_encoder, symbol, pos_state) \
@@ -62,7 +63,7 @@ do { \
#define get_rep_price(price_target, rep_index, len, state, pos_state) \
do { \
get_pure_rep_price(price_target, rep_index, state, pos_state); \
price_target += length_get_price(coder->rep_match_len_encoder, \
price_target += length_get_price(coder->rep_len_encoder, \
(len) - MATCH_MIN_LEN, pos_state); \
} while (0)
@@ -79,7 +80,7 @@ do { \
+ align_prices[(pos) & ALIGN_MASK]; \
} \
price_target += length_get_price( \
coder->len_encoder, (len) - MATCH_MIN_LEN, pos_state); \
coder->match_len_encoder, (len) - MATCH_MIN_LEN, pos_state); \
} while (0)
@@ -111,8 +112,7 @@ fill_distances_prices(lzma_coder *coder)
const uint32_t pos_slot = get_pos_slot(i);
const uint32_t footer_bits = ((pos_slot >> 1) - 1);
const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
temp_prices[i] = 0;
bittree_reverse_get_price(temp_prices[i],
temp_prices[i] = bittree_reverse_get_price(
coder->pos_encoders + base - pos_slot - 1,
footer_bits, i - base);
}
@@ -129,8 +129,7 @@ fill_distances_prices(lzma_coder *coder)
for (uint32_t pos_slot = 0;
pos_slot < dist_table_size;
++pos_slot) {
pos_slot_prices[pos_slot] = 0;
bittree_get_price(pos_slot_prices[pos_slot], encoder,
pos_slot_prices[pos_slot] = bittree_get_price(encoder,
POS_SLOT_BITS, pos_slot);
}
@@ -162,14 +161,12 @@ fill_distances_prices(lzma_coder *coder)
static void
fill_align_prices(lzma_coder *coder)
{
for (uint32_t i = 0; i < ALIGN_TABLE_SIZE; ++i) {
uint32_t tmp = 0;
bittree_reverse_get_price(tmp, coder->pos_align_encoder,
ALIGN_BITS, i);
coder->align_prices[i] = tmp;
}
for (uint32_t i = 0; i < ALIGN_TABLE_SIZE; ++i)
coder->align_prices[i] = bittree_reverse_get_price(
coder->pos_align_encoder, ALIGN_BITS, i);
coder->align_price_count = 0;
return;
}
@@ -371,7 +368,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
+ literal_get_price(
literal_get_subcoder(coder->literal_coder,
position, coder->previous_byte),
!is_char_state(coder->state), match_byte, current_byte);
!is_literal_state(coder->state), match_byte, current_byte);
make_as_char(coder->optimum[1]);
@@ -427,7 +424,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
do {
const uint32_t cur_and_len_price = price
+ length_get_price(
coder->rep_match_len_encoder,
coder->rep_len_encoder,
rep_len - 2, pos_state);
if (cur_and_len_price < coder->optimum[rep_len].price) {
@@ -516,7 +513,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
state = coder->optimum[coder->optimum[cur].pos_prev_2].state;
if (coder->optimum[cur].back_prev_2 < REP_DISTANCES)
update_rep(state);
update_long_rep(state);
else
update_match(state);
@@ -524,7 +521,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
state = coder->optimum[pos_prev].state;
}
update_char(state);
update_literal(state);
} else {
state = coder->optimum[pos_prev].state;
@@ -534,17 +531,17 @@ lzma_get_optimum(lzma_coder *restrict coder,
if (is_short_rep(coder->optimum[cur]))
update_short_rep(state);
else
update_char(state);
update_literal(state);
} else {
uint32_t pos;
if (coder->optimum[cur].prev_1_is_char && coder->optimum[cur].prev_2) {
pos_prev = coder->optimum[cur].pos_prev_2;
pos = coder->optimum[cur].back_prev_2;
update_rep(state);
update_long_rep(state);
} else {
pos = coder->optimum[cur].back_prev;
if (pos < REP_DISTANCES)
update_rep(state);
update_long_rep(state);
else
update_match(state);
}
@@ -585,7 +582,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
+ literal_get_price(
literal_get_subcoder(coder->literal_coder,
position, buf[-1]),
!is_char_state(state), match_byte, current_byte);
!is_literal_state(state), match_byte, current_byte);
bool next_is_char = false;
@@ -641,7 +638,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
if (len_test_2 >= 2) {
uint32_t state_2 = state;
update_char(state_2);
update_literal(state_2);
const uint32_t pos_state_next = (position + 1) & pos_mask;
const uint32_t next_rep_match_price = cur_and_1_price
@@ -692,7 +689,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
do {
const uint32_t cur_and_len_price = price
+ length_get_price(coder->rep_match_len_encoder,
+ length_get_price(coder->rep_len_encoder,
len_test - 2, pos_state);
if (cur_and_len_price < coder->optimum[cur + len_test].price) {
@@ -720,12 +717,12 @@ lzma_get_optimum(lzma_coder *restrict coder,
if (len_test_2 >= 2) {
uint32_t state_2 = state;
update_rep(state_2);
update_long_rep(state_2);
uint32_t pos_state_next = (position + len_test) & pos_mask;
const uint32_t cur_and_len_char_price = price
+ length_get_price(coder->rep_match_len_encoder,
+ length_get_price(coder->rep_len_encoder,
len_test - 2, pos_state)
+ bit_get_price_0(coder->is_match[state_2][pos_state_next])
+ literal_get_price(
@@ -733,7 +730,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
position + len_test, buf[len_test - 1]),
true, *(buf + len_test - back_offset), buf[len_test]);
update_char(state_2);
update_literal(state_2);
pos_state_next = (position + len_test + 1) & pos_mask;
@@ -804,7 +801,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
len_to_pos_state][pos_slot]
+ align_prices[cur_back & ALIGN_MASK];
cur_and_len_price += length_get_price(coder->len_encoder,
cur_and_len_price += length_get_price(coder->match_len_encoder,
len_test - MATCH_MIN_LEN, pos_state);
if (cur_and_len_price < coder->optimum[cur + len_test].price) {
@@ -846,7 +843,7 @@ lzma_get_optimum(lzma_coder *restrict coder,
*(buf + len_test - back_offset),
buf[len_test]);
update_char(state_2);
update_literal(state_2);
pos_state_next = (pos_state_next + 1) & pos_mask;
const uint32_t next_rep_match_price

View File

@@ -21,28 +21,6 @@
#include "lzma_encoder_private.h"
uint8_t lzma_fastpos[1 << 11];
extern void
lzma_fastpos_init(void)
{
static const uint8_t fast_slots = 22;
int c = 2;
lzma_fastpos[0] = 0;
lzma_fastpos[1] = 1;
for (uint8_t slot_fast = 2; slot_fast < fast_slots; ++slot_fast) {
const uint32_t k = (1 << ((slot_fast >> 1) - 1));
for (uint32_t j = 0; j < k; ++j, ++c)
lzma_fastpos[c] = slot_fast;
}
return;
}
/// \brief Initializes the length encoder
static void
length_encoder_reset(lzma_length_encoder *lencoder,
@@ -158,6 +136,8 @@ lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
}
// Misc FIXME desc
next->coder->align_price_count = UINT32_MAX;
next->coder->match_price_count = UINT32_MAX;
next->coder->dictionary_size = options->dictionary_size;
next->coder->pos_mask = (1U << options->pos_bits) - 1;
next->coder->fast_bytes = options->fast_bytes;
@@ -194,10 +174,11 @@ lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
bittree_reset(next->coder->pos_align_encoder, ALIGN_BITS);
// Length encoders
length_encoder_reset(&next->coder->len_encoder, 1U << options->pos_bits,
length_encoder_reset(&next->coder->match_len_encoder,
1U << options->pos_bits,
options->fast_bytes + 1 - MATCH_MIN_LEN);
length_encoder_reset(&next->coder->rep_match_len_encoder,
length_encoder_reset(&next->coder->rep_len_encoder,
1U << options->pos_bits,
next->coder->fast_bytes + 1 - MATCH_MIN_LEN);

View File

@@ -24,13 +24,15 @@
#include "lzma_encoder.h"
#include "lzma_common.h"
#include "lz_encoder.h"
#include "range_encoder.h"
// We need space for about two encoding loops, because there is no check
// for available buffer space before end of payload marker gets written.
// 2*26 bytes should be enough for this... but Lasse isn't very sure about
// the exact value. 64 bytes certainly is enough. :-)
#define RC_BUFFER_SIZE 64
#include "range_encoder.h"
#if LZMA_LZ_TEMP_SIZE < 64
# error LZMA_LZ_TEMP_SIZE is too small.
#endif
#define move_pos(num) \
@@ -43,27 +45,6 @@ do { \
} while (0)
#define get_pos_slot(pos) \
((pos) < (1 << 11) \
? lzma_fastpos[pos] \
: ((pos) < (1 << 21) \
? lzma_fastpos[(pos) >> 10] + 20 \
: lzma_fastpos[(pos) >> 20] + 40))
#define get_pos_slot_2(pos) \
((pos) < (1 << 17) \
? lzma_fastpos[(pos) >> 6] + 12 \
: ((pos) < (1 << 27) \
? lzma_fastpos[(pos) >> 16] + 32 \
: lzma_fastpos[(pos) >> 26] + 52))
/// This isn't modified once its contents have been
/// initialized by lzma_fastpos_init().
extern uint8_t lzma_fastpos[1 << 11];
typedef struct {
probability choice;
probability choice2;
@@ -79,7 +60,7 @@ typedef struct {
typedef struct {
uint32_t state;
lzma_lzma_state state;
bool prev_1_is_char;
bool prev_2;
@@ -107,7 +88,7 @@ struct lzma_coder_s {
lzma_range_encoder rc;
// State
uint32_t state;
lzma_lzma_state state;
uint8_t previous_byte;
uint32_t rep_distances[REP_DISTANCES];
@@ -136,8 +117,8 @@ struct lzma_coder_s {
probability pos_align_encoder[1 << ALIGN_BITS];
// Length encoders
lzma_length_encoder len_encoder;
lzma_length_encoder rep_match_len_encoder;
lzma_length_encoder match_len_encoder;
lzma_length_encoder rep_len_encoder;
// Optimal
lzma_optimal optimum[OPTS];
@@ -197,12 +178,12 @@ lzma_read_match_distances(lzma_coder *coder,
uint32_t limit = MATCH_MAX_LEN - *len_res;
assert(offset + limit < coder->lz.keep_size_after);
assert(coder->lz.read_pos <= coder->lz.write_pos);
// If we are close to end of the stream, we may need
// to limit the length of the match.
if (coder->lz.stream_end_was_reached
&& coder->lz.write_pos
< coder->lz.read_pos + offset + limit)
if (coder->lz.write_pos - coder->lz.read_pos
< offset + limit)
limit = coder->lz.write_pos
- (coder->lz.read_pos + offset);

View File

@@ -12,6 +12,8 @@
## Lesser General Public License for more details.
##
EXTRA_DIST = price_table_gen.c
noinst_LTLIBRARIES = librangecoder.la
librangecoder_la_SOURCES = range_common.h
@@ -20,7 +22,12 @@ librangecoder_la_CPPFLAGS = \
-I@top_srcdir@/src/liblzma/common
if COND_MAIN_ENCODER
librangecoder_la_SOURCES += range_encoder.c range_encoder.h
librangecoder_la_SOURCES += range_encoder.h
if COND_SMALL
librangecoder_la_SOURCES += price_table_init.c
else
librangecoder_la_SOURCES += price_table.c
endif
endif
if COND_MAIN_DECODER

View File

@@ -0,0 +1,70 @@
/* This file has been automatically generated by price_table_gen.c. */
#include "range_encoder.h"
const uint32_t lzma_rc_prob_prices[BIT_MODEL_TOTAL >> MOVE_REDUCING_BITS] = {
0, 576, 512, 480, 448, 432, 416, 400,
384, 376, 368, 360, 352, 344, 336, 328,
320, 316, 312, 308, 304, 300, 296, 292,
288, 284, 280, 276, 272, 268, 264, 260,
256, 254, 252, 250, 248, 246, 244, 242,
240, 238, 236, 234, 232, 230, 228, 226,
224, 222, 220, 218, 216, 214, 212, 210,
208, 206, 204, 202, 200, 198, 196, 194,
192, 191, 190, 189, 188, 187, 186, 185,
184, 183, 182, 181, 180, 179, 178, 177,
176, 175, 174, 173, 172, 171, 170, 169,
168, 167, 166, 165, 164, 163, 162, 161,
160, 159, 158, 157, 156, 155, 154, 153,
152, 151, 150, 149, 148, 147, 146, 145,
144, 143, 142, 141, 140, 139, 138, 137,
136, 135, 134, 133, 132, 131, 130, 129,
128, 127, 127, 126, 126, 125, 125, 124,
124, 123, 123, 122, 122, 121, 121, 120,
120, 119, 119, 118, 118, 117, 117, 116,
116, 115, 115, 114, 114, 113, 113, 112,
112, 111, 111, 110, 110, 109, 109, 108,
108, 107, 107, 106, 106, 105, 105, 104,
104, 103, 103, 102, 102, 101, 101, 100,
100, 99, 99, 98, 98, 97, 97, 96,
96, 95, 95, 94, 94, 93, 93, 92,
92, 91, 91, 90, 90, 89, 89, 88,
88, 87, 87, 86, 86, 85, 85, 84,
84, 83, 83, 82, 82, 81, 81, 80,
80, 79, 79, 78, 78, 77, 77, 76,
76, 75, 75, 74, 74, 73, 73, 72,
72, 71, 71, 70, 70, 69, 69, 68,
68, 67, 67, 66, 66, 65, 65, 64,
64, 63, 63, 63, 63, 62, 62, 62,
62, 61, 61, 61, 61, 60, 60, 60,
60, 59, 59, 59, 59, 58, 58, 58,
58, 57, 57, 57, 57, 56, 56, 56,
56, 55, 55, 55, 55, 54, 54, 54,
54, 53, 53, 53, 53, 52, 52, 52,
52, 51, 51, 51, 51, 50, 50, 50,
50, 49, 49, 49, 49, 48, 48, 48,
48, 47, 47, 47, 47, 46, 46, 46,
46, 45, 45, 45, 45, 44, 44, 44,
44, 43, 43, 43, 43, 42, 42, 42,
42, 41, 41, 41, 41, 40, 40, 40,
40, 39, 39, 39, 39, 38, 38, 38,
38, 37, 37, 37, 37, 36, 36, 36,
36, 35, 35, 35, 35, 34, 34, 34,
34, 33, 33, 33, 33, 32, 32, 32,
32, 31, 31, 31, 31, 30, 30, 30,
30, 29, 29, 29, 29, 28, 28, 28,
28, 27, 27, 27, 27, 26, 26, 26,
26, 25, 25, 25, 25, 24, 24, 24,
24, 23, 23, 23, 23, 22, 22, 22,
22, 21, 21, 21, 21, 20, 20, 20,
20, 19, 19, 19, 19, 18, 18, 18,
18, 17, 17, 17, 17, 16, 16, 16,
16, 15, 15, 15, 15, 14, 14, 14,
14, 13, 13, 13, 13, 12, 12, 12,
12, 11, 11, 11, 11, 10, 10, 10,
10, 9, 9, 9, 9, 8, 8, 8,
8, 7, 7, 7, 7, 6, 6, 6,
6, 5, 5, 5, 5, 4, 4, 4,
4, 3, 3, 3, 3, 2, 2, 2,
2, 1, 1, 1, 1, 0, 0, 0
};

View File

@@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file price_table_gen.c
/// \brief Probability price table generator
///
/// Compiling: gcc -std=c99 -o price_table_gen price_table_gen.c
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#include <sys/types.h>
#include <inttypes.h>
#include <stdio.h>
#include "range_common.h"
#include "price_table_init.c"
int
main(void)
{
lzma_rc_init();
printf("/* This file has been automatically generated by "
"price_table_gen.c. */\n\n"
"#include \"range_encoder.h\"\n\n"
"const uint32_t lzma_rc_prob_prices["
"BIT_MODEL_TOTAL >> MOVE_REDUCING_BITS] = {");
const size_t array_size = sizeof(lzma_rc_prob_prices)
/ sizeof(lzma_rc_prob_prices[0]);
for (size_t i = 0; i < array_size; ++i) {
if (i % 8 == 0)
printf("\n\t");
printf("%4" PRIu32, lzma_rc_prob_prices[i]);
if (i != array_size - 1)
printf(",");
}
printf("\n};\n");
return 0;
}

View File

@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file range_encoder.c
/// \file price_table_init.c
/// \brief Static initializations for the range encoder's prices array
//
// Copyright (C) 1999-2006 Igor Pavlov
@@ -18,7 +18,9 @@
//
///////////////////////////////////////////////////////////////////////////////
#include "range_encoder.h"
#ifdef HAVE_CONFIG_H
# include "range_encoder.h"
#endif
#define NUM_BITS (BIT_MODEL_TOTAL_BITS - MOVE_REDUCING_BITS)

View File

@@ -21,7 +21,9 @@
#ifndef LZMA_RANGE_COMMON_H
#define LZMA_RANGE_COMMON_H
#include "common.h"
#ifdef HAVE_CONFIG_H
# include "common.h"
#endif
///////////////
@@ -58,11 +60,24 @@
// Type definitions //
//////////////////////
// Bit coder speed optimization
// uint16_t is enough for probability, but usually uint32_t is faster and it
// doesn't waste too much memory. If uint64_t is fastest on 64-bit CPU, you
// probably want to use that instead of uint32_t. With uint64_t you will
// waste RAM _at maximum_ of 4.5 MiB (same for both encoding and decoding).
typedef uint32_t probability;
/// \brief Type of probabilities used with range coder
///
/// This needs to be at least 12-bit integer, so uint16_t is a logical choice.
/// However, on some architecture and compiler combinations, a bigger type
/// may give better speed, because the probability variables are accessed
/// a lot. On the other hand, bigger probability type increases cache
/// footprint, since there are 2 to 14 thousand probability variables in
/// LZMA (assuming the limit of lc + lp <= 4; with lc + lp <= 12 there
/// would be about 1.5 million variables).
///
/// With malicious files, the initialization speed of the LZMA decoder can
/// become important. In that case, smaller probability variables mean that
/// there is less bytes to write to RAM, which makes initialization faster.
/// With big probability type, the initialization can become so slow that it
/// can be a problem e.g. for email servers doing virus scanning.
///
/// I will be sticking to uint16_t unless some specific architectures
/// are *much* faster (20-50 %) with uint32_t.
typedef uint16_t probability;
#endif

View File

@@ -27,36 +27,50 @@
typedef struct {
uint32_t range;
uint32_t code;
uint32_t init_bytes_left;
} lzma_range_decoder;
static inline bool
rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
size_t *restrict in_pos, size_t in_size)
{
while (rc->init_bytes_left > 0) {
if (*in_pos == in_size)
return false;
rc->code = (rc->code << 8) | in[*in_pos];
++*in_pos;
--rc->init_bytes_left;
}
return true;
}
/// Makes local copies of range decoder variables.
#define rc_to_local(rc) \
uint32_t rc_range = (rc).range; \
uint32_t rc_code = (rc).code; \
#define rc_to_local(range_decoder) \
lzma_range_decoder rc = range_decoder; \
uint32_t rc_bound
/// Stores the local copes back to the range decoder structure.
#define rc_from_local(rc) \
do {\
(rc).range = rc_range; \
(rc).code = rc_code; \
} while (0)
#define rc_from_local(range_decoder) \
range_decoder = rc
/// Resets the range decoder structure.
#define rc_reset(rc) \
#define rc_reset(range_decoder) \
do { \
(rc).range = UINT32_MAX; \
(rc).code = 0; \
(range_decoder).range = UINT32_MAX; \
(range_decoder).code = 0; \
(range_decoder).init_bytes_left = 5; \
} while (0)
// All of the macros in this file expect the following variables being defined:
// - uint32_t rc_range;
// - uint32_t rc_code;
// - lzma_range_decoder range_decoder;
// - uint32_t rc_bound; // Temporary variable
// - uint8_t *in;
// - size_t in_pos_local; // Local alias for *in_pos
// - uint8_t *in;
// - size_t in_pos_local; // Local alias for *in_pos
//////////////////
@@ -66,9 +80,9 @@ do { \
// Read the next byte of compressed data from buffer_in, if needed.
#define rc_normalize() \
do { \
if (rc_range < TOP_VALUE) { \
rc_range <<= SHIFT_BITS; \
rc_code = (rc_code << SHIFT_BITS) | in[in_pos_local++]; \
if (rc.range < TOP_VALUE) { \
rc.range <<= SHIFT_BITS; \
rc.code = (rc.code << SHIFT_BITS) | in[in_pos_local++]; \
} \
} while (0)
@@ -88,37 +102,57 @@ do { \
#define if_bit_0(prob) \
rc_normalize(); \
rc_bound = (rc_range >> BIT_MODEL_TOTAL_BITS) * (prob); \
if (rc_code < rc_bound)
rc_bound = (rc.range >> BIT_MODEL_TOTAL_BITS) * (prob); \
if (rc.code < rc_bound)
#define update_bit_0(prob) \
do { \
rc_range = rc_bound; \
rc.range = rc_bound; \
prob += (BIT_MODEL_TOTAL - (prob)) >> MOVE_BITS; \
} while (0)
#define update_bit_1(prob) \
do { \
rc_range -= rc_bound; \
rc_code -= rc_bound; \
rc.range -= rc_bound; \
rc.code -= rc_bound; \
prob -= (prob) >> MOVE_BITS; \
} while (0)
// Dummy versions don't update prob.
#define rc_decode_direct(dest, count) \
do { \
rc_normalize(); \
rc.range >>= 1; \
rc.code -= rc.range; \
rc_bound = UINT32_C(0) - (rc.code >> 31); \
rc.code += rc.range & rc_bound; \
dest = (dest << 1) + (rc_bound + 1); \
} while (--count > 0)
// Dummy versions don't update prob or dest.
#define update_bit_0_dummy() \
rc_range = rc_bound
rc.range = rc_bound
#define update_bit_1_dummy() \
do { \
rc_range -= rc_bound; \
rc_code -= rc_bound; \
rc.range -= rc_bound; \
rc.code -= rc_bound; \
} while (0)
#define rc_decode_direct_dummy(count) \
do { \
rc_normalize(); \
rc.range >>= 1; \
rc.code -= rc.range; \
rc.code += rc.range & (UINT32_C(0) - (rc.code >> 31)); \
} while (--count > 0)
///////////////////////
// Bit tree decoding //
///////////////////////

View File

@@ -24,46 +24,38 @@
#include "range_common.h"
// Allow #including this file even if RC_TEMP_BUFFER_SIZE isn't defined.
#ifdef RC_BUFFER_SIZE
typedef struct {
uint64_t low;
uint64_t cache_size;
uint32_t range;
uint32_t cache_size;
uint8_t cache;
uint8_t buffer[RC_BUFFER_SIZE];
size_t buffer_size;
} lzma_range_encoder;
#ifdef HAVE_SMALL
/// Probability prices used by *_get_price() macros. This is initialized
/// by lzma_rc_init() and is not modified later.
extern uint32_t lzma_rc_prob_prices[BIT_MODEL_TOTAL >> MOVE_REDUCING_BITS];
/// Initializes lzma_rc_prob_prices[]. This needs to be called only once.
extern void lzma_rc_init(void);
#else
// Not building a size optimized version, so we use a precomputed
// constant table.
extern const uint32_t
lzma_rc_prob_prices[BIT_MODEL_TOTAL >> MOVE_REDUCING_BITS];
#endif
/// Makes local copies of range encoder variables.
#define rc_to_local(rc) \
uint64_t rc_low = (rc).low; \
uint32_t rc_range = (rc).range; \
uint32_t rc_cache_size = (rc).cache_size; \
uint8_t rc_cache = (rc).cache; \
uint8_t *rc_buffer = (rc).buffer; \
size_t rc_buffer_size = (rc).buffer_size
/// Stores the local copes back to the range encoder structure.
#define rc_from_local(rc) \
do { \
(rc).low = rc_low; \
(rc).range = rc_range; \
(rc).cache_size = rc_cache_size; \
(rc).cache = rc_cache; \
(rc).buffer_size = rc_buffer_size; \
} while (0)
/// Resets the range encoder structure.
#define rc_reset(rc) \
do { \
(rc).low = 0; \
(rc).range = 0xFFFFFFFF; \
(rc).range = UINT32_MAX; \
(rc).cache_size = 1; \
(rc).cache = 0; \
(rc).buffer_size = 0; \
} while (0)
@@ -72,13 +64,14 @@ do { \
//////////////////
// These macros expect that the following variables are defined:
// - uint64_t rc_low;
// - uint32_t rc_range;
// - uint8_t rc_cache;
// - uint32_t rc_cache_size;
// - uint8_t *out;
// - size_t out_pos_local; // Local copy of *out_pos
// - size_t size_out;
// - lzma_range_encoder rc;
// - uint8_t *out;
// - size_t out_pos_local; // Local copy of *out_pos
// - size_t size_out;
//
// Macros pointing to these variables are also needed:
// - uint8_t rc_buffer[]; // Don't use a pointer, must be real array!
// - size_t rc_buffer_size;
// Combined from NRangeCoder::CEncoder::Encode()
@@ -87,13 +80,13 @@ do { \
do { \
probability rc_prob = prob; \
const uint32_t rc_bound \
= (rc_range >> BIT_MODEL_TOTAL_BITS) * rc_prob; \
= (rc.range >> BIT_MODEL_TOTAL_BITS) * rc_prob; \
if ((symbol) == 0) { \
rc_range = rc_bound; \
rc.range = rc_bound; \
rc_prob += (BIT_MODEL_TOTAL - rc_prob) >> MOVE_BITS; \
} else { \
rc_low += rc_bound; \
rc_range -= rc_bound; \
rc.low += rc_bound; \
rc.range -= rc_bound; \
rc_prob -= rc_prob >> MOVE_BITS; \
} \
prob = rc_prob; \
@@ -105,7 +98,7 @@ do { \
#define bit_encode_0(prob) \
do { \
probability rc_prob = prob; \
rc_range = (rc_range >> BIT_MODEL_TOTAL_BITS) * rc_prob; \
rc.range = (rc.range >> BIT_MODEL_TOTAL_BITS) * rc_prob; \
rc_prob += (BIT_MODEL_TOTAL - rc_prob) >> MOVE_BITS; \
prob = rc_prob; \
rc_normalize(); \
@@ -116,10 +109,10 @@ do { \
#define bit_encode_1(prob) \
do { \
probability rc_prob = prob; \
const uint32_t rc_bound = (rc_range >> BIT_MODEL_TOTAL_BITS) \
const uint32_t rc_bound = (rc.range >> BIT_MODEL_TOTAL_BITS) \
* rc_prob; \
rc_low += rc_bound; \
rc_range -= rc_bound; \
rc.low += rc_bound; \
rc.range -= rc_bound; \
rc_prob -= rc_prob >> MOVE_BITS; \
prob = rc_prob; \
rc_normalize(); \
@@ -160,9 +153,9 @@ do { \
#define rc_encode_direct_bits(value, num_total_bits) \
do { \
for (int32_t rc_i = (num_total_bits) - 1; rc_i >= 0; --rc_i) { \
rc_range >>= 1; \
rc.range >>= 1; \
if ((((value) >> rc_i) & 1) == 1) \
rc_low += rc_range; \
rc.low += rc.range; \
rc_normalize(); \
} \
} while (0)
@@ -175,8 +168,8 @@ do { \
// Calls rc_shift_low() to write out a byte if needed.
#define rc_normalize() \
do { \
if (rc_range < TOP_VALUE) { \
rc_range <<= SHIFT_BITS; \
if (rc.range < TOP_VALUE) { \
rc.range <<= SHIFT_BITS; \
rc_shift_low(); \
} \
} while (0)
@@ -192,23 +185,23 @@ do { \
// TODO: Notation change?
// (uint32_t)(0xFF000000) => ((uint32_t)(0xFF) << TOP_BITS)
// TODO: Another notation change?
// rc_low = (uint32_t)(rc_low) << SHIFT_BITS;
// rc.low = (uint32_t)(rc.low) << SHIFT_BITS;
// =>
// rc_low &= TOP_VALUE - 1;
// rc_low <<= SHIFT_BITS;
// rc.low &= TOP_VALUE - 1;
// rc.low <<= SHIFT_BITS;
#define rc_shift_low() \
do { \
if ((uint32_t)(rc_low) < (uint32_t)(0xFF000000) \
|| (uint32_t)(rc_low >> 32) != 0) { \
uint8_t rc_temp = rc_cache; \
if ((uint32_t)(rc.low) < (uint32_t)(0xFF000000) \
|| (uint32_t)(rc.low >> 32) != 0) { \
uint8_t rc_temp = rc.cache; \
do { \
rc_write_byte(rc_temp + (uint8_t)(rc_low >> 32)); \
rc_write_byte(rc_temp + (uint8_t)(rc.low >> 32)); \
rc_temp = 0xFF; \
} while(--rc_cache_size != 0); \
rc_cache = (uint8_t)((uint32_t)(rc_low) >> 24); \
} while(--rc.cache_size != 0); \
rc.cache = (uint8_t)((uint32_t)(rc.low) >> 24); \
} \
++rc_cache_size; \
rc_low = (uint32_t)(rc_low) << SHIFT_BITS; \
++rc.cache_size; \
rc.low = (uint32_t)(rc.low) << SHIFT_BITS; \
} while (0)
@@ -218,7 +211,7 @@ do { \
do { \
if (out_pos_local == out_size) { \
rc_buffer[rc_buffer_size++] = (uint8_t)(b); \
assert(rc_buffer_size < RC_BUFFER_SIZE); \
assert(rc_buffer_size < sizeof(rc_buffer)); \
} else { \
assert(rc_buffer_size == 0); \
out[out_pos_local++] = (uint8_t)(b); \
@@ -246,72 +239,37 @@ do { \
lzma_rc_prob_prices[(BIT_MODEL_TOTAL - (prob)) >> MOVE_REDUCING_BITS]
// Adds price to price_target. TODO Optimize/Cleanup?
#define bittree_get_price(price_target, probs, bit_levels, symbol) \
do { \
uint32_t bittree_symbol = (symbol) | (UINT32_C(1) << bit_levels); \
while (bittree_symbol != 1) { \
price_target += bit_get_price((probs)[bittree_symbol >> 1], \
bittree_symbol & 1); \
bittree_symbol >>= 1; \
} \
} while (0)
// Adds price to price_target.
#define bittree_reverse_get_price(price_target, probs, bit_levels, symbol) \
do { \
uint32_t model_index = 1; \
for (uint32_t bit_index = 0; bit_index < bit_levels; ++bit_index) { \
const uint32_t bit = ((symbol) >> bit_index) & 1; \
price_target += bit_get_price((probs)[model_index], bit); \
model_index = (model_index << 1) | bit; \
} \
} while (0)
//////////////////////
// Global variables //
//////////////////////
// Probability prices used by *_get_price() macros. This is initialized
// by lzma_rc_init() and is not modified later.
extern uint32_t lzma_rc_prob_prices[BIT_MODEL_TOTAL >> MOVE_REDUCING_BITS];
///////////////
// Functions //
///////////////
/// Initializes lzma_rc_prob_prices[]. This needs to be called only once.
extern void lzma_rc_init(void);
#ifdef RC_BUFFER_SIZE
/// Flushes data from rc->temp[] to out[] as much as possible. If everything
/// cannot be flushed, returns true; false otherwise.
static inline bool
rc_flush_buffer(lzma_range_encoder *rc,
uint8_t *out, size_t *out_pos, size_t out_size)
static inline uint32_t
bittree_get_price(const probability *probs,
uint32_t bit_levels, uint32_t symbol)
{
if (rc->buffer_size > 0) {
const size_t out_avail = out_size - *out_pos;
if (rc->buffer_size > out_avail) {
memcpy(out + *out_pos, rc->buffer, out_avail);
*out_pos += out_avail;
rc->buffer_size -= out_avail;
memmove(rc->buffer, rc->buffer + out_avail,
rc->buffer_size);
return true;
}
uint32_t price = 0;
symbol |= UINT32_C(1) << bit_levels;
memcpy(out + *out_pos, rc->buffer, rc->buffer_size);
*out_pos += rc->buffer_size;
rc->buffer_size = 0;
}
do {
price += bit_get_price(probs[symbol >> 1], symbol & 1);
symbol >>= 1;
} while (symbol != 1);
return false;
return price;
}
static inline uint32_t
bittree_reverse_get_price(const probability *probs,
uint32_t bit_levels, uint32_t symbol)
{
uint32_t price = 0;
uint32_t model_index = 1;
do {
const uint32_t bit = symbol & 1;
symbol >>= 1;
price += bit_get_price(probs[model_index], bit);
model_index = (model_index << 1) | bit;
} while (--bit_levels != 0);
return price;
}
#endif
#endif

View File

@@ -97,7 +97,7 @@ ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter_info *filters, bool is_encoder)
{
return lzma_simple_coder_init(next, allocator, filters,
&ia64_code, 0, 4, is_encoder);
&ia64_code, 0, 16, is_encoder);
}

View File

@@ -39,44 +39,23 @@ copy_or_code(lzma_coder *coder, lzma_allocator *allocator,
if (coder->next.code == NULL) {
const size_t in_avail = in_size - *in_pos;
if (coder->is_encoder) {
if (action == LZMA_FINISH) {
// If uncompressed size is known and the
// amount of available input doesn't match
// the uncompressed size, return an error.
if (coder->uncompressed_size
!= LZMA_VLI_VALUE_UNKNOWN
&& coder->uncompressed_size
!= in_avail)
return LZMA_DATA_ERROR;
} else if (coder->uncompressed_size
< (lzma_vli)(in_avail)) {
// There is too much input available.
return LZMA_DATA_ERROR;
}
} else {
if (!coder->is_encoder) {
// Limit in_size so that we don't copy too much.
if ((lzma_vli)(in_avail) > coder->uncompressed_size)
in_size = *in_pos + (size_t)(
coder->uncompressed_size);
}
// Store the old position so we can update uncompressed_size.
const size_t out_start = *out_pos;
// Copy the data
bufcpy(in, in_pos, in_size, out, out_pos, out_size);
// Update uncompressed_size.
if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
coder->uncompressed_size -= *out_pos - out_start;
// Check if end of stream was reached.
if (coder->is_encoder) {
if (action == LZMA_FINISH && *in_pos == in_size)
coder->end_was_reached = true;
} else {
} else if (coder->uncompressed_size
!= LZMA_VLI_VALUE_UNKNOWN) {
coder->uncompressed_size -= *out_pos - out_start;
if (coder->uncompressed_size == 0)
coder->end_was_reached = true;
}
@@ -122,6 +101,14 @@ simple_code(lzma_coder *coder, lzma_allocator *allocator,
size_t in_size, uint8_t *restrict out,
size_t *restrict out_pos, size_t out_size, lzma_action action)
{
// TODO: Add partial support for LZMA_SYNC_FLUSH. We can support it
// in cases when the filter is able to filter everything. With most
// simple filters it can be done at offset that is a multiple of 2,
// 4, or 16. With x86 filter, it needs good luck, and thus cannot
// be made to work predictably.
if (action == LZMA_SYNC_FLUSH)
return LZMA_HEADER_ERROR;
// Flush already filtered data from coder->buffer[] to out[].
if (coder->pos < coder->filtered) {
bufcpy(coder->buffer, &coder->pos, coder->filtered,

Some files were not shown because too many files have changed in this diff Show More