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 202685 : buffer_init(buffer *restrict b, char *restrict buf, size_t size)
20 : {
21 202685 : if (b == NULL || buf == NULL)
22 : return;
23 202685 : b->pos = 0;
24 202685 : b->buf = buf;
25 202685 : b->len = size;
26 : }
27 :
28 : buffer *
29 452 : buffer_create(size_t size)
30 : {
31 452 : buffer *b;
32 :
33 452 : if ((b = malloc(sizeof(*b))) == NULL)
34 : return NULL;
35 452 : *b = (buffer) {
36 452 : .buf = malloc(size),
37 : .len = size,
38 : };
39 452 : if (b->buf == NULL) {
40 0 : free(b);
41 0 : return NULL;
42 : }
43 : return b;
44 : }
45 :
46 : char *
47 186 : buffer_get_buf(buffer *b)
48 : {
49 186 : char *r;
50 :
51 186 : if (b == NULL)
52 : return NULL;
53 186 : if (b->pos == b->len) {
54 0 : if ((r = realloc(b->buf, b->len + 1)) == NULL) {
55 : /* keep b->buf in tact */
56 : return NULL;
57 : }
58 0 : b->buf = r;
59 : }
60 186 : r = b->buf;
61 186 : r[b->pos] = '\0';
62 186 : b->buf = malloc(b->len);
63 186 : if (b->buf == NULL) {
64 : /* restore b->buf */
65 0 : b->buf = r;
66 0 : return NULL;
67 : }
68 186 : b->pos = 0;
69 186 : return r;
70 : }
71 :
72 : void
73 203137 : buffer_destroy(buffer *b)
74 : {
75 203137 : if (b == NULL)
76 : return;
77 203137 : if (b->buf)
78 203137 : free(b->buf);
79 203137 : free(b);
80 : }
81 :
82 : buffer *
83 0 : mnstr_get_buffer(stream *s)
84 : {
85 0 : if (s == NULL)
86 : return NULL;
87 0 : buffer *b = (buffer *) s->stream_data.p;
88 0 : if (b == NULL)
89 : return NULL;
90 0 : if (!s->readonly) {
91 : /* switching from write mode to read mode */
92 0 : s->readonly = true;
93 0 : b->len = b->pos;
94 : }
95 0 : b->pos = 0;
96 0 : return b;
97 : }
98 :
99 : static ssize_t
100 202685 : buffer_read(stream *restrict s, void *restrict buf, size_t elmsize, size_t cnt)
101 : {
102 202685 : size_t size = elmsize * cnt;
103 202685 : buffer *b;
104 :
105 202685 : b = (buffer *) s->stream_data.p;
106 202685 : assert(b);
107 202685 : if (b == NULL)
108 : return -1;
109 202685 : if (size != 0) {
110 202685 : if (size + b->pos > b->len)
111 0 : size = b->len - b->pos;
112 202685 : memcpy(buf, b->buf + b->pos, size);
113 202685 : b->pos += size;
114 202685 : return (ssize_t) (size / elmsize);
115 : }
116 0 : s->eof |= b->pos == b->len;
117 0 : return 0;
118 : }
119 :
120 : static ssize_t
121 38626 : buffer_write(stream *restrict s, const void *restrict buf, size_t elmsize, size_t cnt)
122 : {
123 38626 : size_t size = elmsize * cnt;
124 38626 : buffer *b;
125 :
126 38626 : b = (buffer *) s->stream_data.p;
127 38626 : assert(b);
128 38626 : if (b == NULL) {
129 : mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer already deallocated");
130 : return -1;
131 : }
132 38626 : if (b->pos + size > b->len) {
133 15 : char *p;
134 15 : size_t ns = b->pos + size + 8192;
135 :
136 15 : if ((p = realloc(b->buf, ns)) == NULL) {
137 0 : mnstr_set_error(s, MNSTR_WRITE_ERROR, "buffer reallocation failed");
138 0 : return -1;
139 : }
140 15 : b->buf = p;
141 15 : b->len = ns;
142 : }
143 38626 : memcpy(b->buf + b->pos, buf, size);
144 38626 : b->pos += size;
145 38626 : return (ssize_t) cnt;
146 : }
147 :
148 : static void
149 203137 : buffer_close(stream *s)
150 : {
151 203137 : (void) s;
152 203137 : }
153 :
154 : static int
155 0 : buffer_flush(stream *s, mnstr_flush_level flush_level)
156 : {
157 0 : buffer *b;
158 :
159 0 : b = (buffer *) s->stream_data.p;
160 0 : assert(b);
161 0 : if (b == NULL)
162 : return -1;
163 0 : b->pos = 0;
164 0 : (void) flush_level;
165 0 : return 0;
166 : }
167 :
168 : static void
169 0 : buffer_destroy_stream(stream *s)
170 : {
171 0 : buffer_destroy(s->stream_data.p);
172 0 : destroy_stream(s);
173 0 : }
174 :
175 : stream *
176 202685 : buffer_rastream(buffer *restrict b, const char *restrict name)
177 : {
178 202685 : stream *s;
179 :
180 202685 : if (b == NULL || name == NULL) {
181 0 : mnstr_set_open_error(name, 0, "no buffer or no name");
182 0 : return NULL;
183 : }
184 : #ifdef STREAM_DEBUG
185 : fprintf(stderr, "buffer_rastream %s\n", name);
186 : #endif
187 202685 : if ((s = create_stream(name)) == NULL)
188 : return NULL;
189 202685 : s->binary = false;
190 202685 : s->read = buffer_read;
191 202685 : s->write = buffer_write;
192 202685 : s->close = buffer_close;
193 202685 : s->flush = buffer_flush;
194 202685 : s->stream_data.p = (void *) b;
195 202685 : return s;
196 : }
197 :
198 : stream *
199 452 : buffer_wastream(buffer *restrict b, const char *restrict name)
200 : {
201 452 : stream *s;
202 :
203 452 : if (name == NULL) {
204 0 : mnstr_set_open_error(name, 0, "no name");
205 0 : return NULL;
206 : }
207 : #ifdef STREAM_DEBUG
208 : fprintf(stderr, "buffer_wastream %s\n", name);
209 : #endif
210 452 : if ((s = create_stream(name)) == NULL)
211 : return NULL;
212 452 : s->readonly = false;
213 452 : s->binary = false;
214 452 : s->read = buffer_read;
215 452 : s->write = buffer_write;
216 452 : s->close = buffer_close;
217 452 : s->flush = buffer_flush;
218 452 : if (b == NULL) {
219 0 : b = buffer_create(1 << 20);
220 0 : if (b == NULL) {
221 0 : destroy_stream(s);
222 0 : return NULL;
223 : }
224 0 : s->destroy = buffer_destroy_stream;
225 : }
226 452 : s->stream_data.p = (void *) b;
227 452 : return s;
228 : }
|