| author | |
| committer | |
| log | 7f975bf09f4e6e81d68c9a573ac2e31b997b5816 |
| tree | 1fd5c25caa7321898f45c45e6a42f6623b94c760 |
| parent | fa46bcb36864e6616ce4449965063f3b8720f8e1 |
| parent | 231a4b8fde6ff061198c76d02990a471ec48c977 |
| signature |
Closes #4405
Closes #465611 files changed, 165 insertions(+), 131 deletions(-)
build.zig-1| ... | @@ -6,7 +6,6 @@ const BufMap = std.BufMap; | ... | @@ -6,7 +6,6 @@ const BufMap = std.BufMap; |
| 6 | const warn = std.debug.warn; | 6 | const warn = std.debug.warn; |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | const ArrayList = std.ArrayList; | 8 | const ArrayList = std.ArrayList; |
| 9 | const Buffer = std.Buffer; | ||
| 10 | const io = std.io; | 9 | const io = std.io; |
| 11 | const fs = std.fs; | 10 | const fs = std.fs; |
| 12 | const InstallDirectoryOptions = std.build.InstallDirectoryOptions; | 11 | const InstallDirectoryOptions = std.build.InstallDirectoryOptions; |
lib/std/array_list.zig+48-34| ... | @@ -5,10 +5,8 @@ const testing = std.testing; | ... | @@ -5,10 +5,8 @@ const testing = std.testing; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| 7 | 7 | ||
| 8 | /// List of items. | 8 | /// A contiguous, growable list of items in memory. |
| 9 | /// | 9 | /// This is a wrapper around an array of T values. Initialize with `init`. |
| 10 | /// This is a wrapper around an array of T values. Initialize with | ||
| 11 | /// `init`. | ||
| 12 | pub fn ArrayList(comptime T: type) type { | 10 | pub fn ArrayList(comptime T: type) type { |
| 13 | return AlignedArrayList(T, null); | 11 | return AlignedArrayList(T, null); |
| 14 | } | 12 | } |
| ... | @@ -22,7 +20,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -22,7 +20,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 22 | return struct { | 20 | return struct { |
| 23 | const Self = @This(); | 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 | /// specify the end position of the slice, this will potentially give | 24 | /// specify the end position of the slice, this will potentially give |
| 27 | /// you uninitialized memory. | 25 | /// you uninitialized memory. |
| 28 | items: Slice, | 26 | items: Slice, |
| ... | @@ -56,34 +54,37 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -56,34 +54,37 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 56 | 54 | ||
| 57 | /// Return contents as a slice. Only valid while the list | 55 | /// Return contents as a slice. Only valid while the list |
| 58 | /// doesn't change size. | 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 | return self.items[0..self.len]; | 58 | return self.items[0..self.len]; |
| 61 | } | 59 | } |
| 62 | 60 | ||
| 63 | /// Return list as const slice. Only valid while the list | 61 | /// Deprecated: use `span`. |
| 64 | /// doesn't change size. | 62 | pub fn toSlice(self: Self) Slice { |
| 63 | return self.span(); | ||
| 64 | } | ||
| 65 | |||
| 66 | /// Deprecated: use `span`. | ||
| 65 | pub fn toSliceConst(self: Self) SliceConst { | 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 | pub fn at(self: Self, i: usize) T { | 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 | pub fn ptrAt(self: Self, i: usize) *T { | 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 | 81 | /// Deprecated: use `if (i >= list.len) return error.OutOfBounds else span()[i] = item`. |
| 80 | /// the index is not in range. | ||
| 81 | pub fn setOrError(self: Self, i: usize, item: T) !void { | 82 | pub fn setOrError(self: Self, i: usize, item: T) !void { |
| 82 | if (i >= self.len) return error.OutOfBounds; | 83 | if (i >= self.len) return error.OutOfBounds; |
| 83 | self.items[i] = item; | 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 | pub fn set(self: *Self, i: usize, item: T) void { | 88 | pub fn set(self: *Self, i: usize, item: T) void { |
| 88 | assert(i < self.len); | 89 | assert(i < self.len); |
| 89 | self.items[i] = item; | 90 | self.items[i] = item; |
| ... | @@ -124,18 +125,18 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -124,18 +125,18 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 124 | self.items[n] = item; | 125 | self.items[n] = item; |
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | /// Insert slice `items` at index `n`. Moves | 128 | /// Insert slice `items` at index `i`. Moves |
| 128 | /// `list[n .. list.len]` to make room. | 129 | /// `list[i .. list.len]` to make room. |
| 129 | pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void { | 130 | /// This operation is O(N). |
| 131 | pub fn insertSlice(self: *Self, i: usize, items: SliceConst) !void { | ||
| 130 | try self.ensureCapacity(self.len + items.len); | 132 | try self.ensureCapacity(self.len + items.len); |
| 131 | self.len += items.len; | 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]); | 135 | mem.copyBackwards(T, self.items[i + items.len .. self.len], self.items[i .. self.len - items.len]); |
| 134 | mem.copy(T, self.items[n .. n + items.len], items); | 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 | 139 | /// Extend the list by 1 element. Allocates more memory as necessary. |
| 138 | /// necessary. | ||
| 139 | pub fn append(self: *Self, item: T) !void { | 140 | pub fn append(self: *Self, item: T) !void { |
| 140 | const new_item_ptr = try self.addOne(); | 141 | const new_item_ptr = try self.addOne(); |
| 141 | new_item_ptr.* = item; | 142 | new_item_ptr.* = item; |
| ... | @@ -148,8 +149,9 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -148,8 +149,9 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 148 | new_item_ptr.* = item; | 149 | new_item_ptr.* = item; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| 151 | /// Remove the element at index `i` from the list and return | 152 | /// Remove the element at index `i` from the list and return its value. |
| 152 | /// its value. Asserts the array has at least one item. | 153 | /// Asserts the array has at least one item. |
| 154 | /// This operation is O(N). | ||
| 153 | pub fn orderedRemove(self: *Self, i: usize) T { | 155 | pub fn orderedRemove(self: *Self, i: usize) T { |
| 154 | const newlen = self.len - 1; | 156 | const newlen = self.len - 1; |
| 155 | if (newlen == i) return self.pop(); | 157 | if (newlen == i) return self.pop(); |
| ... | @@ -163,18 +165,17 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -163,18 +165,17 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 163 | 165 | ||
| 164 | /// Removes the element at the specified index and returns it. | 166 | /// Removes the element at the specified index and returns it. |
| 165 | /// The empty slot is filled from the end of the list. | 167 | /// The empty slot is filled from the end of the list. |
| 168 | /// This operation is O(1). | ||
| 166 | pub fn swapRemove(self: *Self, i: usize) T { | 169 | pub fn swapRemove(self: *Self, i: usize) T { |
| 167 | if (self.len - 1 == i) return self.pop(); | 170 | if (self.len - 1 == i) return self.pop(); |
| 168 | 171 | ||
| 169 | const slice = self.toSlice(); | 172 | const slice = self.span(); |
| 170 | const old_item = slice[i]; | 173 | const old_item = slice[i]; |
| 171 | slice[i] = self.pop(); | 174 | slice[i] = self.pop(); |
| 172 | return old_item; | 175 | return old_item; |
| 173 | } | 176 | } |
| 174 | 177 | ||
| 175 | /// Removes the element at the specified index and returns it | 178 | /// Deprecated: use `if (i >= list.len) return error.OutOfBounds else list.swapRemove(i)`. |
| 176 | /// or an error.OutOfBounds is returned. If no error then | ||
| 177 | /// the empty slot is filled from the end of the list. | ||
| 178 | pub fn swapRemoveOrError(self: *Self, i: usize) !T { | 179 | pub fn swapRemoveOrError(self: *Self, i: usize) !T { |
| 179 | if (i >= self.len) return error.OutOfBounds; | 180 | if (i >= self.len) return error.OutOfBounds; |
| 180 | return self.swapRemove(i); | 181 | return self.swapRemove(i); |
| ... | @@ -204,6 +205,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -204,6 +205,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 204 | } | 205 | } |
| 205 | 206 | ||
| 206 | /// Reduce allocated capacity to `new_len`. | 207 | /// Reduce allocated capacity to `new_len`. |
| 208 | /// Invalidates element pointers. | ||
| 207 | pub fn shrink(self: *Self, new_len: usize) void { | 209 | pub fn shrink(self: *Self, new_len: usize) void { |
| 208 | assert(new_len <= self.len); | 210 | assert(new_len <= self.len); |
| 209 | self.len = new_len; | 211 | self.len = new_len; |
| ... | @@ -222,13 +224,24 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -222,13 +224,24 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 222 | self.items = try self.allocator.realloc(self.items, better_capacity); | 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 | /// Increase length by 1, returning pointer to the new item. | 234 | /// Increase length by 1, returning pointer to the new item. |
| 235 | /// The returned pointer becomes invalid when the list is resized. | ||
| 226 | pub fn addOne(self: *Self) !*T { | 236 | pub fn addOne(self: *Self) !*T { |
| 227 | const new_length = self.len + 1; | 237 | const new_length = self.len + 1; |
| 228 | try self.ensureCapacity(new_length); | 238 | try self.ensureCapacity(new_length); |
| 229 | return self.addOneAssumeCapacity(); | 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 | pub fn addOneAssumeCapacity(self: *Self) *T { | 245 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 233 | assert(self.len < self.capacity()); | 246 | assert(self.len < self.capacity()); |
| 234 | const result = &self.items[self.len]; | 247 | const result = &self.items[self.len]; |
| ... | @@ -236,14 +249,15 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -236,14 +249,15 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { |
| 236 | return result; | 249 | return result; |
| 237 | } | 250 | } |
| 238 | 251 | ||
| 239 | /// Remove and return the last element from the list. Asserts | 252 | /// Remove and return the last element from the list. |
| 240 | /// the list has at least one item. | 253 | /// Asserts the list has at least one item. |
| 241 | pub fn pop(self: *Self) T { | 254 | pub fn pop(self: *Self) T { |
| 242 | self.len -= 1; | 255 | self.len -= 1; |
| 243 | return self.items[self.len]; | 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 | pub fn popOrNull(self: *Self) ?T { | 261 | pub fn popOrNull(self: *Self) ?T { |
| 248 | if (self.len == 0) return null; | 262 | if (self.len == 0) return null; |
| 249 | return self.pop(); | 263 | return self.pop(); |
| ... | @@ -287,7 +301,7 @@ test "std.ArrayList.basic" { | ... | @@ -287,7 +301,7 @@ test "std.ArrayList.basic" { |
| 287 | } | 301 | } |
| 288 | } | 302 | } |
| 289 | 303 | ||
| 290 | for (list.toSlice()) |v, i| { | 304 | for (list.span()) |v, i| { |
| 291 | testing.expect(v == @intCast(i32, i + 1)); | 305 | testing.expect(v == @intCast(i32, i + 1)); |
| 292 | } | 306 | } |
| 293 | 307 | ||
| ... | @@ -325,7 +339,7 @@ test "std.ArrayList.appendNTimes" { | ... | @@ -325,7 +339,7 @@ test "std.ArrayList.appendNTimes" { |
| 325 | 339 | ||
| 326 | try list.appendNTimes(2, 10); | 340 | try list.appendNTimes(2, 10); |
| 327 | testing.expectEqual(@as(usize, 10), list.len); | 341 | testing.expectEqual(@as(usize, 10), list.len); |
| 328 | for (list.toSlice()) |element| { | 342 | for (list.span()) |element| { |
| 329 | testing.expectEqual(@as(i32, 2), element); | 343 | testing.expectEqual(@as(i32, 2), element); |
| 330 | } | 344 | } |
| 331 | } | 345 | } |
lib/std/buffer.zig+8-2| ... | @@ -81,12 +81,18 @@ pub const Buffer = struct { | ... | @@ -81,12 +81,18 @@ pub const Buffer = struct { |
| 81 | self.list.deinit(); | 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 | pub fn toSlice(self: Buffer) [:0]u8 { | 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 | pub fn toSliceConst(self: Buffer) [:0]const u8 { | 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 | pub fn shrink(self: *Buffer, new_len: usize) void { | 98 | pub fn shrink(self: *Buffer, new_len: usize) void { |
lib/std/build.zig+3-5| ... | @@ -926,11 +926,9 @@ pub const Builder = struct { | ... | @@ -926,11 +926,9 @@ pub const Builder = struct { |
| 926 | 926 | ||
| 927 | try child.spawn(); | 927 | try child.spawn(); |
| 928 | 928 | ||
| 929 | var stdout = std.Buffer.initNull(self.allocator); | ||
| 930 | defer std.Buffer.deinit(&stdout); | ||
| 931 | |||
| 932 | var stdout_file_in_stream = child.stdout.?.inStream(); | 929 | var stdout_file_in_stream = child.stdout.?.inStream(); |
| 933 | try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); | 930 | const stdout = try stdout_file_in_stream.stream.readAllAlloc(self.allocator, max_output_size); |
| 931 | errdefer self.allocator.free(stdout); | ||
| 934 | 932 | ||
| 935 | const term = try child.wait(); | 933 | const term = try child.wait(); |
| 936 | switch (term) { | 934 | switch (term) { |
| ... | @@ -939,7 +937,7 @@ pub const Builder = struct { | ... | @@ -939,7 +937,7 @@ pub const Builder = struct { |
| 939 | out_code.* = @truncate(u8, code); | 937 | out_code.* = @truncate(u8, code); |
| 940 | return error.ExitCodeFailure; | 938 | return error.ExitCodeFailure; |
| 941 | } | 939 | } |
| 942 | return stdout.toOwnedSlice(); | 940 | return stdout; |
| 943 | }, | 941 | }, |
| 944 | .Signal, .Stopped, .Unknown => |code| { | 942 | .Signal, .Stopped, .Unknown => |code| { |
| 945 | out_code.* = @truncate(u8, code); | 943 | out_code.* = @truncate(u8, code); |
lib/std/build/run.zig+17-15| ... | @@ -9,7 +9,6 @@ const mem = std.mem; | ... | @@ -9,7 +9,6 @@ const mem = std.mem; |
| 9 | const process = std.process; | 9 | const process = std.process; |
| 10 | const ArrayList = std.ArrayList; | 10 | const ArrayList = std.ArrayList; |
| 11 | const BufMap = std.BufMap; | 11 | const BufMap = std.BufMap; |
| 12 | const Buffer = std.Buffer; | ||
| 13 | const warn = std.debug.warn; | 12 | const warn = std.debug.warn; |
| 14 | 13 | ||
| 15 | const max_stdout_size = 1 * 1024 * 1024; // 1 MiB | 14 | const max_stdout_size = 1 * 1024 * 1024; // 1 MiB |
| ... | @@ -169,23 +168,26 @@ pub const RunStep = struct { | ... | @@ -169,23 +168,26 @@ pub const RunStep = struct { |
| 169 | return err; | 168 | return err; |
| 170 | }; | 169 | }; |
| 171 | 170 | ||
| 172 | var stdout = Buffer.initNull(self.builder.allocator); | ||
| 173 | var stderr = Buffer.initNull(self.builder.allocator); | ||
| 174 | |||
| 175 | // TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O). | 171 | // TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O). |
| 176 | 172 | ||
| 173 | var stdout: ?[]const u8 = null; | ||
| 174 | defer if (stdout) |s| self.builder.allocator.free(s); | ||
| 175 | |||
| 177 | switch (self.stdout_action) { | 176 | switch (self.stdout_action) { |
| 178 | .expect_exact, .expect_matches => { | 177 | .expect_exact, .expect_matches => { |
| 179 | var stdout_file_in_stream = child.stdout.?.inStream(); | 178 | var stdout_file_in_stream = child.stdout.?.inStream(); |
| 180 | stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable; | 179 | stdout = stdout_file_in_stream.stream.readAllAlloc(self.builder.allocator, max_stdout_size) catch unreachable; |
| 181 | }, | 180 | }, |
| 182 | .inherit, .ignore => {}, | 181 | .inherit, .ignore => {}, |
| 183 | } | 182 | } |
| 184 | 183 | ||
| 185 | switch (self.stdout_action) { | 184 | var stderr: ?[]const u8 = null; |
| 185 | defer if (stderr) |s| self.builder.allocator.free(s); | ||
| 186 | |||
| 187 | switch (self.stderr_action) { | ||
| 186 | .expect_exact, .expect_matches => { | 188 | .expect_exact, .expect_matches => { |
| 187 | var stderr_file_in_stream = child.stderr.?.inStream(); | 189 | var stderr_file_in_stream = child.stderr.?.inStream(); |
| 188 | stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable; | 190 | stderr = stderr_file_in_stream.stream.readAllAlloc(self.builder.allocator, max_stdout_size) catch unreachable; |
| 189 | }, | 191 | }, |
| 190 | .inherit, .ignore => {}, | 192 | .inherit, .ignore => {}, |
| 191 | } | 193 | } |
| ... | @@ -216,7 +218,7 @@ pub const RunStep = struct { | ... | @@ -216,7 +218,7 @@ pub const RunStep = struct { |
| 216 | switch (self.stderr_action) { | 218 | switch (self.stderr_action) { |
| 217 | .inherit, .ignore => {}, | 219 | .inherit, .ignore => {}, |
| 218 | .expect_exact => |expected_bytes| { | 220 | .expect_exact => |expected_bytes| { |
| 219 | if (!mem.eql(u8, expected_bytes, stderr.toSliceConst())) { | 221 | if (!mem.eql(u8, expected_bytes, stderr.?)) { |
| 220 | warn( | 222 | warn( |
| 221 | \\ | 223 | \\ |
| 222 | \\========= Expected this stderr: ========= | 224 | \\========= Expected this stderr: ========= |
| ... | @@ -224,13 +226,13 @@ pub const RunStep = struct { | ... | @@ -224,13 +226,13 @@ pub const RunStep = struct { |
| 224 | \\========= But found: ==================== | 226 | \\========= But found: ==================== |
| 225 | \\{} | 227 | \\{} |
| 226 | \\ | 228 | \\ |
| 227 | , .{ expected_bytes, stderr.toSliceConst() }); | 229 | , .{ expected_bytes, stderr.? }); |
| 228 | printCmd(cwd, argv); | 230 | printCmd(cwd, argv); |
| 229 | return error.TestFailed; | 231 | return error.TestFailed; |
| 230 | } | 232 | } |
| 231 | }, | 233 | }, |
| 232 | .expect_matches => |matches| for (matches) |match| { | 234 | .expect_matches => |matches| for (matches) |match| { |
| 233 | if (mem.indexOf(u8, stderr.toSliceConst(), match) == null) { | 235 | if (mem.indexOf(u8, stderr.?, match) == null) { |
| 234 | warn( | 236 | warn( |
| 235 | \\ | 237 | \\ |
| 236 | \\========= Expected to find in stderr: ========= | 238 | \\========= Expected to find in stderr: ========= |
| ... | @@ -238,7 +240,7 @@ pub const RunStep = struct { | ... | @@ -238,7 +240,7 @@ pub const RunStep = struct { |
| 238 | \\========= But stderr does not contain it: ===== | 240 | \\========= But stderr does not contain it: ===== |
| 239 | \\{} | 241 | \\{} |
| 240 | \\ | 242 | \\ |
| 241 | , .{ match, stderr.toSliceConst() }); | 243 | , .{ match, stderr.? }); |
| 242 | printCmd(cwd, argv); | 244 | printCmd(cwd, argv); |
| 243 | return error.TestFailed; | 245 | return error.TestFailed; |
| 244 | } | 246 | } |
| ... | @@ -248,7 +250,7 @@ pub const RunStep = struct { | ... | @@ -248,7 +250,7 @@ pub const RunStep = struct { |
| 248 | switch (self.stdout_action) { | 250 | switch (self.stdout_action) { |
| 249 | .inherit, .ignore => {}, | 251 | .inherit, .ignore => {}, |
| 250 | .expect_exact => |expected_bytes| { | 252 | .expect_exact => |expected_bytes| { |
| 251 | if (!mem.eql(u8, expected_bytes, stdout.toSliceConst())) { | 253 | if (!mem.eql(u8, expected_bytes, stdout.?)) { |
| 252 | warn( | 254 | warn( |
| 253 | \\ | 255 | \\ |
| 254 | \\========= Expected this stdout: ========= | 256 | \\========= Expected this stdout: ========= |
| ... | @@ -256,13 +258,13 @@ pub const RunStep = struct { | ... | @@ -256,13 +258,13 @@ pub const RunStep = struct { |
| 256 | \\========= But found: ==================== | 258 | \\========= But found: ==================== |
| 257 | \\{} | 259 | \\{} |
| 258 | \\ | 260 | \\ |
| 259 | , .{ expected_bytes, stdout.toSliceConst() }); | 261 | , .{ expected_bytes, stdout.? }); |
| 260 | printCmd(cwd, argv); | 262 | printCmd(cwd, argv); |
| 261 | return error.TestFailed; | 263 | return error.TestFailed; |
| 262 | } | 264 | } |
| 263 | }, | 265 | }, |
| 264 | .expect_matches => |matches| for (matches) |match| { | 266 | .expect_matches => |matches| for (matches) |match| { |
| 265 | if (mem.indexOf(u8, stdout.toSliceConst(), match) == null) { | 267 | if (mem.indexOf(u8, stdout.?, match) == null) { |
| 266 | warn( | 268 | warn( |
| 267 | \\ | 269 | \\ |
| 268 | \\========= Expected to find in stdout: ========= | 270 | \\========= Expected to find in stdout: ========= |
| ... | @@ -270,7 +272,7 @@ pub const RunStep = struct { | ... | @@ -270,7 +272,7 @@ pub const RunStep = struct { |
| 270 | \\========= But stdout does not contain it: ===== | 272 | \\========= But stdout does not contain it: ===== |
| 271 | \\{} | 273 | \\{} |
| 272 | \\ | 274 | \\ |
| 273 | , .{ match, stdout.toSliceConst() }); | 275 | , .{ match, stdout.? }); |
| 274 | printCmd(cwd, argv); | 276 | printCmd(cwd, argv); |
| 275 | return error.TestFailed; | 277 | return error.TestFailed; |
| 276 | } | 278 | } |
lib/std/child_process.zig+7-9| ... | @@ -217,21 +217,19 @@ pub const ChildProcess = struct { | ... | @@ -217,21 +217,19 @@ pub const ChildProcess = struct { |
| 217 | 217 | ||
| 218 | try child.spawn(); | 218 | try child.spawn(); |
| 219 | 219 | ||
| 220 | var stdout = Buffer.initNull(args.allocator); | ||
| 221 | var stderr = Buffer.initNull(args.allocator); | ||
| 222 | defer Buffer.deinit(&stdout); | ||
| 223 | defer Buffer.deinit(&stderr); | ||
| 224 | |||
| 225 | var stdout_file_in_stream = child.stdout.?.inStream(); | 220 | var stdout_file_in_stream = child.stdout.?.inStream(); |
| 226 | var stderr_file_in_stream = child.stderr.?.inStream(); | 221 | var stderr_file_in_stream = child.stderr.?.inStream(); |
| 227 | 222 | ||
| 228 | try stdout_file_in_stream.stream.readAllBuffer(&stdout, args.max_output_bytes); | 223 | // TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O). |
| 229 | try stderr_file_in_stream.stream.readAllBuffer(&stderr, args.max_output_bytes); | 224 | const stdout = try stdout_file_in_stream.stream.readAllAlloc(args.allocator, args.max_output_bytes); |
| 225 | errdefer args.allocator.free(stdout); | ||
| 226 | const stderr = try stderr_file_in_stream.stream.readAllAlloc(args.allocator, args.max_output_bytes); | ||
| 227 | errdefer args.allocator.free(stderr); | ||
| 230 | 228 | ||
| 231 | return ExecResult{ | 229 | return ExecResult{ |
| 232 | .term = try child.wait(), | 230 | .term = try child.wait(), |
| 233 | .stdout = stdout.toOwnedSlice(), | 231 | .stdout = stdout, |
| 234 | .stderr = stderr.toOwnedSlice(), | 232 | .stderr = stderr, |
| 235 | }; | 233 | }; |
| 236 | } | 234 | } |
| 237 | 235 |
lib/std/fmt.zig+11-11| ... | @@ -1643,10 +1643,10 @@ test "hexToBytes" { | ... | @@ -1643,10 +1643,10 @@ test "hexToBytes" { |
| 1643 | test "formatIntValue with comptime_int" { | 1643 | test "formatIntValue with comptime_int" { |
| 1644 | const value: comptime_int = 123456789123456789; | 1644 | const value: comptime_int = 123456789123456789; |
| 1645 | 1645 | ||
| 1646 | var buf = try std.Buffer.init(std.testing.allocator, ""); | 1646 | var buf = std.ArrayList(u8).init(std.testing.allocator); |
| 1647 | defer buf.deinit(); | 1647 | defer buf.deinit(); |
| 1648 | try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append); | 1648 | try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice); |
| 1649 | std.testing.expect(mem.eql(u8, buf.toSlice(), "123456789123456789")); | 1649 | std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789")); |
| 1650 | } | 1650 | } |
| 1651 | 1651 | ||
| 1652 | test "formatType max_depth" { | 1652 | test "formatType max_depth" { |
| ... | @@ -1698,24 +1698,24 @@ test "formatType max_depth" { | ... | @@ -1698,24 +1698,24 @@ test "formatType max_depth" { |
| 1698 | inst.a = &inst; | 1698 | inst.a = &inst; |
| 1699 | inst.tu.ptr = &inst.tu; | 1699 | inst.tu.ptr = &inst.tu; |
| 1700 | 1700 | ||
| 1701 | var buf0 = try std.Buffer.init(std.testing.allocator, ""); | 1701 | var buf0 = std.ArrayList(u8).init(std.testing.allocator); |
| 1702 | defer buf0.deinit(); | 1702 | defer buf0.deinit(); |
| 1703 | try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0); | 1703 | try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0); |
| 1704 | std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }")); | 1704 | std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }")); |
| 1705 | 1705 | ||
| 1706 | var buf1 = try std.Buffer.init(std.testing.allocator, ""); | 1706 | var buf1 = std.ArrayList(u8).init(std.testing.allocator); |
| 1707 | defer buf1.deinit(); | 1707 | defer buf1.deinit(); |
| 1708 | try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1); | 1708 | try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1); |
| 1709 | std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); | 1709 | std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); |
| 1710 | 1710 | ||
| 1711 | var buf2 = try std.Buffer.init(std.testing.allocator, ""); | 1711 | var buf2 = std.ArrayList(u8).init(std.testing.allocator); |
| 1712 | defer buf2.deinit(); | 1712 | defer buf2.deinit(); |
| 1713 | try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2); | 1713 | try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2); |
| 1714 | std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); | 1714 | std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); |
| 1715 | 1715 | ||
| 1716 | var buf3 = try std.Buffer.init(std.testing.allocator, ""); | 1716 | var buf3 = std.ArrayList(u8).init(std.testing.allocator); |
| 1717 | defer buf3.deinit(); | 1717 | defer buf3.deinit(); |
| 1718 | try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3); | 1718 | try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3); |
| 1719 | std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); | 1719 | std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); |
| 1720 | } | 1720 | } |
| 1721 | 1721 |
lib/std/io/in_stream.zig+56-33| ... | @@ -41,10 +41,13 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -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 | /// Returns the number of bytes read. If the number read is smaller than buf.len, it | 47 | /// Returns the number of bytes read. If the number read is smaller than buf.len, it |
| 45 | /// means the stream reached the end. Reaching the end of a stream is not an error | 48 | /// means the stream reached the end. Reaching the end of a stream is not an error |
| 46 | /// condition. | 49 | /// condition. |
| 47 | pub fn readFull(self: *Self, buffer: []u8) Error!usize { | 50 | pub fn readAll(self: *Self, buffer: []u8) Error!usize { |
| 48 | var index: usize = 0; | 51 | var index: usize = 0; |
| 49 | while (index != buffer.len) { | 52 | while (index != buffer.len) { |
| 50 | const amt = try self.read(buffer[index..]); | 53 | const amt = try self.read(buffer[index..]); |
| ... | @@ -57,30 +60,43 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -57,30 +60,43 @@ pub fn InStream(comptime ReadError: type) type { |
| 57 | /// Returns the number of bytes read. If the number read would be smaller than buf.len, | 60 | /// Returns the number of bytes read. If the number read would be smaller than buf.len, |
| 58 | /// error.EndOfStream is returned instead. | 61 | /// error.EndOfStream is returned instead. |
| 59 | pub fn readNoEof(self: *Self, buf: []u8) !void { | 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 | if (amt_read < buf.len) return error.EndOfStream; | 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. | 67 | /// Deprecated: use `readAllArrayList`. |
| 65 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and | ||
| 66 | /// the contents read from the stream are lost. | ||
| 67 | pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void { | 68 | pub fn readAllBuffer(self: *Self, buffer: *Buffer, max_size: usize) !void { |
| 68 | try buffer.resize(0); | 69 | buffer.list.shrink(0); |
| 70 | try self.readAllArrayList(&buffer.list, max_size); | ||
| 71 | errdefer buffer.shrink(0); | ||
| 72 | try buffer.list.append(0); | ||
| 73 | } | ||
| 69 | 74 | ||
| 70 | 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; | ||
| 71 | while (true) { | 82 | while (true) { |
| 72 | const dest_slice = buffer.toSlice()[actual_buf_len..]; | 83 | array_list.expandToCapacity(); |
| 73 | const bytes_read = try self.readFull(dest_slice); | 84 | const dest_slice = array_list.span()[start_index..]; |
| 74 | actual_buf_len += bytes_read; | 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 | } | ||
| 75 | 92 | ||
| 76 | if (bytes_read != dest_slice.len) { | 93 | if (bytes_read != dest_slice.len) { |
| 77 | buffer.shrink(actual_buf_len); | 94 | array_list.shrink(start_index); |
| 78 | return; | 95 | return; |
| 79 | } | 96 | } |
| 80 | 97 | ||
| 81 | const new_buf_size = math.min(max_size, actual_buf_len + mem.page_size); | 98 | // This will trigger ArrayList to expand superlinearly at whatever its growth rate is. |
| 82 | if (new_buf_size == actual_buf_len) return error.StreamTooLong; | 99 | try array_list.ensureCapacity(start_index + 1); |
| 83 | try buffer.resize(new_buf_size); | ||
| 84 | } | 100 | } |
| 85 | } | 101 | } |
| 86 | 102 | ||
| ... | @@ -89,20 +105,23 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -89,20 +105,23 @@ pub fn InStream(comptime ReadError: type) type { |
| 89 | /// Caller owns returned memory. | 105 | /// Caller owns returned memory. |
| 90 | /// If this function returns an error, the contents from the stream read so far are lost. | 106 | /// If this function returns an error, the contents from the stream read so far are lost. |
| 91 | pub fn readAllAlloc(self: *Self, allocator: *mem.Allocator, max_size: usize) ![]u8 { | 107 | pub fn readAllAlloc(self: *Self, allocator: *mem.Allocator, max_size: usize) ![]u8 { |
| 92 | var buf = Buffer.initNull(allocator); | 108 | var array_list = std.ArrayList(u8).init(allocator); |
| 93 | defer buf.deinit(); | 109 | defer array_list.deinit(); |
| 94 | 110 | try self.readAllArrayList(&array_list, max_size); | |
| 95 | try self.readAllBuffer(&buf, max_size); | 111 | return array_list.toOwnedSlice(); |
| 96 | return buf.toOwnedSlice(); | ||
| 97 | } | 112 | } |
| 98 | 113 | ||
| 99 | /// Replaces `buffer` 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. |
| 100 | /// Does not include the delimiter in the result. | 115 | /// Does not include the delimiter in the result. |
| 101 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents | 116 | /// If the `std.ArrayList` length would exceed `max_size`, `error.StreamTooLong` is returned and the |
| 102 | /// read from the stream so far are lost. | 117 | /// `std.ArrayList` is populated with `max_size` bytes from the stream. |
| 103 | pub fn readUntilDelimiterBuffer(self: *Self, buffer: *Buffer, delimiter: u8, max_size: usize) !void { | 118 | pub fn readUntilDelimiterArrayList( |
| 104 | try buffer.resize(0); | 119 | self: *Self, |
| 105 | 120 | array_list: *std.ArrayList(u8), | |
| 121 | delimiter: u8, | ||
| 122 | max_size: usize, | ||
| 123 | ) !void { | ||
| 124 | array_list.shrink(0); | ||
| 106 | while (true) { | 125 | while (true) { |
| 107 | var byte: u8 = try self.readByte(); | 126 | var byte: u8 = try self.readByte(); |
| 108 | 127 | ||
| ... | @@ -110,11 +129,11 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -110,11 +129,11 @@ pub fn InStream(comptime ReadError: type) type { |
| 110 | return; | 129 | return; |
| 111 | } | 130 | } |
| 112 | 131 | ||
| 113 | if (buffer.len() == max_size) { | 132 | if (array_list.len == max_size) { |
| 114 | return error.StreamTooLong; | 133 | return error.StreamTooLong; |
| 115 | } | 134 | } |
| 116 | 135 | ||
| 117 | try buffer.appendByte(byte); | 136 | try array_list.append(byte); |
| 118 | } | 137 | } |
| 119 | } | 138 | } |
| 120 | 139 | ||
| ... | @@ -122,12 +141,16 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -122,12 +141,16 @@ pub fn InStream(comptime ReadError: type) type { |
| 122 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. | 141 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. |
| 123 | /// Caller owns returned memory. | 142 | /// Caller owns returned memory. |
| 124 | /// If this function returns an error, the contents from the stream read so far are lost. | 143 | /// If this function returns an error, the contents from the stream read so far are lost. |
| 125 | pub fn readUntilDelimiterAlloc(self: *Self, allocator: *mem.Allocator, delimiter: u8, max_size: usize) ![]u8 { | 144 | pub fn readUntilDelimiterAlloc( |
| 126 | var buf = Buffer.initNull(allocator); | 145 | self: *Self, |
| 127 | defer buf.deinit(); | 146 | allocator: *mem.Allocator, |
| 128 | 147 | delimiter: u8, | |
| 129 | try self.readUntilDelimiterBuffer(&buf, delimiter, max_size); | 148 | max_size: usize, |
| 130 | return buf.toOwnedSlice(); | 149 | ) ![]u8 { |
| 150 | var array_list = std.ArrayList(u8).init(allocator); | ||
| 151 | defer array_list.deinit(); | ||
| 152 | try self.readUntilDelimiterArrayList(&array_list, delimiter, max_size); | ||
| 153 | return array_list.toOwnedSlice(); | ||
| 131 | } | 154 | } |
| 132 | 155 | ||
| 133 | /// Reads from the stream until specified byte is found. If the buffer is not | 156 | /// Reads from the stream until specified byte is found. If the buffer is not |
lib/std/process.zig+9-10| ... | @@ -3,7 +3,6 @@ const builtin = std.builtin; | ... | @@ -3,7 +3,6 @@ const builtin = std.builtin; |
| 3 | const os = std.os; | 3 | const os = std.os; |
| 4 | const fs = std.fs; | 4 | const fs = std.fs; |
| 5 | const BufMap = std.BufMap; | 5 | const BufMap = std.BufMap; |
| 6 | const Buffer = std.Buffer; | ||
| 7 | const mem = std.mem; | 6 | const mem = std.mem; |
| 8 | const math = std.math; | 7 | const math = std.math; |
| 9 | const Allocator = mem.Allocator; | 8 | const Allocator = mem.Allocator; |
| ... | @@ -266,7 +265,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -266,7 +265,7 @@ pub const ArgIteratorWindows = struct { |
| 266 | } | 265 | } |
| 267 | 266 | ||
| 268 | fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![]u8 { | 267 | fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![]u8 { |
| 269 | var buf = try Buffer.initSize(allocator, 0); | 268 | var buf = std.ArrayList(u8).init(allocator); |
| 270 | defer buf.deinit(); | 269 | defer buf.deinit(); |
| 271 | 270 | ||
| 272 | var backslash_count: usize = 0; | 271 | var backslash_count: usize = 0; |
| ... | @@ -282,10 +281,10 @@ pub const ArgIteratorWindows = struct { | ... | @@ -282,10 +281,10 @@ pub const ArgIteratorWindows = struct { |
| 282 | if (quote_is_real) { | 281 | if (quote_is_real) { |
| 283 | self.seen_quote_count += 1; | 282 | self.seen_quote_count += 1; |
| 284 | if (self.seen_quote_count == self.quote_count and self.seen_quote_count % 2 == 1) { | 283 | if (self.seen_quote_count == self.quote_count and self.seen_quote_count % 2 == 1) { |
| 285 | try buf.appendByte('"'); | 284 | try buf.append('"'); |
| 286 | } | 285 | } |
| 287 | } else { | 286 | } else { |
| 288 | try buf.appendByte('"'); | 287 | try buf.append('"'); |
| 289 | } | 288 | } |
| 290 | }, | 289 | }, |
| 291 | '\\' => { | 290 | '\\' => { |
| ... | @@ -295,7 +294,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -295,7 +294,7 @@ pub const ArgIteratorWindows = struct { |
| 295 | try self.emitBackslashes(&buf, backslash_count); | 294 | try self.emitBackslashes(&buf, backslash_count); |
| 296 | backslash_count = 0; | 295 | backslash_count = 0; |
| 297 | if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) { | 296 | if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) { |
| 298 | try buf.appendByte(byte); | 297 | try buf.append(byte); |
| 299 | } else { | 298 | } else { |
| 300 | return buf.toOwnedSlice(); | 299 | return buf.toOwnedSlice(); |
| 301 | } | 300 | } |
| ... | @@ -303,16 +302,16 @@ pub const ArgIteratorWindows = struct { | ... | @@ -303,16 +302,16 @@ pub const ArgIteratorWindows = struct { |
| 303 | else => { | 302 | else => { |
| 304 | try self.emitBackslashes(&buf, backslash_count); | 303 | try self.emitBackslashes(&buf, backslash_count); |
| 305 | backslash_count = 0; | 304 | backslash_count = 0; |
| 306 | try buf.appendByte(byte); | 305 | try buf.append(byte); |
| 307 | }, | 306 | }, |
| 308 | } | 307 | } |
| 309 | } | 308 | } |
| 310 | } | 309 | } |
| 311 | 310 | ||
| 312 | fn emitBackslashes(self: *ArgIteratorWindows, buf: *Buffer, emit_count: usize) !void { | 311 | fn emitBackslashes(self: *ArgIteratorWindows, buf: *std.ArrayList(u8), emit_count: usize) !void { |
| 313 | var i: usize = 0; | 312 | var i: usize = 0; |
| 314 | while (i < emit_count) : (i += 1) { | 313 | while (i < emit_count) : (i += 1) { |
| 315 | try buf.appendByte('\\'); | 314 | try buf.append('\\'); |
| 316 | } | 315 | } |
| 317 | } | 316 | } |
| 318 | 317 | ||
| ... | @@ -410,7 +409,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { | ... | @@ -410,7 +409,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { |
| 410 | 409 | ||
| 411 | // TODO refactor to only make 1 allocation. | 410 | // TODO refactor to only make 1 allocation. |
| 412 | var it = args(); | 411 | var it = args(); |
| 413 | var contents = try Buffer.initSize(allocator, 0); | 412 | var contents = std.ArrayList(u8).init(allocator); |
| 414 | defer contents.deinit(); | 413 | defer contents.deinit(); |
| 415 | 414 | ||
| 416 | var slice_list = std.ArrayList(usize).init(allocator); | 415 | var slice_list = std.ArrayList(usize).init(allocator); |
| ... | @@ -419,7 +418,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { | ... | @@ -419,7 +418,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { |
| 419 | while (it.next(allocator)) |arg_or_err| { | 418 | while (it.next(allocator)) |arg_or_err| { |
| 420 | const arg = try arg_or_err; | 419 | const arg = try arg_or_err; |
| 421 | defer allocator.free(arg); | 420 | defer allocator.free(arg); |
| 422 | try contents.append(arg); | 421 | try contents.appendSlice(arg); |
| 423 | try slice_list.append(arg.len); | 422 | try slice_list.append(arg.len); |
| 424 | } | 423 | } |
| 425 | 424 |
src-self-hosted/main.zig-1| ... | @@ -9,7 +9,6 @@ const mem = std.mem; | ... | @@ -9,7 +9,6 @@ const mem = std.mem; |
| 9 | const process = std.process; | 9 | const process = std.process; |
| 10 | const Allocator = mem.Allocator; | 10 | const Allocator = mem.Allocator; |
| 11 | const ArrayList = std.ArrayList; | 11 | const ArrayList = std.ArrayList; |
| 12 | const Buffer = std.Buffer; | ||
| 13 | 12 | ||
| 14 | const c = @import("c.zig"); | 13 | const c = @import("c.zig"); |
| 15 | const introspect = @import("introspect.zig"); | 14 | const introspect = @import("introspect.zig"); |
test/tests.zig+6-10| ... | @@ -566,14 +566,13 @@ pub const StackTracesContext = struct { | ... | @@ -566,14 +566,13 @@ pub const StackTracesContext = struct { |
| 566 | } | 566 | } |
| 567 | child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) }); | 567 | child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) }); |
| 568 | 568 | ||
| 569 | var stdout = Buffer.initNull(b.allocator); | ||
| 570 | var stderr = Buffer.initNull(b.allocator); | ||
| 571 | |||
| 572 | var stdout_file_in_stream = child.stdout.?.inStream(); | 569 | var stdout_file_in_stream = child.stdout.?.inStream(); |
| 573 | var stderr_file_in_stream = child.stderr.?.inStream(); | 570 | var stderr_file_in_stream = child.stderr.?.inStream(); |
| 574 | 571 | ||
| 575 | stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable; | 572 | const stdout = stdout_file_in_stream.stream.readAllAlloc(b.allocator, max_stdout_size) catch unreachable; |
| 576 | stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable; | 573 | defer b.allocator.free(stdout); |
| 574 | const stderr = stderr_file_in_stream.stream.readAllAlloc(b.allocator, max_stdout_size) catch unreachable; | ||
| 575 | defer b.allocator.free(stderr); | ||
| 577 | 576 | ||
| 578 | const term = child.wait() catch |err| { | 577 | const term = child.wait() catch |err| { |
| 579 | debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) }); | 578 | debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) }); |
| ... | @@ -616,11 +615,8 @@ pub const StackTracesContext = struct { | ... | @@ -616,11 +615,8 @@ pub const StackTracesContext = struct { |
| 616 | const got: []const u8 = got_result: { | 615 | const got: []const u8 = got_result: { |
| 617 | var buf = try Buffer.initSize(b.allocator, 0); | 616 | var buf = try Buffer.initSize(b.allocator, 0); |
| 618 | defer buf.deinit(); | 617 | defer buf.deinit(); |
| 619 | const bytes = if (stderr.endsWith("\n")) | 618 | if (stderr.len != 0 and stderr[stderr.len - 1] == '\n') stderr = stderr[0 .. stderr.len - 1]; |
| 620 | stderr.toSliceConst()[0 .. stderr.len() - 1] | 619 | var it = mem.separate(stderr, "\n"); |
| 621 | else | ||
| 622 | stderr.toSliceConst()[0..stderr.len()]; | ||
| 623 | var it = mem.separate(bytes, "\n"); | ||
| 624 | process_lines: while (it.next()) |line| { | 620 | process_lines: while (it.next()) |line| { |
| 625 | if (line.len == 0) continue; | 621 | if (line.len == 0) continue; |
| 626 | const delims = [_][]const u8{ ":", ":", ":", " in " }; | 622 | const delims = [_][]const u8{ ":", ":", ":", " in " }; |