LCOV - code coverage report
Current view: top level - src/base - pdf-stm.c (source / functions) Hit Total Coverage
Test: libgnupdf.info Lines: 187 241 77.6 %
Date: 2011-12-09 Functions: 15 17 88.2 %
Branches: 94 150 62.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C -*-
       2                 :            :  *
       3                 :            :  *       File:         pdf-stm.c
       4                 :            :  *       Date:         Fri Jul  6 18:43:15 2007
       5                 :            :  *
       6                 :            :  *       GNU PDF Library - Streams
       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 <unistd.h>
      29                 :            : #include <string.h>
      30                 :            : 
      31                 :            : #include <pdf-alloc.h>
      32                 :            : #include <pdf-stm.h>
      33                 :            : #include <pdf-stm-be.h>
      34                 :            : #include <pdf-stm-be-mem.h>
      35                 :            : #include <pdf-stm-be-cfile.h>
      36                 :            : #include <pdf-stm-be-file.h>
      37                 :            : 
      38                 :            : /* Forward declarations */
      39                 :            : 
      40                 :            : static pdf_bool_t pdf_stm_init (pdf_stm_t            *stm,
      41                 :            :                                 pdf_size_t            cache_size,
      42                 :            :                                 enum pdf_stm_mode_e   mode,
      43                 :            :                                 pdf_error_t         **error);
      44                 :            : 
      45                 :            : static pdf_bool_t pdf_stm_read_peek_char (pdf_stm_t     *stm,
      46                 :            :                                           pdf_uchar_t   *read_char,
      47                 :            :                                           pdf_bool_t     peek,
      48                 :            :                                           pdf_error_t  **error);
      49                 :            : 
      50                 :            : /*
      51                 :            :  * Public functions
      52                 :            :  */
      53                 :            : 
      54                 :            : pdf_stm_t *
      55                 :          0 : pdf_stm_cfile_new (FILE                 *file,
      56                 :            :                    pdf_off_t             offset,
      57                 :            :                    pdf_size_t            cache_size,
      58                 :            :                    enum pdf_stm_mode_e   mode,
      59                 :            :                    pdf_error_t         **error)
      60                 :            : {
      61                 :            :   pdf_stm_t *stm;
      62                 :            : 
      63         [ #  # ]:          0 :   PDF_ASSERT_POINTER_RETURN_VAL (file, NULL);
      64                 :            :   /* Note: if cache_size == 0, we'll use the default one */
      65                 :            : 
      66                 :            :   /* Allocate memory for the new stream */
      67                 :          0 :   stm = pdf_alloc (sizeof (struct pdf_stm_s));
      68         [ #  # ]:          0 :   if (!stm)
      69                 :            :     {
      70                 :          0 :       pdf_set_error (error,
      71                 :            :                      PDF_EDOMAIN_BASE_STM,
      72                 :            :                      PDF_ENOMEM,
      73                 :            :                      "not enough memory to create a stream: "
      74                 :            :                      "couldn't allocate %lu bytes",
      75                 :            :                      (unsigned long) sizeof (struct pdf_stm_s));
      76                 :          0 :       return NULL;
      77                 :            :     }
      78                 :            : 
      79                 :            :   /* Initialize a file stream */
      80                 :          0 :   stm->type = PDF_STM_FILE;
      81                 :          0 :   stm->backend = pdf_stm_be_new_cfile (file, offset, error);
      82         [ #  # ]:          0 :   if (!stm->backend)
      83                 :            :     {
      84                 :          0 :       pdf_stm_destroy (stm);
      85                 :          0 :       return NULL;
      86                 :            :     }
      87                 :            : 
      88                 :            :   /* Initialize the common parts */
      89         [ #  # ]:          0 :   if (!pdf_stm_init (stm, cache_size, mode, error))
      90                 :            :     {
      91                 :          0 :       pdf_stm_destroy (stm);
      92                 :          0 :       return NULL;
      93                 :            :     }
      94                 :          0 :   return stm;
      95                 :            : }
      96                 :            : 
      97                 :            : pdf_stm_t *
      98                 :         11 : pdf_stm_file_new (pdf_fsys_file_t      *file,
      99                 :            :                   pdf_off_t             offset,
     100                 :            :                   pdf_size_t            cache_size,
     101                 :            :                   enum pdf_stm_mode_e   mode,
     102                 :            :                   pdf_error_t         **error)
     103                 :            : {
     104                 :            :   pdf_stm_t *stm;
     105                 :            : 
     106         [ -  + ]:         11 :   PDF_ASSERT_POINTER_RETURN_VAL (file, NULL);
     107                 :            :   /* Note: if cache_size == 0, we'll use the default one */
     108                 :            : 
     109                 :            :   /* Allocate memory for the new stream */
     110                 :         11 :   stm = pdf_alloc (sizeof (struct pdf_stm_s));
     111         [ -  + ]:         11 :   if (!stm)
     112                 :            :     {
     113                 :          0 :       pdf_set_error (error,
     114                 :            :                      PDF_EDOMAIN_BASE_STM,
     115                 :            :                      PDF_ENOMEM,
     116                 :            :                      "not enough memory to create a stream: "
     117                 :            :                      "couldn't allocate %lu bytes",
     118                 :            :                      (unsigned long) sizeof (struct pdf_stm_s));
     119                 :          0 :       return NULL;
     120                 :            :     }
     121                 :            : 
     122                 :            :   /* Initialize a file stream */
     123                 :         11 :   stm->type = PDF_STM_FILE;
     124                 :         11 :   stm->backend = pdf_stm_be_new_file (file, offset, error);
     125         [ -  + ]:         11 :   if (!stm->backend)
     126                 :            :     {
     127                 :          0 :       pdf_stm_destroy (stm);
     128                 :          0 :       return NULL;
     129                 :            :     }
     130                 :            : 
     131                 :            :   /* Initialize the common parts */
     132         [ -  + ]:         11 :   if (!pdf_stm_init (stm, cache_size, mode, error))
     133                 :            :     {
     134                 :          0 :       pdf_stm_destroy (stm);
     135                 :          0 :       return NULL;
     136                 :            :     }
     137                 :         11 :   return stm;
     138                 :            : }
     139                 :            : 
     140                 :            : pdf_stm_t *
     141                 :       1284 : pdf_stm_mem_new (pdf_uchar_t          *buffer,
     142                 :            :                  pdf_size_t            size,
     143                 :            :                  pdf_size_t            cache_size,
     144                 :            :                  enum pdf_stm_mode_e   mode,
     145                 :            :                  pdf_error_t         **error)
     146                 :            : {
     147                 :            :   pdf_stm_t *stm;
     148                 :            : 
     149         [ -  + ]:       1284 :   PDF_ASSERT_POINTER_RETURN_VAL (buffer, NULL);
     150         [ -  + ]:       1284 :   PDF_ASSERT_RETURN_VAL (size > 0, NULL);
     151                 :            :   /* Note: if cache_size == 0, we'll use the default one */
     152                 :            : 
     153                 :            :   /* Allocate memory for the new stream */
     154                 :       1284 :   stm = pdf_alloc (sizeof (struct pdf_stm_s));
     155         [ -  + ]:       1284 :   if (!stm)
     156                 :            :     {
     157                 :          0 :       pdf_set_error (error,
     158                 :            :                      PDF_EDOMAIN_BASE_STM,
     159                 :            :                      PDF_ENOMEM,
     160                 :            :                      "not enough memory to create a stream: "
     161                 :            :                      "couldn't allocate %lu bytes",
     162                 :            :                      (unsigned long) sizeof (struct pdf_stm_s));
     163                 :          0 :       return NULL;
     164                 :            :     }
     165                 :            : 
     166                 :            :   /* Initialize a memory stream */
     167                 :       1284 :   stm->type = PDF_STM_MEM;
     168                 :       1284 :   stm->backend = pdf_stm_be_new_mem (buffer, size, 0, error);
     169         [ -  + ]:       1284 :   if (!stm->backend)
     170                 :            :     {
     171                 :          0 :       pdf_stm_destroy (stm);
     172                 :          0 :       return NULL;
     173                 :            :     }
     174                 :            : 
     175                 :            :   /* Initialize the common parts */
     176         [ -  + ]:       1284 :   if (!pdf_stm_init (stm, cache_size, mode, error))
     177                 :            :     {
     178                 :          0 :       pdf_stm_destroy (stm);
     179                 :          0 :       return NULL;
     180                 :            :     }
     181                 :       1284 :   return stm;
     182                 :            : }
     183                 :            : 
     184                 :            : void
     185                 :       1114 : pdf_stm_destroy (pdf_stm_t *stm)
     186                 :            : {
     187                 :            :   pdf_stm_filter_t *filter;
     188                 :       1114 :   pdf_size_t flushed_bytes = 0;
     189                 :            : 
     190                 :            :   /* Flush the cache ignoring any possible error, finishing the filters */
     191         [ +  + ]:       1114 :   if (stm->mode == PDF_STM_WRITE)
     192                 :        306 :     pdf_stm_flush (stm, PDF_TRUE, &flushed_bytes, NULL);
     193                 :            : 
     194                 :            :   /* Destroy the backend */
     195                 :       1114 :   pdf_stm_be_destroy (stm->backend);
     196                 :            : 
     197                 :            :   /* Destroy the cache */
     198                 :       1114 :   pdf_buffer_destroy (stm->cache);
     199                 :            : 
     200                 :            :   /* Destroy the filter chain */
     201                 :       1114 :   filter = stm->filter;
     202         [ +  + ]:       2714 :   while (filter != NULL)
     203                 :            :     {
     204                 :            :       pdf_stm_filter_t *filter_to_delete;
     205                 :            : 
     206                 :       1600 :       filter_to_delete = filter;
     207                 :       1600 :       filter = pdf_stm_filter_get_next (filter);
     208                 :       1600 :       pdf_stm_filter_destroy (filter_to_delete);
     209                 :            :     }
     210                 :            : 
     211                 :            :   /* Deallocate the stm structure */
     212                 :       1114 :   pdf_dealloc (stm);
     213                 :       1114 : }
     214                 :            : 
     215                 :            : enum pdf_stm_mode_e
     216                 :        737 : pdf_stm_get_mode (pdf_stm_t *stm)
     217                 :            : {
     218         [ -  + ]:        737 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, PDF_STM_UNKNOWN);
     219                 :            : 
     220                 :        737 :   return stm->mode;
     221                 :            : }
     222                 :            : 
     223                 :            : pdf_bool_t
     224                 :       2767 : pdf_stm_read (pdf_stm_t    *stm,
     225                 :            :               pdf_uchar_t  *buf,
     226                 :            :               pdf_size_t    bytes,
     227                 :            :               pdf_size_t   *read_bytes,
     228                 :            :               pdf_error_t **error)
     229                 :            : {
     230                 :            :   pdf_bool_t eof;
     231                 :            : 
     232         [ -  + ]:       2767 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, PDF_FALSE);
     233         [ -  + ]:       2767 :   PDF_ASSERT_POINTER_RETURN_VAL (buf, PDF_FALSE);
     234         [ -  + ]:       2767 :   PDF_ASSERT_RETURN_VAL (bytes > 0, PDF_FALSE);
     235                 :            : 
     236                 :       2767 :   *read_bytes = 0;
     237                 :            : 
     238                 :            :   /* Is this a read stream? */
     239         [ -  + ]:       2767 :   if (stm->mode != PDF_STM_READ)
     240                 :            :     {
     241                 :            :       /* Invalid operation */
     242                 :          0 :       pdf_set_error (error,
     243                 :            :                      PDF_EDOMAIN_BASE_STM,
     244                 :            :                      PDF_EINVOP,
     245                 :            :                      "cannot read from a write stream");
     246                 :          0 :       return PDF_FALSE;
     247                 :            :     }
     248                 :            : 
     249                 :       2767 :   eof = PDF_FALSE;
     250 [ +  + ][ +  + ]:       5506 :   while (*read_bytes < bytes && !eof)
     251                 :            :     {
     252                 :            :       pdf_size_t pending_bytes;
     253                 :            :       pdf_size_t to_copy_bytes;
     254                 :            :       pdf_size_t cache_size;
     255                 :            : 
     256                 :            :       /* If the cache is empty, refill it with filtered data */
     257         [ +  + ]:       2809 :       if (pdf_buffer_eob_p (stm->cache))
     258                 :            :         {
     259                 :        407 :           pdf_error_t *inner_error = NULL;
     260                 :            : 
     261                 :        407 :           pdf_buffer_rewind (stm->cache);
     262                 :            : 
     263                 :            :           /* Break if apply fails */
     264         [ +  + ]:        407 :           if (!pdf_stm_filter_apply (stm->filter,
     265                 :            :                                      PDF_FALSE,
     266                 :            :                                      &eof,
     267                 :            :                                      &inner_error))
     268                 :            :             {
     269                 :            :               /* Report error */
     270                 :         70 :               pdf_propagate_error (error, inner_error);
     271                 :         70 :               return PDF_FALSE;
     272                 :            :             }
     273                 :            :         }
     274                 :            : 
     275                 :            :       /* Read data from the cache */
     276         [ -  + ]:       2739 :       PDF_ASSERT (stm->cache->wp >= stm->cache->rp);
     277                 :       2739 :       pending_bytes = bytes - *read_bytes;
     278                 :       2739 :       cache_size = stm->cache->wp - stm->cache->rp;
     279                 :       2739 :       to_copy_bytes = PDF_MIN (pending_bytes, cache_size);
     280                 :            : 
     281                 :       5478 :       memcpy ((buf + *read_bytes),
     282                 :       5478 :               stm->cache->data + stm->cache->rp,
     283                 :            :               to_copy_bytes);
     284                 :            : 
     285                 :       2739 :       *read_bytes += to_copy_bytes;
     286                 :       2739 :       stm->cache->rp += to_copy_bytes;
     287                 :            :     }
     288                 :            : 
     289                 :            :   /* Update the sequential counter */
     290                 :       2697 :   stm->seq_counter += *read_bytes;
     291                 :            : 
     292                 :            :   /* On EOF, we return PDF_FALSE without error */
     293 [ +  + ][ +  + ]:       2767 :   return ((eof && *read_bytes < bytes) ? PDF_FALSE : PDF_TRUE);
     294                 :            : }
     295                 :            : 
     296                 :            : pdf_bool_t
     297                 :       3032 : pdf_stm_write (pdf_stm_t         *stm,
     298                 :            :                const pdf_uchar_t *buf,
     299                 :            :                pdf_size_t         bytes,
     300                 :            :                pdf_size_t        *written_bytes,
     301                 :            :                pdf_error_t      **error)
     302                 :            : {
     303                 :            :   pdf_stm_filter_t *tail_filter;
     304                 :            :   pdf_buffer_t *tail_buffer;
     305                 :       3032 :   pdf_bool_t eof = PDF_FALSE;
     306                 :            : 
     307         [ -  + ]:       3032 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, PDF_FALSE);
     308         [ -  + ]:       3032 :   PDF_ASSERT_POINTER_RETURN_VAL (buf, PDF_FALSE);
     309         [ -  + ]:       3032 :   PDF_ASSERT_RETURN_VAL (bytes > 0, PDF_FALSE);
     310                 :            : 
     311                 :       3032 :   *written_bytes = 0;
     312                 :            : 
     313                 :            :   /* Is this a write stream? */
     314         [ -  + ]:       3032 :   if (stm->mode != PDF_STM_WRITE)
     315                 :            :     {
     316                 :            :       /* Invalid operation */
     317                 :          0 :       pdf_set_error (error,
     318                 :            :                      PDF_EDOMAIN_BASE_STM,
     319                 :            :                      PDF_EINVOP,
     320                 :            :                      "cannot write in a read stream");
     321                 :          0 :       return PDF_FALSE;
     322                 :            :     }
     323                 :            : 
     324                 :       3032 :   tail_filter = pdf_stm_filter_get_tail (stm->filter);
     325                 :       3032 :   tail_buffer = pdf_stm_filter_get_in (tail_filter);
     326                 :            : 
     327         [ +  + ]:       6068 :   while (*written_bytes < bytes)
     328                 :            :     {
     329                 :            :       pdf_size_t tail_buffer_size;
     330                 :            :       pdf_size_t to_write_bytes;
     331                 :            :       pdf_size_t pending_bytes;
     332                 :            : 
     333 [ +  + ][ +  - ]:       3037 :       if ((pdf_buffer_full_p (tail_buffer)) &&
     334                 :            :           (!pdf_buffer_eob_p (tail_buffer)))
     335                 :            :         {
     336                 :          5 :           pdf_size_t flushed_bytes = 0;
     337                 :          5 :           pdf_error_t *inner_error = NULL;
     338                 :            : 
     339                 :            :           /* Flush the cache */
     340         [ +  + ]:          5 :           if (!pdf_stm_flush (stm,
     341                 :            :                               PDF_FALSE,
     342                 :            :                               &flushed_bytes,
     343                 :            :                               &inner_error))
     344                 :            :             {
     345         [ -  + ]:          1 :               if (inner_error)
     346                 :            :                 {
     347                 :            :                   /* Error flushing */
     348                 :          0 :                   pdf_propagate_error (error, inner_error);
     349                 :          0 :                   return PDF_FALSE;
     350                 :            :                 }
     351                 :            : 
     352                 :            :               /* flush returned PDF_FALSE without error: EOF */
     353                 :          1 :               eof = PDF_TRUE;
     354                 :          1 :               break;
     355                 :            :             }
     356                 :            : 
     357                 :            :           /* No flush needed, keep on */
     358                 :            :         }
     359                 :            : 
     360                 :            :       /* Write the data into the tail buffer. Note that at this
     361                 :            :        * point the tail buffer should be empty */
     362                 :       3036 :       tail_buffer_size = tail_buffer->size - tail_buffer->wp;
     363                 :       3036 :       pending_bytes = bytes - *written_bytes;
     364                 :            : 
     365                 :       3036 :       to_write_bytes = PDF_MIN (pending_bytes, tail_buffer_size);
     366                 :            : 
     367         [ +  - ]:       3036 :       if (to_write_bytes != 0)
     368                 :            :         {
     369                 :       3036 :           memcpy (tail_buffer->data + tail_buffer->wp,
     370                 :       3036 :                   buf + *written_bytes,
     371                 :            :                   to_write_bytes);
     372                 :            : 
     373                 :       3036 :           *written_bytes += to_write_bytes;
     374                 :       3036 :           tail_buffer->wp += to_write_bytes;
     375                 :            :         }
     376                 :            :     }
     377                 :            : 
     378                 :            :   /* Update the sequential counter */
     379                 :       3032 :   stm->seq_counter += *written_bytes;
     380                 :            : 
     381 [ +  + ][ -  + ]:       3032 :   return ((eof && *written_bytes < bytes) ? PDF_FALSE : PDF_TRUE);
     382                 :            : }
     383                 :            : 
     384                 :            : pdf_bool_t
     385                 :        583 : pdf_stm_flush (pdf_stm_t    *stm,
     386                 :            :                pdf_bool_t    finish,
     387                 :            :                pdf_size_t   *flushed_bytes,
     388                 :            :                pdf_error_t **error)
     389                 :            : {
     390                 :            :   pdf_stm_filter_t *tail_filter;
     391                 :            :   pdf_buffer_t *tail_buffer;
     392                 :        583 :   pdf_error_t *inner_error = NULL;
     393                 :        583 :   pdf_bool_t eof = PDF_FALSE;
     394                 :            : 
     395                 :            :   /* NOTE: NULL flushed_bytes is ALLOWED */
     396                 :            : 
     397         [ -  + ]:        583 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, -1);
     398                 :            : 
     399                 :            :   /* Is this a write stream? */
     400         [ +  + ]:        583 :   if (stm->mode != PDF_STM_WRITE)
     401                 :            :     {
     402                 :            :       /* Invalid operation */
     403                 :          1 :       pdf_set_error (error,
     404                 :            :                      PDF_EDOMAIN_BASE_STM,
     405                 :            :                      PDF_EINVOP,
     406                 :            :                      "cannot write in a read stream");
     407                 :          1 :       return PDF_FALSE;
     408                 :            :     }
     409                 :            : 
     410                 :            :   /* Apply the head filter until the filter chain gets empty */
     411                 :        582 :   tail_filter = pdf_stm_filter_get_tail (stm->filter);
     412                 :        582 :   tail_buffer = pdf_stm_filter_get_in (tail_filter);
     413                 :            : 
     414         [ +  + ]:        582 :   if (flushed_bytes)
     415                 :        315 :     *flushed_bytes = 0;
     416                 :            : 
     417                 :            :   while (PDF_TRUE)
     418                 :            :     {
     419                 :            :       pdf_size_t cache_size;
     420                 :            :       pdf_ssize_t written_bytes;
     421                 :            :       pdf_size_t tail_size;
     422                 :            : 
     423                 :        821 :       tail_size = tail_buffer->wp - tail_buffer->rp;
     424                 :            : 
     425                 :            :       /* Break only on error */
     426         [ +  + ]:        821 :       if (!pdf_stm_filter_apply (stm->filter, finish, &eof, &inner_error))
     427                 :            :         break;
     428                 :            : 
     429                 :            :       /* Update the number of flushed bytes */
     430         [ +  + ]:        681 :       if (flushed_bytes)
     431                 :        287 :         *flushed_bytes += tail_size - (tail_buffer->wp - tail_buffer->rp);
     432                 :            : 
     433                 :            :       /* Avoid false EEOF error */
     434 [ +  + ][ +  + ]:        681 :       if (eof && pdf_buffer_eob_p (stm->cache))
     435                 :            :         {
     436                 :        440 :           eof = PDF_FALSE;
     437                 :        440 :           pdf_buffer_rewind (tail_buffer);
     438                 :        440 :           break;
     439                 :            :         }
     440                 :            : 
     441                 :            :       /* Write the data from the buffer cache into the backend */
     442                 :        241 :       cache_size = stm->cache->wp - stm->cache->rp;
     443                 :        241 :       written_bytes = pdf_stm_be_write (stm->backend,
     444                 :            :                                         stm->cache->data + stm->cache->rp,
     445                 :            :                                         cache_size,
     446                 :            :                                         &inner_error);
     447         [ +  - ]:        241 :       if (written_bytes < 0)
     448                 :            :         break;
     449                 :            : 
     450         [ +  + ]:        241 :       if (written_bytes != cache_size)
     451                 :            :         {
     452                 :            :           /* EOF, could not write all the contents of the cache buffer into
     453                 :            :            * the backend */
     454                 :          2 :           stm->cache->rp += written_bytes;
     455                 :          2 :           eof = PDF_TRUE;
     456                 :          2 :           break;
     457                 :            :         }
     458                 :            : 
     459                 :            :       /* Rewind the cache */
     460                 :        239 :       pdf_buffer_rewind (stm->cache);
     461                 :        239 :     }
     462                 :            : 
     463                 :            :   /* Propagate error */
     464         [ +  + ]:        582 :   if (inner_error)
     465                 :            :     {
     466                 :        140 :       pdf_propagate_error (error, inner_error);
     467                 :        140 :       return PDF_FALSE;
     468                 :            :     }
     469                 :            : 
     470         [ +  + ]:        583 :   return (eof ? PDF_FALSE : PDF_TRUE);;
     471                 :            : }
     472                 :            : 
     473                 :            : pdf_bool_t
     474                 :          0 : pdf_stm_supported_filter_p (enum pdf_stm_filter_type_e filter_type)
     475                 :            : {
     476         [ #  # ]:          0 :   PDF_ASSERT_RETURN_VAL (filter_type >= PDF_STM_FILTER_NULL, PDF_FALSE);
     477         [ #  # ]:          0 :   PDF_ASSERT_RETURN_VAL (filter_type < PDF_STM_FILTER_LAST, PDF_FALSE);
     478                 :            : 
     479                 :          0 :   return pdf_stm_filter_p (filter_type);
     480                 :            : }
     481                 :            : 
     482                 :            : pdf_bool_t
     483                 :        486 : pdf_stm_install_filter (pdf_stm_t                   *stm,
     484                 :            :                         enum pdf_stm_filter_type_e   filter_type,
     485                 :            :                         const pdf_hash_t            *filter_params,
     486                 :            :                         pdf_error_t                **error)
     487                 :            : {
     488                 :            :   pdf_stm_filter_t *filter;
     489                 :            :   enum pdf_stm_filter_mode_e filter_mode;
     490                 :            : 
     491         [ -  + ]:        486 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, PDF_FALSE);
     492                 :            : 
     493                 :        486 :   filter_mode = (stm->mode == PDF_STM_READ ?
     494                 :            :                  PDF_STM_FILTER_MODE_READ :
     495                 :            :                  PDF_STM_FILTER_MODE_WRITE);
     496                 :            : 
     497                 :            :   /* Create the new filter. Note that filter_params is passed directly to the
     498                 :            :    * filter implementation creator, and that it may well be NULL. */
     499                 :        486 :   filter = pdf_stm_filter_new (filter_type,
     500                 :            :                                filter_params,
     501                 :        486 :                                stm->cache->size,
     502                 :            :                                filter_mode,
     503                 :            :                                error);
     504         [ -  + ]:        486 :   if (!filter)
     505                 :          0 :     return PDF_FALSE;
     506                 :            : 
     507                 :            :   /* Set the new filter as the new head of the filter chain */
     508                 :        486 :   pdf_stm_filter_set_next (filter, stm->filter);
     509                 :        486 :   pdf_stm_filter_set_out (filter, stm->cache);
     510                 :        486 :   pdf_stm_filter_set_out (stm->filter, pdf_stm_filter_get_in (filter));
     511                 :        486 :   stm->filter = filter;
     512                 :            : 
     513                 :        486 :   return PDF_TRUE;
     514                 :            : }
     515                 :            : 
     516                 :            : pdf_bool_t
     517                 :      89744 : pdf_stm_read_char (pdf_stm_t    *stm,
     518                 :            :                    pdf_uchar_t  *read_char,
     519                 :            :                    pdf_error_t **error)
     520                 :            : {
     521         [ -  + ]:      89744 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, PDF_FALSE);
     522         [ -  + ]:      89744 :   PDF_ASSERT_POINTER_RETURN_VAL (read_char, PDF_FALSE);
     523                 :            : 
     524                 :      89744 :   return pdf_stm_read_peek_char (stm, read_char, PDF_FALSE, error);
     525                 :            : }
     526                 :            : 
     527                 :            : pdf_bool_t
     528                 :      49685 : pdf_stm_peek_char (pdf_stm_t    *stm,
     529                 :            :                    pdf_uchar_t  *read_char,
     530                 :            :                    pdf_error_t **error)
     531                 :            : {
     532         [ -  + ]:      49685 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, PDF_FALSE);
     533         [ -  + ]:      49685 :   PDF_ASSERT_POINTER_RETURN_VAL (read_char, PDF_FALSE);
     534                 :            : 
     535                 :      49685 :   return pdf_stm_read_peek_char (stm, read_char, PDF_TRUE, error);
     536                 :            : }
     537                 :            : 
     538                 :            : pdf_off_t
     539                 :         23 : pdf_stm_bseek (pdf_stm_t *stm,
     540                 :            :                pdf_off_t  pos)
     541                 :            : {
     542                 :            :   pdf_off_t cur_pos;
     543                 :            :   pdf_off_t new_pos;
     544                 :            : 
     545         [ -  + ]:         23 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, (pdf_off_t)-1);
     546                 :            : 
     547                 :         23 :   cur_pos = pdf_stm_tell (stm);
     548                 :            : 
     549         [ +  + ]:         23 :   if (stm->mode == PDF_STM_READ)
     550                 :            :     {
     551                 :            :       /* Discard the cache contents */
     552                 :         22 :       pdf_buffer_rewind (stm->cache);
     553                 :            : 
     554                 :            :       /* Seek the backend */
     555                 :         22 :       new_pos = pdf_stm_be_seek (stm->backend, pos);
     556                 :            :     }
     557                 :            :   else /* Writing stream */
     558                 :            :     {
     559                 :            :       pdf_stm_filter_t *tail_filter;
     560                 :            :       pdf_buffer_t *tail_buffer;
     561                 :            : 
     562                 :          1 :       tail_filter = pdf_stm_filter_get_tail (stm->filter);
     563                 :          1 :       tail_buffer = pdf_stm_filter_get_in (tail_filter);
     564                 :            : 
     565         [ -  + ]:          1 :       if (!pdf_buffer_eob_p (tail_buffer))
     566                 :            :         {
     567                 :          0 :           pdf_error_t *inner_error = NULL;
     568                 :          0 :           pdf_size_t flushed_bytes = 0;
     569                 :            : 
     570                 :            :           /* Flush the stream */
     571 [ #  # ][ #  # ]:          0 :           if (!pdf_stm_flush (stm, PDF_FALSE, &flushed_bytes, &inner_error) &&
     572                 :          0 :               inner_error)
     573                 :            :             {
     574                 :            :               /* Error flushing the stream: return the current position */
     575                 :          0 :               pdf_error_destroy (inner_error);
     576                 :          0 :               return cur_pos;
     577                 :            :             }
     578                 :            :         }
     579                 :            : 
     580                 :            :       /* Note that if there is an EOF condition in the backend we are
     581                 :            :        * going to loose data */
     582                 :          1 :       pdf_buffer_rewind (tail_buffer);
     583                 :            : 
     584                 :            :       /* Seek the backend */
     585                 :          1 :       new_pos = pdf_stm_be_seek (stm->backend, pos);
     586                 :            :     }
     587                 :            : 
     588                 :            :   /* Reset the sequential counter */
     589                 :         23 :   stm->seq_counter = 0;
     590                 :            : 
     591                 :         23 :   return new_pos;
     592                 :            : }
     593                 :            : 
     594                 :            : pdf_off_t
     595                 :         77 : pdf_stm_btell (pdf_stm_t *stm)
     596                 :            : {
     597                 :            :   pdf_off_t pos;
     598                 :            :   pdf_size_t cache_size;
     599                 :            : 
     600         [ -  + ]:         77 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, (pdf_off_t)-1);
     601                 :            : 
     602         [ +  - ]:         77 :   if (stm->mode == PDF_STM_READ)
     603                 :            :     {
     604                 :         77 :       cache_size = stm->cache->wp - stm->cache->rp;
     605                 :         77 :       pos = pdf_stm_be_tell (stm->backend) - cache_size;
     606                 :            :     }
     607                 :            :   else /* Writing stream */
     608                 :            :     {
     609                 :            :       pdf_stm_filter_t *tail_filter;
     610                 :            :       pdf_buffer_t *tail_buffer;
     611                 :            : 
     612                 :          0 :       tail_filter = pdf_stm_filter_get_tail (stm->filter);
     613                 :          0 :       tail_buffer = pdf_stm_filter_get_in (tail_filter);
     614                 :            : 
     615                 :          0 :       cache_size = tail_buffer->wp - tail_buffer->rp;
     616                 :          0 :       pos = pdf_stm_be_tell (stm->backend) - cache_size;
     617                 :            :     }
     618                 :            : 
     619                 :         77 :   return pos;
     620                 :            : }
     621                 :            : 
     622                 :            : pdf_off_t
     623                 :       2540 : pdf_stm_tell (pdf_stm_t *stm)
     624                 :            : {
     625         [ -  + ]:       2540 :   PDF_ASSERT_POINTER_RETURN_VAL (stm, (pdf_off_t)-1);
     626                 :            : 
     627                 :       2540 :   return stm->seq_counter;
     628                 :            : }
     629                 :            : 
     630                 :            : /*
     631                 :            :  * Private functions
     632                 :            :  */
     633                 :            : 
     634                 :            : static pdf_bool_t
     635                 :       1295 : pdf_stm_init (pdf_stm_t            *stm,
     636                 :            :               pdf_size_t            cache_size,
     637                 :            :               enum pdf_stm_mode_e   mode,
     638                 :            :               pdf_error_t         **error)
     639                 :            : {
     640                 :            :   /* Use the default cache size */
     641         [ +  + ]:       1295 :   if (cache_size == 0)
     642                 :       1111 :     cache_size = PDF_STM_DEFAULT_CACHE_SIZE;
     643                 :            : 
     644                 :            :   /* The sequential counter is initially 0 */
     645                 :       1295 :   stm->seq_counter = 0;
     646                 :            : 
     647                 :       1295 :   stm->filter = pdf_stm_filter_new (PDF_STM_FILTER_NULL,
     648                 :            :                                     NULL, /* No filter params needed */
     649                 :            :                                     cache_size,
     650                 :            :                                     (mode == PDF_STM_READ ?
     651                 :            :                                      PDF_STM_FILTER_MODE_READ :
     652                 :            :                                      PDF_STM_FILTER_MODE_WRITE),
     653                 :            :                                     error);
     654         [ -  + ]:       1295 :   if (!stm->filter)
     655                 :          0 :     return PDF_FALSE;
     656                 :            : 
     657                 :            :   /* Initialize the filter cache */
     658                 :       1295 :   stm->cache = pdf_buffer_new (cache_size, error);
     659         [ -  + ]:       1295 :   if (!stm->cache)
     660                 :          0 :     return PDF_FALSE;
     661                 :            : 
     662                 :            :   /* Configure the filter */
     663                 :       1295 :   stm->mode = mode;
     664         [ +  + ]:       1295 :   if (stm->mode == PDF_STM_READ)
     665                 :            :     {
     666                 :            :       /* Configuration for a reading stream
     667                 :            :        *
     668                 :            :        *  <cache> <--- <null-filter> <--- <backend>
     669                 :            :        */
     670                 :        989 :       pdf_stm_filter_set_out (stm->filter, stm->cache);
     671                 :        989 :       pdf_stm_filter_set_be (stm->filter, stm->backend);
     672                 :            :     }
     673                 :            :   else
     674                 :            :     {
     675                 :            :       /* Configuration for a writing stream
     676                 :            :        *
     677                 :            :        * <null-filter> --> <cache> --> <backend>
     678                 :            :        */
     679                 :        306 :       pdf_stm_filter_set_out (stm->filter, stm->cache);
     680                 :            :     }
     681                 :            : 
     682                 :       1295 :   return PDF_TRUE;
     683                 :            : }
     684                 :            : 
     685                 :            : static pdf_bool_t
     686                 :     139429 : pdf_stm_read_peek_char (pdf_stm_t    *stm,
     687                 :            :                         pdf_uchar_t  *read_char,
     688                 :            :                         pdf_bool_t    peek,
     689                 :            :                         pdf_error_t **error)
     690                 :            : {
     691                 :            :   /* Is this a read stream? */
     692         [ -  + ]:     139429 :   if (stm->mode != PDF_STM_READ)
     693                 :            :     {
     694                 :            :       /* Invalid operation */
     695                 :          0 :       pdf_set_error (error,
     696                 :            :                      PDF_EDOMAIN_BASE_STM,
     697                 :            :                      PDF_EINVOP,
     698                 :            :                      "cannot read from a write stream");
     699                 :          0 :       return PDF_FALSE;
     700                 :            :     }
     701                 :            : 
     702                 :            :   /* Is the cache empty? */
     703         [ +  + ]:     139429 :   if (pdf_buffer_eob_p (stm->cache))
     704                 :            :     {
     705                 :       1121 :       pdf_bool_t eof = PDF_FALSE;
     706                 :       1121 :       pdf_error_t *inner_error = NULL;
     707                 :            : 
     708                 :       1121 :       pdf_buffer_rewind (stm->cache);
     709         [ -  + ]:       1121 :       if (!pdf_stm_filter_apply (stm->filter,
     710                 :            :                                  PDF_FALSE,
     711                 :            :                                  &eof,
     712                 :            :                                  &inner_error))
     713                 :            :         {
     714                 :          0 :           pdf_propagate_error (error, inner_error);
     715                 :          0 :           return PDF_FALSE;
     716                 :            :         }
     717                 :            :     }
     718                 :            : 
     719                 :            :   /* If still empty, EOF */
     720         [ +  + ]:     139429 :   if (pdf_buffer_eob_p (stm->cache))
     721                 :        367 :     return PDF_FALSE;
     722                 :            : 
     723                 :            :   /* Read a character from the cache */
     724                 :     139062 :   *read_char = (pdf_u32_t) stm->cache->data[stm->cache->rp];
     725                 :            : 
     726         [ +  + ]:     139062 :   if (!peek)
     727                 :            :     {
     728                 :      89741 :       stm->cache->rp++;
     729                 :      89741 :       stm->seq_counter++;
     730                 :            :     }
     731                 :            : 
     732                 :     139429 :   return PDF_TRUE;
     733                 :            : }
     734                 :            : 
     735                 :            : /* End of pdf_stm.c */

Generated by: LCOV version 1.8