pdf-devel
[Top][All Lists]
Advanced

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

[pdf-devel] LZW filter re-implementation


From: Juan Pedro Bolivar Puente
Subject: [pdf-devel] LZW filter re-implementation
Date: Sun, 28 Jun 2009 01:31:27 +0200
User-agent: Mozilla-Thunderbird 2.0.0.19 (X11/20090103)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

I attach a new patch trying to adapt the LZW filter implementation to
the new filter API.

Some comments:

1. The filter now works with any cache size. I tested with the submited
test cases (from the standard specification) and long playing with
pdf-filter :)

2. Because of the cache size stuff, those embarrassing weird goto's are
kept. Maybe we can consider allowing the filters specify a
"minimum-cache" parameter to avoid non-necessary code bloat and/or
efficiency tradeoffs?

3. I added the pdf-filter patch submitted by jemarch the other day.

4. I factored out the test cases sent by Brad Hards using fixtures to
allocate/deallocate the stream. This may cause an overhead in the
overall runing time as the fixture is setup/teareddown on every test
cases. I still think that it would be useful to factor-out other tests
to use this fixture and so avoid setup/dealloc boilerplate -I did not do
it in case their authors disagree.

5. I disabled the tokenizer utility, it seems that a header file was
forgotten in the last commit.

6. Many thanks to Brad Hards for his work in this task.

Enjoy :)

JP
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkpGq88ACgkQchi8veCammch/ACgnWu88IA2zgJOnG58MdaAcM60
TgEAnAllNQRLslljhfNYfjThT8zTasn2
=REVR
-----END PGP SIGNATURE-----
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: address@hidden
# target_branch: http://bzr.savannah.gnu.org/r/pdf/libgnupdf/branches\
#   /trunk/
# testament_sha1: 6260da11d5ebb802e1a33b95dd7ec3a00cf74f2d
# timestamp: 2009-06-28 01:20:01 +0200
# base_revision_id: address@hidden
# 
# Begin patch
=== modified file 'AUTHORS'
--- AUTHORS     2009-06-24 19:25:52 +0000
+++ AUTHORS     2009-06-27 23:19:51 +0000
@@ -282,6 +282,7 @@
 and changed utils/pdf-filter.c utils/pdf-filter.h
     src/base/pdf-stm.c src/base/pdf-stm.h
     src/base/pdf-stm-be.c src/base/pdf-stm-be.h
+    torture/unit/base/stm/pdf-stm-write.c
 
 Karl Berry: changed doc/gnupdf.texi doc/gnupdf-utils.texi
   doc/Makefile.am 

=== modified file 'ChangeLog'
--- ChangeLog   2009-06-24 19:25:52 +0000
+++ ChangeLog   2009-06-27 23:19:51 +0000
@@ -1,3 +1,16 @@
+2009-06-28  Juan Pedro Bolívar Puente  <address@hidden>
+
+       * src/base/pdf-stm-f-lzw.c: port of LZW filter to new API
+       * src/base/pdf-stm-f-lzw.h: likewise
+       * src/base/pdf-stm-filter.c: likewise
+       * src/base/pdf-stm-filter.h: likewise
+       * src/Makefile.am: integrate pdf-stm-f-lzw.[c,h] back into build
+       system
+       * torture/unit/base/stm/pdf-stm-write.c: add test case from PDF
+       specification version 1.7.
+       * (Brad Hards contributed to this patch)
+       * util/pdf-filter.c: added LZW filter. (by Jose E. Marchesi)
+
 2009-06-24  Jose E. Marchesi  <address@hidden>
 
        * doc/pdf-tokeniser.1: New file, generated from
@@ -14,6 +27,19 @@
 
        * utils/pdf-tokeniser.c: Renamed from 'utils/toktest.c'.
 
+
+2009-06-24  Jose E. Marchesi  <address@hidden>
+
+       * src/base/pdf-hash-helper.h: Added functions 'pdf_hash_add_bool'
+       and 'pdf_hash_get_bool'.
+
+       * src/base/pdf-hash-helper.c: Likewise.
+
+       * utils/pdf-filter.h: Added support for the LZW filters.
+
+       * utils/pdf-filter.c: Likewise.
+
+
 2009-06-22  Brad Hards  <address@hidden>
 
        * src/base/pdf-text.c (pdf_text_dup): Protect against NULL arg.

=== modified file 'src/Makefile.am'
--- src/Makefile.am     2009-05-20 15:54:43 +0000
+++ src/Makefile.am     2009-06-27 23:19:51 +0000
@@ -46,7 +46,8 @@
                      base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c \
                      base/pdf-stm-f-v2.h base/pdf-stm-f-v2.c \
                      base/pdf-stm-f-aesv2.h base/pdf-stm-f-aesv2.c \
-                     base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c
+                     base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c \
+                     base/pdf-stm-f-lzw.h base/pdf-stm-f-lzw.c
 
 if ZLIB
   STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h

=== modified file 'src/base/pdf-hash-helper.c'
--- src/base/pdf-hash-helper.c  2009-01-27 20:59:40 +0000
+++ src/base/pdf-hash-helper.c  2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/01/27 21:37:10 jemarch"
+/* -*- mode: C -*- Time-stamp: "09/06/24 20:13:29 jemarch"
  *
  *       File:         pdf-hash-helper.c
  *       Date:         Thu Jul 24 21:05:05 2008
@@ -97,6 +97,37 @@
 }
 
 pdf_status_t
+pdf_hash_add_bool (pdf_hash_t table, const char *key, const pdf_bool_t elt)
+{
+  pdf_bool_t *vbool;
+
+  vbool = pdf_alloc (sizeof(pdf_bool_t));
+  if (vbool == NULL)
+    {
+      return PDF_ERROR;
+    }
+
+  *vbool = elt;
+
+  return (pdf_hash_add (table, key, vbool, pdf_dealloc));
+}
+
+pdf_status_t
+pdf_hash_get_bool (pdf_hash_t table, const char *key, pdf_bool_t *elt)
+{
+  pdf_status_t ret;
+  pdf_bool_t *vbool;
+
+  ret = pdf_hash_get (table, key, (const void **) &vbool);
+  if (ret == PDF_OK)
+    {
+      *elt = *vbool;
+    }
+
+  return ret;
+}
+
+pdf_status_t
 pdf_hash_add_size (pdf_hash_t table, const char *key, const pdf_size_t elt)
 {
   pdf_size_t *size;

=== modified file 'src/base/pdf-hash-helper.h'
--- src/base/pdf-hash-helper.h  2008-12-28 01:13:47 +0000
+++ src/base/pdf-hash-helper.h  2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/12/28 02:10:50 jemarch"
+/* -*- mode: C -*- Time-stamp: "09/06/24 20:13:57 jemarch"
  *
  *       File:         pdf-hash-helper.h
  *       Date:         Thu Jul 24 21:05:05 2008
@@ -73,6 +73,12 @@
 pdf_hash_get_size (pdf_hash_t table, const char *key, pdf_size_t *elt);
 
 pdf_status_t
+pdf_hash_add_bool (pdf_hash_t table, const char *key, const pdf_bool_t elt);
+
+pdf_status_t
+pdf_hash_get_bool (pdf_hash_t table, const char *key, pdf_bool_t *elt);
+
+pdf_status_t
 pdf_hash_add_string (pdf_hash_t table, const char *key, const pdf_char_t *elt);
 
 pdf_status_t

=== modified file 'src/base/pdf-stm-f-lzw.c'
--- src/base/pdf-stm-f-lzw.c    2009-01-11 21:37:29 +0000
+++ src/base/pdf-stm-f-lzw.c    2009-06-27 23:19:51 +0000
@@ -1,9 +1,9 @@
-/* -*- mode: C -*- Time-stamp: "09/01/11 22:04:33 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-06-28 00:40:49 raskolnikov"
  *
  *       File:         pdf-stm-f-lzw.c
  *       Date:         Wed Aug 15 14:41:18 2007
  *
- *       GNU PDF Library - LWZ encoder/decoder filter
+ *       GNU PDF Library - LZW encoder/decoder filter
  *
  */
 
