1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file index_encoder.c
4 /// \brief Encodes the Index field
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 ///////////////////////////////////////////////////////////////////////////////
13 #include "index_encoder.h"
29 /// Index being encoded
30 const lzma_index
*index
;
32 /// Iterator for the Index being encoded
35 /// Position in integers
38 /// CRC32 of the List of Records field
44 index_encode(lzma_coder
*coder
,
45 const lzma_allocator
*allocator
lzma_attribute((__unused__
)),
46 const uint8_t *restrict in
lzma_attribute((__unused__
)),
47 size_t *restrict in_pos
lzma_attribute((__unused__
)),
48 size_t in_size
lzma_attribute((__unused__
)),
49 uint8_t *restrict out
, size_t *restrict out_pos
,
51 lzma_action action
lzma_attribute((__unused__
)))
53 // Position where to start calculating CRC32. The idea is that we
54 // need to call lzma_crc32() only once per call to index_encode().
55 const size_t out_start
= *out_pos
;
57 // Return value to use if we return at the end of this function.
58 // We use "goto out" to jump out of the while-switch construct
59 // instead of returning directly, because that way we don't need
60 // to copypaste the lzma_crc32() call to many places.
61 lzma_ret ret
= LZMA_OK
;
63 while (*out_pos
< out_size
)
64 switch (coder
->sequence
) {
68 coder
->sequence
= SEQ_COUNT
;
72 const lzma_vli count
= lzma_index_block_count(coder
->index
);
73 ret
= lzma_vli_encode(count
, &coder
->pos
,
74 out
, out_pos
, out_size
);
75 if (ret
!= LZMA_STREAM_END
)
80 coder
->sequence
= SEQ_NEXT
;
85 if (lzma_index_iter_next(
86 &coder
->iter
, LZMA_INDEX_ITER_BLOCK
)) {
87 // Get the size of the Index Padding field.
88 coder
->pos
= lzma_index_padding_size(coder
->index
);
89 assert(coder
->pos
<= 3);
90 coder
->sequence
= SEQ_PADDING
;
94 coder
->sequence
= SEQ_UNPADDED
;
99 case SEQ_UNCOMPRESSED
: {
100 const lzma_vli size
= coder
->sequence
== SEQ_UNPADDED
101 ? coder
->iter
.block
.unpadded_size
102 : coder
->iter
.block
.uncompressed_size
;
104 ret
= lzma_vli_encode(size
, &coder
->pos
,
105 out
, out_pos
, out_size
);
106 if (ret
!= LZMA_STREAM_END
)
112 // Advance to SEQ_UNCOMPRESSED or SEQ_NEXT.
118 if (coder
->pos
> 0) {
120 out
[(*out_pos
)++] = 0x00;
124 // Finish the CRC32 calculation.
125 coder
->crc32
= lzma_crc32(out
+ out_start
,
126 *out_pos
- out_start
, coder
->crc32
);
128 coder
->sequence
= SEQ_CRC32
;
133 // We don't use the main loop, because we don't want
134 // coder->crc32 to be touched anymore.
136 if (*out_pos
== out_size
)
139 out
[*out_pos
] = (coder
->crc32
>> (coder
->pos
* 8))
143 } while (++coder
->pos
< 4);
145 return LZMA_STREAM_END
;
149 return LZMA_PROG_ERROR
;
154 coder
->crc32
= lzma_crc32(out
+ out_start
,
155 *out_pos
- out_start
, coder
->crc32
);
162 index_encoder_end(lzma_coder
*coder
, const lzma_allocator
*allocator
)
164 lzma_free(coder
, allocator
);
170 index_encoder_reset(lzma_coder
*coder
, const lzma_index
*i
)
172 lzma_index_iter_init(&coder
->iter
, i
);
174 coder
->sequence
= SEQ_INDICATOR
;
184 lzma_index_encoder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
187 lzma_next_coder_init(&lzma_index_encoder_init
, next
, allocator
);
190 return LZMA_PROG_ERROR
;
192 if (next
->coder
== NULL
) {
193 next
->coder
= lzma_alloc(sizeof(lzma_coder
), allocator
);
194 if (next
->coder
== NULL
)
195 return LZMA_MEM_ERROR
;
197 next
->code
= &index_encode
;
198 next
->end
= &index_encoder_end
;
201 index_encoder_reset(next
->coder
, i
);
207 extern LZMA_API(lzma_ret
)
208 lzma_index_encoder(lzma_stream
*strm
, const lzma_index
*i
)
210 lzma_next_strm_init(lzma_index_encoder_init
, strm
, i
);
212 strm
->internal
->supported_actions
[LZMA_RUN
] = true;
213 strm
->internal
->supported_actions
[LZMA_FINISH
] = true;
219 extern LZMA_API(lzma_ret
)
220 lzma_index_buffer_encode(const lzma_index
*i
,
221 uint8_t *out
, size_t *out_pos
, size_t out_size
)
223 // Validate the arguments.
224 if (i
== NULL
|| out
== NULL
|| out_pos
== NULL
|| *out_pos
> out_size
)
225 return LZMA_PROG_ERROR
;
227 // Don't try to encode if there's not enough output space.
228 if (out_size
- *out_pos
< lzma_index_size(i
))
229 return LZMA_BUF_ERROR
;
231 // The Index encoder needs just one small data structure so we can
232 // allocate it on stack.
234 index_encoder_reset(&coder
, i
);
236 // Do the actual encoding. This should never fail, but store
237 // the original *out_pos just in case.
238 const size_t out_start
= *out_pos
;
239 lzma_ret ret
= index_encode(&coder
, NULL
, NULL
, NULL
, 0,
240 out
, out_pos
, out_size
, LZMA_RUN
);
242 if (ret
== LZMA_STREAM_END
) {
245 // We should never get here, but just in case, restore the
246 // output position and set the error accordingly if something
247 // goes wrong and debugging isn't enabled.
249 *out_pos
= out_start
;
250 ret
= LZMA_PROG_ERROR
;