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-2026 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 : */
|