LCOV - code coverage report
Current view: top level - u8stream/source/u8stream - universal_file_input_stream.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.64.2_covts Lines: 100.0 % 75 75
Test Date: 2025-06-21 07:03:58 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /* File: universal_file_input_stream.c; Copyright and License: see below */
       2              : 
       3              : #include "u8stream/universal_file_input_stream.h"
       4              : #include "u8stream/universal_input_stream_if.h"
       5              : #include "u8_test_cond.h"
       6              : #include "u8/u8_fault_inject.h"
       7              : #include "u8/u8_trace.h"
       8              : #include "u8/u8_log.h"
       9              : #include <errno.h>
      10              : #include <string.h>
      11              : #include <stdbool.h>
      12              : #include <assert.h>
      13              : 
      14              : /* the vmt implementing the interface */
      15              : static const universal_input_stream_if_t universal_file_input_stream_private_if
      16              :     = {
      17              :         .read = (u8_error_t (*)(universal_input_stream_impl_t*, void*, size_t, size_t*)) &universal_file_input_stream_read,
      18              :         .reset = (u8_error_t (*)(universal_input_stream_impl_t*)) &universal_file_input_stream_reset
      19              :     };
      20              : 
      21           12 : void universal_file_input_stream_init ( universal_file_input_stream_t *this_ )
      22              : {
      23           12 :     U8_TRACE_BEGIN();
      24              : 
      25           12 :     (*this_).input = NULL;
      26           12 :     universal_input_stream_private_init( &((*this_).input_stream), &universal_file_input_stream_private_if, this_ );
      27              : 
      28           12 :     U8_TRACE_END();
      29           12 : }
      30              : 
      31           11 : u8_error_t universal_file_input_stream_destroy( universal_file_input_stream_t *this_ )
      32              : {
      33           11 :     U8_TRACE_BEGIN();
      34           11 :     u8_error_t err = U8_ERROR_NONE;
      35              : 
      36           11 :     if ( (*this_).input != NULL )
      37              :     {
      38            2 :         err = universal_file_input_stream_close( this_ );
      39              :     }
      40           11 :     (*this_).input = NULL;
      41           11 :     universal_input_stream_private_destroy( &((*this_).input_stream) );
      42              : 
      43           11 :     U8_TRACE_END_ERR(err);
      44           11 :     return err;
      45              : }
      46              : 
      47           14 : u8_error_t universal_file_input_stream_open ( universal_file_input_stream_t *this_, const char *path )
      48              : {
      49           14 :     U8_TRACE_BEGIN();
      50           14 :     assert( path != NULL );
      51           14 :     u8_error_t err = 0;
      52              : 
      53           14 :     if ( (*this_).input != NULL )
      54              :     {
      55            1 :         U8_LOG_ERROR("cannot open a file that is already open.");
      56            1 :         err = U8_ERROR_WRONG_STATE;
      57            1 :         err |= universal_file_input_stream_close( this_ );
      58              :     }
      59           14 :     (*this_).input = fopen( path, "r" );
      60           14 :     if ( NULL == (*this_).input )
      61              :     {
      62              :         /* Note: This need not be an error, could be intentionally to avoid TOCTOU issues. */
      63            4 :         U8_LOG_EVENT_STR("could not open file for reading:", strerror(errno) );
      64            4 :         err |= U8_ERROR_AT_FILE_READ;
      65              :     }
      66              : 
      67           14 :     U8_TRACE_END_ERR(err);
      68           14 :     return err;
      69              : }
      70              : 
      71           19 : u8_error_t universal_file_input_stream_read ( universal_file_input_stream_t *this_,
      72              :                                               void *out_buffer,
      73              :                                               size_t max_size,
      74              :                                               size_t *out_length )
      75              : {
      76              :     /*U8_TRACE_BEGIN();*/
      77           19 :     assert( out_buffer != NULL );
      78           19 :     u8_error_t err = U8_ERROR_NONE;
      79              : 
      80           19 :     if ( (*this_).input != NULL )
      81              :     {
      82           18 :         size_t read_bytes = fread( out_buffer, 1, max_size, (*this_).input );
      83           18 :         if ( read_bytes != 0 )
      84              :         {
      85           10 :             *out_length = read_bytes;
      86              :         }
      87              :         else
      88              :         {
      89            8 :             err = U8_ERROR_END_OF_STREAM;  /* finished, no more bytes to read or other error */
      90            8 :             *out_length = 0;
      91              :         }
      92              :     }
      93              :     else
      94              :     {
      95            1 :         U8_LOG_ERROR("cannot read from a file that is not open.");
      96            1 :         err = U8_ERROR_WRONG_STATE;
      97              :     }
      98              : 
      99              :     /*U8_TRACE_END_ERR(err);*/
     100           19 :     return err;
     101              : }
     102              : 
     103            5 : u8_error_t universal_file_input_stream_reset ( universal_file_input_stream_t *this_ )
     104              : {
     105            5 :     U8_TRACE_BEGIN();
     106            5 :     u8_error_t err = U8_ERROR_NONE;
     107              : 
     108            5 :     if ( (*this_).input != NULL )
     109              :     {
     110            4 :         int seek_err = fseek( (*this_).input, 0, SEEK_SET );
     111            4 :         assert( seek_err == 0 );  /* this should not happen, but do not take this for granted */
     112            4 :         U8_FAULT_INJECT_COND_SET( U8_TEST_COND_FSEEK, seek_err, -1 );
     113            4 :         if ( seek_err != 0 )
     114              :         {
     115            1 :             U8_LOG_ERROR("error at resetting the read-cursor in a file.");
     116            1 :             err = U8_ERROR_AT_FILE_READ;
     117              :         }
     118              :     }
     119              :     else
     120              :     {
     121            1 :         U8_LOG_ERROR("cannot reset/seek a file that is not open.");
     122            1 :         err = U8_ERROR_WRONG_STATE;
     123              :     }
     124              : 
     125            5 :     U8_TRACE_END_ERR(err);
     126            5 :     return err;
     127              : }
     128              : 
     129           11 : u8_error_t universal_file_input_stream_close( universal_file_input_stream_t *this_ )
     130              : {
     131           11 :     U8_TRACE_BEGIN();
     132           11 :     u8_error_t err = U8_ERROR_NONE;
     133              : 
     134           11 :     if ( (*this_).input != NULL )
     135              :     {
     136           10 :         int close_err = fclose( (*this_).input );
     137           10 :         assert( close_err == 0 );  /* this should not happen, but do not take this for granted */
     138           10 :         U8_FAULT_INJECT_COND_SET( U8_TEST_COND_FCLOSE, close_err, EOF );
     139           10 :         if ( 0 != close_err )
     140              :         {
     141            1 :             U8_LOG_ERROR_INT( "error at closing file:", close_err );
     142            1 :             err = U8_ERROR_AT_FILE_READ;
     143              :         }
     144           10 :         (*this_).input = NULL;
     145              :     }
     146              :     else
     147              :     {
     148            1 :         U8_LOG_ERROR("cannot close a file that is not open.");
     149            1 :         err = U8_ERROR_WRONG_STATE;
     150              :     }
     151              : 
     152           11 :     U8_TRACE_END_ERR(err);
     153           11 :     return err;
     154              : }
     155              : 
     156            3 : universal_input_stream_t* universal_file_input_stream_get_input_stream( universal_file_input_stream_t *this_ )
     157              : {
     158            3 :     U8_TRACE_BEGIN();
     159              : 
     160            3 :     universal_input_stream_t* result = &((*this_).input_stream);
     161              : 
     162            3 :     U8_TRACE_END();
     163            3 :     return result;
     164              : }
     165              : 
     166              : 
     167              : /*
     168              : Copyright 2021-2025 Andreas Warnke
     169              : 
     170              : Licensed under the Apache License, Version 2.0 (the "License");
     171              : you may not use this file except in compliance with the License.
     172              : You may obtain a copy of the License at
     173              : 
     174              :     http://www.apache.org/licenses/LICENSE-2.0
     175              : 
     176              : Unless required by applicable law or agreed to in writing, software
     177              : distributed under the License is distributed on an "AS IS" BASIS,
     178              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     179              : See the License for the specific language governing permissions and
     180              : limitations under the License.
     181              : */
        

Generated by: LCOV version 2.0-1