Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmliblzma/liblzma/common/alone_encoder.c
3153 views
1
// SPDX-License-Identifier: 0BSD
2
3
///////////////////////////////////////////////////////////////////////////////
4
//
5
/// \file alone_encoder.c
6
/// \brief Encoder for LZMA_Alone files
7
//
8
// Author: Lasse Collin
9
//
10
///////////////////////////////////////////////////////////////////////////////
11
12
#include "common.h"
13
#include "lzma_encoder.h"
14
15
16
#define ALONE_HEADER_SIZE (1 + 4 + 8)
17
18
19
typedef struct {
20
lzma_next_coder next;
21
22
enum {
23
SEQ_HEADER,
24
SEQ_CODE,
25
} sequence;
26
27
size_t header_pos;
28
uint8_t header[ALONE_HEADER_SIZE];
29
} lzma_alone_coder;
30
31
32
static lzma_ret
33
alone_encode(void *coder_ptr, const lzma_allocator *allocator,
34
const uint8_t *restrict in, size_t *restrict in_pos,
35
size_t in_size, uint8_t *restrict out,
36
size_t *restrict out_pos, size_t out_size,
37
lzma_action action)
38
{
39
lzma_alone_coder *coder = coder_ptr;
40
41
while (*out_pos < out_size)
42
switch (coder->sequence) {
43
case SEQ_HEADER:
44
lzma_bufcpy(coder->header, &coder->header_pos,
45
ALONE_HEADER_SIZE,
46
out, out_pos, out_size);
47
if (coder->header_pos < ALONE_HEADER_SIZE)
48
return LZMA_OK;
49
50
coder->sequence = SEQ_CODE;
51
break;
52
53
case SEQ_CODE:
54
return coder->next.code(coder->next.coder,
55
allocator, in, in_pos, in_size,
56
out, out_pos, out_size, action);
57
58
default:
59
assert(0);
60
return LZMA_PROG_ERROR;
61
}
62
63
return LZMA_OK;
64
}
65
66
67
static void
68
alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
69
{
70
lzma_alone_coder *coder = coder_ptr;
71
lzma_next_end(&coder->next, allocator);
72
lzma_free(coder, allocator);
73
return;
74
}
75
76
77
static lzma_ret
78
alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
79
const lzma_options_lzma *options)
80
{
81
lzma_next_coder_init(&alone_encoder_init, next, allocator);
82
83
lzma_alone_coder *coder = next->coder;
84
85
if (coder == NULL) {
86
coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
87
if (coder == NULL)
88
return LZMA_MEM_ERROR;
89
90
next->coder = coder;
91
next->code = &alone_encode;
92
next->end = &alone_encoder_end;
93
coder->next = LZMA_NEXT_CODER_INIT;
94
}
95
96
// Basic initializations
97
coder->sequence = SEQ_HEADER;
98
coder->header_pos = 0;
99
100
// Encode the header:
101
// - Properties (1 byte)
102
if (lzma_lzma_lclppb_encode(options, coder->header))
103
return LZMA_OPTIONS_ERROR;
104
105
// - Dictionary size (4 bytes)
106
if (options->dict_size < LZMA_DICT_SIZE_MIN)
107
return LZMA_OPTIONS_ERROR;
108
109
// Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
110
// one is the next unless it is UINT32_MAX. While the header would
111
// allow any 32-bit integer, we do this to keep the decoder of liblzma
112
// accepting the resulting files.
113
uint32_t d = options->dict_size - 1;
114
d |= d >> 2;
115
d |= d >> 3;
116
d |= d >> 4;
117
d |= d >> 8;
118
d |= d >> 16;
119
if (d != UINT32_MAX)
120
++d;
121
122
write32le(coder->header + 1, d);
123
124
// - Uncompressed size (always unknown and using EOPM)
125
memset(coder->header + 1 + 4, 0xFF, 8);
126
127
// Initialize the LZMA encoder.
128
const lzma_filter_info filters[2] = {
129
{
130
.id = LZMA_FILTER_LZMA1,
131
.init = &lzma_lzma_encoder_init,
132
.options = (void *)(options),
133
}, {
134
.init = NULL,
135
}
136
};
137
138
return lzma_next_filter_init(&coder->next, allocator, filters);
139
}
140
141
142
extern LZMA_API(lzma_ret)
143
lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
144
{
145
lzma_next_strm_init(alone_encoder_init, strm, options);
146
147
strm->internal->supported_actions[LZMA_RUN] = true;
148
strm->internal->supported_actions[LZMA_FINISH] = true;
149
150
return LZMA_OK;
151
}
152
153