pdf-devel
[Top][All Lists]
Advanced

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

[pdf-devel] Patch for Flate filter improved


From: gerel
Subject: [pdf-devel] Patch for Flate filter improved
Date: Sat, 04 Oct 2008 14:09:08 -0700 (PDT)


Duh, here is an improved patch for the flate encoder.

##
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: address@hidden
# target_branch: file:///home/gerel/PROJECTS/libgnupdf/trunk/
# testament_sha1: b8b25117710fc027952cc4005ed404c205fb4619
# timestamp: 2008-10-04 18:04:18 -0300
# base_revision_id: address@hidden
# 
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog   2008-10-04 18:44:47 +0000
+++ ChangeLog   2008-10-04 20:36:54 +0000
@@ -1,11 +1,32 @@
 2008-10-04  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-10-04  Gerardo E. Gidoni  <address@hidden>
+
        * src/base/pdf-stm-f-rl.c: adapted to new filter API.
 
        * torture/unit/base/stm/pdf-stm-read.c: same.
 
        * torture/unit/base/stm/pdf-stm-write.c: same.
 
+
 2008-10-04  Jose E. Marchesi  <address@hidden>
 
        * doc/pdf-filter.1: Generated.

=== 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-10-01 21:19:40 +0000
@@ -44,11 +44,11 @@
                      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 
 
-# if ZLIB
-#  STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h
-#endif
+if ZLIB
+  STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h
+endif
 
 TEXT_MODULE_SOURCES = base/pdf-text-context.c base/pdf-text-context.h \
                       base/pdf-text-encoding.c base/pdf-text-encoding.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-04 21:03:53 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/03/05 12:24:36 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-04 18:03:28 gerel"
  *
  *       File:         pdf-stm-f-flate.c
  *       Date:         Tue Jul 10 23:44:00 2007
@@ -26,172 +26,324 @@
 
 #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);
+static pdf_status_t deflate_inbuf_return (pdf_stm_f_flate_t st,
+                                          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 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->writing_p = PDF_FALSE;
+      filter_state->to_write = 0;
+      filter_state->incnt = 0;
+      filter_state->outcnt = 0;
+      filter_state->zret = Z_OK;
+
+      if (deflateInit (&(filter_state->stream), Z_DEFAULT_COMPRESSION) != Z_OK)
+        {
+          ret = PDF_ERROR;
+        }
+      else
+        {
+          *state = (void *) filter_state;
+          ret = PDF_OK;
+        }
+    }
+
+  return ret;
+}
+
+
+pdf_status_t
+pdf_stm_f_flatedec_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->stream.avail_in = 0;
+      filter_state->stream.next_in = Z_NULL;
+      filter_state->writing_p = PDF_FALSE;
+      filter_state->to_write = 0;
+      filter_state->incnt = 0;
+      filter_state->outcnt = 0;
+      filter_state->zret = Z_OK;
+
+      if (inflateInit (&(filter_state->stream)) != Z_OK)
+        {
+          ret = PDF_ERROR;
+        }
+      else
+        {
+          *state = (void *) filter_state;
+          ret = PDF_OK;
+        }
+    }
+
+  return ret;
+
+}
+
+
+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;
+
+
+  /* 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++;
+        }
+      /* If more data may come and the input CHUNK has space, ask for it. */
+      if (!finish_p && st->incnt < PDF_STM_F_FLATE_CHUNK)
+        {
+          return PDF_ENINPUT;
+        }
+    }
+    
+  /* 
+   * Now we have the input CHUNK full or finish_p is set,
+   * we deflate and write to out.
+   */ 
+  return (deflate_inbuf_return (st, out, finish_p));
+}
+
+
+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;
+
+  /* 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)
+    {
+      return PDF_ENINPUT;
+    }
+
+  /* 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;
       }
-    }
-  
-  /* 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;
-}
+
+    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_ENOUTPUT;
+      }
+  } while (st->stream.avail_out == 0);
+
+  if (st->zret == Z_STREAM_END)
+    {
+      return PDF_EEOF;
+    }
+  /* 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_ENINPUT;
+    }
+
+  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;
+deflate_inbuf (pdf_stm_f_flate_t st, pdf_stm_buffer_t out, int flush)
+{
+  if (st->writing_p)
+    {
+      /* 
+       * 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;
+    }
+
+  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 = 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;
+
+  writing:
+
+    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))
+      {
+        st->writing_p = PDF_TRUE;
+        return 1;
+      }
+  } while (st->stream.avail_out == 0);
+
+  st->writing_p = PDF_FALSE;
+  return 0;
+}
+
+
+static pdf_status_t
+deflate_inbuf_return (pdf_stm_f_flate_t st, pdf_stm_buffer_t out,
+                      pdf_bool_t finish_p)
+{
   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);
+  if (finish_p)
+    {
+      ret = deflate_inbuf(st, out, Z_FINISH);
+    }
+  else
+    {
+      ret = deflate_inbuf(st, out, Z_NO_FLUSH);
+    }
+
+  if (ret < 0)
+    {
+      return PDF_ERROR;
+    }
+  else if (ret > 0)
+    {
+      return PDF_ENOUTPUT;
+    }
+  else if (finish_p)
+    {
+      deflateEnd (&(st->stream));
+      return PDF_EEOF;
+    }
+  else
+    {
+      /* the input CHUNK now is empty */
+      st->incnt = 0;
       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;
 }
 
 

