pdf-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pdf-devel] Patch for the Flate filter


From: gerel
Subject: [pdf-devel] Patch for the Flate filter
Date: Wed, 01 Oct 2008 10:18:51 -0700 (PDT)

Hi everyone,

Here is a patch for the Flate filter implementation plus tests.

##
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: address@hidden
# target_branch: file:///home/gerel/PROJECTS/libgnupdf/trunk/
# testament_sha1: 1aa276b97f1e53feced4a3dd7ce1a7eb0a338389
# timestamp: 2008-10-01 14:08:25 -0300
# base_revision_id: address@hidden
# 
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog   2008-09-28 23:21:24 +0000
+++ ChangeLog   2008-10-01 02:14:52 +0000
@@ -1,3 +1,23 @@
+2008-09-30  Gerardo E. Gidoni  <address@hidden>
+
+       * doc/gnupdf-tsd.texi: added flate filter tests.
+
+       * torture/unit/base/stm/pdf-stm-read.c: same.
+
+       * torture/unit/base/stm/pdf-stm-write.c: same.
+
+       * src/Makefile.am: added flate filter source files.
+
+       * src/base/pdf-stm-f-flate.c: adapted for new stream API.
+
+       * src/base/pdf-stm-f-flate.h: same.
+
+       * src/base/pdf-stm-filter.c: added flate filter.
+
+       * src/base/pdf-stm-filter.h: same.
+
+       * utils/pdf-filter.c: same.
+
 2008-09-28  Gerardo E. Gidoni  <address@hidden>
 
        * src/base/pdf-stm-f-rl.c: decoder EOD mark fix.

=== modified file 'doc/gnupdf-tsd.texi'
--- doc/gnupdf-tsd.texi 2008-09-28 14:00:42 +0000
+++ doc/gnupdf-tsd.texi 2008-10-01 02:14:52 +0000
@@ -277,6 +277,16 @@
 @end table
 @end deffn
 
address@hidden Test pdf_stm_read_009
+Create a memory-based reading stream and attach a flate filter
+decoder to it.
address@hidden @strong
address@hidden Success condition
+The decoded data should be correct.
address@hidden table
address@hidden deffn
+
+
 @node pdf_stm_read_char
 @subsubsection pdf_stm_read_char
 
@@ -405,6 +415,15 @@
 @end deffn
 
 
address@hidden Test pdf_stm_write_007
+Create a memory-based writing stream and attach a flate filter
+encoder to it.
address@hidden @strong
address@hidden Success condition
+The encoded data should be correct.
address@hidden table
address@hidden deffn
+
 @node Text Module
 @subsection Text Module
 

=== modified file 'src/Makefile.am'
--- src/Makefile.am     2008-09-27 22:28:27 +0000
+++ src/Makefile.am     2008-09-30 14:21:16 +0000
@@ -44,7 +44,8 @@
                      base/pdf-stm-filter.h base/pdf-stm-filter.c \
                      base/pdf-stm-f-null.h base/pdf-stm-f-null.c \
                      base/pdf-stm-f-ahex.h base/pdf-stm-f-ahex.c \
-                     base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c
+                     base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c \
+                     base/pdf-stm-f-flate.h base/pdf-stm-f-flate.c 
 
 # if ZLIB
 #  STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h

=== modified file 'src/base/pdf-stm-f-flate.c'
--- src/base/pdf-stm-f-flate.c  2008-03-05 12:32:04 +0000
+++ src/base/pdf-stm-f-flate.c  2008-10-01 17:08:10 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/03/05 12:24:36 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-01 14:01:53 gerel"
  *
  *       File:         pdf-stm-f-flate.c
  *       Date:         Tue Jul 10 23:44:00 2007
@@ -26,173 +26,278 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <zlib.h>
 #include <pdf-alloc.h>
-#include <pdf-base.h>
+#include <pdf-hash.h>
 #include <pdf-stm-f-flate.h>
 
 
