From 74315ca990f0ce055a1010735ea1db3243e1bd99 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Fri, 11 May 2012 20:41:05 +1000 Subject: [PATCH] WIP context objects --- Makefile.PL | 2 +- context.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ error.c | 95 ++++++++++++++++++++++++++++++-------------------- imager.h | 4 +++ imageri.h | 11 ++++++ imdatatypes.h | 2 ++ imext.h | 1 - immacros.h | 8 +++++ 8 files changed, 180 insertions(+), 39 deletions(-) create mode 100644 context.c diff --git a/Makefile.PL b/Makefile.PL index 0f7a98bb..926e1761 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -159,7 +159,7 @@ my $OSDEF = "-DOS_$^O"; if ($^O eq 'hpux') { $OSLIBS .= ' -ldld'; } if (defined $Config{'d_dlsymun'}) { $OSDEF .= ' -DDLSYMUN'; } -my @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o +my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o log.o gaussian.o conv.o pnm.o raw.o feat.o font.o combine.o filters.o dynaload.o stackmach.o datatypes.o regmach.o trans2.o quant.o error.o convert.o diff --git a/context.c b/context.c new file mode 100644 index 00000000..f4e7e2ac --- /dev/null +++ b/context.c @@ -0,0 +1,96 @@ +#include "imageri.h" + +/* +=item im_context_new() + +Create a new Imager context object. + +=cut +*/ + +im_context_t +im_context_new(void) { + im_context_t ctx = mymalloc(sizeof(im_context_struct)); + int i; + + ctx->error_sp = IM_ERROR_COUNT-1; + for (i = 0; i < IM_ERROR_COUNT; ++i) { + ctx->error_alloc[i] = 0; + ctx->error_stack[i].msg = NULL; + ctx->error_stack[i].code = 0; + } +#ifdef IMAGER_LOG + ctx->log_level = 0; + ctx->lg_file = NULL; +#endif + + return ctx; +} + +/* +=item im_context_delete(ctx) + +Release memory used by an Imager context object. + +=cut +*/ + +void +im_context_delete(im_context_t ctx) { + int i; + + for (i = 0; i < IM_ERROR_COUNT; ++i) { + if (ctx->error_stack[i].msg) + myfree(ctx->error_stack[i].msg); + } +#ifdef IMAGER_LOG + if (ctx->lg_file) + fclose(ctx->lg_file); +#endif +} + +/* +=item im_context_clone(ctx) + +Clone an Imager context object, returning the result. + +=cut +*/ + +im_context_t +im_context_clone(im_context_t ctx) { + im_context_t nctx = mymalloc(sizeof(im_context_struct)); + int i; + + nctx->error_sp = ctx->error_sp; + for (i = 0; i < IM_ERROR_COUNT; ++i) { + if (ctx->error_stack[i].msg) { + size_t sz = ctx->error_alloc[i]; + nctx->error_alloc[i] = sz; + nctx->error_stack[i].msg = mymalloc(sz); + memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz); + } + else { + nctx->error_alloc[i] = 0; + nctx->error_stack[i].msg = NULL; + } + nctx->error_stack[i].code = ctx->error_stack[i].code; + } +#ifdef IMAGER_LOG + nctx->log_level = ctx->log_level; + if (ctx->lg_file) { + /* disable buffering, this isn't perfect */ + setvbuf(ctx->lg_file, NULL, _IONBF, 0); + + /* clone that and disable buffering some more */ + nctx->lg_file = fdopen(fileno(ctx->lg_file), "a"); + if (nctx->lg_file) + setvbuf(nctx->lg_file, NULL, _IONBF, 0); + } + else { + ctx->lg_file = NULL; + } +#endif + + return ctx; +} diff --git a/error.c b/error.c index 84785a2a..c234147c 100644 --- a/error.c +++ b/error.c @@ -61,25 +61,15 @@ C). The Perl level won't use all of this. =cut */ -#include "imager.h" +#include "imageri.h" #include #include -/* we never actually use the last item - it's the NULL terminator */ -#define ERRSTK 20 -static i_errmsg error_stack[ERRSTK]; -static int error_sp = ERRSTK - 1; -/* we track the amount of space used each string, so we don't reallocate - space unless we need to. - This also means that a memory tracking library may see the memory - allocated for this as a leak. */ -static int error_space[ERRSTK]; - +#if 0 static i_error_cb error_cb; static i_failed_cb failed_cb; static int failures_fatal; static char *argv0; - /* =item i_set_argv0(char const *program) @@ -157,6 +147,8 @@ i_failed_cb i_set_failed_cb(i_failed_cb cb) { return old; } +#endif + /* =item i_errors() @@ -165,8 +157,12 @@ terminated by a NULL pointer. The highest level message is first. =cut */ -i_errmsg *i_errors() { - return error_stack + error_sp; +i_errmsg *im_errors(im_context_t ctx) { + return ctx->error_stack + ctx->error_sp; +} + +i_errmsg *i_errors(void) { + return im_errors(im_get_context()); } /* @@ -192,19 +188,26 @@ Called by any Imager function before doing any other processing. =cut */ -void i_clear_error() { + +void +im_clear_error(im_context_t ctx) { #ifdef IMAGER_DEBUG_MALLOC int i; - for (i = 0; i < ERRSTK; ++i) { - if (error_space[i]) { - myfree(error_stack[i].msg); - error_stack[i].msg = NULL; - error_space[i] = 0; + for (i = 0; i < IM_ERROR_COUNT; ++i) { + if (ctx->error_space[i]) { + myfree(ctx->error_stack[i].msg); + ctx->error_stack[i].msg = NULL; + ctx->error_space[i] = 0; } } #endif - error_sp = ERRSTK-1; + ctx->error_sp = IM_ERROR_COUNT-1; +} + +void +i_clear_error(void) { + im_clear_error(im_get_context()); } /* @@ -221,29 +224,32 @@ error handling is calling function that does.). =cut */ -void i_push_error(int code, char const *msg) { +void +im_push_error(im_context_t ctx, int code, char const *msg) { size_t size = strlen(msg)+1; - if (error_sp <= 0) + if (ctx->error_sp <= 0) /* bad, bad programmer */ return; - --error_sp; - if (error_space[error_sp] < size) { - if (error_stack[error_sp].msg) - myfree(error_stack[error_sp].msg); + --ctx->error_sp; + if (ctx->error_alloc[ctx->error_sp] < size) { + if (ctx->error_stack[ctx->error_sp].msg) + myfree(ctx->error_stack[ctx->error_sp].msg); /* memory allocated on the following line is only ever released when we need a bigger string */ /* size is size (len+1) of an existing string, overflow would mean the system is broken anyway */ - error_stack[error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */ - error_space[error_sp] = size; + ctx->error_stack[ctx->error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */ + ctx->error_alloc[ctx->error_sp] = size; } - strcpy(error_stack[error_sp].msg, msg); - error_stack[error_sp].code = code; + strcpy(ctx->error_stack[ctx->error_sp].msg, msg); + ctx->error_stack[ctx->error_sp].code = code; +} - if (error_cb) - error_cb(code, msg); +void +i_push_error(int code, char const *msg) { + im_push_error(im_get_context(), code, msg); } /* @@ -258,7 +264,8 @@ Does not support perl specific format codes. =cut */ -void i_push_errorvf(int code, char const *fmt, va_list ap) { +void +im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list ap) { char buf[1024]; #if defined(IMAGER_VSNPRINTF) vsnprintf(buf, sizeof(buf), fmt, ap); @@ -271,7 +278,12 @@ void i_push_errorvf(int code, char const *fmt, va_list ap) { */ vsprintf(buf, fmt, ap); #endif - i_push_error(code, buf); + im_push_error(ctx, code, buf); +} + +void +i_push_errorvf(int code, char const *fmt, va_list ap) { + im_push_errorvf(im_get_context(), code, fmt, ap); } /* @@ -285,13 +297,22 @@ Does not support perl specific format codes. =cut */ -void i_push_errorf(int code, char const *fmt, ...) { +void +i_push_errorf(int code, char const *fmt, ...) { va_list ap; va_start(ap, fmt); i_push_errorvf(code, fmt, ap); va_end(ap); } +void +im_push_errorf(im_context_t ctx, int code, char const *fmt, ...) { + va_list ap; + va_start(ap, fmt); + im_push_errorvf(ctx, code, fmt, ap); + va_end(ap); +} + #ifdef IMAGER_I_FAILED #error "This isn't used and is untested" @@ -369,7 +390,7 @@ void im_assert_fail(char const *file, int line, char const *message) { fprintf(stderr, "Assertion failed line %d file %s: %s\n", line, file, message); - exit(EXIT_FAILURE); + abort(); } /* diff --git a/imager.h b/imager.h index aba1399b..b2849a00 100644 --- a/imager.h +++ b/imager.h @@ -452,6 +452,10 @@ extern int i_gsampf_bg(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samples, int out_channels, i_fcolor const *bg); +extern im_context_t (*im_get_context)(void); + +#define aIMCTX (im_get_context()) + #include "imio.h" #endif diff --git a/imageri.h b/imageri.h index 347e2abd..0e9815e9 100644 --- a/imageri.h +++ b/imageri.h @@ -111,4 +111,15 @@ i_img_dim i_abs(i_img_dim x); #define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071) +#define IM_ERROR_COUNT 20 +typedef struct im_context_tag { + int error_sp; + size_t error_alloc[IM_ERROR_COUNT]; + i_errmsg error_stack[IM_ERROR_COUNT]; +#ifdef IMAGER_LOG + int log_level; + FILE *lg_file; +#endif +} im_context_struct; + #endif diff --git a/imdatatypes.h b/imdatatypes.h index d9ad0eb4..1115883c 100644 --- a/imdatatypes.h +++ b/imdatatypes.h @@ -6,6 +6,8 @@ #define MAXCHANNELS 4 +typedef struct im_context_tag *im_context_t; + /* used for palette indices in some internal code (which might be exposed at some point */ diff --git a/imext.h b/imext.h index 8c42b903..1e4bccb6 100644 --- a/imext.h +++ b/imext.h @@ -262,5 +262,4 @@ extern im_ext_funcs *imager_function_ext_table; #define mm_log(x) #endif - #endif diff --git a/immacros.h b/immacros.h index 81ad3af0..269c3fc4 100644 --- a/immacros.h +++ b/immacros.h @@ -75,4 +75,12 @@ returns -1 and pushes an error. #define i_psampf(im, l, r, y, samps, chans, count) \ (((im)->i_f_psampf)((im), (l), (r), (y), (samps), (chans), (count))) +#ifdef IMAGER_NO_CONTEXT +#define dIMCTX im_context_t my_im_ctx = im_get_context() +#define dIMCTXa(a) im_context_t my_im_ctx = im_get_context() +#define aIMCTX my_im_ctx +#else +#define aIMCTX im_get_context() +#endif + #endif -- 2.39.5