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 80 : 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 80 : U8_TRACE_BEGIN();
23 80 : assert( mem_buf_start != NULL );
24 80 : assert( source != NULL );
25 :
26 80 : (*this_).source = source;
27 :
28 80 : (*this_).mem_buf_start = mem_buf_start;
29 80 : (*this_).mem_buf_size = mem_buf_size;
30 80 : (*this_).mem_buf_fill = 0;
31 80 : (*this_).mem_buf_pos = 0;
32 80 : universal_input_stream_private_init( &((*this_).input_stream), &universal_buffer_input_stream_private_if, this_ );
33 80 : (*this_).stream_pos_of_buf = 0;
34 :
35 80 : U8_TRACE_END();
36 80 : }
37 :
38 80 : void universal_buffer_input_stream_destroy( universal_buffer_input_stream_t *this_ )
39 : {
40 80 : U8_TRACE_BEGIN();
41 80 : assert( (*this_).mem_buf_start != NULL );
42 80 : assert( (*this_).source != NULL );
43 :
44 80 : (*this_).mem_buf_start = NULL;
45 80 : (*this_).mem_buf_size = 0;
46 80 : (*this_).mem_buf_fill = 0;
47 80 : (*this_).mem_buf_pos = 0;
48 80 : universal_input_stream_private_destroy( &((*this_).input_stream) );
49 80 : (*this_).stream_pos_of_buf = 0;
50 :
51 80 : (*this_).source = NULL;
52 :
53 80 : U8_TRACE_END();
54 80 : }
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-2025 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 : */
|