Please review and apply.

Brad
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [email protected]\
#   y5gf78gg8ikjninq
# target_branch: http://bzr.savannah.gnu.org/r/pdf/libgnupdf/branches\
#   /trunk/
# testament_sha1: c3f32e22f4dfec978346a8b02342bce73053a2a2
# timestamp: 2009-06-24 20:21:51 +1000
# base_revision_id: [email protected]
# 
# Begin patch
=== modified file 'AUTHORS'
--- AUTHORS	2009-06-22 11:20:04 +0000
+++ AUTHORS	2009-06-23 03:16:51 +0000
@@ -82,7 +82,13 @@
   m4/MANIFEST.wiki
   prmgt/MANIFEST.wiki
   src/MANIFEST.wiki
+  src/Makefile.am
   src/README
+  src/base/pdf-stm-f-ahex.c
+  src/base/pdf-stm-f-lzw.c
+  src/base/pdf-stm-f-lzw.h
+  src/base/pdf-stm-filter.c
+  src/base/pdf-stm-filter.h
   src/base/pdf-text.c
   src/base/pdf-time.c
   src/object/MANIFEST.wiki
@@ -92,6 +98,7 @@
   torture/unit/base/time/pdf-time-copy.c 
   torture/unit/base/crypt/pdf-crypt-md-new.c
   torture/unit/base/crypt/pdf-crypt-md-read.c
+  torture/unit/base/stm/pdf-stm-write.c
   torture/unit/base/text/pdf-text-dup.c
   torture/unit/base/text/pdf-text-new-destroy.c
   torture/unit/base/text/pdf-text-new-from-host.c

=== modified file 'ChangeLog'
--- ChangeLog	2009-06-22 11:20:04 +0000
+++ ChangeLog	2009-06-23 03:16:51 +0000
@@ -1,3 +1,18 @@
+2009-06-23  Brad Hards  <[email protected]>
+
+	* src/base/pdf-stm-f-lzw.c: initial 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.
+
+	* src/base/pdf-stm-f-ahex.c (pdf_stm_f_ahexdec_dealloc_state): Use
+	pdf_stm_f_ahexdec_t instead of pdf_stm_f_ahexenc_t. Update variable
+	names to match.
+
 2009-06-22  Brad Hards  <[email protected]>
 
 	* 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-23 03:16: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
@@ -115,7 +116,7 @@
   libgnupdf_la_LDFLAGS = -no-undefined
 endif
 
-AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBGCRYPT_CFLAGS)
+AM_CFLAGS = -Wall -fno-strict-aliasing -Wconversion $(LIBGCRYPT_CFLAGS)
 if USE_COVERAGE
   AM_CFLAGS += -fprofile-arcs -ftest-coverage
 endif

=== modified file 'src/base/pdf-stm-f-ahex.c'
--- src/base/pdf-stm-f-ahex.c	2009-05-07 09:03:31 +0000
+++ src/base/pdf-stm-f-ahex.c	2009-06-22 22:03:57 +0000
@@ -308,10 +308,10 @@
 pdf_status_t
 pdf_stm_f_ahexdec_dealloc_state (void *state)
 {
-  pdf_stm_f_ahexenc_t ahexenc_state;
+  pdf_stm_f_ahexdec_t ahexdec_state;
 
-  ahexenc_state = (pdf_stm_f_ahexenc_t) state;
-  pdf_dealloc (ahexenc_state);
+  ahexdec_state = (pdf_stm_f_ahexdec_t) state;
+  pdf_dealloc (ahexdec_state);
 
   return PDF_OK;
 }

=== 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-24 09:57:17 +0000
@@ -3,7 +3,7 @@
  *       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,86 +25,114 @@
 
 #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 NULL_INDEX ~0U
+
+#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;
-
-
-
-/* -- LZW code output/input -- */
+static const int LZW_RESET_CODE = 256;
+static const int LZW_EOD_CODE   = 257;
+static const int LZW_FIRST_CODE = 258;
+
+static const pdf_real_t MAX_COMPRESSION_FACTOR = 1.5;
+
+enum pdf_stm_f_lzw_mode_t {
+  PDF_STM_F_LZW_MODE_ENCODE,
+  PDF_STM_F_LZW_MODE_DECODE
+};
 
 /*
- * Object to read and write codes of variable bitsize in a buffer.
- * Warning: using both get and put functions may break the buffer.
+ * The strings are stored in a non balanced ordered binary tree.
  */
