authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-23 16:24:22+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-12-23 16:24:22+02:00
loge5aab6222812f29f4e8c99adb89358ac3e781680
tree906a82dec5049765d0a7fcca1476898c9341a340
parent51a904677c9c9264f4856aaff270b18483205443
signaturelock-open Commit is signed but in an unrecognized format.

move ArrayListSentineled to std lib orphanage


7 files changed, 128 insertions(+), 310 deletions(-)

lib/std/array_list.zig+14
...@@ -91,6 +91,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -91,6 +91,13 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
91 return result;91 return result;
92 }92 }
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.list.toOwnedSlice();
98 return result[0 .. result.len - 1 :sentinel];
99 }
100
94 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.101 /// Insert `item` at index `n` by moving `list[n .. list.len]` to make room.
95 /// This operation is O(N).102 /// This operation is O(N).
96 pub fn insert(self: *Self, n: usize, item: T) !void {103 pub fn insert(self: *Self, n: usize, item: T) !void {
...@@ -389,6 +396,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -389,6 +396,13 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
389 return result;396 return result;
390 }397 }
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.list.toOwnedSlice(allocator);
403 return result[0 .. result.len - 1 :sentinel];
404 }
405
392 /// Insert `item` at index `n`. Moves `list[n .. list.len]`406 /// Insert `item` at index `n`. Moves `list[n .. list.len]`
393 /// to make room.407 /// to make room.
394 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {408 pub fn insert(self: *Self, allocator: *Allocator, n: usize, item: T) !void {
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+12-13
...@@ -15,7 +15,6 @@ const windows = os.windows;...@@ -15,7 +15,6 @@ const windows = os.windows;
15const mem = std.mem;15const mem = std.mem;
16const debug = std.debug;16const debug = std.debug;
17const BufMap = std.BufMap;17const BufMap = std.BufMap;
18const ArrayListSentineled = std.ArrayListSentineled;
19const builtin = @import("builtin");18const builtin = @import("builtin");
20const Os = builtin.Os;19const Os = builtin.Os;
21const TailQueue = std.TailQueue;20const TailQueue = std.TailQueue;
...@@ -749,38 +748,38 @@ fn windowsCreateProcess(app_name: [*:0]u16, cmd_line: [*:0]u16, envp_ptr: ?[*]u1...@@ -749,38 +748,38 @@ fn windowsCreateProcess(app_name: [*:0]u16, cmd_line: [*:0]u16, envp_ptr: ?[*]u1
749748
750/// Caller must dealloc.749/// Caller must dealloc.
751fn windowsCreateCommandLine(allocator: *mem.Allocator, argv: []const []const u8) ![:0]u8 {750fn windowsCreateCommandLine(allocator: *mem.Allocator, argv: []const []const u8) ![:0]u8 {
752 var buf = try ArrayListSentineled(u8, 0).initSize(allocator, 0);751 var buf = try ArrayList(u8).init(allocator);
753 defer buf.deinit();752 defer buf.deinit();
754 const buf_stream = buf.outStream();753 const buf_wi = buf.outStream();
755754
756 for (argv) |arg, arg_i| {755 for (argv) |arg, arg_i| {
757 if (arg_i != 0) try buf_stream.writeByte(' ');756 if (arg_i != 0) try buf.append(' ');
758 if (mem.indexOfAny(u8, arg, " \t\n\"") == null) {757 if (mem.indexOfAny(u8, arg, " \t\n\"") == null) {
759 try buf_stream.writeAll(arg);758 try buf.appendSlice(arg);
760 continue;759 continue;
761 }760 }
762 try buf_stream.writeByte('"');761 try buf.append('"');
763 var backslash_count: usize = 0;762 var backslash_count: usize = 0;
764 for (arg) |byte| {763 for (arg) |byte| {
765 switch (byte) {764 switch (byte) {
766 '\\' => backslash_count += 1,765 '\\' => backslash_count += 1,
767 '"' => {766 '"' => {
768 try buf_stream.writeByteNTimes('\\', backslash_count * 2 + 1);767 try buf.appendNTimes('\\', backslash_count * 2 + 1);
769 try buf_stream.writeByte('"');768 try buf.append('"');
770 backslash_count = 0;769 backslash_count = 0;
771 },770 },
772 else => {771 else => {
773 try buf_stream.writeByteNTimes('\\', backslash_count);772 try buf.appendNTimes('\\', backslash_count);
774 try buf_stream.writeByte(byte);773 try buf.append(byte);
775 backslash_count = 0;774 backslash_count = 0;
776 },775 },
777 }776 }
778 }777 }
779 try buf_stream.writeByteNTimes('\\', backslash_count * 2);778 try buf.appendNTimes('\\', backslash_count * 2);
780 try buf_stream.writeByte('"');779 try buf.append('"');
781 }780 }
782781
783 return buf.toOwnedSlice();782 return buf.toOwnedSliceSentinel(0);
784}783}
785784
786fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void {785fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void {
lib/std/net.zig+21-17
...@@ -783,13 +783,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -783,13 +783,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
783 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);783 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);
784 defer lookup_addrs.deinit();784 defer lookup_addrs.deinit();
785785
786 var canon = std.ArrayListSentineled(u8, 0).initNull(arena);786 var canon = std.ArrayList(u8).init(arena);
787 defer canon.deinit();787 defer canon.deinit();
788788
789 try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port);789 try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port);
790790
791 result.addrs = try arena.alloc(Address, lookup_addrs.items.len);791 result.addrs = try arena.alloc(Address, lookup_addrs.items.len);
792 if (!canon.isNull()) {792 if (canon.items.len != 0) {
793 result.canon_name = canon.toOwnedSlice();793 result.canon_name = canon.toOwnedSlice();
794 }794 }
795795
...@@ -818,7 +818,7 @@ const DAS_ORDER_SHIFT = 0;...@@ -818,7 +818,7 @@ const DAS_ORDER_SHIFT = 0;
818818
819fn linuxLookupName(819fn linuxLookupName(
820 addrs: *std.ArrayList(LookupAddr),820 addrs: *std.ArrayList(LookupAddr),
821 canon: *std.ArrayListSentineled(u8, 0),821 canon: *std.ArrayList(u8),
822 opt_name: ?[]const u8,822 opt_name: ?[]const u8,
823 family: os.sa_family_t,823 family: os.sa_family_t,
824 flags: u32,824 flags: u32,
...@@ -826,7 +826,8 @@ fn linuxLookupName(...@@ -826,7 +826,8 @@ fn linuxLookupName(
826) !void {826) !void {
827 if (opt_name) |name| {827 if (opt_name) |name| {
828 // reject empty name and check len so it fits into temp bufs828 // 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);
830 if (Address.parseExpectingFamily(name, family, port)) |addr| {831 if (Address.parseExpectingFamily(name, family, port)) |addr| {
831 try addrs.append(LookupAddr{ .addr = addr });832 try addrs.append(LookupAddr{ .addr = addr });
832 } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {833 } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) {
...@@ -1091,7 +1092,7 @@ fn linuxLookupNameFromNull(...@@ -1091,7 +1092,7 @@ fn linuxLookupNameFromNull(
10911092
1092fn linuxLookupNameFromHosts(1093fn linuxLookupNameFromHosts(
1093 addrs: *std.ArrayList(LookupAddr),1094 addrs: *std.ArrayList(LookupAddr),
1094 canon: *std.ArrayListSentineled(u8, 0),1095 canon: *std.ArrayList(u8),
1095 name: []const u8,1096 name: []const u8,
1096 family: os.sa_family_t,1097 family: os.sa_family_t,
1097 port: u16,1098 port: u16,
...@@ -1142,7 +1143,8 @@ fn linuxLookupNameFromHosts(...@@ -1142,7 +1143,8 @@ fn linuxLookupNameFromHosts(
1142 // first name is canonical name1143 // first name is canonical name
1143 const name_text = first_name_text.?;1144 const name_text = first_name_text.?;
1144 if (isValidHostName(name_text)) {1145 if (isValidHostName(name_text)) {
1145 try canon.replaceContents(name_text);1146 canon.items.len = 0;
1147 try canon.appendSlice(name_text);
1146 }1148 }
1147 }1149 }
1148}1150}
...@@ -1161,7 +1163,7 @@ pub fn isValidHostName(hostname: []const u8) bool {...@@ -1161,7 +1163,7 @@ pub fn isValidHostName(hostname: []const u8) bool {
11611163
1162fn linuxLookupNameFromDnsSearch(1164fn linuxLookupNameFromDnsSearch(
1163 addrs: *std.ArrayList(LookupAddr),1165 addrs: *std.ArrayList(LookupAddr),
1164 canon: *std.ArrayListSentineled(u8, 0),1166 canon: *std.ArrayList(u8),
1165 name: []const u8,1167 name: []const u8,
1166 family: os.sa_family_t,1168 family: os.sa_family_t,
1167 port: u16,1169 port: u16,
...@@ -1177,10 +1179,10 @@ fn linuxLookupNameFromDnsSearch(...@@ -1177,10 +1179,10 @@ fn linuxLookupNameFromDnsSearch(
1177 if (byte == '.') dots += 1;1179 if (byte == '.') dots += 1;
1178 }1180 }
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, "."))
1181 ""1183 ""
1182 else1184 else
1183 rc.search.span();1185 rc.search.items;
11841186
1185 var canon_name = name;1187 var canon_name = name;
11861188
...@@ -1193,14 +1195,14 @@ fn linuxLookupNameFromDnsSearch(...@@ -1193,14 +1195,14 @@ fn linuxLookupNameFromDnsSearch(
1193 // name is not a CNAME record) and serves as a buffer for passing1195 // name is not a CNAME record) and serves as a buffer for passing
1194 // the full requested name to name_from_dns.1196 // the full requested name to name_from_dns.
1195 try canon.resize(canon_name.len);1197 try canon.resize(canon_name.len);
1196 mem.copy(u8, canon.span(), canon_name);1198 mem.copy(u8, canon.items, canon_name);
1197 try canon.append('.');1199 try canon.append('.');
11981200
1199 var tok_it = mem.tokenize(search, " \t");1201 var tok_it = mem.tokenize(search, " \t");
1200 while (tok_it.next()) |tok| {1202 while (tok_it.next()) |tok| {
1201 canon.shrink(canon_name.len + 1);1203 canon.shrink(canon_name.len + 1);
1202 try canon.appendSlice(tok);1204 try canon.appendSlice(tok);
1203 try linuxLookupNameFromDns(addrs, canon, canon.span(), family, rc, port);1205 try linuxLookupNameFromDns(addrs, canon, canon.items, family, rc, port);
1204 if (addrs.items.len != 0) return;1206 if (addrs.items.len != 0) return;
1205 }1207 }
12061208
...@@ -1210,13 +1212,13 @@ fn linuxLookupNameFromDnsSearch(...@@ -1210,13 +1212,13 @@ fn linuxLookupNameFromDnsSearch(
12101212
1211const dpc_ctx = struct {1213const dpc_ctx = struct {
1212 addrs: *std.ArrayList(LookupAddr),1214 addrs: *std.ArrayList(LookupAddr),
1213 canon: *std.ArrayListSentineled(u8, 0),1215 canon: *std.ArrayList(u8),
1214 port: u16,1216 port: u16,
1215};1217};
12161218
1217fn linuxLookupNameFromDns(1219fn linuxLookupNameFromDns(
1218 addrs: *std.ArrayList(LookupAddr),1220 addrs: *std.ArrayList(LookupAddr),
1219 canon: *std.ArrayListSentineled(u8, 0),1221 canon: *std.ArrayList(u8),
1220 name: []const u8,1222 name: []const u8,
1221 family: os.sa_family_t,1223 family: os.sa_family_t,
1222 rc: ResolvConf,1224 rc: ResolvConf,
...@@ -1271,7 +1273,7 @@ const ResolvConf = struct {...@@ -1271,7 +1273,7 @@ const ResolvConf = struct {
1271 attempts: u32,1273 attempts: u32,
1272 ndots: u32,1274 ndots: u32,
1273 timeout: u32,1275 timeout: u32,
1274 search: std.ArrayListSentineled(u8, 0),1276 search: std.ArrayList(u8),
1275 ns: std.ArrayList(LookupAddr),1277 ns: std.ArrayList(LookupAddr),
12761278
1277 fn deinit(rc: *ResolvConf) void {1279 fn deinit(rc: *ResolvConf) void {
...@@ -1286,7 +1288,7 @@ const ResolvConf = struct {...@@ -1286,7 +1288,7 @@ const ResolvConf = struct {
1286fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {1288fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
1287 rc.* = ResolvConf{1289 rc.* = ResolvConf{
1288 .ns = std.ArrayList(LookupAddr).init(allocator),1290 .ns = std.ArrayList(LookupAddr).init(allocator),
1289 .search = std.ArrayListSentineled(u8, 0).initNull(allocator),1291 .search = std.ArrayList(u8).init(allocator),
1290 .ndots = 1,1292 .ndots = 1,
1291 .timeout = 5,1293 .timeout = 5,
1292 .attempts = 2,1294 .attempts = 2,
...@@ -1338,7 +1340,8 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {...@@ -1338,7 +1340,8 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
1338 const ip_txt = line_it.next() orelse continue;1340 const ip_txt = line_it.next() orelse continue;
1339 try linuxLookupNameFromNumericUnspec(&rc.ns, ip_txt, 53);1341 try linuxLookupNameFromNumericUnspec(&rc.ns, ip_txt, 53);
1340 } else if (mem.eql(u8, token, "domain") or mem.eql(u8, token, "search")) {1342 } 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());
1342 }1345 }
1343 }1346 }
13441347
...@@ -1569,7 +1572,8 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)...@@ -1569,7 +1572,8 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
1569 _ = try os.dn_expand(packet, data, &tmp);1572 _ = try os.dn_expand(packet, data, &tmp);
1570 const canon_name = mem.spanZ(std.meta.assumeSentinel(&tmp, 0));1573 const canon_name = mem.spanZ(std.meta.assumeSentinel(&tmp, 0));
1571 if (isValidHostName(canon_name)) {1574 if (isValidHostName(canon_name)) {
1572 try ctx.canon.replaceContents(canon_name);1575 ctx.canon.items.len = 0;
1576 try ctx.canon.appendSlice(canon_name);
1573 }1577 }
1574 },1578 },
1575 else => return,1579 else => return,
lib/std/std.zig-1
...@@ -8,7 +8,6 @@ pub const ArrayHashMapUnmanaged = array_hash_map.ArrayHashMapUnmanaged;...@@ -8,7 +8,6 @@ pub const ArrayHashMapUnmanaged = array_hash_map.ArrayHashMapUnmanaged;
8pub const ArrayList = @import("array_list.zig").ArrayList;8pub const ArrayList = @import("array_list.zig").ArrayList;
9pub const ArrayListAligned = @import("array_list.zig").ArrayListAligned;9pub const ArrayListAligned = @import("array_list.zig").ArrayListAligned;
10pub const ArrayListAlignedUnmanaged = @import("array_list.zig").ArrayListAlignedUnmanaged;10pub const ArrayListAlignedUnmanaged = @import("array_list.zig").ArrayListAlignedUnmanaged;
11pub const ArrayListSentineled = @import("array_list_sentineled.zig").ArrayListSentineled;
12pub const ArrayListUnmanaged = @import("array_list.zig").ArrayListUnmanaged;11pub const ArrayListUnmanaged = @import("array_list.zig").ArrayListUnmanaged;
13pub const AutoArrayHashMap = array_hash_map.AutoArrayHashMap;12pub const AutoArrayHashMap = array_hash_map.AutoArrayHashMap;
14pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;13pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;
src/DepTokenizer.zig+2-3
...@@ -885,7 +885,7 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {...@@ -885,7 +885,7 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
885 defer arena_allocator.deinit();885 defer arena_allocator.deinit();
886886
887 var it: Tokenizer = .{ .bytes = input };887 var it: Tokenizer = .{ .bytes = input };
888 var buffer = try std.ArrayListSentineled(u8, 0).initSize(arena, 0);888 var buffer = std.ArrayList(u8).init(arena);
889 var resolve_buf = std.ArrayList(u8).init(arena);889 var resolve_buf = std.ArrayList(u8).init(arena);
890 var i: usize = 0;890 var i: usize = 0;
891 while (it.next()) |token| {891 while (it.next()) |token| {
...@@ -916,9 +916,8 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {...@@ -916,9 +916,8 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
916 }916 }
917 i += 1;917 i += 1;
918 }918 }
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)) {
922 testing.expect(true);921 testing.expect(true);
923 return;922 return;
924 }923 }
test/standalone/brace_expansion/main.zig+79-47
...@@ -4,7 +4,6 @@ const mem = std.mem;...@@ -4,7 +4,6 @@ const mem = std.mem;
4const debug = std.debug;4const debug = std.debug;
5const assert = debug.assert;5const assert = debug.assert;
6const testing = std.testing;6const testing = std.testing;
7const ArrayListSentineled = std.ArrayListSentineled;
8const ArrayList = std.ArrayList;7const ArrayList = std.ArrayList;
9const maxInt = std.math.maxInt;8const maxInt = std.math.maxInt;
109
...@@ -16,7 +15,8 @@ const Token = union(enum) {...@@ -16,7 +15,8 @@ const Token = union(enum) {
16 Eof,15 Eof,
17};16};
1817
19var global_allocator: *mem.Allocator = undefined;18var gpa = std.heap.GeneralPurposeAllocator(.{}){};
19var global_allocator = &gpa.allocator;
2020
21fn tokenize(input: []const u8) !ArrayList(Token) {21fn tokenize(input: []const u8) !ArrayList(Token) {
22 const State = enum {22 const State = enum {
...@@ -25,12 +25,13 @@ fn tokenize(input: []const u8) !ArrayList(Token) {...@@ -25,12 +25,13 @@ fn tokenize(input: []const u8) !ArrayList(Token) {
25 };25 };
2626
27 var token_list = ArrayList(Token).init(global_allocator);27 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
28 var tok_begin: usize = undefined;29 var tok_begin: usize = undefined;
29 var state = State.Start;30 var state = State.Start;
3031
31 for (input) |b, i| {32 for (input) |b, i| {
32 switch (state) {33 switch (state) {
33 State.Start => switch (b) {34 .Start => switch (b) {
34 'a'...'z', 'A'...'Z' => {35 'a'...'z', 'A'...'Z' => {
35 state = State.Word;36 state = State.Word;
36 tok_begin = i;37 tok_begin = i;
...@@ -40,7 +41,7 @@ fn tokenize(input: []const u8) !ArrayList(Token) {...@@ -40,7 +41,7 @@ fn tokenize(input: []const u8) !ArrayList(Token) {
40 ',' => try token_list.append(Token.Comma),41 ',' => try token_list.append(Token.Comma),
41 else => return error.InvalidInput,42 else => return error.InvalidInput,
42 },43 },
43 State.Word => switch (b) {44 .Word => switch (b) {
44 'a'...'z', 'A'...'Z' => {},45 'a'...'z', 'A'...'Z' => {},
45 '{', '}', ',' => {46 '{', '}', ',' => {
46 try token_list.append(Token{ .Word = input[tok_begin..i] });47 try token_list.append(Token{ .Word = input[tok_begin..i] });
...@@ -68,6 +69,23 @@ const Node = union(enum) {...@@ -68,6 +69,23 @@ const Node = union(enum) {
68 Scalar: []const u8,69 Scalar: []const u8,
69 List: ArrayList(Node),70 List: ArrayList(Node),
70 Combine: []Node,71 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 }
71};89};
7290
73const ParseError = error{91const ParseError = error{
...@@ -80,9 +98,13 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {...@@ -80,9 +98,13 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
80 token_index.* += 1;98 token_index.* += 1;
8199
82 const result_node = switch (first_token) {100 const result_node = switch (first_token) {
83 Token.Word => |word| Node{ .Scalar = word },101 .Word => |word| Node{ .Scalar = word },
84 Token.OpenBrace => blk: {102 .OpenBrace => blk: {
85 var list = ArrayList(Node).init(global_allocator);103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
86 while (true) {108 while (true) {
87 try list.append(try parse(tokens, token_index));109 try list.append(try parse(tokens, token_index));
88110
...@@ -90,8 +112,8 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {...@@ -90,8 +112,8 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
90 token_index.* += 1;112 token_index.* += 1;
91113
92 switch (token) {114 switch (token) {
93 Token.CloseBrace => break,115 .CloseBrace => break,
94 Token.Comma => continue,116 .Comma => continue,
95 else => return error.InvalidInput,117 else => return error.InvalidInput,
96 }118 }
97 }119 }
...@@ -101,8 +123,9 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {...@@ -101,8 +123,9 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
101 };123 };
102124
103 switch (tokens.items[token_index.*]) {125 switch (tokens.items[token_index.*]) {
104 Token.Word, Token.OpenBrace => {126 .Word, .OpenBrace => {
105 const pair = try global_allocator.alloc(Node, 2);127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
106 pair[0] = result_node;129 pair[0] = result_node;
107 pair[1] = try parse(tokens, token_index);130 pair[1] = try parse(tokens, token_index);
108 return Node{ .Combine = pair };131 return Node{ .Combine = pair };
...@@ -111,22 +134,27 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {...@@ -111,22 +134,27 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
111 }134 }
112}135}
113136
114fn expandString(input: []const u8, output: *ArrayListSentineled(u8, 0)) !void {137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
115 const tokens = try tokenize(input);138 const tokens = try tokenize(input);
139 defer tokens.deinit();
116 if (tokens.items.len == 1) {140 if (tokens.items.len == 1) {
117 return output.resize(0);141 return output.resize(0);
118 }142 }
119143
120 var token_index: usize = 0;144 var token_index: usize = 0;
121 const root = try parse(&tokens, &token_index);145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
122 const last_token = tokens.items[token_index];147 const last_token = tokens.items[token_index];
123 switch (last_token) {148 switch (last_token) {
124 Token.Eof => {},149 Token.Eof => {},
125 else => return error.InvalidInput,150 else => return error.InvalidInput,
126 }151 }
127152
128 var result_list = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator);153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
129 defer result_list.deinit();154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
130158
131 try expandNode(root, &result_list);159 try expandNode(root, &result_list);
132160
...@@ -135,39 +163,56 @@ fn expandString(input: []const u8, output: *ArrayListSentineled(u8, 0)) !void {...@@ -135,39 +163,56 @@ fn expandString(input: []const u8, output: *ArrayListSentineled(u8, 0)) !void {
135 if (i != 0) {163 if (i != 0) {
136 try output.append(' ');164 try output.append(' ');
137 }165 }
138 try output.appendSlice(buf.span());166 try output.appendSlice(buf.items);
139 }167 }
140}168}
141169
142const ExpandNodeError = error{OutOfMemory};170const 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 {
145 assert(output.items.len == 0);173 assert(output.items.len == 0);
146 switch (node) {174 switch (node) {
147 Node.Scalar => |scalar| {175 .Scalar => |scalar| {
148 try output.append(try ArrayListSentineled(u8, 0).init(global_allocator, scalar));176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
149 },180 },
150 Node.Combine => |pair| {181 .Combine => |pair| {
151 const a_node = pair[0];182 const a_node = pair[0];
152 const b_node = pair[1];183 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 }
155 try expandNode(a_node, &child_list_a);190 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 }
158 try expandNode(b_node, &child_list_b);197 try expandNode(b_node, &child_list_b);
159198
160 for (child_list_a.items) |buf_a| {199 for (child_list_a.items) |buf_a| {
161 for (child_list_b.items) |buf_b| {200 for (child_list_b.items) |buf_b| {
162 var combined_buf = try ArrayListSentineled(u8, 0).initFromBuffer(buf_a);201 var combined_buf = ArrayList(u8).init(global_allocator);
163 try combined_buf.appendSlice(buf_b.span());202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
164 try output.append(combined_buf);206 try output.append(combined_buf);
165 }207 }
166 }208 }
167 },209 },
168 Node.List => |list| {210 .List => |list| {
169 for (list.items) |child_node| {211 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
171 try expandNode(child_node, &child_list);216 try expandNode(child_node, &child_list);
172217
173 for (child_list.items) |buf| {218 for (child_list.items) |buf| {
...@@ -179,32 +224,22 @@ fn expandNode(node: Node, output: *ArrayList(ArrayListSentineled(u8, 0))) Expand...@@ -179,32 +224,22 @@ fn expandNode(node: Node, output: *ArrayList(ArrayListSentineled(u8, 0))) Expand
179}224}
180225
181pub fn main() !void {226pub fn main() !void {
227 defer _ = gpa.deinit();
182 const stdin_file = io.getStdIn();228 const stdin_file = io.getStdIn();
183 const stdout_file = io.getStdOut();229 const stdout_file = io.getStdOut();
184230
185 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
186 defer arena.deinit();232 defer global_allocator.free(stdin);
187
188 global_allocator = &arena.allocator;
189233
190 var stdin_buf = try ArrayListSentineled(u8, 0).initSize(global_allocator, 0);234 var result_buf = ArrayList(u8).init(global_allocator);
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);
197 defer result_buf.deinit();235 defer result_buf.deinit();
198236
199 try expandString(stdin_buf.span(), &result_buf);237 try expandString(stdin_buf.items, &result_buf);
200 try stdout_file.write(result_buf.span());238 try stdout_file.write(result_buf.items);
201}239}
202240
203test "invalid inputs" {241test "invalid inputs" {
204 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);242 global_allocator = std.testing.allocator;
205 defer arena.deinit();
206
207 global_allocator = &arena.allocator;
208243
209 expectError("}ABC", error.InvalidInput);244 expectError("}ABC", error.InvalidInput);
210 expectError("{ABC", error.InvalidInput);245 expectError("{ABC", error.InvalidInput);
...@@ -218,17 +253,14 @@ test "invalid inputs" {...@@ -218,17 +253,14 @@ test "invalid inputs" {
218}253}
219254
220fn expectError(test_input: []const u8, expected_err: anyerror) void {255fn 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);
222 defer output_buf.deinit();257 defer output_buf.deinit();
223258
224 testing.expectError(expected_err, expandString(test_input, &output_buf));259 testing.expectError(expected_err, expandString(test_input, &output_buf));
225}260}
226261
227test "valid inputs" {262test "valid inputs" {
228 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);263 global_allocator = std.testing.allocator;
229 defer arena.deinit();
230
231 global_allocator = &arena.allocator;
232264
233 expectExpansion("{x,y,z}", "x y z");265 expectExpansion("{x,y,z}", "x y z");
234 expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");266 expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
...@@ -251,10 +283,10 @@ test "valid inputs" {...@@ -251,10 +283,10 @@ test "valid inputs" {
251}283}
252284
253fn expectExpansion(test_input: []const u8, expected_result: []const u8) void {285fn 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);
255 defer result.deinit();287 defer result.deinit();
256288
257 expandString(test_input, &result) catch unreachable;289 expandString(test_input, &result) catch unreachable;
258290
259 testing.expectEqualSlices(u8, expected_result, result.span());291 testing.expectEqualSlices(u8, expected_result, result.items);
260}292}