]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/filter_decoder.c
050bdd9af1fa9ffd2d6ae68e919c7f843d9647a3
[icculus/xz.git] / src / liblzma / common / filter_decoder.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       filter_decoder.c
4 /// \brief      Filter ID mapping to filter-specific functions
5 //
6 //  Copyright (C) 2008 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 "filter_decoder.h"
21 #include "filter_common.h"
22 #include "lzma_decoder.h"
23 #include "lzma2_decoder.h"
24 #include "subblock_decoder.h"
25 #include "subblock_decoder_helper.h"
26 #include "simple_decoder.h"
27 #include "delta_decoder.h"
28
29
30 typedef struct {
31         /// Filter ID
32         lzma_vli id;
33
34         /// Initializes the filter encoder and calls lzma_next_filter_init()
35         /// for filters + 1.
36         lzma_init_function init;
37
38         /// Calculates memory usage of the encoder. If the options are
39         /// invalid, UINT64_MAX is returned.
40         uint64_t (*memusage)(const void *options);
41
42         /// Decodes Filter Properties.
43         ///
44         /// \return     - LZMA_OK: Properties decoded successfully.
45         ///             - LZMA_OPTIONS_ERROR: Unsupported properties
46         ///             - LZMA_MEM_ERROR: Memory allocation failed.
47         lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
48                         const uint8_t *props, size_t props_size);
49
50 } lzma_filter_decoder;
51
52
53 static const lzma_filter_decoder decoders[] = {
54 #ifdef HAVE_DECODER_LZMA1
55         {
56                 .id = LZMA_FILTER_LZMA1,
57                 .init = &lzma_lzma_decoder_init,
58                 .memusage = &lzma_lzma_decoder_memusage,
59                 .props_decode = &lzma_lzma_props_decode,
60         },
61 #endif
62 #ifdef HAVE_DECODER_LZMA2
63         {
64                 .id = LZMA_FILTER_LZMA2,
65                 .init = &lzma_lzma2_decoder_init,
66                 .memusage = &lzma_lzma2_decoder_memusage,
67                 .props_decode = &lzma_lzma2_props_decode,
68         },
69 #endif
70 #ifdef HAVE_DECODER_SUBBLOCK
71         {
72                 .id = LZMA_FILTER_SUBBLOCK,
73                 .init = &lzma_subblock_decoder_init,
74 //              .memusage = &lzma_subblock_decoder_memusage,
75                 .props_decode = NULL,
76         },
77         {
78                 .id = LZMA_FILTER_SUBBLOCK_HELPER,
79                 .init = &lzma_subblock_decoder_helper_init,
80                 .memusage = NULL,
81                 .props_decode = NULL,
82         },
83 #endif
84 #ifdef HAVE_DECODER_X86
85         {
86                 .id = LZMA_FILTER_X86,
87                 .init = &lzma_simple_x86_decoder_init,
88                 .memusage = NULL,
89                 .props_decode = &lzma_simple_props_decode,
90         },
91 #endif
92 #ifdef HAVE_DECODER_POWERPC
93         {
94                 .id = LZMA_FILTER_POWERPC,
95                 .init = &lzma_simple_powerpc_decoder_init,
96                 .memusage = NULL,
97                 .props_decode = &lzma_simple_props_decode,
98         },
99 #endif
100 #ifdef HAVE_DECODER_IA64
101         {
102                 .id = LZMA_FILTER_IA64,
103                 .init = &lzma_simple_ia64_decoder_init,
104                 .memusage = NULL,
105                 .props_decode = &lzma_simple_props_decode,
106         },
107 #endif
108 #ifdef HAVE_DECODER_ARM
109         {
110                 .id = LZMA_FILTER_ARM,
111                 .init = &lzma_simple_arm_decoder_init,
112                 .memusage = NULL,
113                 .props_decode = &lzma_simple_props_decode,
114         },
115 #endif
116 #ifdef HAVE_DECODER_ARMTHUMB
117         {
118                 .id = LZMA_FILTER_ARMTHUMB,
119                 .init = &lzma_simple_armthumb_decoder_init,
120                 .memusage = NULL,
121                 .props_decode = &lzma_simple_props_decode,
122         },
123 #endif
124 #ifdef HAVE_DECODER_SPARC
125         {
126                 .id = LZMA_FILTER_SPARC,
127                 .init = &lzma_simple_sparc_decoder_init,
128                 .memusage = NULL,
129                 .props_decode = &lzma_simple_props_decode,
130         },
131 #endif
132 #ifdef HAVE_DECODER_DELTA
133         {
134                 .id = LZMA_FILTER_DELTA,
135                 .init = &lzma_delta_decoder_init,
136                 .memusage = &lzma_delta_coder_memusage,
137                 .props_decode = &lzma_delta_props_decode,
138         },
139 #endif
140 };
141
142
143 static const lzma_filter_decoder *
144 decoder_find(lzma_vli id)
145 {
146         for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
147                 if (decoders[i].id == id)
148                         return decoders + i;
149
150         return NULL;
151 }
152
153
154 extern LZMA_API(lzma_bool)
155 lzma_filter_decoder_is_supported(lzma_vli id)
156 {
157         return decoder_find(id) != NULL;
158 }
159
160
161 extern lzma_ret
162 lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
163                 const lzma_filter *options)
164 {
165         return lzma_raw_coder_init(next, allocator,
166                         options, (lzma_filter_find)(&decoder_find), false);
167 }
168
169
170 extern LZMA_API(lzma_ret)
171 lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
172 {
173         lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
174
175         strm->internal->supported_actions[LZMA_RUN] = true;
176         strm->internal->supported_actions[LZMA_FINISH] = true;
177
178         return LZMA_OK;
179 }
180
181
182 extern LZMA_API(uint64_t)
183 lzma_raw_decoder_memusage(const lzma_filter *filters)
184 {
185         return lzma_raw_coder_memusage(
186                         (lzma_filter_find)(&decoder_find), filters);
187 }
188
189
190 extern LZMA_API(lzma_ret)
191 lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
192                 const uint8_t *props, size_t props_size)
193 {
194         // Make it always NULL so that the caller can always safely free() it.
195         filter->options = NULL;
196
197         const lzma_filter_decoder *const fd = decoder_find(filter->id);
198         if (fd == NULL)
199                 return LZMA_OPTIONS_ERROR;
200
201         if (fd->props_decode == NULL)
202                 return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR;
203
204         return fd->props_decode(
205                         &filter->options, allocator, props, props_size);
206 }