[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [pdf-devel] Patch for Flate filter improved
From: |
gerel |
Subject: |
Re: [pdf-devel] Patch for Flate filter improved |
Date: |
Sun, 05 Oct 2008 08:13:48 -0700 (PDT) |
Ok, this is the good one. (I hope)
##
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: address@hidden
# target_branch: file:///home/gerel/PROJECTS/libgnupdf/trunk/
# testament_sha1: 6a01bc7e33f07e93e645cb9c1b931c8d27291d6a
# timestamp: 2008-10-05 13:08:34 -0200
# base_revision_id: address@hidden
#
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog 2008-10-04 18:44:47 +0000
+++ ChangeLog 2008-10-05 15:08:05 +0000
@@ -1,3 +1,23 @@
+2008-10-05 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.
=== modified file 'doc/gnupdf-tsd.texi'
--- doc/gnupdf-tsd.texi 2008-09-28 14:00:42 +0000
+++ doc/gnupdf-tsd.texi 2008-10-05 15:08:05 +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,18 @@
@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-05 15:08:05 +0000
@@ -46,9 +46,9 @@
base/pdf-stm-f-ahex.h base/pdf-stm-f-ahex.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-05 15:08:05 +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-05 15:08:05 +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-05 15:08:05 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/10/04 04:35:11 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-05 12:59:17 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-05 15:08:05 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/10/04 04:34:08 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-05 12:59:37 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-05 15:08:05 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "2008-10-04 15:42:24 gerel"
+/* -*- mode: C -*- Time-stamp: "2008-10-05 13:07:53 gerel"
*
* File: pdf-stm-read.c
* Date: Sat Sep 20 15:20:17 2008
@@ -471,6 +471,7 @@
}
END_TEST
+
/*
* Test: pdf_stm_read_008
* Description:
@@ -536,6 +537,83 @@
}
END_TEST
+/*
+ * 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
@@ -553,6 +631,7 @@
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-05 15:08:05 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "2008-10-04 15:38:46 gerel"
+/* -*- mode: C -*- Time-stamp: "2008-10-05 13:06:54 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 writing stream and attach a flate filter
+ * encoder to it.
+ * Success condition:
+ * The encoded data should be correct.
+ */
+START_TEST (pdf_stm_write_007)
+{
+ pdf_status_t ret;
+ pdf_hash_t params;
+ pdf_stm_t stm;
+ pdf_size_t buf_size, total,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;
}
=== modified file 'utils/pdf-filter.c'
--- utils/pdf-filter.c 2008-10-04 18:10:03 +0000
+++ utils/pdf-filter.c 2008-10-05 15:08:05 +0000
@@ -1,4 +1,4 @@
-/* -*- mode: C -*- Time-stamp: "08/10/04 20:05:35 jemarch"
+/* -*- mode: C -*- Time-stamp: "2008-10-05 12:57:40 gerel"
*
* File: pdf-filter.c
* Date: Tue Jul 10 18:42:07 2007
@@ -335,10 +335,30 @@
#ifdef HAVE_LIBZ
case FLATEDEC_FILTER_ARG:
{
+ ret = pdf_hash_new (NULL, &filter_params);
+ if (ret != PDF_OK)
+ {
+ pdf_error (ret, stderr, "while creating the flatedec filter
parameters hash table");
+ exit (1);
+ }
+
+ pdf_stm_install_filter (stm,
+ PDF_STM_FILTER_FLATE_DEC,
+ filter_params);
break;
}
case FLATEENC_FILTER_ARG:
{
+ ret = pdf_hash_new (NULL, &filter_params);
+ if (ret != PDF_OK)
+ {
+ pdf_error (ret, stderr, "while creating the flateenc filter
parameters hash table");
+ exit (1);
+ }
+
+ pdf_stm_install_filter (stm,
+ PDF_STM_FILTER_FLATE_ENC,
+ filter_params);
break;
}
#endif /* HAVE_LIBZ */
# Begin bundle
IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWfzXcXMAFFr/gH/0EwD7////
f+/enr////5gGt559T4Mx3Du1StGdu7bM0uboqKB21AOstNt3bGrTttLWoAdsaAADRmxU1gNM7cI
dB0OqAHDjQyaaZNAAwQBoMmgAGTQAAAyZANDjQyaaZNAAwQBoMmgAGTQAAAyZANBJBBAQ0INTU9T
GqejAo0aGmgNAHqAAaAaNASakRGk0k/Sjwp7VGJsUBtJ6g2gTIYjajRo0DTJoDQEUSETaKeaqeya
mymFNtJkzUT0mxRhqHqA0yaDQ0AA0CpIiYgEaCMgnpoamJkap+mppNqep+oU3qjQHqPUAM9U9TPU
yWwCPAKkyMQiOoVIHhFSkigdwVIOIVIUDjFSESoR72oCQn4vZ6+/ZPL1ccMScdHIljRUoYiDEUL+
k+/yY8RzmH+57S6UIpQ+OrKOjy7G6aNU3rH+GFt2sMMW2Uy0QrPYv83+8kcVlL40xOKmUcv5/GpU
lUMI1FVgYlMoaKA6wgMzFwLIWoqYGYS8na7XzU1MGSixSU/XYzjCTBSlKlN6mx2MVzFrJNlbLV8a
7tzJNZwrNx/HFqUVQVIIBxzlEGbJxDsJgkcdUcmTOIYYGaHHfrICFWpxD/J2+G8+IYyy3e67VzhL
nKcPG7M6ZSzR2GB/IYv5ihj3mTdJ3Wz2Nx5jcJWZVZAG0fM/y+XRmYYYpbdy6YpVts03pvi9S2D1
h7Ns9cJo5VKrdrairSJY49BkHzSEtIzjOAgDfDbokhALkJAEkZYoQQlKPNVMk81GVqGIkWQUBEkR
kBBgAlDQ2FPxPLJ9TR5n6Xf463umt/9U/yf4KzWY/VhaPNTU/zUpaYqe1T7lHe0Y8GFFJdkxO/dq
1KaKOlOFKop21qSz167v6Nh05XOK2iJDMF4DmPXfPCu6uXbMHfgXwKZ3UQDEEQKZhHr62/Mzhwxd
CbwSD3puB3gSprvpyg9dfFSDzIl8PXFD0y+klqVM5K+nL1xkNTBsMpGoO7XpBBR3PXF5nJi8DhNq
PB4bsovTJ8Jhi+JaMWq+hF2HpWM72iz3IZuAurwR3kDjJhjZlDx0GkXvglCUVN8cLnRBnnHdMCjA
iZVCjAQuMVk0qrvR5/ZJimF25Q+dLeF155EqKbYoyYEyod1nHd/GUIdyWJyLFhiD2pOta2GKUk9B
I9hsHA2FpqU5ziz6LXKdym9Rhz0Fz3Pc9BkYGJBbjIUSoGRkYkjREkxkxWDn/S0M2pneH815Dgou
Zvtb7TKp+huMl8K/owrq5vZ4eHf4ez2V0Mqb+dUqVUcN7gdamNsee5WOV6cPgKr3/AMMiTo7nWl5
UvLGJ2MBF7HA2OHmnm32i0qWsylLo0hyLucllRyUXUpQpgDDarBVVVszgthcve9zlNox2c3i1Fzp
ZFWk3E59sadJvbXKzmxtGjZG98r2SnUp4Kfuanoauld0t522PDl1PrbXP1EV2tc8VNa62fQ3PIwd
TPNrazFx0bVjUvZdS3GvwYPG8rgwGJINz8u56zQ+t/YoC/WwMc0vA94+D1+yfOfUrDer1AkfHGDM
xhd7T6fIzfD9CFWyr3tEGD/CI+nlDv9LWGrXHtmkOgVIc6wLjL5ejwVFgwKlh745PcSi7BTlU/2v
YtHopXBY+xRM1PlKKKki4kRJYjCHCIFzV5Ar8bfAlh4iwdWInq08mnd4OpPgOqcP6ew4HNgY+hcY
MGX8eGBvdqmuetcHaq6n/nmp7Wpo53ybXW3triZ2my30TxpUlUlKk8AUSj7aKLFoUMtSTtEiXEkn
hHfERku05phvhShnI7+nLd43O2vcdhyPvklyhQhSfGdhc9JkYrruzRkpKk0+y+bL5GzGLjL2Dush
zUO76utJ1h8/OMXs3/harcbeAyNjTh0NFsKehwLLYvmtdSjVINz5ZvE2P20Vaq4rvDV85wYt47RE
DaEARCwVQKKAoJERhSpKUM3Qc+dDyVVKk4FLifhy+w7njZuKNk3Saw0piv0fS3ovaWU43VDv2OGJ
5mkCjPvVSIUVKaq5YpEXsenZtcxk9EIGYJDfEeg+k0krAksHnJlHfS41bm5kErqOs2qhxFS1NAy6
tx7XZmewAVQu5AFKT5YF3fQCuHks14w1iyzRkrumKL3sg+P9C6IUItwCniJzzwJMEFLDGqFUYJIw
VAgY3RBGPFhxf3ZM26s9EbWCW1iaWE9MUjrZlte9ZpTVFSVMzNrZViJuEqRG9uWMk0Js50YKKYNZ
gpkwUyZPS4tQlm9muJ6LHUUKHj5EHkW+Fs4JZ73TjLFttzPrdH46/cK/JwZGodKC6L11y29T+2nN
1Nzq52jORzo9U+3GpVOcTRVtLJJHAp2l61RM2xw5tI8U7KHnWBfPRI45mQww/sSMwuWgruOdnO6N
wC4mmmxvrud9xXXHI0ei2GCMDtcqHipBx6jidZY24HELyrZ2bWnNMNJGx1Ptma67RuXdTmbWp53i
nVuPwvBnR1nFW4d4iCBlQKs/BLrPQyHSEsiysDCXbkYNuOCRYycoVUMdMIoDCSJLF7ESoSBYVN1y
hFnxOsrNFTShgdRWjZknAjDFzXcXg6UoXec6Tg0v7vIwANg3hsamWUGZ3HEuXOoxLDLrNnbCwt4T
Xji+JOuFZ2ZIvoOuwX/AFKodapbUyrU4jBuxDAqLWgkigkjrLli5jjcxJIKMowMjImoNvEvE7wEc
7MxGnc3Ft+zoczcqbmLRi1MXJ0tbnczeyc5o3M211mhc8/nPOUEkdummXF2djavY7Zxy1e+IrV54
qpxMl5HS52WHfo2LupczUcWDBsSRnXHgskhSRJHNd0rEjpw2JXQ7hOaF8c2M7DynM5WxgLiUMaXa
zrTTEzSJMxiLkHaZGRxOo5FyqsdGEkYbFLxvWYRXmRlkK1mar6E135ZVdRxzCwC5ZZFwE45O1nAW
QYanAuXgqjeMIy4GZqX0h5Kk3NZLmRkJIu2xvN0CSJ/AJI0wJoQdhkF9MOdCSyLbjmbzAgqLI2OZ
wJGGOZOZQ3F/ohqAsxJGGufIvVmmWam63ZFKZ3XMwmdSpxwKG80MjMxzLsYYkccQsSMJIlzgQJT0
ipvCZCzDht4Yy5gahoWl8rMoXy63WewMYiokizVfjlnRjGjzzglVcSclTxnlQ8UBZjJhR2Lc6+Do
62Lcki6kkfBJGbRxV5fJw2a03Epm2updTtmtwcnmSePl1ieR657nYkjm2ufTteCX05TziWtvqBdz
YgQLkQ6AOu5YzpQqNWYykl8K4qMXYgwYsYqYdMip1CpjLW07WVDuN50JNBioMciTq8/m8SuthJF8
TKNNGoxNeMPLWZmUkJdBrlzblcOz3HLZq5WOqmZBM5N2SSMOxoukj7kkcHjbDBqdbBrdTFx46Oyd
ksDGXGA0dB0kh5FyLj0aZ4COKIjtYzROamknRJweuylHaMXcJqVE6QwKnUkWQrbtKHyEdp2qEMBR
wZDmtQcJmOboX12f2/cb+cw+rn3NkO6p/apZfZj1/N/qa78nO97+OvctnyaWcFNGLIm95TmQEU8r
b+HYeFlwLDL4jhI0GJlhQ4DUpGsHqF8fZNTIWYg+JK0CeUQ7koqAURIUCBUZKEqblEJ8TAc89RDW
KaSqRETIKaXTukLF2MjIdbKSdLp7/NKYoj0NdF8rGjPLX4GNIJyTY1lSpUJZkp5nb97vLTHB4Jwk
DC1/p2cgFGAq5wvI+ERXit3xYxSZcbzOqo1eG5lZSfpESv02amR/+32/mupvLmeaMMJI9adFBkqD
JYoPiu4kcdg1KhZhSa0KRUg3m6a4LOGmPJHCZVuy2qXJtVQpUUzkmSHH//Uk5zohbBr18WtxVnKX
CmXTXUtkNtqBIUKOMfMUWU2qyitxmvbkuMhcEfKMAvnPaOts6mw29LfrK7PnjVLgliapZHiM3NzZ
4x2LSHCoowOWUa11Z6QyFBCoUrIaNVpfTYiIWXRkV2PUgXXy5JNekJ8X0KLEj1vi/FT2vyWUsp+9
dP3P7H9j6NTMu+impTc1PUWaLMW1TU2MWxvf1Plz+KhQnkC0O2Jwa5NEE7usKBxSu9LKwhXInkA7
yREswKRMMh5rCESrGBCrkbw7BQvkUIQkZOloSIHMEiBPRZlmZsCsGxevmtVCxlCpS0maZlolPkpg
xUU6RjS0ClCCFjAFibGB6bMAYHDC1rAkOEaIlKUsSR/rzkwMlqbUvFqGiMEXk2MbTxPzYVFHgbaS
inhNJHpblpHg9Z/Bi+jUp+spveDg9beaNHs/Oz82518HS0TyPrsdjivQ5OdaTqye9afv5Y0ptZO3
B0LPJE4bR4oaPq8iudH5z4LGLmKdKiP91ClEVW6PRI3shQeeumS0/e1po8/jeXayi6HNDXaSOjDt
dpKUWDdM87r1LNchvJimaKKWQVIqFSUqRFSyvzyLEm6Gd2ef8OnxPlb5PK4u5m7mWb1LOh52jBqd
zqdLU9Pp3N7sfUs73O9cwetoeL+FVHccn16OtzMGUl128sbR6xw3JkcMmzzGcxE7xQzxicJYu0iM
oodchdsKEmeDhM4HlVPTAeiAaHHmxdxomcyPblgi0WwWel53ma3lZWd7vycl136tHg8zfHc0c+yq
UqqVVVVVtHW6nJk5Hp5nJ/Iu6epxp6mO5mdbUZOFSZ+r0eWNRjKx83JnHpVORUREYoJYlG4iqgrQ
TqGoLhq9s1Ans0E0btyZqFLLnvLpZSXusvFKUUXNh1sFKe5T0dbuZPbO9k/5Ti1PHz7GjJo71nAm
xuJbzO9xaTXOSR5mjA1uC3jj+oqetXtU17WjoZvep6VGDzRweZNTHgvJ6EeDW2o3G9XVkmZUxqVg
/zf5Wc/w+F9KlWzN/e4PSkdD2LQDg1LB5akWdK50/W3vRTH1t/z8JLuKkqlG6KPkp5PGqyYvlk4Y
Jm9tn9/fgozc2j/tTcwR6tDBRTHaVZNGVmS2i6bNGj8KMJktDJUqmMpaayxGRNGovJKRgNjwdnYs
97ks0fFd2un546ZevH764Pa6mt8Fm9o2PgqTOR29SOqR5GXPUaqikvR1KdaKkvEoyUqkfV9vjg7a
NxKhGcomxvYTteJaDEyWZKGvVuLn2s13jYTqyRt9O18HqZ7HV0tEeRntixUTevtVEPS7HieqPao1
u190KF140R8F3tp7vgVuhn9csk+yehrbB0KHDkWiXtjdeSgUT9cUh5dTNqeQ89nU/F9ScX4sVLaM
WHFJNlPeqTU0EohuKWB/ZKSiV4VeUhHmZCfPGcgKQ3v2SUR9z1Puu9bi9jFqfFZ9r4snbg2yNYnk
QUSyKkkj7Gp5HqGGCtrubmD2l3xfaycz4OqmqRsUkbFMJG9I5M3YeI00eQhYPdIWkm2DJrNJnKiN
p5hOM5ARJKDL8KuMnBegKrMZDETs2LxA2ADFgKJDYSMFVBzneLhaWBz8Ql4A4ZuJJUChVI08a1RK
X+ekn/zQ/FgSkdfgfKIYYKydbR4vM6X4/D1FLKlLKVZ2F5LyXiVQPs/leTZNTxExi9fEomKpOVnk
+4mDwNifB4+BEORssE8VKGbwkpeKRvi3ClpJ0dgvHBoykUVmt+Sz+i8XU5qwO/KR4hPsLwckbUII
QfkMRIK6Fk7o22jHIwP6nqOesLCuCXrSRKQHwo20OuMGzhDZiIYNJIt5S0dRfQoE9Dl1NFs5z1QZ
JoOwXN0Q6Mh80ATgEKJA2CHfJJBLghPd4204SFSKAPCJqtPYnwpbF8txm0fgJ3rbGzgwPFEy+9/D
3/dqTfZSpLT8U5T+vQnA60askkzMIKOEm9qr6oQ9qZNzMUpJShOdqwX6GyMrrFikK2IYtTFaR99i
SYZxx2FDSTJSTyyKUhRFRSgLKJ8+y8OU29C7n4b5NYdTuZpjs7sslbhtdthPLPHu2DenJrHlkbEw
aMA9WV37zqa2+NKVpWCWsXkXYUZXsMjrOuWJbk5ZawZRkmmQ7lwlyGVBCw/vXLFSz1mETDItWXYV
7k90Ypiok0lsW3CR9FHkUWXn7piYRPEkoom2JahcyCS9QbXd4zbEkkzbjreWxbXiEvnjkDdKYx7a
wAUsLvqvGsR5DbW+ZXfIRJDXaYuBcSLneOLTrWyFwohBCyDWhQZgY5n7hxGLuw9CbHZXoT2lpHfP
mtg+S1Iqm1r9Tke3LiSE13HUXku2uc7YxEMQZA4+PjCcpm5MMI0i1VKq9MzB6E+FCd8TeAScvyIU
kQt3QSgMXsDAsCImCsUVYp3CxUFIuxpVVVV0m5Icu2Hx2Jm4AN4dYGe5o2yvex9zR5pNj1vt1PUy
ZnBQ3KWMbQ4KsqJ9UqRFiiqGESyHtv5U2s8Yfxnvtng5PRX0rPkqz9MSzc90I/ij3uc6mXOkOEke
WN59DnlledvWTGWlqM577VqMqtV48vdZHmpplEzohi6jHhzGycoJ9BCJzuw+Y7QJqNLgk7Fz7j9r
e0KSpTA5p42EL6P2Nk9Cek2qn8q6uDvaKJzvw1uO6l+hqXwVWKH9e92xixM5NqikPo+erTBUo4SK
RhI3yMU+xjBddUqpJ6Wp79hMXzU8n22jgMlpuuW0lR4LLeurXWfgou+97GC6YMFliylKYL/ekiSV
cc2DyJRsHtGKjDpOMhwRUYTMe6UhZ82MOZmH2MWpEPgTxxLyL/WSW/i3G2+xfzZ/Kbf49s2yZHmH
YuaduPTF1CwxUil72XkpMGHsfqyZVClJqasVXQ+BSZKiXVqus1FyovnYtL2Wl17roRjJHIzAwwLm
KYFrjDEetxZFwwGB14JeHJ0qd5vRtEMqQ1I2x0slpHrCYGxMSIJCIkgKIqTtjAp0pKCoT3URZtje
ilIVQOLwc7d+RRGNEnNm0lnwcWLFMVBW1Zwkk+jCxEbRKNSaHmS14lOiexZ0qMIRhSPdVm/y9yrk
2m+OhWpYi6F5xwqu7xsoh9nL/ufHI64+DGfNEnjPEnOnLu8G8vjPMkbPE2roXOOPKkpNy0kPrz9Z
1o55SN08UHJHd5Gb9Vixk6Ucp0tDeqqTVPU873rnMp1SndPTJZ3eJV4uMIUzp+O1sbnlSiUUj9Uk
fkp6JQnY/bZHJOJ6PC6JXV3G9063jq11f8Lxud7JjTD0fsezl3m9n6MmIm/hdwtP7hOzH3PcLBt1
dW17W8JVjNcmpE9sDoWoH/WtkaoKwJmZa1lSShUR/4u5IpwoSH5ruLmA
###
-gerel