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