ohmu
·
2026-10-15
1/*
2 * Copyright (c) 2014-2018 Hayaki Saito
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 * the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22#include "config.h"
23
24/* STDC_HEADERS */
25#include <stdio.h>
26#include <stdlib.h>
27
28#if HAVE_MEMORY_H
29# include <memory.h>
30#endif /* HAVE_MEMORY_H */
31#ifdef HAVE_STRING_H
32# include <string.h>
33#endif /* HAVE_STRING_H */
34#ifdef HAVE_ERRNO_H
35# include <errno.h>
36#endif /* HAVE_ERRNO_H */
37#ifdef HAVE_LIBCURL
38# include <curl/curl.h>
39#endif /* HAVE_LIBCURL */
40
41#include <sixel.h>
42#include "status.h"
43
44#define SIXEL_MESSAGE_OK ("succeeded")
45#define SIXEL_MESSAGE_FALSE ("unexpected error (SIXEL_FALSE)");
46#define SIXEL_MESSAGE_UNEXPECTED ("unexpected error")
47#define SIXEL_MESSAGE_INTERRUPTED ("interrupted by a signal")
48#define SIXEL_MESSAGE_BAD_ALLOCATION ("runtime error: bad allocation error")
49#define SIXEL_MESSAGE_BAD_ARGUMENT ("runtime error: bad argument detected")
50#define SIXEL_MESSAGE_BAD_INPUT ("runtime error: bad input detected")
51#define SIXEL_MESSAGE_BAD_INTEGER_OVERFLOW ("runtime error: integer overflow")
52#define SIXEL_MESSAGE_RUNTIME_ERROR ("runtime error")
53#define SIXEL_MESSAGE_LOGIC_ERROR ("logic error")
54#define SIXEL_MESSAGE_NOT_IMPLEMENTED ("feature error: not implemented")
55#define SIXEL_MESSAGE_FEATURE_ERROR ("feature error")
56#define SIXEL_MESSAGE_STBI_ERROR ("stb_image error")
57#define SIXEL_MESSAGE_STBIW_ERROR ("stb_image_write error")
58#define SIXEL_MESSAGE_JPEG_ERROR ("libjpeg error")
59#define SIXEL_MESSAGE_PNG_ERROR ("libpng error")
60#define SIXEL_MESSAGE_GDK_ERROR ("GDK error")
61#define SIXEL_MESSAGE_GD_ERROR ("GD error")
62
63
64static char g_buffer[1024] = { 0x0 };
65
66/* set detailed error message (thread-unsafe) */
67SIXELAPI void
68sixel_helper_set_additional_message(
69 const char /* in */ *message /* error message */
70)
71{
72 size_t len;
73
74 if (message == 0)
75 return;
76 len = strlen(message);
77 memcpy(g_buffer, message, len < sizeof(g_buffer) ? len: sizeof(g_buffer) - 1);
78 g_buffer[sizeof(g_buffer) - 1] = 0;
79}
80
81
82/* get detailed error message (thread-unsafe) */
83SIXELAPI char const *
84sixel_helper_get_additional_message(void)
85{
86 return g_buffer;
87}
88
89
90/* convert error status code int formatted string */
91SIXELAPI char const *
92sixel_helper_format_error(
93 SIXELSTATUS /* in */ status /* status code */
94)
95{
96 static char buffer[1024];
97 char const *error_string;
98 char *p;
99 size_t len;
100
101 switch (status & 0x1000) {
102 case SIXEL_OK:
103 switch (status) {
104 case SIXEL_INTERRUPTED:
105 error_string = SIXEL_MESSAGE_INTERRUPTED;
106 break;
107 case SIXEL_OK:
108 default:
109 error_string = SIXEL_MESSAGE_OK;
110 break;
111 }
112 break;
113 case SIXEL_FALSE:
114 switch (status & 0x1f00) {
115 case SIXEL_RUNTIME_ERROR:
116 switch (status) {
117 case SIXEL_BAD_ALLOCATION:
118 error_string = SIXEL_MESSAGE_BAD_ALLOCATION;
119 break;
120 case SIXEL_BAD_ARGUMENT:
121 error_string = SIXEL_MESSAGE_BAD_ARGUMENT;
122 break;
123 case SIXEL_BAD_INPUT:
124 error_string = SIXEL_MESSAGE_BAD_INPUT;
125 break;
126 case SIXEL_BAD_INTEGER_OVERFLOW:
127 error_string = SIXEL_MESSAGE_BAD_INTEGER_OVERFLOW;
128 break;
129 default:
130 error_string = SIXEL_MESSAGE_RUNTIME_ERROR;
131 break;
132 }
133 break;
134 case SIXEL_LOGIC_ERROR:
135 error_string = SIXEL_MESSAGE_LOGIC_ERROR;
136 break;
137 case SIXEL_FEATURE_ERROR:
138 switch (status) {
139 case SIXEL_NOT_IMPLEMENTED:
140 error_string = SIXEL_MESSAGE_NOT_IMPLEMENTED;
141 break;
142 default:
143 error_string = SIXEL_MESSAGE_FEATURE_ERROR;
144 break;
145 }
146 break;
147 case SIXEL_LIBC_ERROR:
148 p = strerror(errno);
149 len = strlen(p) + 1;
150 memcpy(buffer, p, len < sizeof(buffer) ? len: sizeof(buffer) - 1);
151 buffer[sizeof(buffer) - 1] = 0;
152 error_string = buffer;
153 break;
154#ifdef HAVE_LIBCURL
155 case SIXEL_CURL_ERROR:
156 error_string = curl_easy_strerror(status & 0xff);
157 break;
158#endif
159#ifdef HAVE_JPEG
160 case SIXEL_JPEG_ERROR:
161 error_string = SIXEL_MESSAGE_JPEG_ERROR;
162 break;
163#endif
164#ifdef HAVE_LIBPNG
165 case SIXEL_PNG_ERROR:
166 error_string = SIXEL_MESSAGE_PNG_ERROR;
167 break;
168#endif
169#ifdef HAVE_GDK_PIXBUF2
170 case SIXEL_GDK_ERROR:
171 error_string = SIXEL_MESSAGE_GDK_ERROR;
172 break;
173#endif
174#ifdef HAVE_GD
175 case SIXEL_GD_ERROR:
176 error_string = SIXEL_MESSAGE_GD_ERROR;
177 break;
178#endif
179 case SIXEL_STBI_ERROR:
180 error_string = SIXEL_MESSAGE_STBI_ERROR;
181 break;
182 case SIXEL_STBIW_ERROR:
183 error_string = SIXEL_MESSAGE_STBIW_ERROR;
184 break;
185 case SIXEL_FALSE:
186 error_string = SIXEL_MESSAGE_FALSE;
187 break;
188 default:
189 error_string = SIXEL_MESSAGE_UNEXPECTED;
190 break;
191 }
192 break;
193 default:
194 error_string = SIXEL_MESSAGE_UNEXPECTED;
195 break;
196 }
197 return error_string;
198}
199
200
201#if HAVE_TESTS
202static int
203test1(void)
204{
205 int nret = EXIT_FAILURE;
206 char const *message;
207
208 message = sixel_helper_format_error(SIXEL_OK);
209 if (strcmp(message, SIXEL_MESSAGE_OK) != 0) {
210 goto error;
211 }
212
213 message = sixel_helper_format_error(SIXEL_INTERRUPTED);
214 if (strcmp(message, SIXEL_MESSAGE_INTERRUPTED) != 0) {
215 goto error;
216 }
217 return EXIT_SUCCESS;
218error:
219 perror("test1");
220 return nret;
221}
222
223
224static int
225test2(void)
226{
227 int nret = EXIT_FAILURE;
228 char const *message;
229
230 message = sixel_helper_format_error(SIXEL_BAD_ALLOCATION);
231 if (strcmp(message, SIXEL_MESSAGE_BAD_ALLOCATION) != 0) {
232 goto error;
233 }
234
235 message = sixel_helper_format_error(SIXEL_BAD_ARGUMENT);
236 if (strcmp(message, SIXEL_MESSAGE_BAD_ARGUMENT) != 0) {
237 goto error;
238 }
239
240 message = sixel_helper_format_error(SIXEL_BAD_INPUT);
241 if (strcmp(message, SIXEL_MESSAGE_BAD_INPUT) != 0) {
242 goto error;
243 }
244
245 message = sixel_helper_format_error(SIXEL_RUNTIME_ERROR);
246 if (strcmp(message, SIXEL_MESSAGE_RUNTIME_ERROR) != 0) {
247 goto error;
248 }
249
250 message = sixel_helper_format_error(SIXEL_LOGIC_ERROR);
251 if (strcmp(message, SIXEL_MESSAGE_LOGIC_ERROR) != 0) {
252 goto error;
253 }
254
255 message = sixel_helper_format_error(SIXEL_NOT_IMPLEMENTED);
256 if (strcmp(message, SIXEL_MESSAGE_NOT_IMPLEMENTED) != 0) {
257 goto error;
258 }
259
260 message = sixel_helper_format_error(SIXEL_FEATURE_ERROR);
261 if (strcmp(message, SIXEL_MESSAGE_FEATURE_ERROR) != 0) {
262 goto error;
263 }
264
265 message = sixel_helper_format_error(SIXEL_LIBC_ERROR);
266 if (strcmp(message, SIXEL_MESSAGE_UNEXPECTED) == 0) {
267 goto error;
268 }
269
270#ifdef HAVE_LIBCURL
271 message = sixel_helper_format_error(SIXEL_CURL_ERROR);
272 if (strcmp(message, SIXEL_MESSAGE_UNEXPECTED) == 0) {
273 goto error;
274 }
275#endif
276
277#if HAVE_JPEG
278 message = sixel_helper_format_error(SIXEL_JPEG_ERROR);
279 if (strcmp(message, SIXEL_MESSAGE_JPEG_ERROR) != 0) {
280 goto error;
281 }
282#endif
283
284#if HAVE_LIBPNG
285 message = sixel_helper_format_error(SIXEL_PNG_ERROR);
286 if (strcmp(message, SIXEL_MESSAGE_PNG_ERROR) != 0) {
287 goto error;
288 }
289#endif
290
291#if HAVE_GD
292 message = sixel_helper_format_error(SIXEL_GD_ERROR);
293 if (strcmp(message, SIXEL_MESSAGE_GD_ERROR) != 0) {
294 goto error;
295 }
296#endif
297
298#if HAVE_GDK_PIXBUF2
299 message = sixel_helper_format_error(SIXEL_GDK_ERROR);
300 if (strcmp(message, SIXEL_MESSAGE_GDK_ERROR) != 0) {
301 goto error;
302 }
303#endif
304
305 message = sixel_helper_format_error(SIXEL_STBI_ERROR);
306 if (strcmp(message, SIXEL_MESSAGE_STBI_ERROR) != 0) {
307 goto error;
308 }
309
310 message = sixel_helper_format_error(SIXEL_STBIW_ERROR);
311 if (strcmp(message, SIXEL_MESSAGE_STBIW_ERROR) != 0) {
312 goto error;
313 }
314
315 return EXIT_SUCCESS;
316error:
317 perror("test2");
318 return nret;
319}
320
321
322SIXELAPI int
323sixel_status_tests_main(void)
324{
325 int nret = EXIT_FAILURE;
326 size_t i;
327 typedef int (* testcase)(void);
328
329 static testcase const testcases[] = {
330 test1,
331 test2,
332 };
333
334 for (i = 0; i < sizeof(testcases) / sizeof(testcase); ++i) {
335 nret = testcases[i]();
336 if (nret != EXIT_SUCCESS) {
337 goto error;
338 }
339 }
340
341 nret = EXIT_SUCCESS;
342
343error:
344 return nret;
345}
346#endif /* HAVE_TESTS */
347
348/* emacs Local Variables: */
349/* emacs mode: c */
350/* emacs tab-width: 4 */
351/* emacs indent-tabs-mode: nil */
352/* emacs c-basic-offset: 4 */
353/* emacs End: */
354/* vim: set expandtab ts=4 sts=4 sw=4 : */
355/* EOF */