authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-05-05 13:42:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:28-07:00
log42cc1bd76e00094555fa5115005906848df4ca95
tree618588041409dd804bec9ef143f326f3bfa354c4
parentb78e375a2de5131c99aa20689dcec86840af2a47

std.io.BufferedReader: implement readVecLimit


1 files changed, 51 insertions(+), 43 deletions(-)

lib/std/io/BufferedReader.zig+51-43
......@@ -51,7 +51,7 @@ pub fn reader(br: *BufferedReader) Reader {
5151
5252/// Equivalent semantics to `std.io.Reader.VTable.readVec`.
5353pub fn readVec(br: *BufferedReader, data: []const []u8) Reader.Error!usize {
54 return passthruReadVec(br, data);
54 return readVecLimit(br, data, .unlimited);
5555}
5656
5757/// Equivalent semantics to `std.io.Reader.VTable.read`.
......@@ -106,10 +106,55 @@ pub fn readRemaining(br: *BufferedReader, bw: *BufferedWriter) Reader.RwRemainin
106106
107107/// Equivalent to `readVec` but reads at most `limit` bytes.
108108pub fn readVecLimit(br: *BufferedReader, data: []const []u8, limit: Reader.Limit) Reader.Error!usize {
109 _ = br;
110 _ = data;
111 _ = limit;
112 @panic("TODO");
109 assert(@intFromEnum(Reader.Limit.unlimited) == std.math.maxInt(usize));
110 var remaining = @intFromEnum(limit);
111 for (data, 0..) |buf, i| {
112 const buffered = br.buffer[br.seek..br.end];
113 const copy_len = @min(buffered.len, buf.len, remaining);
114 @memcpy(buf[0..copy_len], buffered[0..copy_len]);
115 br.seek += copy_len;
116 remaining -= copy_len;
117 if (remaining == 0) break;
118 if (buf.len - copy_len == 0) continue;
119
120 br.seek = 0;
121 br.end = 0;
122 var vecs: [8][]u8 = undefined; // Arbitrarily chosen value.
123 const available_remaining_buf = buf[copy_len..];
124 vecs[0] = available_remaining_buf[0..@min(available_remaining_buf.len, remaining)];
125 const vec_start_remaining = remaining;
126 remaining -= vecs[0].len;
127 var vecs_i: usize = 1;
128 var data_i: usize = i + 1;
129 while (true) {
130 if (vecs.len - vecs_i == 0) {
131 const n = try br.unbuffered_reader.readVec(&vecs);
132 return @intFromEnum(limit) - vec_start_remaining + n;
133 }
134 if (remaining == 0 or data.len - data_i == 0) {
135 vecs[vecs_i] = br.buffer;
136 vecs_i += 1;
137 const n = try br.unbuffered_reader.readVec(vecs[0..vecs_i]);
138 const cutoff = vec_start_remaining - remaining;
139 if (n > cutoff) {
140 br.end = n - cutoff;
141 return @intFromEnum(limit) - remaining;
142 } else {
143 return @intFromEnum(limit) - vec_start_remaining + n;
144 }
145 }
146 if (data[data_i].len == 0) {
147 data_i += 1;
148 continue;
149 }
150 const data_elem = data[data_i];
151 vecs[vecs_i] = data_elem[0..@min(data_elem.len, remaining)];
152 remaining -= vecs[vecs_i].len;
153 vecs_i += 1;
154 data_i += 1;
155 }
156 }
157 return @intFromEnum(limit) - remaining;
113158}
114159
115160fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Reader.Limit) Reader.RwError!usize {
......@@ -144,44 +189,7 @@ fn passthruDiscard(context: ?*anyopaque, limit: Reader.Limit) Reader.Error!usize
144189
145190fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize {
146191 const br: *BufferedReader = @alignCast(@ptrCast(context));
147 var total: usize = 0;
148 for (data, 0..) |buf, i| {
149 const buffered = br.buffer[br.seek..br.end];
150 const copy_len = @min(buffered.len, buf.len);
151 @memcpy(buf[0..copy_len], buffered[0..copy_len]);
152 total += copy_len;
153 br.seek += copy_len;
154 if (copy_len < buf.len) {
155 br.seek = 0;
156 br.end = 0;
157 var vecs: [8][]u8 = undefined; // Arbitrarily chosen value.
158 vecs[0] = buf[copy_len..];
159 const vecs_len: usize = @min(vecs.len, data.len - i);
160 var vec_data_len: usize = vecs[0].len;
161 for (vecs[1..vecs_len], data[i + 1 ..][0 .. vecs_len - 1]) |*v, d| {
162 vec_data_len += d.len;
163 v.* = d;
164 }
165 if (vecs_len < vecs.len) {
166 vecs[vecs_len] = br.buffer;
167 const n = try br.unbuffered_reader.readVec(vecs[0 .. vecs_len + 1]);
168 total += @min(n, vec_data_len);
169 br.end = n -| vec_data_len;
170 return total;
171 }
172 if (vecs[vecs.len - 1].len >= br.buffer.len) {
173 total += try br.unbuffered_reader.readVec(&vecs);
174 return total;
175 }
176 vec_data_len -= vecs[vecs.len - 1].len;
177 vecs[vecs.len - 1] = br.buffer;
178 const n = try br.unbuffered_reader.readVec(&vecs);
179 total += @min(n, vec_data_len);
180 br.end = n -| vec_data_len;
181 return total;
182 }
183 }
184 return total;
192 return readVecLimit(br, data, .unlimited);
185193}
186194
187195pub fn seekBy(br: *BufferedReader, seek_by: i64) !void {