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_encode(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 // We are the last coder in the chain.
46 // Just copy as much data as possible.
47 bufcpy(in, in_pos, in_size, out, out_pos, out_size);
49 // LZMA_SYNC_FLUSH and LZMA_FINISH are the same thing for us.
50 if (action != LZMA_RUN && *in_pos == in_size)
51 return LZMA_STREAM_END;
60 copy_decode(lzma_coder *coder, lzma_allocator *allocator,
61 const uint8_t *restrict in, size_t *restrict in_pos,
62 size_t in_size, uint8_t *restrict out,
63 size_t *restrict out_pos, size_t out_size, lzma_action action)
65 if (coder->next.code != NULL)
66 return coder->next.code(coder->next.coder, allocator,
67 in, in_pos, in_size, out, out_pos, out_size,
70 assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
72 const size_t in_avail = in_size - *in_pos;
74 // Limit in_size so that we don't copy too much.
75 if ((lzma_vli)(in_avail) > coder->uncompressed_size)
76 in_size = *in_pos + (size_t)(coder->uncompressed_size);
78 // We are the last coder in the chain.
79 // Just copy as much data as possible.
80 const size_t in_used = bufcpy(
81 in, in_pos, in_size, out, out_pos, out_size);
83 // Update uncompressed_size if it is known.
84 if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
85 coder->uncompressed_size -= in_used;
87 return coder->uncompressed_size == 0 ? LZMA_STREAM_END : LZMA_OK;
93 copy_coder_end(lzma_coder *coder, lzma_allocator *allocator)
95 lzma_next_coder_end(&coder->next, allocator);
96 lzma_free(coder, allocator);
102 copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
103 const lzma_filter_info *filters, lzma_code_function encode)
105 // Allocate memory for the decoder if needed.
106 if (next->coder == NULL) {
107 next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
108 if (next->coder == NULL)
109 return LZMA_MEM_ERROR;
112 next->end = ©_coder_end;
113 next->coder->next = LZMA_NEXT_CODER_INIT;
116 // Copy Uncompressed Size which is used to limit the output size.
117 next->coder->uncompressed_size = filters[0].uncompressed_size;
119 // Initialize the next decoder in the chain, if any.
120 return lzma_next_filter_init(
121 &next->coder->next, allocator, filters + 1);
127 lzma_copy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
128 const lzma_filter_info *filters)
130 lzma_next_coder_init(copy_coder_init, next, allocator, filters,
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,