/src/CMake/Utilities/cmliblzma/liblzma/common/alone_encoder.c
Line | Count | Source |
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 | 0 | #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 | 0 | { |
39 | 0 | lzma_alone_coder *coder = coder_ptr; |
40 | |
|
41 | 0 | while (*out_pos < out_size) |
42 | 0 | switch (coder->sequence) { |
43 | 0 | case SEQ_HEADER: |
44 | 0 | lzma_bufcpy(coder->header, &coder->header_pos, |
45 | 0 | ALONE_HEADER_SIZE, |
46 | 0 | out, out_pos, out_size); |
47 | 0 | if (coder->header_pos < ALONE_HEADER_SIZE) |
48 | 0 | return LZMA_OK; |
49 | | |
50 | 0 | coder->sequence = SEQ_CODE; |
51 | 0 | break; |
52 | | |
53 | 0 | case SEQ_CODE: |
54 | 0 | return coder->next.code(coder->next.coder, |
55 | 0 | allocator, in, in_pos, in_size, |
56 | 0 | out, out_pos, out_size, action); |
57 | | |
58 | 0 | default: |
59 | 0 | assert(0); |
60 | 0 | return LZMA_PROG_ERROR; |
61 | 0 | } |
62 | | |
63 | 0 | return LZMA_OK; |
64 | 0 | } |
65 | | |
66 | | |
67 | | static void |
68 | | alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator) |
69 | 0 | { |
70 | 0 | lzma_alone_coder *coder = coder_ptr; |
71 | 0 | lzma_next_end(&coder->next, allocator); |
72 | 0 | lzma_free(coder, allocator); |
73 | 0 | return; |
74 | 0 | } |
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 | 0 | { |
81 | 0 | lzma_next_coder_init(&alone_encoder_init, next, allocator); |
82 | |
|
83 | 0 | lzma_alone_coder *coder = next->coder; |
84 | |
|
85 | 0 | if (coder == NULL) { |
86 | 0 | coder = lzma_alloc(sizeof(lzma_alone_coder), allocator); |
87 | 0 | if (coder == NULL) |
88 | 0 | return LZMA_MEM_ERROR; |
89 | | |
90 | 0 | next->coder = coder; |
91 | 0 | next->code = &alone_encode; |
92 | 0 | next->end = &alone_encoder_end; |
93 | 0 | coder->next = LZMA_NEXT_CODER_INIT; |
94 | 0 | } |
95 | | |
96 | | // Basic initializations |
97 | 0 | coder->sequence = SEQ_HEADER; |
98 | 0 | coder->header_pos = 0; |
99 | | |
100 | | // Encode the header: |
101 | | // - Properties (1 byte) |
102 | 0 | if (lzma_lzma_lclppb_encode(options, coder->header)) |
103 | 0 | return LZMA_OPTIONS_ERROR; |
104 | | |
105 | | // - Dictionary size (4 bytes) |
106 | 0 | if (options->dict_size < LZMA_DICT_SIZE_MIN) |
107 | 0 | 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 | 0 | uint32_t d = options->dict_size - 1; |
114 | 0 | d |= d >> 2; |
115 | 0 | d |= d >> 3; |
116 | 0 | d |= d >> 4; |
117 | 0 | d |= d >> 8; |
118 | 0 | d |= d >> 16; |
119 | 0 | if (d != UINT32_MAX) |
120 | 0 | ++d; |
121 | |
|
122 | 0 | write32le(coder->header + 1, d); |
123 | | |
124 | | // - Uncompressed size (always unknown and using EOPM) |
125 | 0 | memset(coder->header + 1 + 4, 0xFF, 8); |
126 | | |
127 | | // Initialize the LZMA encoder. |
128 | 0 | const lzma_filter_info filters[2] = { |
129 | 0 | { |
130 | 0 | .id = LZMA_FILTER_LZMA1, |
131 | 0 | .init = &lzma_lzma_encoder_init, |
132 | 0 | .options = (void *)(options), |
133 | 0 | }, { |
134 | 0 | .init = NULL, |
135 | 0 | } |
136 | 0 | }; |
137 | |
|
138 | 0 | return lzma_next_filter_init(&coder->next, allocator, filters); |
139 | 0 | } |
140 | | |
141 | | |
142 | | extern LZMA_API(lzma_ret) |
143 | | lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options) |
144 | 0 | { |
145 | 0 | lzma_next_strm_init(alone_encoder_init, strm, options); |
146 | | |
147 | 0 | strm->internal->supported_actions[LZMA_RUN] = true; |
148 | 0 | strm->internal->supported_actions[LZMA_FINISH] = true; |
149 | |
|
150 | 0 | return LZMA_OK; |
151 | 0 | } |