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 429 : static inline void utf8stream_writer_init ( utf8stream_writer_t *this_, universal_output_stream_t* out_stream ) 9 : { 10 429 : assert( out_stream != NULL ); 11 429 : (*this_).output_stream = out_stream; 12 429 : (*this_).buf_fill = 0; 13 429 : } 14 : 15 429 : static inline u8_error_t utf8stream_writer_destroy ( utf8stream_writer_t *this_ ) 16 : { 17 429 : assert( (*this_).output_stream != NULL ); 18 : 19 429 : const u8_error_t err = utf8stream_writer_flush( this_ ); 20 429 : (*this_).output_stream = NULL; 21 : 22 429 : return err; 23 : } 24 : 25 11645 : static inline u8_error_t utf8stream_writer_write_str ( utf8stream_writer_t *this_, const void *utf8_string ) 26 : { 27 11645 : assert( (*this_).output_stream != NULL ); 28 11645 : assert( utf8_string != NULL ); 29 : 30 11645 : utf8stringview_t view = UTF8STRINGVIEW_STR( utf8_string ); 31 11645 : const u8_error_t err = utf8stream_writer_write_view( this_, &view ); 32 : 33 11645 : return err; 34 : } 35 : 36 2742 : static inline u8_error_t utf8stream_writer_write_int ( utf8stream_writer_t *this_, const int64_t number ) 37 : { 38 2742 : 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 2742 : sprintf( number_str, "%" PRIi64, number ); 43 : 44 2742 : utf8stringview_t view = UTF8STRINGVIEW_STR( number_str ); 45 2742 : const u8_error_t err = utf8stream_writer_write_view( this_, &view ); 46 : 47 2742 : 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 18282 : static inline u8_error_t utf8stream_writer_write_view ( utf8stream_writer_t *this_, const utf8stringview_t *utf8_view ) 80 : { 81 18282 : assert( (*this_).output_stream != NULL ); 82 18282 : assert( (*this_).buf_fill <= sizeof( (*this_).buffer ) ); 83 : assert( UTF8STREAM_WRITER_MAX_BUF == sizeof( (*this_).buffer ) ); 84 18282 : assert( utf8_view != NULL ); 85 18282 : const char *start = utf8stringview_get_start( utf8_view ); 86 18282 : const size_t length = utf8stringview_get_length( utf8_view ); 87 18282 : u8_error_t err = U8_ERROR_NONE; 88 : 89 : /* is there buffer free? */ 90 18282 : if ( length <= UTF8STREAM_WRITER_MAX_BUF - (*this_).buf_fill ) /* all possible constants are on the right side for compiler optimizations */ 91 : { 92 : /* store to buffer */ 93 17346 : memcpy( &((*this_).buffer[(*this_).buf_fill]), start, length ); 94 17346 : (*this_).buf_fill += length; 95 : } 96 : else 97 : { 98 : /* flush the buffer */ 99 936 : if ( (*this_).buf_fill > 0 ) 100 : { 101 450 : err |= universal_output_stream_write( (*this_).output_stream, &((*this_).buffer), (*this_).buf_fill ); 102 450 : (*this_).buf_fill = 0; 103 : } 104 : 105 : /* is there enough buffer free now? */ 106 936 : if ( length < UTF8STREAM_WRITER_MAX_BUF ) 107 : { 108 : /* store to buffer */ 109 357 : memcpy( &((*this_).buffer), start, length ); 110 357 : (*this_).buf_fill = length; 111 : } 112 : else 113 : { 114 : /* write immediate */ 115 579 : err |= universal_output_stream_write( (*this_).output_stream, start, length ); 116 : } 117 : } 118 : 119 18282 : return err; 120 : } 121 : 122 4944 : static inline u8_error_t utf8stream_writer_flush ( utf8stream_writer_t *this_ ) 123 : { 124 4944 : assert( (*this_).output_stream != NULL ); 125 4944 : assert( (*this_).buf_fill <= sizeof( (*this_).buffer ) ); 126 4944 : u8_error_t err = U8_ERROR_NONE; 127 : 128 4944 : if ( (*this_).buf_fill > 0 ) 129 : { 130 4071 : err |= universal_output_stream_write( (*this_).output_stream, &((*this_).buffer), (*this_).buf_fill ); 131 4071 : (*this_).buf_fill = 0; 132 : } 133 : 134 4944 : err |= universal_output_stream_flush( (*this_).output_stream ); 135 : 136 4944 : return err; 137 : } 138 : 139 : 140 : /* 141 : Copyright 2021-2024 Andreas Warnke 142 : 143 : Licensed under the Apache License, Version 2.0 (the "License"); 144 : you may not use this file except in compliance with the License. 145 : You may obtain a copy of the License at 146 : 147 : http://www.apache.org/licenses/LICENSE-2.0 148 : 149 : Unless required by applicable law or agreed to in writing, software 150 : distributed under the License is distributed on an "AS IS" BASIS, 151 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 152 : See the License for the specific language governing permissions and 153 : limitations under the License. 154 : */