+typedef struct lzw_string_s
+{
+  unsigned prefix;   /* Prefix string code */
+  pdf_char_t suffix; /* Appended character */
+
+  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_dict_s
+{
+  lzw_string_t table[MAX_DICTSIZE];
+  unsigned int size;
+} lzw_dict_t;
+
+struct pdf_stm_f_lzw_data_s
+{
+  enum pdf_stm_f_lzw_mode_t  mode; /* encoding or decoding? */
+  unsigned int               early_change;
+};
+
+typedef struct pdf_stm_f_lzw_data_s *pdf_stm_f_lzw_data_t;
+
 typedef struct lzw_buffer_s
 {
-  pdf_char_t* curp;
-  pdf_char_t* endp;
-  unsigned long valbuf;
+  pdf_buffer_t data; /* out for encode, in for decode */
+  pdf_u32_t valbuf;
   unsigned valbits;
   unsigned bitsize;
   unsigned maxval;
 } lzw_buffer_t;
 
 static void
-lzw_buffer_init (lzw_buffer_t* b, 
-		 pdf_char_t* ptr,
-		 int size,
-		 int bitsize)
+lzw_buffer_init (lzw_buffer_t* buf, 
+		 pdf_buffer_t data,
+		 unsigned int bitsize)
 {
-  b->curp = ptr;
-  b->endp = ptr + size;
-  b->valbuf = 0;
-  b->valbits = 0;
-  b->bitsize = bitsize;
-  b->maxval = (1 << bitsize) - 1;
+  buf->data = data;
+  buf->valbuf = 0;
+  buf->valbits = 0;
+  buf->bitsize = bitsize;
+  buf->maxval = (1U << bitsize) - 1;
 }
 
 static unsigned int
 lzw_buffer_get_code (lzw_buffer_t* b)
 {
-  unsigned long r;
-  
+  pdf_u32_t r;
+  pdf_buffer_t in = b->data;
+
   while (b->valbits <= 24)
   {
-    if (b->curp > b->endp)
+    if (in->rp > in->wp)
       return NULL_INDEX;
     
-    b->valbuf |= (unsigned long) *b->curp++ << (24 - b->valbits);
+    b->valbuf |= (in->data[in->rp]) << (24 - b->valbits);
+    ++(in->rp);
     b->valbits += 8;
   }
 
   r = b->valbuf >> (32 - b->bitsize);
   b->valbuf <<= b->bitsize;
   b->valbits -= b->bitsize;
-  
+
   return r;
 }
 
-/* Once finished, call with 0 as code value to flush the buffer. */
 static void
 lzw_buffer_put_code (lzw_buffer_t* b,
 		     unsigned int code)
 {
-  b->valbuf |= (unsigned long) code << (32 - b->bitsize - b->valbits);
+  pdf_buffer_t out = b->data;
+
+  b->valbuf |= code << (32 - b->bitsize - b->valbits);
   b->valbits += b->bitsize;
 
   while (b->valbits >= 8)
     {
-      *b->curp++ = b->valbuf >> 24;
+      if (pdf_buffer_full_p(out))
+        {
+          return;
+        }
+      out->data[out->wp] = (pdf_char_t)(b->valbuf >> 24);
+      ++(out->wp);
       b->valbuf <<= 8;
       b->valbits -= 8;
     }
@@ -117,58 +145,38 @@
     return PDF_ERROR;
   
   ++b->bitsize;
-  b->maxval = (1 << b->bitsize) - 1;
+  b->maxval = (1U << b->bitsize) - 1;
 
   return PDF_OK;
 }
 
 static void
 lzw_buffer_set_bitsize (lzw_buffer_t* b,
-			int newsize)
+			unsigned int newsize)
 {
   b->bitsize = newsize;
-  b->maxval = (1 << newsize) - 1;
+  b->maxval = (1U << newsize) - 1;
 }
 
 
 /* -- LZW dictionary handler -- */
 