-static int pdf_stm_f_flate_encode (pdf_char_t *in, pdf_stm_pos_t in_size,
-                                   pdf_char_t **out, pdf_stm_pos_t *out_size);
-static int pdf_stm_f_flate_decode (pdf_char_t *in, pdf_stm_pos_t in_size,
-                                   pdf_char_t **out, pdf_stm_pos_t *out_size);
-
-int
-pdf_stm_f_flate_init (void **filter_data,
-                     void *conf_data)
-{
-  pdf_stm_f_flate_data_t *data;
-  pdf_stm_f_flate_conf_t conf;
-
-  data = (pdf_stm_f_flate_data_t *) filter_data;
-  conf = (pdf_stm_f_flate_conf_t) conf_data;
-
-  /* Create the private data storage */
-  *data =
-    (pdf_stm_f_flate_data_t) pdf_alloc (sizeof(struct pdf_stm_f_flate_data_s));
-  (*data)->mode = conf->mode;
-
-  return PDF_OK;
-}
-
-int
-pdf_stm_f_flate_apply (void *filter_data,
-                      pdf_char_t *in, pdf_stm_pos_t in_size,
-                      pdf_char_t **out, pdf_stm_pos_t *out_size)
-{
-  pdf_stm_f_flate_data_t data;
-
-  data = (pdf_stm_f_flate_data_t) filter_data;
-  switch (data->mode)
-    {
-    case PDF_STM_F_FLATE_MODE_ENCODE:
-      {
-        return pdf_stm_f_flate_encode (in, in_size, out, out_size);
-      }
-    case PDF_STM_F_FLATE_MODE_DECODE:
-      {
-        return pdf_stm_f_flate_decode (in, in_size, out, out_size);
-      }
-    default:
-      {
+static int deflate_inbuf (pdf_stm_f_flate_t st, pdf_stm_buffer_t out,
+                          int flush);
+
+pdf_status_t
+pdf_stm_f_flateenc_init (pdf_hash_t params, void **state)
+{
+  pdf_status_t ret;
+  pdf_stm_f_flate_t filter_state;
+
+  filter_state = pdf_alloc (sizeof (struct pdf_stm_f_flate_s));
+
+  if (state == NULL)
+    {
+      ret = PDF_EBADDATA;
+    }
+  else if (filter_state == NULL)
+    {
+      ret = PDF_ENOMEM;
+    }
+  else
+    {
+      /* Initialize fields */
+      filter_state->stream.zalloc = Z_NULL;
+      filter_state->stream.zfree = Z_NULL;
+      filter_state->stream.opaque = Z_NULL;
+      filter_state->zlib_init_p = PDF_FALSE;
+      filter_state->writing_p = PDF_FALSE;
+      filter_state->to_write = 0;
+      filter_state->incnt = 0;
+      filter_state->outcnt = 0;
+      filter_state->zret = Z_OK;
+
+      *state = (void *) filter_state;
+      ret = PDF_OK;
+    }
+
+  return ret;
+}
+
+
+pdf_status_t
+pdf_stm_f_flatedec_init (pdf_hash_t params, void **state)
+{
+  return pdf_stm_f_flateenc_init(params, state);
+}
+
+
+pdf_status_t
+pdf_stm_f_flateenc_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in,
+                          pdf_stm_buffer_t out, pdf_bool_t finish_p)
+{
+  pdf_stm_f_flate_t st;
+
+  st = (pdf_stm_f_flate_t) state;
+
+  /* Initialize stream input/output parameters */
+  if (!st->zlib_init_p)
+    {
+      if (deflateInit (&(st->stream), Z_DEFAULT_COMPRESSION) != Z_OK)
+        {
+          return PDF_ERROR;
+        }
+      st->zlib_init_p = PDF_TRUE;
+    }
+
+  if (st->zret == Z_STREAM_END)
+    {
+      return PDF_EEOF;
+    }
+
+  /* Fill the input CHUNK  */
+  while (st->incnt < PDF_STM_F_FLATE_CHUNK && !pdf_stm_buffer_eob_p(in))
+    {
+      st->inbuf[st->incnt] = in->data[in->rp];
+      st->incnt++;
+      in->rp++;
+    }
+
+  /* More data may come */
+  if (!finish_p)
+    {
+      /* if the input CHUNK has space, ask for it. */
+      if (st->incnt < PDF_STM_F_FLATE_CHUNK)
+        {
+          return PDF_EEOF;
+        }
+      /* Now we have the input CHUNK full, we deflate and write to out */
+      if (deflate_inbuf(st, out, Z_NO_FLUSH) < 0)
+        {
+          return PDF_ERROR;
+        }
+      /* the input CHUNK now is empty, if needed, ask for input */
+      st->incnt = 0;
+      if (pdf_stm_buffer_eob_p(in))
+        {
+          return PDF_EEOF;
+        }
+      return PDF_OK;
+    }
+  /* No more data will come, we deflate with Z_FINISH and write to out */
+  else
+    {
+      if (deflate_inbuf(st, out, Z_FINISH) < 0)
+        {
+          return PDF_ERROR;
+        }
+    }
+
+  deflateEnd (&(st->stream));
+  return PDF_EEOF;
+}
+
+
+pdf_status_t
+pdf_stm_f_flatedec_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in,
+                          pdf_stm_buffer_t out, pdf_bool_t finish_p)
+{
+  pdf_stm_f_flate_t st;
+
+  st = (pdf_stm_f_flate_t) state;
+
+  /* Initialize stream input/output parameters */
+  if (!st->zlib_init_p)
+    {
+      if (inflateInit (&(st->stream)) != Z_OK)
+        {
+          st->zret = Z_OK;
+          return PDF_ERROR;
+        }
+      st->zlib_init_p = PDF_TRUE;
+    }
+
+
+  /* Fill the input CHUNK    */
+  if (!st->writing_p)
+    {
+      while (st->incnt < PDF_STM_F_FLATE_CHUNK && !pdf_stm_buffer_eob_p(in))
+        {
+          st->inbuf[st->incnt] = in->data[in->rp];
+          st->incnt++;
+          in->rp++;
+        }
+    }
+  else
+    {
+      /* 
+       * Not nice, but keeps the writing process code clear.
+       * Notice that the labeled code is inside a while loop,
+       * so I feel that avoiding this goto won't bring us better code.
+       */
+      goto writing;
+    }
+
+  if (st->incnt == 0 || st->zret == Z_STREAM_END)
+    {
+      return PDF_EEOF;
+    }
+
+  /* we inflate and write to out */
+  st->stream.avail_in = st->incnt;
+  st->stream.next_in = st->inbuf;
+  do {
+    st->stream.avail_out = PDF_STM_F_FLATE_CHUNK;
+    st->stream.next_out = st->outbuf;
+    st->outcnt = 0;
+
+    st->zret = inflate(&(st->stream), Z_NO_FLUSH);
+    if (st->zret == Z_STREAM_ERROR || st->zret == Z_NEED_DICT ||
+        st->zret == Z_DATA_ERROR || st->zret == Z_MEM_ERROR)
+      {
+        /* should not be reached */
+        inflateEnd(&(st->stream));
         return PDF_ERROR;
       }
+
+    st->to_write = PDF_STM_F_FLATE_CHUNK - st->stream.avail_out;
+
+  writing:
+    while (st->outcnt < st->to_write && !pdf_stm_buffer_full_p(out))
+      {
+        out->data[out->wp] = st->outbuf[st->outcnt];
+        out->wp++;
+        st->outcnt++;
+      }
+    if (pdf_stm_buffer_full_p(out))
+      {
+        st->writing_p = PDF_TRUE;
+        return PDF_OK;
+      }
+  } while (st->stream.avail_out == 0);
+
+  /* the input CHUNK now is empty, if needed, ask for input */
+  st->writing_p = PDF_FALSE;
+  st->incnt = 0;
+  if (pdf_stm_buffer_eob_p(in))
+    {
+      return PDF_EEOF;
     }
-  
-  /* Not reached */
-}
-
-int
-pdf_stm_f_flate_dealloc (void **filter_data)
-{
-  pdf_stm_f_flate_data_t *data;
-
-  data = (pdf_stm_f_flate_data_t *) filter_data;
-  pdf_dealloc (*data);
-
-  return PDF_OK;
-}
+
+  return PDF_OK;
+}
+
+
+
+pdf_status_t
+pdf_stm_f_flatedec_dealloc_state (void *state)
+{
+  pdf_stm_f_flate_t st = state;
+  inflateEnd(&(st->stream));
+  pdf_dealloc (state);
+  return PDF_OK;
+}
+
+pdf_status_t
+pdf_stm_f_flateenc_dealloc_state (void *state)
+{
+  pdf_dealloc (state);
+  return PDF_OK;
+}
+
 
 /* Private functions */
 
 static int
