| ... | ... | @@ -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 | 198 | if (self.index == self.count) return null; |
| 199 | 199 | |
| 200 | 200 | const s = os.argv[self.index]; |
| ... | ... | @@ -213,7 +213,7 @@ pub const ArgIteratorPosix = struct { |
| 213 | 213 | pub const ArgIteratorWasi = struct { |
| 214 | 214 | allocator: *mem.Allocator, |
| 215 | 215 | index: usize, |
| 216 | | args: [][]u8, |
| 216 | args: [][:0]u8, |
| 217 | 217 | |
| 218 | 218 | pub const InitError = error{OutOfMemory} || os.UnexpectedError; |
| 219 | 219 | |
| ... | ... | @@ -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 | 232 | const w = os.wasi; |
| 233 | 233 | var count: usize = undefined; |
| 234 | 234 | var buf_size: usize = undefined; |
| ... | ... | @@ -248,7 +248,7 @@ pub const ArgIteratorWasi = struct { |
| 248 | 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 | 252 | var i: usize = 0; |
| 253 | 253 | while (i < count) : (i += 1) { |
| 254 | 254 | result_args[i] = mem.spanZ(argv[i]); |
| ... | ... | @@ -257,7 +257,7 @@ pub const ArgIteratorWasi = struct { |
| 257 | 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 | 261 | if (self.index == self.args.len) return null; |
| 262 | 262 | |
| 263 | 263 | const arg = self.args[self.index]; |
| ... | ... | @@ -301,7 +301,7 @@ pub const ArgIteratorWindows = struct { |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | 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 | 305 | // march forward over whitespace |
| 306 | 306 | while (true) : (self.index += 1) { |
| 307 | 307 | const byte = self.cmd_line[self.index]; |
| ... | ... | @@ -355,8 +355,8 @@ pub const ArgIteratorWindows = struct { |
| 355 | 355 | } |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | | fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![]u8 { |
| 359 | | var buf = std.ArrayList(u8).init(allocator); |
| 358 | fn internalNext(self: *ArgIteratorWindows, allocator: *Allocator) NextError![:0]u8 { |
| 359 | var buf = try std.ArrayListSentineled(u8, 0).init(allocator, ""); |
| 360 | 360 | defer buf.deinit(); |
| 361 | 361 | |
| 362 | 362 | var backslash_count: usize = 0; |
| ... | ... | @@ -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 | 401 | var i: usize = 0; |
| 402 | 402 | while (i < emit_count) : (i += 1) { |
| 403 | 403 | try buf.append('\\'); |
| ... | ... | @@ -437,21 +437,21 @@ pub const ArgIterator = struct { |
| 437 | 437 | pub const NextError = ArgIteratorWindows.NextError; |
| 438 | 438 | |
| 439 | 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 | 441 | if (builtin.os.tag == .windows) { |
| 442 | 442 | return self.inner.next(allocator); |
| 443 | 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 | 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 | 450 | return self.inner.next(); |
| 451 | 451 | } |
| 452 | 452 | |
| 453 | 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 | 455 | return self.inner.next(); |
| 456 | 456 | } |
| 457 | 457 | |
| ... | ... | @@ -501,7 +501,7 @@ test "args iterator" { |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | 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 | 505 | // TODO refactor to only make 1 allocation. |
| 506 | 506 | var it = if (builtin.os.tag == .wasi) try argsWithAllocator(allocator) else args(); |
| 507 | 507 | defer it.deinit(); |
| ... | ... | @@ -515,35 +515,36 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { |
| 515 | 515 | while (it.next(allocator)) |arg_or_err| { |
| 516 | 516 | const arg = try arg_or_err; |
| 517 | 517 | defer allocator.free(arg); |
| 518 | | try contents.appendSlice(arg); |
| 518 | try contents.appendSlice(arg[0 .. arg.len + 1]); |
| 519 | 519 | try slice_list.append(arg.len); |
| 520 | 520 | } |
| 521 | 521 | |
| 522 | 522 | const contents_slice = contents.span(); |
| 523 | 523 | const slice_sizes = slice_list.span(); |
| 524 | const contents_size_bytes = try math.add(usize, contents_slice.len, slice_sizes.len); |
| 524 | 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 | 527 | const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); |
| 527 | 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 | 531 | const result_contents = buf[slice_list_bytes..]; |
| 531 | 532 | mem.copy(u8, result_contents, contents_slice); |
| 532 | 533 | |
| 533 | 534 | var contents_index: usize = 0; |
| 534 | 535 | for (slice_sizes) |len, i| { |
| 535 | 536 | const new_index = contents_index + len; |
| 536 | | result_slice_list[i] = result_contents[contents_index..new_index]; |
| 537 | | contents_index = new_index; |
| 537 | result_slice_list[i] = result_contents[contents_index..new_index :0]; |
| 538 | contents_index = new_index + 1; |
| 538 | 539 | } |
| 539 | 540 | |
| 540 | 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 | 545 | var total_bytes: usize = 0; |
| 545 | 546 | for (args_alloc) |arg| { |
| 546 | | total_bytes += @sizeOf([]u8) + arg.len; |
| 547 | total_bytes += @sizeOf([]u8) + arg.len + 1; |
| 547 | 548 | } |
| 548 | 549 | const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes]; |
| 549 | 550 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); |