-/*
- * The strings are stored in a non balanced ordered binary tree.
- */
-typedef struct lzw_string_s
-{
-  unsigned prefix;   /* Prefix string code */
-  pdf_char_t suffix; /* Appended character */
-
-  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;
-
 static void
 lzw_string_init (lzw_string_t* s)
 {
   memset(s, 0xFF, sizeof(lzw_string_t));
 }
 
-
-typedef struct lzw_dict_s
-{
-  lzw_string_t table[MAX_DICTSIZE];
-  unsigned size;
-} lzw_dict_t;
-
 static void
 lzw_dict_init (lzw_dict_t* d)
 {
   int i;
-  
+
   memset(d->table, 0xFF, sizeof(lzw_string_t) * 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;
@@ -176,11 +184,11 @@
 
 static int
 lzw_dict_add (lzw_dict_t* d,
-	      lzw_string_t* s)
+              lzw_string_t* s)
 {
   unsigned index;
   int must_add;
-  
+
   if (s->prefix == NULL_INDEX)
     {
       s->prefix = s->suffix;
@@ -264,170 +272,152 @@
   
 }
 
-/* -- 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)
-{
+pdf_status_t
+pdf_stm_f_lzw_common_init (pdf_hash_t params,
+                           void **state,
+                           enum pdf_stm_f_lzw_mode_t mode)
+{
+  pdf_stm_f_lzw_data_t lzw_filter_state;
+  pdf_char_t *early_change_str;
+
+  if (state == NULL)
+    {
+      return PDF_EBADDATA;
+    }
+
+  lzw_filter_state = pdf_alloc (sizeof(struct pdf_stm_f_lzw_data_s));
+  // check result of allocation
+  if (lzw_filter_state == NULL)
+    {
+      return PDF_ERROR;
+    }
+
+  lzw_filter_state->mode = mode;
+  lzw_filter_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')
+        {
+          lzw_filter_state->early_change = 0;
+        }
+    }
+
+  *state = lzw_filter_state;
+
+  return PDF_OK;
+}
+
+
+pdf_status_t
+pdf_stm_f_lzwenc_init (pdf_hash_t params,
+                       void **state)
+{
+  return pdf_stm_f_lzw_common_init(params, state, PDF_STM_F_LZW_MODE_ENCODE);
+}
+
+
+pdf_status_t
+pdf_stm_f_lzwdec_init (pdf_hash_t params,
+                       void **state)
+{
+  return pdf_stm_f_lzw_common_init(params, state, PDF_STM_F_LZW_MODE_DECODE);
+}
+
+
+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_stm_f_lzw_data_t data = (pdf_stm_f_lzw_data_t) state;
   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)
-    {
-      *out_size = 0;
-      return PDF_ERROR;
-    }
-
-  /* Do the actual encoding. */
-  lzw_buffer_init(&buffer, *out, *out_size, MIN_BITSIZE);
-  lzw_dict_init(&dict);
+
+  if (finish_p == PDF_TRUE)
+    {
+      return PDF_EEOF;
+    }
+  if (in->rp == in->wp)
+    {
+      return PDF_ENINPUT;
+    }
+
+  lzw_buffer_init(&buffer, out, MIN_BITSIZE);
+  lzw_dict_init (&dict);
   lzw_string_init(&string);
 
   lzw_buffer_put_code(&buffer, LZW_RESET_CODE);
 
-  while (--in_size >= 0)
+  while (in->rp <= in->wp)
     {
-      string.suffix = *in++;
-
+      string.suffix = in->data[in->rp];
+      (in->rp)++;
       if (lzw_dict_add(&dict, &string))
-	{
-	  lzw_buffer_put_code(&buffer, string.prefix);
-	  string.prefix = string.suffix;
+        {
+          lzw_buffer_put_code(&buffer, string.prefix);
+          string.prefix = string.suffix;
 
-	  if (buffer.maxval - data->early_change == dict.size)
-	    {
-	      if (!lzw_buffer_inc_bitsize(&buffer))
-		{
-		  lzw_buffer_put_code(&buffer, LZW_RESET_CODE);
-		  lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE);
-		  lzw_dict_reset(&dict);
-		}
-	    }
-	}
+          if (buffer.maxval - data->early_change == dict.size)
+            {
+              if (!lzw_buffer_inc_bitsize(&buffer))
+                {
+                  lzw_buffer_put_code(&buffer, LZW_RESET_CODE);
+                  lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE);
+                  lzw_dict_reset(&dict);
+                }
+            }
+        }
+      if (pdf_buffer_full_p(out))
+        {
+          return PDF_ENOUTPUT;
+        }
     }
-  
-  lzw_buffer_put_code(&buffer, string.prefix);
+
   if (buffer.maxval - data->early_change == dict.size)
-    lzw_buffer_inc_bitsize(&buffer);
+    {
+      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)
+
+  return PDF_ENINPUT;
+}
+
+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_char_t dec_buf[MAX_DICTSIZE];
   pdf_char_t* decoded;
   unsigned dec_size;
-  
   unsigned new_code;
   unsigned old_code;
-   
+  int lv = 0;
+  
   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);
+
+  if (finish_p == PDF_TRUE)
+    {
+      return PDF_EEOF;
+    }
+  if (in->rp == in->wp)
+    {
+      return PDF_ENINPUT;
+    }
+
+  lzw_buffer_init(&buffer, in, MIN_BITSIZE);
   lzw_dict_init(&dict);
   old_code = NULL_INDEX;
-  
+
   do {
     lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE);
     lzw_dict_reset(&dict);
@@ -435,123 +425,70 @@
     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;
+        return PDF_EEOF;
       }
-    
+
     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);
