LCOV - code coverage report
Current view: top level - src/base - pdf-stm-f-rl.c (source / functions) Hit Total Coverage
Test: libgnupdf.info Lines: 87 108 80.6 %
Date: 2011-12-09 Functions: 7 7 100.0 %
Branches: 35 57 61.4 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C -*-
       2                 :            :  *
       3                 :            :  *       File:         pdf-stm-f-rl.c
       4                 :            :  *       Date:         Sun Jul 15 22:01:18 2007
       5                 :            :  *
       6                 :            :  *       GNU PDF Library - RunLength encoder/decoder
       7                 :            :  *
       8                 :            :  */
       9                 :            : 
      10                 :            : /* Copyright (C) 2007-2011 Free Software Foundation, Inc. */
      11                 :            : 
      12                 :            : /* This program is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU General Public License as published by
      14                 :            :  * the Free Software Foundation, either version 3 of the License, or
      15                 :            :  * (at your option) any later version.
      16                 :            :  *
      17                 :            :  * This program is distributed in the hope that it will be useful,
      18                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :            :  * GNU General Public License for more details.
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU General Public License
      23                 :            :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <config.h>
      27                 :            : 
      28                 :            : #include <string.h>
      29                 :            : #include <stdio.h>
      30                 :            : 
      31                 :            : #include <pdf-alloc.h>
      32                 :            : #include <pdf-stm-f-rl.h>
      33                 :            : #include <pdf-types.h>
      34                 :            : #include <pdf-types-buffer.h>
      35                 :            : #include <pdf-hash.h>
      36                 :            : 
      37                 :            : /* Define RL encoder */
      38                 :         10 : PDF_STM_FILTER_DEFINE (pdf_stm_f_rlenc_get,
      39                 :            :                        stm_f_rl_init,
      40                 :            :                        stm_f_rlenc_apply,
      41                 :            :                        stm_f_rl_deinit);
      42                 :            : 
      43                 :            : /* Define RL decoder */
      44                 :         10 : PDF_STM_FILTER_DEFINE (pdf_stm_f_rldec_get,
      45                 :            :                        stm_f_rl_init,
      46                 :            :                        stm_f_rldec_apply,
      47                 :            :                        stm_f_rl_deinit);
      48                 :            : 
      49                 :            : typedef enum
      50                 :            : {
      51                 :            :   PDF_STM_F_RL_WRL,
      52                 :            :   PDF_STM_F_RL_NONE
      53                 :            : } pdf_stm_f_rl_enc_e;
      54                 :            : 
      55                 :            : /* Internal state */
      56                 :            : struct pdf_stm_f_rl_s
      57                 :            : {
      58                 :            :   pdf_uchar_t curchar;
      59                 :            :   pdf_uchar_t rlchar;
      60                 :            :   pdf_uchar_t dec_count;
      61                 :            :   pdf_i32_t rl;
      62                 :            :   pdf_bool_t run_p;
      63                 :            :   pdf_bool_t dec_p;
      64                 :            :   pdf_stm_f_rl_enc_e enc_p;
      65                 :            : };
      66                 :            : 
      67                 :            : static pdf_bool_t encode_rl_char (struct pdf_stm_f_rl_s *st,
      68                 :            :                                   pdf_buffer_t          *out);
      69                 :            : 
      70                 :            : static pdf_bool_t decode_rl_char (struct pdf_stm_f_rl_s *st,
      71                 :            :                                   pdf_buffer_t          *out);
      72                 :            : 
      73                 :            : static int copy_next_bytes (struct pdf_stm_f_rl_s *st,
      74                 :            :                             pdf_buffer_t          *in,
      75                 :            :                             pdf_buffer_t          *out);
      76                 :            : 
      77                 :            : /* Common implementation */
      78                 :            : 
      79                 :            : static pdf_bool_t
      80                 :         20 : stm_f_rl_init (const pdf_hash_t  *params,
      81                 :            :                void             **state,
      82                 :            :                pdf_error_t      **error)
      83                 :            : {
      84                 :            :   struct pdf_stm_f_rl_s *filter_state;
      85                 :            : 
      86                 :         20 :   filter_state = pdf_alloc (sizeof (struct pdf_stm_f_rl_s));
      87         [ -  + ]:         20 :   if (!filter_state)
      88                 :            :     {
      89                 :          0 :       pdf_set_error (error,
      90                 :            :                      PDF_EDOMAIN_BASE_STM,
      91                 :            :                      PDF_ENOMEM,
      92                 :            :                      "cannot create RunLength encoder/decoder internal state: "
      93                 :            :                      "couldn't allocate %lu bytes",
      94                 :            :                      (unsigned long)sizeof (struct pdf_stm_f_rl_s));
      95                 :          0 :       return PDF_FALSE;
      96                 :            :     }
      97                 :            : 
      98                 :            :   /* Initialize fields */
      99                 :         20 :   filter_state->curchar = 0;
     100                 :         20 :   filter_state->rlchar = 0;
     101                 :         20 :   filter_state->run_p = PDF_FALSE;
     102                 :         20 :   filter_state->rl = -1;
     103                 :         20 :   filter_state->dec_p = PDF_FALSE;;
     104                 :         20 :   filter_state->dec_count = 0;
     105                 :         20 :   filter_state->enc_p = PDF_STM_F_RL_NONE;
     106                 :            : 
     107                 :         20 :   *state = (void *) filter_state;
     108                 :            : 
     109                 :         20 :   return PDF_TRUE;
     110                 :            : }
     111                 :            : 
     112                 :            : static void
     113                 :         20 : stm_f_rl_deinit (void *state)
     114                 :            : {
     115                 :         20 :   pdf_dealloc (state);
     116                 :         20 : }
     117                 :            : 
     118                 :            : /* Encoder implementation */
     119                 :            : 
     120                 :            : static enum pdf_stm_filter_apply_status_e
     121                 :         30 : stm_f_rlenc_apply (void          *state,
     122                 :            :                    pdf_buffer_t  *in,
     123                 :            :                    pdf_buffer_t  *out,
     124                 :            :                    pdf_bool_t     finish,
     125                 :            :                    pdf_error_t  **error)
     126                 :            : {
     127                 :            :   struct pdf_stm_f_rl_s *filter_state;
     128                 :            : 
     129                 :         30 :   filter_state = (struct pdf_stm_f_rl_s *) state;
     130                 :            : 
     131         [ +  + ]:        580 :   while (!pdf_buffer_eob_p (in))
     132                 :            :     {
     133                 :        550 :       filter_state->curchar = in->data[in->rp];
     134                 :            : 
     135                 :            :       /* we're not encoding any character yet */
     136         [ +  + ]:        550 :       if (!filter_state->run_p)
     137                 :            :         {
     138                 :        100 :           filter_state->rlchar = filter_state->curchar;
     139                 :        100 :           filter_state->run_p = PDF_TRUE;
     140                 :        100 :           filter_state->rl++;
     141                 :        100 :           in->rp++;
     142                 :            :         }
     143                 :            :       /* we're encoding some character now */
     144 [ +  + ][ +  - ]:        450 :       else if (filter_state->curchar == filter_state->rlchar &&
     145                 :        360 :                filter_state->rl < 127)
     146                 :            :         {
     147                 :        360 :           filter_state->rl++;
     148                 :        360 :           in->rp++;
     149                 :            :         }
     150                 :            :       /*
     151                 :            :        * the rl code is too long or the rl char is different,
     152                 :            :        * so we write what we encoded so far.
     153                 :            :        */
     154                 :            :       else
     155                 :            :         {
     156         [ -  + ]:         90 :           if (!encode_rl_char (filter_state, out))
     157                 :          0 :             return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
     158                 :            : 
     159                 :         90 :           filter_state->rl = -1;
     160                 :         90 :           filter_state->run_p = PDF_FALSE;
     161                 :            :         }
     162                 :            :     }
     163                 :            : 
     164                 :            :   /*
     165                 :            :    * we may have finished with some history, we save it if needed,
     166                 :            :    * then we add the EOD.
     167                 :            :    */
     168         [ +  + ]:         30 :   if (finish)
     169                 :            :     {
     170         [ +  - ]:         10 :       if (filter_state->run_p)
     171                 :            :         {
     172         [ -  + ]:         10 :           if (!encode_rl_char (filter_state, out))
     173                 :          0 :             return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
     174                 :            : 
     175                 :         10 :           filter_state->rl = -1;
     176                 :         10 :           filter_state->run_p = PDF_FALSE;
     177                 :            :         }
     178                 :            : 
     179                 :            :       /* Insert EOD marker */
     180         [ -  + ]:         10 :       if (pdf_buffer_full_p (out))
     181                 :          0 :         return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
     182                 :         10 :       out->data[out->wp++] = 128;
     183                 :         10 :       return PDF_STM_FILTER_APPLY_STATUS_EOF;
     184                 :            :     }
     185                 :            : 
     186                 :         30 :   return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
     187                 :            : }
     188                 :            : 
     189                 :            : static enum pdf_stm_filter_apply_status_e
     190                 :         45 : stm_f_rldec_apply (void          *state,
     191                 :            :                    pdf_buffer_t  *in,
     192                 :            :                    pdf_buffer_t  *out,
     193                 :            :                    pdf_bool_t     finish,
     194                 :            :                    pdf_error_t  **error)
     195                 :            : {
     196                 :            :   struct pdf_stm_f_rl_s *filter_state;
     197                 :            : 
     198                 :         45 :   filter_state = (struct pdf_stm_f_rl_s *) state;
     199                 :            : 
     200         [ +  + ]:        255 :   while (!pdf_buffer_eob_p (in))
     201                 :            :     {
     202                 :        210 :       filter_state->curchar = in->data[in->rp];
     203                 :            : 
     204                 :            :       /* we're not decoding any character yet */
     205         [ +  + ]:        210 :       if (!filter_state->run_p)
     206                 :            :         {
     207                 :        110 :           filter_state->rlchar = filter_state->curchar;
     208                 :        110 :           filter_state->run_p = PDF_TRUE;
     209                 :        110 :           in->rp++;
     210                 :            :         }
     211                 :            :       /* copy the following 1 to 128 bytes literally */
     212         [ +  + ]:        100 :       else if (filter_state->rlchar < 128)
     213                 :            :         {
     214                 :            :           int copied;
     215                 :            : 
     216                 :         20 :           copied = copy_next_bytes (filter_state, in, out);
     217         [ -  + ]:         20 :           if (copied < 0)
     218                 :          0 :             return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
     219         [ -  + ]:         20 :           if (copied > 0)
     220                 :          0 :             return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
     221                 :         20 :           filter_state->run_p = PDF_FALSE;
     222                 :            :         }
     223                 :            :       /* copy the next char 257 - length (2 to 128) times */
     224         [ +  - ]:         80 :       else if (filter_state->rlchar > 128)
     225                 :            :         {
     226         [ -  + ]:         80 :           if (!decode_rl_char (filter_state, out))
     227                 :          0 :             return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
     228                 :         80 :           filter_state->run_p = PDF_FALSE;
     229                 :         80 :           in->rp++;
     230                 :            :         }
     231                 :            :       /* EOD mark */
     232                 :            :       else
     233                 :            :         {
     234                 :          0 :           filter_state->run_p = PDF_FALSE;
     235                 :          0 :           return PDF_STM_FILTER_APPLY_STATUS_EOF;
     236                 :            :         }
     237                 :            :     }
     238                 :            : 
     239                 :         45 :   return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT;
     240                 :            : }
     241                 :            : 
     242                 :            : /* Helper functions */
     243                 :            : 
     244                 :            : static pdf_bool_t
     245                 :        100 : encode_rl_char (struct pdf_stm_f_rl_s *st,
     246                 :            :                 pdf_buffer_t          *out)
     247                 :            : {
     248         [ -  + ]:        100 :   if (pdf_buffer_full_p (out))
     249                 :          0 :     return PDF_FALSE;
     250                 :            : 
     251      [ +  -  - ]:        100 :   switch (st->enc_p)
     252                 :            :     {
     253                 :            :     case PDF_STM_F_RL_NONE:
     254         [ +  + ]:        100 :       out->data[out->wp++] = (st->rl == 0) ? 0 : 256 - st->rl;
     255                 :        100 :       st->enc_p = PDF_STM_F_RL_WRL;
     256                 :            :       /* Continue to RL_WRL! */
     257                 :            :     case PDF_STM_F_RL_WRL:
     258                 :        100 :       out->data[out->wp++] = st->rlchar;
     259                 :        100 :       st->enc_p = PDF_STM_F_RL_NONE;
     260                 :            :       break;
     261                 :            :     }
     262                 :            : 
     263                 :        100 :   return PDF_TRUE;
     264                 :            : }
     265                 :            : 
     266                 :            : static pdf_bool_t
     267                 :            : decode_rl_char (struct pdf_stm_f_rl_s *st,
     268                 :            :                 pdf_buffer_t          *out)
     269                 :            : {
     270         [ +  - ]:         80 :   if (!st->dec_p)
     271                 :            :     {
     272                 :         80 :       st->dec_count = 257 - st->rlchar;
     273                 :         80 :       st->dec_p = PDF_TRUE;
     274                 :            :     }
     275                 :            : 
     276         [ +  + ]:        520 :   while (st->dec_count > 0)
     277                 :            :     {
     278         [ -  + ]:        440 :       if (pdf_buffer_full_p (out))
     279                 :          0 :         return PDF_FALSE;
     280                 :            : 
     281                 :        440 :       out->data[out->wp++] = st->curchar;
     282                 :        440 :       st->dec_count--;
     283                 :            :     }
     284                 :            : 
     285                 :         80 :   st->dec_p = PDF_FALSE;
     286                 :         80 :   return PDF_TRUE;
     287                 :            : }
     288                 :            : 
     289                 :            : static int
     290                 :            : copy_next_bytes (struct pdf_stm_f_rl_s *st,
     291                 :            :                  pdf_buffer_t          *in,
     292                 :            :                  pdf_buffer_t          *out)
     293                 :            : {
     294         [ +  - ]:         20 :   if (!st->dec_p)
     295                 :            :     {
     296         [ -  + ]:         20 :       if (pdf_buffer_full_p (out))
     297                 :          0 :         return -1;
     298                 :            : 
     299                 :         20 :       st->dec_count = st->rlchar + 1;
     300                 :         20 :       st->dec_p = PDF_TRUE;
     301                 :         20 :       out->data[out->wp++] = st->curchar;
     302                 :         20 :       in->rp++;
     303                 :         20 :       st->dec_count--;
     304                 :            :     }
     305                 :            : 
     306         [ -  + ]:         20 :   while (st->dec_count > 0)
     307                 :            :     {
     308         [ #  # ]:          0 :       if (pdf_buffer_eob_p (in))
     309                 :          0 :         return 1;
     310                 :            : 
     311         [ #  # ]:          0 :       if (pdf_buffer_full_p (out))
     312                 :          0 :         return -1;
     313                 :            : 
     314                 :          0 :       out->data[out->wp] = in->data[in->rp];
     315                 :          0 :       out->wp++;
     316                 :          0 :       in->rp++;
     317                 :          0 :       st->dec_count--;
     318                 :            :     }
     319                 :            : 
     320                 :         20 :   st->dec_p = PDF_FALSE;
     321                 :         20 :   return 0;
     322                 :            : }
     323                 :            : 
     324                 :            : /* End of pdf_stm_f_rl.c */

Generated by: LCOV version 1.8