1 ///////////////////////////////////////////////////////////////////////////////
4 /// \brief The Copy filter encoder and decoder
6 // Copyright (C) 2007 Lasse Collin
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 ///////////////////////////////////////////////////////////////////////////////
20 #include "copy_coder.h"
25 lzma_vli uncompressed_size;
31 copy_code(lzma_coder *coder, lzma_allocator *allocator,
32 const uint8_t *restrict in, size_t *restrict in_pos,
33 size_t in_size, uint8_t *restrict out,
34 size_t *restrict out_pos, size_t out_size, lzma_action action)
36 // If we aren't the last filter in the chain, the Copy filter
37 // is totally useless. Note that it is job of the next coder to
38 // take care of Uncompressed Size, so we don't need to update our
39 // coder->uncompressed_size at all.
40 if (coder->next.code != NULL)
41 return coder->next.code(coder->next.coder, allocator,
42 in, in_pos, in_size, out, out_pos, out_size,
45 // If we get here, we are the last filter in the chain.
47 const size_t in_avail = in_size - *in_pos;
49 if (coder->is_encoder) {
50 // Check that we don't have too much input.
51 if ((lzma_vli)(in_avail) > coder->uncompressed_size)
52 return LZMA_DATA_ERROR;
54 // Check that once LZMA_FINISH has been given, the
55 // amount of input matches uncompressed_size if it
57 if (action == LZMA_FINISH && coder->uncompressed_size
58 != LZMA_VLI_VALUE_UNKNOWN
59 && coder->uncompressed_size
60 != (lzma_vli)(in_avail))
61 return LZMA_DATA_ERROR;
64 // Limit in_size so that we don't copy too much.
65 if ((lzma_vli)(in_avail) > coder->uncompressed_size)
66 in_size = *in_pos + (size_t)(coder->uncompressed_size);
69 // Store the old input position, which is needed to update
70 // coder->uncompressed_size.
71 const size_t in_start = *in_pos;
73 // We are the last coder in the chain.
74 // Just copy as much data as possible.
75 bufcpy(in, in_pos, in_size, out, out_pos, out_size);
77 // Update uncompressed_size if it is known.
78 if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
79 coder->uncompressed_size -= *in_pos - in_start;
81 // action can be LZMA_FINISH only in the encoder.
82 if ((action == LZMA_FINISH && *in_pos == in_size)
83 || coder->uncompressed_size == 0)
84 return LZMA_STREAM_END;
91 copy_coder_end(lzma_coder *coder, lzma_allocator *allocator)
93 lzma_next_coder_end(&coder->next, allocator);
94 lzma_free(coder, allocator);
100 copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
101 const lzma_filter_info *filters, bool is_encoder)
103 // Allocate memory for the decoder if needed.
104 if (next->coder == NULL) {
105 next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
106 if (next->coder == NULL)
107 return LZMA_MEM_ERROR;
109 next->code = ©_code;
110 next->end = ©_coder_end;
111 next->coder->next = LZMA_NEXT_CODER_INIT;
114 // Copy Uncompressed Size which is used to limit the output size.
115 next->coder->uncompressed_size = filters[0].uncompressed_size;
117 // The coder acts slightly differently as encoder and decoder.
118 next->coder->is_encoder = is_encoder;
120 // Initialize the next decoder in the chain, if any.
121 return lzma_next_filter_init(
122 &next->coder->next, allocator, filters + 1);
128 lzma_copy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
129 const lzma_filter_info *filters)
131 lzma_next_coder_init(copy_coder_init, next, allocator, filters, true);
138 lzma_copy_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
139 const lzma_filter_info *filters)
141 lzma_next_coder_init(copy_coder_init, next, allocator, filters, false);