@@ -25,23 +25,23 @@
 
 #include <string.h>
 #include <pdf-alloc.h>
+#include <pdf-hash-helper.h>
 #include <pdf-stm-f-lzw.h>
 
-#define MIN_BITSIZE 9
-#define MAX_BITSIZE 12
-#define MAX_DICTSIZE (1 << MAX_BITSIZE)
-
-#define MAX_COMPRESSION_FACTOR 1.5
-
-#define NULL_INDEX ~0U
-
-enum {
-  LZW_RESET_CODE = 256,
-  LZW_EOD_CODE,
-  LZW_FIRST_CODE
-} lzw_special_codes;
-
-
+#define LZW_DEFAULT_EARLY_CHANGE  1
+
+#define LZW_CACHE_SIZE    16
+#define LZW_MIN_BITSIZE   9
+#define LZW_MAX_BITSIZE   12
+#define LZW_MAX_DICTSIZE  (1 << LZW_MAX_BITSIZE)
+#define LZW_NULL_INDEX    ~0U
+
+enum lzw_special_codes_e
+  {
+    LZW_RESET_CODE = 256,
+    LZW_EOD_CODE,
+    LZW_FIRST_CODE
+  };
 
 /* -- LZW code output/input -- */
 
@@ -49,54 +49,79 @@
  * Object to read and write codes of variable bitsize in a buffer.
  * Warning: using both get and put functions may break the buffer.
  */
-typedef struct lzw_buffer_s
+struct lzw_buffer_s
 {
-  pdf_char_t* curp;
-  pdf_char_t* endp;
+  pdf_buffer_t buf;
+  pdf_char_t cache [LZW_CACHE_SIZE];
+  int cache_rp;
+  int cache_wp;
   unsigned long valbuf;
-  unsigned valbits;
-  unsigned bitsize;
-  unsigned maxval;
-} lzw_buffer_t;
+  int valbits;
+  int bitsize;
+  int maxval;
+};
+typedef struct lzw_buffer_s* lzw_buffer_t;
 
 static void
-lzw_buffer_init (lzw_buffer_t* b, 
-                pdf_char_t* ptr,
-                int size,
+lzw_buffer_init (lzw_buffer_t b,
                 int bitsize)
 {
-  b->curp = ptr;
-  b->endp = ptr + size;
+  b->buf = NULL;
   b->valbuf = 0;
   b->valbits = 0;
   b->bitsize = bitsize;
   b->maxval = (1 << bitsize) - 1;
-}
-
-static unsigned int
-lzw_buffer_get_code (lzw_buffer_t* b)
+  b->cache_wp = 0;
+  b->cache_rp = 0;
+}
+
+static void
+lzw_buffer_set (lzw_buffer_t b,
+               pdf_buffer_t buf)
+{
+  b->buf = buf;
+}
+
+static pdf_status_t
+lzw_buffer_get_code (lzw_buffer_t b,
+                    unsigned int* code,
+                    pdf_bool_t finish_p)
 {
   unsigned long r;
-  
-  while (b->valbits <= 24)
-  {
-    if (b->curp > b->endp)
-      return NULL_INDEX;
-    
-    b->valbuf |= (unsigned long) *b->curp++ << (24 - b->valbits);
-    b->valbits += 8;
-  }
+
+  while (b->valbits <= 24 && !finish_p)
+    {
+      if (pdf_buffer_eob_p (b->buf))
+       {
+         return PDF_ENINPUT;
+       }
+      else
+       {
+         b->valbuf |=
+           (unsigned int) b->buf->data [b->buf->rp++] <<
+           (24 - b->valbits);
+       
+         b->valbits += 8;
+       }
+    }
+
+  if (b->valbits < b->bitsize)
+    {
+      return PDF_EEOF;
+    }
 
   r = b->valbuf >> (32 - b->bitsize);
   b->valbuf <<= b->bitsize;
   b->valbits -= b->bitsize;
-  
-  return r;
+      
+  *code = r;
+
+  return PDF_OK;
 }
 
 /* Once finished, call with 0 as code value to flush the buffer. */
 static void
-lzw_buffer_put_code (lzw_buffer_t* b,
+lzw_buffer_put_code (lzw_buffer_t b,
                     unsigned int code)
 {
   b->valbuf |= (unsigned long) code << (32 - b->bitsize - b->valbits);
@@ -104,17 +129,46 @@
 
   while (b->valbits >= 8)
     {
-      *b->curp++ = b->valbuf >> 24;
+      if (pdf_buffer_full_p (b->buf))
+       {
+         b->cache [b->cache_wp++] = (pdf_char_t) (b->valbuf >> 24);
+       }
+      else
+       {
+         b->buf->data [b->buf->wp++] = (pdf_char_t) (b->valbuf >> 24);
+       }
       b->valbuf <<= 8;
       b->valbits -= 8;
     }
 }
 
+static pdf_status_t
+lzw_buffer_flush (lzw_buffer_t b)
+{
+  while (b->cache_rp != b->cache_wp &&
+        !pdf_buffer_full_p (b->buf))
+    {
+      b->buf->data [b->buf->wp++] = b->cache [b->cache_rp++];
+    }
+
+  if (pdf_buffer_full_p (b->buf))
+    {
+      return PDF_ENOUTPUT;
+    }
+  
+  b->cache_wp = 0;
+  b->cache_rp = 0;
+  
+  return PDF_OK;
+}
+
 static int
-lzw_buffer_inc_bitsize (lzw_buffer_t* b)
+lzw_buffer_inc_bitsize (lzw_buffer_t b)
 {
-  if (b->bitsize == MAX_BITSIZE)
-    return PDF_ERROR;
+  if (b->bitsize == LZW_MAX_BITSIZE)
+    {
+      return PDF_ERROR;
+    }
   
   ++b->bitsize;
   b->maxval = (1 << b->bitsize) - 1;
@@ -123,20 +177,19 @@
 }
 
 static void
-lzw_buffer_set_bitsize (lzw_buffer_t* b,
+lzw_buffer_set_bitsize (lzw_buffer_t b,
                        int newsize)
 {
   b->bitsize = newsize;
   b->maxval = (1 << newsize) - 1;
 }
 
-
 /* -- LZW dictionary handler -- */
 
 /*
  * The strings are stored in a non balanced ordered binary tree.
  */
-typedef struct lzw_string_s
+struct lzw_string_s
 {
   unsigned prefix;   /* Prefix string code */
   pdf_char_t suffix; /* Appended character */
@@ -144,44 +197,48 @@
   unsigned first; /* First string with the same prefix.  */
   unsigned left;  /* Next string with smaller suffix and same prefix. */
   unsigned right; /* Next string with greater suffix and same prefix. */
-} lzw_string_t;
+};
+
+typedef struct lzw_string_s* lzw_string_t;
 
 static void
-lzw_string_init (lzw_string_t* s)
+lzw_string_init (lzw_string_t s)
 {
-  memset(s, 0xFF, sizeof(lzw_string_t));
+  memset (s, 0xFF, sizeof (struct lzw_string_s));
 }
 
-
-typedef struct lzw_dict_s
+struct lzw_dict_s
 {
-  lzw_string_t table[MAX_DICTSIZE];
+  struct lzw_string_s table [LZW_MAX_DICTSIZE];
   unsigned size;
-} lzw_dict_t;
+};
+typedef struct lzw_dict_s* lzw_dict_t;
 
 static void
