LCOV - code coverage report
Current view: top level - u8stream/source/u8stream - universal_memory_output_stream.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.57.0_covts Lines: 87 87 100.0 %
Date: 2024-04-07 11:14:42 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* File: universal_memory_output_stream.c; Copyright and License: see below */
       2             : 
       3             : #include "u8stream/universal_memory_output_stream.h"
       4             : #include "u8stream/universal_output_stream_if.h"
       5             : #include "utf8stringbuf/utf8stringview.h"
       6             : #include "u8/u8_trace.h"
       7             : #include "u8/u8_log.h"
       8             : #include <string.h>
       9             : #include <assert.h>
      10             : 
      11             : /* the vmt implementing the interface */
      12             : static const universal_output_stream_if_t universal_memory_output_stream_private_if
      13             :     = {
      14             :         .write = (u8_error_t (*)(universal_output_stream_impl_t*, const void*, size_t)) &universal_memory_output_stream_write,
      15             :         .flush = (u8_error_t (*)(universal_output_stream_impl_t*)) &universal_memory_output_stream_flush
      16             :     };
      17             : 
      18        1452 : void universal_memory_output_stream_init ( universal_memory_output_stream_t *this_,
      19             :                                            void* mem_buf_start,
      20             :                                            size_t mem_buf_size,
      21             :                                            universal_memory_output_stream_0term_t mode )
      22             : {
      23        1452 :     U8_TRACE_BEGIN();
      24        1452 :     assert( mem_buf_start != NULL );
      25             : 
      26        1452 :     (*this_).mem_buf_start = mem_buf_start;
      27        1452 :     (*this_).mem_buf_size = mem_buf_size;
      28        1452 :     (*this_).mem_buf_filled = 0;
      29        1452 :     (*this_).mode = mode;
      30        1452 :     universal_output_stream_private_init( &((*this_).output_stream), &universal_memory_output_stream_private_if, this_ );
      31             : 
      32        1452 :     U8_TRACE_END();
      33        1452 : }
      34             : 
      35        1449 : u8_error_t universal_memory_output_stream_destroy( universal_memory_output_stream_t *this_ )
      36             : {
      37        1449 :     U8_TRACE_BEGIN();
      38             : 
      39        1449 :     const u8_error_t err = universal_memory_output_stream_flush( this_ );
      40             : 
      41        1449 :     (*this_).mem_buf_start = NULL;
      42        1449 :     (*this_).mem_buf_size = 0;
      43        1449 :     (*this_).mem_buf_filled = 0;
      44        1449 :     universal_output_stream_private_destroy( &((*this_).output_stream) );
      45             : 
      46        1449 :     U8_TRACE_END_ERR(err);
      47        1449 :     return err;
      48             : }
      49             : 
      50         825 : u8_error_t universal_memory_output_stream_reset ( universal_memory_output_stream_t *this_ )
      51             : {
      52         825 :     U8_TRACE_BEGIN();
      53         825 :     assert( (*this_).mem_buf_start != NULL );
      54         825 :     const u8_error_t err = U8_ERROR_NONE;
      55             : 
      56         825 :     (*this_).mem_buf_filled = 0;
      57             : 
      58         825 :     U8_TRACE_END_ERR(err);
      59         825 :     return err;
      60             : }
      61             : 
      62        5848 : u8_error_t universal_memory_output_stream_write ( universal_memory_output_stream_t *this_, const void *start, size_t length )
      63             : {
      64             :     /*U8_TRACE_BEGIN();*/
      65        5848 :     assert( start != NULL );
      66        5848 :     assert( (*this_).mem_buf_start != NULL );
      67        5848 :     u8_error_t err = U8_ERROR_NONE;
      68             : 
      69        5848 :     const size_t space_left = ( (*this_).mem_buf_size - (*this_).mem_buf_filled );
      70        5848 :     char *const buf_first_free = &(  (*(  (char(*)[])(*this_).mem_buf_start  ))[(*this_).mem_buf_filled]  );
      71        5848 :     if ( length <= space_left )
      72             :     {
      73        5803 :         memcpy( buf_first_free, start, length );
      74        5803 :         (*this_).mem_buf_filled += length;
      75             :     }
      76             :     else
      77             :     {
      78          45 :         U8_TRACE_BEGIN();
      79          45 :         memcpy( buf_first_free, start, space_left );
      80          45 :         (*this_).mem_buf_filled += space_left;
      81          45 :         U8_TRACE_INFO_INT( "not all bytes could be written. missing:", length-space_left );
      82          45 :         err = U8_ERROR_AT_FILE_WRITE;
      83          45 :         U8_TRACE_END_ERR(err);
      84             :     }
      85             : 
      86             :     /*U8_TRACE_END_ERR(err);*/
      87        5848 :     return err;
      88             : }
      89             : 
      90        7447 : u8_error_t universal_memory_output_stream_flush( universal_memory_output_stream_t *this_ )
      91             : {
      92        7447 :     U8_TRACE_BEGIN();
      93        7447 :     assert( (*this_).mem_buf_start != NULL );
      94        7447 :     u8_error_t err = U8_ERROR_NONE;
      95             : 
      96        7447 :     switch( (*this_).mode )
      97             :     {
      98           2 :         case UNIVERSAL_MEMORY_OUTPUT_STREAM_0TERM_BYTE:
      99             :         {
     100           2 :             err = universal_memory_output_stream_private_write_0term( this_, false );
     101             :         }
     102           2 :         break;
     103             : 
     104        7444 :         case UNIVERSAL_MEMORY_OUTPUT_STREAM_0TERM_UTF8:
     105             :         {
     106        7444 :             err = universal_memory_output_stream_private_write_0term( this_, true );
     107             :         }
     108        7444 :         break;
     109             : 
     110           1 :         default:
     111             :         case UNIVERSAL_MEMORY_OUTPUT_STREAM_0TERM_NONE:
     112             :         {
     113             :             /* no 0term to be appended */
     114             :         }
     115           1 :         break;
     116             :     }
     117             : 
     118        7447 :     U8_TRACE_END_ERR(err);
     119        7447 :     return err;
     120             : }
     121             : 
     122        7446 : u8_error_t universal_memory_output_stream_private_write_0term ( universal_memory_output_stream_t *this_, bool utf8_mode )
     123             : {
     124        7446 :     U8_TRACE_BEGIN();
     125        7446 :     assert( (*this_).mem_buf_start != NULL );
     126        7446 :     u8_error_t err = U8_ERROR_NONE;
     127             : 
     128        7446 :     if ( (*this_).mem_buf_size == 0 )
     129             :     {
     130           1 :         U8_LOG_ERROR( "buffer size is 0; buffer is not terminated by zero." );
     131           1 :         err = U8_ERROR_CONFIG_OUT_OF_RANGE;
     132             :     }
     133        7445 :     else if ( (*this_).mem_buf_filled < (*this_).mem_buf_size )
     134             :     {
     135             :         /* add a terminating zero at position (*this_).mem_buf_filled, */
     136             :         /* but do not increase the mem_buf_filled because more bytes may be written ... */
     137        7361 :         char *const term_char = &(  (*(  (char(*)[])(*this_).mem_buf_start  ))[(*this_).mem_buf_filled]  );
     138        7361 :         *term_char = '\0';
     139             :     }
     140             :     else
     141             :     {
     142          84 :         if ( utf8_mode )
     143             :         {
     144             :             /* use a utf8stringview_t to determine the end-position of the last full unicode codepoint: */
     145             :             utf8stringview_t view_on_buf;
     146          83 :             const utf8error_t cut = utf8stringview_init( &view_on_buf, (*this_).mem_buf_start, (*this_).mem_buf_size-1 );
     147          83 :             char *const last_char
     148          83 :                 = &(  (*(  (char(*)[])utf8stringview_get_start(&view_on_buf)  ))[utf8stringview_get_length(&view_on_buf)]  );
     149          83 :             *last_char = '\0';
     150          83 :             utf8stringview_destroy( &view_on_buf );
     151          83 :             if ( cut == UTF8ERROR_SUCCESS )
     152             :             {
     153          81 :                 U8_TRACE_INFO( "last byte overwritten by terminating zero" );
     154             :             }
     155             :             else
     156             :             {
     157           2 :                 U8_TRACE_INFO( "multiple last bytes dropped by terminating zero" );
     158             :             }
     159             :         }
     160             :         else
     161             :         {
     162           1 :             char *const last_char = &(  (*(  (char(*)[])(*this_).mem_buf_start  ))[(*this_).mem_buf_size - 1]  );
     163           1 :             *last_char = '\0';
     164           1 :             U8_TRACE_INFO( "last byte overwritten by terminating zero" );
     165             :         }
     166          84 :         err = U8_ERROR_AT_FILE_WRITE;
     167             :     }
     168             : 
     169             : 
     170        7446 :     U8_TRACE_END_ERR(err);
     171        7446 :     return err;
     172             : }
     173             : 
     174        1448 : universal_output_stream_t* universal_memory_output_stream_get_output_stream( universal_memory_output_stream_t *this_ )
     175             : {
     176        1448 :     U8_TRACE_BEGIN();
     177             : 
     178        1448 :     universal_output_stream_t* result = &((*this_).output_stream);
     179             : 
     180        1448 :     U8_TRACE_END();
     181        1448 :     return result;
     182             : }
     183             : 
     184             : 
     185             : /*
     186             : Copyright 2020-2024 Andreas Warnke
     187             : 
     188             : Licensed under the Apache License, Version 2.0 (the "License");
     189             : you may not use this file except in compliance with the License.
     190             : You may obtain a copy of the License at
     191             : 
     192             :     http://www.apache.org/licenses/LICENSE-2.0
     193             : 
     194             : Unless required by applicable law or agreed to in writing, software
     195             : distributed under the License is distributed on an "AS IS" BASIS,
     196             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     197             : See the License for the specific language governing permissions and
     198             : limitations under the License.
     199             : */

Generated by: LCOV version 1.16