=== 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 21:19:40 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/02/11 01:04:11 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-01 18:16:15 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 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-10-04 12:31:11 +0000
+++ src/base/pdf-stm-filter.c   2008-10-04 19:29:59 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/10/04 04:35:11 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-04 16:25:56 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-10-04 12:31:11 +0000
+++ src/base/pdf-stm-filter.h   2008-10-04 19:29:59 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/10/04 04:34:08 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-04 16:26:39 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_ENC,
+  PDF_STM_FILTER_FLATE_DEC
+
 };
 
 /* Filter implementation */

=== modified file 'torture/unit/base/stm/pdf-stm-read.c'
--- torture/unit/base/stm/pdf-stm-read.c        2008-10-04 18:44:47 +0000
+++ torture/unit/base/stm/pdf-stm-read.c        2008-10-04 20:36:54 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "2008-10-04 15:42:24 gerel"
+/* -*- mode: C -*- Time-stamp: "2008-10-04 16:38:06 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,
+                         1,
+                         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-10-04 18:44:47 +0000
+++ torture/unit/base/stm/pdf-stm-write.c       2008-10-04 20:36:54 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "2008-10-04 15:38:46 gerel"
+/* -*- mode: C -*- Time-stamp: "2008-10-04 17:29:25 gerel"
  *
  *       File:         pdf-stm-write.c
  *       Date:         Sun Sep 21 16:37:27 2008
@@ -347,6 +347,86 @@
 }
 END_TEST
 
+
+/*
+ * Test: pdf_stm_write_007
+ * Description:
+ *   Create a memory-based reading stream and attach a flate filter
+ *   encoder to it.
+ * Success condition:
+ *   The decoded 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,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,
+                         1,
+                         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;
+  total = 1059;
+  dataux = decoded;
+  while (total > 0)
+    {
+      written = pdf_stm_write (stm, dataux, total);
+      dataux = dataux + written;
+      total -= written;
+    }
+  pdf_stm_flush (stm, PDF_TRUE);
+
+  fail_if (memcmp (buf, encoded, 41) != 0);
+  /* Destroy the stream */
+  pdf_stm_destroy (stm);
+  pdf_dealloc (buf);
+
+}
+END_TEST
+
+
 /*
  * Test case creation function
  */
@@ -361,6 +441,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;
 }

# Begin bundle
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
Qd14

###

-gerel




reply via email to

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