1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
5 /// \file alone_encoder.c
6 /// \brief Encoder for LZMA_Alone files
8 // Author: Lasse Collin
10 ///////////////////////////////////////////////////////////////////////////////
13 #include "lzma_encoder.h"
16 #define ALONE_HEADER_SIZE (1 + 4 + 8)
28 uint8_t header
[ALONE_HEADER_SIZE
];
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
,
39 lzma_alone_coder
*coder
= coder_ptr
;
41 while (*out_pos
< out_size
)
42 switch (coder
->sequence
) {
44 lzma_bufcpy(coder
->header
, &coder
->header_pos
,
46 out
, out_pos
, out_size
);
47 if (coder
->header_pos
< ALONE_HEADER_SIZE
)
50 coder
->sequence
= SEQ_CODE
;
54 return coder
->next
.code(coder
->next
.coder
,
55 allocator
, in
, in_pos
, in_size
,
56 out
, out_pos
, out_size
, action
);
60 return LZMA_PROG_ERROR
;
68 alone_encoder_end(void *coder_ptr
, const lzma_allocator
*allocator
)
70 lzma_alone_coder
*coder
= coder_ptr
;
71 lzma_next_end(&coder
->next
, allocator
);
72 lzma_free(coder
, allocator
);
78 alone_encoder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
79 const lzma_options_lzma
*options
)
81 lzma_next_coder_init(&alone_encoder_init
, next
, allocator
);
83 lzma_alone_coder
*coder
= next
->coder
;
86 coder
= lzma_alloc(sizeof(lzma_alone_coder
), allocator
);
88 return LZMA_MEM_ERROR
;
91 next
->code
= &alone_encode
;
92 next
->end
= &alone_encoder_end
;
93 coder
->next
= LZMA_NEXT_CODER_INIT
;
96 // Basic initializations
97 coder
->sequence
= SEQ_HEADER
;
98 coder
->header_pos
= 0;
100 // Encode the header:
101 // - Properties (1 byte)
102 if (lzma_lzma_lclppb_encode(options
, coder
->header
))
103 return LZMA_OPTIONS_ERROR
;
105 // - Dictionary size (4 bytes)
106 if (options
->dict_size
< LZMA_DICT_SIZE_MIN
)
107 return LZMA_OPTIONS_ERROR
;
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;
122 write32le(coder
->header
+ 1, d
);
124 // - Uncompressed size (always unknown and using EOPM)
125 memset(coder
->header
+ 1 + 4, 0xFF, 8);
127 // Initialize the LZMA encoder.
128 const lzma_filter_info filters
[2] = {
130 .id
= LZMA_FILTER_LZMA1
,
131 .init
= &lzma_lzma_encoder_init
,
132 .options
= (void *)(options
),
138 return lzma_next_filter_init(&coder
->next
, allocator
, filters
);
142 extern LZMA_API(lzma_ret
)
143 lzma_alone_encoder(lzma_stream
*strm
, const lzma_options_lzma
*options
)
145 lzma_next_strm_init(alone_encoder_init
, strm
, options
);
147 strm
->internal
->supported_actions
[LZMA_RUN
] = true;
148 strm
->internal
->supported_actions
[LZMA_FINISH
] = true;