authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-06 18:49:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-06 18:49:26-05:00
log7f975bf09f4e6e81d68c9a573ac2e31b997b5816
tree1fd5c25caa7321898f45c45e6a42f6623b94c760
parentfa46bcb36864e6616ce4449965063f3b8720f8e1
parent231a4b8fde6ff061198c76d02990a471ec48c977
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'daurnimator-less-buffer'

Closes #4405 Closes #4656

11 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;
6const warn = std.debug.warn;6const warn = std.debug.warn;
7const mem = std.mem;7const mem = std.mem;
8const ArrayList = std.ArrayList;8const ArrayList = std.ArrayList;
9const Buffer = std.Buffer;
10const io = std.io;9const io = std.io;
11const fs = std.fs;10const fs = std.fs;
12const InstallDirectoryOptions = std.build.InstallDirectoryOptions;11const 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;
5const mem = std.mem;5const mem = std.mem;
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
77
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`.
12pub fn ArrayList(comptime T: type) type {10pub 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();
2422
25 /// Use toSlice instead of slicing this directly, because if you don't23 /// Use `span` instead of slicing this directly, because if you don't
26 /// specify the end position of the slice, this will potentially give24 /// 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 {
5654
57 /// Return contents as a slice. Only valid while the list55 /// 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 }
6260
63 /// Return list as const slice. Only valid while the list61 /// 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 }
6870
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 }
7375
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 }
7880
79 /// Sets the value at index `i`, or returns `error.OutOfBounds` if81 /// 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 }
8586
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 }
126127
127 /// Insert slice `items` at index `n`. Moves128 /// 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;
132134
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 }
136138
137 /// Extend the list by 1 element. Allocates more memory as139 /// 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 }
150151
151 /// Remove the element at index `i` from the list and return152 /// 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 {
163165
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();
168171
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 }
174177
175 /// Removes the element at the specified index and returns it178 /// 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 }
205206
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 }
224226
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 }
231241
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 }
238251
239 /// Remove and return the last element from the list. Asserts252 /// 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 }
245258
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 }
289303
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 }
293307
...@@ -325,7 +339,7 @@ test "std.ArrayList.appendNTimes" {...@@ -325,7 +339,7 @@ test "std.ArrayList.appendNTimes" {
325339
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 }
8383
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 }
8792
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 }
9197
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 {
926926
927 try child.spawn();927 try child.spawn();
928928
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);
934932
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;
9const process = std.process;9const process = std.process;
10const ArrayList = std.ArrayList;10const ArrayList = std.ArrayList;
11const BufMap = std.BufMap;11const BufMap = std.BufMap;
12const Buffer = std.Buffer;
13const warn = std.debug.warn;12const warn = std.debug.warn;
1413
15const max_stdout_size = 1 * 1024 * 1024; // 1 MiB14const 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 };
171170
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).
176172
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 }
184183
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 {
217217
218 try child.spawn();218 try child.spawn();
219219
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();
227222
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);
230228
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 }
237235
lib/std/fmt.zig+11-11
...@@ -1643,10 +1643,10 @@ test "hexToBytes" {...@@ -1643,10 +1643,10 @@ test "hexToBytes" {
1643test "formatIntValue with comptime_int" {1643test "formatIntValue with comptime_int" {
1644 const value: comptime_int = 123456789123456789;1644 const value: comptime_int = 123456789123456789;
16451645
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}
16511651
1652test "formatType max_depth" {1652test "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;
17001700
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{ ... }"));
17051705
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) }"));
17101710
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) }"));
17151715
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}
17211721
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 }
4343
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, it47 /// 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 error48 /// 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 }
6366
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 }
6974
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 }
7592
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 }
8097
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 }
86102
...@@ -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();
94110 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 }
98113
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 contents116 /// 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,
105120 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();
108127
...@@ -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 }
112131
113 if (buffer.len() == max_size) {132 if (array_list.len == max_size) {
114 return error.StreamTooLong;133 return error.StreamTooLong;
115 }134 }
116135
117 try buffer.appendByte(byte);136 try array_list.append(byte);
118 }137 }
119 }138 }
120139
...@@ -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,
128147 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 }
132155
133 /// Reads from the stream until specified byte is found. If the buffer is not156 /// 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;
3const os = std.os;3const os = std.os;
4const fs = std.fs;4const fs = std.fs;
5const BufMap = std.BufMap;5const BufMap = std.BufMap;
6const Buffer = std.Buffer;
7const mem = std.mem;6const mem = std.mem;
8const math = std.math;7const math = std.math;
9const Allocator = mem.Allocator;8const Allocator = mem.Allocator;
...@@ -266,7 +265,7 @@ pub const ArgIteratorWindows = struct {...@@ -266,7 +265,7 @@ pub const ArgIteratorWindows = struct {
266 }265 }
267266
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();
271270
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 }
311310
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 }
318317
...@@ -410,7 +409,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {...@@ -410,7 +409,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
410409
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();
415414
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 }
425424
src-self-hosted/main.zig-1
...@@ -9,7 +9,6 @@ const mem = std.mem;...@@ -9,7 +9,6 @@ const mem = std.mem;
9const process = std.process;9const process = std.process;
10const Allocator = mem.Allocator;10const Allocator = mem.Allocator;
11const ArrayList = std.ArrayList;11const ArrayList = std.ArrayList;
12const Buffer = std.Buffer;
1312
14const c = @import("c.zig");13const c = @import("c.zig");
15const introspect = @import("introspect.zig");14const 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) });
568568
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();
574571
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);
577576
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 " };