]> granicus.if.org Git - graphviz/commitdiff
saving experimental code
authorellson <devnull@localhost>
Mon, 25 Aug 2008 04:53:51 +0000 (04:53 +0000)
committerellson <devnull@localhost>
Mon, 25 Aug 2008 04:53:51 +0000 (04:53 +0000)
lib/gvc/gvdevice.c

index 30138f13fef301f566acb51fcb1eca5dd1d55695..03519e3f0a47f639586b57fa87e82138c6421840 100644 (file)
@@ -15,8 +15,6 @@
 **********************************************************/
 
 /*
- *  graphics code generator wrapper
- *
  *  This library forms the socket for run-time loadable device plugins.  
  */
 
@@ -24,8 +22,8 @@
 #include "config.h"
 #endif
 
-/* experimenting with in-memory compression so as to write compressed files to channels and strings */
-// #define IN_MEM_COMPRESSION
+/* experimenting with in-memory deflation so as to write compressed files to channels and strings */
+//  #define IN_MEM_COMPRESSION
 
 #include <stdarg.h>
 #include <stdlib.h>
 #endif
 static unsigned char z_file_header[] =
    {0x1f, 0x8b, /*magic*/ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE};
+
+static z_stream z_strm;
+static unsigned char *df;
+static unsigned int dfallocated;
+static unsigned long int crc;
 #endif
 #endif
 
@@ -60,55 +63,24 @@ static unsigned char z_file_header[] =
 #include "gvcproc.h"
 #include "logic.h"
 
+#ifdef WITH_CODEGENS
+extern FILE* Output_file;
+#endif
+
 static const int PAGE_ALIGN = 4095;            /* align to a 4K boundary (less one), typical for Linux, Mac OS X and Windows memory allocation */
 
-size_t gvdevice_write (GVJ_t * job, const unsigned char *s, unsigned int len)
+static size_t gvdevice_write_no_z (GVJ_t * job, const unsigned char *s, unsigned int len)
 {
-#ifdef IN_MEM_COMPRESSION
-    if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
-#ifdef HAVE_LIBZ
-        static unsigned char *dest;
-        static unsigned int destAllocated;
-        unsigned long int destLen;
-
-       destLen = compressBound(len);
-       if (destAllocated < destLen) {
-           dest = realloc(dest, len+100);
-           if (! dest) {
-               fprintf(stderr, "memory allocation failure\n");
-               return 0;
-           }
-       }
-
-       if (compress (dest, &destLen, s, len) != Z_OK) {
-           fprintf(stderr, "failure compressing output string\n");
-           return 0;
-       }
-
-       len = destLen;
-       s = dest;
-#endif
-    }
-#endif
-
     if (job->gvc->write_fn)   /* externally provided write dicipline */
        return (job->gvc->write_fn)(job, (char*)s, len);
-#ifndef IN_MEM_COMPRESSION
-    if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
-#ifdef HAVE_LIBZ
-       return gzwrite((gzFile *) (job->output_file), s, len);
-#endif
-    }
-    else
-#endif
     if (job->output_data) {
        if (len > job->output_data_allocated - (job->output_data_position + 1)) {
            /* ensure enough allocation for string = null terminator */
            job->output_data_allocated = (job->output_data_position + len + 1 + PAGE_ALIGN) & ~PAGE_ALIGN;
            job->output_data = realloc(job->output_data, job->output_data_allocated);
            if (!job->output_data) {
-               fprintf(stderr, "failure realloc'ing for result string\n");
-               return 0;
+                (job->common->errorfn) ("memory allocation failure\n");
+               exit(1);
            }
        }
        memcpy(job->output_data + job->output_data_position, s, len);
@@ -121,11 +93,297 @@ size_t gvdevice_write (GVJ_t * job, const unsigned char *s, unsigned int len)
     return 0;
 }
 
