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

       1                 : /* -*- mode: C -*-
       2                 :  *
       3                 :  *       File:         pdf-stm-f-flate.c
       4                 :  *       Date:         Tue Jul 10 23:44:00 2007
       5                 :  *
       6                 :  *       GNU PDF Library - FlateDecode stream filter
       7                 :  *
       8                 :  */
       9                 : 
      10                 : /* Copyright (C) 2007, 2008, 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                 : 
      28                 : #include <stdio.h>
      29                 : #include <string.h>
      30                 : 
      31                 : #include <pdf-alloc.h>
      32                 : #include <pdf-hash.h>
      33                 : #include <pdf-stm-f-flate.h>
      34                 : 
      35                 : 
      36                 : static pdf_status_t read_and_inflate (pdf_stm_f_flate_t st, pdf_buffer_t in,
      37                 :                                       pdf_buffer_t out);
      38                 : static pdf_status_t read_and_deflate (pdf_stm_f_flate_t st, pdf_buffer_t in,
      39                 :                                       pdf_buffer_t out,
      40                 :                                       pdf_bool_t finish_p);
      41                 : static int deflate_inbuf (pdf_stm_f_flate_t st, pdf_buffer_t out,
      42                 :                           int flush);
      43                 : static pdf_status_t deflate_inbuf_return (pdf_stm_f_flate_t st,
      44                 :                                           pdf_buffer_t out,
      45                 :                                           pdf_bool_t finish_p);
      46                 : 
      47                 : pdf_status_t
      48                 : pdf_stm_f_flateenc_init (pdf_hash_t params, void **state)
      49               1 : {
      50                 :   pdf_status_t ret;
      51                 :   pdf_stm_f_flate_t filter_state;
      52                 : 
      53               1 :   filter_state = pdf_alloc (sizeof (struct pdf_stm_f_flate_s));
      54                 : 
      55               1 :   if (state == NULL)
      56                 :     {
      57               0 :       ret = PDF_EBADDATA;
      58                 :     }
      59               1 :   else if (filter_state == NULL)
      60                 :     {
      61               0 :       ret = PDF_ENOMEM;
      62                 :     }
      63                 :   else
      64                 :     {
      65                 :       /* Initialize fields */
      66               1 :       filter_state->stream.zalloc = Z_NULL;
      67               1 :       filter_state->stream.zfree = Z_NULL;
      68               1 :       filter_state->stream.opaque = Z_NULL;
      69               1 :       filter_state->writing_p = PDF_FALSE;
      70               1 :       filter_state->to_write = 0;
      71               1 :       filter_state->incnt = 0;
      72               1 :       filter_state->outcnt = 0;
      73               1 :       filter_state->zret = Z_OK;
      74                 : 
      75               1 :       if (deflateInit (&(filter_state->stream), Z_DEFAULT_COMPRESSION) != Z_OK)
      76                 :         {
      77               0 :           ret = PDF_ERROR;
      78                 :         }
      79                 :       else
      80                 :         {
      81               1 :           *state = (void *) filter_state;
      82               1 :           ret = PDF_OK;
      83                 :         }
      84                 :     }
      85                 : 
      86               1 :   return ret;
      87                 : }
      88                 : 
      89                 : 
      90                 : pdf_status_t
      91                 : pdf_stm_f_flatedec_init (pdf_hash_t params, void **state)
      92               1 : {
      93                 :   pdf_status_t ret;
      94                 :   pdf_stm_f_flate_t filter_state;
      95                 : 
      96               1 :   filter_state = pdf_alloc (sizeof (struct pdf_stm_f_flate_s));
      97                 : 
      98               1 :   if (state == NULL)
      99                 :     {
     100               0 :       ret = PDF_EBADDATA;
     101                 :     }
     102               1 :   else if (filter_state == NULL)
     103                 :     {
     104               0 :       ret = PDF_ENOMEM;
     105                 :     }
     106                 :   else
     107                 :     {
     108                 :       /* Initialize fields */
     109               1 :       filter_state->stream.zalloc = Z_NULL;
     110               1 :       filter_state->stream.zfree = Z_NULL;
     111               1 :       filter_state->stream.opaque = Z_NULL;
     112               1 :       filter_state->stream.avail_in = 0;
     113               1 :       filter_state->stream.next_in = Z_NULL;
     114               1 :       filter_state->writing_p = PDF_FALSE;
     115               1 :       filter_state->to_write = 0;
     116               1 :       filter_state->incnt = 0;
     117               1 :       filter_state->outcnt = 0;
     118               1 :       filter_state->zret = Z_OK;
     119                 : 
     120               1 :       if (inflateInit (&(filter_state->stream)) != Z_OK)
     121                 :         {
     122               0 :           ret = PDF_ERROR;
     123                 :         }
     124                 :       else
     125                 :         {
     126               1 :           *state = (void *) filter_state;
     127               1 :           ret = PDF_OK;
     128                 :         }
     129                 :     }
     130                 : 
     131               1 :   return ret;
     132                 : 
     133                 : }
     134                 : 
     135                 : 
     136                 : pdf_status_t
     137                 : pdf_stm_f_flateenc_apply (pdf_hash_t params, void *state, pdf_buffer_t in,
     138                 :                           pdf_buffer_t out, pdf_bool_t finish_p)
     139            2160 : {
     140                 :   pdf_stm_f_flate_t st;
     141                 :   pdf_status_t ret;
     142            2160 :   st = (pdf_stm_f_flate_t) state;
     143                 : 
     144            2160 :   ret = read_and_deflate (st, in, out, finish_p);
     145            4320 :   while (ret == PDF_OK)
     146                 :     {
     147               0 :       ret = read_and_deflate (st, in, out, finish_p);
     148                 :     }
     149            2160 :   return ret;
     150                 : }
     151                 : 
     152                 : 
     153                 : pdf_status_t
     154                 : pdf_stm_f_flatedec_apply (pdf_hash_t params, void *state, pdf_buffer_t in,
     155                 :                           pdf_buffer_t out, pdf_bool_t finish_p)
     156            1095 : {
     157                 :   pdf_stm_f_flate_t st;
     158                 :   pdf_status_t ret;
     159            1095 :   st = (pdf_stm_f_flate_t) state;
     160                 :   
     161            1095 :   ret = read_and_inflate (st, in, out);
     162            2190 :   while (ret == PDF_OK)
     163                 :     {
     164               0 :       ret = read_and_inflate (st, in, out);
     165                 :     }
     166            1095 :   return ret;
     167                 : }
     168                 : 
     169                 : 
     170                 : 
     171                 : pdf_status_t
     172                 : pdf_stm_f_flatedec_dealloc_state (void *state)
     173               1 : {
     174               1 :   pdf_stm_f_flate_t st = state;
     175               1 :   inflateEnd(&(st->stream));
     176               1 :   pdf_dealloc (state);
     177               1 :   return PDF_OK;
     178                 : }
     179                 : 
     180                 : pdf_status_t
     181                 : pdf_stm_f_flateenc_dealloc_state (void *state)
     182               1 : {
     183               1 :   pdf_dealloc (state);
     184               1 :   return PDF_OK;
     185                 : }
     186                 : 
     187                 : 
     188                 : /* Private functions */
     189                 : 
     190                 : 
     191                 : static pdf_status_t read_and_deflate (pdf_stm_f_flate_t st, pdf_buffer_t in,
     192                 :                                       pdf_buffer_t out, pdf_bool_t finish_p)
     193            2160 : {
     194                 : 
     195                 :   /* Fill the input CHUNK  */
     196            2160 :   if (!st->writing_p)
     197                 :     {
     198            3178 :       while (st->incnt < PDF_STM_F_FLATE_CHUNK && !pdf_buffer_eob_p(in))
     199                 :         {
     200            1059 :           st->inbuf[st->incnt] = in->data[in->rp];
     201            1059 :           st->incnt++;
     202            1059 :           in->rp++;
     203                 :         }
     204                 :       /* If more data may come and the input CHUNK has space, ask for it. */
     205            2119 :       if (!finish_p && st->incnt < PDF_STM_F_FLATE_CHUNK)
     206                 :         {
     207            2118 :           return PDF_ENINPUT;
     208                 :         }
     209                 :     }
     210                 :     
     211                 :   /* 
     212                 :    * Now we have the input CHUNK full or finish_p is set,
     213                 :    * we deflate and write to out.
     214                 :    */ 
     215              84 :   return (deflate_inbuf_return (st, out, finish_p));
     216                 : }
     217                 : 
     218                 : 
     219                 : static pdf_status_t read_and_inflate (pdf_stm_f_flate_t st, pdf_buffer_t in,
     220                 :                                       pdf_buffer_t out)
     221            1095 : {
     222                 :   /* Fill the input CHUNK */
     223            1095 :   if (!st->writing_p)
     224                 :     {
     225              73 :       while (st->incnt < PDF_STM_F_FLATE_CHUNK && !pdf_buffer_eob_p(in))
     226                 :         {
     227              36 :           st->inbuf[st->incnt] = in->data[in->rp];
     228              36 :           st->incnt++;
     229              36 :           in->rp++;
     230                 :         }
     231                 :     }
     232                 :   else
     233                 :     {
     234                 :       /*
     235                 :        * Not nice, but keeps the writing process code clear.
     236                 :        * Notice that the labeled code is inside a while loop,
     237                 :        * so I feel that avoiding this goto won't bring us better code.
     238                 :        */
     239            1058 :       goto writing;
     240                 :     }
     241                 : 
     242              37 :   if (st->incnt == 0)
     243                 :     {
     244               1 :       return PDF_ENINPUT;
     245                 :     }
     246                 : 
     247                 :   /* we inflate and write to out */
     248              36 :   st->stream.avail_in = st->incnt;
     249              36 :   st->stream.next_in = st->inbuf;
     250                 :   do {
     251              36 :     st->stream.avail_out = PDF_STM_F_FLATE_CHUNK;
     252              36 :     st->stream.next_out = st->outbuf;
     253              36 :     st->outcnt = 0;
     254                 : 
     255              36 :     st->zret = inflate(&(st->stream), Z_NO_FLUSH);
     256              36 :     if (st->zret == Z_STREAM_ERROR || st->zret == Z_NEED_DICT ||
     257                 :         st->zret == Z_DATA_ERROR || st->zret == Z_MEM_ERROR)
     258                 :       {
     259                 :         /* should not be reached */
     260               0 :         inflateEnd(&(st->stream));
     261               0 :         return PDF_ERROR;
     262                 :       }
     263                 : 
     264              36 :     st->to_write = PDF_STM_F_FLATE_CHUNK - st->stream.avail_out;
     265                 : 
     266                 :   writing:
     267            2153 :     while (st->outcnt < st->to_write && !pdf_buffer_full_p(out))
     268                 :       {
     269            1059 :         out->data[out->wp] = st->outbuf[st->outcnt];
     270            1059 :         out->wp++;
     271            1059 :         st->outcnt++;
     272                 :       }
     273            1094 :     if (pdf_buffer_full_p(out))
     274                 :       {
     275            1059 :         st->writing_p = PDF_TRUE;
     276            1059 :         return PDF_ENOUTPUT;
     277                 :       }
     278              35 :   } while (st->stream.avail_out == 0);
     279                 : 
     280              35 :   if (st->zret == Z_STREAM_END)
     281                 :     {
     282               0 :       return PDF_EEOF;
     283                 :     }
     284                 :   /* the input CHUNK now is empty, if needed, ask for input */
     285              35 :   st->writing_p = PDF_FALSE;
     286              35 :   st->incnt = 0;
     287              35 :   if (pdf_buffer_eob_p(in))
     288                 :     {
     289              35 :       return PDF_ENINPUT;
     290                 :     }
     291                 : 
     292                 :   /* ask for the input we couldn't read */
     293               0 :   return PDF_OK;
     294                 : }
     295                 : 
     296                 : 
     297                 : static int
     298                 : deflate_inbuf (pdf_stm_f_flate_t st, pdf_buffer_t out, int flush)
     299              42 : {
     300              42 :   if (st->writing_p)
     301                 :     {
     302                 :       /* 
     303                 :        * Not nice, but keeps the writing process code clear.
     304                 :        * Notice that the labeled code is inside a while loop,
     305                 :        * so I feel that avoiding this goto won't bring us better code.
     306                 :        */
     307              41 :       goto writing;
     308                 :     }
     309                 : 
     310               1 :   st->stream.avail_in = st->incnt;
     311               1 :   st->stream.next_in = st->inbuf;
     312                 :   do {
     313               1 :     st->stream.avail_out = PDF_STM_F_FLATE_CHUNK;
     314               1 :     st->stream.next_out = st->outbuf;
     315               1 :     st->outcnt = 0;
     316                 : 
     317               1 :     st->zret = deflate(&(st->stream), flush);
     318               1 :     if (st->zret == Z_STREAM_ERROR)
     319                 :       {
     320                 :         /* should not be reached */
     321               0 :         deflateEnd (&(st->stream));
     322               0 :         return -1;
     323                 :       }
     324                 : 
     325               1 :     st->to_write = PDF_STM_F_FLATE_CHUNK - st->stream.avail_out;
     326                 : 
     327                 :   writing:
     328                 : 
     329              83 :     while (st->outcnt < st->to_write && !pdf_buffer_full_p(out))
     330                 :       {
     331              41 :         out->data[out->wp++] = st->outbuf[st->outcnt];
     332              41 :         st->outcnt++;
     333                 :       }
     334              42 :     if (pdf_buffer_full_p(out))
     335                 :       {
     336              41 :         st->writing_p = PDF_TRUE;
     337              41 :         return 1;
     338                 :       }
     339               1 :   } while (st->stream.avail_out == 0);
     340                 : 
     341               1 :   st->writing_p = PDF_FALSE;
     342               1 :   return 0;
     343                 : }
     344                 : 
     345                 : 
     346                 : static pdf_status_t
     347                 : deflate_inbuf_return (pdf_stm_f_flate_t st, pdf_buffer_t out,
     348                 :                       pdf_bool_t finish_p)
     349                 : {
     350                 :   int ret;
     351                 : 
     352              42 :   if (finish_p)
     353                 :     {
     354              42 :       ret = deflate_inbuf(st, out, Z_FINISH);
     355                 :     }
     356                 :   else
     357                 :     {
     358               0 :       ret = deflate_inbuf(st, out, Z_NO_FLUSH);
     359                 :     }
     360                 : 
     361              42 :   if (ret < 0)
     362                 :     {
     363               0 :       return PDF_ERROR;
     364                 :     }
     365              42 :   else if (ret > 0)
     366                 :     {
     367              41 :       return PDF_ENOUTPUT;
     368                 :     }
     369               1 :   else if (finish_p)
     370                 :     {
     371               1 :       deflateEnd (&(st->stream));
     372               1 :       return PDF_EEOF;
     373                 :     }
     374                 :   else
     375                 :     {
     376                 :       /* the input CHUNK now is empty */
     377               0 :       st->incnt = 0;
     378                 :       /* ask for the input we couldn't read */
     379               0 :       return PDF_OK;
     380                 :     }
     381                 : }
     382                 : 
     383                 : 
     384                 : /* End of pdf_stm_f_flate.c */

Generated by: LTP GCOV extension version 1.6