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 :
19 :
20 : /* ------------------------------------------------------------------ */
21 :
22 : bstream *
23 246587 : bstream_create(stream *s, size_t size)
24 : {
25 246587 : bstream *b;
26 :
27 246587 : if (s == NULL)
28 : return NULL;
29 246587 : if ((b = malloc(sizeof(*b))) == NULL)
30 : return NULL;
31 246587 : if (size == 0)
32 350 : size = BUFSIZ;
33 246587 : *b = (bstream) {
34 : .mode = size,
35 : .s = s,
36 : .eof = false,
37 : .size = size,
38 246587 : .buf = malloc(size + 1 + 1),
39 : };
40 246587 : if (b->buf == NULL) {
41 0 : free(b);
42 0 : return NULL;
43 : }
44 : return b;
45 : }
46 :
47 : ssize_t
48 1011900 : bstream_read(bstream *s, size_t size)
49 : {
50 1011900 : ssize_t rd, rd1 = 0;
51 :
52 1011900 : if (s == NULL)
53 : return -1;
54 :
55 1011900 : if (s->eof)
56 : return 0;
57 :
58 1011898 : assert(s->buf != NULL);
59 :
60 1011898 : if (s->pos > 0) {
61 381760 : if (s->pos < s->len) {
62 : /* move all data and end of string marker */
63 1630 : memmove(s->buf, s->buf + s->pos, s->len - s->pos + 1);
64 1630 : s->len -= s->pos;
65 : } else
66 380130 : s->len = 0;
67 381760 : s->pos = 0;
68 : }
69 :
70 1011898 : if (s->len == s->size) {
71 110 : size_t sz = size > 8192 ? 8192 : size;
72 110 : char tmpbuf[8192];
73 :
74 : /* before we realloc more space, see if there is a need */
75 110 : if ((rd1 = s->s->read(s->s, tmpbuf, 1, sz)) == 0) {
76 0 : s->eof = true;
77 0 : return 0;
78 : }
79 110 : if (rd1 < 0)
80 : return rd1;
81 110 : char *p;
82 110 : size_t ns = s->size + size;
83 110 : if ((p = realloc(s->buf, ns + 1)) == NULL) {
84 : return -1;
85 : }
86 110 : s->size = ns;
87 110 : s->buf = p;
88 110 : memcpy(s->buf + s->len, tmpbuf, rd1);
89 110 : s->len += rd1;
90 110 : size -= rd1;
91 110 : if (size == 0)
92 : return rd1;
93 : }
94 :
95 1011898 : if (s->len + size > s->size)
96 234216 : size = s->size - s->len;
97 :
98 1011898 : rd = s->s->read(s->s, s->buf + s->len, 1, size);
99 :
100 1011894 : if (rd < 0)
101 : return rd;
102 :
103 1011876 : if (rd == 0) {
104 420657 : s->eof = true;
105 420657 : return rd1;
106 : }
107 591219 : s->len += (size_t) rd;
108 591219 : s->buf[s->len] = 0; /* fill in the spare with EOS */
109 591219 : return rd + rd1;
110 : }
111 :
112 : #ifdef _POSIX2_LINE_MAX
113 : #define STREAM_LINE_MAX _POSIX2_LINE_MAX
114 : #else
115 : #define STREAM_LINE_MAX 2048
116 : #endif
117 :
118 : static ssize_t
119 0 : bstream_readline(bstream *s)
120 : {
121 0 : size_t size = STREAM_LINE_MAX;
122 0 : size_t rd;
123 :
124 0 : if (s->eof)
125 : return 0;
126 :
127 0 : if (s->pos > 0 && s->len + size >= s->size) {
128 0 : if (s->pos < s->len) {
129 : /* move all data and end of string marker */
130 0 : memmove(s->buf, s->buf + s->pos, s->len - s->pos + 1);
131 0 : s->len -= s->pos;
132 : } else
133 0 : s->len = 0;
134 0 : s->pos = 0;
135 : }
136 :
137 0 : assert(s->buf != NULL);
138 0 : if (s->len == s->size) {
139 0 : char *p;
140 0 : size_t ns = s->size + size + 8192;
141 0 : if ((p = realloc(s->buf, ns + 1)) == NULL) {
142 : return -1;
143 : }
144 0 : s->size = ns;
145 0 : s->buf = p;
146 : }
147 :
148 0 : if (size > s->size - s->len)
149 : size = s->size - s->len;
150 :
151 0 : if (fgets(s->buf + s->len, (int) size, s->s->stream_data.p) == NULL)
152 : return -1;
153 :
154 0 : rd = strlen(s->buf + s->len);
155 :
156 0 : if (rd == 0) {
157 0 : s->eof = true;
158 0 : return 0;
159 : }
160 0 : s->len += rd;
161 0 : s->buf[s->len] = 0; /* fill in the spare with EOS */
162 0 : return (ssize_t) rd;
163 : }
164 :
165 :
166 : ssize_t
167 1010287 : bstream_next(bstream *s)
168 : {
169 1010287 : if (s == NULL)
170 : return -1;
171 1010287 : if (s->mode > 0) {
172 1010287 : return bstream_read(s, s->mode);
173 0 : } else if (s->s->read == file_read) {
174 0 : return bstream_readline(s);
175 : } else {
176 : size_t sz = 0;
177 : ssize_t rd;
178 :
179 0 : while ((rd = bstream_read(s, 1)) == 1 &&
180 0 : s->buf[s->pos + sz] != '\n') {
181 0 : sz++; /* sz += rd, but rd == 1 */
182 : }
183 0 : if (rd < 0)
184 : return rd;
185 0 : return (ssize_t) sz;
186 : }
187 : }
188 :
189 : void
190 246586 : bstream_destroy(bstream *s)
191 : {
192 246586 : if (s) {
193 246586 : if (s->s) {
194 246179 : s->s->close(s->s);
195 246179 : s->s->destroy(s->s);
196 : }
197 246586 : if (s->buf)
198 246586 : free(s->buf);
199 246586 : free(s);
200 : }
201 246586 : }
202 :
203 : int
204 10667738 : bstream_getoob(bstream *s)
205 : {
206 10667738 : if (s && s->s)
207 10667731 : return mnstr_getoob(s->s);
208 : return 0;
209 : }
|