authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-06 18:01:20-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-06 18:49:13-05:00
log231a4b8fde6ff061198c76d02990a471ec48c977
tree1fd5c25caa7321898f45c45e6a42f6623b94c760
parent4114b63d751cd00ea759f4c0de8568efff58e945
signaturelock-open Commit is signed but in an unrecognized format.

fixups & make some API decisions

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.readUntilDelimiterArrayList

4 files changed, 114 insertions(+), 107 deletions(-)

lib/std/array_list.zig+48-49
......@@ -5,10 +5,8 @@ const testing = std.testing;
55const mem = std.mem;
66const Allocator = mem.Allocator;
77
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`.
1210pub fn ArrayList(comptime T: type) type {
1311 return AlignedArrayList(T, null);
1412}
......@@ -22,7 +20,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
2220 return struct {
2321 const Self = @This();
2422
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
2624 /// specify the end position of the slice, this will potentially give
2725 /// you uninitialized memory.
2826 items: Slice,
......@@ -56,34 +54,37 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
5654
5755 /// Return contents as a slice. Only valid while the list
5856 /// doesn't change size.
59 pub fn toSlice(self: Self) Slice {
57 pub fn span(self: var) @TypeOf(self.items[0..self.len]) {
6058 return self.items[0..self.len];
6159 }
6260
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`.
6567 pub fn toSliceConst(self: Self) SliceConst {
66 return self.items[0..self.len];
68 return self.span();
6769 }
6870
69 /// Safely access index i of the list.
71 /// Deprecated: use `span()[i]`.
7072 pub fn at(self: Self, i: usize) T {
71 return self.toSliceConst()[i];
73 return self.span()[i];
7274 }
7375
74 /// Safely access ptr to index i of the list.
76 /// Deprecated: use `&span()[i]`.
7577 pub fn ptrAt(self: Self, i: usize) *T {
76 return &self.toSlice()[i];
78 return &self.span()[i];
7779 }
7880
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`.
8182 pub fn setOrError(self: Self, i: usize, item: T) !void {
8283 if (i >= self.len) return error.OutOfBounds;
8384 self.items[i] = item;
8485 }
8586
86 /// Sets the value at index `i`, asserting that the value is in range.
87 /// Deprecated: use `list.span()[i] = item`.
8788 pub fn set(self: *Self, i: usize, item: T) void {
8889 assert(i < self.len);
8990 self.items[i] = item;
......@@ -124,18 +125,18 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
124125 self.items[n] = item;
125126 }
126127
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 {
130132 try self.ensureCapacity(self.len + items.len);
131133 self.len += items.len;
132134
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);
135137 }
136138
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.
139140 pub fn append(self: *Self, item: T) !void {
140141 const new_item_ptr = try self.addOne();
141142 new_item_ptr.* = item;
......@@ -148,8 +149,9 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
148149 new_item_ptr.* = item;
149150 }
150151
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).
153155 pub fn orderedRemove(self: *Self, i: usize) T {
154156 const newlen = self.len - 1;
155157 if (newlen == i) return self.pop();
......@@ -163,18 +165,17 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
163165
164166 /// Removes the element at the specified index and returns it.
165167 /// The empty slot is filled from the end of the list.
168 /// This operation is O(1).
166169 pub fn swapRemove(self: *Self, i: usize) T {
167170 if (self.len - 1 == i) return self.pop();
168171
169 const slice = self.toSlice();
172 const slice = self.span();
170173 const old_item = slice[i];
171174 slice[i] = self.pop();
172175 return old_item;
173176 }
174177
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)`.
178179 pub fn swapRemoveOrError(self: *Self, i: usize) !T {
179180 if (i >= self.len) return error.OutOfBounds;
180181 return self.swapRemove(i);
......@@ -204,6 +205,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
204205 }
205206
206207 /// Reduce allocated capacity to `new_len`.
208 /// Invalidates element pointers.
207209 pub fn shrink(self: *Self, new_len: usize) void {
208210 assert(new_len <= self.len);
209211 self.len = new_len;
......@@ -222,13 +224,24 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
222224 self.items = try self.allocator.realloc(self.items, better_capacity);
223225 }
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
225234 /// Increase length by 1, returning pointer to the new item.
235 /// The returned pointer becomes invalid when the list is resized.
226236 pub fn addOne(self: *Self) !*T {
227237 const new_length = self.len + 1;
228238 try self.ensureCapacity(new_length);
229239 return self.addOneAssumeCapacity();
230240 }
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.
232245 pub fn addOneAssumeCapacity(self: *Self) *T {
233246 assert(self.len < self.capacity());
234247 const result = &self.items[self.len];
......@@ -236,33 +249,19 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
236249 return result;
237250 }
238251
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.
241254 pub fn pop(self: *Self) T {
242255 self.len -= 1;
243256 return self.items[self.len];
244257 }
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`.
247261 pub fn popOrNull(self: *Self) ?T {
248262 if (self.len == 0) return null;
249263 return self.pop();
250264 }
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 }
266265 };
267266}
268267
......@@ -302,7 +301,7 @@ test "std.ArrayList.basic" {
302301 }
303302 }
304303
305 for (list.toSlice()) |v, i| {
304 for (list.span()) |v, i| {
306305 testing.expect(v == @intCast(i32, i + 1));
307306 }
308307
......@@ -340,7 +339,7 @@ test "std.ArrayList.appendNTimes" {
340339
341340 try list.appendNTimes(2, 10);
342341 testing.expectEqual(@as(usize, 10), list.len);
343 for (list.toSlice()) |element| {
342 for (list.span()) |element| {
344343 testing.expectEqual(@as(i32, 2), element);
345344 }
346345}
lib/std/buffer.zig+9-3
......@@ -81,12 +81,18 @@ pub const Buffer = struct {
8181 self.list.deinit();
8282 }
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`
8489 pub fn toSlice(self: Buffer) [:0]u8 {
85 return self.list.toSlice()[0..self.len() :0];
90 return self.span();
8691 }
8792
93 /// Deprecated: use `span`
8894 pub fn toSliceConst(self: Buffer) [:0]const u8 {
89 return self.list.toSliceConst()[0..self.len() :0];
95 return self.span();
9096 }
9197
9298 pub fn shrink(self: *Buffer, new_len: usize) void {
......@@ -133,7 +139,7 @@ pub const Buffer = struct {
133139
134140 pub fn startsWith(self: Buffer, m: []const u8) bool {
135141 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);
137143 }
138144
139145 pub fn endsWith(self: Buffer, m: []const u8) bool {
lib/std/build/run.zig+14-18
......@@ -170,7 +170,9 @@ pub const RunStep = struct {
170170
171171 // TODO need to poll to read these streams to prevent a deadlock (or rely on evented I/O).
172172
173 var stdout: []const u8 = undefined;
173 var stdout: ?[]const u8 = null;
174 defer if (stdout) |s| self.builder.allocator.free(s);
175
174176 switch (self.stdout_action) {
175177 .expect_exact, .expect_matches => {
176178 var stdout_file_in_stream = child.stdout.?.inStream();
......@@ -178,12 +180,10 @@ pub const RunStep = struct {
178180 },
179181 .inherit, .ignore => {},
180182 }
181 defer switch (self.stdout_action) {
182 .expect_exact, .expect_matches => self.builder.allocator.free(stdout),
183 .inherit, .ignore => {},
184 };
185183
186 var stderr: []const u8 = undefined;
184 var stderr: ?[]const u8 = null;
185 defer if (stderr) |s| self.builder.allocator.free(s);
186
187187 switch (self.stderr_action) {
188188 .expect_exact, .expect_matches => {
189189 var stderr_file_in_stream = child.stderr.?.inStream();
......@@ -191,10 +191,6 @@ pub const RunStep = struct {
191191 },
192192 .inherit, .ignore => {},
193193 }
194 defer switch (self.stderr_action) {
195 .expect_exact, .expect_matches => self.builder.allocator.free(stderr),
196 .inherit, .ignore => {},
197 };
198194
199195 const term = child.wait() catch |err| {
200196 warn("Unable to spawn {}: {}\n", .{ argv[0], @errorName(err) });
......@@ -222,7 +218,7 @@ pub const RunStep = struct {
222218 switch (self.stderr_action) {
223219 .inherit, .ignore => {},
224220 .expect_exact => |expected_bytes| {
225 if (!mem.eql(u8, expected_bytes, stderr)) {
221 if (!mem.eql(u8, expected_bytes, stderr.?)) {
226222 warn(
227223 \\
228224 \\========= Expected this stderr: =========
......@@ -230,13 +226,13 @@ pub const RunStep = struct {
230226 \\========= But found: ====================
231227 \\{}
232228 \\
233 , .{ expected_bytes, stderr });
229 , .{ expected_bytes, stderr.? });
234230 printCmd(cwd, argv);
235231 return error.TestFailed;
236232 }
237233 },
238234 .expect_matches => |matches| for (matches) |match| {
239 if (mem.indexOf(u8, stderr, match) == null) {
235 if (mem.indexOf(u8, stderr.?, match) == null) {
240236 warn(
241237 \\
242238 \\========= Expected to find in stderr: =========
......@@ -244,7 +240,7 @@ pub const RunStep = struct {
244240 \\========= But stderr does not contain it: =====
245241 \\{}
246242 \\
247 , .{ match, stderr });
243 , .{ match, stderr.? });
248244 printCmd(cwd, argv);
249245 return error.TestFailed;
250246 }
......@@ -254,7 +250,7 @@ pub const RunStep = struct {
254250 switch (self.stdout_action) {
255251 .inherit, .ignore => {},
256252 .expect_exact => |expected_bytes| {
257 if (!mem.eql(u8, expected_bytes, stdout)) {
253 if (!mem.eql(u8, expected_bytes, stdout.?)) {
258254 warn(
259255 \\
260256 \\========= Expected this stdout: =========
......@@ -262,13 +258,13 @@ pub const RunStep = struct {
262258 \\========= But found: ====================
263259 \\{}
264260 \\
265 , .{ expected_bytes, stdout });
261 , .{ expected_bytes, stdout.? });
266262 printCmd(cwd, argv);
267263 return error.TestFailed;
268264 }
269265 },
270266 .expect_matches => |matches| for (matches) |match| {
271 if (mem.indexOf(u8, stdout, match) == null) {
267 if (mem.indexOf(u8, stdout.?, match) == null) {
272268 warn(
273269 \\
274270 \\========= Expected to find in stdout: =========
......@@ -276,7 +272,7 @@ pub const RunStep = struct {
276272 \\========= But stdout does not contain it: =====
277273 \\{}
278274 \\
279 , .{ match, stdout });
275 , .{ match, stdout.? });
280276 printCmd(cwd, argv);
281277 return error.TestFailed;
282278 }
lib/std/io/in_stream.zig+43-37
......@@ -41,10 +41,13 @@ pub fn InStream(comptime ReadError: type) type {
4141 }
4242 }
4343
44 /// Deprecated: use `readAll`.
45 pub const readFull = readAll;
46
4447 /// Returns the number of bytes read. If the number read is smaller than buf.len, it
4548 /// means the stream reached the end. Reaching the end of a stream is not an error
4649 /// condition.
47 pub fn readFull(self: *Self, buffer: []u8) Error!usize {
50 pub fn readAll(self: *Self, buffer: []u8) Error!usize {
4851 var index: usize = 0;
4952 while (index != buffer.len) {
5053 const amt = try self.read(buffer[index..]);
......@@ -57,39 +60,43 @@ pub fn InStream(comptime ReadError: type) type {
5760 /// Returns the number of bytes read. If the number read would be smaller than buf.len,
5861 /// error.EndOfStream is returned instead.
5962 pub fn readNoEof(self: *Self, buf: []u8) !void {
60 const amt_read = try self.readFull(buf);
63 const amt_read = try self.readAll(buf);
6164 if (amt_read < buf.len) return error.EndOfStream;
6265 }
6366
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`.
6768 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);
7170 try self.readAllArrayList(&buffer.list, max_size);
71 errdefer buffer.shrink(0);
7272 try buffer.list.append(0);
7373 }
7474
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;
8082 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 }
8492
8593 if (bytes_read != dest_slice.len) {
86 array_list.shrink(actual_buf_len);
94 array_list.shrink(start_index);
8795 return;
8896 }
8997
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);
93100 }
94101 }
95102
......@@ -104,23 +111,17 @@ pub fn InStream(comptime ReadError: type) type {
104111 return array_list.toOwnedSlice();
105112 }
106113
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.
120115 /// 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);
124125 while (true) {
125126 var byte: u8 = try self.readByte();
126127
......@@ -140,7 +141,12 @@ pub fn InStream(comptime ReadError: type) type {
140141 /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
141142 /// Caller owns returned memory.
142143 /// 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 {
144150 var array_list = std.ArrayList(u8).init(allocator);
145151 defer array_list.deinit();
146152 try self.readUntilDelimiterArrayList(&array_list, delimiter, max_size);