Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "stream.h"
15 : #include "stream_internal.h"
16 :
17 :
18 : void
19 211145 : buffer_init(buffer *restrict b, char *restrict buf, size_t size)
20 : {
21 211145 : if (b == NULL || buf == NULL)
22 : return;
23 211145 : *b = (buffer) {
24 : .pos = 0,
25 : .buf = buf,
26 : .len = size,
27 : };
28 : }
29 :
30 : buffer *
31 543 : buffer_create(size_t size)
32 : {
33 543 : buffer *b;
34 :
35 543 : if ((b = malloc(sizeof(*b))) == NULL)
36 : return NULL;
37 543 : *b = (buffer) {
38 543 : .buf = malloc(size),
39 : .len = size,
40 : };
41 543 : if (b->buf == NULL) {
42 0 : free(b);
43 0 : return NULL;
44 : }
45 : return b;
46 : }
47 :
48 : char *
49 229 : buffer_get_buf(buffer *b)
50 : {
51 229 : char *r;
52 :
53 229 : if (b == NULL)
54 : return NULL;
55 229 : if (b->pos == b->len) {
56 0 : if ((r = realloc(b->buf, b->len + 1)) == NULL) {
57 : /* keep b->buf in tact */
58 : return NULL;
59 : }
60 0 : b->buf = r;
61 : }
62 229 : r = b->buf;
63 229 : r[b->pos] = '\0';
64 229 : b->buf = malloc(b->len);
65 229 : if (b->buf == NULL) {
66 : /* restore b->buf */
67 0 : b->buf = r;
68 0 : return NULL;
69 : }
70 229 : b->pos = 0;
71 229 : return r;
72 : }
73 :
74 : void
75 211688 : buffer_destroy(buffer *b)
76 : {
77 211688 : if (b == NULL)
78 : return;
79 211688 : if (b->buf)
80 211688 : free(b->buf);
81 211688 : free(b);
82 : }
83 :
84 : buffer *
85 0 : mnstr_get_buffer(stream *s)
86 : {
87 0 : if (s == NULL)
88 : return NULL;
89 0 : buffer *b = (buffer *) s->stream_data.p;
90 0 : if (b == NULL)
91 : return NULL;
92 0 : if (!s->readonly) {
93 : /* switching from write mode to read mode */
94 0 : s->readonly = true;
95 0 : b->len = b->pos;
96 : }
97 0 : b->pos = 0;
98 0 : return b;
99 : }
100 :
101 : static ssize_t
102 211145 : buffer_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
103 : {
104 211145 : size_t size = elmsize * cnt;
105 211145 : buffer *b;
106 :
107 211145 : b = (buffer *) s->stream_data.p;
108 211145 : assert(b);
109 211145 : if (b == NULL)
110 : return -1;
111 211145 : if (size != 0) {
112 211145 : if (size + b->pos > b->len)
113 0 : size = b->len - b->pos;
114 211145 : memcpy(buf, b->buf + b->pos, size);
115 211145 : b->pos += size;
116 211145 : return (ssize_t) (size / elmsize);
117 : }
118 0 : s->eof |= b->pos == b->len;
119 0 : return 0;
120 : }
121 :
122 : static ssize_t
123 48838 : buffer_write(stream *restrict s, const void *restrict buf, size_t elmsize, size_t cnt)
124 : {
125 48838 : size_t size = elmsize * cnt;
126 48838 : buffer *b;
127 :
128 48838 : b = (buffer *) s->stream_data.p;
129 48838 : assert(b);
130 48838 : if (b == NULL) {
131 : mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer already deallocated");
132 : return -1;
133 : }
134 48838 : if (b->pos + size > b->len) {
135 15 : char *p;
136 15 : size_t ns = b->pos + size + 8192;
137 :
138 15 : if ((p = realloc(b->buf, ns)) == NULL) {
139 0 : mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer reallocation failed");
140 0 : return -1;
141 : }
142 15 : b->buf = p;
143 15 : b->len = ns;
144 : }
145 48838 : memcpy(b->buf + b->pos, buf, size);
146 48838 : b->pos += size;
147 48838 : return (ssize_t) cnt;
148 : }
149 :
150 : static void
151 211688 : buffer_close(stream *s)
152 : {
153 211688 : (void) s;
154 211688 : }
155 :
156 : static int
157 0 : buffer_flush(stream *s, mnstr_flush_level flush_level)
158 : {
159 0 : buffer *b;
160 :
161 0 : b = (buffer *) s->stream_data.p;
162 0 : assert(b);
163 0 : if (b == NULL)
164 : return -1;
165 0 : b->pos = 0;
166 0 : (void) flush_level;
167 0 : return 0;
168 : }
169 :
170 : static void
171 0 : buffer_destroy_stream(stream *s)
172 : {
173 0 : buffer_destroy(s->stream_data.p);
174 0 : destroy_stream(s);
175 0 : }
176 :
177 : stream *
178 211145 : buffer_rastream(buffer *restrict b, const char *restrict name)
179 : {
180 211145 : stream *s;
181 :
182 211145 : if (b == NULL || name == NULL) {
183 0 : mnstr_set_open_error(name, 0, "no buffer or no name");
184 0 : return NULL;
185 : }
186 : #ifdef STREAM_DEBUG
187 : fprintf(stderr, "buffer_rastream %s\n", name);
188 : #endif
189 211145 : if ((s = create_stream(name)) == NULL)
190 : return NULL;
191 211145 : s->binary = false;
192 211145 : s->read = buffer_read;
193 211145 : s->write = buffer_write;
194 211145 : s->close = buffer_close;
195 211145 : s->flush = buffer_flush;
196 211145 : s->stream_data.p = (void *) b;
197 211145 : return s;
198 : }
199 :
200 : stream *
201 543 : buffer_wastream(buffer *restrict b, const char *restrict name)
202 : {
203 543 : stream *s;
204 :
205 543 : if (name == NULL) {
206 0 : mnstr_set_open_error(name, 0, "no name");
207 0 : return NULL;
208 : }
209 : #ifdef STREAM_DEBUG
210 : fprintf(stderr, "buffer_wastream %s\n", name);
211 : #endif
212 543 : if ((s = create_stream(name)) == NULL)
213 : return NULL;
214 543 : s->readonly = false;
215 543 : s->binary = false;
216 543 : s->read = buffer_read;
217 543 : s->write = buffer_write;
218 543 : s->close = buffer_close;
219 543 : s->flush = buffer_flush;
220 543 : if (b == NULL) {
221 0 : b = buffer_create(1 << 20);
222 0 : if (b == NULL) {
223 0 : destroy_stream(s);
224 0 : return NULL;
225 : }
226 0 : s->destroy = buffer_destroy_stream;
227 : }
228 543 : s->stream_data.p = (void *) b;
229 543 : return s;
230 : }
|