+static void auto_output_filename(GVJ_t *job)
+{
+    static char *buf;
+    static int bufsz;
+    char gidx[100];  /* large enough for '.' plus any integer */
+    char *fn, *p;
+    int len;
+
+    if (job->graph_index)
+        sprintf(gidx, ".%d", job->graph_index + 1);
+    else
+        gidx[0] = '\0';
+    if (!(fn = job->input_filename))
+        fn = "noname.dot";
+    len = strlen(fn)                    /* typically "something.dot" */
+        + strlen(gidx)                  /* "", ".2", ".3", ".4", ... */
+        + 1                             /* "." */
+        + strlen(job->output_langname)  /* e.g. "png" */
+        + 1;                            /* null terminaor */
+    if (bufsz < len) {
+            bufsz = len + 10;
+            buf = realloc(buf, bufsz * sizeof(char));
+    }
+    strcpy(buf, fn);
+    strcat(buf, gidx);
+    strcat(buf, ".");
+    if ((p = strchr(job->output_langname, ':'))) {
+        strcat(buf, p+1);
+        strcat(buf, ".");
+        strncat(buf, job->output_langname, (p - job->output_langname));
+    }
+    else {
+        strcat(buf, job->output_langname);
+    }
+
+    job->output_filename = buf;
+}
+
+void gvdevice_initialize(GVJ_t * job)
+{
+    gvdevice_engine_t *gvde = job->device.engine;
+    GVC_t *gvc = job->gvc;
+
+    if (gvde && gvde->initialize) {
+       gvde->initialize(job);
+    }
+    else if (job->output_data) {
+    }
+    /* if the device has no initialization then it uses file output */
+    else if (!job->output_file) {        /* if not yet opened */
+        if (gvc->common.auto_outfile_names)
+            auto_output_filename(job);
+        if (job->output_filename) {
+            job->output_file = fopen(job->output_filename, "w");
+            if (job->output_file == NULL) {
+                perror(job->output_filename);
+                exit(1);
+            }
+        }
+        else
+            job->output_file = stdout;
+
+#ifdef WITH_CODEGENS
+        Output_file = job->output_file;
+#endif
+
+#ifdef HAVE_SETMODE
+#ifdef O_BINARY
+        if (job->flags & GVDEVICE_BINARY_FORMAT)
+            setmode(fileno(job->output_file), O_BINARY);
+#endif
+#endif
+
+#ifndef IN_MEM_COMPRESSION
+        if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
+#if HAVE_LIBZ
+           int fd;
+
+           /* open dup so can gzclose independent of FILE close */
+           fd = dup(fileno(job->output_file));
+           job->output_file = (FILE *) (gzdopen(fd, "wb"));
+           if (!job->output_file) {
+               (job->common->errorfn) ("Error initializing deflation on output file\n");
+               exit(1);
+           }
+#else
+           (job->common->errorfn) ("No libz support.\n");
+           exit(1);
+#endif
+        }
+#endif
+    }
+
+#ifdef IN_MEM_COMPRESSION
+    if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
+#ifdef HAVE_LIBZ
+       z_stream *z = &z_strm;
+
+       z->zalloc = (alloc_func)0;
+       z->zfree = (free_func)0;
+       z->opaque = (voidpf)0;
+       z->next_in = NULL;
+       z->next_out = NULL;
+       z->avail_in = 0;
+
+       crc = crc32(0L, Z_NULL, 0);
+
+       if (deflateInit2(z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
+           (job->common->errorfn) ("Error initializing for deflation\n");
+           exit(1);
+       }
+       gvdevice_write_no_z(job, z_file_header, sizeof(z_file_header));
+#else
+       (job->common->errorfn) ("No libz support.\n");
+       exit(1);
+#endif
+    }
+#endif
+}
+
+size_t gvdevice_write (GVJ_t * job, const unsigned char *s, unsigned int len)
+{
+    if (!len || !s)
+       return 0;
+
+#ifdef IN_MEM_COMPRESSION
+    if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
+#ifdef HAVE_LIBZ
+       z_streamp z = &z_strm;
+       int ret, dflen;
+
+       dflen = deflateBound(z, len);
+       if (dfallocated < dflen) {
+           dfallocated = (dflen + 1 + PAGE_ALIGN) & ~PAGE_ALIGN;
+           df = realloc(df, dfallocated);
+           if (! df) {
+                (job->common->errorfn) ("memory allocation failure\n");
+               exit(1);
+           }
+       }
+
+       z->next_in = (unsigned char*)s;
+       z->avail_in = len;
+       z->next_out = df;
+       z->avail_out = dfallocated;
+       ret=deflate (z, Z_NO_FLUSH);
+       if (ret != Z_OK) {
+            (job->common->errorfn) ("deflation problem %d\n", ret);
+           exit(1);
+       }
+       crc = crc32(crc, s, len);
+       len = z->next_out - df;
+       s = df;
+#endif
+    }
+#else
+    if (!(job->gvc->write_fn) && (job->flags & GVDEVICE_COMPRESSED_FORMAT)) {
+#ifdef HAVE_LIBZ
+       return gzwrite((gzFile *) (job->output_file), s, len);
+#endif
+    }
+#endif
+    return gvdevice_write_no_z (job, s, len);
+}
+
 void gvdevice_fputs(GVJ_t * job, char *s)
 {
     gvdevice_write (job, (unsigned char*)s, strlen(s));
 }
 
