Branch data Line data Source code
1 : : /* -*- mode: C -*-
2 : : *
3 : : * File: pdf-stm-f-a85.c
4 : : * Date: Mon Jul 9 22:01:41 2007
5 : : *
6 : : * GNU PDF Library - ASCII85 stream filter
7 : : *
8 : : */
9 : :
10 : : /* Copyright (C) 2009-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 : : #include <string.h>
28 : : #include <ctype.h>
29 : :
30 : : #include <pdf-types.h>
31 : : #include <pdf-stm-f-a85.h>
32 : : #include <pdf-types-buffer.h>
33 : : #include <pdf-hash.h>
34 : :
35 : : /* Define A85 encoder */
36 : 68 : PDF_STM_FILTER_DEFINE (pdf_stm_f_a85enc_get,
37 : : stm_f_a85_init,
38 : : stm_f_a85enc_apply,
39 : : stm_f_a85_deinit);
40 : :
41 : : /* Define A85 decoder */
42 : 250 : PDF_STM_FILTER_DEFINE (pdf_stm_f_a85dec_get,
43 : : stm_f_a85_init,
44 : : stm_f_a85dec_apply,
45 : : stm_f_a85_deinit);
46 : :
47 : : /* If something goes wrong in writing out data, 5 bytes could be leftover */
48 : : #define A85_SPARE_BYTES_LEN 5
49 : : #define A85_OUTPUT_BUFF_LEN 8
50 : :
51 : : /* defined as 79 so that the newline character completes the 80 char line */
52 : : /* (of course that only happens when newline is a single character...) */
53 : : #define A85_ENC_LINE_LENGTH 79
54 : :
55 : : /* Internal state */
56 : : struct pdf_stm_f_a85_s
57 : : {
58 : : /* spare_bytes will store leftover bytes if finish is not set */
59 : : pdf_size_t line_length;
60 : : pdf_size_t spare_count; /* Number of input bytes in spare_bytes */
61 : : pdf_size_t output_count; /* Number of output bytes left in output_buff */
62 : : pdf_bool_t terminated;
63 : : pdf_char_t spare_bytes[A85_SPARE_BYTES_LEN];
64 : : pdf_char_t output_buff[A85_OUTPUT_BUFF_LEN];
65 : : };
66 : :
67 : : /* Common implementation */
68 : :
69 : : static pdf_bool_t
70 : 318 : stm_f_a85_init (const pdf_hash_t *params,
71 : : void **state,
72 : : pdf_error_t **error)
73 : : {
74 : : struct pdf_stm_f_a85_s *filter_state;
75 : :
76 : : /* This filter uses no parameters */
77 : : /* Allocate the internal state structure */
78 : 318 : filter_state = pdf_alloc (sizeof (struct pdf_stm_f_a85_s));
79 [ - + ]: 318 : if (!filter_state)
80 : : {
81 : 0 : pdf_set_error (error,
82 : : PDF_EDOMAIN_BASE_STM,
83 : : PDF_ENOMEM,
84 : : "cannot create ASCII-85 encoder/decoder internal state: "
85 : : "couldn't allocate %lu bytes",
86 : : (unsigned long)sizeof (struct pdf_stm_f_a85_s));
87 : 0 : return PDF_FALSE;
88 : : }
89 : :
90 : : /* Initialization */
91 : 318 : filter_state->line_length = 0;
92 : 318 : filter_state->spare_count = 0;
93 : 318 : filter_state->output_count = 0;
94 : 318 : filter_state->terminated = PDF_FALSE;
95 : :
96 : 318 : *state = (void *) filter_state;
97 : 318 : return PDF_TRUE;
98 : : }
99 : :
100 : : static void
101 : 318 : stm_f_a85_deinit (void *state)
102 : : {
103 : 318 : pdf_dealloc (state);
104 : 318 : }
105 : :
106 : : /* pdf_stm_f_a85_write_out helps deal with the possibility of extremely
107 : : * small output buffer sizes - like 1 byte for example. Since this
108 : : * filter needs to work with 4 to 5 input bytes at a time, and since it
109 : : * then produces 1 to 8 output bytes at a time, it is necessary to be
110 : : * able to buffer up to 8 output bytes internally, and then wait for
111 : : * them to be sent to the output stream.
112 : : *
113 : : * pdf_stm_f_a85_write_out sends data directly to the output stream if
114 : : * there is room, and if no data is already waiting to go out.
115 : : * If there is data waiting to go out, then it appends to the end of
116 : : * the output buffer.
117 : : *
118 : : * All writing to the out stream from this filter should take place
119 : : * through this function.
120 : : *
121 : : * it is critical that pdf_stm_a85_flush_outbuff return PDF_OK
122 : : * (meaning that it's output buffers are empty) before starting
123 : : * to send a new group of output bytes with pdf_stm_f_a85_write_out.
124 : : *
125 : : */
126 : :
127 : : static pdf_bool_t
128 : 2862 : stm_f_a85_write_out (pdf_char_t c,
129 : : pdf_buffer_t *out,
130 : : struct pdf_stm_f_a85_s *filter_state)
131 : : {
132 [ + - ][ + - ]: 2862 : if (!pdf_buffer_full_p (out) &&
133 : 2862 : filter_state->output_count == 0)
134 : : {
135 : 2862 : out->data[out->wp++] = c;
136 : 2862 : return PDF_TRUE;
137 : : }
138 : :
139 [ # # ]: 0 : if (filter_state->output_count < A85_OUTPUT_BUFF_LEN)
140 : : {
141 : 0 : filter_state->output_buff[filter_state->output_count++] = c;
142 : 0 : return PDF_TRUE;
143 : : }
144 : :
145 : 2862 : return PDF_FALSE;
146 : : }
147 : :
148 : : /* pdf_stm_f_a85_flush_outbuff helps deal with the possibility of extremely
149 : : * small output buffer sizes - like 1 byte for example. Since this
150 : : * filter needs to work with 4 to 5 input bytes at a time, and since it
151 : : * then produces 1 to 8 output bytes at a time, it is necessary to be
152 : : * able to buffer up to 8 output bytes internally, and then wait for
153 : : * them to be sent to the output stream.
154 : : *
155 : : * Because this output buffer is sized to handle the output data from a single
156 : : * input group (up to 8 bytes for the encoding (5 output data bytes, plus a
157 : : * newline, plus the terminating sequence)) it is necessary that the output
158 : : * buffer be empty before starting to generate another set of output.
159 : : *
160 : : * pdf_stm_f_a85_flush_outbuff must return PDF_OK before starting to generate
161 : : * a new set of output bytes. This ensures that all call to _write_out for
162 : : * this set of output bytes will succeed, and no data will be lost.
163 : : *
164 : : */
165 : : static pdf_status_t
166 : 1886 : stm_f_a85_flush_outbuff (pdf_buffer_t *out,
167 : : struct pdf_stm_f_a85_s *filter_state)
168 : : {
169 : 1886 : pdf_status_t retval = PDF_OK;
170 : : pdf_size_t i;
171 : : pdf_size_t k;
172 : :
173 : 1886 : i = 0;
174 : :
175 [ - + ]: 1886 : while ((i < filter_state->output_count) && (PDF_OK == retval))
176 : : {
177 [ # # ]: 0 : if (pdf_buffer_full_p (out))
178 : : {
179 : 0 : retval = PDF_ENOUTPUT;
180 : : }
181 : : else
182 : : {
183 : 0 : out->data[out->wp++] = filter_state->output_buff[i++];
184 : : }
185 : : }
186 : :
187 [ + - ][ + - ]: 3772 : if ((PDF_ENOUTPUT == retval) || (i == filter_state->output_count))
188 : : { /* done flushing (to the extent possible) */
189 : : /* shift remaining bytes back to the beginning of buffer */
190 : :
191 [ - + ]: 1886 : for (k = 0; (k + i) < filter_state->output_count; k++)
192 : : {
193 : 0 : filter_state->output_buff[k] = filter_state->output_buff[k + i];
194 : : }
195 : :
196 : 1886 : filter_state->output_count -= i;
197 : :
198 : : }
199 : : else
200 : : { /* This should not be reachable */
201 : 0 : retval = PDF_ERROR;
202 : : }
203 : :
204 : 1886 : return retval;
205 : : }
206 : :
207 : : static pdf_status_t
208 : 178 : stm_f_a85enc_wr_tuple (pdf_u32_t tuple,
209 : : pdf_u8_t tuple_bytes, /* always 4 for a full tuple */
210 : : void *state,
211 : : pdf_buffer_t *out)
212 : : {
213 : : struct pdf_stm_f_a85_s *filter_state;
214 : : pdf_char_t buf[5];
215 : : int i;
216 : :
217 : 178 : filter_state = (struct pdf_stm_f_a85_s *) state;
218 : :
219 : : /* partial tuple doesn't get z handling */
220 [ + + ]: 178 : if (tuple == 0 &&
221 : 178 : tuple_bytes == 4)
222 : : {
223 : : /* Four 0s in row */
224 : :
225 : : /*
226 : : * PDF_FALSE from pdf_stm_f_a85_write_out means full buffer
227 : : * This should never happen because buffer should have been
228 : : * flushed before starting this set of output data. All
229 : : * subsequent calls to _write_out will fail with PDF_FALSE
230 : : * also, so it is reasonable to ignore the pass or fail
231 : : * status of these invocations within this function. The
232 : : * error will be reported back to the caller of this function.
233 : : */
234 [ - + ]: 40 : if (!stm_f_a85_write_out ('z', out, filter_state))
235 : 0 : return PDF_ERROR;
236 : :
237 : 40 : filter_state->line_length++;
238 [ - + ]: 40 : if (filter_state->line_length >= A85_ENC_LINE_LENGTH)
239 : : {
240 [ # # ]: 0 : if (!stm_f_a85_write_out ('\n', out, filter_state))
241 : 0 : return PDF_ERROR;
242 : :
243 : 0 : filter_state->line_length = 0;
244 : : }
245 : 40 : return PDF_OK;
246 : : }
247 : :
248 : : /* Encode this tuple in base-85 */
249 [ + + ]: 828 : for (i = 0; i < 5; i++)
250 : : {
251 : 690 : buf[i] = (pdf_char_t) (tuple % 85);
252 : 690 : tuple = tuple / 85;
253 : : }
254 : :
255 [ + + ]: 724 : for (i = tuple_bytes; i >= 0; i--)
256 : : {
257 [ - + ]: 586 : if (!stm_f_a85_write_out (buf[i] + (pdf_char_t) '!',
258 : : out, filter_state))
259 : 0 : return PDF_ERROR;
260 : :
261 : 586 : filter_state->line_length++;
262 [ - + ]: 586 : if (filter_state->line_length >= A85_ENC_LINE_LENGTH)
263 : : {
264 [ # # ]: 0 : if (!stm_f_a85_write_out ('\n', out, filter_state))
265 : 0 : return PDF_ERROR;
266 : :
267 : 0 : filter_state->line_length = 0;
268 : : }
269 : : }
270 : :
271 : 178 : return PDF_OK;
272 : : }
273 : :
274 : : static pdf_status_t
275 : 231 : a85enc_apply (void *state,
276 : : pdf_buffer_t *in,
277 : : pdf_buffer_t *out,
278 : : pdf_bool_t finish)
279 : : {
280 : : pdf_size_t in_size;
281 : : struct pdf_stm_f_a85_s *filter_state;
282 : :
283 : : pdf_u32_t tuple;
284 : : pdf_size_t read_bytes;
285 : : pdf_size_t pos_in;
286 : : int avail;
287 : : int i;
288 : : pdf_char_t buf[5];
289 : : pdf_char_t temp_byte;
290 : 231 : pdf_status_t retval = PDF_OK;
291 : :
292 : 231 : filter_state = (struct pdf_stm_f_a85_s *) state;
293 : :
294 : : /*
295 : : * ASCII base-85 encoding produces 5 ASCII characters for every 4
296 : : * bytes in the input data.
297 : : *
298 : : * But take care of the EOD marker (~>) and the newlines/whitespace.
299 : : *
300 : : * Note that 0x00000000 is coded with 'z',
301 : : */
302 : :
303 : : /*
304 : : * Make sure that the output_buff is flushed and ready to accept another
305 : : * batch of data
306 : : */
307 : :
308 : 231 : retval = stm_f_a85_flush_outbuff (out, filter_state);
309 : :
310 [ - + ]: 231 : if (PDF_OK != retval)
311 : : { /* Probably this is PDF_ENOUTPUT - meaning output_buff still has data */
312 : 0 : return retval;
313 : : }
314 : :
315 : : /* Pull any leftover data from last _apply from state->spare_bytes */
316 : :
317 [ + + ]: 231 : if (filter_state->spare_count)
318 : : {
319 : 48 : avail = in->wp - in->rp;
320 [ - + ]: 48 : if ((avail + filter_state->spare_count) >= 4)
321 : : { /* There is a full tuple available */
322 : :
323 : 0 : tuple = 0;
324 : :
325 : 0 : i = 0;
326 : :
327 : 0 : tuple = tuple | (filter_state->spare_bytes[i++] << 24);
328 : 0 : filter_state->spare_count--;
329 : :
330 [ # # ]: 0 : if (filter_state->spare_count)
331 : : {
332 : 0 : temp_byte = filter_state->spare_bytes[i++];
333 : 0 : filter_state->spare_count--;
334 : : }
335 : : else
336 : : {
337 : 0 : temp_byte = in->data[in->rp++];
338 : : }
339 : :
340 : 0 : tuple = tuple | (temp_byte << 16);
341 : :
342 [ # # ]: 0 : if (filter_state->spare_count)
343 : : { /* don't bother incrementing i here - not used again */
344 : 0 : temp_byte = filter_state->spare_bytes[i];
345 : 0 : filter_state->spare_count--;
346 : : }
347 : : else
348 : : {
349 : 0 : temp_byte = in->data[in->rp++];
350 : : }
351 : :
352 : 0 : tuple = tuple | (temp_byte << 8);
353 : :
354 : 0 : tuple = tuple | in->data[in->rp++];
355 : :
356 : 0 : retval = stm_f_a85enc_wr_tuple (tuple, 4, filter_state, out);
357 : : } /* End of if there is a full tuple available */
358 : : else
359 : : {
360 : : /* There was no full tuple available - do nothing.
361 : : If finish is set, then a partial tuple will be written later */
362 : 48 : retval = PDF_ENINPUT;
363 : : }
364 : : } /* end of if spare_count */
365 : :
366 [ - + ]: 231 : if (retval == PDF_ERROR)
367 : 0 : return retval;
368 : :
369 : 231 : retval = stm_f_a85_flush_outbuff (out, filter_state);
370 : :
371 [ - + ]: 231 : if (PDF_OK != retval)
372 : : { /* Probably this is PDF_ENOUTPUT - meaning output_buff still has data */
373 : 0 : return retval;
374 : : }
375 : :
376 : : /* Now do all normal tuples */
377 : :
378 : 231 : in_size = in->wp - in->rp;
379 : :
380 : :
381 [ + + ]: 231 : if ((PDF_OK == retval) && (in_size >= 4))
382 : : {
383 : :
384 [ + + ]: 190 : for (pos_in = 0; (pos_in < in_size) && (PDF_OK == retval); pos_in += 4)
385 : : {
386 : 150 : tuple = 0;
387 : 150 : avail = in_size - pos_in;
388 : :
389 [ + + ]: 150 : if (avail >= 4)
390 : : {
391 : 130 : tuple = tuple | (in->data[in->rp] << 24);
392 : 130 : tuple = tuple | (in->data[in->rp + 1] << 16);
393 : 130 : tuple = tuple | (in->data[in->rp + 2] << 8);
394 : 130 : tuple = tuple | in->data[in->rp + 3];
395 : :
396 : 130 : in->rp += 4;
397 : :
398 : 130 : retval = stm_f_a85enc_wr_tuple (tuple, 4, filter_state, out);
399 [ - + ]: 130 : if (retval != PDF_OK)
400 : 0 : return retval;
401 : :
402 : 130 : retval = stm_f_a85_flush_outbuff (out, filter_state);
403 : :
404 : : } /* end of whole tuple available */
405 : :
406 : : } /* end for loop */
407 : :
408 [ + - ]: 40 : if (PDF_OK == retval)
409 : : { /* Loop terminated by PDF_ENINPUT */
410 : 40 : retval = PDF_ENINPUT;
411 : : }
412 : :
413 : : } /* End if retval == PDF_OK && whole tuple available */
414 [ + - ]: 191 : else if ((PDF_OK == retval) && (in_size < 4))
415 : : {
416 : 191 : retval = PDF_ENINPUT;
417 : : }
418 : : /* Now if finish do a partial tuple if there are leftover bytes */
419 : :
420 [ + + ][ + - ]: 231 : if (finish && (PDF_ENINPUT == retval))
421 : : {
422 : :
423 : : /* If the length of the binary data to be encoded is not a multiple of 4
424 : : bytes, the last, partial group of 4 is used to produce a last, partial
425 : : group of 5 output characters. Given n (1, 2 or 3) bytes of binary
426 : : data, the encoder first appends 4 - n zero bytes to make a complete
427 : : group of 4. It then encodes this group in the usual way, but without
428 : : applying the special z case. Finally, it writes only the first n + 1
429 : : characters of the resulting group of 5. */
430 : :
431 : 95 : in_size = filter_state->spare_count + (in->wp - in->rp);
432 : :
433 [ + + ]: 95 : if (in_size)
434 : : {
435 : :
436 [ + + ]: 152 : for (i = 0; i < (4 - in_size); i++)
437 : : {
438 : 104 : buf[i] = 0;
439 : : }
440 : :
441 : 48 : read_bytes = 0;
442 : :
443 [ + + ]: 136 : for (i = (4 - in_size); i < 4; i++)
444 : : {
445 : :
446 : 88 : avail = in->wp - in->rp;
447 : :
448 [ + - ]: 88 : if (filter_state->spare_count || avail)
449 : : {
450 [ + - ]: 88 : if (filter_state->spare_count)
451 : : {
452 : 88 : buf[i] = filter_state->spare_bytes[read_bytes++];
453 : 88 : filter_state->spare_count--;
454 : : }
455 : : else
456 : : {
457 : 0 : buf[i] = in->data[in->rp++];
458 : : }
459 : : }
460 : : else
461 : : {
462 : 0 : buf[i] = 0;
463 : : }
464 : :
465 : : }
466 : :
467 : 48 : tuple = 0;
468 : 48 : tuple = tuple | buf[0] << 24;
469 : 48 : tuple = tuple | buf[1] << 16;
470 : 48 : tuple = tuple | buf[2] << 8;
471 : 48 : tuple = tuple | buf[3];
472 : :
473 : 48 : retval =
474 : 48 : stm_f_a85enc_wr_tuple (tuple, in_size, filter_state, out);
475 : :
476 : :
477 : : } /* end of if (in_size) */
478 : : else
479 : : {
480 : : /* There was no partial tuple to write out. Do Nothing. */
481 : : }
482 : :
483 [ + + ]: 95 : if (!filter_state->terminated)
484 : : {
485 : : /* Insert the EOD marker */
486 [ + - ][ - + ]: 68 : if (!stm_f_a85_write_out ('~', out, filter_state) ||
487 : : !stm_f_a85_write_out ('>', out, filter_state))
488 : 0 : return PDF_ERROR;
489 : :
490 : 68 : filter_state->terminated = PDF_TRUE;
491 : : }
492 : :
493 : : }
494 [ + - ]: 136 : else if (PDF_ENINPUT == retval)
495 : : { /* finish not set, so save partial tuple (if present) for next call */
496 : 136 : avail = in->wp - in->rp;
497 [ + + ]: 224 : while (avail)
498 : : {
499 [ - + ]: 88 : if (filter_state->spare_count >= A85_SPARE_BYTES_LEN)
500 : : {
501 : 0 : retval = PDF_ERROR;
502 : : }
503 : : else
504 : : {
505 : 176 : filter_state->spare_bytes[filter_state->spare_count++] =
506 : 88 : in->data[in->rp++];
507 : : }
508 : 88 : avail--;
509 : : }
510 : : }
511 : :
512 : :
513 [ + + ][ + + ]: 231 : if (finish && (PDF_OK == retval))
514 : : {
515 : 48 : retval = stm_f_a85_flush_outbuff (out, filter_state);
516 : :
517 [ + - ]: 48 : if (PDF_OK == retval)
518 : : { /* We have completed this filter job: */
519 : 48 : retval = PDF_EEOF;
520 : : }
521 : : }
522 : :
523 : 231 : return retval;
524 : :
525 : : }
526 : :
527 : : /* Do not Pass this function a 'z' quint. */
528 : : /* Make certain that there is room in the output buffer before calling */
529 : : static pdf_status_t
530 : 510 : stm_f_a85dec_wr_quad (const pdf_char_t *quint,
531 : : const pdf_size_t outcount,
532 : : pdf_buffer_t *out,
533 : : struct pdf_stm_f_a85_s *filter_state)
534 : : {
535 : 510 : pdf_status_t retval = PDF_OK;
536 : : pdf_u32_t quad;
537 : : int i;
538 : : pdf_char_t outbytes[4];
539 : :
540 [ - + ]: 510 : if ((outcount < 1) || (outcount > 4))
541 : : {
542 : 0 : retval = PDF_ERROR;
543 : 0 : return retval;
544 : : }
545 : :
546 : : /* Error check on quint contents */
547 : :
548 [ + + ]: 510 : if (quint[0] > 82)
549 : : { /* 83 * 85^4 is greater than 2^32 all by itself. */
550 : 10 : retval = PDF_ERROR;
551 : : }
552 : :
553 [ + + ][ + + ]: 510 : if ((quint[1] > 84) || (quint[2] > 84) ||
[ + + ][ + + ]
554 : 970 : (quint[3] > 84) || (quint[4] > 84))
555 : : { /* any character here greater than 84 is an error */
556 : 50 : retval = PDF_ERROR;
557 : : }
558 : :
559 : : /* Begin Conversion to quad. */
560 : 510 : quad = (pdf_u32_t) quint[0] * 85u;
561 : 510 : quad = (quad + (pdf_u32_t) quint[1]) * 85u;
562 : 510 : quad = (quad + (pdf_u32_t) quint[2]) * 85u;
563 : :
564 : : /* Now we could be adding up to too big a number */
565 : : /* Go in smaller steps and check for potential overflow: */
566 : 510 : quad = (quad + (pdf_u32_t) quint[3]);
567 : :
568 [ + + ]: 510 : if (quad > (pdf_u32_t) ((pdf_u32_t) UINT32_MAX / (pdf_u32_t) 85u))
569 : : { /* This would overflow, so it's an error. Bail */
570 : 50 : retval = PDF_ERROR;
571 : : }
572 : : else
573 : : {
574 : 460 : quad = quad * 85u; /* Complete the incorporation of quint[3] */
575 : :
576 [ + + ]: 460 : if (((pdf_u32_t) (UINT32_MAX - quad)) >= (pdf_u32_t) quint[4])
577 : : {
578 : 430 : quad += quint[4];
579 : : }
580 : : else
581 : : {
582 : 30 : retval = PDF_ERROR;
583 : : }
584 : : }
585 : :
586 [ + + ]: 510 : if (PDF_OK == retval)
587 : : {
588 [ + + ]: 1900 : for (i = 0; i < 4; i++)
589 : : {
590 : 1520 : outbytes[3 - i] = quad % 256;
591 : 1520 : quad = quad / 256;
592 : : }
593 : :
594 [ + + ]: 1760 : for (i = (4 - outcount); i < 4; i++)
595 : : {
596 [ - + ]: 1380 : if (!stm_f_a85_write_out (outbytes[i], out, filter_state))
597 : 0 : return PDF_ERROR;
598 : : }
599 : : }
600 : :
601 : 510 : return retval;
602 : : }
603 : :
604 : : /* Get the next non-whitespace character */
605 : : static pdf_status_t
606 : : stm_f_a85dec_getnext (pdf_buffer_t *in,
607 : : pdf_char_t *pc)
608 : : {
609 : : /* Get the next non-whitespace character */
610 : 3426 : int done = PDF_FALSE;
611 : 3426 : pdf_status_t retval = PDF_OK;
612 : : pdf_char_t c;
613 : :
614 [ + + ]: 7082 : while (!done)
615 : : {
616 [ + + ]: 3656 : if (in->wp > in->rp)
617 : : {
618 : 3070 : c = in->data[in->rp++];
619 [ + + ]: 3070 : if (!isspace (c))
620 : : { /* Found a non-whitespace character. We're done. */
621 : 2840 : done = PDF_TRUE;
622 : 2840 : retval = PDF_OK;
623 : 2840 : *pc = c;
624 : : }
625 : : }
626 : : else
627 : : { /* ran out of input data. We're done. */
628 : 586 : retval = PDF_ENINPUT;
629 : 586 : done = PDF_TRUE;
630 : : }
631 : : }
632 : :
633 : 3426 : return retval;
634 : : }
635 : :
636 : : #define A85_INVALID_TERM_IDX 255
637 : :
638 : : static pdf_status_t
639 : 686 : a85dec_apply (void *state,
640 : : pdf_buffer_t *in,
641 : : pdf_buffer_t *out,
642 : : pdf_bool_t finish)
643 : : {
644 : : struct pdf_stm_f_a85_s *filter_state;
645 : : pdf_char_t quint[5];
646 : : pdf_char_t tr_quint[5];
647 : : pdf_size_t q_idx;
648 : : int i;
649 : : int done;
650 : : int oldone; /* Outer Loop Done */
651 : : pdf_size_t term_idx;
652 : 686 : pdf_status_t retval = PDF_OK;
653 : : int k;
654 : :
655 : 686 : filter_state = (struct pdf_stm_f_a85_s *) state;
656 : :
657 : : /* Fill the output buffer with the contents of the input buffer, but
658 : : note that the second may be bigger than the former */
659 : :
660 : : /* Only process the next bit of input if the output buffer is empty */
661 : 686 : retval = stm_f_a85_flush_outbuff (out, filter_state);
662 [ - + ]: 686 : if (PDF_OK != retval)
663 : : {
664 : 0 : return retval;
665 : : }
666 : :
667 : 686 : oldone = PDF_FALSE;
668 : :
669 [ + + ]: 1932 : while (!oldone)
670 : : {
671 : 1246 : q_idx = 0;
672 : 1246 : term_idx = A85_INVALID_TERM_IDX;
673 : :
674 : : /* First pull any leftover bytes from last _apply(...) and prepend here */
675 [ + + ]: 1246 : if (filter_state->spare_count)
676 : : {
677 : : /* First pull the spare_bytes into the quint */
678 [ + + ]: 196 : for (i = 0; i < filter_state->spare_count; i++)
679 : : {
680 : 123 : quint[q_idx] = filter_state->spare_bytes[i];
681 [ + + ]: 123 : if ('~' == quint[q_idx])
682 : : {
683 : 50 : term_idx = q_idx;
684 : : }
685 : 123 : q_idx++;
686 : : }
687 : 73 : filter_state->spare_count = 0;
688 : : }
689 : :
690 : : /* Now attempt to fill up the rest of the quint from the input stream */
691 : 1246 : done = PDF_FALSE;
692 [ + + ]: 4672 : for (i = q_idx; ((i < 5) && !done); i++)
693 : : {
694 : 6852 : retval = stm_f_a85dec_getnext (in, &(quint[q_idx]));
695 [ + + ]: 3426 : if (PDF_ENINPUT == retval)
696 : : { /* Ran out of input before filling quint */
697 : 586 : done = PDF_TRUE;
698 : : }
699 : : else
700 : : {
701 [ + + ]: 2840 : if ('~' == quint[q_idx])
702 : : {
703 : 120 : term_idx = q_idx;
704 : : }
705 : :
706 [ + + ][ + + ]: 2840 : if ((0 == q_idx) && ('z' == quint[0]))
707 : : {
708 : 180 : done = PDF_TRUE;
709 : : }
710 : :
711 : 2840 : q_idx++;
712 : : }
713 : : }
714 : :
715 : :
716 [ + + ]: 1246 : if (A85_INVALID_TERM_IDX == term_idx)
717 : : { /* Normal Processing */
718 [ + + ]: 1076 : if (5 != q_idx)
719 : : {
720 [ + + ][ + + ]: 626 : if ((1 == q_idx) && ('z' == quint[0]) && (PDF_OK == retval))
721 : : { /* special case 'z' encodes value 0x00000000 */
722 [ + - ][ + - ]: 180 : if (!stm_f_a85_write_out (0, out, filter_state) ||
[ + - ][ - + ]
723 : : !stm_f_a85_write_out (0, out, filter_state) ||
724 : : !stm_f_a85_write_out (0, out, filter_state) ||
725 : : !stm_f_a85_write_out (0, out, filter_state))
726 : 0 : return PDF_FALSE;
727 : : }
728 [ + - ]: 446 : else if (PDF_ENINPUT == retval)
729 : : { /* Not full dataset. Save this data for later */
730 [ + + ]: 479 : for (i = 0; i < q_idx; i++)
731 : : {
732 : 33 : filter_state->spare_bytes[i] = quint[i];
733 : : }
734 : 446 : filter_state->spare_count = q_idx;
735 : 446 : oldone = PDF_TRUE;
736 : : }
737 [ # # ]: 0 : else if (finish)
738 : : { /* finish specified, but valid term. sequence not present */
739 : 0 : retval = PDF_ERROR;
740 : 0 : oldone = PDF_TRUE;
741 : : }
742 : : else
743 : : { /* some other error than PDF_ENINPUT */
744 : : /* Let this other error pass through. */
745 : 0 : oldone = PDF_TRUE;
746 : : }
747 : : }
748 [ + - ]: 450 : else if ((5 == q_idx) && (PDF_OK == retval))
749 : : { /* 5 good output bytes present */
750 : : /* remove the offset from each byte */
751 [ + + ]: 2700 : for (i = 0; i < 5; i++)
752 : : {
753 : 2250 : tr_quint[i] = quint[i] - '!';
754 : :
755 : : }
756 : :
757 : 450 : retval = stm_f_a85dec_wr_quad (tr_quint, 4, out,
758 : : filter_state);
759 : :
760 [ + + ]: 450 : if (PDF_OK != retval)
761 : : {
762 : : /* Something wrong in writing out data. Save for next call */
763 [ + + ]: 780 : for (i = 0; i < q_idx; i++)
764 : : {
765 : 650 : filter_state->spare_bytes[i] = quint[i];
766 : : }
767 : 130 : filter_state->spare_count = q_idx;
768 : 130 : oldone = PDF_TRUE;
769 : : }
770 : :
771 : : }
772 : : }
773 : : else
774 : : { /* Start of termination pattern detected. */
775 : :
776 [ + + ]: 170 : if (1 == term_idx)
777 : : {
778 : : /* There is a single byte to process before term sequence */
779 : : /* This is an error */
780 : 10 : retval = PDF_ERROR;
781 : 10 : oldone = PDF_TRUE;
782 : : }
783 [ + + ]: 160 : else if (term_idx > 1)
784 : : {
785 : : /* Prepare quint for handoff to wr_quad */
786 [ + + ]: 200 : for (i = 0; i < (5 - term_idx); i++)
787 : : { /* Pad with zeroes */
788 : 140 : tr_quint[i] = 0;
789 : : }
790 : :
791 [ + + ]: 220 : for (i = 0; i < term_idx; i++)
792 : : { /* Pull in data bytes */
793 : 160 : tr_quint[(5 - term_idx) + i] = quint[i] - '!';
794 : : }
795 : :
796 : 60 : retval = stm_f_a85dec_wr_quad (tr_quint, (term_idx - 1), out,
797 : : filter_state);
798 : :
799 : : /* Now put remaining parts of the term. seq. at beg. of quint */
800 : 60 : k = 0;
801 [ + + ]: 170 : for (i = term_idx; i < q_idx; i++)
802 : : {
803 : 110 : quint[k++] = quint[i];
804 : : }
805 : 60 : q_idx = k;
806 : :
807 : : }
808 : : else
809 : : {
810 : : /* 0 == term_idx - only term sequence - no quad output */
811 : : }
812 : :
813 : : /* Now check to see if we have valid finishing conditions: */
814 [ + + ][ + - ]: 170 : if ((PDF_ENINPUT == retval) && (2 == q_idx)
[ + - ]
815 : 370 : && ('~' == quint[0]) && ('>' == quint[1]))
816 : : {
817 [ + + ]: 100 : if (finish)
818 : : {
819 : : /* All we have is term code, and finish is requested. fini */
820 : 50 : retval = PDF_EEOF;
821 : 50 : oldone = PDF_TRUE;
822 : : }
823 : : else
824 : : { /* finish not set. save the bytes for later */
825 [ + + ]: 150 : for (i = 0; i < q_idx; i++)
826 : : {
827 : 100 : filter_state->spare_bytes[i] = quint[i];
828 : : }
829 : 50 : filter_state->spare_count = q_idx;
830 : 50 : oldone = PDF_TRUE;
831 : : }
832 : : }
833 : : }
834 : :
835 [ + + ]: 1246 : if (!oldone && PDF_OK == retval)
836 : : {
837 : 560 : retval = stm_f_a85_flush_outbuff (out, filter_state);
838 : :
839 [ - + ]: 560 : if (PDF_OK != retval)
840 : : {
841 : 0 : oldone = PDF_TRUE;
842 : : }
843 : : }
844 : :
845 : : }
846 : 686 : return retval;
847 : : }
848 : :
849 : : /* NOTE:
850 : : * This method is just a helper method until the A85 filter is fully ported to
851 : : * the new API */
852 : : static enum pdf_stm_filter_apply_status_e
853 : 231 : stm_f_a85enc_apply (void *state,
854 : : pdf_buffer_t *in,
855 : : pdf_buffer_t *out,
856 : : pdf_bool_t finish,
857 : : pdf_error_t **error)
858 : : {
859 : : pdf_status_t ret;
860 : :
861 : 231 : ret = a85enc_apply (state,
862 : : in,
863 : : out,
864 : : finish);
865 [ + - + - ]: 231 : switch (ret)
866 : : {
867 : : case PDF_OK:
868 : : case PDF_ENINPUT:
869 : 183 : return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
870 : : case PDF_ENOUTPUT:
871 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
872 : : case PDF_EEOF:
873 : 48 : return PDF_STM_FILTER_APPLY_STATUS_EOF;
874 : : default:
875 : 0 : pdf_set_error (error,
876 : : PDF_EDOMAIN_BASE_STM,
877 : : ret,
878 : : "Generic error applying ASCII-85 encoder");
879 : 231 : return PDF_STM_FILTER_APPLY_STATUS_ERROR;
880 : : }
881 : : }
882 : :
883 : : /* NOTE:
884 : : * This method is just a helper method until the A85 filter is fully ported to
885 : : * the new API */
886 : : static enum pdf_stm_filter_apply_status_e
887 : 686 : stm_f_a85dec_apply (void *state,
888 : : pdf_buffer_t *in,
889 : : pdf_buffer_t *out,
890 : : pdf_bool_t finish,
891 : : pdf_error_t **error)
892 : : {
893 : : pdf_status_t ret;
894 : :
895 : 686 : ret = a85dec_apply (state,
896 : : in,
897 : : out,
898 : : finish);
899 [ + - + + ]: 686 : switch (ret)
900 : : {
901 : : case PDF_OK:
902 : : case PDF_ENINPUT:
903 : 496 : return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
904 : : case PDF_ENOUTPUT:
905 : 0 : return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
906 : : case PDF_EEOF:
907 : 50 : return PDF_STM_FILTER_APPLY_STATUS_EOF;
908 : : default:
909 : 140 : pdf_set_error (error,
910 : : PDF_EDOMAIN_BASE_STM,
911 : : ret,
912 : : "Generic error applying ASCII-85 decoder");
913 : 686 : return PDF_STM_FILTER_APPLY_STATUS_ERROR;
914 : : }
915 : : }
916 : :
917 : : /* End of pdf_stm_f_a85.c */
|