-pdf_stm_f_flate_encode (pdf_char_t *in, 
-                        pdf_stm_pos_t in_size,
-                        pdf_char_t **out,
-                        pdf_stm_pos_t *out_size)
-{
-  unsigned long compressed_bound;
-  int ret;
-
-  /* Allocate memory for destination buffer */
-  compressed_bound = compressBound (in_size);
-  *out_size = compressed_bound;
-  *out = (pdf_char_t *) pdf_alloc (*out_size);
-
-  /* Compress input */
-  ret = compress (*out, 
-                  (unsigned long *) out_size,
-                  in,
-                  in_size);
-
-  if (ret == Z_OK)
-    {
-      /* Adjust memory to really used  and return */
-      *out = (pdf_char_t *) pdf_realloc (*out,
-                                         *out_size);
-      return PDF_OK;
-    }
-  else
-    {
-      /* Z_MEM_ERROR or Z_BUF_ERROR happened.  In any case, return
-         reporting that the filter application failed. */
-      return PDF_FALSE;
-    }
-
-  /* Not reached */
-}
-
-#define CHUNK 16384
-
-static int
-pdf_stm_f_flate_decode (pdf_char_t *in,
-                        pdf_stm_pos_t in_size,
-                        pdf_char_t **out,
-                        pdf_stm_pos_t *out_size)
-{
-  z_stream zstm;
-  int ret;
-  pdf_char_t out_aux[16384];
-  pdf_stm_pos_t nchunks;
-
-  zstm.zalloc = Z_NULL;
-  zstm.zfree = Z_NULL;
-  zstm.opaque = Z_NULL;
-  zstm.avail_in = in_size;
-  zstm.next_in = in;
-
-  inflateInit (&zstm);
-
-  *out_size = 0;
-  *out = NULL;
-  nchunks = 0;
-  do
-    {
-      zstm.avail_out = CHUNK;
-      zstm.next_out = out_aux;
-      
-      ret = inflate (&zstm, Z_NO_FLUSH);
-
-      switch (ret)
-        {
-        case Z_NEED_DICT:
-        case Z_DATA_ERROR:
-        case Z_MEM_ERROR:
-          {
-            goto error;
-          }
-        }
-          
-      *out_size =  *out_size + (CHUNK - zstm.avail_out);
-      *out = (pdf_char_t *) pdf_realloc (*out,
-                                         *out_size);
-
-      memcpy (*out + (nchunks * CHUNK),
-              out_aux,
-              CHUNK - zstm.avail_out);
-
-      nchunks++;
-
-    } while (ret != Z_STREAM_END);
-
-  ret = inflateEnd (&zstm);
-  
-  return PDF_OK;
-
- error:
-  (void) inflateEnd (&zstm);
-  return PDF_ERROR;
-}
+deflate_inbuf (pdf_stm_f_flate_t st, pdf_stm_buffer_t out, int flush)
+{
+  st->stream.avail_in = st->incnt;
+  st->stream.next_in = st->inbuf;
+  do {
+    st->stream.avail_out = PDF_STM_F_FLATE_CHUNK;
+    st->stream.next_out = st->outbuf;
+    st->outcnt = 0;
+
+    /* Make sure the output limit is enough */
+    if(deflateBound(&st->stream,st->incnt) > (out->size - out->wp))
+      {
+        /* should not be reached */
+        deflateEnd (&(st->stream));
+        return -1;
+      }  
+
+    st->zret = deflate(&(st->stream), flush);
+    if (st->zret == Z_STREAM_ERROR)
+      {
+        /* should not be reached */
+        deflateEnd (&(st->stream));
+        return -1;
+      }
+
+    st->to_write = PDF_STM_F_FLATE_CHUNK - st->stream.avail_out;
+    while (st->outcnt < st->to_write && !pdf_stm_buffer_full_p(out))
+      {
+        out->data[out->wp++] = st->outbuf[st->outcnt];
+        st->outcnt++;
+      }
+    if (pdf_stm_buffer_full_p(out))
+      {
+        /* should _not_ be reached */
+        deflateEnd (&(st->stream));
+        return -1;
+      }
+  } while (st->stream.avail_out == 0);
+
+  return 0;
+}
+
+
 
 
 /* End of pdf_stm_f_flate.c */

