LCOV - code coverage report
Current view: top level - u8stream/include/utf8stream - utf8stream_writer.inl (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 100.0 % 66 66
Test Date: 2025-05-01 10:10:14 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /* File: utf8stream_writer.c; Copyright and License: see below */
       2              : 
       3              : #include "u8/u8_trace.h"
       4              : #include <string.h>
       5              : #include <inttypes.h>
       6              : #include <assert.h>
       7              : 
       8          188 : static inline void utf8stream_writer_init ( utf8stream_writer_t *this_, universal_output_stream_t* out_stream )
       9              : {
      10          188 :     assert( out_stream != NULL );
      11          188 :     (*this_).output_stream = out_stream;
      12          188 :     (*this_).buf_fill = 0;
      13          188 : }
      14              : 
      15          188 : static inline u8_error_t utf8stream_writer_destroy ( utf8stream_writer_t *this_ )
      16              : {
      17          188 :     assert( (*this_).output_stream != NULL );
      18              : 
      19          188 :     const u8_error_t err = utf8stream_writer_flush( this_ );
      20          188 :     (*this_).output_stream = NULL;
      21              : 
      22          188 :     return err;
      23              : }
      24              : 
      25        31867 : static inline u8_error_t utf8stream_writer_write_str ( utf8stream_writer_t *this_, const void *utf8_string )
      26              : {
      27        31867 :     assert( (*this_).output_stream != NULL );
      28        31867 :     assert( utf8_string != NULL );
      29              : 
      30        31867 :     utf8stringview_t view = UTF8STRINGVIEW_STR( utf8_string );
      31        31867 :     const u8_error_t err = utf8stream_writer_write_view( this_, &view );
      32              : 
      33        31867 :     return err;
      34              : }
      35              : 
      36         6267 : static inline u8_error_t utf8stream_writer_write_int ( utf8stream_writer_t *this_, const int64_t number )
      37              : {
      38         6267 :     assert( (*this_).output_stream != NULL );
      39              : 
      40              :     char number_str[21]; /* this is sufficient for signed 64 bit integers: -9223372036854775806 */
      41              :     /* Note: snprintf is not available on every OS */
      42         6267 :     sprintf( number_str, "%" PRIi64, number );
      43              : 
      44         6267 :     utf8stringview_t view = UTF8STRINGVIEW_STR( number_str );
      45         6267 :     const u8_error_t err = utf8stream_writer_write_view( this_, &view );
      46              : 
      47         6267 :     return err;
      48              : }
      49              : 
      50            1 : static inline u8_error_t utf8stream_writer_write_hex ( utf8stream_writer_t *this_, const int64_t number )
      51              : {
      52            1 :     assert( (*this_).output_stream != NULL );
      53              : 
      54              :     char number_str[17]; /* this is sufficient for 64 bit integers */
      55              :     /* Note: snprintf is not available on every OS */
      56            1 :     sprintf( number_str, "%" PRIx64, number );
      57              : 
      58            1 :     utf8stringview_t view = UTF8STRINGVIEW_STR( number_str );
      59            1 :     const u8_error_t err = utf8stream_writer_write_view( this_, &view );
      60              : 
      61            1 :     return err;
      62              : }
      63              : 
      64         3841 : static inline utf8error_t utf8stream_writer_write_char( utf8stream_writer_t *this_, const uint32_t codepoint )
      65              : {
      66         3841 :     assert( (*this_).output_stream != NULL );
      67              : 
      68         3841 :     const utf8codepoint_t cp = utf8codepoint( codepoint );
      69         3841 :     const utf8codepointseq_t mem_buf = utf8codepoint_get_utf8( &cp );
      70         3841 :     const unsigned int mem_len = utf8codepoint_get_length( &cp );
      71         3841 :     assert( mem_len <= sizeof(utf8codepointseq_t) );
      72              : 
      73         3841 :     utf8stringview_t view = UTF8STRINGVIEW( (const char*) &mem_buf, mem_len );
      74         3841 :     const u8_error_t err = utf8stream_writer_write_view( this_, &view );
      75              : 
      76         3841 :     return err;
      77              : }
      78              : 
      79        42029 : static inline u8_error_t utf8stream_writer_write_view ( utf8stream_writer_t *this_, const utf8stringview_t *utf8_view )
      80              : {
      81        42029 :     assert( (*this_).output_stream != NULL );
      82        42029 :     assert( (*this_).buf_fill <= sizeof( (*this_).buffer ) );
      83              :     assert( UTF8STREAM_WRITER_MAX_BUF == sizeof( (*this_).buffer ) );
      84        42029 :     assert( utf8_view != NULL );
      85        42029 :     const char *start = utf8stringview_get_start( utf8_view );
      86        42029 :     const size_t length = utf8stringview_get_length( utf8_view );
      87        42029 :     u8_error_t err = U8_ERROR_NONE;
      88              : 
      89              :     /* is there buffer free? */
      90        42029 :     if ( length <= ((size_t)UTF8STREAM_WRITER_MAX_BUF) - (*this_).buf_fill )  /* all possible constants are on the right side for compiler optimizations */
      91              :     {
      92              :         /* store to buffer */
      93              : #if __GNUC__ >= 8
      94              : #pragma GCC diagnostic push
      95              : #pragma GCC diagnostic ignored "-Warray-bounds"
      96              : #endif
      97        40109 :         memcpy( &((*this_).buffer[(*this_).buf_fill]), start, length );
      98              : #if __GNUC__ >= 8
      99              : #pragma GCC diagnostic pop
     100              : #endif
     101        40109 :         (*this_).buf_fill += length;
     102              :     }
     103              :     else
     104              :     {
     105              :         /* flush the buffer */
     106         1920 :         if ( (*this_).buf_fill > 0 )
     107              :         {
     108          452 :             err |= universal_output_stream_write( (*this_).output_stream, &((*this_).buffer), (*this_).buf_fill );
     109          452 :             (*this_).buf_fill = 0;
     110              :         }
     111              : 
     112              :         /* is there enough buffer free now? */
     113         1920 :         if ( length < UTF8STREAM_WRITER_MAX_BUF )
     114              :         {
     115              :             /* store to buffer */
     116          358 :             memcpy( &((*this_).buffer), start, length );
     117          358 :             (*this_).buf_fill = length;
     118              :         }
     119              :         else
     120              :         {
     121              :             /* write immediate */
     122         1562 :             err |= universal_output_stream_write( (*this_).output_stream, start, length );
     123              :         }
     124              :     }
     125              : 
     126        42029 :     return err;
     127              : }
     128              : 
     129        12871 : static inline u8_error_t utf8stream_writer_flush ( utf8stream_writer_t *this_ )
     130              : {
     131        12871 :     U8_TRACE_BEGIN();
     132        12871 :     assert( (*this_).output_stream != NULL );
     133        12871 :     assert( (*this_).buf_fill <= sizeof( (*this_).buffer ) );
     134        12871 :     u8_error_t err = U8_ERROR_NONE;
     135              : 
     136        12871 :     if ( (*this_).buf_fill > 0 )
     137              :     {
     138        11150 :         err |= universal_output_stream_write( (*this_).output_stream, &((*this_).buffer), (*this_).buf_fill );
     139        11150 :         (*this_).buf_fill = 0;
     140              :     }
     141              : 
     142        12871 :     err |= universal_output_stream_flush( (*this_).output_stream );
     143              : 
     144        12871 :     U8_TRACE_END_ERR( err );
     145        12871 :     return err;
     146              : }
     147              : 
     148              : 
     149              : /*
     150              : Copyright 2021-2025 Andreas Warnke
     151              : 
     152              : Licensed under the Apache License, Version 2.0 (the "License");
     153              : you may not use this file except in compliance with the License.
     154              : You may obtain a copy of the License at
     155              : 
     156              :     http://www.apache.org/licenses/LICENSE-2.0
     157              : 
     158              : Unless required by applicable law or agreed to in writing, software
     159              : distributed under the License is distributed on an "AS IS" BASIS,
     160              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     161              : See the License for the specific language governing permissions and
     162              : limitations under the License.
     163              : */
        

Generated by: LCOV version 2.0-1