]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/copy_coder.c
Don't fill allocated memory with 0xFD when debugging is
[icculus/xz.git] / src / liblzma / common / copy_coder.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       copy_coder.c
4 /// \brief      The Copy filter encoder and decoder
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
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.
12 //
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.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include "copy_coder.h"
21
22
23 struct lzma_coder_s {
24         lzma_next_coder next;
25         lzma_vli uncompressed_size;
26 };
27
28
29 #ifdef HAVE_ENCODER
30 static lzma_ret
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)
35 {
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,
43                                 action);
44
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);
48
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;
52
53         return LZMA_OK;
54 }
55 #endif
56
57
58 #ifdef HAVE_DECODER
59 static lzma_ret
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)
64 {
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,
68                                 action);
69
70         assert(coder->uncompressed_size <= LZMA_VLI_VALUE_MAX);
71
72         const size_t in_avail = in_size - *in_pos;
73
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);
77
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);
82
83         // Update uncompressed_size if it is known.
84         if (coder->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
85                 coder->uncompressed_size -= in_used;
86
87         return coder->uncompressed_size == 0 ? LZMA_STREAM_END : LZMA_OK;
88 }
89 #endif
90
91
92 static void
93 copy_coder_end(lzma_coder *coder, lzma_allocator *allocator)
94 {
95         lzma_next_coder_end(&coder->next, allocator);
96         lzma_free(coder, allocator);
97         return;
98 }
99
100
101 static lzma_ret
102 copy_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
103                 const lzma_filter_info *filters, lzma_code_function encode)
104 {
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;
110
111                 next->code = encode;
112                 next->end = &copy_coder_end;
113                 next->coder->next = LZMA_NEXT_CODER_INIT;
114         }
115
116         // Copy Uncompressed Size which is used to limit the output size.
117         next->coder->uncompressed_size = filters[0].uncompressed_size;
118
119         // Initialize the next decoder in the chain, if any.
120         return lzma_next_filter_init(
121                         &next->coder->next, allocator, filters + 1);
122 }
123
124
125 #ifdef HAVE_ENCODER
126 extern lzma_ret
127 lzma_copy_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
128                 const lzma_filter_info *filters)
129 {
130         lzma_next_coder_init(copy_coder_init, next, allocator, filters,
131                         &copy_encode);
132 }
133 #endif
134
135
136 #ifdef HAVE_DECODER
137 extern lzma_ret
138 lzma_copy_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
139                 const lzma_filter_info *filters)
140 {
141         lzma_next_coder_init(copy_coder_init, next, allocator, filters,
142                         &copy_decode);
143 }
144 #endif