WIP context objects
authorTony Cook <tony@develop-help.com>
Fri, 11 May 2012 10:41:05 +0000 (20:41 +1000)
committerTony Cook <tony@develop-help.com>
Tue, 14 Aug 2012 09:58:15 +0000 (19:58 +1000)
Makefile.PL
context.c [new file with mode: 0644]
error.c
imager.h
imageri.h
imdatatypes.h
imext.h
immacros.h

index 0f7a98b..926e176 100644 (file)
@@ -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 (file)
index 0000000..f4e7e2a
--- /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 84785a2..c234147 100644 (file)
--- 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 <stdio.h>
 #include <stdlib.h>
 
-/* 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();
 }
 
 /*
index aba1399..b2849a0 100644 (file)
--- 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
index 347e2ab..0e9815e 100644 (file)
--- 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
index d9ad0eb..1115883 100644 (file)
@@ -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 8c42b90..1e4bccb 100644 (file)
--- a/imext.h
+++ b/imext.h
@@ -262,5 +262,4 @@ extern im_ext_funcs *imager_function_ext_table;
 #define mm_log(x)
 #endif
 
-
 #endif
index 81ad3af..269c3fc 100644 (file)
@@ -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