=== modified file 'src/base/pdf-stm-f-flate.h'
--- src/base/pdf-stm-f-flate.h  2008-02-11 01:11:25 +0000
+++ src/base/pdf-stm-f-flate.h  2008-10-01 17:08:10 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/02/11 01:04:11 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-01 14:07:32 gerel"
  *
  *       File:         pdf-stm-f-flate.h
  *       Date:         Tue Jul 10 23:39:27 2007
@@ -27,43 +27,53 @@
 #define PDF_STM_F_FLATE_H
 
 #include <config.h>
-#include <pdf-base.h>
-
-/* Filter configuration */
-
-/* BEGIN PUBLIC */
-
-enum pdf_stm_f_flate_mode_t
-{
-  PDF_STM_F_FLATE_MODE_ENCODE,
-  PDF_STM_F_FLATE_MODE_DECODE
-};
-
-/* END PUBLIC */
-
-struct pdf_stm_f_flate_conf_s
-{
-  int mode;
-};
-
-typedef struct pdf_stm_f_flate_conf_s *pdf_stm_f_flate_conf_t;
-
-/* Private data */
-
-struct pdf_stm_f_flate_data_s
-{
-  int mode;
-};
-
-typedef struct pdf_stm_f_flate_data_s *pdf_stm_f_flate_data_t;
+#include <pdf-hash.h>
+#include <pdf-stm-buffer.h>
+#include <zlib.h>
+
+
+
+ /* 
+  * As read in the zlib documentation, our cache size must be at least 0.1%
+  * larger than the CHUNK size, plus 12 bytes.
+  * We assume that our cache size is of 4096 bytes.
+  */
+#define PDF_STM_F_FLATE_CHUNK 1024
+
+struct pdf_stm_f_flate_s
+{
+  z_stream stream;
+  int zret;
+  pdf_size_t incnt, outcnt, to_write;
+  pdf_bool_t zlib_init_p, writing_p;
+  pdf_char_t inbuf[PDF_STM_F_FLATE_CHUNK], outbuf[PDF_STM_F_FLATE_CHUNK];
+};
+
+typedef struct pdf_stm_f_flate_s * pdf_stm_f_flate_t;
+
 
 /* Filter API implementation */
 
