Index: xz/debug/known_sizes.c |
=================================================================== |
--- xz/debug/known_sizes.c (revision 0) |
+++ xz/debug/known_sizes.c (revision 0) |
@@ -0,0 +1,129 @@ |
+/////////////////////////////////////////////////////////////////////////////// |
+// |
+/// \file known_sizes.c |
+/// \brief Encodes .lzma Stream with sizes known in Block Header |
+/// |
+/// The input file is encoded in RAM, and the known Compressed Size |
+/// and/or Uncompressed Size values are stored in the Block Header. |
+/// As of writing there's no such Stream encoder in liblzma. |
+// |
+// Author: Lasse Collin |
+// |
+// This file has been put into the public domain. |
+// You can do whatever you want with this file. |
+// |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+#include "sysdefs.h" |
+#include "lzma.h" |
+#include <sys/types.h> |
+#include <sys/stat.h> |
+#include <sys/unistd.h> |
+#include <stdio.h> |
+ |
+ |
+// Support file sizes up to 1 MiB. We use this for output space too, so files |
+// close to 1 MiB had better compress at least a little or we have a buffer |
+// overflow. |
+#define BUFFER_SIZE (1U << 20) |
+ |
+ |
+int |
+main(void) |
+{ |
+ // Allocate the buffers. |
+ uint8_t *in = malloc(BUFFER_SIZE); |
+ uint8_t *out = malloc(BUFFER_SIZE); |
+ if (in == NULL || out == NULL) |
+ return 1; |
+ |
+ // Fill the input buffer. |
+ const size_t in_size = fread(in, 1, BUFFER_SIZE, stdin); |
+ |
+ // Filter setup |
+ lzma_options_lzma opt_lzma; |
+ if (lzma_lzma_preset(&opt_lzma, 1)) |
+ return 1; |
+ |
+ lzma_filter filters[] = { |
+ { |
+ .id = LZMA_FILTER_LZMA2, |
+ .options = &opt_lzma |
+ }, |
+ { |
+ .id = LZMA_VLI_UNKNOWN |
+ } |
+ }; |
+ |
+ lzma_block block = { |
+ .check = LZMA_CHECK_CRC32, |
+ .compressed_size = BUFFER_SIZE, // Worst case reserve |
+ .uncompressed_size = in_size, |
+ .filters = filters, |
+ }; |
+ |
+ lzma_stream strm = LZMA_STREAM_INIT; |
+ if (lzma_block_encoder(&strm, &block) != LZMA_OK) |
+ return 1; |
+ |
+ // Reserve space for Stream Header and Block Header. We need to |
+ // calculate the size of the Block Header first. |
+ if (lzma_block_header_size(&block) != LZMA_OK) |
+ return 1; |
+ |
+ size_t out_size = LZMA_STREAM_HEADER_SIZE + block.header_size; |
+ |
+ strm.next_in = in; |
+ strm.avail_in = in_size; |
+ strm.next_out = out + out_size; |
+ strm.avail_out = BUFFER_SIZE - out_size; |
+ |
+ if (lzma_code(&strm, LZMA_FINISH) != LZMA_STREAM_END) |
+ return 1; |
+ |
+ out_size += strm.total_out; |
+ |
+ if (lzma_block_header_encode(&block, out + LZMA_STREAM_HEADER_SIZE) |
+ != LZMA_OK) |
+ return 1; |
+ |
+ lzma_index *idx = lzma_index_init(NULL); |
+ if (idx == NULL) |
+ return 1; |
+ |
+ if (lzma_index_append(idx, NULL, block.header_size + strm.total_out, |
+ strm.total_in) != LZMA_OK) |
+ return 1; |
+ |
+ if (lzma_index_encoder(&strm, idx) != LZMA_OK) |
+ return 1; |
+ |
+ if (lzma_code(&strm, LZMA_RUN) != LZMA_STREAM_END) |
+ return 1; |
+ |
+ out_size += strm.total_out; |
+ |
+ lzma_end(&strm); |
+ |
+ lzma_index_end(idx, NULL); |
+ |
+ // Encode the Stream Header and Stream Footer. backwards_size is |
+ // needed only for the Stream Footer. |
+ lzma_stream_flags sf = { |
+ .backward_size = strm.total_out, |
+ .check = block.check, |
+ }; |
+ |
+ if (lzma_stream_header_encode(&sf, out) != LZMA_OK) |
+ return 1; |
+ |
+ if (lzma_stream_footer_encode(&sf, out + out_size) != LZMA_OK) |
+ return 1; |
+ |
+ out_size += LZMA_STREAM_HEADER_SIZE; |
+ |
+ // Write out the file. |
+ fwrite(out, 1, out_size, stdout); |
+ |
+ return 0; |
+} |
Property changes on: xz/debug/known_sizes.c |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |