Line data Source code
1 : /* File: universal_buffer_input_stream.c; Copyright and License: see below */ 2 : 3 : #include "u8stream/universal_buffer_input_stream.h" 4 : #include "u8stream/universal_input_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_input_stream_if_t universal_buffer_input_stream_private_if 12 : = { 13 : .read = (u8_error_t (*)(universal_input_stream_impl_t*, void*, size_t, size_t*)) &universal_buffer_input_stream_read, 14 : .reset = (u8_error_t (*)(universal_input_stream_impl_t*)) &universal_buffer_input_stream_reset 15 : }; 16 : 17 77 : void universal_buffer_input_stream_init( universal_buffer_input_stream_t *this_, 18 : void* mem_buf_start, 19 : size_t mem_buf_size, 20 : universal_input_stream_t *source ) 21 : { 22 77 : U8_TRACE_BEGIN(); 23 77 : assert( mem_buf_start != NULL ); 24 77 : assert( source != NULL ); 25 : 26 77 : (*this_).source = source; 27 : 28 77 : (*this_).mem_buf_start = mem_buf_start; 29 77 : (*this_).mem_buf_size = mem_buf_size; 30 77 : (*this_).mem_buf_fill = 0; 31 77 : (*this_).mem_buf_pos = 0; 32 77 : universal_input_stream_private_init( &((*this_).input_stream), &universal_buffer_input_stream_private_if, this_ ); 33 77 : (*this_).stream_pos_of_buf = 0; 34 : 35 77 : U8_TRACE_END(); 36 77 : } 37 : 38 77 : void universal_buffer_input_stream_destroy( universal_buffer_input_stream_t *this_ ) 39 : { 40 77 : U8_TRACE_BEGIN(); 41 77 : assert( (*this_).mem_buf_start != NULL ); 42 77 : assert( (*this_).source != NULL ); 43 : 44 77 : (*this_).mem_buf_start = NULL; 45 77 : (*this_).mem_buf_size = 0; 46 77 : (*this_).mem_buf_fill = 0; 47 77 : (*this_).mem_buf_pos = 0; 48 77 : universal_input_stream_private_destroy( &((*this_).input_stream) ); 49 77 : (*this_).stream_pos_of_buf = 0; 50 : 51 77 : (*this_).source = NULL; 52 : 53 77 : U8_TRACE_END(); 54 77 : } 55 : 56 1 : void universal_buffer_input_stream_reset ( universal_buffer_input_stream_t *this_ ) 57 : { 58 1 : U8_TRACE_BEGIN(); 59 1 : assert( (*this_).mem_buf_start != NULL ); 60 1 : assert( (*this_).source != NULL ); 61 : 62 1 : (*this_).mem_buf_pos = 0; 63 1 : (*this_).mem_buf_fill = 0; 64 1 : (*this_).stream_pos_of_buf = 0; 65 : 66 1 : U8_TRACE_END(); 67 1 : } 68 : 69 7 : u8_error_t universal_buffer_input_stream_read ( universal_buffer_input_stream_t *this_, void *out_buffer, size_t max_size, size_t *out_length ) 70 : { 71 : /*U8_TRACE_BEGIN();*/ 72 7 : assert( out_buffer != NULL ); 73 7 : assert( max_size != 0 ); 74 7 : assert( out_length != NULL ); 75 7 : assert( (*this_).mem_buf_start != NULL ); 76 7 : assert( (*this_).source != NULL ); 77 7 : u8_error_t err = U8_ERROR_NONE; 78 : 79 7 : const size_t buf_available1 = (*this_).mem_buf_fill - (*this_).mem_buf_pos; 80 7 : char *const buf_first_read = &( (*( (char(*)[])(*this_).mem_buf_start ))[(*this_).mem_buf_pos] ); 81 7 : if ( max_size <= buf_available1 ) 82 : { 83 : /* read all from buffer */ 84 1 : memcpy( out_buffer, buf_first_read, max_size ); 85 1 : (*this_).mem_buf_pos += max_size; 86 1 : *out_length = max_size; 87 : } 88 : else 89 : { 90 : /* read from buffer till buffer is empty */ 91 6 : memcpy( out_buffer, buf_first_read, buf_available1 ); 92 6 : (*this_).stream_pos_of_buf += (*this_).mem_buf_fill; 93 6 : (*this_).mem_buf_pos = 0; 94 6 : (*this_).mem_buf_fill = 0; 95 6 : const size_t remaining_len = max_size - buf_available1; 96 6 : void *const remaining_start = &( (*( (char(*)[])out_buffer ))[buf_available1] ); 97 : 98 6 : if ( remaining_len < (*this_).mem_buf_size ) 99 : { 100 3 : err |= universal_input_stream_read( (*this_).source, (*this_).mem_buf_start, (*this_).mem_buf_size, &((*this_).mem_buf_fill) ); 101 : 102 3 : const size_t buf_available2 = ( (*this_).mem_buf_fill < remaining_len )?( (*this_).mem_buf_fill ):( remaining_len ); 103 : 104 3 : memcpy( remaining_start, (*this_).mem_buf_start, buf_available2 ); 105 3 : (*this_).mem_buf_pos = buf_available2; 106 3 : *out_length = buf_available1 + buf_available2; 107 : } 108 : else 109 : { 110 3 : size_t remaining_actual = 0; 111 3 : err |= universal_input_stream_read( (*this_).source, remaining_start, remaining_len, &remaining_actual ); 112 3 : *out_length = buf_available1 + remaining_actual; 113 3 : (*this_).stream_pos_of_buf += remaining_actual; 114 : } 115 : } 116 : 117 : /*U8_TRACE_END_ERR(err);*/ 118 7 : return err; 119 : } 120 : 121 2 : universal_input_stream_t* universal_buffer_input_stream_get_input_stream( universal_buffer_input_stream_t *this_ ) 122 : { 123 2 : U8_TRACE_BEGIN(); 124 : 125 2 : universal_input_stream_t* result = &((*this_).input_stream); 126 : 127 2 : U8_TRACE_END(); 128 2 : return result; 129 : } 130 : 131 : 132 : /* 133 : Copyright 2021-2024 Andreas Warnke 134 : 135 : Licensed under the Apache License, Version 2.0 (the "License"); 136 : you may not use this file except in compliance with the License. 137 : You may obtain a copy of the License at 138 : 139 : http://www.apache.org/licenses/LICENSE-2.0 140 : 141 : Unless required by applicable law or agreed to in writing, software 142 : distributed under the License is distributed on an "AS IS" BASIS, 143 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144 : See the License for the specific language governing permissions and 145 : limitations under the License. 146 : */