+static void gvdevice_flush(GVJ_t * job)
+{
+    if (job->output_file
+      && ! job->external_context
+      && ! job->gvc->write_fn
+      && job->output_lang != TK
+      && ! (job->flags & GVDEVICE_COMPRESSED_FORMAT)) {
+       fflush(job->output_file);
+    }
+}
+
+static void gvdevice_close(GVJ_t * job)
+{
+    if (job->output_filename
+      && job->output_file != stdout 
+      && ! job->external_context) {
+        if (job->output_file) {
+            fclose(job->output_file);
+            job->output_file = NULL;
+        }
+       job->output_filename = NULL;
+    }
+}
+
+void gvdevice_format(GVJ_t * job)
+{
+    gvdevice_engine_t *gvde = job->device.engine;
+
+    if (gvde && gvde->format)
+       gvde->format(job);
+    gvdevice_flush(job);
+}
+
+void gvdevice_finalize(GVJ_t * job)
+{
+    gvdevice_engine_t *gvde = job->device.engine;
+    boolean finalized_p = FALSE;
+
+#ifdef IN_MEM_COMPRESSION
+    if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
+#ifdef HAVE_LIBZ
+       z_streamp z = &z_strm;
+       unsigned char out[8] = "";
+       int ret;
+       int cnt = 0;
+
+       z->next_in = out;
+       z->avail_in = 0;
+       z->next_out = df;
+       z->avail_out = dfallocated;
+
+#if 1
+       while ((ret = deflate (z, Z_FINISH)) == Z_OK && (cnt++ <= 100)) {
+           gvdevice_write_no_z(job, df, z->next_out - df);
+           z->next_in = out;
+           z->avail_in = 0;
+           z->next_out = df;
+           z->avail_out = dfallocated;
+       }
+#else
+       ret = deflate (z, Z_FINISH);
+#endif
+       if (ret != Z_STREAM_END && ret != Z_OK) {
+            (job->common->errorfn) ("deflation finish problem %d cnt=%d\n", ret, cnt);
+           exit(1);
+       }
+       gvdevice_write_no_z(job, df, z->next_out - df);
+
+       ret = deflateEnd(z);
+       if (ret != Z_OK) {
+           (job->common->errorfn) ("deflation end problem %d\n", ret);
+           exit(1);
+       }
+       out[0] = (unsigned char)(crc);
+       out[1] = (unsigned char)(crc >> 8);
+       out[2] = (unsigned char)(crc >> 16);
+       out[3] = (unsigned char)(crc >> 24);
+       out[4] = (unsigned char)(z->total_in);
+       out[5] = (unsigned char)(z->total_in >> 8);
+       out[6] = (unsigned char)(z->total_in >> 16);
+       out[7] = (unsigned char)(z->total_in >> 24);
+       gvdevice_write_no_z(job, out, sizeof(out));
+#else
+       (job->common->errorfn) ("No libz support\n");
+       exit(1);
+#endif
+    }
+#endif
+
+    if (gvde) {
+       if (gvde->finalize) {
+           gvde->finalize(job);
+           finalized_p = TRUE;
+       }
+    }
+#ifdef WITH_CODEGENS
+    else {
+       codegen_t *cg = job->codegen;
+
+       if (cg && cg->reset)
+           cg->reset();
+    }
+#endif
+
+    if (! finalized_p) {
+        /* if the device has no finalization then it uses file output */
+#ifndef IN_MEM_COMPRESSION
+        if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
+#ifdef HAVE_LIBZ
+           gzclose((gzFile *) (job->output_file));
+           job->output_file = NULL;
+#else
+           (job->common->errorfn) ("No libz support\n");
+           exit(1);
+#endif
+       }
+#endif
+       gvdevice_flush(job);
+       gvdevice_close(job);
+    }
+}
 /* gvdevice_printf:
  * Note that this function is unsafe due to the fixed buffer size.
  * It should only be used when the caller is sure the input will not
@@ -289,175 +547,3 @@ void gvdevice_printpointflist(GVJ_t * job, pointf *p, int n)
     }
 } 
 
-static void auto_output_filename(GVJ_t *job)
-{
-    static char *buf;
-    static int bufsz;
-    char gidx[100];  /* large enough for '.' plus any integer */
-    char *fn, *p;
-    int len;
-
-    if (job->graph_index)
-        sprintf(gidx, ".%d", job->graph_index + 1);
-    else
-        gidx[0] = '\0';
-    if (!(fn = job->input_filename))
-        fn = "noname.dot";
-    len = strlen(fn)                    /* typically "something.dot" */
-        + strlen(gidx)                  /* "", ".2", ".3", ".4", ... */
-        + 1                             /* "." */
-        + strlen(job->output_langname)  /* e.g. "png" */
-        + 1;                            /* null terminaor */
-    if (bufsz < len) {
-            bufsz = len + 10;
-            buf = realloc(buf, bufsz * sizeof(char));
-    }
-    strcpy(buf, fn);
-    strcat(buf, gidx);
-    strcat(buf, ".");
-    if ((p = strchr(job->output_langname, ':'))) {
-        strcat(buf, p+1);
-        strcat(buf, ".");
-        strncat(buf, job->output_langname, (p - job->output_langname));
-    }
-    else {
-        strcat(buf, job->output_langname);
-    }
-
-    job->output_filename = buf;
-}
-
-#ifdef WITH_CODEGENS
-extern FILE* Output_file;
-#endif
-
-void gvdevice_initialize(GVJ_t * job)
-{
-    gvdevice_engine_t *gvde = job->device.engine;
-    GVC_t *gvc = job->gvc;
-
-    if (gvde && gvde->initialize) {
-       gvde->initialize(job);
-    }
-    else if (job->output_data) {
-    }
-    /* if the device has no initialization then it uses file output */
-    else if (!job->output_file) {        /* if not yet opened */
-        if (gvc->common.auto_outfile_names)
-            auto_output_filename(job);
-        if (job->output_filename) {
-            job->output_file = fopen(job->output_filename, "w");
-            if (job->output_file == NULL) {
-                perror(job->output_filename);
-                exit(1);
-            }
-        }
-        else
-            job->output_file = stdout;
-
-#ifdef WITH_CODEGENS
-        Output_file = job->output_file;
-#endif
-
-#ifdef HAVE_SETMODE
-#ifdef O_BINARY
-        if (job->flags & GVDEVICE_BINARY_FORMAT)
-            setmode(fileno(job->output_file), O_BINARY);
-#endif
-#endif
-
-        if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
-#ifdef IN_MEM_COMPRESSION
-           job->flags ^= GVDEVICE_COMPRESSED_FORMAT; /* don't complress header!!! */
-           gvdevice_write(job, z_file_header, sizeof(z_file_header));
-           job->flags ^= GVDEVICE_COMPRESSED_FORMAT;
-#else
-#if HAVE_LIBZ
-           int fd;
-
-           /* open dup so can gzclose independent of FILE close */
-           fd = dup(fileno(job->output_file));
-           job->output_file = (FILE *) (gzdopen(fd, "wb"));
-           if (!job->output_file) {
-               (job->common->errorfn) ("Error initializing compression on output file\n");
-               exit(1);
-           }
-#else
-           (job->common->errorfn) ("No libz support.\n");
-           exit(1);
-#endif
-#endif
-        }
-    }
-}
-
-static void gvdevice_flush(GVJ_t * job)
-{
-    if (job->output_file
-      && ! job->external_context
-      && ! job->gvc->write_fn
-      && job->output_lang != TK
-      && ! (job->flags & GVDEVICE_COMPRESSED_FORMAT)) {
-       fflush(job->output_file);
-    }
-}
-
-static void gvdevice_close(GVJ_t * job)
-{
-    if (job->output_filename
-      && job->output_file != stdout 
-      && ! job->external_context) {
-        if (job->output_file) {
-            fclose(job->output_file);
-            job->output_file = NULL;
-        }
-       job->output_filename = NULL;
-    }
-}
-
-void gvdevice_format(GVJ_t * job)
-{
-    gvdevice_engine_t *gvde = job->device.engine;
-
-    if (gvde && gvde->format)
-       gvde->format(job);
-    gvdevice_flush(job);
-}
-
-void gvdevice_finalize(GVJ_t * job)
-{
-    gvdevice_engine_t *gvde = job->device.engine;
-    boolean finalized_p = FALSE;
-
-    if (gvde) {
-       if (gvde->finalize) {
-           gvde->finalize(job);
-           finalized_p = TRUE;
-       }
-    }
-#ifdef WITH_CODEGENS
-    else {
-       codegen_t *cg = job->codegen;
-
-       if (cg && cg->reset)
-           cg->reset();
-    }
-#endif
-
-    if (! finalized_p) {
-        /* if the device has no finalization then it uses file output */
-#ifndef IN_MEM_COMPRESSION
-       if (job->flags & GVDEVICE_COMPRESSED_FORMAT) {
-#ifdef HAVE_LIBZ
-           gzclose((gzFile *) (job->output_file));
-           job->output_file = NULL;
-#else
-           (job->common->errorfn) ("No libz support\n");
-           exit(1);
-#endif
-       }
-#endif
-       gvdevice_flush(job);
-       gvdevice_close(job);
-    }
-}