-lzw_dict_init (lzw_dict_t* d)
+lzw_dict_init (lzw_dict_t d)
 {
   int i;
   
-  memset(d->table, 0xFF, sizeof(lzw_string_t) * MAX_DICTSIZE);
+  memset (d->table,
+         0xFF,
+         sizeof (struct lzw_string_s) * LZW_MAX_DICTSIZE);
 
   for (i = 0; i < LZW_FIRST_CODE; i++)
     {
-      d->table[i].suffix = i;
+      d->table[i].suffix = (pdf_char_t) (i & 0xFF);
     }
 
   d->size = LZW_FIRST_CODE;
 }
 
-static int
-lzw_dict_add (lzw_dict_t* d,
-             lzw_string_t* s)
+static pdf_bool_t
+lzw_dict_add (lzw_dict_t d,
+             lzw_string_t s)
 {
   unsigned index;
   int must_add;
   
-  if (s->prefix == NULL_INDEX)
+  if (s->prefix == LZW_NULL_INDEX)
     {
       s->prefix = s->suffix;
       return PDF_FALSE; /* The string is a basic character, found! */
@@ -189,7 +246,7 @@
   
   index = d->table[s->prefix].first;
 
-  if (index == NULL_INDEX)
+  if (index == LZW_NULL_INDEX)
     {
       d->table[s->prefix].first = d->size;
     }
@@ -205,7 +262,7 @@
            }
          else if (s->suffix < d->table[index].suffix)
            {
-             if (d->table[index].left == NULL_INDEX)
+             if (d->table[index].left == LZW_NULL_INDEX)
                {
                  d->table[index].left = d->size;
                  must_add = PDF_TRUE;
@@ -217,7 +274,7 @@
            }
          else
            {
-             if (d->table[index].right == NULL_INDEX)
+             if (d->table[index].right == LZW_NULL_INDEX)
                {
                  d->table[index].right = d->size;
                  must_add = PDF_TRUE;
@@ -235,10 +292,14 @@
   return PDF_TRUE;
 }
 
-#define lzw_dict_reset lzw_dict_init
+static void
+lzw_dict_reset (lzw_dict_t dict)
+{
+  lzw_dict_init (dict);
+}
 
 static void
-lzw_dict_fast_add (lzw_dict_t* d,
+lzw_dict_fast_add (lzw_dict_t d,
                   unsigned prefix,
                   pdf_char_t suffix)
 {
@@ -248,309 +309,392 @@
 }
 
 static void
-lzw_dict_decode (lzw_dict_t* d,
+lzw_dict_decode (lzw_dict_t d,
                 unsigned code,
                 pdf_char_t** decode,
                 unsigned* size)
 {
   *size = 0;
 
-  do {
-    *(*decode)-- = d->table[code].suffix;
-    ++(*size);
-    code = d->table[code].prefix;
-  } while (code != NULL_INDEX);
+  do
+    {
+      *(*decode)-- = d->table[code].suffix;
+      ++(*size);
+      code = d->table[code].prefix;
+    }
+  while (code != LZW_NULL_INDEX);
+
   (*decode)++;
-  
 }
 
-/* -- The encoder -- */
-
-static int
-pdf_stm_f_lzw_encode (pdf_stm_f_lzw_data_t data,
-                      pdf_char_t *in,
-                      pdf_stm_pos_t in_size,
-                      pdf_char_t **out,
-                      pdf_stm_pos_t *out_size)
-{
-  lzw_buffer_t buffer;
-  lzw_dict_t dict;
-  lzw_string_t string;
-  
-  /* Allocate buffer with enough space. */
-  *out_size = in_size * MAX_COMPRESSION_FACTOR;
-  if ((*out = (pdf_char_t *) pdf_alloc (*out_size)) == NULL)
+/* -- THE ENCODER -- */
+
+struct lzwenc_state_s
+{
+  /* cached params */
+  pdf_i32_t early_change;
+
+  /* encoding state */
+  pdf_bool_t           must_reset_p;
+  struct lzw_buffer_s  buffer;
+  struct lzw_dict_s    dict;
+  struct lzw_string_s  string;
+
+  pdf_bool_t           really_finish_p;
+};
+typedef struct lzwenc_state_s* lzwenc_state_t;
+
+pdf_status_t
+pdf_stm_f_lzwenc_init (pdf_hash_t params,
+                      void **ext_state)
+{
+  pdf_char_t *early_change_str;
+  lzwenc_state_t state;
+
+  state = pdf_alloc (sizeof (struct lzwenc_state_s));
+  if (!state)
     {
-      *out_size = 0;
       return PDF_ERROR;
     }
-
-  /* Do the actual encoding. */
-  lzw_buffer_init(&buffer, *out, *out_size, MIN_BITSIZE);
-  lzw_dict_init(&dict);
-  lzw_string_init(&string);
-
-  lzw_buffer_put_code(&buffer, LZW_RESET_CODE);
-
-  while (--in_size >= 0)
-    {
-      string.suffix = *in++;
-
-      if (lzw_dict_add(&dict, &string))
+  
+  state->early_change = 1; /* set default */
+  
+  if (pdf_hash_key_p (params, "EarlyChange") == PDF_TRUE)
+    {
+      pdf_hash_get_string (params, "EarlyChange", &early_change_str);
+      if (early_change_str[0] == '0')
+        {
+          state->early_change = 0;
+        }
+    }
+
+  lzw_buffer_init (&state->buffer, LZW_MIN_BITSIZE);
+  lzw_dict_init (&state->dict);
+  lzw_string_init (&state->string);
+  state->must_reset_p = PDF_TRUE;
+  state->really_finish_p = PDF_FALSE;
+  
+  *ext_state = state;
+  return PDF_OK;
+}
+
+pdf_status_t
+pdf_stm_f_lzwenc_apply (pdf_hash_t params,
+                       void *ext_state,
+                       pdf_buffer_t in,
+                       pdf_buffer_t out,
+                       pdf_bool_t finish_p)
+{
+  pdf_status_t ret;
+  lzwenc_state_t st;
+
+  ret = PDF_OK;
+  st  = ext_state;
+  lzw_buffer_set (&st->buffer, out);
+
+  ret = lzw_buffer_flush (&st->buffer);
+  if (ret != PDF_OK)
+    {
+      return ret;
+    }
+  
+  if (st->really_finish_p)
+    {
+      return PDF_EEOF;
+    }
+  
+  if (st->must_reset_p)
+    {
+      lzw_buffer_put_code (&st->buffer, LZW_RESET_CODE);
+      st->must_reset_p = PDF_FALSE;
+    }
+  
+  while (!pdf_buffer_eob_p (in) &&
+        !pdf_buffer_full_p (out))
+    {
+      st->string.suffix = in->data [in->rp++];
+      if (lzw_dict_add (&st->dict, &st->string))
        {
-         lzw_buffer_put_code(&buffer, string.prefix);
-         string.prefix = string.suffix;
+         lzw_buffer_put_code (&st->buffer, st->string.prefix);
+         st->string.prefix = st->string.suffix;
 
-         if (buffer.maxval - data->early_change == dict.size)
+         if (st->buffer.maxval - st->early_change == st->dict.size)
            {
-             if (!lzw_buffer_inc_bitsize(&buffer))
+             if (!lzw_buffer_inc_bitsize(&st->buffer))
                {
-                 lzw_buffer_put_code(&buffer, LZW_RESET_CODE);
-                 lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE);
-                 lzw_dict_reset(&dict);
+                 lzw_buffer_put_code (&st->buffer, LZW_RESET_CODE);
+                 lzw_buffer_set_bitsize (&st->buffer, LZW_MIN_BITSIZE);
+                 lzw_dict_reset (&st->dict);
                }
            }
        }
     }
-  
-  lzw_buffer_put_code(&buffer, string.prefix);
-  if (buffer.maxval - data->early_change == dict.size)
-    lzw_buffer_inc_bitsize(&buffer);
-  lzw_buffer_put_code(&buffer, LZW_EOD_CODE);
-  lzw_buffer_put_code(&buffer, 0);
-
-  /* Resize buffer to fit the data. */
-  *out_size = (buffer.curp - *out);
-  if ((*out = pdf_realloc(*out, *out_size)) == NULL)
-    {
-      *out_size = 0;
-      return PDF_ERROR;
-    }
-
-  return PDF_OK;
-}
-
-/* -- The decoder -- */
-
-/* Utility to write to the output. */
-
-typedef struct lzw_writer_s
-{
-  pdf_char_t* buf;
-  pdf_char_t* cur;
-  int writen;
-  int allocated;
-} lzw_writer_t;
-
-static int
-lzw_writer_init (lzw_writer_t* s,
-                int size)
-{
-  if ((s->buf = pdf_alloc(size)) == NULL)
-    {
-      return PDF_ERROR;
-    }
-
-  s->cur = s->buf;
-  s->writen = 0;
-  s->allocated = size;
-  
-  return PDF_OK;
-}
-
-static int
-lzw_writer_fit (lzw_writer_t* s)
-{
-  if ((s->buf = pdf_realloc(s->buf, s->writen)) == NULL)
-    {
-      return PDF_ERROR;
-    }
-
-  s->cur = s->buf + s->writen;
-  s->allocated = s->writen;
-  
-  return PDF_OK;
-}
-
-static int
-lzw_writer_put (lzw_writer_t* s,
-               pdf_char_t* data,
-               unsigned size)
-{
-  if (s->allocated < s->writen + size)
-    {
-      s->allocated = s->allocated * 2 + 1;
-      if ((s->buf = pdf_realloc(s->buf, s->allocated)) == NULL)
-       {
-         return PDF_ERROR;
-       }
-      s->cur = s->buf + s->writen;
-    }
-
-  memcpy(s->cur, data, size);
-  s->cur += size;
-  s->writen += size;
-  
-  return PDF_OK;
-}
-
-static void
-lzw_writer_destroy (lzw_writer_t* s)
-{
-  pdf_dealloc (s->buf);
-}
-
-static int
-pdf_stm_f_lzw_decode (pdf_stm_f_lzw_data_t data,
-                      pdf_char_t *in,
-                      pdf_stm_pos_t in_size,
-                      pdf_char_t **out,
-                      pdf_stm_pos_t *out_size)
-{
-  pdf_char_t dec_buf[MAX_DICTSIZE];
+
+  if (finish_p)
+    {
+      lzw_buffer_put_code (&st->buffer, st->string.prefix);
+      if ((st->buffer.maxval - st->early_change) == st->dict.size)
+       {
+         lzw_buffer_inc_bitsize(&st->buffer);
+       }
+      
+      lzw_buffer_put_code (&st->buffer, LZW_EOD_CODE);
+      lzw_buffer_put_code (&st->buffer, 0); /* flush */
+
+      if (pdf_buffer_full_p (out))
+       {
+         ret = PDF_ENOUTPUT;
+       }
+      else
+       {
+         ret = PDF_EEOF;
+       }
+
+      st->really_finish_p = PDF_TRUE;
+    }
+  else if (pdf_buffer_full_p (out))
+    {
+      ret = PDF_ENOUTPUT;
+    }
+  else if (pdf_buffer_eob_p (in))
+    {
+      ret = PDF_ENINPUT;
+    }
+  
+  return ret;
+}
+
+pdf_status_t
+pdf_stm_f_lzwenc_dealloc_state (void *state)
+{
+  pdf_dealloc (state);
+  return PDF_OK;
+}
+
+/* -- THE DECODER -- */
+
+enum lzwdec_state
+  {
+    LZWDEC_STATE_START,
+    LZWDEC_STATE_CLEAN,
+    LZWDEC_STATE_WRITE,
+    LZWDEC_STATE_READ,
+    LZWDEC_STATE_LOOP_WRITE,
+    LZWDEC_STATE_LOOP_READ
+  };
+
+struct lzwdec_state_s
+{
+  /* cached params */
+  pdf_i32_t early_change;
+
+  /* state */
+  pdf_char_t  dec_buf [LZW_MAX_DICTSIZE];
   pdf_char_t* decoded;
-  unsigned dec_size;
+  unsigned    dec_size;
   
   unsigned new_code;
   unsigned old_code;
-   
-  lzw_buffer_t buffer;
-  lzw_dict_t dict;
-  lzw_writer_t writer;
-
-  *out = NULL;
-  *out_size = 0;
-
-  if (lzw_writer_init(&writer, in_size) == PDF_ERROR)
-    return PDF_ERROR;
-  
-  lzw_buffer_init(&buffer, in, in_size,  MIN_BITSIZE);
-  lzw_dict_init(&dict);
-  old_code = NULL_INDEX;
-  
-  do {
-    lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE);
-    lzw_dict_reset(&dict);
-
-    do {
-      new_code = lzw_buffer_get_code(&buffer);
-    } while(new_code == LZW_RESET_CODE);
-    
-    if (new_code == NULL_INDEX)
-      {
-       lzw_writer_destroy(&writer);
-       return PDF_ERROR;
-      }
-    
-    if (new_code != LZW_EOD_CODE)
-      {
-       if (lzw_writer_put(&writer, (pdf_char_t*)&new_code, 1) == PDF_ERROR)
-         return PDF_ERROR;
-       
-       old_code = new_code;
-       new_code = lzw_buffer_get_code(&buffer);
-      }
-    
-    while (new_code != LZW_EOD_CODE && new_code != LZW_RESET_CODE)
-      {
-       decoded = &(dec_buf[MAX_DICTSIZE-2]);
-       
-       if (new_code < dict.size) /* Is new code in the dict? */
-         {
-           lzw_dict_decode(&dict, new_code, &decoded, &dec_size);
-           lzw_dict_fast_add(&dict, old_code, decoded[0]);
-         }
-       else
-         {
-           lzw_dict_decode(&dict, old_code, &decoded, &dec_size);
-           lzw_dict_fast_add(&dict, old_code, decoded[0]);
-           decoded[dec_size++] = decoded[0];
-         }
-
-       if (lzw_writer_put(&writer, decoded, dec_size) == PDF_ERROR)
-           return PDF_ERROR;
-
-       if (dict.size == buffer.maxval - 1 - data->early_change)
-         if (!lzw_buffer_inc_bitsize(&buffer));
-           /* break; We must wait for the reset code, don't reset yet. */
-       
-       old_code = new_code;
-       new_code = lzw_buffer_get_code(&buffer);
-       
-       if (new_code == NULL_INDEX)
-         {
-           lzw_writer_destroy(&writer);
-           return PDF_ERROR;
-         }
-      }
-  } while (new_code != LZW_EOD_CODE);
-  
-  if (lzw_writer_fit(&writer) == PDF_ERROR)
-    return PDF_ERROR;
-  
-  *out = writer.buf;
-  *out_size = writer.writen;
-
-  return PDF_OK;  
-}
-
-
-/* -- PDF Filter functions --*/
-
-int 
-pdf_stm_f_lzw_init (void **filter_data,
-                    void *conf_data)
-{
-  pdf_stm_f_lzw_data_t *data;
-  pdf_stm_f_lzw_conf_t conf;
-
-  data = (pdf_stm_f_lzw_data_t *) filter_data;
-  conf = (pdf_stm_f_lzw_conf_t) conf_data;
-
-  /* Create the private data storage */
-  *data =
-    (pdf_stm_f_lzw_data_t) pdf_alloc (sizeof(struct pdf_stm_f_lzw_data_s));
-  (*data)->mode = conf->mode;
-  (*data)->early_change = conf->early_change;
-
-  return PDF_OK;
-}
-
-int
-pdf_stm_f_lzw_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_lzw_data_t data;
-
-  data = (pdf_stm_f_lzw_data_t) filter_data;
-  switch (data->mode)
-    {
-    case PDF_STM_F_LZW_MODE_ENCODE:
-      {
-        return pdf_stm_f_lzw_encode (data, in, in_size, out, out_size);
-      }
-    case PDF_STM_F_LZW_MODE_DECODE:
-      {
-        return pdf_stm_f_lzw_decode (data, in, in_size, out, out_size);
-      }
+
+  /* flow managment */
+  enum lzwdec_state state_pos;
+  pdf_status_t tmp_ret;
+  
+  struct lzw_buffer_s buffer;
+  struct lzw_dict_s   dict;
+};
+typedef struct lzwdec_state_s* lzwdec_state_t;
+
+
+pdf_status_t
+pdf_stm_f_lzwdec_init (pdf_hash_t params,
+                      void **ext_state)
+{
+  pdf_char_t *early_change_str;
+  lzwdec_state_t state;
+
+  state = pdf_alloc (sizeof (struct lzwdec_state_s));
+  if (!state)
+    {
+      return PDF_ERROR;
+    }
+    
+  state->early_change = 1; /* set default */
+  
+  if (pdf_hash_key_p (params, "EarlyChange") == PDF_TRUE)
+    {
+      pdf_hash_get_string (params, "EarlyChange", &early_change_str);
+      if (early_change_str[0] == '0')
+        {
+          state->early_change = 0;
+        }
+    }
+
+  lzw_buffer_init (&state->buffer, LZW_MIN_BITSIZE);
+  lzw_dict_init (&state->dict);
+  state->old_code = LZW_NULL_INDEX;
+  state->decoded = state->dec_buf + (LZW_MAX_DICTSIZE-2);
+  state->dec_size = 0;
+  state->state_pos = LZWDEC_STATE_START;
+  state->tmp_ret = 0;
+    
+  *ext_state = state;
+  return PDF_OK;
+}
+
+pdf_status_t
+lzwdec_put_decoded (lzwdec_state_t st, pdf_buffer_t out)
+{
+  pdf_status_t ret;
+  pdf_size_t to_write;
+  
+  ret = PDF_OK;
+
+  if (st->dec_size)
+    {
+      /* output the decoded string */
+      to_write = st->dec_size;
+      if (st->dec_size > (out->size - out->wp))
+       {
+         to_write = out->size - out->wp;
+         ret = PDF_ENOUTPUT;
+       }
+
+      memcpy (out->data + out->wp, st->decoded, to_write);
+      out->wp += to_write;
+      st->decoded += to_write;
+      st->dec_size -= to_write;
+    }
+
+  return ret;
+}
+
+pdf_status_t
+lzwdec_put_code (lzwdec_state_t st,
+                pdf_buffer_t out,
+                unsigned long  code)
+{
+  if (pdf_buffer_full_p (out))
+    {
+      return PDF_ENOUTPUT;
+    }
+  
+  out->data [out->wp++] = (pdf_char_t) (code & 0xFF);
+  
+  return PDF_OK;
+}
+
+#define LZWDEC_CHECK(st, pos, what)            \
+  do { (st)->state_pos = (pos);                        \
+    if (((st)->tmp_ret = (what)) != PDF_OK)    \
+      { return ((st)->tmp_ret); }              \
+  } while (0);
+
+pdf_status_t
+pdf_stm_f_lzwdec_apply (pdf_hash_t params,
+                       void *ext_state,
+                       pdf_buffer_t in,
+                       pdf_buffer_t out,
+                       pdf_bool_t finish_p)
+{
+  lzwdec_state_t st;
+
+  st = ext_state;
+  lzw_buffer_set (&st->buffer, in);
+
+  switch (st->state_pos)
+    {
+    case LZWDEC_STATE_START:
+      break;
+    case LZWDEC_STATE_CLEAN:
+      goto lzwdec_state_clean;
+    case LZWDEC_STATE_WRITE:
+      goto lzwdec_state_write;
+    case LZWDEC_STATE_READ:
+      goto lzwdec_state_read;
+    case LZWDEC_STATE_LOOP_WRITE:
+      goto lzwdec_state_loop_write;
+    case LZWDEC_STATE_LOOP_READ:
+      goto lzwdec_state_loop_read;
     default:
-      {
-        return PDF_ERROR;
-      }
-    }
-  
-  /* Not reached */
+      break;
+    }
+  
+  do
+    {
+      /* need a reset */
+      lzw_buffer_set_bitsize (&st->buffer, LZW_MIN_BITSIZE);
+      lzw_dict_reset (&st->dict);
+      
+      do 
+       {
+       lzwdec_state_clean:
+         LZWDEC_CHECK (st, LZWDEC_STATE_CLEAN,
+                       lzw_buffer_get_code (&st->buffer, &st->new_code, 
finish_p));
+       }
+      while (st->new_code == LZW_RESET_CODE);
+      
+      if (st->new_code != LZW_EOD_CODE)
+       {
+       lzwdec_state_write:
+         LZWDEC_CHECK (st, LZWDEC_STATE_WRITE,
+                       lzwdec_put_code (st, out, st->new_code));
+
+         st->old_code = st->new_code;
+       lzwdec_state_read:
+         LZWDEC_CHECK (st, LZWDEC_STATE_READ,
+                       lzw_buffer_get_code (&st->buffer, &st->new_code, 
finish_p));  
+       }
+      
+      while (st->new_code != LZW_EOD_CODE &&
+            st->new_code != LZW_RESET_CODE)
+       {
+         st->decoded = st->dec_buf + (LZW_MAX_DICTSIZE-2);
+
+         /* Is new code in the dict? */
+         if (st->new_code < st->dict.size)
+           {
+             lzw_dict_decode (&st->dict, st->new_code,
+                              &st->decoded, &st->dec_size);
+             lzw_dict_fast_add (&st->dict, st->old_code, st->decoded[0]);
+           }
+         else
+           {
+             lzw_dict_decode (&st->dict, st->old_code,
+                              &st->decoded, &st->dec_size);
+             lzw_dict_fast_add (&st->dict, st->old_code, st->decoded[0]);
+             st->decoded [st->dec_size++] = st->decoded [0];
+           }
+
+         /* output the decoded string */
+       lzwdec_state_loop_write:
+         LZWDEC_CHECK (st, LZWDEC_STATE_LOOP_WRITE,
+                       lzwdec_put_decoded (st, out));
+         
+         if (st->dict.size == st->buffer.maxval - 1 - st->early_change)
+           {
+             if (!lzw_buffer_inc_bitsize (&st->buffer));
+             /* break; We must wait for the reset code, don't reset yet. */
+           }
+         
+         /* get next code */
+         st->old_code = st->new_code;
+       lzwdec_state_loop_read:
+         LZWDEC_CHECK (st, LZWDEC_STATE_LOOP_READ,
+                       lzw_buffer_get_code (&st->buffer, &st->new_code, 
finish_p));
+       }
+    }
+  while (st->new_code != LZW_EOD_CODE);
+
+  st->state_pos = LZWDEC_STATE_START;
+  
+  return PDF_EEOF;
 }
 
-int
-pdf_stm_f_lzw_dealloc (void **filter_data)
+pdf_status_t
+pdf_stm_f_lzwdec_dealloc_state (void *state)
 {
-  pdf_stm_f_lzw_data_t *data;
-
-  data = (pdf_stm_f_lzw_data_t *) filter_data;
-  pdf_dealloc (*data);
-
+  pdf_dealloc (state);
   return PDF_OK;
 }
 

=== modified file 'src/base/pdf-stm-f-lzw.h'
--- src/base/pdf-stm-f-lzw.h    2009-01-11 21:37:29 +0000
+++ src/base/pdf-stm-f-lzw.h    2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/01/11 22:04:37 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-06-24 20:18:48 raskolnikov"
  *
  *       File:         pdf-stm-f-lzw.h
  *       Date:         Wed Aug 15 14:13:20 2007
@@ -27,54 +27,31 @@
 #define PDF_STM_F_LZW_H
 
 #include <config.h>
-#include <pdf-base.h>
-
-/* Configuration data */
-
-/* BEGIN PUBLIC */
-
-enum pdf_stm_f_lzw_mode_t
-{
-  PDF_STM_F_LZW_MODE_ENCODE,
-  PDF_STM_F_LZW_MODE_DECODE
-};
-
-/* END PUBLIC */
-
-struct pdf_stm_f_lzw_conf_s
-{
-  int mode;
-  int early_change;   /* An indication of when to increase the code
-                         length. If the value of this entry is 0, code
-                         length increases are postponed as long as
-                         possible. If the value is 1, code length
-                         increases occur one code early. This
-                         parameter is included because LZW sample code
-                         distributed by some vendors increases the
-                         code length one code earlier than necessary.
-                         
-                         Default value: 1 */
-};
-
-typedef struct pdf_stm_f_lzw_conf_s *pdf_stm_f_lzw_conf_t;
-
-/* Private data */
-
-struct pdf_stm_f_lzw_data_s
-{
-  int mode;
-  int early_change;
-};
-
-typedef struct pdf_stm_f_lzw_data_s *pdf_stm_f_lzw_data_t;
+
+#include <pdf-types.h>
+#include <pdf-hash.h>
 
 /* Filter API implementation */
 
-int pdf_stm_f_lzw_init (void **filter_data, void *conf_data);
-int pdf_stm_f_lzw_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_lzw_dealloc (void **filter_data);
+pdf_status_t pdf_stm_f_lzwenc_init (pdf_hash_t params,
+                                    void **state);
+pdf_status_t pdf_stm_f_lzwenc_apply (pdf_hash_t params,
+                                     void *state,
+                                     pdf_buffer_t in,
+                                     pdf_buffer_t out,
+                                     pdf_bool_t finish_p);
+
+pdf_status_t pdf_stm_f_lzwdec_init (pdf_hash_t params,
+                                    void **state);
+pdf_status_t pdf_stm_f_lzwdec_apply (pdf_hash_t params,
+                                     void *state,
+                                     pdf_buffer_t in,
+                                     pdf_buffer_t out,
+                                     pdf_bool_t finish_p);
+
+pdf_status_t pdf_stm_f_lzwdec_dealloc_state (void *state);
+
+pdf_status_t pdf_stm_f_lzwenc_dealloc_state (void *state);
 
 #endif /* pdf_stm_f_lzw.h */
 

=== modified file 'src/base/pdf-stm-filter.c'
--- src/base/pdf-stm-filter.c   2009-05-19 13:26:02 +0000
+++ src/base/pdf-stm-filter.c   2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/05/19 15:13:06 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-06-28 00:33:54 raskolnikov"
  *
  *       File:         pdf-stm-filter.c
  *       Date:         Thu Jun 12 22:13:31 2008
@@ -162,6 +162,20 @@
             new->impl.dealloc_state_fn = pdf_stm_f_md5enc_dealloc_state;
             break;
           }
+       case PDF_STM_FILTER_LZW_ENC:
+          {
+            new->impl.init_fn = pdf_stm_f_lzwenc_init;
+            new->impl.apply_fn = pdf_stm_f_lzwenc_apply;
+            new->impl.dealloc_state_fn = pdf_stm_f_lzwenc_dealloc_state;
+            break;
+          }
+       case PDF_STM_FILTER_LZW_DEC:
+          {
+            new->impl.init_fn = pdf_stm_f_lzwdec_init;
+            new->impl.apply_fn = pdf_stm_f_lzwdec_apply;
+            new->impl.dealloc_state_fn = pdf_stm_f_lzwdec_dealloc_state;
+            break;
+          }
 #if defined(HAVE_LIBJBIG2DEC)
         case PDF_STM_FILTER_JBIG2_DEC:
           {

=== modified file 'src/base/pdf-stm-filter.h'
--- src/base/pdf-stm-filter.h   2009-01-12 13:30:36 +0000
+++ src/base/pdf-stm-filter.h   2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/01/11 22:03:22 jemarch"
+/* -*- mode: C -*- Time-stamp: "2009-06-28 00:32:10 raskolnikov"
  *
  *       File:         pdf-stm-filter.h
  *       Date:         Thu Jun 12 22:05:06 2008
@@ -37,6 +37,7 @@
 #include <pdf-stm-f-v2.h>
 #include <pdf-stm-f-aesv2.h>
 #include <pdf-stm-f-md5.h>
+#include <pdf-stm-f-lzw.h>
 
 #if defined(HAVE_LIBZ)
 #  include <pdf-stm-f-flate.h>
@@ -74,7 +75,9 @@
   PDF_STM_FILTER_AESV2_DEC,
   PDF_STM_FILTER_V2_ENC,
   PDF_STM_FILTER_V2_DEC,
-  PDF_STM_FILTER_MD5_ENC
+  PDF_STM_FILTER_MD5_ENC,
+  PDF_STM_FILTER_LZW_DEC,
+  PDF_STM_FILTER_LZW_ENC
 };
 
 /* END PUBLIC */

=== modified file 'torture/unit/base/stm/pdf-stm-write.c'
--- torture/unit/base/stm/pdf-stm-write.c       2009-05-15 17:55:40 +0000
+++ torture/unit/base/stm/pdf-stm-write.c       2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "2009-05-15 13:53:39 gerel"
+/* -*- mode: C -*- Time-stamp: "2009-06-28 01:16:15 raskolnikov"
  *
  *       File:         pdf-stm-write.c
  *       Date:         Sun Sep 21 16:37:27 2008
@@ -30,6 +30,44 @@
 #include <pdf.h>
 
 /*
+ * Fixture: mem_stm_fixture.
+ * Description:
+ *   Common data for memory stream based tests.
+ */
+struct
+{
+  pdf_stm_t stm;
+  pdf_char_t *buf;
+} mem_stm_fixture;
+
+#define MEM_STM_FIXTURE_BUFFER_SIZE 1024
+#define MEM_STM_FIXTURE_CACHE_SIZE  1
+
+static void
+mem_stm_fixture_setup ()
+{
+  pdf_status_t ret;
+  
+  mem_stm_fixture.buf = pdf_alloc (MEM_STM_FIXTURE_BUFFER_SIZE);
+  fail_if (mem_stm_fixture.buf == NULL);
+
+  ret = pdf_stm_mem_new (mem_stm_fixture.buf,
+                         MEM_STM_FIXTURE_BUFFER_SIZE,
+                         MEM_STM_FIXTURE_CACHE_SIZE,
+                         PDF_STM_WRITE,
+                         &mem_stm_fixture.stm);
+  fail_if (ret != PDF_OK);  
+}
+
+static void
+mem_stm_fixture_teardown ()
+{
+  pdf_stm_destroy (mem_stm_fixture.stm);
+  pdf_dealloc (mem_stm_fixture.buf);
+}
+
+
+/*
  * Test: pdf_stm_write_001
  * Description:
  *   Write some bytes to a write memory stream.
@@ -871,6 +909,82 @@
 END_TEST
 
 
+
+/*
+ * Test: pdf_stm_write_015
+ * Description:
+ *   Create a memory-based writing stream and attach an LZW filter
+ *   encoder to it.
+ * Success condition:
+ *   The encoded data should be correct.
+ */
+START_TEST (pdf_stm_write_015)
+{
+  pdf_status_t ret;
+  pdf_hash_t params;
+  pdf_size_t tmp = 0;
+  
+  pdf_char_t *decoded =
+    "-----A---B";
+  pdf_char_t *encoded =
+    "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01";
+
+
+  /* Create the filter */
+  pdf_hash_new (NULL, &params);
+  fail_if (pdf_stm_install_filter (mem_stm_fixture.stm,
+                                  PDF_STM_FILTER_LZW_ENC,
+                                  params)
+          != PDF_OK);
+
+  /* Write and test some stuff */
+  ret = pdf_stm_write (mem_stm_fixture.stm, decoded, 10, &tmp);
+  fail_if (ret == PDF_ERROR);
+  fail_if (pdf_stm_flush (mem_stm_fixture.stm, PDF_TRUE, &tmp) == PDF_ERROR);
+  fail_if (memcmp (mem_stm_fixture.buf, encoded, 9) != 0);
+
+  /* Cleanup */
+  pdf_hash_destroy (params);
+}
+END_TEST
+
+/*
+ * Test: pdf_stm_write_015
+ * Description:
+ *   Create a memory-based writing stream and attach an LZW filter
+ *   encoder to it.
+ * Success condition:
+ *   The encoded data should be correct.
+ */
+START_TEST (pdf_stm_write_016)
+{
+  pdf_status_t ret;
+  pdf_hash_t params;
+  pdf_size_t tmp = 0;
+
+  pdf_char_t *encoded =
+    "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01";
+  pdf_char_t *decoded =
+    "-----A---B";
+
+  /* Create the filter */
+  pdf_hash_new (NULL, &params);
+  fail_if (pdf_stm_install_filter (mem_stm_fixture.stm,
+                                  PDF_STM_FILTER_LZW_DEC,
+                                  params)
+          != PDF_OK);
+
+  /* Test some data */
+  ret = pdf_stm_write (mem_stm_fixture.stm, encoded, 9, &tmp);
+  fail_if (ret == PDF_ERROR);
+  fail_if (pdf_stm_flush (mem_stm_fixture.stm, PDF_TRUE, &tmp) == PDF_ERROR);  
+  fail_if (memcmp (mem_stm_fixture.buf, decoded, 10) != 0);
+  
+  /* Cleanup */
+  pdf_hash_destroy (params);
+}
+END_TEST
+
 /*
  * Test case creation function
  */
@@ -879,6 +993,10 @@
 {
   TCase *tc = tcase_create ("pdf_stm_write");
 
+  tcase_add_checked_fixture(tc,
+                           mem_stm_fixture_setup,
+                           mem_stm_fixture_teardown);
+  
   tcase_add_test(tc, pdf_stm_write_001);
   tcase_add_test(tc, pdf_stm_write_002);
   tcase_add_test(tc, pdf_stm_write_003);
@@ -896,6 +1014,8 @@
   tcase_add_test(tc, pdf_stm_write_012);
   tcase_add_test(tc, pdf_stm_write_013);
   tcase_add_test(tc, pdf_stm_write_014);
+  tcase_add_test(tc, pdf_stm_write_015);
+  tcase_add_test(tc, pdf_stm_write_016);
 
   return tc;
 }

=== modified file 'utils/Makefile.am'
--- utils/Makefile.am   2009-06-24 19:25:52 +0000
+++ utils/Makefile.am   2009-06-27 23:19:51 +0000
@@ -22,7 +22,7 @@
  ICONV_LIBS = -liconv
 endif #ICONV
 
-bin_PROGRAMS = pdf-filter pdf-tokeniser
+bin_PROGRAMS = pdf-filter 
 
 LDADD = $(top_builddir)/src/libgnupdf.la \
         $(ICONV_LIBS)
@@ -31,6 +31,6 @@
               -I$(top_srcdir)/src/base -I $(top_srcdir)/src/object
 
 pdf_filter_SOURCES = pdf-filter.h pdf-filter.c
-pdf_tokeniser__SOURCES = pdf-tokeniser.c
+# pdf_tokeniser__SOURCES = pdf-tokeniser.c
 
 # End of Makefile.am

=== modified file 'utils/pdf-filter.c'
--- utils/pdf-filter.c  2009-06-24 19:25:52 +0000
+++ utils/pdf-filter.c  2009-06-27 23:19:51 +0000
@@ -58,11 +58,12 @@
     {"null", no_argument, NULL, NULL_FILTER_ARG},
     {"ahexdec", no_argument, NULL, ASCIIHEXDEC_FILTER_ARG},
     {"ahexenc", no_argument, NULL, ASCIIHEXENC_FILTER_ARG},
+    {"lzwenc", no_argument, NULL, LZWENC_FILTER_ARG},
+    {"lzwdec", no_argument, NULL, LZWDEC_FILTER_ARG},
+    {"lzw-earlychange", no_argument, NULL, LZW_EARLYCHANGE_ARG},
 #if 0
     {"a85dec", no_argument, NULL, ASCII85DEC_FILTER_ARG},
     {"a85enc", no_argument, NULL, ASCII85ENC_FILTER_ARG},
-    {"lzwenc", no_argument, NULL, LZWENC_FILTER_ARG},
-    {"lzwdec", no_argument, NULL, LZWDEC_FILTER_ARG},
     {"cfaxdec", no_argument, NULL, CCITTFAXDEC_FILTER_ARG},
     {"jxpdec", no_argument, NULL, JXPDEC_FILTER_ARG},
     {"predenc", no_argument, NULL, PREDENC_FILTER_ARG},
@@ -108,12 +109,12 @@
 available filters\n\
   --null                              use the NULL filter\n\
   --ahexdec                           use the ASCII Hex decoder filter\n\
-  --ahexenc                           use the ASCII Hex encoder filter\n"
+  --ahexenc                           use the ASCII Hex encoder filter\n\
+  --lzwenc                            use the LZW encoder filter\n\
+  --lzwdec                            use the LZW decoder filter\n"
 #if 0
 "  --a85dec                            use the ASCII 85 decoder filter\n\
   --a85enc                            use the ASCII 85 encoder filter\n\
-  --lzwenc                            use the LZW encoder filter\n\
-  --lzwdec                            use the LZW decoder filter\n
   --jxpdec                            use the JXP decoder filter\n\
   --predenc                           use the predictor encoder filter\n\
   --preddec                           use the predictor decoder filter\n"
@@ -139,14 +140,15 @@
   --version                           show pdf-filter version and exit\n\
 \nfilter properties\n"
 #if 0
-"  --lzw-earlychange                   toggles earlychange for next lzw 
filters\n\
+"  
   --preddec-type=NUM                  code for next preddec filters type\n\
   --predenc-type=NUM                  code for next predenc filters type\n\
   --pred-colors=NUM                   next predictors colors per sample\n\
   --pred-bpc=NUM                      next predictors bits per color 
component\n\
   --pred-columns=NUM                  next predictors number of samples per 
row\n"
 #endif /* 0 */
-"  --jbig2dec-globals=FILE             file containing global segments\n\
+"  --lzw-earlychange                   toggles earlychange for next lzw 
filters\n\
+  --jbig2dec-globals=FILE             file containing global segments\n\
 ";
 
 char *pdf_filter_help_msg = "";
@@ -448,6 +450,7 @@
   char *key = NULL;
   pdf_size_t jbig2dec_global_segments_size = 0;
   pdf_status_t status;
+  pdf_bool_t lzw_earlychange = PDF_FALSE;
 
   /* Initialize the crypt module */
   if (pdf_crypt_init () != PDF_OK)
@@ -554,14 +557,6 @@
           {
             break;
           }
-       case LZWENC_FILTER_ARG:
-          {
-            break;
-          }
-        case LZWDEC_FILTER_ARG:
-          {
-            break;
-          }
         case CCITTFAXDEC_FILTER_ARG:
           {
             break;
@@ -591,6 +586,57 @@
             break;
           }
 #endif /* 0 */
+        case LZW_EARLYCHANGE_ARG:
+          {
+            lzw_earlychange = PDF_TRUE;
+            break;
+          }
+       case LZWENC_FILTER_ARG:
+          {
+            ret = pdf_hash_new (NULL, &filter_params);
+            if (ret != PDF_OK)
+              {
+                pdf_error (ret, stderr, "while creating the lzwenc filter 
parameters hash table");
+                exit (1);
+              }
+
+            pdf_hash_add_bool (filter_params, "EarlyChange", lzw_earlychange);
+
+            status = pdf_stm_install_filter (stm,
+                                             PDF_STM_FILTER_LZW_ENC,
+                                             filter_params);
+
+            if (status != PDF_OK)
+              {
+                pdf_error (status, stderr, "while creating the LZW encoder 
filter");
+                exit (1);
+              }
+
+            break;
+          }
+        case LZWDEC_FILTER_ARG:
+          {
+            ret = pdf_hash_new (NULL, &filter_params);
+            if (ret != PDF_OK)
+              {
+                pdf_error (ret, stderr, "while creating the lzwdec filter 
parameters hash table");
+                exit (1);
+              }
+
+            pdf_hash_add_bool (filter_params, "EarlyChange", lzw_earlychange);
+
+            status = pdf_stm_install_filter (stm,
+                                             PDF_STM_FILTER_LZW_DEC,
+                                             filter_params);
+
+            if (status != PDF_OK)
+              {
+                pdf_error (status, stderr, "while creating the LZW decoder 
filter");
+                exit (1);
+              }
+
+            break;
+          }
 #ifdef HAVE_LIBZ
         case FLATEDEC_FILTER_ARG:
           {

=== modified file 'utils/pdf-filter.h'
--- utils/pdf-filter.h  2009-05-06 17:54:48 +0000
+++ utils/pdf-filter.h  2009-06-27 23:19:51 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "09/05/06 19:46:33 jemarch"
+/* -*- mode: C -*- Time-stamp: "09/06/24 19:37:20 jemarch"
  *
  *       File:         pdf-filter.h
  *       Date:         Tue Jul 10 18:40:55 2007
@@ -46,8 +46,6 @@
 #if 0
   ASCII85DEC_FILTER_ARG,
   ASCII85ENC_FILTER_ARG,
-  LZWENC_FILTER_ARG,
-  LZWDEC_FILTER_ARG,
   CCITTFAXDEC_FILTER_ARG,
   JXPDEC_FILTER_ARG,
   PREDENC_FILTER_ARG,
@@ -67,6 +65,9 @@
   JBIG2DEC_GLOBAL_SEGMENTS_ARG,
   JBIG2DEC_PAGE_SIZE,
 #endif /* HAVE_LIBJBIG2DEC */
+  LZWENC_FILTER_ARG,
+  LZWDEC_FILTER_ARG,
+  LZW_EARLYCHANGE_ARG,
   MD5ENC_FILTER_ARG,
   KEY_ARG,
   AESENC_FILTER_ARG,

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

Attachment: lzw-28-06-09.patch.sig
Description: PGP signature


reply via email to

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