LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-stm-f-a85.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 269
Code covered: 87.0 % Executed lines: 234

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

Generated by: LTP GCOV extension version 1.6