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