-int pdf_stm_f_flate_init (void **filter_data, void *conf_data);
-int pdf_stm_f_flate_apply (void *filter_data,
-                          pdf_char_t *in, pdf_stm_pos_t in_size,
-                          pdf_char_t **out, pdf_stm_pos_t *out_size);
-int pdf_stm_f_flate_dealloc (void **filter_data);
+pdf_status_t pdf_stm_f_flatedec_init (pdf_hash_t params,
+                                   void **state);
+
+pdf_status_t pdf_stm_f_flatedec_apply (pdf_hash_t params,
+                                    void *state,
+                                    pdf_stm_buffer_t in,
+                                    pdf_stm_buffer_t out,
+                                    pdf_bool_t finish_p);
+
+pdf_status_t pdf_stm_f_flateenc_init (pdf_hash_t params,
+                                   void **state);
+
+pdf_status_t pdf_stm_f_flateenc_apply (pdf_hash_t params,
+                                    void *state,
+                                    pdf_stm_buffer_t in,
+                                    pdf_stm_buffer_t out,
+                                    pdf_bool_t finish_p);
+
+pdf_status_t pdf_stm_f_flatedec_dealloc_state (void *state);
+pdf_status_t pdf_stm_f_flateenc_dealloc_state (void *state);
 
 
 #endif /* pdf_stm_f_flate.h */