+        if (pdf_buffer_full_p(out))
+          {
+            return PDF_ENOUTPUT;
+          }
+        out->data[out->wp] = (pdf_char_t) (new_code & 0xFF);
+        ++(out->wp);
+
+        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);
+        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);
-	
+        for (lv = 0; lv < dec_size; ++lv)
+          {
+            if (pdf_buffer_full_p(out))
+              {
+                return PDF_ENOUTPUT;
+              }
+            out->data[out->wp] = decoded[lv];
+            ++(out->wp);
+          }
+
+        old_code = new_code;
+        new_code = lzw_buffer_get_code(&buffer);
+
 	if (new_code == NULL_INDEX)
 	  {
-	    lzw_writer_destroy(&writer);
-	    return PDF_ERROR;
+	    return PDF_EEOF;
 	  }
       }
   } 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);
-      }
-    default:
-      {
-        return PDF_ERROR;
-      }
-    }
-  
-  /* Not reached */
-}
-
-int
-pdf_stm_f_lzw_dealloc (void **filter_data)
-{
-  pdf_stm_f_lzw_data_t *data;
-
-  data = (pdf_stm_f_lzw_data_t *) filter_data;
-  pdf_dealloc (*data);
-
-  return PDF_OK;
-}
-
+
+  return PDF_OK;
+}
+
+
+pdf_status_t
+pdf_stm_f_lzw_dealloc_state (void *state)
+{
+  pdf_dealloc ((pdf_stm_f_lzw_data_t) state);
+
+  return PDF_OK;
+}
 /* End of pdf_stm_f_lzw.c */

=== 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-22 23:47:24 +0000
@@ -27,54 +27,29 @@
 #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_lzw_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-23 10:31:09 +0000
@@ -72,7 +72,6 @@
       
       /* Output buffer */
       new->out = NULL;
-      
       /* Install the appropriate implementation */
       switch (new->type)
         {
@@ -180,6 +179,20 @@
             break;
           }
 #endif /* HAVE_LIBJPEG */
+        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_lzw_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_lzw_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	2009-01-12 13:30:36 +0000
+++ src/base/pdf-stm-filter.h	2009-06-22 23:47:24 +0000
@@ -34,6 +34,7 @@
 #include <pdf-stm-f-null.h>
 #include <pdf-stm-f-ahex.h>
 #include <pdf-stm-f-rl.h>
+#include <pdf-stm-f-lzw.h>
 #include <pdf-stm-f-v2.h>
 #include <pdf-stm-f-aesv2.h>
 #include <pdf-stm-f-md5.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_ENC,
+  PDF_STM_FILTER_LZW_DEC
 };
 
 /* 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-23 10:31:09 +0000
@@ -870,6 +870,110 @@
 }
 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_stm_t stm;
+  pdf_size_t buf_size, total;
+  pdf_size_t written = 0;
+  pdf_size_t flushed_bytes = 0;
+  pdf_char_t *buf = 0;
+  pdf_char_t *decoded =
+    "-----A---B";
+  pdf_char_t *encoded =
+    "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01";
+
+  /* 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 */
+  pdf_hash_new (NULL, &params);
+  fail_if (pdf_stm_install_filter (stm, PDF_STM_FILTER_LZW_ENC, params) !=
+           PDF_OK);
+  written = 0;
+  ret = pdf_stm_write (stm, decoded, 10, &written);
+  fail_if (ret == PDF_ERROR);
+  fail_if(pdf_stm_flush (stm, PDF_TRUE, &flushed_bytes) == PDF_ERROR);
+  fail_if (memcmp (buf, encoded, 9) != 0);
+  /* Destroy the stream */
+  pdf_hash_destroy (params);
+  pdf_stm_destroy (stm);
+  pdf_dealloc (buf);
+
+}
+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_stm_t stm;
+  pdf_size_t buf_size, total;
+  pdf_size_t written = 0;
+  pdf_size_t flushed_bytes = 0;
+  pdf_char_t *buf = 0;
+  pdf_char_t *encoded =
+    "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01";
+  pdf_char_t *decoded =
+    "-----A---B";
+
+  /* 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 */
+  pdf_hash_new (NULL, &params);
+  fail_if (pdf_stm_install_filter (stm, PDF_STM_FILTER_LZW_DEC, params) !=
+           PDF_OK);
+  written = 0;
+  ret = pdf_stm_write (stm, encoded, 9, &written);
+  fail_if (ret == PDF_ERROR);
+  fail_if(pdf_stm_flush (stm, PDF_TRUE, &flushed_bytes) == PDF_ERROR);
+  fail_if (memcmp (buf, decoded, 1) != 0);
+  fail_if (memcmp (buf, decoded, 9) != 0);
+  fail_if (memcmp (buf, decoded, 10) != 0);
+  /* Destroy the stream */
+  pdf_hash_destroy (params);
+  pdf_stm_destroy (stm);
+  pdf_dealloc (buf);
+
+}
+END_TEST
+
 
 /*
  * Test case creation function
@@ -896,6 +1000,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;
 }

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

Reply via email to