Line data Source code
1 : /* File: universal_buffer_output_stream.c; Copyright and License: see below */ 2 : 3 : #include "u8stream/universal_buffer_output_stream.h" 4 : #include "u8stream/universal_output_stream_if.h" 5 : #include "u8/u8_trace.h" 6 : #include "u8/u8_log.h" 7 : #include <string.h> 8 : #include <assert.h> 9 : 10 : /* the vmt implementing the interface */ 11 : static const universal_output_stream_if_t universal_buffer_output_stream_private_if 12 : = { 13 : .write = (u8_error_t (*)(universal_output_stream_impl_t*, const void*, size_t)) &universal_buffer_output_stream_write, 14 : .flush = (u8_error_t (*)(universal_output_stream_impl_t*)) &universal_buffer_output_stream_flush 15 : }; 16 : 17 2 : void universal_buffer_output_stream_init( universal_buffer_output_stream_t *this_, 18 : void* mem_buf_start, 19 : size_t mem_buf_size, 20 : universal_output_stream_t *sink ) 21 : { 22 2 : U8_TRACE_BEGIN(); 23 2 : assert( mem_buf_start != NULL ); 24 2 : assert( sink != NULL ); 25 : 26 2 : (*this_).sink = sink; 27 : 28 2 : (*this_).mem_buf_start = mem_buf_start; 29 2 : (*this_).mem_buf_size = mem_buf_size; 30 2 : (*this_).mem_buf_filled = 0; 31 2 : universal_output_stream_private_init( &((*this_).output_stream), &universal_buffer_output_stream_private_if, this_ ); 32 : 33 2 : U8_TRACE_END(); 34 2 : } 35 : 36 2 : u8_error_t universal_buffer_output_stream_destroy( universal_buffer_output_stream_t *this_ ) 37 : { 38 2 : U8_TRACE_BEGIN(); 39 2 : assert( (*this_).mem_buf_start != NULL ); 40 2 : assert( (*this_).sink != NULL ); 41 2 : u8_error_t err = U8_ERROR_NONE; 42 : 43 2 : err = universal_buffer_output_stream_flush( this_ ); 44 : 45 2 : (*this_).mem_buf_start = NULL; 46 2 : (*this_).mem_buf_size = 0; 47 2 : (*this_).mem_buf_filled = 0; 48 2 : universal_output_stream_private_destroy( &((*this_).output_stream) ); 49 : 50 2 : (*this_).sink = NULL; 51 : 52 2 : U8_TRACE_END_ERR(err); 53 2 : return err; 54 : } 55 : 56 7 : u8_error_t universal_buffer_output_stream_write ( universal_buffer_output_stream_t *this_, const void *start, size_t length ) 57 : { 58 : /*U8_TRACE_BEGIN();*/ 59 7 : assert( start != NULL ); 60 7 : assert( (*this_).mem_buf_start != NULL ); 61 7 : assert( (*this_).sink != NULL ); 62 7 : u8_error_t err = U8_ERROR_NONE; 63 : 64 7 : const size_t space_left = (*this_).mem_buf_size - (*this_).mem_buf_filled; 65 7 : char *const buf_first_free = &( (*( (char(*)[])(*this_).mem_buf_start ))[(*this_).mem_buf_filled] ); 66 7 : if ( length <= space_left ) 67 : { 68 : /* append all to buffer */ 69 3 : memcpy( buf_first_free, start, length ); 70 3 : (*this_).mem_buf_filled += length; 71 : } 72 : else 73 : { 74 : /* append to buffer till buffer is full */ 75 4 : memcpy( buf_first_free, start, space_left ); 76 4 : (*this_).mem_buf_filled += space_left; 77 4 : const size_t remaining_len = length - space_left; 78 4 : const void *remaining_start = &( (*( (char(*)[])start ))[space_left] ); 79 : 80 4 : err |= universal_buffer_output_stream_flush( this_ ); 81 : 82 4 : if ( remaining_len <= (*this_).mem_buf_size ) 83 : { 84 3 : memcpy( (*this_).mem_buf_start , remaining_start, remaining_len ); 85 3 : (*this_).mem_buf_filled = remaining_len; 86 : } 87 : else 88 : { 89 1 : err |= universal_output_stream_write( (*this_).sink, remaining_start, remaining_len ); 90 : } 91 : } 92 : 93 : /*U8_TRACE_END_ERR(err);*/ 94 7 : return err; 95 : } 96 : 97 7 : u8_error_t universal_buffer_output_stream_flush( universal_buffer_output_stream_t *this_ ) 98 : { 99 7 : U8_TRACE_BEGIN(); 100 7 : assert( (*this_).mem_buf_start != NULL ); 101 7 : assert( (*this_).sink != NULL ); 102 7 : u8_error_t err = U8_ERROR_NONE; 103 : 104 7 : if ( (*this_).mem_buf_filled > 0 ) 105 : { 106 7 : err |= universal_output_stream_write( (*this_).sink, (*this_).mem_buf_start, (*this_).mem_buf_filled ); 107 : } 108 7 : (*this_).mem_buf_filled = 0; 109 : 110 7 : U8_TRACE_END_ERR(err); 111 7 : return err; 112 : } 113 : 114 2 : universal_output_stream_t* universal_buffer_output_stream_get_output_stream( universal_buffer_output_stream_t *this_ ) 115 : { 116 2 : U8_TRACE_BEGIN(); 117 : 118 2 : universal_output_stream_t* result = &((*this_).output_stream); 119 : 120 2 : U8_TRACE_END(); 121 2 : return result; 122 : } 123 : 124 : 125 : /* 126 : Copyright 2021-2024 Andreas Warnke 127 : 128 : Licensed under the Apache License, Version 2.0 (the "License"); 129 : you may not use this file except in compliance with the License. 130 : You may obtain a copy of the License at 131 : 132 : http://www.apache.org/licenses/LICENSE-2.0 133 : 134 : Unless required by applicable law or agreed to in writing, software 135 : distributed under the License is distributed on an "AS IS" BASIS, 136 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137 : See the License for the specific language governing permissions and 138 : limitations under the License. 139 : */