diff options
author | Jun Wang <junbill.wang@samsung.com> | 2016-05-18 10:24:32 +0800 |
---|---|---|
committer | Jun Wang <junbill.wang@samsung.com> | 2016-05-18 10:24:32 +0800 |
commit | a96d62621beefe4aa20b696744be6325bc536fb6 (patch) | |
tree | 453fe36c1a5c9f9a2ccd23ab14d7c19e9ffdb471 /xdelta3-lzma.h | |
download | xdelta3-a96d62621beefe4aa20b696744be6325bc536fb6.tar.gz xdelta3-a96d62621beefe4aa20b696744be6325bc536fb6.tar.bz2 xdelta3-a96d62621beefe4aa20b696744be6325bc536fb6.zip |
Import from upstream 3.1.0
Diffstat (limited to 'xdelta3-lzma.h')
-rw-r--r-- | xdelta3-lzma.h | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/xdelta3-lzma.h b/xdelta3-lzma.h new file mode 100644 index 0000000..6c16a7e --- /dev/null +++ b/xdelta3-lzma.h @@ -0,0 +1,197 @@ +/* xdelta 3 - delta compression tools and library + * Copyright (C) 2012, 2013, 2014, 2015. Joshua P. MacDonald + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Note: The use of the _easy_ decoder means we're not calling the + * xd3_stream malloc hooks. TODO(jmacd) Fix if anyone cares. */ + +#ifndef _XDELTA3_LZMA_H_ +#define _XDELTA3_LZMA_H_ + +#include <lzma.h> + +typedef struct _xd3_lzma_stream xd3_lzma_stream; + +struct _xd3_lzma_stream { + lzma_stream lzma; + lzma_options_lzma options; + lzma_filter filters[2]; +}; + +static xd3_sec_stream* +xd3_lzma_alloc (xd3_stream *stream) +{ + return (xd3_sec_stream*) xd3_alloc (stream, sizeof (xd3_lzma_stream), 1); +} + +static void +xd3_lzma_destroy (xd3_stream *stream, xd3_sec_stream *sec_stream) +{ + xd3_lzma_stream *ls = (xd3_lzma_stream*) sec_stream; + lzma_end (&ls->lzma); + xd3_free (stream, ls); +} + +static int +xd3_lzma_init (xd3_stream *stream, xd3_lzma_stream *sec, int is_encode) +{ + int ret; + + memset (&sec->lzma, 0, sizeof(sec->lzma)); + + if (is_encode) + { + uint32_t preset = + (stream->flags & XD3_COMPLEVEL_MASK) >> XD3_COMPLEVEL_SHIFT; + + if (lzma_lzma_preset(&sec->options, preset)) + { + stream->msg = "invalid lzma preset"; + return XD3_INVALID; + } + + sec->filters[0].id = LZMA_FILTER_LZMA2; + sec->filters[0].options = &sec->options; + sec->filters[1].id = LZMA_VLI_UNKNOWN; + + ret = lzma_stream_encoder (&sec->lzma, &sec->filters[0], LZMA_CHECK_NONE); + } + else + { + ret = lzma_stream_decoder (&sec->lzma, UINT64_MAX, LZMA_TELL_NO_CHECK); + } + + if (ret != LZMA_OK) + { + stream->msg = "lzma stream init failed"; + return XD3_INTERNAL; + } + + return 0; +} + +static int xd3_decode_lzma (xd3_stream *stream, xd3_lzma_stream *sec, + const uint8_t **input_pos, + const uint8_t *const input_end, + uint8_t **output_pos, + const uint8_t *const output_end) +{ + uint8_t *output = *output_pos; + const uint8_t *input = *input_pos; + size_t avail_in = input_end - input; + size_t avail_out = output_end - output; + + sec->lzma.avail_in = avail_in; + sec->lzma.next_in = input; + sec->lzma.avail_out = avail_out; + sec->lzma.next_out = output; + + while (1) + { + int lret = lzma_code (&sec->lzma, LZMA_RUN); + + switch (lret) + { + case LZMA_NO_CHECK: + case LZMA_OK: + if (sec->lzma.avail_out == 0) + { + (*output_pos) = sec->lzma.next_out; + (*input_pos) = sec->lzma.next_in; + return 0; + } + break; + + default: + stream->msg = "lzma decoding error"; + return XD3_INTERNAL; + } + } +} + +#if XD3_ENCODER + +static int xd3_encode_lzma (xd3_stream *stream, + xd3_lzma_stream *sec, + xd3_output *input, + xd3_output *output, + xd3_sec_cfg *cfg) + +{ + lzma_action action = LZMA_RUN; + + cfg->inefficient = 1; /* Can't skip windows */ + sec->lzma.next_in = NULL; + sec->lzma.avail_in = 0; + sec->lzma.next_out = (output->base + output->next); + sec->lzma.avail_out = (output->avail - output->next); + + while (1) + { + int lret; + size_t nwrite; + if (sec->lzma.avail_in == 0 && input != NULL) + { + sec->lzma.avail_in = input->next; + sec->lzma.next_in = input->base; + + if ((input = input->next_page) == NULL) + { + action = LZMA_SYNC_FLUSH; + } + } + + lret = lzma_code (&sec->lzma, action); + + nwrite = (output->avail - output->next) - sec->lzma.avail_out; + + if (nwrite != 0) + { + output->next += nwrite; + + if (output->next == output->avail) + { + if ((output = xd3_alloc_output (stream, output)) == NULL) + { + return ENOMEM; + } + + sec->lzma.next_out = output->base; + sec->lzma.avail_out = output->avail; + } + } + + switch (lret) + { + case LZMA_OK: + break; + + case LZMA_STREAM_END: + return 0; + + default: + stream->msg = "lzma encoding error"; + return XD3_INTERNAL; + } + } + + return 0; +} + +#endif /* XD3_ENCODER */ + +#endif /* _XDELTA3_LZMA_H_ */ |