authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-24 10:59:37+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-12-24 10:59:37+02:00
log83646df2cce59f254822355ec1ceeb6884e1177e
tree3266d030c2d6e5da949f74840afa5f47a72b2bb3
parent0fd68f49e2eabb866ea1d21c4657c2a1d3c8ce53
parente79acc24d301bd4d6afe715ce1e6be9dc3c654b5
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7531 from Vexu/orphanage

Move ArrayListSentineled to std lib orphanage

11 files changed, 171 insertions(+), 330 deletions(-)

lib/std/array_list.zig+38
......@@ -91,6 +91,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
9191 return result;
9292 }
9393
94 /// The caller owns the returned memory. ArrayList becomes empty.
95 pub fn toOwnedSliceSentinel(self: *Self, comptime sentinel: T) ![:sentinel]T {
96 try self.append(sentinel);
97 const result = self.toOwnedSlice();
98 return result[0 .. result.len - 1 :sentinel];
99 }
100
94101 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.
95102 /// This operation is O(N).
96103 pub fn insert(self: *Self, n: usize, item: T) !void {
......@@ -389,6 +396,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
389396 return result;
390397 }
391398
399 /// The caller owns the returned memory. ArrayList becomes empty.
400 pub fn toOwnedSliceSentinel(self: *Self, allocator: *Allocator, comptime sentinel: T) ![:sentinel]T {
401 try self.append(allocator, sentinel);
402 const result = self.toOwnedSlice(allocator);
403 return result[0 .. result.len - 1 :sentinel];
404 }
405
392406 /// Insert `item` at index `n`. Moves `list[n .. list.len]`
393407 /// to make room.
394408 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {
......@@ -1121,3 +1135,27 @@ test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
11211135 testing.expectEqualSlices(u8, list.items, "aoeuasdf");
11221136 }
11231137}
1138
1139test "std.ArrayList/ArrayListUnmanaged.toOwnedSliceSentinel" {
1140 const a = testing.allocator;
1141 {
1142 var list = ArrayList(u8).init(a);
1143 defer list.deinit();
1144
1145 try list.appendSlice("foobar");
1146
1147 const result = try list.toOwnedSliceSentinel(0);
1148 defer a.free(result);
1149 testing.expectEqualStrings(result, mem.spanZ(result.ptr));
1150 }
1151 {
1152 var list = ArrayListUnmanaged(u8){};
1153 defer list.deinit(a);
1154
1155 try list.appendSlice(a, "foobar");
1156
1157 const result = try list.toOwnedSliceSentinel(a, 0);
1158 defer a.free(result);
1159 testing.expectEqualStrings(result, mem.spanZ(result.ptr));
1160 }
1161}
lib/std/array_list_sentineled.zig deleted-229
......@@ -1,229 +0,0 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6const std = @import("std.zig");
7const debug = std.debug;
8const mem = std.mem;
9const Allocator = mem.Allocator;
10const assert = debug.assert;
11const testing = std.testing;
12const ArrayList = std.ArrayList;
13
14/// A contiguous, growable list of items in memory, with a sentinel after them.
15/// The sentinel is maintained when appending, resizing, etc.
16/// If you do not need a sentinel, consider using `ArrayList` instead.
17pub fn ArrayListSentineled(comptime T: type, comptime sentinel: T) type {
18 return struct {
19 list: ArrayList(T),
20
21 const Self = @This();
22
23 /// Must deinitialize with deinit.
24 pub fn init(allocator: *Allocator, m: []const T) !Self {
25 var self = try initSize(allocator, m.len);
26 mem.copy(T, self.list.items, m);
27 return self;
28 }
29
30 /// Initialize memory to size bytes of undefined values.
31 /// Must deinitialize with deinit.
32 pub fn initSize(allocator: *Allocator, size: usize) !Self {
33 var self = initNull(allocator);
34 try self.resize(size);
35 return self;
36 }
37
38 /// Initialize with capacity to hold at least num bytes.
39 /// Must deinitialize with deinit.
40 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
41 var self = Self{ .list = try ArrayList(T).initCapacity(allocator, num + 1) };
42 self.list.appendAssumeCapacity(sentinel);
43 return self;
44 }
45
46 /// Must deinitialize with deinit.
47 /// None of the other operations are valid until you do one of these:
48 /// * `replaceContents`
49 /// * `resize`
50 pub fn initNull(allocator: *Allocator) Self {
51 return Self{ .list = ArrayList(T).init(allocator) };
52 }
53
54 /// Must deinitialize with deinit.
55 pub fn initFromBuffer(buffer: Self) !Self {
56 return Self.init(buffer.list.allocator, buffer.span());
57 }
58
59 /// Takes ownership of the passed in slice. The slice must have been
60 /// allocated with `allocator`.
61 /// Must deinitialize with deinit.
62 pub fn fromOwnedSlice(allocator: *Allocator, slice: []T) !Self {
63 var self = Self{ .list = ArrayList(T).fromOwnedSlice(allocator, slice) };
64 try self.list.append(sentinel);
65 return self;
66 }
67
68 /// The caller owns the returned memory. The list becomes null and is safe to `deinit`.
69 pub fn toOwnedSlice(self: *Self) [:sentinel]T {
70 const allocator = self.list.allocator;
71 const result = self.list.toOwnedSlice();
72 self.* = initNull(allocator);
73 return result[0 .. result.len - 1 :sentinel];
74 }
75
76 /// Only works when `T` is `u8`.
77 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: anytype) !Self {
78 const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) {
79 error.Overflow => return error.OutOfMemory,
80 };
81 var self = try Self.initSize(allocator, size);
82 assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
83 return self;
84 }
85
86 pub fn deinit(self: *Self) void {
87 self.list.deinit();
88 }
89
90 pub fn span(self: anytype) @TypeOf(self.list.items[0..:sentinel]) {
91 return self.list.items[0..self.len() :sentinel];
92 }
93
94 pub fn shrink(self: *Self, new_len: usize) void {
95 assert(new_len <= self.len());
96 self.list.shrink(new_len + 1);
97 self.list.items[self.len()] = sentinel;
98 }
99
100 pub fn resize(self: *Self, new_len: usize) !void {
101 try self.list.resize(new_len + 1);
102 self.list.items[self.len()] = sentinel;
103 }
104
105 pub fn isNull(self: Self) bool {
106 return self.list.items.len == 0;
107 }
108
109 pub fn len(self: Self) usize {
110 return self.list.items.len - 1;
111 }
112
113 pub fn capacity(self: Self) usize {
114 return if (self.list.capacity > 0)
115 self.list.capacity - 1
116 else
117 0;
118 }
119
120 pub fn appendSlice(self: *Self, m: []const T) !void {
121 const old_len = self.len();
122 try self.resize(old_len + m.len);
123 mem.copy(T, self.list.items[old_len..], m);
124 }
125
126 pub fn append(self: *Self, byte: T) !void {
127 const old_len = self.len();
128 try self.resize(old_len + 1);
129 self.list.items[old_len] = byte;
130 }
131
132 pub fn eql(self: Self, m: []const T) bool {
133 return mem.eql(T, self.span(), m);
134 }
135
136 pub fn startsWith(self: Self, m: []const T) bool {
137 if (self.len() < m.len) return false;
138 return mem.eql(T, self.list.items[0..m.len], m);
139 }
140
141 pub fn endsWith(self: Self, m: []const T) bool {
142 const l = self.len();
143 if (l < m.len) return false;
144 const start = l - m.len;
145 return mem.eql(T, self.list.items[start..l], m);
146 }
147
148 pub fn replaceContents(self: *Self, m: []const T) !void {
149 try self.resize(m.len);
150 mem.copy(T, self.list.items, m);
151 }
152
153 /// Initializes an OutStream which will append to the list.
154 /// This function may be called only when `T` is `u8`.
155 pub fn outStream(self: *Self) std.io.OutStream(*Self, error{OutOfMemory}, appendWrite) {
156 return .{ .context = self };
157 }
158
159 /// Same as `append` except it returns the number of bytes written, which is always the same
160 /// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API.
161 /// This function may be called only when `T` is `u8`.
162 pub fn appendWrite(self: *Self, m: []const u8) !usize {
163 try self.appendSlice(m);
164 return m.len;
165 }
166 };
167}
168
169test "simple" {
170 var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, "");
171 defer buf.deinit();
172
173 testing.expect(buf.len() == 0);
174 try buf.appendSlice("hello");
175 try buf.appendSlice(" ");
176 try buf.appendSlice("world");
177 testing.expect(buf.eql("hello world"));
178 testing.expect(mem.eql(u8, mem.spanZ(buf.span().ptr), buf.span()));
179
180 var buf2 = try ArrayListSentineled(u8, 0).initFromBuffer(buf);
181 defer buf2.deinit();
182 testing.expect(buf.eql(buf2.span()));
183
184 testing.expect(buf.startsWith("hell"));
185 testing.expect(buf.endsWith("orld"));
186
187 try buf2.resize(4);
188 testing.expect(buf.startsWith(buf2.span()));
189}
190
191test "initSize" {
192 var buf = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 3);
193 defer buf.deinit();
194 testing.expect(buf.len() == 3);
195 try buf.appendSlice("hello");
196 testing.expect(mem.eql(u8, buf.span()[3..], "hello"));
197}
198
199test "initCapacity" {
200 var buf = try ArrayListSentineled(u8, 0).initCapacity(testing.allocator, 10);
201 defer buf.deinit();
202 testing.expect(buf.len() == 0);
203 testing.expect(buf.capacity() >= 10);
204 const old_cap = buf.capacity();
205 try buf.appendSlice("hello");
206 testing.expect(buf.len() == 5);
207 testing.expect(buf.capacity() == old_cap);
208 testing.expect(mem.eql(u8, buf.span(), "hello"));
209}
210
211test "print" {
212 var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, "");
213 defer buf.deinit();
214
215 try buf.outStream().print("Hello {} the {}", .{ 2, "world" });
216 testing.expect(buf.eql("Hello 2 the world"));
217}
218
219test "outStream" {
220 var buffer = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 0);
221 defer buffer.deinit();
222 const buf_stream = buffer.outStream();
223
224 const x: i32 = 42;
225 const y: i32 = 1234;
226 try buf_stream.print("x: {}\ny: {}\n", .{ x, y });
227
228 testing.expect(mem.eql(u8, buffer.span(), "x: 42\ny: 1234\n"));
229}
lib/std/child_process.zig+11-13
......@@ -15,7 +15,6 @@ const windows = os.windows;
1515const mem = std.mem;
1616const debug = std.debug;
1717const BufMap = std.BufMap;
18const ArrayListSentineled = std.ArrayListSentineled;
1918const builtin = @import("builtin");
2019const Os = builtin.Os;
2120const TailQueue = std.TailQueue;
......@@ -749,38 +748,37 @@ fn windowsCreateProcess(app_name: [*:0]u16, cmd_line: [*:0]u16, envp_ptr: ?[*]u1
749748
750749/// Caller must dealloc.
751750fn windowsCreateCommandLine(allocator: *mem.Allocator, argv: []const []const u8) ![:0]u8 {
752 var buf = try ArrayListSentineled(u8, 0).initSize(allocator, 0);
751 var buf = std.ArrayList(u8).init(allocator);
753752 defer buf.deinit();
754 const buf_stream = buf.outStream();
755753
756754 for (argv) |arg, arg_i| {
757 if (arg_i != 0) try buf_stream.writeByte(' ');
755 if (arg_i != 0) try buf.append(' ');
758756 if (mem.indexOfAny(u8, arg, " \t\n\"") == null) {
759 try buf_stream.writeAll(arg);
757 try buf.appendSlice(arg);
760758 continue;
761759 }
762 try buf_stream.writeByte('"');
760 try buf.append('"');
763761 var backslash_count: usize = 0;
764762 for (arg) |byte| {
765763 switch (byte) {
766764 '\\' => backslash_count += 1,
767765 '"' => {
768 try buf_stream.writeByteNTimes('\\', backslash_count * 2 + 1);
769 try buf_stream.writeByte('"');
766 try buf.appendNTimes('\\', backslash_count * 2 + 1);
767 try buf.append('"');
770768 backslash_count = 0;
771769 },
772770 else => {
773 try buf_stream.writeByteNTimes('\\', backslash_count);
774 try buf_stream.writeByte(byte);
771 try buf.appendNTimes('\\', backslash_count);
772 try buf.append(byte);
775773 backslash_count = 0;
776774 },
777775 }
778776 }
779 try buf_stream.writeByteNTimes('\\', backslash_count * 2);
780 try buf_stream.writeByte('"');
777 try buf.appendNTimes('\\', backslash_count * 2);
778 try buf.append('"');
781779 }
782780
783 return buf.toOwnedSlice();
781 return buf.toOwnedSliceSentinel(0);
784782}
785783
786784fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void {
lib/std/io.zig+1
......@@ -209,6 +209,7 @@ test "" {
209209 _ = @import("io/buffered_writer.zig");
210210 _ = @import("io/c_writer.zig");
211211 _ = @import("io/counting_writer.zig");
212 _ = @import("io/counting_reader.zig");
212213 _ = @import("io/fixed_buffer_stream.zig");
213214 _ = @import("io/reader.zig");
214215 _ = @import("io/writer.zig");
lib/std/io/counting_reader.zig+9-9
......@@ -12,16 +12,16 @@ pub fn CountingReader(comptime ReaderType: anytype) type {
1212 return struct {
1313 child_reader: ReaderType,
1414 bytes_read: u64 = 0,
15
15
1616 pub const Error = ReaderType.Error;
1717 pub const Reader = io.Reader(*@This(), Error, read);
18
18
1919 pub fn read(self: *@This(), buf: []u8) Error!usize {
2020 const amt = try self.child_reader.read(buf);
2121 self.bytes_read += amt;
2222 return amt;
2323 }
24
24
2525 pub fn reader(self: *@This()) Reader {
2626 return .{ .context = self };
2727 }
......@@ -29,20 +29,20 @@ pub fn CountingReader(comptime ReaderType: anytype) type {
2929}
3030
3131pub fn countingReader(reader: anytype) CountingReader(@TypeOf(reader)) {
32 return .{ .child_reader = reader, };
32 return .{ .child_reader = reader };
3333}
3434
3535test "io.CountingReader" {
3636 const bytes = "yay" ** 100;
3737 var fbs = io.fixedBufferStream(bytes);
38
38
3939 var counting_stream = countingReader(fbs.reader());
4040 const stream = counting_stream.reader();
41
41
4242 //read and discard all bytes
43 while(stream.readByte()) |_| {} else |err| {
43 while (stream.readByte()) |_| {} else |err| {
4444 testing.expect(err == error.EndOfStream);
4545 }
46
46
4747 testing.expect(counting_stream.bytes_read == bytes.len);
48}
\ No newline at end of file
48}
lib/std/json.zig+7-7
......@@ -1553,7 +1553,7 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
15531553 const source_slice = stringToken.slice(tokens.slice, tokens.i - 1);
15541554 switch (stringToken.escapes) {
15551555 .None => mem.copy(u8, &r, source_slice),
1556 .Some => try unescapeString(&r, source_slice),
1556 .Some => try unescapeValidString(&r, source_slice),
15571557 }
15581558 return r;
15591559 },
......@@ -1600,7 +1600,7 @@ fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options:
16001600 .Some => |some_escapes| {
16011601 const output = try allocator.alloc(u8, stringToken.decodedLength());
16021602 errdefer allocator.free(output);
1603 try unescapeString(output, source_slice);
1603 try unescapeValidString(output, source_slice);
16041604 return output;
16051605 },
16061606 }
......@@ -2084,7 +2084,7 @@ pub const Parser = struct {
20842084 .Some => |some_escapes| {
20852085 const output = try allocator.alloc(u8, s.decodedLength());
20862086 errdefer allocator.free(output);
2087 try unescapeString(output, slice);
2087 try unescapeValidString(output, slice);
20882088 return Value{ .String = output };
20892089 },
20902090 }
......@@ -2098,10 +2098,10 @@ pub const Parser = struct {
20982098 }
20992099};
21002100
2101// Unescape a JSON string
2102// Only to be used on strings already validated by the parser
2103// (note the unreachable statements and lack of bounds checking)
2104pub fn unescapeString(output: []u8, input: []const u8) !void {
2101/// Unescape a JSON string
2102/// Only to be used on strings already validated by the parser
2103/// (note the unreachable statements and lack of bounds checking)
2104pub fn unescapeValidString(output: []u8, input: []const u8) !void {
21052105 var inIndex: usize = 0;
21062106 var outIndex: usize = 0;
21072107
lib/std/net.zig+21-17
......@@ -783,13 +783,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
783783 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);
784784 defer lookup_addrs.deinit();
785785
786 var canon = std.ArrayListSentineled(u8, 0).initNull(arena);
786 var canon = std.ArrayList(u8).init(arena);
787787 defer canon.deinit();
788788
789789 try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port);
790790
791791 result.addrs = try arena.alloc(Address, lookup_addrs.items.len);
792 if (!canon.isNull()) {
792 if (canon.items.len != 0) {
793793 result.canon_name = canon.toOwnedSlice();
794794 }
795795
......@@ -818,7 +818,7 @@ const DAS_ORDER_SHIFT = 0;
818818
819819fn linuxLookupName(
820820 addrs: *std.ArrayList(LookupAddr),
821 canon: *std.ArrayListSentineled(u8, 0),
821 canon: *std.ArrayList(u8),
822822 opt_name: ?[]const u8,
823823 family: os.sa_family_t,
824824 flags: u32,
......@@ -826,7 +826,8 @@ fn linuxLookupName(
826826) !void {
827827 if (opt_name) |name| {
828828 // reject empty name and check len so it fits into temp bufs
829 try canon.replaceContents(name);
829 canon.items.len = 0;
830 try canon.appendSlice(name);
830831 if (Address.parseExpectingFamily(name, family, port)) |addr| {
831832 try addrs.append(LookupAddr{ .addr = addr });
832833 } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {
......@@ -1091,7 +1092,7 @@ fn linuxLookupNameFromNull(
10911092
10921093fn linuxLookupNameFromHosts(
10931094 addrs: *std.ArrayList(LookupAddr),
1094 canon: *std.ArrayListSentineled(u8, 0),
1095 canon: *std.ArrayList(u8),
10951096 name: []const u8,
10961097 family: os.sa_family_t,
10971098 port: u16,
......@@ -1142,7 +1143,8 @@ fn linuxLookupNameFromHosts(
11421143 // first name is canonical name
11431144 const name_text = first_name_text.?;
11441145 if (isValidHostName(name_text)) {
1145 try canon.replaceContents(name_text);
1146 canon.items.len = 0;
1147 try canon.appendSlice(name_text);
11461148 }
11471149 }
11481150}
......@@ -1161,7 +1163,7 @@ pub fn isValidHostName(hostname: []const u8) bool {
11611163
11621164fn linuxLookupNameFromDnsSearch(
11631165 addrs: *std.ArrayList(LookupAddr),
1164 canon: *std.ArrayListSentineled(u8, 0),
1166 canon: *std.ArrayList(u8),
11651167 name: []const u8,
11661168 family: os.sa_family_t,
11671169 port: u16,
......@@ -1177,10 +1179,10 @@ fn linuxLookupNameFromDnsSearch(
11771179 if (byte == '.') dots += 1;
11781180 }
11791181
1180 const search = if (rc.search.isNull() or dots >= rc.ndots or mem.endsWith(u8, name, "."))
1182 const search = if (dots >= rc.ndots or mem.endsWith(u8, name, "."))
11811183 ""
11821184 else
1183 rc.search.span();
1185 rc.search.items;
11841186
11851187 var canon_name = name;
11861188
......@@ -1193,14 +1195,14 @@ fn linuxLookupNameFromDnsSearch(
11931195 // name is not a CNAME record) and serves as a buffer for passing
11941196 // the full requested name to name_from_dns.
11951197 try canon.resize(canon_name.len);
1196 mem.copy(u8, canon.span(), canon_name);
1198 mem.copy(u8, canon.items, canon_name);
11971199 try canon.append('.');
11981200
11991201 var tok_it = mem.tokenize(search, " \t");
12001202 while (tok_it.next()) |tok| {
12011203 canon.shrink(canon_name.len + 1);
12021204 try canon.appendSlice(tok);
1203 try linuxLookupNameFromDns(addrs, canon, canon.span(), family, rc, port);
1205 try linuxLookupNameFromDns(addrs, canon, canon.items, family, rc, port);
12041206 if (addrs.items.len != 0) return;
12051207 }
12061208
......@@ -1210,13 +1212,13 @@ fn linuxLookupNameFromDnsSearch(
12101212
12111213const dpc_ctx = struct {
12121214 addrs: *std.ArrayList(LookupAddr),
1213 canon: *std.ArrayListSentineled(u8, 0),
1215 canon: *std.ArrayList(u8),
12141216 port: u16,
12151217};
12161218
12171219fn linuxLookupNameFromDns(
12181220 addrs: *std.ArrayList(LookupAddr),
1219 canon: *std.ArrayListSentineled(u8, 0),
1221 canon: *std.ArrayList(u8),
12201222 name: []const u8,
12211223 family: os.sa_family_t,
12221224 rc: ResolvConf,
......@@ -1271,7 +1273,7 @@ const ResolvConf = struct {
12711273 attempts: u32,
12721274 ndots: u32,
12731275 timeout: u32,
1274 search: std.ArrayListSentineled(u8, 0),
1276 search: std.ArrayList(u8),
12751277 ns: std.ArrayList(LookupAddr),
12761278
12771279 fn deinit(rc: *ResolvConf) void {
......@@ -1286,7 +1288,7 @@ const ResolvConf = struct {
12861288fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
12871289 rc.* = ResolvConf{
12881290 .ns = std.ArrayList(LookupAddr).init(allocator),
1289 .search = std.ArrayListSentineled(u8, 0).initNull(allocator),
1291 .search = std.ArrayList(u8).init(allocator),
12901292 .ndots = 1,
12911293 .timeout = 5,
12921294 .attempts = 2,
......@@ -1338,7 +1340,8 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
13381340 const ip_txt = line_it.next() orelse continue;
13391341 try linuxLookupNameFromNumericUnspec(&rc.ns, ip_txt, 53);
13401342 } else if (mem.eql(u8, token, "domain") or mem.eql(u8, token, "search")) {
1341 try rc.search.replaceContents(line_it.rest());
1343 rc.search.items.len = 0;
1344 try rc.search.appendSlice(line_it.rest());
13421345 }
13431346 }
13441347
......@@ -1569,7 +1572,8 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
15691572 _ = try os.dn_expand(packet, data, &tmp);
15701573 const canon_name = mem.spanZ(std.meta.assumeSentinel(&tmp, 0));
15711574 if (isValidHostName(canon_name)) {
1572 try ctx.canon.replaceContents(canon_name);
1575 ctx.canon.items.len = 0;
1576 try ctx.canon.appendSlice(canon_name);
15731577 }
15741578 },
15751579 else => return,
lib/std/os/linux/io_uring.zig+3-4
......@@ -1378,11 +1378,10 @@ test "timeout_remove" {
13781378 // Timeout remove operations set the fd to -1, which results in EBADF before EINVAL.
13791379 // We use IORING_FEAT_RW_CUR_POS as a safety check here to make sure we are at least pre-5.6.
13801380 // We don't want to skip this test for newer kernels.
1381 if (
1382 cqe_timeout.user_data == 0x99999999 and
1381 if (cqe_timeout.user_data == 0x99999999 and
13831382 cqe_timeout.res == -linux.EBADF and
1384 (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0
1385 ) {
1383 (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0)
1384 {
13861385 return error.SkipZigTest;
13871386 }
13881387 testing.expectEqual(linux.io_uring_cqe{
lib/std/std.zig-1
......@@ -8,7 +8,6 @@ pub const ArrayHashMapUnmanaged = array_hash_map.ArrayHashMapUnmanaged;
88pub const ArrayList = @import("array_list.zig").ArrayList;
99pub const ArrayListAligned = @import("array_list.zig").ArrayListAligned;
1010pub const ArrayListAlignedUnmanaged = @import("array_list.zig").ArrayListAlignedUnmanaged;
11pub const ArrayListSentineled = @import("array_list_sentineled.zig").ArrayListSentineled;
1211pub const ArrayListUnmanaged = @import("array_list.zig").ArrayListUnmanaged;
1312pub const AutoArrayHashMap = array_hash_map.AutoArrayHashMap;
1413pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;
src/DepTokenizer.zig+2-3
......@@ -885,7 +885,7 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
885885 defer arena_allocator.deinit();
886886
887887 var it: Tokenizer = .{ .bytes = input };
888 var buffer = try std.ArrayListSentineled(u8, 0).initSize(arena, 0);
888 var buffer = std.ArrayList(u8).init(arena);
889889 var resolve_buf = std.ArrayList(u8).init(arena);
890890 var i: usize = 0;
891891 while (it.next()) |token| {
......@@ -916,9 +916,8 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
916916 }
917917 i += 1;
918918 }
919 const got: []const u8 = buffer.span();
920919
921 if (std.mem.eql(u8, expect, got)) {
920 if (std.mem.eql(u8, expect, buffer.items)) {
922921 testing.expect(true);
923922 return;
924923 }
test/standalone/brace_expansion/main.zig+79-47
......@@ -4,7 +4,6 @@ const mem = std.mem;
44const debug = std.debug;
55const assert = debug.assert;
66const testing = std.testing;
7const ArrayListSentineled = std.ArrayListSentineled;
87const ArrayList = std.ArrayList;
98const maxInt = std.math.maxInt;
109
......@@ -16,7 +15,8 @@ const Token = union(enum) {
1615 Eof,
1716};
1817
19var global_allocator: *mem.Allocator = undefined;
18var gpa = std.heap.GeneralPurposeAllocator(.{}){};
19var global_allocator = &gpa.allocator;
2020
2121fn tokenize(input: []const u8) !ArrayList(Token) {
2222 const State = enum {
......@@ -25,12 +25,13 @@ fn tokenize(input: []const u8) !ArrayList(Token) {
2525 };
2626
2727 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
2829 var tok_begin: usize = undefined;
2930 var state = State.Start;
3031
3132 for (input) |b, i| {
3233 switch (state) {
33 State.Start => switch (b) {
34 .Start => switch (b) {
3435 'a'...'z', 'A'...'Z' => {
3536 state = State.Word;
3637 tok_begin = i;
......@@ -40,7 +41,7 @@ fn tokenize(input: []const u8) !ArrayList(Token) {
4041 ',' => try token_list.append(Token.Comma),
4142 else => return error.InvalidInput,
4243 },
43 State.Word => switch (b) {
44 .Word => switch (b) {
4445 'a'...'z', 'A'...'Z' => {},
4546 '{', '}', ',' => {
4647 try token_list.append(Token{ .Word = input[tok_begin..i] });
......@@ -68,6 +69,23 @@ const Node = union(enum) {
6869 Scalar: []const u8,
6970 List: ArrayList(Node),
7071 Combine: []Node,
72
73 fn deinit(self: Node) void {
74 switch (self) {
75 .Scalar => {},
76 .Combine => |pair| {
77 pair[0].deinit();
78 pair[1].deinit();
79 global_allocator.free(pair);
80 },
81 .List => |list| {
82 for (list.items) |item| {
83 item.deinit();
84 }
85 list.deinit();
86 },
87 }
88 }
7189};
7290
7391const ParseError = error{
......@@ -80,9 +98,13 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
8098 token_index.* += 1;
8199
82100 const result_node = switch (first_token) {
83 Token.Word => |word| Node{ .Scalar = word },
84 Token.OpenBrace => blk: {
101 .Word => |word| Node{ .Scalar = word },
102 .OpenBrace => blk: {
85103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
86108 while (true) {
87109 try list.append(try parse(tokens, token_index));
88110
......@@ -90,8 +112,8 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
90112 token_index.* += 1;
91113
92114 switch (token) {
93 Token.CloseBrace => break,
94 Token.Comma => continue,
115 .CloseBrace => break,
116 .Comma => continue,
95117 else => return error.InvalidInput,
96118 }
97119 }
......@@ -101,8 +123,9 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
101123 };
102124
103125 switch (tokens.items[token_index.*]) {
104 Token.Word, Token.OpenBrace => {
126 .Word, .OpenBrace => {
105127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
106129 pair[0] = result_node;
107130 pair[1] = try parse(tokens, token_index);
108131 return Node{ .Combine = pair };
......@@ -111,22 +134,27 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
111134 }
112135}
113136
114fn expandString(input: []const u8, output: *ArrayListSentineled(u8, 0)) !void {
137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
115138 const tokens = try tokenize(input);
139 defer tokens.deinit();
116140 if (tokens.items.len == 1) {
117141 return output.resize(0);
118142 }
119143
120144 var token_index: usize = 0;
121145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
122147 const last_token = tokens.items[token_index];
123148 switch (last_token) {
124149 Token.Eof => {},
125150 else => return error.InvalidInput,
126151 }
127152
128 var result_list = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator);
129 defer result_list.deinit();
153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
130158
131159 try expandNode(root, &result_list);
132160
......@@ -135,39 +163,56 @@ fn expandString(input: []const u8, output: *ArrayListSentineled(u8, 0)) !void {
135163 if (i != 0) {
136164 try output.append(' ');
137165 }
138 try output.appendSlice(buf.span());
166 try output.appendSlice(buf.items);
139167 }
140168}
141169
142170const ExpandNodeError = error{OutOfMemory};
143171
144fn expandNode(node: Node, output: *ArrayList(ArrayListSentineled(u8, 0))) ExpandNodeError!void {
172fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void {
145173 assert(output.items.len == 0);
146174 switch (node) {
147 Node.Scalar => |scalar| {
148 try output.append(try ArrayListSentineled(u8, 0).init(global_allocator, scalar));
175 .Scalar => |scalar| {
176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
149180 },
150 Node.Combine => |pair| {
181 .Combine => |pair| {
151182 const a_node = pair[0];
152183 const b_node = pair[1];
153184
154 var child_list_a = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator);
185 var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator);
186 defer {
187 for (child_list_a.items) |*buf| buf.deinit();
188 child_list_a.deinit();
189 }
155190 try expandNode(a_node, &child_list_a);
156191
157 var child_list_b = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator);
192 var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator);
193 defer {
194 for (child_list_b.items) |*buf| buf.deinit();
195 child_list_b.deinit();
196 }
158197 try expandNode(b_node, &child_list_b);
159198
160199 for (child_list_a.items) |buf_a| {
161200 for (child_list_b.items) |buf_b| {
162 var combined_buf = try ArrayListSentineled(u8, 0).initFromBuffer(buf_a);
163 try combined_buf.appendSlice(buf_b.span());
201 var combined_buf = ArrayList(u8).init(global_allocator);
202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
164206 try output.append(combined_buf);
165207 }
166208 }
167209 },
168 Node.List => |list| {
210 .List => |list| {
169211 for (list.items) |child_node| {
170 var child_list = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator);
212 var child_list = ArrayList(ArrayList(u8)).init(global_allocator);
213 errdefer for (child_list.items) |*buf| buf.deinit();
214 defer child_list.deinit();
215
171216 try expandNode(child_node, &child_list);
172217
173218 for (child_list.items) |buf| {
......@@ -179,32 +224,22 @@ fn expandNode(node: Node, output: *ArrayList(ArrayListSentineled(u8, 0))) Expand
179224}
180225
181226pub fn main() !void {
227 defer _ = gpa.deinit();
182228 const stdin_file = io.getStdIn();
183229 const stdout_file = io.getStdOut();
184230
185 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
186 defer arena.deinit();
187
188 global_allocator = &arena.allocator;
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232 defer global_allocator.free(stdin);
189233
190 var stdin_buf = try ArrayListSentineled(u8, 0).initSize(global_allocator, 0);
191 defer stdin_buf.deinit();
192
193 var stdin_adapter = stdin_file.inStream();
194 try stdin_adapter.stream.readAllBuffer(&stdin_buf, maxInt(usize));
195
196 var result_buf = try ArrayListSentineled(u8, 0).initSize(global_allocator, 0);
234 var result_buf = ArrayList(u8).init(global_allocator);
197235 defer result_buf.deinit();
198236
199 try expandString(stdin_buf.span(), &result_buf);
200 try stdout_file.write(result_buf.span());
237 try expandString(stdin_buf.items, &result_buf);
238 try stdout_file.write(result_buf.items);
201239}
202240
203241test "invalid inputs" {
204 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
205 defer arena.deinit();
206
207 global_allocator = &arena.allocator;
242 global_allocator = std.testing.allocator;
208243
209244 expectError("}ABC", error.InvalidInput);
210245 expectError("{ABC", error.InvalidInput);
......@@ -218,17 +253,14 @@ test "invalid inputs" {
218253}
219254
220255fn expectError(test_input: []const u8, expected_err: anyerror) void {
221 var output_buf = ArrayListSentineled(u8, 0).initSize(global_allocator, 0) catch unreachable;
256 var output_buf = ArrayList(u8).init(global_allocator);
222257 defer output_buf.deinit();
223258
224259 testing.expectError(expected_err, expandString(test_input, &output_buf));
225260}
226261
227262test "valid inputs" {
228 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
229 defer arena.deinit();
230
231 global_allocator = &arena.allocator;
263 global_allocator = std.testing.allocator;
232264
233265 expectExpansion("{x,y,z}", "x y z");
234266 expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
......@@ -251,10 +283,10 @@ test "valid inputs" {
251283}
252284
253285fn expectExpansion(test_input: []const u8, expected_result: []const u8) void {
254 var result = ArrayListSentineled(u8, 0).initSize(global_allocator, 0) catch unreachable;
286 var result = ArrayList(u8).init(global_allocator);
255287 defer result.deinit();
256288
257289 expandString(test_input, &result) catch unreachable;
258290
259 testing.expectEqualSlices(u8, expected_result, result.span());
291 testing.expectEqualSlices(u8, expected_result, result.items);
260292}