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