Branch data Line data Source code
1 : : /* -*- mode: C -*-
2 : : *
3 : : * File: pdf-stm-f-lzw.c
4 : : * Date: Wed Aug 15 14:41:18 2007
5 : : *
6 : : * GNU PDF Library - LZW encoder/decoder filter
7 : : *
8 : : */
9 : :
10 : : /* Copyright (C) 2007-2011 Free Software Foundation, Inc. */
11 : :
12 : : /* This program is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU General Public License as published by
14 : : * the Free Software Foundation, either version 3 of the License, or
15 : : * (at your option) any later version.
16 : : *
17 : : * This program is distributed in the hope that it will be useful,
18 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : : * GNU General Public License for more details.
21 : : *
22 : : * You should have received a copy of the GNU General Public License
23 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : : */
25 : :
26 : : #include <config.h>
27 : :
28 : : #include <string.h>
29 : :
30 : : #include <pdf-types.h>
31 : : #include <pdf-types-buffer.h>
32 : : #include <pdf-hash.h>
33 : : #include <pdf-alloc.h>
34 : : #include <pdf-hash-helper.h>
35 : : #include <pdf-stm-f-lzw.h>
36 : :
37 : : /* Define LZW encoder */
38 : 0 : PDF_STM_FILTER_DEFINE (pdf_stm_f_lzwenc_get,
39 : : stm_f_lzwenc_init,
40 : : stm_f_lzwenc_apply,
41 : : stm_f_lzwenc_deinit);
42 : :
43 : : /* Define LZW decoder */
44 : 0 : PDF_STM_FILTER_DEFINE (pdf_stm_f_lzwdec_get,
45 : : stm_f_lzwdec_init,
46 : : stm_f_lzwdec_apply,
47 : : stm_f_lzwdec_deinit);
48 : :
49 : : #define LZW_PARAM_EARLY_CHANGE "EarlyChange"
50 : :
51 : : /* -- LZW helper definitions -- */
52 : :
53 : : typedef unsigned lzw_code_t;
54 : : #define LZW_DEFAULT_EARLY_CHANGE 1
55 : : #define LZW_CODE_SIZE (sizeof (lzw_code_t) << 3)
56 : : #define LZW_CACHE_SIZE (sizeof (lzw_code_t) << 3)
57 : : #define LZW_MIN_BITSIZE 9
58 : : #define LZW_MAX_BITSIZE 12
59 : : #define LZW_MAX_DICTSIZE (1 << LZW_MAX_BITSIZE)
60 : : #define LZW_NULL_INDEX ~0U
61 : :
62 : : enum lzw_special_codes_e {
63 : : LZW_RESET_CODE = 256,
64 : : LZW_EOD_CODE,
65 : : LZW_FIRST_CODE
66 : : };
67 : :
68 : : /* -- LZW code output/input -- */
69 : : /*
70 : : * Object to read and write codes of variable bitsize in a buffer.
71 : : * Warning: using both get and put functions may break the buffer.
72 : : */
73 : : struct lzw_buffer_s
74 : : {
75 : : pdf_buffer_t *buf;
76 : : pdf_uchar_t cache [LZW_CACHE_SIZE];
77 : : pdf_size_t cache_rp;
78 : : pdf_size_t cache_wp;
79 : : lzw_code_t valbuf;
80 : : lzw_code_t maxval;
81 : : int bitsize;
82 : : int valbits;
83 : : };
84 : :
85 : : static void
86 : : lzw_buffer_init (struct lzw_buffer_s *b,
87 : : int bitsize)
88 : : {
89 : 0 : b->buf = NULL;
90 : 0 : b->valbuf = 0;
91 : 0 : b->valbits = 0;
92 : 0 : b->bitsize = bitsize;
93 : 0 : b->maxval = (1 << bitsize) - 1;
94 : 0 : b->cache_wp = 0;
95 : 0 : b->cache_rp = 0;
96 : : }
97 : :
98 : : static enum pdf_stm_filter_apply_status_e
99 : 0 : lzw_buffer_get_code (struct lzw_buffer_s *b,
100 : : pdf_bool_t finish,
101 : : lzw_code_t *code) /* out */
102 : : {
103 : : lzw_code_t r;
104 : :
105 [ # # ][ # # ]: 0 : while (b->valbits <= LZW_CODE_SIZE - 8 && !finish)
106 : : {
107 [ # # ]: 0 : if (!pdf_buffer_eob_p (b->buf))
108 : : {
109 : 0 : b->valbuf |=
110 : 0 : (lzw_code_t) b->buf->data [b->buf->rp++]
111 : : << (LZW_CODE_SIZE - 8 - b->valbits);
112 : :
113 : 0 : b->valbits += 8;
114 : : }
115 : : else
116 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
117 : : }
118 : :
119 [ # # ]: 0 : if (b->valbits < b->bitsize)
120 : 0 : return PDF_STM_FILTER_APPLY_STATUS_EOF;
121 : :
122 : 0 : r = b->valbuf >> (LZW_CODE_SIZE - b->bitsize);
123 : 0 : b->valbuf <<= b->bitsize;
124 : 0 : b->valbits -= b->bitsize;
125 : :
126 : 0 : *code = r;
127 : :
128 : 0 : return PDF_STM_FILTER_APPLY_STATUS_OK;
129 : : }
130 : :
131 : : /* Once finished, call with 0 as code value to flush the buffer. */
132 : : static void
133 : 0 : lzw_buffer_put_code (struct lzw_buffer_s *b,
134 : : lzw_code_t code)
135 : : {
136 : 0 : b->valbuf |= (lzw_code_t) code << (LZW_CODE_SIZE - b->bitsize - b->valbits);
137 : 0 : b->valbits += b->bitsize;
138 : :
139 [ # # ]: 0 : while (b->valbits >= 8)
140 : : {
141 [ # # ]: 0 : if (pdf_buffer_full_p (b->buf))
142 : : {
143 : 0 : b->cache [b->cache_wp++] =
144 : 0 : (pdf_uchar_t) (b->valbuf >> (LZW_CODE_SIZE - 8));
145 : : }
146 : : else
147 : : {
148 : 0 : b->buf->data [b->buf->wp++] =
149 : 0 : (pdf_uchar_t) (b->valbuf >> (LZW_CODE_SIZE - 8));
150 : : }
151 : 0 : b->valbuf <<= 8;
152 : 0 : b->valbits -= 8;
153 : : }
154 : 0 : }
155 : :
156 : : static pdf_bool_t
157 : : lzw_buffer_flush (struct lzw_buffer_s *b)
158 : : {
159 [ # # ][ # # ]: 0 : while (b->cache_rp != b->cache_wp &&
160 : : !pdf_buffer_full_p (b->buf))
161 : : {
162 : 0 : b->buf->data [b->buf->wp++] = b->cache [b->cache_rp++];
163 : : }
164 : :
165 [ # # ]: 0 : if (pdf_buffer_full_p (b->buf))
166 : 0 : return PDF_FALSE;
167 : :
168 : 0 : b->cache_wp = 0;
169 : 0 : b->cache_rp = 0;
170 : :
171 : 0 : return PDF_TRUE;
172 : : }
173 : :
174 : : static pdf_bool_t
175 : : lzw_buffer_inc_bitsize (struct lzw_buffer_s *b)
176 : : {
177 [ # # ][ # # ]: 0 : if (b->bitsize == LZW_MAX_BITSIZE)
[ # # ]
178 : 0 : return PDF_FALSE;
179 : :
180 : 0 : ++b->bitsize;
181 : 0 : b->maxval = (1 << b->bitsize) - 1;
182 : :
183 : 0 : return PDF_TRUE;
184 : : }
185 : :
186 : : static void
187 : : lzw_buffer_set_bitsize (struct lzw_buffer_s *b,
188 : : int newsize)
189 : : {
190 : 0 : b->bitsize = newsize;
191 : 0 : b->maxval = (1 << newsize) - 1;
192 : : }
193 : :
194 : : /* -- LZW dictionary handler -- */
195 : :
196 : : /*
197 : : * The strings are stored in a non balanced ordered binary tree.
198 : : */
199 : : struct lzw_string_s
200 : : {
201 : : lzw_code_t prefix; /* Prefix string code */
202 : : pdf_uchar_t suffix; /* Appended character */
203 : :
204 : : lzw_code_t first; /* First string with the same prefix. */
205 : : lzw_code_t left; /* Next string with smaller suffix and same prefix. */
206 : : lzw_code_t right; /* Next string with greater suffix and same prefix. */
207 : : };
208 : :
209 : : struct lzw_dict_s
210 : : {
211 : : struct lzw_string_s table [LZW_MAX_DICTSIZE];
212 : : pdf_size_t size;
213 : : };
214 : :
215 : : static void
216 : : lzw_string_init (struct lzw_string_s *s)
217 : : {
218 : 0 : memset (s, 0xFF, sizeof (struct lzw_string_s));
219 : : }
220 : :
221 : : static void
222 : 0 : lzw_dict_init (struct lzw_dict_s *d)
223 : : {
224 : : int i;
225 : :
226 : 0 : memset (d->table,
227 : : 0xFF,
228 : : sizeof (struct lzw_string_s) * LZW_MAX_DICTSIZE);
229 : :
230 [ # # ]: 0 : for (i = 0; i < LZW_FIRST_CODE; i++)
231 : : {
232 : 0 : d->table[i].suffix = (pdf_uchar_t) (i & 0xFF);
233 : : }
234 : :
235 : 0 : d->size = LZW_FIRST_CODE;
236 : 0 : }
237 : :
238 : : static pdf_bool_t
239 : : lzw_dict_add (struct lzw_dict_s *d,
240 : : struct lzw_string_s *s)
241 : : {
242 : : lzw_code_t index;
243 : : pdf_bool_t must_add;
244 : :
245 [ # # ]: 0 : if (s->prefix == LZW_NULL_INDEX)
246 : : {
247 : 0 : s->prefix = s->suffix;
248 : 0 : return PDF_FALSE; /* The string is a basic character, found! */
249 : : }
250 : :
251 : 0 : index = d->table[s->prefix].first;
252 : :
253 [ # # ]: 0 : if (index == LZW_NULL_INDEX)
254 : : {
255 : 0 : d->table[s->prefix].first = d->size;
256 : : }
257 : : else
258 : : {
259 : 0 : must_add = PDF_FALSE;
260 [ # # ]: 0 : while (!must_add)
261 : : {
262 [ # # ]: 0 : if (s->suffix == d->table[index].suffix)
263 : : {
264 : 0 : s->prefix = index;
265 : 0 : return PDF_FALSE; /* The string is already in the table, found! */
266 : : }
267 [ # # ]: 0 : else if (s->suffix < d->table[index].suffix)
268 : : {
269 [ # # ]: 0 : if (d->table[index].left == LZW_NULL_INDEX)
270 : : {
271 : 0 : d->table[index].left = d->size;
272 : 0 : must_add = PDF_TRUE;
273 : : }
274 : : else
275 : : {
276 : 0 : index = d->table[index].left;
277 : : }
278 : : }
279 : : else
280 : : {
281 [ # # ]: 0 : if (d->table[index].right == LZW_NULL_INDEX)
282 : : {
283 : 0 : d->table[index].right = d->size;
284 : 0 : must_add = PDF_TRUE;
285 : : }
286 : : else
287 : : {
288 : 0 : index = d->table[index].right;
289 : : }
290 : : }
291 : : }
292 : : }
293 : :
294 : 0 : d->table[d->size++] = *s;
295 : :
296 : 0 : return PDF_TRUE;
297 : : }
298 : :
299 : : static void
300 : : lzw_dict_reset (struct lzw_dict_s *dict)
301 : : {
302 : 0 : lzw_dict_init (dict);
303 : : }
304 : :
305 : : static void
306 : : lzw_dict_fast_add (struct lzw_dict_s *d,
307 : : lzw_code_t prefix,
308 : : pdf_uchar_t suffix)
309 : : {
310 : 0 : d->table[d->size].prefix = prefix;
311 : 0 : d->table[d->size].suffix = suffix;
312 : 0 : d->size++;
313 : : }
314 : :
315 : : static void
316 : : lzw_dict_decode (struct lzw_dict_s *d,
317 : : lzw_code_t code,
318 : : pdf_uchar_t **decode,
319 : : pdf_size_t *size)
320 : : {
321 : 0 : *size = 0;
322 : :
323 : : do
324 : : {
325 : 0 : *(*decode)-- = d->table[code].suffix;
326 : 0 : ++(*size);
327 : 0 : code = d->table[code].prefix;
328 : : }
329 [ # # ][ # # ]: 0 : while (code != LZW_NULL_INDEX);
330 : :
331 : 0 : (*decode)++;
332 : : }
333 : :
334 : : /* -- THE ENCODER -- */
335 : :
336 : : struct lzwenc_state_s
337 : : {
338 : : /* cached params */
339 : : pdf_i32_t early_change;
340 : :
341 : : /* encoding state */
342 : : pdf_bool_t must_reset;
343 : : struct lzw_buffer_s buffer;
344 : : struct lzw_dict_s dict;
345 : : struct lzw_string_s string;
346 : :
347 : : pdf_bool_t really_finish;
348 : : };
349 : :
350 : : static pdf_bool_t
351 : 0 : stm_f_lzwenc_init (const pdf_hash_t *params,
352 : : void **state,
353 : : pdf_error_t **error)
354 : : {
355 : : struct lzwenc_state_s *filter_state;
356 : :
357 : 0 : filter_state = pdf_alloc (sizeof (struct lzwenc_state_s));
358 [ # # ]: 0 : if (!filter_state)
359 : : {
360 : 0 : pdf_set_error (error,
361 : : PDF_EDOMAIN_BASE_STM,
362 : : PDF_ENOMEM,
363 : : "cannot create LZW encoder internal state: "
364 : : "couldn't allocate %lu bytes",
365 : : (unsigned long)sizeof (struct lzwenc_state_s));
366 : 0 : return PDF_FALSE;
367 : : }
368 : :
369 : 0 : filter_state->early_change = LZW_DEFAULT_EARLY_CHANGE; /* set default */
370 : :
371 : : /* EarlyChange is optional! */
372 [ # # ][ # # ]: 0 : if (params &&
373 : : pdf_hash_key_p (params, LZW_PARAM_EARLY_CHANGE))
374 : : {
375 : 0 : filter_state->early_change = pdf_hash_get_bool (params,
376 : : LZW_PARAM_EARLY_CHANGE);
377 : : }
378 : :
379 : 0 : lzw_buffer_init (&filter_state->buffer, LZW_MIN_BITSIZE);
380 : 0 : lzw_dict_init (&filter_state->dict);
381 : 0 : lzw_string_init (&filter_state->string);
382 : 0 : filter_state->must_reset = PDF_TRUE;
383 : 0 : filter_state->really_finish = PDF_FALSE;
384 : :
385 : 0 : *state = filter_state;
386 : 0 : return PDF_TRUE;
387 : : }
388 : :
389 : : static enum pdf_stm_filter_apply_status_e
390 : 0 : stm_f_lzwenc_apply (void *state,
391 : : pdf_buffer_t *in,
392 : : pdf_buffer_t *out,
393 : : pdf_bool_t finish,
394 : : pdf_error_t **error)
395 : : {
396 : : struct lzwenc_state_s *st;
397 : :
398 : 0 : st = state;
399 : 0 : st->buffer.buf = out;
400 : :
401 [ # # ]: 0 : if (!lzw_buffer_flush (&st->buffer))
402 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
403 : :
404 [ # # ]: 0 : if (st->really_finish)
405 : 0 : return PDF_STM_FILTER_APPLY_STATUS_EOF;
406 : :
407 [ # # ]: 0 : if (st->must_reset)
408 : : {
409 : 0 : lzw_buffer_put_code (&st->buffer, LZW_RESET_CODE);
410 : 0 : st->must_reset = PDF_FALSE;
411 : : }
412 : :
413 [ # # ][ # # ]: 0 : while (!pdf_buffer_eob_p (in) &&
414 : : !pdf_buffer_full_p (out))
415 : : {
416 : 0 : st->string.suffix = in->data [in->rp++];
417 [ # # ]: 0 : if (lzw_dict_add (&st->dict, &st->string))
418 : : {
419 : 0 : lzw_buffer_put_code (&st->buffer, st->string.prefix);
420 : 0 : st->string.prefix = st->string.suffix;
421 : :
422 [ # # ]: 0 : if (st->dict.size == st->buffer.maxval - st->early_change)
423 : : {
424 : : PDF_DEBUG_BASE ("[LZW encoder] Increasing bitsize... "
425 : : "(dictsize[%d] == maxval[%d] - earlychange[%d])",
426 : : st->dict.size,
427 : : st->buffer.maxval,
428 : : st->early_change);
429 [ # # ]: 0 : if (!lzw_buffer_inc_bitsize (&st->buffer))
430 : : {
431 : 0 : lzw_buffer_put_code (&st->buffer, LZW_RESET_CODE);
432 : 0 : lzw_buffer_set_bitsize (&st->buffer, LZW_MIN_BITSIZE);
433 : 0 : lzw_dict_reset (&st->dict);
434 : : }
435 : : }
436 : : }
437 : : }
438 : :
439 [ # # ]: 0 : if (finish)
440 : : {
441 : 0 : lzw_buffer_put_code (&st->buffer, st->string.prefix);
442 [ # # ]: 0 : if (st->dict.size == st->buffer.maxval - st->early_change)
443 : : {
444 : : PDF_DEBUG_BASE ("[LZW encoder] Increasing bitsize (FINISHING)... "
445 : : "(dictsize[%d] == maxval[%d] - earlychange[%d])",
446 : : st->dict.size,
447 : : st->buffer.maxval,
448 : : st->early_change);
449 : 0 : lzw_buffer_inc_bitsize (&st->buffer);
450 : : }
451 : :
452 : 0 : lzw_buffer_put_code (&st->buffer, LZW_EOD_CODE);
453 : 0 : lzw_buffer_put_code (&st->buffer, 0); /* flush */
454 : :
455 : : /* Delete 0 byte if buffer was already aligned before flush. */
456 [ # # ]: 0 : if (out->data[out->wp - 1] == 0x0)
457 : 0 : out->wp--;
458 : :
459 : 0 : st->really_finish = PDF_TRUE;
460 : :
461 [ # # ]: 0 : return (pdf_buffer_full_p (out) ?
462 : : PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT :
463 : : PDF_STM_FILTER_APPLY_STATUS_EOF);
464 : : }
465 : :
466 [ # # ]: 0 : if (pdf_buffer_full_p (out))
467 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
468 : :
469 : : /* Default, request more input */
470 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
471 : : }
472 : :
473 : : static void
474 : 0 : stm_f_lzwenc_deinit (void *state)
475 : : {
476 : 0 : pdf_dealloc (state);
477 : 0 : }
478 : :
479 : : /* -- THE DECODER -- */
480 : :
481 : : enum lzwdec_state
482 : : {
483 : : LZWDEC_STATE_START,
484 : : LZWDEC_STATE_CLEAN,
485 : : LZWDEC_STATE_WRITE,
486 : : LZWDEC_STATE_READ,
487 : : LZWDEC_STATE_LOOP_WRITE,
488 : : LZWDEC_STATE_LOOP_READ
489 : : };
490 : :
491 : : struct lzwdec_state_s
492 : : {
493 : : /* cached params */
494 : : pdf_i32_t early_change;
495 : :
496 : : /* state */
497 : : pdf_uchar_t dec_buf [LZW_MAX_DICTSIZE];
498 : : pdf_uchar_t *decoded;
499 : : pdf_size_t dec_size;
500 : :
501 : : lzw_code_t new_code;
502 : : lzw_code_t old_code;
503 : :
504 : : /* flow managment */
505 : : enum lzwdec_state state_pos;
506 : : pdf_error_t *tmp_error;
507 : :
508 : : struct lzw_buffer_s buffer;
509 : : struct lzw_dict_s dict;
510 : : };
511 : :
512 : : static pdf_bool_t
513 : 0 : stm_f_lzwdec_init (const pdf_hash_t *params,
514 : : void **state,
515 : : pdf_error_t **error)
516 : : {
517 : : struct lzwdec_state_s *filter_state;
518 : :
519 : 0 : filter_state = pdf_alloc (sizeof (struct lzwdec_state_s));
520 [ # # ]: 0 : if (!filter_state)
521 : : {
522 : 0 : pdf_set_error (error,
523 : : PDF_EDOMAIN_BASE_STM,
524 : : PDF_ENOMEM,
525 : : "cannot create LZW decoder internal state: "
526 : : "couldn't allocate %lu bytes",
527 : : (unsigned long)sizeof (struct lzwdec_state_s));
528 : 0 : return PDF_FALSE;
529 : : }
530 : :
531 : 0 : filter_state->early_change = LZW_DEFAULT_EARLY_CHANGE; /* set default */
532 : :
533 : : /* EarlyChange is optional! */
534 [ # # ][ # # ]: 0 : if (params &&
535 : : pdf_hash_key_p (params, LZW_PARAM_EARLY_CHANGE))
536 : : {
537 : 0 : filter_state->early_change = pdf_hash_get_bool (params, LZW_PARAM_EARLY_CHANGE);
538 : : }
539 : :
540 : 0 : lzw_buffer_init (&filter_state->buffer, LZW_MIN_BITSIZE);
541 : 0 : lzw_dict_init (&filter_state->dict);
542 : 0 : filter_state->old_code = LZW_NULL_INDEX;
543 : 0 : filter_state->decoded = filter_state->dec_buf + (LZW_MAX_DICTSIZE-2);
544 : 0 : filter_state->dec_size = 0;
545 : 0 : filter_state->state_pos = LZWDEC_STATE_START;
546 : 0 : filter_state->tmp_error = NULL;
547 : :
548 : 0 : *state = filter_state;
549 : 0 : return PDF_TRUE;
550 : : }
551 : :
552 : : static void
553 : 0 : stm_f_lzwdec_deinit (void *state)
554 : : {
555 : 0 : pdf_dealloc (state);
556 : 0 : }
557 : :
558 : : /* Returns PDF_FALSE if no more output */
559 : : static pdf_bool_t
560 : : lzwdec_put_decoded (struct lzwdec_state_s *st,
561 : : pdf_buffer_t *out)
562 : : {
563 : 0 : pdf_bool_t no_output = PDF_FALSE;
564 : :
565 [ # # ]: 0 : if (st->dec_size)
566 : : {
567 : : pdf_size_t to_write;
568 : :
569 [ # # ]: 0 : PDF_ASSERT (out->size >= out->wp);
570 : :
571 : : /* output the decoded string */
572 : 0 : to_write = st->dec_size;
573 [ # # ]: 0 : if (st->dec_size > (out->size - out->wp))
574 : : {
575 : 0 : to_write = out->size - out->wp;
576 : 0 : no_output = PDF_TRUE;
577 : : }
578 : :
579 : 0 : memcpy (out->data + out->wp, st->decoded, to_write);
580 : 0 : out->wp += to_write;
581 : 0 : st->decoded += to_write;
582 : 0 : st->dec_size -= to_write;
583 : : }
584 : :
585 : 0 : return !no_output;
586 : : }
587 : :
588 : : /* Returns PDF_FALSE if no more output */
589 : : static pdf_bool_t
590 : : lzwdec_put_code (struct lzwdec_state_s *st,
591 : : pdf_buffer_t *out,
592 : : unsigned long code)
593 : : {
594 [ # # ]: 0 : if (pdf_buffer_full_p (out))
595 : 0 : return PDF_FALSE;
596 : :
597 : 0 : out->data [out->wp++] = (pdf_uchar_t) (code & 0xFF);
598 : 0 : return PDF_TRUE;
599 : : }
600 : :
601 : : #define LZWDEC_CHECK(st, pos, what) \
602 : : do { \
603 : : enum pdf_stm_filter_apply_status_e ret; \
604 : : \
605 : : (st)->state_pos = (pos); \
606 : : if ((ret = (what)) != PDF_STM_FILTER_APPLY_STATUS_OK) \
607 : : { return ret; } \
608 : : } while (0);
609 : :
610 : : static enum pdf_stm_filter_apply_status_e
611 : 0 : stm_f_lzwdec_apply (void *state,
612 : : pdf_buffer_t *in,
613 : : pdf_buffer_t *out,
614 : : pdf_bool_t finish,
615 : : pdf_error_t **error)
616 : : {
617 : : struct lzwdec_state_s *st;
618 : :
619 : 0 : st = state;
620 : 0 : st->buffer.buf = in;
621 : :
622 [ # # # # # : 0 : switch (st->state_pos)
# ]
623 : : {
624 : : case LZWDEC_STATE_START:
625 : : break;
626 : : case LZWDEC_STATE_CLEAN:
627 : : goto lzwdec_state_clean;
628 : : case LZWDEC_STATE_WRITE:
629 : : goto lzwdec_state_write;
630 : : case LZWDEC_STATE_READ:
631 : : goto lzwdec_state_read;
632 : : case LZWDEC_STATE_LOOP_WRITE:
633 : : goto lzwdec_state_loop_write;
634 : : case LZWDEC_STATE_LOOP_READ:
635 : : goto lzwdec_state_loop_read;
636 : : default:
637 : : break;
638 : : }
639 : :
640 : : do
641 : : {
642 : : /* need a reset */
643 : 0 : lzw_buffer_set_bitsize (&st->buffer, LZW_MIN_BITSIZE);
644 : 0 : lzw_dict_reset (&st->dict);
645 : :
646 : : do
647 : : {
648 : : lzwdec_state_clean:
649 [ # # ]: 0 : LZWDEC_CHECK (st,
650 : : LZWDEC_STATE_CLEAN,
651 : : lzw_buffer_get_code (&st->buffer,
652 : : finish,
653 : : &st->new_code));
654 : : }
655 [ # # ]: 0 : while (st->new_code == LZW_RESET_CODE);
656 : :
657 [ # # ]: 0 : if (st->new_code != LZW_EOD_CODE)
658 : : {
659 : : lzwdec_state_write:
660 : 0 : st->state_pos = LZWDEC_STATE_WRITE;
661 [ # # ]: 0 : if (!lzwdec_put_code (st, out, st->new_code))
662 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT; /* No more output */
663 : :
664 : 0 : st->old_code = st->new_code;
665 : :
666 : : lzwdec_state_read:
667 [ # # ]: 0 : LZWDEC_CHECK (st,
668 : : LZWDEC_STATE_READ,
669 : : lzw_buffer_get_code (&st->buffer,
670 : : finish,
671 : : &st->new_code));
672 : : }
673 : :
674 [ # # ]: 0 : while (st->new_code != LZW_EOD_CODE &&
675 : : st->new_code != LZW_RESET_CODE)
676 : : {
677 : 0 : st->decoded = st->dec_buf + (LZW_MAX_DICTSIZE - 2);
678 : :
679 : : /* Is new code in the dict? */
680 [ # # ]: 0 : if (st->new_code < st->dict.size)
681 : : {
682 : 0 : lzw_dict_decode (&st->dict, st->new_code,
683 : : &st->decoded, &st->dec_size);
684 : 0 : lzw_dict_fast_add (&st->dict, st->old_code, st->decoded[0]);
685 : : }
686 : : else
687 : : {
688 : 0 : lzw_dict_decode (&st->dict, st->old_code,
689 : : &st->decoded, &st->dec_size);
690 : 0 : lzw_dict_fast_add (&st->dict, st->old_code, st->decoded[0]);
691 : 0 : st->decoded [st->dec_size++] = st->decoded [0];
692 : : }
693 : :
694 : : /* output the decoded string */
695 : : lzwdec_state_loop_write:
696 : 0 : st->state_pos = LZWDEC_STATE_LOOP_WRITE;
697 [ # # ]: 0 : if (!lzwdec_put_decoded (st, out))
698 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT; /* No more output */
699 : :
700 [ # # ]: 0 : if (st->dict.size == st->buffer.maxval - 1 - st->early_change)
701 : : {
702 : 0 : lzw_buffer_inc_bitsize (&st->buffer);
703 : : /* break; We must wait for the reset code, don't reset yet. */
704 : : }
705 : :
706 : : /* get next code */
707 : 0 : st->old_code = st->new_code;
708 : :
709 : : lzwdec_state_loop_read:
710 [ # # ]: 0 : LZWDEC_CHECK (st,
711 : : LZWDEC_STATE_LOOP_READ,
712 : : lzw_buffer_get_code (&st->buffer,
713 : : finish,
714 : : &st->new_code));
715 : : }
716 : : }
717 [ # # ]: 0 : while (st->new_code != LZW_EOD_CODE);
718 : :
719 : 0 : st->state_pos = LZWDEC_STATE_START;
720 : 0 : return PDF_STM_FILTER_APPLY_STATUS_EOF;
721 : : }
722 : :
723 : : /* End of pdf_stm_f_lzw.c */
|