/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 | 1.46M | Error::Error() = default; |
47 | | |
48 | | |
49 | | Error::Error(heif_error_code c, |
50 | | heif_suberror_code sc, |
51 | | const std::string& msg) |
52 | 459k | : error_code(c), |
53 | 459k | sub_error_code(sc), |
54 | 459k | message(msg) |
55 | 459k | { |
56 | 459k | } |
57 | | |
58 | | |
59 | | // Replacement for C++20 std::string::starts_with() |
60 | 137k | static bool starts_with(const std::string& str, const std::string& prefix) { |
61 | 137k | if (str.length() < prefix.length()) { |
62 | 92.3k | return false; |
63 | 92.3k | } |
64 | | |
65 | 45.3k | return str.compare(0, prefix.size(), prefix) == 0; |
66 | 137k | } |
67 | | |
68 | | |
69 | | Error Error::from_heif_error(const heif_error& c_error) |
70 | 53.7k | { |
71 | | // unpack the concatenated error message and extract the last part only |
72 | | |
73 | 53.7k | const char* err_string = get_error_string(c_error.code); |
74 | 53.7k | const char* sub_err_string = get_error_string(c_error.subcode); |
75 | | |
76 | 53.7k | std::string msg = c_error.message; |
77 | 53.7k | if (starts_with(msg, err_string)) { |
78 | 41.9k | msg = msg.substr(strlen(err_string)); |
79 | | |
80 | 41.9k | if (starts_with(msg, ": ")) { |
81 | 40 | msg = msg.substr(2); |
82 | 40 | } |
83 | | |
84 | 41.9k | if (starts_with(msg, sub_err_string)) { |
85 | 40 | msg = msg.substr(strlen(sub_err_string)); |
86 | | |
87 | 40 | if (starts_with(msg, ": ")) { |
88 | 40 | msg = msg.substr(2); |
89 | 40 | } |
90 | 40 | } |
91 | 41.9k | } |
92 | | |
93 | 53.7k | return {c_error.code, c_error.subcode, msg}; |
94 | 53.7k | } |
95 | | |
96 | | |
97 | | const char* Error::get_error_string(heif_error_code err) |
98 | 136k | { |
99 | 136k | switch (err) { |
100 | 41.8k | case heif_error_Ok: |
101 | 41.8k | return "Success"; |
102 | 0 | case heif_error_Input_does_not_exist: |
103 | 0 | return "Input file does not exist"; |
104 | 61.2k | case heif_error_Invalid_input: |
105 | 61.2k | return "Invalid input"; |
106 | 2.15k | case heif_error_Unsupported_filetype: |
107 | 2.15k | return "Unsupported file-type"; |
108 | 7.27k | case heif_error_Unsupported_feature: |
109 | 7.27k | return "Unsupported feature"; |
110 | 15 | case heif_error_Usage_error: |
111 | 15 | return "Usage error"; |
112 | 1.66k | case heif_error_Memory_allocation_error: |
113 | 1.66k | return "Memory allocation error"; |
114 | 22.1k | case heif_error_Decoder_plugin_error: |
115 | 22.1k | return "Decoder plugin generated an error"; |
116 | 0 | case heif_error_Encoder_plugin_error: |
117 | 0 | return "Encoder plugin generated an error"; |
118 | 1 | case heif_error_Encoding_error: |
119 | 1 | return "Error during encoding or writing output file"; |
120 | 0 | case heif_error_Color_profile_does_not_exist: |
121 | 0 | return "Color profile does not exist"; |
122 | 0 | case heif_error_Plugin_loading_error: |
123 | 0 | return "Error while loading plugin"; |
124 | 0 | case heif_error_Canceled: |
125 | 0 | return "Canceled by user"; |
126 | 0 | case heif_error_End_of_sequence: |
127 | 0 | return "End of sequence"; |
128 | 136k | } |
129 | | |
130 | 136k | assert(false); |
131 | 0 | return "Unknown error"; |
132 | 0 | } |
133 | | |
134 | | const char* Error::get_error_string(heif_suberror_code err) |
135 | 136k | { |
136 | 136k | switch (err) { |
137 | 88.8k | case heif_suberror_Unspecified: |
138 | 88.8k | return "Unspecified"; |
139 | | |
140 | | // --- Invalid_input --- |
141 | | |
142 | 11.3k | case heif_suberror_End_of_data: |
143 | 11.3k | return "Unexpected end of file"; |
144 | 239 | case heif_suberror_Invalid_box_size: |
145 | 239 | return "Invalid box size"; |
146 | 114 | case heif_suberror_Invalid_grid_data: |
147 | 114 | return "Invalid grid data"; |
148 | 188 | case heif_suberror_Missing_grid_images: |
149 | 188 | return "Missing grid images"; |
150 | 9.38k | case heif_suberror_No_ftyp_box: |
151 | 9.38k | return "No 'ftyp' box"; |
152 | 30 | case heif_suberror_No_idat_box: |
153 | 30 | return "No 'idat' box"; |
154 | 494 | case heif_suberror_No_meta_box: |
155 | 494 | return "No 'meta' box"; |
156 | 0 | case heif_suberror_No_hdlr_box: |
157 | 0 | return "No 'hdlr' box"; |
158 | 103 | case heif_suberror_No_hvcC_box: |
159 | 103 | return "No 'hvcC' box"; |
160 | 0 | case heif_suberror_No_vvcC_box: |
161 | 0 | return "No 'vvcC' box"; |
162 | 286 | case heif_suberror_No_av1C_box: |
163 | 286 | return "No 'av1C' box"; |
164 | 0 | case heif_suberror_No_avcC_box: |
165 | 0 | return "No 'avcC' box"; |
166 | 39 | case heif_suberror_No_pitm_box: |
167 | 39 | return "No 'pitm' box"; |
168 | 47 | case heif_suberror_No_ipco_box: |
169 | 47 | return "No 'ipco' box"; |
170 | 36 | case heif_suberror_No_ipma_box: |
171 | 36 | return "No 'ipma' box"; |
172 | 90 | case heif_suberror_No_iloc_box: |
173 | 90 | return "No 'iloc' box"; |
174 | 422 | case heif_suberror_No_iinf_box: |
175 | 422 | return "No 'iinf' box"; |
176 | 86 | case heif_suberror_No_iprp_box: |
177 | 86 | return "No 'iprp' box"; |
178 | 44 | case heif_suberror_No_iref_box: |
179 | 44 | return "No 'iref' box"; |
180 | 0 | case heif_suberror_No_infe_box: |
181 | 0 | return "No 'infe' box"; |
182 | 0 | case heif_suberror_No_pict_handler: |
183 | 0 | return "Not a 'pict' handler"; |
184 | 145 | case heif_suberror_Ipma_box_references_nonexisting_property: |
185 | 145 | return "'ipma' box references a non-existing property"; |
186 | 260 | case heif_suberror_No_properties_assigned_to_item: |
187 | 260 | return "No properties assigned to item"; |
188 | 445 | case heif_suberror_No_item_data: |
189 | 445 | return "Item has no data"; |
190 | 181 | case heif_suberror_Invalid_clean_aperture: |
191 | 181 | return "Invalid clean-aperture specification"; |
192 | 21 | case heif_suberror_Invalid_overlay_data: |
193 | 21 | return "Invalid overlay data"; |
194 | 0 | case heif_suberror_Overlay_image_outside_of_canvas: |
195 | 0 | return "Overlay image outside of canvas area"; |
196 | 72 | case heif_suberror_Auxiliary_image_type_unspecified: |
197 | 72 | return "Type of auxiliary image unspecified"; |
198 | 0 | case heif_suberror_No_or_invalid_primary_item: |
199 | 0 | return "No or invalid primary item"; |
200 | 201 | case heif_suberror_Unknown_color_profile_type: |
201 | 201 | return "Unknown color profile type"; |
202 | 0 | case heif_suberror_Wrong_tile_image_chroma_format: |
203 | 0 | return "Wrong tile image chroma format"; |
204 | 15 | case heif_suberror_Invalid_fractional_number: |
205 | 15 | return "Invalid fractional number"; |
206 | 10.0k | case heif_suberror_Invalid_image_size: |
207 | 10.0k | return "Invalid image size"; |
208 | 0 | case heif_suberror_Invalid_pixi_box: |
209 | 0 | return "Invalid pixi box"; |
210 | 0 | case heif_suberror_Wrong_tile_image_pixel_depth: |
211 | 0 | return "Wrong tile image pixel depth"; |
212 | 0 | case heif_suberror_Unknown_NCLX_color_primaries: |
213 | 0 | return "Unknown NCLX color primaries"; |
214 | 0 | case heif_suberror_Unknown_NCLX_transfer_characteristics: |
215 | 0 | return "Unknown NCLX transfer characteristics"; |
216 | 0 | case heif_suberror_Unknown_NCLX_matrix_coefficients: |
217 | 0 | return "Unknown NCLX matrix coefficients"; |
218 | 0 | case heif_suberror_Invalid_region_data: |
219 | 0 | return "Invalid region item data"; |
220 | 15 | case heif_suberror_No_ispe_property: |
221 | 15 | return "Image has no 'ispe' property"; |
222 | 0 | case heif_suberror_Camera_intrinsic_matrix_undefined: |
223 | 0 | return "Camera intrinsic matrix undefined"; |
224 | 0 | case heif_suberror_Camera_extrinsic_matrix_undefined: |
225 | 0 | return "Camera extrinsic matrix undefined"; |
226 | 0 | case heif_suberror_Invalid_J2K_codestream: |
227 | 0 | return "Invalid JPEG 2000 codestream"; |
228 | 1.13k | case heif_suberror_Decompression_invalid_data: |
229 | 1.13k | return "Invalid data in generic compression inflation"; |
230 | 376 | case heif_suberror_No_moov_box: |
231 | 376 | return "No 'moov' box"; |
232 | 0 | case heif_suberror_NCLX_colr_VUI_mismatch: |
233 | 0 | return "colr box and bitstream colour signalling disagree"; |
234 | 0 | case heif_suberror_No_icbr_box: |
235 | 0 | return "No 'icbr' box"; |
236 | 123 | case heif_suberror_Invalid_mini_box: |
237 | 123 | return "Unsupported or invalid 'mini' box"; |
238 | | |
239 | | |
240 | | // --- Memory_allocation_error --- |
241 | | |
242 | 2.40k | case heif_suberror_Security_limit_exceeded: |
243 | 2.40k | return "Security limit exceeded"; |
244 | 0 | case heif_suberror_Compression_initialisation_error: |
245 | 0 | return "Compression initialisation method error"; |
246 | | |
247 | | // --- Usage_error --- |
248 | | |
249 | 990 | case heif_suberror_Nonexisting_item_referenced: |
250 | 990 | return "Non-existing item ID referenced"; |
251 | 0 | case heif_suberror_Null_pointer_argument: |
252 | 0 | return "NULL argument received"; |
253 | 0 | case heif_suberror_Nonexisting_image_channel_referenced: |
254 | 0 | return "Non-existing image channel referenced"; |
255 | 0 | case heif_suberror_Unsupported_plugin_version: |
256 | 0 | return "The version of the passed plugin is not supported"; |
257 | 0 | case heif_suberror_Unsupported_writer_version: |
258 | 0 | return "The version of the passed writer is not supported"; |
259 | 21 | case heif_suberror_Unsupported_parameter: |
260 | 21 | return "Unsupported parameter"; |
261 | 909 | case heif_suberror_Invalid_parameter_value: |
262 | 909 | return "Invalid parameter value"; |
263 | 0 | case heif_suberror_Invalid_property: |
264 | 0 | return "Invalid property"; |
265 | 41 | case heif_suberror_Item_reference_cycle: |
266 | 41 | return "Image reference cycle"; |
267 | | |
268 | | // --- Unsupported_feature --- |
269 | | |
270 | 18 | case heif_suberror_Unsupported_codec: |
271 | 18 | return "Unsupported codec"; |
272 | 3 | case heif_suberror_Unsupported_image_type: |
273 | 3 | return "Unsupported image type"; |
274 | 405 | case heif_suberror_Unsupported_data_version: |
275 | 405 | return "Unsupported data version"; |
276 | 6.69k | case heif_suberror_Unsupported_color_conversion: |
277 | 6.69k | return "Unsupported color conversion"; |
278 | 20 | case heif_suberror_Unsupported_item_construction_method: |
279 | 20 | return "Unsupported item construction method"; |
280 | 0 | case heif_suberror_Unsupported_header_compression_method: |
281 | 0 | return "Unsupported header compression method"; |
282 | 3 | case heif_suberror_Unsupported_generic_compression_method: |
283 | 3 | return "Unsupported generic compression method"; |
284 | 63 | case heif_suberror_Unsupported_essential_property: |
285 | 63 | return "Unsupported essential item property"; |
286 | 0 | case heif_suberror_Unsupported_track_type: |
287 | 0 | return "Unsupported track type"; |
288 | | |
289 | | // --- Encoder_plugin_error -- |
290 | | |
291 | 3 | case heif_suberror_Unsupported_bit_depth: |
292 | 3 | return "Unsupported bit depth"; |
293 | | |
294 | | // --- Encoding_error -- |
295 | | |
296 | 0 | case heif_suberror_Cannot_write_output_data: |
297 | 0 | return "Cannot write output data"; |
298 | 0 | case heif_suberror_Encoder_initialization: |
299 | 0 | return "Initialization problem"; |
300 | 0 | case heif_suberror_Encoder_encoding: |
301 | 0 | return "Encoding problem"; |
302 | 0 | case heif_suberror_Encoder_cleanup: |
303 | 0 | return "Cleanup problem"; |
304 | 0 | case heif_suberror_Too_many_regions: |
305 | 0 | return "Too many regions (>255) in an 'rgan' item."; |
306 | | |
307 | | // --- Plugin_loading_error --- |
308 | | |
309 | 0 | case heif_suberror_Plugin_loading_error: |
310 | 0 | return "Plugin file cannot be loaded"; |
311 | 0 | case heif_suberror_Plugin_is_not_loaded: |
312 | 0 | return "Trying to remove a plugin that is not loaded"; |
313 | 0 | case heif_suberror_Cannot_read_plugin_directory: |
314 | 0 | return "Error while scanning the directory for plugins"; |
315 | 39 | case heif_suberror_No_matching_decoder_installed: |
316 | | #if ENABLE_PLUGIN_LOADING |
317 | | return "No decoding plugin installed for this compression format"; |
318 | | #else |
319 | 39 | return "Support for this compression format has not been built in"; |
320 | 136k | #endif |
321 | 136k | } |
322 | | |
323 | 136k | assert(false); |
324 | 0 | return cUnknownError; |
325 | 0 | } |
326 | | |
327 | | |
328 | | heif_error Error::error_struct(ErrorBuffer* error_buffer) const |
329 | 275k | { |
330 | 275k | if (error_buffer) { |
331 | 199k | if (error_code == heif_error_Ok) { |
332 | 117k | error_buffer->set_success(); |
333 | 117k | } |
334 | 82.6k | else { |
335 | 82.6k | std::stringstream sstr; |
336 | 82.6k | sstr << get_error_string(error_code) << ": " |
337 | 82.6k | << get_error_string(sub_error_code); |
338 | 82.6k | if (!message.empty()) { |
339 | 59.9k | sstr << ": " << message; |
340 | 59.9k | } |
341 | | |
342 | 82.6k | error_buffer->set_error(sstr.str()); |
343 | 82.6k | } |
344 | 199k | } |
345 | | |
346 | 275k | heif_error err; |
347 | 275k | err.code = error_code; |
348 | 275k | err.subcode = sub_error_code; |
349 | 275k | if (error_buffer) { |
350 | 199k | err.message = error_buffer->get_error(); |
351 | 199k | } |
352 | 76.2k | else { |
353 | 76.2k | err.message = cUnknownError; |
354 | 76.2k | } |
355 | 275k | return err; |
356 | 275k | } |