extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator) { lzma_free(outq->bufs, allocator); outq->bufs = NULL; lzma_free(outq->bufs_mem, allocator); outq->bufs_mem = NULL; return; }
static void stream_encoder_end(lzma_coder *coder, const lzma_allocator *allocator) { lzma_next_end(&coder->block_encoder, allocator); lzma_next_end(&coder->index_encoder, allocator); lzma_index_end(coder->index, allocator); for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i) lzma_free(coder->filters[i].options, allocator); lzma_free(coder, allocator); return; }
static void delta_coder_end(lzma_coder *coder, lzma_allocator *allocator) { lzma_next_end(&coder->next, allocator); lzma_free(coder, allocator); return; }
extern lzma_ret lzma_simple_props_decode(void **options, const lzma_allocator *allocator, const uint8_t *props, size_t props_size) { if (props_size == 0) return LZMA_OK; if (props_size != 4) { return LZMA_OPTIONS_ERROR; } lzma_options_bcj *opt = lzma_alloc( sizeof(lzma_options_bcj), allocator); if (opt == NULL) return LZMA_MEM_ERROR; opt->start_offset = unaligned_read32le(props); // Don't leave an options structure allocated if start_offset is zero. if (opt->start_offset == 0) lzma_free(opt, allocator); else *options = opt; return LZMA_OK; }
lzma_index_end(lzma_index *i, lzma_allocator *allocator) { if (i != NULL) { free_index_list(i, allocator); lzma_free(i, allocator); } return; }
lzma_index_end(lzma_index *i, const lzma_allocator *allocator) { // NOTE: If you modify this function, check also the bottom // of lzma_index_cat(). if (i != NULL) { index_tree_end(&i->streams, allocator, &index_stream_end); lzma_free(i, allocator); } return; }
static void free_index_list(lzma_index *i, lzma_allocator *allocator) { lzma_index_group *g = i->head; while (g != NULL) { lzma_index_group *tmp = g->next; lzma_free(g, allocator); g = tmp; } return; }
static void free_properties(lzma_block *block, const lzma_allocator *allocator) { // Free allocated filter options. The last array member is not // touched after the initialization in the beginning of // lzma_block_header_decode(), so we don't need to touch that here. for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) { lzma_free(block->filters[i].options, allocator); block->filters[i].id = LZMA_VLI_UNKNOWN; block->filters[i].options = NULL; } return; }
lzma_index_init(const lzma_allocator *allocator) { lzma_index *i = index_init_plain(allocator); if (i == NULL) return NULL; index_stream *s = index_stream_init(0, 0, 1, 0, allocator); if (s == NULL) { lzma_free(i, allocator); return NULL; } index_tree_append(&i->streams, &s->node); return i; }
/// Helper for index_tree_end() static void index_tree_node_end(index_tree_node *node, const lzma_allocator *allocator, void (*free_func)(void *node, const lzma_allocator *allocator)) { // The tree won't ever be very huge, so recursion should be fine. // 20 levels in the tree is likely quite a lot already in practice. if (node->left != NULL) index_tree_node_end(node->left, allocator, free_func); if (node->right != NULL) index_tree_node_end(node->right, allocator, free_func); if (free_func != NULL) free_func(node, allocator); lzma_free(node, allocator); return; }
static lzma_ret stream_encoder_update(lzma_coder *coder, const lzma_allocator *allocator, const lzma_filter *filters, const lzma_filter *reversed_filters) { if (coder->sequence <= SEQ_BLOCK_INIT) { // There is no incomplete Block waiting to be finished, // thus we can change the whole filter chain. Start by // trying to initialize the Block encoder with the new // chain. This way we detect if the chain is valid. coder->block_encoder_is_initialized = false; coder->block_options.filters = (lzma_filter *)(filters); const lzma_ret ret = block_encoder_init(coder, allocator); coder->block_options.filters = coder->filters; if (ret != LZMA_OK) return ret; coder->block_encoder_is_initialized = true; } else if (coder->sequence <= SEQ_BLOCK_ENCODE) { // We are in the middle of a Block. Try to update only // the filter-specific options. return_if_error(coder->block_encoder.update( coder->block_encoder.coder, allocator, filters, reversed_filters)); } else { // Trying to update the filter chain when we are already // encoding Index or Stream Footer. return LZMA_PROG_ERROR; } // Free the copy of the old chain and make a copy of the new chain. for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i) lzma_free(coder->filters[i].options, allocator); return lzma_filters_copy(filters, coder->filters, allocator); }
lzma_filters_copy(const lzma_filter *src, lzma_filter *dest, lzma_allocator *allocator) { if (src == NULL || dest == NULL) return LZMA_PROG_ERROR; lzma_ret ret; size_t i; for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) { // There must be a maximum of four filters plus // the array terminator. if (i == LZMA_FILTERS_MAX) { ret = LZMA_OPTIONS_ERROR; goto error; } dest[i].id = src[i].id; if (src[i].options == NULL) { dest[i].options = NULL; } else { // See if the filter is supported only when the // options is not NULL. This might be convenient // sometimes if the app is actually copying only // a partial filter chain with a place holder ID. // // When options is not NULL, the Filter ID must be // supported by us, because otherwise we don't know // how big the options are. size_t j; for (j = 0; src[i].id != features[j].id; ++j) { if (features[j].id == LZMA_VLI_UNKNOWN) { ret = LZMA_OPTIONS_ERROR; goto error; } } // Allocate and copy the options. dest[i].options = lzma_alloc(features[j].options_size, allocator); if (dest[i].options == NULL) { ret = LZMA_MEM_ERROR; goto error; } memcpy(dest[i].options, src[i].options, features[j].options_size); } } // Terminate the filter array. assert(i <= LZMA_FILTERS_MAX + 1); dest[i].id = LZMA_VLI_UNKNOWN; dest[i].options = NULL; return LZMA_OK; error: // Free the options which we have already allocated. while (i-- > 0) { lzma_free(dest[i].options, allocator); dest[i].options = NULL; } return ret; }