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