=== modified file 'src/base/pdf-stm-filter.c'
--- src/base/pdf-stm-filter.c   2008-09-28 13:51:52 +0000
+++ src/base/pdf-stm-filter.c   2008-09-30 17:51:31 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/09/28 15:44:46 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-09-30 13:15:19 gerel"
  *
  *       File:         pdf-stm-filter.c
  *       Date:         Thu Jun 12 22:13:31 2008
@@ -97,6 +97,20 @@
         new->impl.dealloc_state_fn = pdf_stm_f_rldec_dealloc_state;
         break;
       }
+    case PDF_STM_FILTER_FLATE_ENC:
+      {
+        new->impl.init_fn = pdf_stm_f_flateenc_init;
+        new->impl.apply_fn = pdf_stm_f_flateenc_apply;
+        new->impl.dealloc_state_fn = pdf_stm_f_flateenc_dealloc_state;
+        break;
+      }
+    case PDF_STM_FILTER_FLATE_DEC:
+      {
+        new->impl.init_fn = pdf_stm_f_flatedec_init;
+        new->impl.apply_fn = pdf_stm_f_flatedec_apply;
+        new->impl.dealloc_state_fn = pdf_stm_f_flatedec_dealloc_state;
+        break;
+      }
     default:
       {
         /* Shall not be reached, but makes the compiler happy */

=== modified file 'src/base/pdf-stm-filter.h'
--- src/base/pdf-stm-filter.h   2008-09-28 13:51:52 +0000
+++ src/base/pdf-stm-filter.h   2008-09-30 14:21:16 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/09/28 15:40:32 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-09-30 11:20:36 gerel"
  *
  *       File:         pdf-stm-filter.h
  *       Date:         Thu Jun 12 22:05:06 2008
@@ -35,6 +35,7 @@
 #include <pdf-stm-f-null.h>
 #include <pdf-stm-f-ahex.h>
 #include <pdf-stm-f-rl.h>
+#include <pdf-stm-f-flate.h>
 
 /* BEGIN PUBLIC */
 
@@ -45,7 +46,10 @@
   PDF_STM_FILTER_AHEX_ENC,
   PDF_STM_FILTER_AHEX_DEC,
   PDF_STM_FILTER_RL_ENC,
-  PDF_STM_FILTER_RL_DEC
+  PDF_STM_FILTER_RL_DEC,
+  PDF_STM_FILTER_FLATE_DEC,
+  PDF_STM_FILTER_FLATE_ENC
+
 };
 
 /* Filter implementation */

