| author | |
| committer | |
| log | 231a4b8fde6ff061198c76d02990a471ec48c977 |
| tree | 1fd5c25caa7321898f45c45e6a42f6623b94c760 |
| parent | 4114b63d751cd00ea759f4c0de8568efff58e945 |
| signature |
Removed:
std.io.InStream.readUntilDelimiterBuffer
Deprecated:
std.ArrayList.toSlice
std.ArrayList.toSliceConst
std.ArrayList.at
std.ArrayList.ptrAt
std.ArrayList.setOrError
std.ArrayList.set
std.ArrayList.swapRemoveOrError
std.Buffer.toSlice
std.Buffer.toSliceConst
std.io.InStream.readFull => std.io.InStream.readAll
std.io.InStream.readAllBuffer
New:
std.ArrayList.span
std.ArrayList.expandToCapacity
std.Buffer.span
std.io.InStream.readUntilDelimiterArrayList4 files changed, 114 insertions(+), 107 deletions(-)
lib/std/array_list.zig+48-49| ... | ... | @@ -5,10 +5,8 @@ const testing = std.testing; |
| 5 | 5 | const mem = std.mem; |
| 6 | 6 | const Allocator = mem.Allocator; |
| 7 | 7 | |
| 8 | /// List of items. | |
| 9 | /// | |
| 10 | /// This is a wrapper around an array of T values. Initialize with | |
| 11 | /// `init`. | |
| 8 | /// A contiguous, growable list of items in memory. | |
| 9 | /// This is a wrapper around an array of T values. Initialize with `init`. | |
| 12 | 10 | pub fn ArrayList(comptime T: type) type { |
| 13 | 11 | return AlignedArrayList(T, null); |
| 14 | 12 | } |
| ... | ... | @@ -22,7 +20,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 22 | 20 | return struct { |
| 23 | 21 | const Self = @This(); |
| 24 | 22 | |
| 25 | /// Use toSlice instead of slicing this directly, because if you don't | |
| 23 | /// Use `span` instead of slicing this directly, because if you don't | |
| 26 | 24 | /// specify the end position of the slice, this will potentially give |
| 27 | 25 | /// you uninitialized memory. |
| 28 | 26 | items: Slice, |
| ... | ... | @@ -56,34 +54,37 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 56 | 54 | |
| 57 | 55 | /// Return contents as a slice. Only valid while the list |
| 58 | 56 | /// doesn't change size. |
| 59 | pub fn toSlice(self: Self) Slice { | |
| 57 | pub fn span(self: var) @TypeOf(self.items[0..self.len]) { | |
| 60 | 58 | return self.items[0..self.len]; |
| 61 | 59 | } |
| 62 | 60 | |
| 63 | /// Return list as const slice. Only valid while the list | |
| 64 | /// doesn't change size. | |
| 61 | /// Deprecated: use `span`. | |
| 62 | pub fn toSlice(self: Self) Slice { | |
| 63 | return self.span(); | |
| 64 | } | |
| 65 | ||
| 66 | /// Deprecated: use `span`. | |
| 65 | 67 | pub fn toSliceConst(self: Self) SliceConst { |
| 66 | return self.items[0..self.len]; | |
| 68 | return self.span(); | |
| 67 | 69 | } |
| 68 | 70 | |
| 69 | /// Safely access index i of the list. | |
| 71 | /// Deprecated: use `span()[i]`. | |
| 70 | 72 | pub fn at(self: Self, i: usize) T { |
| 71 | return self.toSliceConst()[i]; | |
| 73 | return self.span()[i]; | |
| 72 | 74 | } |
| 73 | 75 | |
| 74 | /// Safely access ptr to index i of the list. | |
| 76 | /// Deprecated: use `&span()[i]`. | |
| 75 | 77 | pub fn ptrAt(self: Self, i: usize) *T { |
| 76 | return &self.toSlice()[i]; | |
| 78 | return &self.span()[i]; | |
| 77 | 79 | } |
| 78 | 80 | |
| 79 | /// Sets the value at index `i`, or returns `error.OutOfBounds` if | |
| 80 | /// the index is not in range. | |
| 81 | /// Deprecated: use `if (i >= list.len) return error.OutOfBounds else span()[i] = item`. | |
| 81 | 82 | pub fn setOrError(self: Self, i: usize, item: T) !void { |
| 82 | 83 | if (i >= self.len) return error.OutOfBounds; |
| 83 | 84 | self.items[i] = item; |
| 84 | 85 | } |
| 85 | 86 | |
| 86 | /// Sets the value at index `i`, asserting that the value is in range. | |
| 87 | /// Deprecated: use `list.span()[i] = item`. | |
| 87 | 88 | pub fn set(self: *Self, i: usize, item: T) void { |
| 88 | 89 | assert(i < self.len); |
| 89 | 90 | self.items[i] = item; |
| ... | ... | @@ -124,18 +125,18 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 124 | 125 | self.items[n] = item; |
| 125 | 126 | } |
| 126 | 127 | |
| 127 | /// Insert slice `items` at index `n`. Moves | |
| 128 | /// `list[n .. list.len]` to make room. | |
| 129 | pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void { | |
| 128 | /// Insert slice `items` at index `i`. Moves | |
| 129 | /// `list[i .. list.len]` to make room. | |
| 130 | /// This operation is O(N). | |
| 131 | pub fn insertSlice(self: *Self, i: usize, items: SliceConst) !void { | |
| 130 | 132 | try self.ensureCapacity(self.len + items.len); |
| 131 | 133 | self.len += items.len; |
| 132 | 134 | |
| 133 | mem.copyBackwards(T, self.items[n + items.len .. self.len], self.items[n .. self.len - items.len]); | |
| 134 | mem.copy(T, self.items[n .. n + items.len], items); | |
| 135 | mem.copyBackwards(T, self.items[i + items.len .. self.len], self.items[i .. self.len - items.len]); | |
| 136 | mem.copy(T, self.items[i .. i + items.len], items); | |
| 135 | 137 | } |
| 136 | 138 | |
| 137 | /// Extend the list by 1 element. Allocates more memory as | |
| 138 | /// necessary. | |
| 139 | /// Extend the list by 1 element. Allocates more memory as necessary. | |
| 139 | 140 | pub fn append(self: *Self, item: T) !void { |
| 140 | 141 | const new_item_ptr = try self.addOne(); |
| 141 | 142 | new_item_ptr.* = item; |
| ... | ... | @@ -148,8 +149,9 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 148 | 149 | new_item_ptr.* = item; |
| 149 | 150 | } |
| 150 | 151 | |
| 151 | /// Remove the element at index `i` from the list and return | |
| 152 | /// its value. Asserts the array has at least one item. | |
| 152 | /// Remove the element at index `i` from the list and return its value. | |
| 153 | /// Asserts the array has at least one item. | |
| 154 | /// This operation is O(N). | |
| 153 | 155 | pub fn orderedRemove(self: *Self, i: usize) T { |
| 154 | 156 | const newlen = self.len - 1; |
| 155 | 157 | if (newlen == i) return self.pop(); |
| ... | ... | @@ -163,18 +165,17 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 163 | 165 | |
| 164 | 166 | /// Removes the element at the specified index and returns it. |
| 165 | 167 | /// The empty slot is filled from the end of the list. |
| 168 | /// This operation is O(1). | |
| 166 | 169 | pub fn swapRemove(self: *Self, i: usize) T { |
| 167 | 170 | if (self.len - 1 == i) return self.pop(); |
| 168 | 171 | |
| 169 | const slice = self.toSlice(); | |
| 172 | const slice = self.span(); | |
| 170 | 173 | const old_item = slice[i]; |
| 171 | 174 | slice[i] = self.pop(); |
| 172 | 175 | return old_item; |
| 173 | 176 | } |
| 174 | 177 | |
| 175 | /// Removes the element at the specified index and returns it | |
| 176 | /// or an error.OutOfBounds is returned. If no error then | |
| 177 | /// the empty slot is filled from the end of the list. | |
| 178 | /// Deprecated: use `if (i >= list.len) return error.OutOfBounds else list.swapRemove(i)`. | |
| 178 | 179 | pub fn swapRemoveOrError(self: *Self, i: usize) !T { |
| 179 | 180 | if (i >= self.len) return error.OutOfBounds; |
| 180 | 181 | return self.swapRemove(i); |
| ... | ... | @@ -204,6 +205,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 204 | 205 | } |
| 205 | 206 | |
| 206 | 207 | /// Reduce allocated capacity to `new_len`. |
| 208 | /// Invalidates element pointers. | |
| 207 | 209 | pub fn shrink(self: *Self, new_len: usize) void { |
| 208 | 210 | assert(new_len <= self.len); |
| 209 | 211 | self.len = new_len; |
| ... | ... | @@ -222,13 +224,24 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 222 | 224 | self.items = try self.allocator.realloc(self.items, better_capacity); |
| 223 | 225 | } |
| 224 | 226 | |
| 227 | /// Increases the array's length to match the full capacity that is already allocated. | |
| 228 | /// The new elements have `undefined` values. This operation does not invalidate any | |
| 229 | /// element pointers. | |
| 230 | pub fn expandToCapacity(self: *Self) void { | |
| 231 | self.len = self.items.len; | |
| 232 | } | |
| 233 | ||
| 225 | 234 | /// Increase length by 1, returning pointer to the new item. |
| 235 | /// The returned pointer becomes invalid when the list is resized. | |
| 226 | 236 | pub fn addOne(self: *Self) !*T { |
| 227 | 237 | const new_length = self.len + 1; |
| 228 | 238 | try self.ensureCapacity(new_length); |
| 229 | 239 | return self.addOneAssumeCapacity(); |
| 230 | 240 | } |
| 231 | 241 | |
| 242 | /// Increase length by 1, returning pointer to the new item. | |
| 243 | /// Asserts that there is already space for the new item without allocating more. | |
| 244 | /// The returned pointer becomes invalid when the list is resized. | |
| 232 | 245 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 233 | 246 | assert(self.len < self.capacity()); |
| 234 | 247 | const result = &self.items[self.len]; |
| ... | ... | @@ -236,33 +249,19 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 236 | 249 | return result; |
| 237 | 250 | } |
| 238 | 251 | |
| 239 | /// Remove and return the last element from the list. Asserts | |
| 240 | /// the list has at least one item. | |
| 252 | /// Remove and return the last element from the list. | |
| 253 | /// Asserts the list has at least one item. | |
| 241 | 254 | pub fn pop(self: *Self) T { |
| 242 | 255 | self.len -= 1; |
| 243 | 256 | return self.items[self.len]; |
| 244 | 257 | } |
| 245 | 258 | |
| 246 | /// Like `pop` but returns `null` if empty. | |
| 259 | /// Remove and return the last element from the list. | |
| 260 | /// If the list is empty, returns `null`. | |
| 247 | 261 | pub fn popOrNull(self: *Self) ?T { |
| 248 | 262 | if (self.len == 0) return null; |
| 249 | 263 | return self.pop(); |
| 250 | 264 | } |
| 251 | ||
| 252 | pub fn eql(self: Self, m: []const T) bool { | |
| 253 | return mem.eql(T, self.toSliceConst(), m); | |
| 254 | } | |
| 255 | ||
| 256 | pub fn startsWith(self: Self, m: []const T) bool { | |
| 257 | if (self.len < m.len) return false; | |
| 258 | return mem.eql(T, self.items[0..m.len], m); | |
| 259 | } | |
| 260 | ||
| 261 | pub fn endsWith(self: Self, m: []const T) bool { | |
| 262 | if (self.len < m.len) return false; | |
| 263 | const start = self.len - m.len; | |
| 264 | return mem.eql(T, self.items[start..self.len], m); | |
| 265 | } | |
| 266 | 265 | }; |
| 267 | 266 | } |
| 268 | 267 | |
| ... | ... | @@ -302,7 +301,7 @@ test "std.ArrayList.basic" { |
| 302 | 301 | } |
| 303 | 302 | } |
| 304 | 303 | |
| 305 | for (list.toSlice()) |v, i| { | |
| 304 | for (list.span()) |v, i| { | |
| 306 | 305 | testing.expect(v == @intCast(i32, i + 1)); |
| 307 | 306 | } |
| 308 | 307 | |
| ... | ... | @@ -340,7 +339,7 @@ test "std.ArrayList.appendNTimes" { |
| 340 | 339 | |
| 341 | 340 | try list.appendNTimes(2, 10); |
| 342 | 341 | testing.expectEqual(@as(usize, 10), list.len); |
| 343 | for (list.toSlice()) |element| { | |
| 342 | for (list.span()) |element| { | |
| 344 | 343 | testing.expectEqual(@as(i32, 2), element); |
| 345 | 344 | } |
| 346 | 345 | } |
lib/std/buffer.zig+9-3| ... | ... | @@ -81,12 +81,18 @@ pub const Buffer = struct { |
| 81 | 81 | self.list.deinit(); |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | pub fn span(self: var) @TypeOf(self.list.items[0 .. self.list.len - 1 :0]) { | |
| 85 | return self.list.span()[0..self.len() :0]; | |
| 86 | } | |
| 87 | ||
| 88 | /// Deprecated: use `span` | |
| 84 | 89 | pub fn toSlice(self: Buffer) [:0]u8 { |
| 85 | return self.list.toSlice()[0..self.len() :0]; | |
| 90 | return self.span(); | |
| 86 | 91 | } |
| 87 | 92 | |
| 93 | /// Deprecated: use `span` | |
| 88 | 94 | pub fn toSliceConst(self: Buffer) [:0]const u8 { |
| 89 | return self.list.toSliceConst()[0..self.len() :0]; | |
| 95 | return self.span(); | |
| 90 | 96 | } |
| 91 | 97 | |
| 92 | 98 | pub fn shrink(self: *Buffer, new_len: usize) void { |
| ... | ... | @@ -133,7 +139,7 @@ pub const Buffer = struct { |
| 133 | 139 | |
| 134 | 140 | pub fn startsWith(self: Buffer, m: []const u8) bool { |
| 135 | 141 | if (self.len() < m.len) return false; |
| 136 | return self.list.startsWith(m); | |
| 142 | return mem.eql(u8, self.list.items[0..m.len], m); | |
| 137 | 143 | } |
| 138 | 144 | |
| 139 | 145 | pub fn endsWith(self: Buffer, m: []const u8) bool { |
lib/std/build/run.zig+14-18| ... | ... | @@ -170,7 +170,9 @@ pub const RunStep = struct { |
| 170 | 170 | |
| 171 | 171 | // TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O). |
| 172 | 172 | |
| 173 | var stdout: []const u8 = undefined; | |
| 173 | var stdout: ?[]const u8 = null; | |
| 174 | defer if (stdout) |s| self.builder.allocator.free(s); | |
| 175 | ||
| 174 | 176 | switch (self.stdout_action) { |
| 175 | 177 | .expect_exact, .expect_matches => { |
| 176 | 178 | var stdout_file_in_stream = child.stdout.?.inStream(); |
| ... | ... | @@ -178,12 +180,10 @@ pub const RunStep = struct { |
| 178 | 180 | }, |
| 179 | 181 | .inherit, .ignore => {}, |
| 180 | 182 | } |
| 181 | defer switch (self.stdout_action) { | |
| 182 | .expect_exact, .expect_matches => self.builder.allocator.free(stdout), | |
| 183 | .inherit, .ignore => {}, | |
| 184 | }; | |
| 185 | 183 | |
| 186 | var stderr: []const u8 = undefined; | |
| 184 | var stderr: ?[]const u8 = null; | |
| 185 | defer if (stderr) |s| self.builder.allocator.free(s); | |
| 186 | ||
| 187 | 187 | switch (self.stderr_action) { |
| 188 | 188 | .expect_exact, .expect_matches => { |
| 189 | 189 | var stderr_file_in_stream = child.stderr.?.inStream(); |
| ... | ... | @@ -191,10 +191,6 @@ pub const RunStep = struct { |
| 191 | 191 | }, |
| 192 | 192 | .inherit, .ignore => {}, |
| 193 | 193 | } |
| 194 | defer switch (self.stderr_action) { | |
| 195 | .expect_exact, .expect_matches => self.builder.allocator.free(stderr), | |
| 196 | .inherit, .ignore => {}, | |
| 197 | }; | |
| 198 | 194 | |
| 199 | 195 | const term = child.wait() catch |err| { |
| 200 | 196 | warn("Unable to spawn {}: {}\n", .{ argv[0], @errorName(err) }); |
| ... | ... | @@ -222,7 +218,7 @@ pub const RunStep = struct { |
| 222 | 218 | switch (self.stderr_action) { |
| 223 | 219 | .inherit, .ignore => {}, |
| 224 | 220 | .expect_exact => |expected_bytes| { |
| 225 | if (!mem.eql(u8, expected_bytes, stderr)) { | |
| 221 | if (!mem.eql(u8, expected_bytes, stderr.?)) { | |
| 226 | 222 | warn( |
| 227 | 223 | \\ |
| 228 | 224 | \\========= Expected this stderr: ========= |
| ... | ... | @@ -230,13 +226,13 @@ pub const RunStep = struct { |
| 230 | 226 | \\========= But found: ==================== |
| 231 | 227 | \\{} |
| 232 | 228 | \\ |
| 233 | , .{ expected_bytes, stderr }); | |
| 229 | , .{ expected_bytes, stderr.? }); | |
| 234 | 230 | printCmd(cwd, argv); |
| 235 | 231 | return error.TestFailed; |
| 236 | 232 | } |
| 237 | 233 | }, |
| 238 | 234 | .expect_matches => |matches| for (matches) |match| { |
| 239 | if (mem.indexOf(u8, stderr, match) == null) { | |
| 235 | if (mem.indexOf(u8, stderr.?, match) == null) { | |
| 240 | 236 | warn( |
| 241 | 237 | \\ |
| 242 | 238 | \\========= Expected to find in stderr: ========= |
| ... | ... | @@ -244,7 +240,7 @@ pub const RunStep = struct { |
| 244 | 240 | \\========= But stderr does not contain it: ===== |
| 245 | 241 | \\{} |
| 246 | 242 | \\ |
| 247 | , .{ match, stderr }); | |
| 243 | , .{ match, stderr.? }); | |
| 248 | 244 | printCmd(cwd, argv); |
| 249 | 245 | return error.TestFailed; |
| 250 | 246 | } |
| ... | ... | @@ -254,7 +250,7 @@ pub const RunStep = struct { |
| 254 | 250 | switch (self.stdout_action) { |
| 255 | 251 | .inherit, .ignore => {}, |
| 256 | 252 | .expect_exact => |expected_bytes| { |
| 257 | if (!mem.eql(u8, expected_bytes, stdout)) { | |
| 253 | if (!mem.eql(u8, expected_bytes, stdout.?)) { | |
| 258 | 254 | warn( |
| 259 | 255 | \\ |
| 260 | 256 | \\========= Expected this stdout: ========= |
| ... | ... | @@ -262,13 +258,13 @@ pub const RunStep = struct { |
| 262 | 258 | \\========= But found: ==================== |
| 263 | 259 | \\{} |
| 264 | 260 | \\ |
| 265 | , .{ expected_bytes, stdout }); | |
| 261 | , .{ expected_bytes, stdout.? }); | |
| 266 | 262 | printCmd(cwd, argv); |
| 267 | 263 | return error.TestFailed; |
| 268 | 264 | } |
| 269 | 265 | }, |
| 270 | 266 | .expect_matches => |matches| for (matches) |match| { |
| 271 | if (mem.indexOf(u8, stdout, match) == null) { | |
| 267 | if (mem.indexOf(u8, stdout.?, match) == null) { | |
| 272 | 268 | warn( |
| 273 | 269 | \\ |
| 274 | 270 | \\========= Expected to find in stdout: ========= |
| ... | ... | @@ -276,7 +272,7 @@ pub const RunStep = struct { |
| 276 | 272 | \\========= But stdout does not contain it: ===== |
| 277 | 273 | \\{} |
| 278 | 274 | \\ |
| 279 | , .{ match, stdout }); | |
| 275 | , .{ match, stdout.? }); | |
| 280 | 276 | printCmd(cwd, argv); |
| 281 | 277 | return error.TestFailed; |
| 282 | 278 | } |
lib/std/io/in_stream.zig+43-37| ... | ... | @@ -41,10 +41,13 @@ pub fn InStream(comptime ReadError: type) type { |
| 41 | 41 | } |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | /// Deprecated: use `readAll`. | |
| 45 | pub const readFull = readAll; | |
| 46 | ||
| 44 | 47 | /// Returns the number of bytes read. If the number read is smaller than buf.len, it |
| 45 | 48 | /// means the stream reached the end. Reaching the end of a stream is not an error |
| 46 | 49 | /// condition. |
| 47 | pub fn readFull(self: *Self, buffer: []u8) Error!usize { | |
| 50 | pub fn readAll(self: *Self, buffer: []u8) Error!usize { | |
| 48 | 51 | var index: usize = 0; |
| 49 | 52 | while (index != buffer.len) { |
| 50 | 53 | const amt = try self.read(buffer[index..]); |
| ... | ... | @@ -57,39 +60,43 @@ pub fn InStream(comptime ReadError: type) type { |
| 57 | 60 | /// Returns the number of bytes read. If the number read would be smaller than buf.len, |
| 58 | 61 | /// error.EndOfStream is returned instead. |
| 59 | 62 | pub fn readNoEof(self: *Self, buf: []u8) !void { |
| 60 | const amt_read = try self.readFull(buf); | |
| 63 | const amt_read = try self.readAll(buf); | |
| 61 | 64 | if (amt_read < buf.len) return error.EndOfStream; |
| 62 | 65 | } |
| 63 | 66 | |
| 64 | /// Replaces `buffer` contents by reading from the stream until it is finished. | |
| 65 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and | |
| 66 | /// the contents read from the stream are lost. | |
| 67 | /// Deprecated: use `readAllArrayList`. | |
| 67 | 68 | pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void { |
| 68 | try buffer.list.ensureCapacity(1); | |
| 69 | buffer.list.len = 0; | |
| 70 | errdefer buffer.resize(0) catch unreachable; // make sure we leave buffer in a valid state on error | |
| 69 | buffer.list.shrink(0); | |
| 71 | 70 | try self.readAllArrayList(&buffer.list, max_size); |
| 71 | errdefer buffer.shrink(0); | |
| 72 | 72 | try buffer.list.append(0); |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | /// Appends to the ArrayList contents by reading from the stream until end of stream is found. | |
| 76 | /// If the ArrayList length would exceed `max_size`, `error.StreamTooLong` is returned and the contents | |
| 77 | /// read from the stream so far are lost. | |
| 78 | pub fn readAllArrayList(self: *Self, array_list: *std.ArrayList(u8), max_size: usize) !void { | |
| 79 | var actual_buf_len: usize = 0; | |
| 75 | /// Appends to the `std.ArrayList` contents by reading from the stream until end of stream is found. | |
| 76 | /// If the number of bytes appended would exceed `max_append_size`, `error.StreamTooLong` is returned | |
| 77 | /// and the `std.ArrayList` has exactly `max_append_size` bytes appended. | |
| 78 | pub fn readAllArrayList(self: *Self, array_list: *std.ArrayList(u8), max_append_size: usize) !void { | |
| 79 | try array_list.ensureCapacity(math.min(max_append_size, 4096)); | |
| 80 | const original_len = array_list.len; | |
| 81 | var start_index: usize = original_len; | |
| 80 | 82 | while (true) { |
| 81 | const dest_slice = array_list.toSlice()[actual_buf_len..]; | |
| 82 | const bytes_read = try self.readFull(dest_slice); | |
| 83 | actual_buf_len += bytes_read; | |
| 83 | array_list.expandToCapacity(); | |
| 84 | const dest_slice = array_list.span()[start_index..]; | |
| 85 | const bytes_read = try self.readAll(dest_slice); | |
| 86 | start_index += bytes_read; | |
| 87 | ||
| 88 | if (start_index - original_len > max_append_size) { | |
| 89 | array_list.shrink(original_len + max_append_size); | |
| 90 | return error.StreamTooLong; | |
| 91 | } | |
| 84 | 92 | |
| 85 | 93 | if (bytes_read != dest_slice.len) { |
| 86 | array_list.shrink(actual_buf_len); | |
| 94 | array_list.shrink(start_index); | |
| 87 | 95 | return; |
| 88 | 96 | } |
| 89 | 97 | |
| 90 | const new_buf_size = math.min(max_size, actual_buf_len + mem.page_size); | |
| 91 | if (new_buf_size == actual_buf_len) return error.StreamTooLong; | |
| 92 | try array_list.resize(new_buf_size); | |
| 98 | // This will trigger ArrayList to expand superlinearly at whatever its growth rate is. | |
| 99 | try array_list.ensureCapacity(start_index + 1); | |
| 93 | 100 | } |
| 94 | 101 | } |
| 95 | 102 | |
| ... | ... | @@ -104,23 +111,17 @@ pub fn InStream(comptime ReadError: type) type { |
| 104 | 111 | return array_list.toOwnedSlice(); |
| 105 | 112 | } |
| 106 | 113 | |
| 107 | /// Replaces `buffer` contents by reading from the stream until `delimiter` is found. | |
| 108 | /// Does not include the delimiter in the result. | |
| 109 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents | |
| 110 | /// read from the stream so far are lost. | |
| 111 | pub fn readUntilDelimiterBuffer(self: *Self, buffer: *Buffer, delimiter: u8, max_size: usize) !void { | |
| 112 | try buffer.list.ensureCapacity(1); | |
| 113 | buffer.list.len = 0; | |
| 114 | errdefer buffer.resize(0) catch unreachable; // make sure we leave buffer in a valid state on error | |
| 115 | try self.readUntilDelimiterArrayList(&buffer.list, delimiter, max_size); | |
| 116 | try buffer.list.append(0); | |
| 117 | } | |
| 118 | ||
| 119 | /// Appends to the ArrayList contents by reading from the stream until `delimiter` is found. | |
| 114 | /// Replaces the `std.ArrayList` contents by reading from the stream until `delimiter` is found. | |
| 120 | 115 | /// Does not include the delimiter in the result. |
| 121 | /// If the ArrayList length would exceed `max_size`, `error.StreamTooLong` is returned and the contents | |
| 122 | /// read from the stream so far are lost. | |
| 123 | pub fn readUntilDelimiterArrayList(self: *Self, array_list: *std.ArrayList(u8), delimiter: u8, max_size: usize) !void { | |
| 116 | /// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the | |
| 117 | /// `std.ArrayList` is populated with `max_size` bytes from the stream. | |
| 118 | pub fn readUntilDelimiterArrayList( | |
| 119 | self: *Self, | |
| 120 | array_list: *std.ArrayList(u8), | |
| 121 | delimiter: u8, | |
| 122 | max_size: usize, | |
| 123 | ) !void { | |
| 124 | array_list.shrink(0); | |
| 124 | 125 | while (true) { |
| 125 | 126 | var byte: u8 = try self.readByte(); |
| 126 | 127 | |
| ... | ... | @@ -140,7 +141,12 @@ pub fn InStream(comptime ReadError: type) type { |
| 140 | 141 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. |
| 141 | 142 | /// Caller owns returned memory. |
| 142 | 143 | /// If this function returns an error, the contents from the stream read so far are lost. |
| 143 | pub fn readUntilDelimiterAlloc(self: *Self, allocator: *mem.Allocator, delimiter: u8, max_size: usize) ![]u8 { | |
| 144 | pub fn readUntilDelimiterAlloc( | |
| 145 | self: *Self, | |
| 146 | allocator: *mem.Allocator, | |
| 147 | delimiter: u8, | |
| 148 | max_size: usize, | |
| 149 | ) ![]u8 { | |
| 144 | 150 | var array_list = std.ArrayList(u8).init(allocator); |
| 145 | 151 | defer array_list.deinit(); |
| 146 | 152 | try self.readUntilDelimiterArrayList(&array_list, delimiter, max_size); |