1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file alone_encoder.c
4 /// \brief Encoder for LZMA_Alone files
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
14 #include "lzma_encoder.h"
17 #define ALONE_HEADER_SIZE (1 + 4 + 8)
29 uint8_t header
[ALONE_HEADER_SIZE
];
34 alone_encode(void *coder_ptr
, const lzma_allocator
*allocator
,
35 const uint8_t *restrict in
, size_t *restrict in_pos
,
36 size_t in_size
, uint8_t *restrict out
,
37 size_t *restrict out_pos
, size_t out_size
,
40 lzma_alone_coder
*coder
= coder_ptr
;
42 while (*out_pos
< out_size
)
43 switch (coder
->sequence
) {
45 lzma_bufcpy(coder
->header
, &coder
->header_pos
,
47 out
, out_pos
, out_size
);
48 if (coder
->header_pos
< ALONE_HEADER_SIZE
)
51 coder
->sequence
= SEQ_CODE
;
55 return coder
->next
.code(coder
->next
.coder
,
56 allocator
, in
, in_pos
, in_size
,
57 out
, out_pos
, out_size
, action
);
61 return LZMA_PROG_ERROR
;
69 alone_encoder_end(void *coder_ptr
, const lzma_allocator
*allocator
)
71 lzma_alone_coder
*coder
= coder_ptr
;
72 lzma_next_end(&coder
->next
, allocator
);
73 lzma_free(coder
, allocator
);
79 alone_encoder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
80 const lzma_options_lzma
*options
)
82 lzma_next_coder_init(&alone_encoder_init
, next
, allocator
);
84 lzma_alone_coder
*coder
= next
->coder
;
87 coder
= lzma_alloc(sizeof(lzma_alone_coder
), allocator
);
89 return LZMA_MEM_ERROR
;
92 next
->code
= &alone_encode
;
93 next
->end
= &alone_encoder_end
;
94 coder
->next
= LZMA_NEXT_CODER_INIT
;
97 // Basic initializations
98 coder
->sequence
= SEQ_HEADER
;
99 coder
->header_pos
= 0;
101 // Encode the header:
102 // - Properties (1 byte)
103 if (lzma_lzma_lclppb_encode(options
, coder
->header
))
104 return LZMA_OPTIONS_ERROR
;
106 // - Dictionary size (4 bytes)
107 if (options
->dict_size
< LZMA_DICT_SIZE_MIN
)
108 return LZMA_OPTIONS_ERROR
;
110 // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
111 // one is the next unless it is UINT32_MAX. While the header would
112 // allow any 32-bit integer, we do this to keep the decoder of liblzma
113 // accepting the resulting files.
114 uint32_t d
= options
->dict_size
- 1;
123 write32le(coder
->header
+ 1, d
);
125 // - Uncompressed size (always unknown and using EOPM)
126 memset(coder
->header
+ 1 + 4, 0xFF, 8);
128 // Initialize the LZMA encoder.
129 const lzma_filter_info filters
[2] = {
131 .id
= LZMA_FILTER_LZMA1
,
132 .init
= &lzma_lzma_encoder_init
,
133 .options
= (void *)(options
),
139 return lzma_next_filter_init(&coder
->next
, allocator
, filters
);
143 extern LZMA_API(lzma_ret
)
144 lzma_alone_encoder(lzma_stream
*strm
, const lzma_options_lzma
*options
)
146 lzma_next_strm_init(alone_encoder_init
, strm
, options
);
148 strm
->internal
->supported_actions
[LZMA_RUN
] = true;
149 strm
->internal
->supported_actions
[LZMA_FINISH
] = true;