=== modified file 'torture/unit/base/stm/pdf-stm-read.c'
--- torture/unit/base/stm/pdf-stm-read.c        2008-09-28 23:21:24 +0000
+++ torture/unit/base/stm/pdf-stm-read.c        2008-10-01 16:29:41 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "2008-09-28 20:17:40 gerel"
+/* -*- mode: C -*- Time-stamp: "2008-10-01 13:28:35 gerel"
  *
  *       File:         pdf-stm-read.c
  *       Date:         Sat Sep 20 15:20:17 2008
@@ -289,6 +289,9 @@
 }
 END_TEST
 
+
+
+
 /*
  * Test: pdf_stm_read_005
  * Description:
@@ -538,6 +541,84 @@
 
 
 /*
+ * Test: pdf_stm_read_009
+ * Description:
+ *   Create a memory-based reading stream and attach a flate filter
+ *   decoder to it.
+ * Success condition:
+ *   The decoded data should be correct.
+ */
+START_TEST (pdf_stm_read_009)
+{
+  pdf_status_t ret;
+  pdf_hash_t params;
+  pdf_stm_t stm;
+  pdf_size_t buf_size, total=1059,read;
+  pdf_char_t *buf, *decoded=
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990";
+  pdf_char_t *dataux, *encoded =
+    "\x78\x9c\x33\x34\x32\x32\x36\x36\x36\x01\x02\x53\x10\x30\x03\x03"
+    "\x73\x08\xb0\x80\x02\x4b\x18\x30\x30\x1c\x55\x3d\xaa\x7a\x54\xf5"
+    "\x88\x52\xcd\x00\x00\xe1\x0b\xdf\xfc";
+
+  /* Writing stream */
+  /* Create a memory buffer */
+  buf_size = 2000;
+  buf = pdf_alloc (buf_size);
+  fail_if(buf == NULL);
+  /* Create the stream */
+  ret = pdf_stm_mem_new (encoded,
+                         41,
+                         1040,
+                         PDF_STM_READ,
+                         &stm);
+  fail_if(ret != PDF_OK);
+  /* Create the filter */
+  fail_if (pdf_stm_install_filter (stm, PDF_STM_FILTER_FLATE_DEC, params) !=
+           PDF_OK);
+
+  read = 0;
+  total = 1059;
+  dataux = buf;
+  while (total > 0)
+    {
+      read = pdf_stm_read (stm, dataux, total);
+      dataux = dataux + read;
+      total -= read;
+    }
+
+  fail_if (memcmp (buf, decoded, 1059) != 0);
+  /* Destroy the stream */
+  pdf_stm_destroy (stm);
+  pdf_dealloc (buf);
+
+}
+END_TEST
+
+
+/*
  * Test case creation function
  */
 TCase *
@@ -553,6 +634,8 @@
   tcase_add_test(tc, pdf_stm_read_006);
   tcase_add_test(tc, pdf_stm_read_007);
   tcase_add_test(tc, pdf_stm_read_008);
+  tcase_add_test(tc, pdf_stm_read_009);
+
 
   return tc;
 }

=== modified file 'torture/unit/base/stm/pdf-stm-write.c'
--- torture/unit/base/stm/pdf-stm-write.c       2008-09-28 13:32:56 +0000
+++ torture/unit/base/stm/pdf-stm-write.c       2008-10-01 16:29:41 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/09/28 15:32:34 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-01 13:29:09 gerel"
  *
  *       File:         pdf-stm-write.c
  *       Date:         Sun Sep 21 16:37:27 2008
@@ -348,6 +348,88 @@
 }
 END_TEST
 
