]> git.imager.perl.org - imager.git/blame - context.c
properly initialize slot_alloc in context objects
[imager.git] / context.c
CommitLineData
9c852bc4 1#include "imageri.h"
28da39ee 2#include <stdio.h>
9c852bc4 3
fe634989
TC
4static im_slot_t slot_count;
5static im_slot_destroy_t *slot_destructors;
6static i_mutex_t slot_mutex;
7
9c852bc4
TC
8/*
9=item im_context_new()
10
11Create a new Imager context object.
12
13=cut
14*/
15
16im_context_t
17im_context_new(void) {
0e2999c7 18 im_context_t ctx = malloc(sizeof(im_context_struct));
9c852bc4
TC
19 int i;
20
fe634989
TC
21 if (!slot_mutex)
22 slot_mutex = i_mutex_new();
23
0e2999c7
TC
24 if (!ctx)
25 return NULL;
26
9c852bc4
TC
27 ctx->error_sp = IM_ERROR_COUNT-1;
28 for (i = 0; i < IM_ERROR_COUNT; ++i) {
29 ctx->error_alloc[i] = 0;
30 ctx->error_stack[i].msg = NULL;
31 ctx->error_stack[i].code = 0;
32 }
33#ifdef IMAGER_LOG
34 ctx->log_level = 0;
35 ctx->lg_file = NULL;
36#endif
a482206e
TC
37 ctx->max_width = 0;
38 ctx->max_height = 0;
0e2999c7 39 ctx->max_bytes = DEF_BYTES_LIMIT;
9c852bc4 40
a1f32c0c
TC
41 ctx->slot_alloc = slot_count;
42 ctx->slots = calloc(sizeof(void *), ctx->slot_alloc);
fe634989
TC
43 if (!ctx->slots) {
44 free(ctx);
45 return NULL;
46 }
47
28da39ee
TC
48 ctx->refcount = 1;
49
50#ifdef IMAGER_TRACE_CONTEXT
51 fprintf(stderr, "im_context: created %p\n", ctx);
52#endif
53
fe634989 54
9c852bc4
TC
55 return ctx;
56}
57
58/*
28da39ee 59=item im_context_refinc(ctx, where)
934c0e37
TC
60X<im_context_refinc API>
61=section Context objects
62=synopsis im_context_refinc(aIMCTX, "a description");
28da39ee
TC
63
64Add a new reference to the context.
65
66=cut
67*/
68
69void
70im_context_refinc(im_context_t ctx, const char *where) {
71 ++ctx->refcount;
72
73#ifdef IMAGER_TRACE_CONTEXT
74 fprintf(stderr, "im_context:%s: refinc %p (count now %lu)\n", where,
75 ctx, (unsigned long)ctx->refcount);
76#endif
77}
78
79/*
934c0e37
TC
80=item im_context_refdec(ctx, where)
81X<im_context_refdec API>
82=section Context objects
83=synopsis im_context_refdec(aIMCTX, "a description");
9c852bc4 84
934c0e37
TC
85Remove a reference to the context, releasing it if all references have
86been removed.
9c852bc4
TC
87
88=cut
89*/
90
91void
28da39ee 92im_context_refdec(im_context_t ctx, const char *where) {
9c852bc4 93 int i;
fe634989 94 im_slot_t slot;
9c852bc4 95
28da39ee
TC
96 im_assert(ctx->refcount > 0);
97
98 --ctx->refcount;
99
100#ifdef IMAGER_TRACE_CONTEXT
101 fprintf(stderr, "im_context:%s: delete %p (count now %lu)\n", where,
102 ctx, (unsigned long)ctx->refcount);
103#endif
104
105 if (ctx->refcount != 0)
106 return;
107
fe634989
TC
108 for (slot = 0; slot < ctx->slot_alloc; ++slot) {
109 if (ctx->slots[slot] && slot_destructors[slot])
110 slot_destructors[slot](ctx->slots[slot]);
111 }
112
113 free(ctx->slots);
114
9c852bc4
TC
115 for (i = 0; i < IM_ERROR_COUNT; ++i) {
116 if (ctx->error_stack[i].msg)
117 myfree(ctx->error_stack[i].msg);
118 }
119#ifdef IMAGER_LOG
120 if (ctx->lg_file)
121 fclose(ctx->lg_file);
122#endif
0e2999c7
TC
123
124 free(ctx);
9c852bc4
TC
125}
126
127/*
128=item im_context_clone(ctx)
129
130Clone an Imager context object, returning the result.
131
132=cut
133*/
134
135im_context_t
28da39ee 136im_context_clone(im_context_t ctx, const char *where) {
0e2999c7 137 im_context_t nctx = malloc(sizeof(im_context_struct));
9c852bc4
TC
138 int i;
139
0e2999c7
TC
140 if (!nctx)
141 return NULL;
142
a1f32c0c
TC
143 nctx->slot_alloc = slot_count;
144 nctx->slots = calloc(sizeof(void *), ctx->slot_alloc);
fe634989
TC
145 if (!nctx->slots) {
146 free(nctx);
147 return NULL;
148 }
fe634989 149
9c852bc4
TC
150 nctx->error_sp = ctx->error_sp;
151 for (i = 0; i < IM_ERROR_COUNT; ++i) {
152 if (ctx->error_stack[i].msg) {
153 size_t sz = ctx->error_alloc[i];
154 nctx->error_alloc[i] = sz;
155 nctx->error_stack[i].msg = mymalloc(sz);
156 memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz);
157 }
158 else {
159 nctx->error_alloc[i] = 0;
160 nctx->error_stack[i].msg = NULL;
161 }
162 nctx->error_stack[i].code = ctx->error_stack[i].code;
163 }
164#ifdef IMAGER_LOG
165 nctx->log_level = ctx->log_level;
166 if (ctx->lg_file) {
167 /* disable buffering, this isn't perfect */
168 setvbuf(ctx->lg_file, NULL, _IONBF, 0);
169
170 /* clone that and disable buffering some more */
171 nctx->lg_file = fdopen(fileno(ctx->lg_file), "a");
172 if (nctx->lg_file)
173 setvbuf(nctx->lg_file, NULL, _IONBF, 0);
174 }
175 else {
a482206e 176 nctx->lg_file = NULL;
9c852bc4
TC
177 }
178#endif
a482206e
TC
179 nctx->max_width = ctx->max_width;
180 nctx->max_height = ctx->max_height;
181 nctx->max_bytes = ctx->max_bytes;
fe634989 182
28da39ee 183 nctx->refcount = 1;
9c852bc4 184
28da39ee
TC
185#ifdef IMAGER_TRACE_CONTEXT
186 fprintf(stderr, "im_context:%s: cloned %p to %p\n", where, ctx, nctx);
187#endif
188
189 return nctx;
9c852bc4 190}
fe634989
TC
191
192/*
61495d69 193=item im_context_slot_new(destructor, where)
fe634989
TC
194
195Allocate a new context-local-storage slot.
196
197=cut
198*/
199
200im_slot_t
61495d69 201im_context_slot_new(im_slot_destroy_t destructor, const char *where) {
fe634989
TC
202 im_slot_t new_slot;
203 im_slot_destroy_t *new_destructors;
204 if (!slot_mutex)
205 slot_mutex = i_mutex_new();
206
207 i_mutex_lock(slot_mutex);
208
209 new_slot = slot_count++;
210 new_destructors = realloc(slot_destructors, sizeof(void *) * slot_count);
211 if (!new_destructors)
212 i_fatal(1, "Cannot allocate memory for slot destructors");
213 slot_destructors = new_destructors;
214
215 slot_destructors[new_slot] = destructor;
216
61495d69
TC
217#ifdef IMAGER_TRACE_CONTEXT
218 fprintf(stderr, "im_context: slot %d allocated for %s\n",
219 (int)new_slot, where);
220#endif
221
fe634989
TC
222 i_mutex_unlock(slot_mutex);
223
224 return new_slot;
225}
226
227/*
228=item im_context_slot_set(slot, value)
229
230Set the value of a slot.
231
232Returns true on success.
233
234Aborts if the slot supplied is invalid.
235
236If reallocation of slot storage fails, returns false.
237
238=cut
239*/
240
241int
242im_context_slot_set(im_context_t ctx, im_slot_t slot, void *value) {
243 if (slot < 0 || slot >= slot_count) {
244 fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
245 (int)slot, (int)slot_count-1);
246 abort();
247 }
248
249 if (slot >= ctx->slot_alloc) {
250 ssize_t i;
251 size_t new_alloc = slot_count;
252 void **new_slots = realloc(ctx->slots, sizeof(void *) * new_alloc);
253
254 if (!new_slots)
255 return 0;
256
257 for (i = ctx->slot_alloc; i < new_alloc; ++i)
258 new_slots[i] = NULL;
259
260 ctx->slots = new_slots;
261 ctx->slot_alloc = new_alloc;
262 }
263
264 ctx->slots[slot] = value;
265
61495d69
TC
266#ifdef IMAGER_TRACE_CONTEXT
267 fprintf(stderr, "im_context: ctx %p slot %d set to %p\n",
268 ctx, (int)slot, value);
269#endif
270
fe634989
TC
271 return 1;
272}
273
274/*
275=item im_context_slot_get(ctx, slot)
276
277Retrieve the value previously stored in the given slot of the context
278object.
279
280=cut
281*/
282
283void *
284im_context_slot_get(im_context_t ctx, im_slot_t slot) {
285 if (slot < 0 || slot >= slot_count) {
286 fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
287 (int)slot, (int)slot_count-1);
288 abort();
289 }
290
291 if (slot >= ctx->slot_alloc)
292 return NULL;
293
61495d69
TC
294#ifdef IMAGER_TRACE_CONTEXT
295 fprintf(stderr, "im_context: ctx %p slot %d retrieved as %p\n",
296 ctx, (int)slot, ctx->slots[slot]);
297#endif
298
fe634989
TC
299 return ctx->slots[slot];
300}