VirtualBox

source: vbox/trunk/src/libs/liblzma-5.4.1/common/microlzma_encoder.c

Last change on this file was 98730, checked in by vboxsync, 21 months ago

libs/liblzma-5.4.1: Export to OSE, bugref:10254

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 3.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2//
3/// \file microlzma_encoder.c
4/// \brief Encode into MicroLZMA format
5//
6// Author: Lasse Collin
7//
8// This file has been put into the public domain.
9// You can do whatever you want with this file.
10//
11///////////////////////////////////////////////////////////////////////////////
12
13#include "lzma_encoder.h"
14
15
16typedef struct {
17 /// LZMA1 encoder
18 lzma_next_coder lzma;
19
20 /// LZMA properties byte (lc/lp/pb)
21 uint8_t props;
22} lzma_microlzma_coder;
23
24
25static lzma_ret
26microlzma_encode(void *coder_ptr, const lzma_allocator *allocator,
27 const uint8_t *restrict in, size_t *restrict in_pos,
28 size_t in_size, uint8_t *restrict out,
29 size_t *restrict out_pos, size_t out_size, lzma_action action)
30{
31 lzma_microlzma_coder *coder = coder_ptr;
32
33 // Remember *out_pos so that we can overwrite the first byte with
34 // the LZMA properties byte.
35 const size_t out_start = *out_pos;
36
37 // Remember *in_pos so that we can set it based on how many
38 // uncompressed bytes were actually encoded.
39 const size_t in_start = *in_pos;
40
41 // Set the output size limit based on the available output space.
42 // We know that the encoder supports set_out_limit() so
43 // LZMA_OPTIONS_ERROR isn't possible. LZMA_BUF_ERROR is possible
44 // but lzma_code() has an assertion to not allow it to be returned
45 // from here and I don't want to change that for now, so
46 // LZMA_BUF_ERROR becomes LZMA_PROG_ERROR.
47 uint64_t uncomp_size;
48 if (coder->lzma.set_out_limit(coder->lzma.coder,
49 &uncomp_size, out_size - *out_pos) != LZMA_OK)
50 return LZMA_PROG_ERROR;
51
52 // set_out_limit fails if this isn't true.
53 assert(out_size - *out_pos >= 6);
54
55 // Encode as much as possible.
56 const lzma_ret ret = coder->lzma.code(coder->lzma.coder, allocator,
57 in, in_pos, in_size, out, out_pos, out_size, action);
58
59 if (ret != LZMA_STREAM_END) {
60 if (ret == LZMA_OK) {
61 assert(0);
62 return LZMA_PROG_ERROR;
63 }
64
65 return ret;
66 }
67
68 // The first output byte is bitwise-negation of the properties byte.
69 // We know that there is space for this byte because set_out_limit
70 // and the actual encoding succeeded.
71 out[out_start] = (uint8_t)(~coder->props);
72
73 // The LZMA encoder likely read more input than it was able to encode.
74 // Set *in_pos based on uncomp_size.
75 assert(uncomp_size <= in_size - in_start);
76 *in_pos = in_start + (size_t)(uncomp_size);
77
78 return ret;
79}
80
81
82static void
83microlzma_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
84{
85 lzma_microlzma_coder *coder = coder_ptr;
86 lzma_next_end(&coder->lzma, allocator);
87 lzma_free(coder, allocator);
88 return;
89}
90
91
92static lzma_ret
93microlzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
94 const lzma_options_lzma *options)
95{
96 lzma_next_coder_init(&microlzma_encoder_init, next, allocator);
97
98 lzma_microlzma_coder *coder = next->coder;
99
100 if (coder == NULL) {
101 coder = lzma_alloc(sizeof(lzma_microlzma_coder), allocator);
102 if (coder == NULL)
103 return LZMA_MEM_ERROR;
104
105 next->coder = coder;
106 next->code = &microlzma_encode;
107 next->end = &microlzma_encoder_end;
108
109 coder->lzma = LZMA_NEXT_CODER_INIT;
110 }
111
112 // Encode the properties byte. Bitwise-negation of it will be the
113 // first output byte.
114 if (lzma_lzma_lclppb_encode(options, &coder->props))
115 return LZMA_OPTIONS_ERROR;
116
117 // Initialize the LZMA encoder.
118 const lzma_filter_info filters[2] = {
119 {
120 .id = LZMA_FILTER_LZMA1,
121 .init = &lzma_lzma_encoder_init,
122 .options = (void *)(options),
123 }, {
124 .init = NULL,
125 }
126 };
127
128 return lzma_next_filter_init(&coder->lzma, allocator, filters);
129}
130
131
132extern LZMA_API(lzma_ret)
133lzma_microlzma_encoder(lzma_stream *strm, const lzma_options_lzma *options)
134{
135 lzma_next_strm_init(microlzma_encoder_init, strm, options);
136
137 strm->internal->supported_actions[LZMA_FINISH] = true;
138
139 return LZMA_OK;
140
141}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette