4 static im_slot_t slot_count;
5 static im_slot_destroy_t *slot_destructors;
6 static i_mutex_t slot_mutex;
11 Create a new Imager context object.
17 im_context_new(void) {
18 im_context_t ctx = malloc(sizeof(im_context_struct));
22 slot_mutex = i_mutex_new();
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;
39 ctx->max_bytes = DEF_BYTES_LIMIT;
41 ctx->slots = calloc(sizeof(void *), slot_count);
49 #ifdef IMAGER_TRACE_CONTEXT
50 fprintf(stderr, "im_context: created %p\n", ctx);
58 =item im_context_refinc(ctx, where)
59 X<im_context_refinc API>
60 =section Context objects
61 =synopsis im_context_refinc(aIMCTX, "a description");
63 Add a new reference to the context.
69 im_context_refinc(im_context_t ctx, const char *where) {
72 #ifdef IMAGER_TRACE_CONTEXT
73 fprintf(stderr, "im_context:%s: refinc %p (count now %lu)\n", where,
74 ctx, (unsigned long)ctx->refcount);
79 =item im_context_refdec(ctx, where)
80 X<im_context_refdec API>
81 =section Context objects
82 =synopsis im_context_refdec(aIMCTX, "a description");
84 Remove a reference to the context, releasing it if all references have
91 im_context_refdec(im_context_t ctx, const char *where) {
95 im_assert(ctx->refcount > 0);
99 #ifdef IMAGER_TRACE_CONTEXT
100 fprintf(stderr, "im_context:%s: delete %p (count now %lu)\n", where,
101 ctx, (unsigned long)ctx->refcount);
104 if (ctx->refcount != 0)
107 for (slot = 0; slot < ctx->slot_alloc; ++slot) {
108 if (ctx->slots[slot] && slot_destructors[slot])
109 slot_destructors[slot](ctx->slots[slot]);
114 for (i = 0; i < IM_ERROR_COUNT; ++i) {
115 if (ctx->error_stack[i].msg)
116 myfree(ctx->error_stack[i].msg);
120 fclose(ctx->lg_file);
127 =item im_context_clone(ctx)
129 Clone an Imager context object, returning the result.
135 im_context_clone(im_context_t ctx, const char *where) {
136 im_context_t nctx = malloc(sizeof(im_context_struct));
142 nctx->slots = calloc(sizeof(void *), slot_count);
147 nctx->slot_alloc = slot_count;
149 nctx->error_sp = ctx->error_sp;
150 for (i = 0; i < IM_ERROR_COUNT; ++i) {
151 if (ctx->error_stack[i].msg) {
152 size_t sz = ctx->error_alloc[i];
153 nctx->error_alloc[i] = sz;
154 nctx->error_stack[i].msg = mymalloc(sz);
155 memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz);
158 nctx->error_alloc[i] = 0;
159 nctx->error_stack[i].msg = NULL;
161 nctx->error_stack[i].code = ctx->error_stack[i].code;
164 nctx->log_level = ctx->log_level;
166 /* disable buffering, this isn't perfect */
167 setvbuf(ctx->lg_file, NULL, _IONBF, 0);
169 /* clone that and disable buffering some more */
170 nctx->lg_file = fdopen(fileno(ctx->lg_file), "a");
172 setvbuf(nctx->lg_file, NULL, _IONBF, 0);
175 nctx->lg_file = NULL;
178 nctx->max_width = ctx->max_width;
179 nctx->max_height = ctx->max_height;
180 nctx->max_bytes = ctx->max_bytes;
184 #ifdef IMAGER_TRACE_CONTEXT
185 fprintf(stderr, "im_context:%s: cloned %p to %p\n", where, ctx, nctx);
192 =item im_context_slot_new(destructor, where)
194 Allocate a new context-local-storage slot.
200 im_context_slot_new(im_slot_destroy_t destructor, const char *where) {
202 im_slot_destroy_t *new_destructors;
204 slot_mutex = i_mutex_new();
206 i_mutex_lock(slot_mutex);
208 new_slot = slot_count++;
209 new_destructors = realloc(slot_destructors, sizeof(void *) * slot_count);
210 if (!new_destructors)
211 i_fatal(1, "Cannot allocate memory for slot destructors");
212 slot_destructors = new_destructors;
214 slot_destructors[new_slot] = destructor;
216 #ifdef IMAGER_TRACE_CONTEXT
217 fprintf(stderr, "im_context: slot %d allocated for %s\n",
218 (int)new_slot, where);
221 i_mutex_unlock(slot_mutex);
227 =item im_context_slot_set(slot, value)
229 Set the value of a slot.
231 Returns true on success.
233 Aborts if the slot supplied is invalid.
235 If reallocation of slot storage fails, returns false.
241 im_context_slot_set(im_context_t ctx, im_slot_t slot, void *value) {
242 if (slot < 0 || slot >= slot_count) {
243 fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
244 (int)slot, (int)slot_count-1);
248 if (slot >= ctx->slot_alloc) {
250 size_t new_alloc = slot_count;
251 void **new_slots = realloc(ctx->slots, sizeof(void *) * new_alloc);
256 for (i = ctx->slot_alloc; i < new_alloc; ++i)
259 ctx->slots = new_slots;
260 ctx->slot_alloc = new_alloc;
263 ctx->slots[slot] = value;
265 #ifdef IMAGER_TRACE_CONTEXT
266 fprintf(stderr, "im_context: ctx %p slot %d set to %p\n",
267 ctx, (int)slot, value);
274 =item im_context_slot_get(ctx, slot)
276 Retrieve the value previously stored in the given slot of the context
283 im_context_slot_get(im_context_t ctx, im_slot_t slot) {
284 if (slot < 0 || slot >= slot_count) {
285 fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
286 (int)slot, (int)slot_count-1);
290 if (slot >= ctx->slot_alloc)
293 #ifdef IMAGER_TRACE_CONTEXT
294 fprintf(stderr, "im_context: ctx %p slot %d retrieved as %p\n",
295 ctx, (int)slot, ctx->slots[slot]);
298 return ctx->slots[slot];