+
+/*
+ * Test: pdf_stm_write_007
+ * Description:
+ *   Create a memory-based writing stream and attach a flate filter
+ *   encoder to it.
+ * Success condition:
+ *   The encoded data should be correct.
+ */
+START_TEST (pdf_stm_write_007)
+{
+  pdf_status_t ret;
+  pdf_hash_t params;
+  pdf_stm_t stm;
+  pdf_size_t buf_size, total=1059,written;
+  pdf_char_t *buf, *decoded=
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990" \
+    "1223334444555556666667777777888888889999999990";
+  pdf_char_t *dataux, *encoded =
+    "\x78\x9c\x33\x34\x32\x32\x36\x36\x36\x01\x02\x53\x10\x30\x03\x03"
+    "\x73\x08\xb0\x80\x02\x4b\x18\x30\x30\x1c\x55\x3d\xaa\x7a\x54\xf5"
+    "\x88\x52\xcd\x00\x00\xe1\x0b\xdf\xfc";
+
+  /* Writing stream */
+  /* Create a memory buffer */
+  buf_size = 100;
+  buf = pdf_alloc (buf_size);
+  fail_if(buf == NULL);
+  /* Create the stream */
+  ret = pdf_stm_mem_new (buf,
+                         buf_size,
+                         0, 
+                         PDF_STM_WRITE,
+                         &stm);
+  fail_if(ret != PDF_OK);
+  /* Create the filter */
+  fail_if (pdf_stm_install_filter (stm, PDF_STM_FILTER_FLATE_ENC, params) !=
+           PDF_OK);
+
+  written = 0;
+  dataux = decoded;
+  while (total > 0)
+    {
+      written = pdf_stm_write (stm, dataux, total);
+      dataux = dataux + written;
+      total -= written;
+    }
+  pdf_stm_flush(stm);
+  pdf_stm_finish(stm);
+
+  fail_if (memcmp (buf, encoded, 41) != 0);
+  /* Destroy the stream */
+  pdf_stm_destroy (stm);
+  pdf_dealloc (buf);
+
+
+}
+END_TEST
+
+
+
 /*
  * Test case creation function
  */
@@ -362,6 +444,7 @@
   tcase_add_test(tc, pdf_stm_write_004);
   tcase_add_test(tc, pdf_stm_write_005);
   tcase_add_test(tc, pdf_stm_write_006);
+  tcase_add_test(tc, pdf_stm_write_007);
   
   return tc;
 }

=== modified file 'utils/pdf-filter.c'
--- utils/pdf-filter.c  2008-09-28 10:56:49 +0000
+++ utils/pdf-filter.c  2008-10-01 02:14:52 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/09/28 12:54:36 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-09-30 23:11:26 gerel"
  *
  *       File:         pdf-filter.c
  *       Date:         Tue Jul 10 18:42:07 2007
@@ -164,6 +164,8 @@
   pdf_hash_t ahexdec_filter_params;
   pdf_hash_t rlenc_filter_params;
   pdf_hash_t rldec_filter_params;
+  pdf_hash_t flateenc_filter_params;
+  pdf_hash_t flatedec_filter_params;
   pdf_char_t *line;
   pdf_size_t line_bytes;
   pdf_size_t read_bytes;
@@ -288,14 +290,30 @@
 #ifdef HAVE_LIBZ
         case FLATEDEC_FILTER_ARG:
           {
-            /* pdf_stm_install_flatedec_filter (input,
-               PDF_STM_FILTER_READ); */
+            ret = pdf_hash_new (NULL, &flatedec_filter_params);
+            if (ret != PDF_OK)
+              {
+                pdf_error (ret, stderr, "while creating the rldec filter 
parameters hash table");
+                exit (1);
+              }
+
+            pdf_stm_install_filter (stm,
+                                    PDF_STM_FILTER_FLATE_DEC,
+                                    flatedec_filter_params);
             break;
           }
         case FLATEENC_FILTER_ARG:
           {
-            /* pdf_stm_install_flateenc_filter (input,
-               PDF_STM_FILTER_READ); */
+            ret = pdf_hash_new (NULL, &flateenc_filter_params);
+            if (ret != PDF_OK)
+              {
+                pdf_error (ret, stderr, "while creating the rldec filter 
parameters hash table");
+                exit (1);
+              }
+
+            pdf_stm_install_filter (stm,
+                                    PDF_STM_FILTER_FLATE_ENC,
+                                    flateenc_filter_params);
             break;
           }
 #endif /* HAVE_LIBZ */

# Begin bundle
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
/8XckU4UJARl4zoA

###

cheers,
-gerel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]