Revert manifest to default one
[external/cups.git] / filter / error.c
1 /*
2  * "$Id: error.c 9771 2011-05-12 05:21:56Z mike $"
3  *
4  *   Raster error handling for CUPS.
5  *
6  *   Copyright 2007-2011 by Apple Inc.
7  *   Copyright 2007 by Easy Software Products.
8  *
9  *   These coded instructions, statements, and computer programs are the
10  *   property of Apple Inc. and are protected by Federal copyright
11  *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
12  *   which should have been included with this file.  If this file is
13  *   file is missing or damaged, see the license at "http://www.cups.org/".
14  *
15  *   This file is subject to the Apple OS-Developed Software exception.
16  *
17  * Contents:
18  *
19  *   _cupsRasterAddError()   - Add an error message to the error buffer.
20  *   _cupsRasterClearError() - Clear the error buffer.
21  *   cupsRasterErrorString() - Return the last error from a raster function.
22  *   get_error_buffer()      - Return a pointer to thread local storage.
23  *   raster_init()           - Initialize error buffer once.
24  *   raster_destructor()     - Free memory allocated by get_error_buffer().
25  */
26
27 /*
28  * Include necessary headers...
29  */
30
31 #include "image-private.h"
32 #include <stdarg.h>
33
34
35 /*
36  * Local structures...
37  */
38
39 typedef struct _cups_raster_error_s     /**** Error buffer structure ****/
40 {
41   char  *start,                         /* Start of buffer */
42         *current,                       /* Current position in buffer */
43         *end;                           /* End of buffer */
44 } _cups_raster_error_t;
45
46
47 /*
48  * Local functions...
49  */
50
51 static _cups_raster_error_t     *get_error_buffer(void);
52
53
54 /*
55  * '_cupsRasterAddError()' - Add an error message to the error buffer.
56  */
57
58 void
59 _cupsRasterAddError(const char *f,      /* I - Printf-style error message */
60                     ...)                /* I - Additional arguments as needed */
61 {
62   _cups_raster_error_t  *buf = get_error_buffer();
63                                         /* Error buffer */
64   va_list       ap;                     /* Pointer to additional arguments */
65   char          s[2048];                /* Message string */
66   size_t        bytes;                  /* Bytes in message string */
67
68
69   va_start(ap, f);
70   bytes = vsnprintf(s, sizeof(s), f, ap);
71   va_end(ap);
72
73   if (bytes <= 0)
74     return;
75
76   bytes ++;
77
78   if (bytes >= sizeof(s))
79     return;
80
81   if (bytes > (size_t)(buf->end - buf->current))
82   {
83    /*
84     * Allocate more memory...
85     */
86
87     char        *temp;                  /* New buffer */
88     size_t      size;                   /* Size of buffer */
89
90
91     size = buf->end - buf->start + 2 * bytes + 1024;
92
93     if (buf->start)
94       temp = realloc(buf->start, size);
95     else
96       temp = malloc(size);
97
98     if (!temp)
99       return;
100
101    /*
102     * Update pointers...
103     */
104
105     buf->end     = temp + size;
106     buf->current = temp + (buf->current - buf->start);
107     buf->start   = temp;
108   }
109
110  /*
111   * Append the message to the end of the current string...
112   */
113
114   memcpy(buf->current, s, bytes);
115   buf->current += bytes - 1;
116 }
117
118
119 /*
120  * '_cupsRasterClearError()' - Clear the error buffer.
121  */
122
123 void
124 _cupsRasterClearError(void)
125 {
126   _cups_raster_error_t  *buf = get_error_buffer();
127                                         /* Error buffer */
128
129
130   buf->current = buf->start;
131
132   if (buf->start)
133     *(buf->start) = '\0';
134 }
135
136
137 /*
138  * 'cupsRasterErrorString()' - Return the last error from a raster function.
139  *
140  * If there are no recent errors, NULL is returned.
141  *
142  * @since CUPS 1.3/Mac OS X 10.5@
143  */
144
145 const char *                            /* O - Last error */
146 cupsRasterErrorString(void)
147 {
148   _cups_raster_error_t  *buf = get_error_buffer();
149                                         /* Error buffer */
150
151
152   if (buf->current == buf->start)
153     return (NULL);
154   else
155     return (buf->start);
156 }
157
158
159 #ifdef HAVE_PTHREAD_H
160 /*
161  * Implement per-thread globals...
162  */
163
164 #  include <pthread.h>
165
166
167 /*
168  * Local globals...
169  */
170
171 static pthread_key_t    raster_key = -1;
172                                         /* Thread local storage key */
173 static pthread_once_t   raster_key_once = PTHREAD_ONCE_INIT;
174                                         /* One-time initialization object */
175
176
177 /*
178  * Local functions...
179  */
180
181 static void     raster_init(void);
182 static void     raster_destructor(void *value);
183
184
185 /*
186  * 'get_error_buffer()' - Return a pointer to thread local storage.
187  */
188
189 _cups_raster_error_t *                  /* O - Pointer to error buffer */
190 get_error_buffer(void)
191 {
192   _cups_raster_error_t *buf;            /* Pointer to error buffer */
193
194
195  /*
196   * Initialize the global data exactly once...
197   */
198
199   DEBUG_puts("get_error_buffer()");
200
201   pthread_once(&raster_key_once, raster_init);
202
203  /*
204   * See if we have allocated the data yet...
205   */
206
207   if ((buf = (_cups_raster_error_t *)pthread_getspecific(raster_key))
208           == NULL)
209   {
210     DEBUG_puts("get_error_buffer: allocating memory for thread...");
211
212    /*
213     * No, allocate memory as set the pointer for the key...
214     */
215
216     buf = calloc(1, sizeof(_cups_raster_error_t));
217     pthread_setspecific(raster_key, buf);
218
219     DEBUG_printf(("    buf=%p\n", buf));
220   }
221
222  /*
223   * Return the pointer to the data...
224   */
225
226   return (buf);
227 }
228
229
230 /*
231  * 'raster_init()' - Initialize error buffer once.
232  */
233
234 static void
235 raster_init(void)
236 {
237   pthread_key_create(&raster_key, raster_destructor);
238
239   DEBUG_printf(("raster_init(): raster_key=%x(%u)\n", (unsigned)raster_key,
240                 (unsigned)raster_key));
241 }
242
243
244 /*
245  * 'raster_destructor()' - Free memory allocated by get_error_buffer().
246  */
247
248 static void
249 raster_destructor(void *value)          /* I - Data to free */
250 {
251   _cups_raster_error_t *buf = (_cups_raster_error_t *)value;
252                                         /* Error buffer */
253
254
255   DEBUG_printf(("raster_destructor(value=%p)\n", value));
256
257   if (buf->start)
258     free(buf->start);
259
260   free(value);
261 }
262
263
264 #else
265 /*
266  * Implement static globals...
267  */
268
269 /*
270  * 'get_error_buffer()' - Return a pointer to thread local storage.
271  */
272
273 _cups_raster_error_t *                  /* O - Pointer to error buffer */
274 get_error_buffer(void)
275 {
276   static _cups_raster_error_t buf = { 0, 0, 0 };
277                                         /* Error buffer */
278
279
280   return (&buf);
281 }
282 #endif /* HAVE_PTHREAD_H */
283
284
285 /*
286  * End of "$Id: error.c 9771 2011-05-12 05:21:56Z mike $".
287  */