/src/libheif/libheif/error.cc
Line | Count | Source |
1 | | /* |
2 | | * HEIF codec. |
3 | | * Copyright (c) 2017 Dirk Farin <dirk.farin@gmail.com> |
4 | | * |
5 | | * This file is part of libheif. |
6 | | * |
7 | | * libheif is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libheif is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libheif. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "error.h" |
22 | | |
23 | | #include <cassert> |
24 | | #include <cstring> |
25 | | |
26 | | |
27 | | const heif_error heif_error_null_pointer_argument { |
28 | | heif_error_Usage_error, |
29 | | heif_suberror_Null_pointer_argument, |
30 | | "NULL argument passed" |
31 | | }; |
32 | | |
33 | | |
34 | | // static |
35 | | const char Error::kSuccess[] = "Success"; |
36 | | const char* cUnknownError = "Unknown error"; |
37 | | |
38 | | |
39 | | const Error Error::Ok(heif_error_Ok); |
40 | | |
41 | | const Error Error::InternalError{heif_error_Unsupported_feature, // TODO: use better value |
42 | | heif_suberror_Unspecified, |
43 | | "Internal error"}; |
44 | | |
45 | | |
46 | 56.6k | Error::Error() = default; |
47 | | |
48 | | |
49 | | Error::Error(heif_error_code c, |
50 | | heif_suberror_code sc, |
51 | | const std::string& msg) |
52 | 20.8k | : error_code(c), |
53 | 20.8k | sub_error_code(sc), |
54 | 20.8k | message(msg) |
55 | 20.8k | { |
56 | 20.8k | } |
57 | | |
58 | | |
59 | | // Replacement for C++20 std::string::starts_with() |
60 | 736 | static bool starts_with(const std::string& str, const std::string& prefix) { |
61 | 736 | if (str.length() < prefix.length()) { |
62 | 0 | return false; |
63 | 0 | } |
64 | 736 | return str.rfind(prefix, 0) == 0; |
65 | 736 | } |
66 | | |
67 | | |
68 | | Error Error::from_heif_error(const heif_error& c_error) |
69 | 736 | { |
70 | | // unpack the concatenated error message and extract the last part only |
71 | | |
72 | 736 | const char* err_string = get_error_string(c_error.code); |
73 | 736 | const char* sub_err_string = get_error_string(c_error.subcode); |
74 | | |
75 | 736 | std::string msg = c_error.message; |
76 | 736 | if (starts_with(msg, err_string)) { |
77 | 0 | msg = msg.substr(strlen(err_string)); |
78 | |
|
79 | 0 | if (starts_with(msg, ": ")) { |
80 | 0 | msg = msg.substr(2); |
81 | 0 | } |
82 | |
|
83 | 0 | if (starts_with(msg, sub_err_string)) { |
84 | 0 | msg = msg.substr(strlen(sub_err_string)); |
85 | |
|
86 | 0 | if (starts_with(msg, ": ")) { |
87 | 0 | msg = msg.substr(2); |
88 | 0 | } |
89 | 0 | } |
90 | 0 | } |
91 | | |
92 | 736 | return {c_error.code, c_error.subcode, msg}; |
93 | 736 | } |
94 | | |
95 | | |
96 | | const char* Error::get_error_string(heif_error_code err) |
97 | 9.82k | { |
98 | 9.82k | switch (err) { |
99 | 0 | case heif_error_Ok: |
100 | 0 | return "Success"; |
101 | 0 | case heif_error_Input_does_not_exist: |
102 | 0 | return "Input file does not exist"; |
103 | 5.20k | case heif_error_Invalid_input: |
104 | 5.20k | return "Invalid input"; |
105 | 851 | case heif_error_Unsupported_filetype: |
106 | 851 | return "Unsupported file-type"; |
107 | 1.75k | case heif_error_Unsupported_feature: |
108 | 1.75k | return "Unsupported feature"; |
109 | 0 | case heif_error_Usage_error: |
110 | 0 | return "Usage error"; |
111 | 236 | case heif_error_Memory_allocation_error: |
112 | 236 | return "Memory allocation error"; |
113 | 1.63k | case heif_error_Decoder_plugin_error: |
114 | 1.63k | return "Decoder plugin generated an error"; |
115 | 0 | case heif_error_Encoder_plugin_error: |
116 | 0 | return "Encoder plugin generated an error"; |
117 | 0 | case heif_error_Encoding_error: |
118 | 0 | return "Error during encoding or writing output file"; |
119 | 0 | case heif_error_Color_profile_does_not_exist: |
120 | 0 | return "Color profile does not exist"; |
121 | 140 | case heif_error_Plugin_loading_error: |
122 | 140 | return "Error while loading plugin"; |
123 | 0 | case heif_error_Canceled: |
124 | 0 | return "Canceled by user"; |
125 | 0 | case heif_error_End_of_sequence: |
126 | 0 | return "End of sequence"; |
127 | 9.82k | } |
128 | | |
129 | 9.82k | assert(false); |
130 | 0 | return "Unknown error"; |
131 | 9.82k | } |
132 | | |
133 | | const char* Error::get_error_string(heif_suberror_code err) |
134 | 9.82k | { |
135 | 9.82k | switch (err) { |
136 | 2.91k | case heif_suberror_Unspecified: |
137 | 2.91k | return "Unspecified"; |
138 | | |
139 | | // --- Invalid_input --- |
140 | | |
141 | 2.82k | case heif_suberror_End_of_data: |
142 | 2.82k | return "Unexpected end of file"; |
143 | 105 | case heif_suberror_Invalid_box_size: |
144 | 105 | return "Invalid box size"; |
145 | 44 | case heif_suberror_Invalid_grid_data: |
146 | 44 | return "Invalid grid data"; |
147 | 95 | case heif_suberror_Missing_grid_images: |
148 | 95 | return "Missing grid images"; |
149 | 204 | case heif_suberror_No_ftyp_box: |
150 | 204 | return "No 'ftyp' box"; |
151 | 6 | case heif_suberror_No_idat_box: |
152 | 6 | return "No 'idat' box"; |
153 | 109 | case heif_suberror_No_meta_box: |
154 | 109 | return "No 'meta' box"; |
155 | 0 | case heif_suberror_No_hdlr_box: |
156 | 0 | return "No 'hdlr' box"; |
157 | 22 | case heif_suberror_No_hvcC_box: |
158 | 22 | return "No 'hvcC' box"; |
159 | 0 | case heif_suberror_No_vvcC_box: |
160 | 0 | return "No 'vvcC' box"; |
161 | 64 | case heif_suberror_No_av1C_box: |
162 | 64 | return "No 'av1C' box"; |
163 | 0 | case heif_suberror_No_avcC_box: |
164 | 0 | return "No 'avcC' box"; |
165 | 87 | case heif_suberror_No_pitm_box: |
166 | 87 | return "No 'pitm' box"; |
167 | 18 | case heif_suberror_No_ipco_box: |
168 | 18 | return "No 'ipco' box"; |
169 | 13 | case heif_suberror_No_ipma_box: |
170 | 13 | return "No 'ipma' box"; |
171 | 12 | case heif_suberror_No_iloc_box: |
172 | 12 | return "No 'iloc' box"; |
173 | 13 | case heif_suberror_No_iinf_box: |
174 | 13 | return "No 'iinf' box"; |
175 | 45 | case heif_suberror_No_iprp_box: |
176 | 45 | return "No 'iprp' box"; |
177 | 45 | case heif_suberror_No_iref_box: |
178 | 45 | return "No 'iref' box"; |
179 | 0 | case heif_suberror_No_infe_box: |
180 | 0 | return "No 'infe' box"; |
181 | 15 | case heif_suberror_No_pict_handler: |
182 | 15 | return "Not a 'pict' handler"; |
183 | 36 | case heif_suberror_Ipma_box_references_nonexisting_property: |
184 | 36 | return "'ipma' box references a non-existing property"; |
185 | 56 | case heif_suberror_No_properties_assigned_to_item: |
186 | 56 | return "No properties assigned to item"; |
187 | 135 | case heif_suberror_No_item_data: |
188 | 135 | return "Item has no data"; |
189 | 60 | case heif_suberror_Invalid_clean_aperture: |
190 | 60 | return "Invalid clean-aperture specification"; |
191 | 10 | case heif_suberror_Invalid_overlay_data: |
192 | 10 | return "Invalid overlay data"; |
193 | 0 | case heif_suberror_Overlay_image_outside_of_canvas: |
194 | 0 | return "Overlay image outside of canvas area"; |
195 | 17 | case heif_suberror_Auxiliary_image_type_unspecified: |
196 | 17 | return "Type of auxiliary image unspecified"; |
197 | 0 | case heif_suberror_No_or_invalid_primary_item: |
198 | 0 | return "No or invalid primary item"; |
199 | 62 | case heif_suberror_Unknown_color_profile_type: |
200 | 62 | return "Unknown color profile type"; |
201 | 0 | case heif_suberror_Wrong_tile_image_chroma_format: |
202 | 0 | return "Wrong tile image chroma format"; |
203 | 4 | case heif_suberror_Invalid_fractional_number: |
204 | 4 | return "Invalid fractional number"; |
205 | 10 | case heif_suberror_Invalid_image_size: |
206 | 10 | return "Invalid image size"; |
207 | 0 | case heif_suberror_Invalid_pixi_box: |
208 | 0 | return "Invalid pixi box"; |
209 | 0 | case heif_suberror_Wrong_tile_image_pixel_depth: |
210 | 0 | return "Wrong tile image pixel depth"; |
211 | 0 | case heif_suberror_Unknown_NCLX_color_primaries: |
212 | 0 | return "Unknown NCLX color primaries"; |
213 | 0 | case heif_suberror_Unknown_NCLX_transfer_characteristics: |
214 | 0 | return "Unknown NCLX transfer characteristics"; |
215 | 0 | case heif_suberror_Unknown_NCLX_matrix_coefficients: |
216 | 0 | return "Unknown NCLX matrix coefficients"; |
217 | 0 | case heif_suberror_Invalid_region_data: |
218 | 0 | return "Invalid region item data"; |
219 | 6 | case heif_suberror_No_ispe_property: |
220 | 6 | return "Image has no 'ispe' property"; |
221 | 0 | case heif_suberror_Camera_intrinsic_matrix_undefined: |
222 | 0 | return "Camera intrinsic matrix undefined"; |
223 | 0 | case heif_suberror_Camera_extrinsic_matrix_undefined: |
224 | 0 | return "Camera extrinsic matrix undefined"; |
225 | 0 | case heif_suberror_Invalid_J2K_codestream: |
226 | 0 | return "Invalid JPEG 2000 codestream"; |
227 | 0 | case heif_suberror_Decompression_invalid_data: |
228 | 0 | return "Invalid data in generic compression inflation"; |
229 | 83 | case heif_suberror_No_moov_box: |
230 | 83 | return "No 'moov' box"; |
231 | 0 | case heif_suberror_No_icbr_box: |
232 | 0 | return "No 'icbr' box"; |
233 | 0 | case heif_suberror_Invalid_mini_box: |
234 | 0 | return "Unsupported or invalid 'mini' box"; |
235 | | |
236 | | |
237 | | // --- Memory_allocation_error --- |
238 | | |
239 | 406 | case heif_suberror_Security_limit_exceeded: |
240 | 406 | return "Security limit exceeded"; |
241 | 0 | case heif_suberror_Compression_initialisation_error: |
242 | 0 | return "Compression initialisation method error"; |
243 | | |
244 | | // --- Usage_error --- |
245 | | |
246 | 385 | case heif_suberror_Nonexisting_item_referenced: |
247 | 385 | return "Non-existing item ID referenced"; |
248 | 0 | case heif_suberror_Null_pointer_argument: |
249 | 0 | return "NULL argument received"; |
250 | 0 | case heif_suberror_Nonexisting_image_channel_referenced: |
251 | 0 | return "Non-existing image channel referenced"; |
252 | 0 | case heif_suberror_Unsupported_plugin_version: |
253 | 0 | return "The version of the passed plugin is not supported"; |
254 | 0 | case heif_suberror_Unsupported_writer_version: |
255 | 0 | return "The version of the passed writer is not supported"; |
256 | 0 | case heif_suberror_Unsupported_parameter: |
257 | 0 | return "Unsupported parameter"; |
258 | 3 | case heif_suberror_Invalid_parameter_value: |
259 | 3 | return "Invalid parameter value"; |
260 | 0 | case heif_suberror_Invalid_property: |
261 | 0 | return "Invalid property"; |
262 | 14 | case heif_suberror_Item_reference_cycle: |
263 | 14 | return "Image reference cycle"; |
264 | | |
265 | | // --- Unsupported_feature --- |
266 | | |
267 | 3 | case heif_suberror_Unsupported_codec: |
268 | 3 | return "Unsupported codec"; |
269 | 3 | case heif_suberror_Unsupported_image_type: |
270 | 3 | return "Unsupported image type"; |
271 | 144 | case heif_suberror_Unsupported_data_version: |
272 | 144 | return "Unsupported data version"; |
273 | 1.47k | case heif_suberror_Unsupported_color_conversion: |
274 | 1.47k | return "Unsupported color conversion"; |
275 | 106 | case heif_suberror_Unsupported_item_construction_method: |
276 | 106 | return "Unsupported item construction method"; |
277 | 1 | case heif_suberror_Unsupported_header_compression_method: |
278 | 1 | return "Unsupported header compression method"; |
279 | 0 | case heif_suberror_Unsupported_generic_compression_method: |
280 | 0 | return "Unsupported generic compression method"; |
281 | 21 | case heif_suberror_Unsupported_essential_property: |
282 | 21 | return "Unsupported essential item property"; |
283 | | |
284 | | // --- Encoder_plugin_error -- |
285 | | |
286 | 0 | case heif_suberror_Unsupported_bit_depth: |
287 | 0 | return "Unsupported bit depth"; |
288 | | |
289 | | // --- Encoding_error -- |
290 | | |
291 | 0 | case heif_suberror_Cannot_write_output_data: |
292 | 0 | return "Cannot write output data"; |
293 | 0 | case heif_suberror_Encoder_initialization: |
294 | 0 | return "Initialization problem"; |
295 | 0 | case heif_suberror_Encoder_encoding: |
296 | 0 | return "Encoding problem"; |
297 | 0 | case heif_suberror_Encoder_cleanup: |
298 | 0 | return "Cleanup problem"; |
299 | 0 | case heif_suberror_Too_many_regions: |
300 | 0 | return "Too many regions (>255) in an 'rgan' item."; |
301 | | |
302 | | // --- Plugin_loading_error --- |
303 | | |
304 | 0 | case heif_suberror_Plugin_loading_error: |
305 | 0 | return "Plugin file cannot be loaded"; |
306 | 0 | case heif_suberror_Plugin_is_not_loaded: |
307 | 0 | return "Trying to remove a plugin that is not loaded"; |
308 | 0 | case heif_suberror_Cannot_read_plugin_directory: |
309 | 0 | return "Error while scanning the directory for plugins"; |
310 | 140 | case heif_suberror_No_matching_decoder_installed: |
311 | | #if ENABLE_PLUGIN_LOADING |
312 | | return "No decoding plugin installed for this compression format"; |
313 | | #else |
314 | 140 | return "Support for this compression format has not been built in"; |
315 | 9.82k | #endif |
316 | 9.82k | } |
317 | | |
318 | 9.82k | assert(false); |
319 | 0 | return cUnknownError; |
320 | 9.82k | } |
321 | | |
322 | | |
323 | | heif_error Error::error_struct(ErrorBuffer* error_buffer) const |
324 | 23.6k | { |
325 | 23.6k | if (error_buffer) { |
326 | 20.3k | if (error_code == heif_error_Ok) { |
327 | 11.2k | error_buffer->set_success(); |
328 | 11.2k | } |
329 | 9.08k | else { |
330 | 9.08k | std::stringstream sstr; |
331 | 9.08k | sstr << get_error_string(error_code) << ": " |
332 | 9.08k | << get_error_string(sub_error_code); |
333 | 9.08k | if (!message.empty()) { |
334 | 4.30k | sstr << ": " << message; |
335 | 4.30k | } |
336 | | |
337 | 9.08k | error_buffer->set_error(sstr.str()); |
338 | 9.08k | } |
339 | 20.3k | } |
340 | | |
341 | 23.6k | heif_error err; |
342 | 23.6k | err.code = error_code; |
343 | 23.6k | err.subcode = sub_error_code; |
344 | 23.6k | if (error_buffer) { |
345 | 20.3k | err.message = error_buffer->get_error(); |
346 | 20.3k | } |
347 | 3.31k | else { |
348 | 3.31k | err.message = cUnknownError; |
349 | 3.31k | } |
350 | 23.6k | return err; |
351 | 23.6k | } |