1 ///////////////////////////////////////////////////////////////////////////////
4 /// \brief Common functions needed in many places in liblzma
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 ///////////////////////////////////////////////////////////////////////////////
20 extern LZMA_API(uint32_t)
21 lzma_version_number(void)
27 extern LZMA_API(const char *)
28 lzma_version_string(void)
30 return LZMA_VERSION_STRING
;
34 ///////////////////////
35 // Memory allocation //
36 ///////////////////////
38 extern void * lzma_attribute((__malloc__
)) lzma_attr_alloc_size(1)
39 lzma_alloc(size_t size
, const lzma_allocator
*allocator
)
41 // Some malloc() variants return NULL if called with size == 0.
47 if (allocator
!= NULL
&& allocator
->alloc
!= NULL
)
48 ptr
= allocator
->alloc(allocator
->opaque
, 1, size
);
56 extern void * lzma_attribute((__malloc__
)) lzma_attr_alloc_size(1)
57 lzma_alloc_zero(size_t size
, const lzma_allocator
*allocator
)
59 // Some calloc() variants return NULL if called with size == 0.
65 if (allocator
!= NULL
&& allocator
->alloc
!= NULL
) {
66 ptr
= allocator
->alloc(allocator
->opaque
, 1, size
);
70 ptr
= calloc(1, size
);
78 lzma_free(void *ptr
, const lzma_allocator
*allocator
)
80 if (allocator
!= NULL
&& allocator
->free
!= NULL
)
81 allocator
->free(allocator
->opaque
, ptr
);
94 lzma_bufcpy(const uint8_t *restrict in
, size_t *restrict in_pos
,
95 size_t in_size
, uint8_t *restrict out
,
96 size_t *restrict out_pos
, size_t out_size
)
98 const size_t in_avail
= in_size
- *in_pos
;
99 const size_t out_avail
= out_size
- *out_pos
;
100 const size_t copy_size
= my_min(in_avail
, out_avail
);
102 memcpy(out
+ *out_pos
, in
+ *in_pos
, copy_size
);
104 *in_pos
+= copy_size
;
105 *out_pos
+= copy_size
;
112 lzma_next_filter_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
113 const lzma_filter_info
*filters
)
115 lzma_next_coder_init(filters
[0].init
, next
, allocator
);
116 next
->id
= filters
[0].id
;
117 return filters
[0].init
== NULL
118 ? LZMA_OK
: filters
[0].init(next
, allocator
, filters
);
123 lzma_next_filter_update(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
124 const lzma_filter
*reversed_filters
)
126 // Check that the application isn't trying to change the Filter ID.
127 // End of filters is indicated with LZMA_VLI_UNKNOWN in both
128 // reversed_filters[0].id and next->id.
129 if (reversed_filters
[0].id
!= next
->id
)
130 return LZMA_PROG_ERROR
;
132 if (reversed_filters
[0].id
== LZMA_VLI_UNKNOWN
)
135 assert(next
->update
!= NULL
);
136 return next
->update(next
->coder
, allocator
, NULL
, reversed_filters
);
141 lzma_next_end(lzma_next_coder
*next
, const lzma_allocator
*allocator
)
143 if (next
->init
!= (uintptr_t)(NULL
)) {
144 // To avoid tiny end functions that simply call
145 // lzma_free(coder, allocator), we allow leaving next->end
146 // NULL and call lzma_free() here.
147 if (next
->end
!= NULL
)
148 next
->end(next
->coder
, allocator
);
150 lzma_free(next
->coder
, allocator
);
152 // Reset the variables so the we don't accidentally think
153 // that it is an already initialized coder.
154 *next
= LZMA_NEXT_CODER_INIT
;
161 //////////////////////////////////////
162 // External to internal API wrapper //
163 //////////////////////////////////////
166 lzma_strm_init(lzma_stream
*strm
)
169 return LZMA_PROG_ERROR
;
171 if (strm
->internal
== NULL
) {
172 strm
->internal
= lzma_alloc(sizeof(lzma_internal
),
174 if (strm
->internal
== NULL
)
175 return LZMA_MEM_ERROR
;
177 strm
->internal
->next
= LZMA_NEXT_CODER_INIT
;
180 memzero(strm
->internal
->supported_actions
,
181 sizeof(strm
->internal
->supported_actions
));
182 strm
->internal
->sequence
= ISEQ_RUN
;
183 strm
->internal
->allow_buf_error
= false;
192 extern LZMA_API(lzma_ret
)
193 lzma_code(lzma_stream
*strm
, lzma_action action
)
196 if ((strm
->next_in
== NULL
&& strm
->avail_in
!= 0)
197 || (strm
->next_out
== NULL
&& strm
->avail_out
!= 0)
198 || strm
->internal
== NULL
199 || strm
->internal
->next
.code
== NULL
200 || (unsigned int)(action
) > LZMA_ACTION_MAX
201 || !strm
->internal
->supported_actions
[action
])
202 return LZMA_PROG_ERROR
;
204 // Check if unsupported members have been set to non-zero or non-NULL,
205 // which would indicate that some new feature is wanted.
206 if (strm
->reserved_ptr1
!= NULL
207 || strm
->reserved_ptr2
!= NULL
208 || strm
->reserved_ptr3
!= NULL
209 || strm
->reserved_ptr4
!= NULL
210 || strm
->reserved_int1
!= 0
211 || strm
->reserved_int2
!= 0
212 || strm
->reserved_int3
!= 0
213 || strm
->reserved_int4
!= 0
214 || strm
->reserved_enum1
!= LZMA_RESERVED_ENUM
215 || strm
->reserved_enum2
!= LZMA_RESERVED_ENUM
)
216 return LZMA_OPTIONS_ERROR
;
218 switch (strm
->internal
->sequence
) {
224 case LZMA_SYNC_FLUSH
:
225 strm
->internal
->sequence
= ISEQ_SYNC_FLUSH
;
228 case LZMA_FULL_FLUSH
:
229 strm
->internal
->sequence
= ISEQ_FULL_FLUSH
;
233 strm
->internal
->sequence
= ISEQ_FINISH
;
236 case LZMA_FULL_BARRIER
:
237 strm
->internal
->sequence
= ISEQ_FULL_BARRIER
;
243 case ISEQ_SYNC_FLUSH
:
244 // The same action must be used until we return
245 // LZMA_STREAM_END, and the amount of input must not change.
246 if (action
!= LZMA_SYNC_FLUSH
247 || strm
->internal
->avail_in
!= strm
->avail_in
)
248 return LZMA_PROG_ERROR
;
252 case ISEQ_FULL_FLUSH
:
253 if (action
!= LZMA_FULL_FLUSH
254 || strm
->internal
->avail_in
!= strm
->avail_in
)
255 return LZMA_PROG_ERROR
;
260 if (action
!= LZMA_FINISH
261 || strm
->internal
->avail_in
!= strm
->avail_in
)
262 return LZMA_PROG_ERROR
;
266 case ISEQ_FULL_BARRIER
:
267 if (action
!= LZMA_FULL_BARRIER
268 || strm
->internal
->avail_in
!= strm
->avail_in
)
269 return LZMA_PROG_ERROR
;
274 return LZMA_STREAM_END
;
278 return LZMA_PROG_ERROR
;
283 lzma_ret ret
= strm
->internal
->next
.code(
284 strm
->internal
->next
.coder
, strm
->allocator
,
285 strm
->next_in
, &in_pos
, strm
->avail_in
,
286 strm
->next_out
, &out_pos
, strm
->avail_out
, action
);
288 strm
->next_in
+= in_pos
;
289 strm
->avail_in
-= in_pos
;
290 strm
->total_in
+= in_pos
;
292 strm
->next_out
+= out_pos
;
293 strm
->avail_out
-= out_pos
;
294 strm
->total_out
+= out_pos
;
296 strm
->internal
->avail_in
= strm
->avail_in
;
298 // Cast is needed to silence a warning about LZMA_TIMED_OUT, which
299 // isn't part of lzma_ret enumeration.
300 switch ((unsigned int)(ret
)) {
302 // Don't return LZMA_BUF_ERROR when it happens the first time.
303 // This is to avoid returning LZMA_BUF_ERROR when avail_out
304 // was zero but still there was no more data left to written
306 if (out_pos
== 0 && in_pos
== 0) {
307 if (strm
->internal
->allow_buf_error
)
308 ret
= LZMA_BUF_ERROR
;
310 strm
->internal
->allow_buf_error
= true;
312 strm
->internal
->allow_buf_error
= false;
317 strm
->internal
->allow_buf_error
= false;
321 case LZMA_STREAM_END
:
322 if (strm
->internal
->sequence
== ISEQ_SYNC_FLUSH
323 || strm
->internal
->sequence
== ISEQ_FULL_FLUSH
324 || strm
->internal
->sequence
325 == ISEQ_FULL_BARRIER
)
326 strm
->internal
->sequence
= ISEQ_RUN
;
328 strm
->internal
->sequence
= ISEQ_END
;
333 case LZMA_UNSUPPORTED_CHECK
:
335 case LZMA_MEMLIMIT_ERROR
:
336 // Something else than LZMA_OK, but not a fatal error,
337 // that is, coding may be continued (except if ISEQ_END).
338 strm
->internal
->allow_buf_error
= false;
342 // All the other errors are fatal; coding cannot be continued.
343 assert(ret
!= LZMA_BUF_ERROR
);
344 strm
->internal
->sequence
= ISEQ_ERROR
;
352 extern LZMA_API(void)
353 lzma_end(lzma_stream
*strm
)
355 if (strm
!= NULL
&& strm
->internal
!= NULL
) {
356 lzma_next_end(&strm
->internal
->next
, strm
->allocator
);
357 lzma_free(strm
->internal
, strm
->allocator
);
358 strm
->internal
= NULL
;
365 extern LZMA_API(void)
366 lzma_get_progress(lzma_stream
*strm
,
367 uint64_t *progress_in
, uint64_t *progress_out
)
369 if (strm
->internal
->next
.get_progress
!= NULL
) {
370 strm
->internal
->next
.get_progress(strm
->internal
->next
.coder
,
371 progress_in
, progress_out
);
373 *progress_in
= strm
->total_in
;
374 *progress_out
= strm
->total_out
;
381 extern LZMA_API(lzma_check
)
382 lzma_get_check(const lzma_stream
*strm
)
384 // Return LZMA_CHECK_NONE if we cannot know the check type.
385 // It's a bug in the application if this happens.
386 if (strm
->internal
->next
.get_check
== NULL
)
387 return LZMA_CHECK_NONE
;
389 return strm
->internal
->next
.get_check(strm
->internal
->next
.coder
);
393 extern LZMA_API(uint64_t)
394 lzma_memusage(const lzma_stream
*strm
)
397 uint64_t old_memlimit
;
399 if (strm
== NULL
|| strm
->internal
== NULL
400 || strm
->internal
->next
.memconfig
== NULL
401 || strm
->internal
->next
.memconfig(
402 strm
->internal
->next
.coder
,
403 &memusage
, &old_memlimit
, 0) != LZMA_OK
)
410 extern LZMA_API(uint64_t)
411 lzma_memlimit_get(const lzma_stream
*strm
)
413 uint64_t old_memlimit
;
416 if (strm
== NULL
|| strm
->internal
== NULL
417 || strm
->internal
->next
.memconfig
== NULL
418 || strm
->internal
->next
.memconfig(
419 strm
->internal
->next
.coder
,
420 &memusage
, &old_memlimit
, 0) != LZMA_OK
)
427 extern LZMA_API(lzma_ret
)
428 lzma_memlimit_set(lzma_stream
*strm
, uint64_t new_memlimit
)
430 // Dummy variables to simplify memconfig functions
431 uint64_t old_memlimit
;
434 if (strm
== NULL
|| strm
->internal
== NULL
435 || strm
->internal
->next
.memconfig
== NULL
)
436 return LZMA_PROG_ERROR
;
438 if (new_memlimit
!= 0 && new_memlimit
< LZMA_MEMUSAGE_BASE
)
439 return LZMA_MEMLIMIT_ERROR
;
441 return strm
->internal
->next
.memconfig(strm
->internal
->next
.coder
,
442 &memusage
, &old_memlimit
, new_memlimit
);