| ... | @@ -194,7 +194,7 @@ pub const ArgIteratorPosix = struct { | ... | @@ -194,7 +194,7 @@ pub const ArgIteratorPosix = struct { |
| 194 | }; | 194 | }; |
| 195 | } | 195 | } |
| 196 | | 196 | |
| 197 | pub fn next(self: *ArgIteratorPosix) ?[]const u8 { | 197 | pub fn next(self: *ArgIteratorPosix) ?[:0]const u8 { |
| 198 | if (self.index == self.count) return null; | 198 | if (self.index == self.count) return null; |
| 199 | | 199 | |
| 200 | const s = os.argv[self.index]; | 200 | const s = os.argv[self.index]; |
| ... | @@ -213,7 +213,7 @@ pub const ArgIteratorPosix = struct { | ... | @@ -213,7 +213,7 @@ pub const ArgIteratorPosix = struct { |
| 213 | pub const ArgIteratorWasi = struct { | 213 | pub const ArgIteratorWasi = struct { |
| 214 | allocator: *mem.Allocator, | 214 | allocator: *mem.Allocator, |
| 215 | index: usize, | 215 | index: usize, |
| 216 | args: [][]u8, | 216 | args: [][:0]u8, |
| 217 | | 217 | |
| 218 | pub const InitError = error{OutOfMemory} || os.UnexpectedError; | 218 | pub const InitError = error{OutOfMemory} || os.UnexpectedError; |
| 219 | | 219 | |
| ... | @@ -228,7 +228,7 @@ pub const ArgIteratorWasi = struct { | ... | @@ -228,7 +228,7 @@ pub const ArgIteratorWasi = struct { |
| 228 | }; | 228 | }; |
| 229 | } | 229 | } |
| 230 | | 230 | |
| 231 | fn internalInit(allocator: *mem.Allocator) InitError![][]u8 { | 231 | fn internalInit(allocator: *mem.Allocator) InitError![][:0]u8 { |
| 232 | const w = os.wasi; | 232 | const w = os.wasi; |
| 233 | var count: usize = undefined; | 233 | var count: usize = undefined; |
| 234 | var buf_size: usize = undefined; | 234 | var buf_size: usize = undefined; |
| ... | @@ -248,7 +248,7 @@ pub const ArgIteratorWasi = struct { | ... | @@ -248,7 +248,7 @@ pub const ArgIteratorWasi = struct { |
| 248 | else => |err| return os.unexpectedErrno(err), | 248 | else => |err| return os.unexpectedErrno(err), |
| 249 | } | 249 | } |
| 250 | | 250 | |
| 251 | var result_args = try allocator.alloc([]u8, count); | 251 | var result_args = try allocator.alloc([:0]u8, count); |
| 252 | var i: usize = 0; | 252 | var i: usize = 0; |
| 253 | while (i < count) : (i += 1) { | 253 | while (i < count) : (i += 1) { |
| 254 | result_args[i] = mem.spanZ(argv[i]); | 254 | result_args[i] = mem.spanZ(argv[i]); |
| ... | @@ -257,7 +257,7 @@ pub const ArgIteratorWasi = struct { | ... | @@ -257,7 +257,7 @@ pub const ArgIteratorWasi = struct { |
| 257 | return result_args; | 257 | return result_args; |
| 258 | } | 258 | } |
| 259 | | 259 | |
| 260 | pub fn next(self: *ArgIteratorWasi) ?[]const u8 { | 260 | pub fn next(self: *ArgIteratorWasi) ?[:0]const u8 { |
| 261 | if (self.index == self.args.len) return null; | 261 | if (self.index == self.args.len) return null; |
| 262 | | 262 | |
| 263 | const arg = self.args[self.index]; | 263 | const arg = self.args[self.index]; |
| ... | @@ -301,7 +301,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -301,7 +301,7 @@ pub const ArgIteratorWindows = struct { |
| 301 | } | 301 | } |
| 302 | | 302 | |
| 303 | /// You must free the returned memory when done. | 303 | /// You must free the returned memory when done. |
| 304 | pub fn next(self: *ArgIteratorWindows, allocator: *Allocator) ?(NextError![]u8) { | 304 | pub fn next(self: *ArgIteratorWindows, allocator: *Allocator) ?(NextError![:0]u8) { |
| 305 | // march forward over whitespace | 305 | // march forward over whitespace |
| 306 | while (true) : (self.index += 1) { | 306 | while (true) : (self.index += 1) { |
| 307 | const byte = self.cmd_line[self.index]; | 307 | const byte = self.cmd_line[self.index]; |
| ... | @@ -355,8 +355,8 @@ pub const ArgIteratorWindows = struct { | ... | @@ -355,8 +355,8 @@ pub const ArgIteratorWindows = struct { |
| 355 | } | 355 | } |
| 356 | } | 356 | } |
| 357 | | 357 | |
| 358 | fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![]u8 { | 358 | fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![:0]u8 { |
| 359 | var buf = std.ArrayList(u8).init(allocator); | 359 | var buf = try std.ArrayListSentineled(u8, 0).init(allocator, ""); |
| 360 | defer buf.deinit(); | 360 | defer buf.deinit(); |
| 361 | | 361 | |
| 362 | var backslash_count: usize = 0; | 362 | var backslash_count: usize = 0; |
| ... | @@ -397,7 +397,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -397,7 +397,7 @@ pub const ArgIteratorWindows = struct { |
| 397 | } | 397 | } |
| 398 | } | 398 | } |
| 399 | | 399 | |
| 400 | fn emitBackslashes(self: *ArgIteratorWindows, buf: *std.ArrayList(u8), emit_count: usize) !void { | 400 | fn emitBackslashes(self: *ArgIteratorWindows, buf: *std.ArrayListSentineled(u8, 0), emit_count: usize) !void { |
| 401 | var i: usize = 0; | 401 | var i: usize = 0; |
| 402 | while (i < emit_count) : (i += 1) { | 402 | while (i < emit_count) : (i += 1) { |
| 403 | try buf.append('\\'); | 403 | try buf.append('\\'); |
| ... | @@ -437,21 +437,21 @@ pub const ArgIterator = struct { | ... | @@ -437,21 +437,21 @@ pub const ArgIterator = struct { |
| 437 | pub const NextError = ArgIteratorWindows.NextError; | 437 | pub const NextError = ArgIteratorWindows.NextError; |
| 438 | | 438 | |
| 439 | /// You must free the returned memory when done. | 439 | /// You must free the returned memory when done. |
| 440 | pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) { | 440 | pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![:0]u8) { |
| 441 | if (builtin.os.tag == .windows) { | 441 | if (builtin.os.tag == .windows) { |
| 442 | return self.inner.next(allocator); | 442 | return self.inner.next(allocator); |
| 443 | } else { | 443 | } else { |
| 444 | return allocator.dupe(u8, self.inner.next() orelse return null); | 444 | return allocator.dupeZ(u8, self.inner.next() orelse return null); |
| 445 | } | 445 | } |
| 446 | } | 446 | } |
| 447 | | 447 | |
| 448 | /// If you only are targeting posix you can call this and not need an allocator. | 448 | /// If you only are targeting posix you can call this and not need an allocator. |
| 449 | pub fn nextPosix(self: *ArgIterator) ?[]const u8 { | 449 | pub fn nextPosix(self: *ArgIterator) ?[:0]const u8 { |
| 450 | return self.inner.next(); | 450 | return self.inner.next(); |
| 451 | } | 451 | } |
| 452 | | 452 | |
| 453 | /// If you only are targeting WASI, you can call this and not need an allocator. | 453 | /// If you only are targeting WASI, you can call this and not need an allocator. |
| 454 | pub fn nextWasi(self: *ArgIterator) ?[]const u8 { | 454 | pub fn nextWasi(self: *ArgIterator) ?[:0]const u8 { |
| 455 | return self.inner.next(); | 455 | return self.inner.next(); |
| 456 | } | 456 | } |
| 457 | | 457 | |
| ... | @@ -501,7 +501,7 @@ test "args iterator" { | ... | @@ -501,7 +501,7 @@ test "args iterator" { |
| 501 | } | 501 | } |
| 502 | | 502 | |
| 503 | /// Caller must call argsFree on result. | 503 | /// Caller must call argsFree on result. |
| 504 | pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { | 504 | pub fn argsAlloc(allocator: *mem.Allocator) ![][:0]u8 { |
| 505 | // TODO refactor to only make 1 allocation. | 505 | // TODO refactor to only make 1 allocation. |
| 506 | var it = if (builtin.os.tag == .wasi) try argsWithAllocator(allocator) else args(); | 506 | var it = if (builtin.os.tag == .wasi) try argsWithAllocator(allocator) else args(); |
| 507 | defer it.deinit(); | 507 | defer it.deinit(); |
| ... | @@ -515,35 +515,36 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { | ... | @@ -515,35 +515,36 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { |
| 515 | while (it.next(allocator)) |arg_or_err| { | 515 | while (it.next(allocator)) |arg_or_err| { |
| 516 | const arg = try arg_or_err; | 516 | const arg = try arg_or_err; |
| 517 | defer allocator.free(arg); | 517 | defer allocator.free(arg); |
| 518 | try contents.appendSlice(arg); | 518 | try contents.appendSlice(arg[0 .. arg.len + 1]); |
| 519 | try slice_list.append(arg.len); | 519 | try slice_list.append(arg.len); |
| 520 | } | 520 | } |
| 521 | | 521 | |
| 522 | const contents_slice = contents.span(); | 522 | const contents_slice = contents.span(); |
| 523 | const slice_sizes = slice_list.span(); | 523 | const slice_sizes = slice_list.span(); |
| | 524 | const contents_size_bytes = try math.add(usize, contents_slice.len, slice_sizes.len); |
| 524 | const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); | 525 | const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); |
| 525 | const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len); | 526 | const total_bytes = try math.add(usize, slice_list_bytes, contents_size_bytes); |
| 526 | const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); | 527 | const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); |
| 527 | errdefer allocator.free(buf); | 528 | errdefer allocator.free(buf); |
| 528 | | 529 | |
| 529 | const result_slice_list = mem.bytesAsSlice([]u8, buf[0..slice_list_bytes]); | 530 | const result_slice_list = mem.bytesAsSlice([:0]u8, buf[0..slice_list_bytes]); |
| 530 | const result_contents = buf[slice_list_bytes..]; | 531 | const result_contents = buf[slice_list_bytes..]; |
| 531 | mem.copy(u8, result_contents, contents_slice); | 532 | mem.copy(u8, result_contents, contents_slice); |
| 532 | | 533 | |
| 533 | var contents_index: usize = 0; | 534 | var contents_index: usize = 0; |
| 534 | for (slice_sizes) |len, i| { | 535 | for (slice_sizes) |len, i| { |
| 535 | const new_index = contents_index + len; | 536 | const new_index = contents_index + len; |
| 536 | result_slice_list[i] = result_contents[contents_index..new_index]; | 537 | result_slice_list[i] = result_contents[contents_index..new_index :0]; |
| 537 | contents_index = new_index; | 538 | contents_index = new_index + 1; |
| 538 | } | 539 | } |
| 539 | | 540 | |
| 540 | return result_slice_list; | 541 | return result_slice_list; |
| 541 | } | 542 | } |
| 542 | | 543 | |
| 543 | pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void { | 544 | pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const [:0]u8) void { |
| 544 | var total_bytes: usize = 0; | 545 | var total_bytes: usize = 0; |
| 545 | for (args_alloc) |arg| { | 546 | for (args_alloc) |arg| { |
| 546 | total_bytes += @sizeOf([]u8) + arg.len; | 547 | total_bytes += @sizeOf([]u8) + arg.len + 1; |
| 547 | } | 548 | } |
| 548 | const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes]; | 549 | const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes]; |
| 549 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); | 550 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); |