diff --git a/doc/docgen.zig b/doc/docgen.zig index be62cab076..9e4c8173c0 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -321,7 +321,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { var last_action = Action.Open; var last_columns: ?u8 = null; - var toc_buf = try std.Buffer.initSize(allocator, 0); + var toc_buf = std.ArrayList(u8).init(allocator); defer toc_buf.deinit(); var toc = toc_buf.outStream(); @@ -607,7 +607,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { } fn urlize(allocator: *mem.Allocator, input: []const u8) ![]u8 { - var buf = try std.Buffer.initSize(allocator, 0); + var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); const out = buf.outStream(); @@ -626,7 +626,7 @@ fn urlize(allocator: *mem.Allocator, input: []const u8) ![]u8 { } fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 { - var buf = try std.Buffer.initSize(allocator, 0); + var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); const out = buf.outStream(); @@ -672,7 +672,7 @@ test "term color" { } fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 { - var buf = try std.Buffer.initSize(allocator, 0); + var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); var out = buf.outStream(); diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index cbbec0b4f3..523d1c810f 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -189,16 +189,30 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { self.len += items.len; } - /// Append a value to the list `n` times. Allocates more memory - /// as necessary. + /// Same as `append` except it returns the number of bytes written, which is always the same + /// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API. + /// This function may be called only when `T` is `u8`. + fn appendWrite(self: *Self, m: []const u8) !usize { + try self.appendSlice(m); + return m.len; + } + + /// Initializes an OutStream which will append to the list. + /// This function may be called only when `T` is `u8`. + pub fn outStream(self: *Self) std.io.OutStream(*Self, error{OutOfMemory}, appendWrite) { + return .{ .context = self }; + } + + /// Append a value to the list `n` times. + /// Allocates more memory as necessary. pub fn appendNTimes(self: *Self, value: T, n: usize) !void { const old_len = self.len; try self.resize(self.len + n); mem.set(T, self.items[old_len..self.len], value); } - /// Adjust the list's length to `new_len`. Doesn't initialize - /// added items if any. + /// Adjust the list's length to `new_len`. + /// Does not initialize added items if any. pub fn resize(self: *Self, new_len: usize) !void { try self.ensureCapacity(new_len); self.len = new_len; @@ -479,3 +493,14 @@ test "std.ArrayList: ArrayList(T) of struct T" { try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) }); testing.expect(root.sub_items.items[0].integer == 42); } + +test "std.ArrayList(u8) implements outStream" { + var buffer = ArrayList(u8).init(std.testing.allocator); + defer buffer.deinit(); + + const x: i32 = 42; + const y: i32 = 1234; + try buffer.outStream().print("x: {}\ny: {}\n", .{ x, y }); + + testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span()); +} diff --git a/lib/std/array_list_sentineled.zig b/lib/std/array_list_sentineled.zig new file mode 100644 index 0000000000..ee262b0322 --- /dev/null +++ b/lib/std/array_list_sentineled.zig @@ -0,0 +1,224 @@ +const std = @import("std.zig"); +const debug = std.debug; +const mem = std.mem; +const Allocator = mem.Allocator; +const assert = debug.assert; +const testing = std.testing; +const ArrayList = std.ArrayList; + +/// A contiguous, growable list of items in memory, with a sentinel after them. +/// The sentinel is maintained when appending, resizing, etc. +/// If you do not need a sentinel, consider using `ArrayList` instead. +pub fn ArrayListSentineled(comptime T: type, comptime sentinel: T) type { + return struct { + list: ArrayList(T), + + const Self = @This(); + + /// Must deinitialize with deinit. + pub fn init(allocator: *Allocator, m: []const T) !Self { + var self = try initSize(allocator, m.len); + mem.copy(T, self.list.items, m); + return self; + } + + /// Initialize memory to size bytes of undefined values. + /// Must deinitialize with deinit. + pub fn initSize(allocator: *Allocator, size: usize) !Self { + var self = initNull(allocator); + try self.resize(size); + return self; + } + + /// Initialize with capacity to hold at least num bytes. + /// Must deinitialize with deinit. + pub fn initCapacity(allocator: *Allocator, num: usize) !Self { + var self = Self{ .list = try ArrayList(T).initCapacity(allocator, num + 1) }; + self.list.appendAssumeCapacity(sentinel); + return self; + } + + /// Must deinitialize with deinit. + /// None of the other operations are valid until you do one of these: + /// * `replaceContents` + /// * `resize` + pub fn initNull(allocator: *Allocator) Self { + return Self{ .list = ArrayList(T).init(allocator) }; + } + + /// Must deinitialize with deinit. + pub fn initFromBuffer(buffer: Self) !Self { + return Self.init(buffer.list.allocator, buffer.span()); + } + + /// Takes ownership of the passed in slice. The slice must have been + /// allocated with `allocator`. + /// Must deinitialize with deinit. + pub fn fromOwnedSlice(allocator: *Allocator, slice: []T) !Self { + var self = Self{ .list = ArrayList(T).fromOwnedSlice(allocator, slice) }; + try self.list.append(sentinel); + return self; + } + + /// The caller owns the returned memory. The list becomes null and is safe to `deinit`. + pub fn toOwnedSlice(self: *Self) [:sentinel]T { + const allocator = self.list.allocator; + const result = self.list.toOwnedSlice(); + self.* = initNull(allocator); + return result[0 .. result.len - 1 :sentinel]; + } + + /// Only works when `T` is `u8`. + pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Self { + const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) { + error.Overflow => return error.OutOfMemory, + }; + var self = try Self.initSize(allocator, size); + assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size); + return self; + } + + pub fn deinit(self: *Self) void { + self.list.deinit(); + } + + pub fn span(self: var) @TypeOf(self.list.items[0 .. self.list.len - 1 :sentinel]) { + return self.list.span()[0..self.len() :sentinel]; + } + + pub fn shrink(self: *Self, new_len: usize) void { + assert(new_len <= self.len()); + self.list.shrink(new_len + 1); + self.list.items[self.len()] = sentinel; + } + + pub fn resize(self: *Self, new_len: usize) !void { + try self.list.resize(new_len + 1); + self.list.items[self.len()] = sentinel; + } + + pub fn isNull(self: Self) bool { + return self.list.len == 0; + } + + pub fn len(self: Self) usize { + return self.list.len - 1; + } + + pub fn capacity(self: Self) usize { + return if (self.list.items.len > 0) + self.list.items.len - 1 + else + 0; + } + + pub fn appendSlice(self: *Self, m: []const T) !void { + const old_len = self.len(); + try self.resize(old_len + m.len); + mem.copy(T, self.list.span()[old_len..], m); + } + + pub fn append(self: *Self, byte: T) !void { + const old_len = self.len(); + try self.resize(old_len + 1); + self.list.span()[old_len] = byte; + } + + pub fn eql(self: Self, m: []const T) bool { + return mem.eql(T, self.span(), m); + } + + pub fn startsWith(self: Self, m: []const T) bool { + if (self.len() < m.len) return false; + return mem.eql(T, self.list.items[0..m.len], m); + } + + pub fn endsWith(self: Self, m: []const T) bool { + const l = self.len(); + if (l < m.len) return false; + const start = l - m.len; + return mem.eql(T, self.list.items[start..l], m); + } + + pub fn replaceContents(self: *Self, m: []const T) !void { + try self.resize(m.len); + mem.copy(T, self.list.span(), m); + } + + /// Initializes an OutStream which will append to the list. + /// This function may be called only when `T` is `u8`. + pub fn outStream(self: *Self) std.io.OutStream(*Self, error{OutOfMemory}, appendWrite) { + return .{ .context = self }; + } + + /// Same as `append` except it returns the number of bytes written, which is always the same + /// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API. + /// This function may be called only when `T` is `u8`. + pub fn appendWrite(self: *Self, m: []const u8) !usize { + try self.appendSlice(m); + return m.len; + } + }; +} + +test "simple" { + var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, ""); + defer buf.deinit(); + + testing.expect(buf.len() == 0); + try buf.appendSlice("hello"); + try buf.appendSlice(" "); + try buf.appendSlice("world"); + testing.expect(buf.eql("hello world")); + testing.expect(mem.eql(u8, mem.spanZ(buf.span().ptr), buf.span())); + + var buf2 = try ArrayListSentineled(u8, 0).initFromBuffer(buf); + defer buf2.deinit(); + testing.expect(buf.eql(buf2.span())); + + testing.expect(buf.startsWith("hell")); + testing.expect(buf.endsWith("orld")); + + try buf2.resize(4); + testing.expect(buf.startsWith(buf2.span())); +} + +test "initSize" { + var buf = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 3); + defer buf.deinit(); + testing.expect(buf.len() == 3); + try buf.appendSlice("hello"); + testing.expect(mem.eql(u8, buf.span()[3..], "hello")); +} + +test "initCapacity" { + var buf = try ArrayListSentineled(u8, 0).initCapacity(testing.allocator, 10); + defer buf.deinit(); + testing.expect(buf.len() == 0); + testing.expect(buf.capacity() >= 10); + const old_cap = buf.capacity(); + try buf.appendSlice("hello"); + testing.expect(buf.len() == 5); + testing.expect(buf.capacity() == old_cap); + testing.expect(mem.eql(u8, buf.span(), "hello")); +} + +test "print" { + var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, ""); + defer buf.deinit(); + + try buf.outStream().print("Hello {} the {}", .{ 2, "world" }); + testing.expect(buf.eql("Hello 2 the world")); +} + +test "outStream" { + var buffer = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 0); + defer buffer.deinit(); + const buf_stream = buffer.outStream(); + + const x: i32 = 42; + const y: i32 = 1234; + try buf_stream.print("x: {}\ny: {}\n", .{ x, y }); + + testing.expect(mem.eql(u8, buffer.span(), "x: 42\ny: 1234\n")); +} diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig deleted file mode 100644 index 7971820770..0000000000 --- a/lib/std/buffer.zig +++ /dev/null @@ -1,218 +0,0 @@ -const std = @import("std.zig"); -const debug = std.debug; -const mem = std.mem; -const Allocator = mem.Allocator; -const assert = debug.assert; -const testing = std.testing; -const ArrayList = std.ArrayList; - -/// A buffer that allocates memory and maintains a null byte at the end. -pub const Buffer = struct { - list: ArrayList(u8), - - /// Must deinitialize with deinit. - pub fn init(allocator: *Allocator, m: []const u8) !Buffer { - var self = try initSize(allocator, m.len); - mem.copy(u8, self.list.items, m); - return self; - } - - /// Initialize memory to size bytes of undefined values. - /// Must deinitialize with deinit. - pub fn initSize(allocator: *Allocator, size: usize) !Buffer { - var self = initNull(allocator); - try self.resize(size); - return self; - } - - /// Initialize with capacity to hold at least num bytes. - /// Must deinitialize with deinit. - pub fn initCapacity(allocator: *Allocator, num: usize) !Buffer { - var self = Buffer{ .list = try ArrayList(u8).initCapacity(allocator, num + 1) }; - self.list.appendAssumeCapacity(0); - return self; - } - - /// Must deinitialize with deinit. - /// None of the other operations are valid until you do one of these: - /// * ::replaceContents - /// * ::resize - pub fn initNull(allocator: *Allocator) Buffer { - return Buffer{ .list = ArrayList(u8).init(allocator) }; - } - - /// Must deinitialize with deinit. - pub fn initFromBuffer(buffer: Buffer) !Buffer { - return Buffer.init(buffer.list.allocator, buffer.span()); - } - - /// Buffer takes ownership of the passed in slice. The slice must have been - /// allocated with `allocator`. - /// Must deinitialize with deinit. - pub fn fromOwnedSlice(allocator: *Allocator, slice: []u8) !Buffer { - var self = Buffer{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) }; - try self.list.append(0); - return self; - } - - /// The caller owns the returned memory. The Buffer becomes null and - /// is safe to `deinit`. - pub fn toOwnedSlice(self: *Buffer) [:0]u8 { - const allocator = self.list.allocator; - const result = self.list.toOwnedSlice(); - self.* = initNull(allocator); - return result[0 .. result.len - 1 :0]; - } - - pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer { - const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) { - error.Overflow => return error.OutOfMemory, - }; - var self = try Buffer.initSize(allocator, size); - assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size); - return self; - } - - pub fn deinit(self: *Buffer) void { - self.list.deinit(); - } - - pub fn span(self: var) @TypeOf(self.list.items[0 .. self.list.len - 1 :0]) { - return self.list.span()[0..self.len() :0]; - } - - pub const toSlice = @compileError("deprecated; use span()"); - pub const toSliceConst = @compileError("deprecated; use span()"); - - pub fn shrink(self: *Buffer, new_len: usize) void { - assert(new_len <= self.len()); - self.list.shrink(new_len + 1); - self.list.items[self.len()] = 0; - } - - pub fn resize(self: *Buffer, new_len: usize) !void { - try self.list.resize(new_len + 1); - self.list.items[self.len()] = 0; - } - - pub fn isNull(self: Buffer) bool { - return self.list.len == 0; - } - - pub fn len(self: Buffer) usize { - return self.list.len - 1; - } - - pub fn capacity(self: Buffer) usize { - return if (self.list.items.len > 0) - self.list.items.len - 1 - else - 0; - } - - pub fn append(self: *Buffer, m: []const u8) !void { - const old_len = self.len(); - try self.resize(old_len + m.len); - mem.copy(u8, self.list.span()[old_len..], m); - } - - pub fn appendByte(self: *Buffer, byte: u8) !void { - const old_len = self.len(); - try self.resize(old_len + 1); - self.list.span()[old_len] = byte; - } - - pub fn eql(self: Buffer, m: []const u8) bool { - return mem.eql(u8, self.span(), m); - } - - pub fn startsWith(self: Buffer, m: []const u8) bool { - if (self.len() < m.len) return false; - return mem.eql(u8, self.list.items[0..m.len], m); - } - - pub fn endsWith(self: Buffer, m: []const u8) bool { - const l = self.len(); - if (l < m.len) return false; - const start = l - m.len; - return mem.eql(u8, self.list.items[start..l], m); - } - - pub fn replaceContents(self: *Buffer, m: []const u8) !void { - try self.resize(m.len); - mem.copy(u8, self.list.span(), m); - } - - pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) { - return .{ .context = self }; - } - - /// Same as `append` except it returns the number of bytes written, which is always the same - /// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API. - pub fn appendWrite(self: *Buffer, m: []const u8) !usize { - try self.append(m); - return m.len; - } -}; - -test "simple Buffer" { - var buf = try Buffer.init(testing.allocator, ""); - defer buf.deinit(); - - testing.expect(buf.len() == 0); - try buf.append("hello"); - try buf.append(" "); - try buf.append("world"); - testing.expect(buf.eql("hello world")); - testing.expect(mem.eql(u8, mem.spanZ(buf.span().ptr), buf.span())); - - var buf2 = try Buffer.initFromBuffer(buf); - defer buf2.deinit(); - testing.expect(buf.eql(buf2.span())); - - testing.expect(buf.startsWith("hell")); - testing.expect(buf.endsWith("orld")); - - try buf2.resize(4); - testing.expect(buf.startsWith(buf2.span())); -} - -test "Buffer.initSize" { - var buf = try Buffer.initSize(testing.allocator, 3); - defer buf.deinit(); - testing.expect(buf.len() == 3); - try buf.append("hello"); - testing.expect(mem.eql(u8, buf.span()[3..], "hello")); -} - -test "Buffer.initCapacity" { - var buf = try Buffer.initCapacity(testing.allocator, 10); - defer buf.deinit(); - testing.expect(buf.len() == 0); - testing.expect(buf.capacity() >= 10); - const old_cap = buf.capacity(); - try buf.append("hello"); - testing.expect(buf.len() == 5); - testing.expect(buf.capacity() == old_cap); - testing.expect(mem.eql(u8, buf.span(), "hello")); -} - -test "Buffer.print" { - var buf = try Buffer.init(testing.allocator, ""); - defer buf.deinit(); - - try buf.outStream().print("Hello {} the {}", .{ 2, "world" }); - testing.expect(buf.eql("Hello 2 the world")); -} - -test "Buffer.outStream" { - var buffer = try Buffer.initSize(testing.allocator, 0); - defer buffer.deinit(); - const buf_stream = buffer.outStream(); - - const x: i32 = 42; - const y: i32 = 1234; - try buf_stream.print("x: {}\ny: {}\n", .{ x, y }); - - testing.expect(mem.eql(u8, buffer.span(), "x: 42\ny: 1234\n")); -} diff --git a/lib/std/build.zig b/lib/std/build.zig index 858f6bd6f0..ccd0ebaf8a 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1139,7 +1139,7 @@ pub const LibExeObjStep = struct { out_lib_filename: []const u8, out_pdb_filename: []const u8, packages: ArrayList(Pkg), - build_options_contents: std.Buffer, + build_options_contents: std.ArrayList(u8), system_linker_hack: bool = false, object_src: []const u8, @@ -1274,7 +1274,7 @@ pub const LibExeObjStep = struct { .lib_paths = ArrayList([]const u8).init(builder.allocator), .framework_dirs = ArrayList([]const u8).init(builder.allocator), .object_src = undefined, - .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable, + .build_options_contents = std.ArrayList(u8).init(builder.allocator), .c_std = Builder.CStd.C99, .override_lib_dir = null, .main_pkg_path = null, @@ -1847,7 +1847,7 @@ pub const LibExeObjStep = struct { } } - if (self.build_options_contents.len() > 0) { + if (self.build_options_contents.len > 0) { const build_options_file = try fs.path.join( builder.allocator, &[_][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", .{self.name}) }, @@ -1960,22 +1960,22 @@ pub const LibExeObjStep = struct { try zig_args.append(cross.cpu.model.name); } } else { - var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu="); - try mcpu_buffer.append(cross.cpu.model.name); + var mcpu_buffer = std.ArrayList(u8).init(builder.allocator); + + try mcpu_buffer.outStream().print("-mcpu={}", .{cross.cpu.model.name}); for (all_features) |feature, i_usize| { const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize); const in_cpu_set = populated_cpu_features.isEnabled(i); const in_actual_set = cross.cpu.features.isEnabled(i); if (in_cpu_set and !in_actual_set) { - try mcpu_buffer.appendByte('-'); - try mcpu_buffer.append(feature.name); + try mcpu_buffer.outStream().print("-{}", .{feature.name}); } else if (!in_cpu_set and in_actual_set) { - try mcpu_buffer.appendByte('+'); - try mcpu_buffer.append(feature.name); + try mcpu_buffer.outStream().print("+{}", .{feature.name}); } } - try zig_args.append(mcpu_buffer.span()); + + try zig_args.append(mcpu_buffer.toOwnedSlice()); } if (self.target.dynamic_linker.get()) |dynamic_linker| { diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 3013133b11..e1c489bf05 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -10,7 +10,7 @@ const windows = os.windows; const mem = std.mem; const debug = std.debug; const BufMap = std.BufMap; -const Buffer = std.Buffer; +const ArrayListSentineled = std.ArrayListSentineled; const builtin = @import("builtin"); const Os = builtin.Os; const TailQueue = std.TailQueue; @@ -757,38 +757,36 @@ fn windowsCreateProcess(app_name: [*:0]u16, cmd_line: [*:0]u16, envp_ptr: ?[*]u1 } /// Caller must dealloc. -/// Guarantees a null byte at result[result.len]. -fn windowsCreateCommandLine(allocator: *mem.Allocator, argv: []const []const u8) ![]u8 { - var buf = try Buffer.initSize(allocator, 0); +fn windowsCreateCommandLine(allocator: *mem.Allocator, argv: []const []const u8) ![:0]u8 { + var buf = try ArrayListSentineled(u8, 0).initSize(allocator, 0); defer buf.deinit(); - - var buf_stream = buf.outStream(); + const buf_stream = buf.outStream(); for (argv) |arg, arg_i| { - if (arg_i != 0) try buf.appendByte(' '); + if (arg_i != 0) try buf_stream.writeByte(' '); if (mem.indexOfAny(u8, arg, " \t\n\"") == null) { - try buf.append(arg); + try buf_stream.writeAll(arg); continue; } - try buf.appendByte('"'); + try buf_stream.writeByte('"'); var backslash_count: usize = 0; for (arg) |byte| { switch (byte) { '\\' => backslash_count += 1, '"' => { try buf_stream.writeByteNTimes('\\', backslash_count * 2 + 1); - try buf.appendByte('"'); + try buf_stream.writeByte('"'); backslash_count = 0; }, else => { try buf_stream.writeByteNTimes('\\', backslash_count); - try buf.appendByte(byte); + try buf_stream.writeByte(byte); backslash_count = 0; }, } } try buf_stream.writeByteNTimes('\\', backslash_count * 2); - try buf.appendByte('"'); + try buf_stream.writeByte('"'); } return buf.toOwnedSlice(); diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 95f1b08bd9..0eeb1758f2 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1416,13 +1416,14 @@ pub const readLinkC = @compileError("deprecated; use Dir.readLinkZ or readLinkAb pub const Walker = struct { stack: std.ArrayList(StackItem), - name_buffer: std.Buffer, + name_buffer: std.ArrayList(u8), pub const Entry = struct { /// The containing directory. This can be used to operate directly on `basename` /// rather than `path`, avoiding `error.NameTooLong` for deeply nested paths. /// The directory remains open until `next` or `deinit` is called. dir: Dir, + /// TODO make this null terminated for API convenience basename: []const u8, path: []const u8, @@ -1445,8 +1446,8 @@ pub const Walker = struct { const dirname_len = top.dirname_len; if (try top.dir_it.next()) |base| { self.name_buffer.shrink(dirname_len); - try self.name_buffer.appendByte(path.sep); - try self.name_buffer.append(base.name); + try self.name_buffer.append(path.sep); + try self.name_buffer.appendSlice(base.name); if (base.kind == .Directory) { var new_dir = top.dir_it.dir.openDir(base.name, .{ .iterate = true }) catch |err| switch (err) { error.NameTooLong => unreachable, // no path sep in base.name @@ -1456,7 +1457,7 @@ pub const Walker = struct { errdefer new_dir.close(); try self.stack.append(StackItem{ .dir_it = new_dir.iterate(), - .dirname_len = self.name_buffer.len(), + .dirname_len = self.name_buffer.len, }); } } @@ -1489,9 +1490,11 @@ pub fn walkPath(allocator: *Allocator, dir_path: []const u8) !Walker { var dir = try cwd().openDir(dir_path, .{ .iterate = true }); errdefer dir.close(); - var name_buffer = try std.Buffer.init(allocator, dir_path); + var name_buffer = std.ArrayList(u8).init(allocator); errdefer name_buffer.deinit(); + try name_buffer.appendSlice(dir_path); + var walker = Walker{ .stack = std.ArrayList(Walker.StackItem).init(allocator), .name_buffer = name_buffer, diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig index 045b0daae0..340995198f 100644 --- a/lib/std/io/in_stream.zig +++ b/lib/std/io/in_stream.zig @@ -3,7 +3,6 @@ const builtin = std.builtin; const math = std.math; const assert = std.debug.assert; const mem = std.mem; -const Buffer = std.Buffer; const testing = std.testing; pub fn InStream( diff --git a/lib/std/net.zig b/lib/std/net.zig index 5b39b8cbd4..0f7118c331 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -504,7 +504,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* var lookup_addrs = std.ArrayList(LookupAddr).init(allocator); defer lookup_addrs.deinit(); - var canon = std.Buffer.initNull(arena); + var canon = std.ArrayListSentineled(u8, 0).initNull(arena); defer canon.deinit(); try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port); @@ -539,7 +539,7 @@ const DAS_ORDER_SHIFT = 0; fn linuxLookupName( addrs: *std.ArrayList(LookupAddr), - canon: *std.Buffer, + canon: *std.ArrayListSentineled(u8, 0), opt_name: ?[]const u8, family: os.sa_family_t, flags: u32, @@ -798,7 +798,7 @@ fn linuxLookupNameFromNull( fn linuxLookupNameFromHosts( addrs: *std.ArrayList(LookupAddr), - canon: *std.Buffer, + canon: *std.ArrayListSentineled(u8, 0), name: []const u8, family: os.sa_family_t, port: u16, @@ -868,7 +868,7 @@ pub fn isValidHostName(hostname: []const u8) bool { fn linuxLookupNameFromDnsSearch( addrs: *std.ArrayList(LookupAddr), - canon: *std.Buffer, + canon: *std.ArrayListSentineled(u8, 0), name: []const u8, family: os.sa_family_t, port: u16, @@ -901,12 +901,12 @@ fn linuxLookupNameFromDnsSearch( // the full requested name to name_from_dns. try canon.resize(canon_name.len); mem.copy(u8, canon.span(), canon_name); - try canon.appendByte('.'); + try canon.append('.'); var tok_it = mem.tokenize(search, " \t"); while (tok_it.next()) |tok| { canon.shrink(canon_name.len + 1); - try canon.append(tok); + try canon.appendSlice(tok); try linuxLookupNameFromDns(addrs, canon, canon.span(), family, rc, port); if (addrs.len != 0) return; } @@ -917,13 +917,13 @@ fn linuxLookupNameFromDnsSearch( const dpc_ctx = struct { addrs: *std.ArrayList(LookupAddr), - canon: *std.Buffer, + canon: *std.ArrayListSentineled(u8, 0), port: u16, }; fn linuxLookupNameFromDns( addrs: *std.ArrayList(LookupAddr), - canon: *std.Buffer, + canon: *std.ArrayListSentineled(u8, 0), name: []const u8, family: os.sa_family_t, rc: ResolvConf, @@ -978,7 +978,7 @@ const ResolvConf = struct { attempts: u32, ndots: u32, timeout: u32, - search: std.Buffer, + search: std.ArrayListSentineled(u8, 0), ns: std.ArrayList(LookupAddr), fn deinit(rc: *ResolvConf) void { @@ -993,7 +993,7 @@ const ResolvConf = struct { fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void { rc.* = ResolvConf{ .ns = std.ArrayList(LookupAddr).init(allocator), - .search = std.Buffer.initNull(allocator), + .search = std.ArrayListSentineled(u8, 0).initNull(allocator), .ndots = 1, .timeout = 5, .attempts = 2, diff --git a/lib/std/std.zig b/lib/std/std.zig index 9277370ca6..4ea8e7170b 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -1,10 +1,10 @@ pub const AlignedArrayList = @import("array_list.zig").AlignedArrayList; pub const ArrayList = @import("array_list.zig").ArrayList; +pub const ArrayListSentineled = @import("array_list_sentineled.zig").ArrayListSentineled; pub const AutoHashMap = @import("hash_map.zig").AutoHashMap; pub const BloomFilter = @import("bloom_filter.zig").BloomFilter; pub const BufMap = @import("buf_map.zig").BufMap; pub const BufSet = @import("buf_set.zig").BufSet; -pub const Buffer = @import("buffer.zig").Buffer; pub const ChildProcess = @import("child_process.zig").ChildProcess; pub const DynLib = @import("dynamic_library.zig").DynLib; pub const HashMap = @import("hash_map.zig").HashMap; diff --git a/lib/std/target.zig b/lib/std/target.zig index 8e1b9f8736..3f18791eb9 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -967,15 +967,15 @@ pub const Target = struct { pub const stack_align = 16; - pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 { + pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { return std.zig.CrossTarget.fromTarget(self).zigTriple(allocator); } - pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 { - return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); + pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 { + return std.fmt.allocPrint(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) }); } - pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 { + pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 { return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi); } diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig index bea69b3978..4d19ecee8c 100644 --- a/lib/std/zig/cross_target.zig +++ b/lib/std/zig/cross_target.zig @@ -495,17 +495,19 @@ pub const CrossTarget = struct { return self.isNativeCpu() and self.isNativeOs() and self.abi == null; } - pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![:0]u8 { + pub fn zigTriple(self: CrossTarget, allocator: *mem.Allocator) error{OutOfMemory}![]u8 { if (self.isNative()) { - return mem.dupeZ(allocator, u8, "native"); + return mem.dupe(allocator, u8, "native"); } const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native"; const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native"; - var result = try std.Buffer.allocPrint(allocator, "{}-{}", .{ arch_name, os_name }); + var result = std.ArrayList(u8).init(allocator); defer result.deinit(); + try result.outStream().print("{}-{}", .{ arch_name, os_name }); + // The zig target syntax does not allow specifying a max os version with no min, so // if either are present, we need the min. if (self.os_version_min != null or self.os_version_max != null) { @@ -532,13 +534,13 @@ pub const CrossTarget = struct { return result.toOwnedSlice(); } - pub fn allocDescription(self: CrossTarget, allocator: *mem.Allocator) ![:0]u8 { + pub fn allocDescription(self: CrossTarget, allocator: *mem.Allocator) ![]u8 { // TODO is there anything else worthy of the description that is not // already captured in the triple? return self.zigTriple(allocator); } - pub fn linuxTriple(self: CrossTarget, allocator: *mem.Allocator) ![:0]u8 { + pub fn linuxTriple(self: CrossTarget, allocator: *mem.Allocator) ![]u8 { return Target.linuxTripleSimple(allocator, self.getCpuArch(), self.getOsTag(), self.getAbi()); } @@ -549,7 +551,7 @@ pub const CrossTarget = struct { pub const VcpkgLinkage = std.builtin.LinkMode; /// Returned slice must be freed by the caller. - pub fn vcpkgTriplet(self: CrossTarget, allocator: *mem.Allocator, linkage: VcpkgLinkage) ![:0]u8 { + pub fn vcpkgTriplet(self: CrossTarget, allocator: *mem.Allocator, linkage: VcpkgLinkage) ![]u8 { const arch = switch (self.getCpuArch()) { .i386 => "x86", .x86_64 => "x64", @@ -580,7 +582,7 @@ pub const CrossTarget = struct { .Dynamic => "", }; - return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix }); + return std.fmt.allocPrint(allocator, "{}-{}{}", .{ arch, os, static_suffix }); } pub const Executor = union(enum) { diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 136e323fe6..91921786a2 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -2953,7 +2953,7 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b return error.ParseError; } - var buffer = try std.Buffer.initSize(allocator, 0); + var buffer = std.ArrayList(u8).init(allocator); errdefer buffer.deinit(); anything_changed.* = try std.zig.render(allocator, buffer.outStream(), tree); diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index e10d66d1f6..585ba6c51a 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -45,7 +45,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) // Don't use ZIG_VERSION_STRING here. LLVM misparses it when it includes // the git revision. - const producer = try std.Buffer.allocPrint(&code.arena.allocator, "zig {}.{}.{}", .{ + const producer = try std.fmt.allocPrintZ(&code.arena.allocator, "zig {}.{}.{}", .{ @as(u32, c.ZIG_VERSION_MAJOR), @as(u32, c.ZIG_VERSION_MINOR), @as(u32, c.ZIG_VERSION_PATCH), @@ -62,7 +62,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) dibuilder, DW.LANG_C99, compile_unit_file, - producer.span(), + producer, is_optimized, flags, runtime_version, diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index 5e2b9ad899..8f9fe9ebc2 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -2,7 +2,7 @@ const std = @import("std"); const io = std.io; const mem = std.mem; const Allocator = mem.Allocator; -const Buffer = std.Buffer; +const ArrayListSentineled = std.ArrayListSentineled; const llvm = @import("llvm.zig"); const c = @import("c.zig"); const builtin = std.builtin; @@ -123,8 +123,8 @@ pub const LlvmHandle = struct { pub const Compilation = struct { zig_compiler: *ZigCompiler, - name: Buffer, - llvm_triple: Buffer, + name: ArrayListSentineled(u8, 0), + llvm_triple: ArrayListSentineled(u8, 0), root_src_path: ?[]const u8, target: std.Target, llvm_target: *llvm.Target, @@ -444,7 +444,7 @@ pub const Compilation = struct { comp.arena_allocator.deinit(); } - comp.name = try Buffer.init(comp.arena(), name); + comp.name = try ArrayListSentineled(u8, 0).init(comp.arena(), name); comp.llvm_triple = try util.getLLVMTriple(comp.arena(), target); comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple); comp.zig_std_dir = try fs.path.join(comp.arena(), &[_][]const u8{ zig_lib_dir, "std" }); @@ -1151,7 +1151,7 @@ pub const Compilation = struct { /// If the temporary directory for this compilation has not been created, it creates it. /// Then it creates a random file name in that dir and returns it. - pub fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer { + pub fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !ArrayListSentineled(u8, 0) { const tmp_dir = try self.getTmpDir(); const file_prefix = self.getRandomFileName(); @@ -1161,7 +1161,7 @@ pub const Compilation = struct { const full_path = try fs.path.join(self.gpa(), &[_][]const u8{ tmp_dir, file_name[0..] }); errdefer self.gpa().free(full_path); - return Buffer.fromOwnedSlice(self.gpa(), full_path); + return ArrayListSentineled(u8, 0).fromOwnedSlice(self.gpa(), full_path); } /// If the temporary directory for this Compilation has not been created, creates it. @@ -1279,7 +1279,7 @@ fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void { const fn_type = try analyzeFnType(comp, tree_scope, fn_decl.base.parent_scope, fn_decl.fn_proto); defer fn_type.base.base.deref(comp); - var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name); + var symbol_name = try std.ArrayListSentineled(u8, 0).init(comp.gpa(), fn_decl.base.name); var symbol_name_consumed = false; errdefer if (!symbol_name_consumed) symbol_name.deinit(); @@ -1426,7 +1426,7 @@ fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void { ); defer fn_type.base.base.deref(comp); - var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name); + var symbol_name = try std.ArrayListSentineled(u8, 0).init(comp.gpa(), fn_decl.base.name); var symbol_name_consumed = false; defer if (!symbol_name_consumed) symbol_name.deinit(); diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig index 6eba0c759c..cad12834a7 100644 --- a/src-self-hosted/dep_tokenizer.zig +++ b/src-self-hosted/dep_tokenizer.zig @@ -33,7 +33,7 @@ pub const Tokenizer = struct { break; // advance }, else => { - self.state = State{ .target = try std.Buffer.initSize(&self.arena.allocator, 0) }; + self.state = State{ .target = try std.ArrayListSentineled(u8, 0).initSize(&self.arena.allocator, 0) }; }, }, .target => |*target| switch (char) { @@ -53,7 +53,7 @@ pub const Tokenizer = struct { break; // advance }, else => { - try target.appendByte(char); + try target.append(char); break; // advance }, }, @@ -62,24 +62,24 @@ pub const Tokenizer = struct { return self.errorIllegalChar(self.index, char, "bad target escape", .{}); }, ' ', '#', '\\' => { - try target.appendByte(char); + try target.append(char); self.state = State{ .target = target.* }; break; // advance }, '$' => { - try target.append(self.bytes[self.index - 1 .. self.index]); + try target.appendSlice(self.bytes[self.index - 1 .. self.index]); self.state = State{ .target_dollar_sign = target.* }; break; // advance }, else => { - try target.append(self.bytes[self.index - 1 .. self.index + 1]); + try target.appendSlice(self.bytes[self.index - 1 .. self.index + 1]); self.state = State{ .target = target.* }; break; // advance }, }, .target_dollar_sign => |*target| switch (char) { '$' => { - try target.appendByte(char); + try target.append(char); self.state = State{ .target = target.* }; break; // advance }, @@ -125,7 +125,7 @@ pub const Tokenizer = struct { continue; }, else => { - try target.append(self.bytes[self.index - 2 .. self.index + 1]); + try target.appendSlice(self.bytes[self.index - 2 .. self.index + 1]); self.state = State{ .target = target.* }; break; }, @@ -144,11 +144,11 @@ pub const Tokenizer = struct { break; // advance }, '"' => { - self.state = State{ .prereq_quote = try std.Buffer.initSize(&self.arena.allocator, 0) }; + self.state = State{ .prereq_quote = try std.ArrayListSentineled(u8, 0).initSize(&self.arena.allocator, 0) }; break; // advance }, else => { - self.state = State{ .prereq = try std.Buffer.initSize(&self.arena.allocator, 0) }; + self.state = State{ .prereq = try std.ArrayListSentineled(u8, 0).initSize(&self.arena.allocator, 0) }; }, }, .rhs_continuation => switch (char) { @@ -181,7 +181,7 @@ pub const Tokenizer = struct { return Token{ .id = .prereq, .bytes = bytes }; }, else => { - try prereq.appendByte(char); + try prereq.append(char); break; // advance }, }, @@ -201,7 +201,7 @@ pub const Tokenizer = struct { break; // advance }, else => { - try prereq.appendByte(char); + try prereq.append(char); break; // advance }, }, @@ -218,7 +218,7 @@ pub const Tokenizer = struct { }, else => { // not continuation - try prereq.append(self.bytes[self.index - 1 .. self.index + 1]); + try prereq.appendSlice(self.bytes[self.index - 1 .. self.index + 1]); self.state = State{ .prereq = prereq.* }; break; // advance }, @@ -300,25 +300,25 @@ pub const Tokenizer = struct { } fn errorf(self: *Tokenizer, comptime fmt: []const u8, args: var) Error { - self.error_text = (try std.Buffer.allocPrint(&self.arena.allocator, fmt, args)).span(); + self.error_text = try std.fmt.allocPrintZ(&self.arena.allocator, fmt, args); return Error.InvalidInput; } fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error { - var buffer = try std.Buffer.initSize(&self.arena.allocator, 0); + var buffer = try std.ArrayListSentineled(u8, 0).initSize(&self.arena.allocator, 0); try buffer.outStream().print(fmt, args); - try buffer.append(" '"); - var out = makeOutput(std.Buffer.append, &buffer); + try buffer.appendSlice(" '"); + var out = makeOutput(std.ArrayListSentineled(u8, 0).appendSlice, &buffer); try printCharValues(&out, bytes); - try buffer.append("'"); + try buffer.appendSlice("'"); try buffer.outStream().print(" at position {}", .{position - (bytes.len - 1)}); self.error_text = buffer.span(); return Error.InvalidInput; } fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error { - var buffer = try std.Buffer.initSize(&self.arena.allocator, 0); - try buffer.append("illegal char "); + var buffer = try std.ArrayListSentineled(u8, 0).initSize(&self.arena.allocator, 0); + try buffer.appendSlice("illegal char "); try printUnderstandableChar(&buffer, char); try buffer.outStream().print(" at position {}", .{position}); if (fmt.len != 0) try buffer.outStream().print(": " ++ fmt, args); @@ -333,18 +333,18 @@ pub const Tokenizer = struct { const State = union(enum) { lhs: void, - target: std.Buffer, - target_reverse_solidus: std.Buffer, - target_dollar_sign: std.Buffer, - target_colon: std.Buffer, - target_colon_reverse_solidus: std.Buffer, + target: std.ArrayListSentineled(u8, 0), + target_reverse_solidus: std.ArrayListSentineled(u8, 0), + target_dollar_sign: std.ArrayListSentineled(u8, 0), + target_colon: std.ArrayListSentineled(u8, 0), + target_colon_reverse_solidus: std.ArrayListSentineled(u8, 0), rhs: void, rhs_continuation: void, rhs_continuation_linefeed: void, - prereq_quote: std.Buffer, - prereq: std.Buffer, - prereq_continuation: std.Buffer, - prereq_continuation_linefeed: std.Buffer, + prereq_quote: std.ArrayListSentineled(u8, 0), + prereq: std.ArrayListSentineled(u8, 0), + prereq_continuation: std.ArrayListSentineled(u8, 0), + prereq_continuation_linefeed: std.ArrayListSentineled(u8, 0), }; const Token = struct { @@ -841,28 +841,28 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void { defer arena_allocator.deinit(); var it = Tokenizer.init(arena, input); - var buffer = try std.Buffer.initSize(arena, 0); + var buffer = try std.ArrayListSentineled(u8, 0).initSize(arena, 0); var i: usize = 0; while (true) { const r = it.next() catch |err| { switch (err) { Tokenizer.Error.InvalidInput => { - if (i != 0) try buffer.append("\n"); - try buffer.append("ERROR: "); - try buffer.append(it.error_text); + if (i != 0) try buffer.appendSlice("\n"); + try buffer.appendSlice("ERROR: "); + try buffer.appendSlice(it.error_text); }, else => return err, } break; }; const token = r orelse break; - if (i != 0) try buffer.append("\n"); - try buffer.append(@tagName(token.id)); - try buffer.append(" = {"); + if (i != 0) try buffer.appendSlice("\n"); + try buffer.appendSlice(@tagName(token.id)); + try buffer.appendSlice(" = {"); for (token.bytes) |b| { - try buffer.appendByte(printable_char_tab[b]); + try buffer.append(printable_char_tab[b]); } - try buffer.append("}"); + try buffer.appendSlice("}"); i += 1; } const got: []const u8 = buffer.span(); @@ -995,13 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void { } } -fn printUnderstandableChar(buffer: *std.Buffer, char: u8) !void { +fn printUnderstandableChar(buffer: *std.ArrayListSentineled(u8, 0), char: u8) !void { if (!std.ascii.isPrint(char) or char == ' ') { try buffer.outStream().print("\\x{X:2}", .{char}); } else { - try buffer.append("'"); - try buffer.appendByte(printable_char_tab[char]); - try buffer.append("'"); + try buffer.appendSlice("'"); + try buffer.append(printable_char_tab[char]); + try buffer.appendSlice("'"); } } diff --git a/src-self-hosted/errmsg.zig b/src-self-hosted/errmsg.zig index 606c8c4b3a..5775c1df83 100644 --- a/src-self-hosted/errmsg.zig +++ b/src-self-hosted/errmsg.zig @@ -158,7 +158,7 @@ pub const Msg = struct { parse_error: *const ast.Error, ) !*Msg { const loc_token = parse_error.loc(); - var text_buf = try std.Buffer.initSize(comp.gpa(), 0); + var text_buf = std.ArrayList(u8).init(comp.gpa()); defer text_buf.deinit(); const realpath_copy = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath); @@ -197,7 +197,7 @@ pub const Msg = struct { realpath: []const u8, ) !*Msg { const loc_token = parse_error.loc(); - var text_buf = try std.Buffer.initSize(allocator, 0); + var text_buf = std.ArrayList(u8).init(allocator); defer text_buf.deinit(); const realpath_copy = try mem.dupe(allocator, u8, realpath); diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 9aa7b39c9b..11708e2a31 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -14,11 +14,11 @@ usingnamespace @import("windows_sdk.zig"); /// See the render function implementation for documentation of the fields. pub const LibCInstallation = struct { - include_dir: ?[:0]const u8 = null, - sys_include_dir: ?[:0]const u8 = null, - crt_dir: ?[:0]const u8 = null, - msvc_lib_dir: ?[:0]const u8 = null, - kernel32_lib_dir: ?[:0]const u8 = null, + include_dir: ?[]const u8 = null, + sys_include_dir: ?[]const u8 = null, + crt_dir: ?[]const u8 = null, + msvc_lib_dir: ?[]const u8 = null, + kernel32_lib_dir: ?[]const u8 = null, pub const FindError = error{ OutOfMemory, @@ -327,13 +327,12 @@ pub const LibCInstallation = struct { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(allocator, 0); + var result_buf = std.ArrayList([]const u8).init(allocator); defer result_buf.deinit(); for (searches) |search| { result_buf.shrink(0); - const stream = result_buf.outStream(); - try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version }); + try result_buf.outStream().print("{}\\Include\\{}\\ucrt", .{ search.path, search.version }); var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { error.FileNotFound, @@ -367,7 +366,7 @@ pub const LibCInstallation = struct { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(allocator, 0); + var result_buf = try std.ArrayList([]const u8).init(allocator); defer result_buf.deinit(); const arch_sub_dir = switch (builtin.arch) { @@ -379,8 +378,7 @@ pub const LibCInstallation = struct { for (searches) |search| { result_buf.shrink(0); - const stream = result_buf.outStream(); - try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir }); + try result_buf.outStream().print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir }); var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { error.FileNotFound, @@ -422,7 +420,7 @@ pub const LibCInstallation = struct { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(allocator, 0); + var result_buf = try std.ArrayList([]const u8).init(allocator); defer result_buf.deinit(); const arch_sub_dir = switch (builtin.arch) { @@ -470,12 +468,10 @@ pub const LibCInstallation = struct { const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound; const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound; - var result_buf = try std.Buffer.init(allocator, up2); - defer result_buf.deinit(); + const dir_path = try fs.path.join(allocator, &[_][]const u8{ up2, "include" }); + errdefer allocator.free(dir_path); - try result_buf.append("\\include"); - - var dir = fs.cwd().openDir(result_buf.span(), .{}) catch |err| switch (err) { + var dir = fs.cwd().openDir(dir_path, .{}) catch |err| switch (err) { error.FileNotFound, error.NotDir, error.NoDevice, @@ -490,7 +486,7 @@ pub const LibCInstallation = struct { else => return error.FileSystem, }; - self.sys_include_dir = result_buf.toOwnedSlice(); + self.sys_include_dir = dir_path; } fn findNativeMsvcLibDir( diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index ee2ef53d22..013a6248cc 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -15,10 +15,10 @@ const Context = struct { link_in_crt: bool, link_err: error{OutOfMemory}!void, - link_msg: std.Buffer, + link_msg: std.ArrayListSentineled(u8, 0), libc: *LibCInstallation, - out_file_path: std.Buffer, + out_file_path: std.ArrayListSentineled(u8, 0), }; pub fn link(comp: *Compilation) !void { @@ -34,9 +34,9 @@ pub fn link(comp: *Compilation) !void { }; defer ctx.arena.deinit(); ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator); - ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator); + ctx.link_msg = std.ArrayListSentineled(u8, 0).initNull(&ctx.arena.allocator); - ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.span()); + ctx.out_file_path = try std.ArrayListSentineled(u8, 0).init(&ctx.arena.allocator, comp.name.span()); switch (comp.kind) { .Exe => { try ctx.out_file_path.append(comp.target.exeFileExt()); diff --git a/src-self-hosted/package.zig b/src-self-hosted/package.zig index c8d46c7719..3111555878 100644 --- a/src-self-hosted/package.zig +++ b/src-self-hosted/package.zig @@ -1,11 +1,11 @@ const std = @import("std"); const mem = std.mem; const assert = std.debug.assert; -const Buffer = std.Buffer; +const ArrayListSentineled = std.ArrayListSentineled; pub const Package = struct { - root_src_dir: Buffer, - root_src_path: Buffer, + root_src_dir: ArrayListSentineled(u8, 0), + root_src_path: ArrayListSentineled(u8, 0), /// relative to root_src_dir table: Table, @@ -17,8 +17,8 @@ pub const Package = struct { pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package { const ptr = try allocator.create(Package); ptr.* = Package{ - .root_src_dir = try Buffer.init(allocator, root_src_dir), - .root_src_path = try Buffer.init(allocator, root_src_path), + .root_src_dir = try ArrayListSentineled(u8, 0).init(allocator, root_src_dir), + .root_src_path = try ArrayListSentineled(u8, 0).init(allocator, root_src_path), .table = Table.init(allocator), }; return ptr; diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index d9b763912c..8dd2ee876d 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -8,7 +8,7 @@ const fs = std.fs; const process = std.process; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; -const Buffer = std.Buffer; +const ArrayListSentineled = std.ArrayListSentineled; const Target = std.Target; const CrossTarget = std.zig.CrossTarget; const self_hosted_main = @import("main.zig"); @@ -411,12 +411,13 @@ fn printErrMsgToFile( const start_loc = tree.tokenLocationPtr(0, first_token); const end_loc = tree.tokenLocationPtr(first_token.end, last_token); - var text_buf = try std.Buffer.initSize(allocator, 0); - const out_stream = &text_buf.outStream(); + var text_buf = std.ArrayList(u8).init(allocator); + defer text_buf.deinit(); + const out_stream = text_buf.outStream(); try parse_error.render(&tree.tokens, out_stream); - const text = text_buf.toOwnedSlice(); + const text = text_buf.span(); - const stream = &file.outStream(); + const stream = file.outStream(); try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text }); if (!color_on) return; @@ -448,7 +449,7 @@ export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void { export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult { const otoken = self.handle.next() catch { - const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text"); + const textz = std.ArrayListSentineled(u8, 0).init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text"); return stage2_DepNextResult{ .type_id = .error_, .textz = textz.span().ptr, @@ -460,7 +461,7 @@ export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextRes .textz = undefined, }; }; - const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); + const textz = std.ArrayListSentineled(u8, 0).init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); return stage2_DepNextResult{ .type_id = switch (token.id) { .target => .target, @@ -740,15 +741,15 @@ fn stage2TargetParse( // ABI warning const Stage2LibCInstallation = extern struct { - include_dir: [*:0]const u8, + include_dir: [*]const u8, include_dir_len: usize, - sys_include_dir: [*:0]const u8, + sys_include_dir: [*]const u8, sys_include_dir_len: usize, - crt_dir: [*:0]const u8, + crt_dir: [*]const u8, crt_dir_len: usize, - msvc_lib_dir: [*:0]const u8, + msvc_lib_dir: [*]const u8, msvc_lib_dir_len: usize, - kernel32_lib_dir: [*:0]const u8, + kernel32_lib_dir: [*]const u8, kernel32_lib_dir_len: usize, fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { @@ -792,19 +793,19 @@ const Stage2LibCInstallation = extern struct { fn toStage2(self: Stage2LibCInstallation) LibCInstallation { var libc: LibCInstallation = .{}; if (self.include_dir_len != 0) { - libc.include_dir = self.include_dir[0..self.include_dir_len :0]; + libc.include_dir = self.include_dir[0..self.include_dir_len]; } if (self.sys_include_dir_len != 0) { - libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; + libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len]; } if (self.crt_dir_len != 0) { - libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; + libc.crt_dir = self.crt_dir[0..self.crt_dir_len]; } if (self.msvc_lib_dir_len != 0) { - libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; + libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len]; } if (self.kernel32_lib_dir_len != 0) { - libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; + libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len]; } return libc; } @@ -923,14 +924,14 @@ const Stage2Target = extern struct { var dynamic_linker: ?[*:0]u8 = null; const target = try crossTargetToTarget(cross_target, &dynamic_linker); - var cache_hash = try std.Buffer.allocPrint(allocator, "{}\n{}\n", .{ + var cache_hash = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, "{}\n{}\n", .{ target.cpu.model.name, target.cpu.features.asBytes(), }); defer cache_hash.deinit(); const generic_arch_name = target.cpu.arch.genericName(); - var cpu_builtin_str_buffer = try std.Buffer.allocPrint(allocator, + var cpu_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, \\Cpu{{ \\ .arch = .{}, \\ .model = &Target.{}.cpu.{}, @@ -945,7 +946,7 @@ const Stage2Target = extern struct { }); defer cpu_builtin_str_buffer.deinit(); - var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); + var llvm_features_buffer = try std.ArrayListSentineled(u8, 0).initSize(allocator, 0); defer llvm_features_buffer.deinit(); // Unfortunately we have to do the work twice, because Clang does not support @@ -960,17 +961,17 @@ const Stage2Target = extern struct { if (feature.llvm_name) |llvm_name| { const plus_or_minus = "-+"[@boolToInt(is_enabled)]; - try llvm_features_buffer.appendByte(plus_or_minus); - try llvm_features_buffer.append(llvm_name); - try llvm_features_buffer.append(","); + try llvm_features_buffer.append(plus_or_minus); + try llvm_features_buffer.appendSlice(llvm_name); + try llvm_features_buffer.appendSlice(","); } if (is_enabled) { // TODO some kind of "zig identifier escape" function rather than // unconditionally using @"" syntax - try cpu_builtin_str_buffer.append(" .@\""); - try cpu_builtin_str_buffer.append(feature.name); - try cpu_builtin_str_buffer.append("\",\n"); + try cpu_builtin_str_buffer.appendSlice(" .@\""); + try cpu_builtin_str_buffer.appendSlice(feature.name); + try cpu_builtin_str_buffer.appendSlice("\",\n"); } } @@ -989,7 +990,7 @@ const Stage2Target = extern struct { }, } - try cpu_builtin_str_buffer.append( + try cpu_builtin_str_buffer.appendSlice( \\ }), \\}; \\ @@ -998,7 +999,7 @@ const Stage2Target = extern struct { assert(mem.endsWith(u8, llvm_features_buffer.span(), ",")); llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); - var os_builtin_str_buffer = try std.Buffer.allocPrint(allocator, + var os_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, \\Os{{ \\ .tag = .{}, \\ .version_range = .{{ @@ -1041,7 +1042,7 @@ const Stage2Target = extern struct { .emscripten, .uefi, .other, - => try os_builtin_str_buffer.append(" .none = {} }\n"), + => try os_builtin_str_buffer.appendSlice(" .none = {} }\n"), .freebsd, .macosx, @@ -1117,9 +1118,9 @@ const Stage2Target = extern struct { @tagName(target.os.version_range.windows.max), }), } - try os_builtin_str_buffer.append("};\n"); + try os_builtin_str_buffer.appendSlice("};\n"); - try cache_hash.append( + try cache_hash.appendSlice( os_builtin_str_buffer.span()[os_builtin_str_ver_start_index..os_builtin_str_buffer.len()], ); diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index f8eec3578f..6ba7fc8ca1 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -209,7 +209,7 @@ const Scope = struct { pub const Context = struct { tree: *ast.Tree, - source_buffer: *std.Buffer, + source_buffer: *std.ArrayList(u8), err: Error, source_manager: *ZigClangSourceManager, decl_table: DeclTable, @@ -275,7 +275,7 @@ pub fn translate( const tree = try tree_arena.allocator.create(ast.Tree); tree.* = ast.Tree{ - .source = undefined, // need to use Buffer.toOwnedSlice later + .source = undefined, // need to use toOwnedSlice later .root_node = undefined, .arena_allocator = tree_arena, .tokens = undefined, // can't reference the allocator yet @@ -296,7 +296,7 @@ pub fn translate( .eof_token = undefined, }; - var source_buffer = try std.Buffer.initSize(arena, 0); + var source_buffer = std.ArrayList(u8).init(arena); var context = Context{ .tree = tree, @@ -4309,7 +4309,7 @@ fn makeRestorePoint(c: *Context) RestorePoint { return RestorePoint{ .c = c, .token_index = c.tree.tokens.len, - .src_buf_index = c.source_buffer.len(), + .src_buf_index = c.source_buffer.len, }; } @@ -4771,11 +4771,11 @@ fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenInd fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex { assert(token_id != .Invalid); - const start_index = c.source_buffer.len(); + const start_index = c.source_buffer.len; errdefer c.source_buffer.shrink(start_index); try c.source_buffer.outStream().print(format, args); - const end_index = c.source_buffer.len(); + const end_index = c.source_buffer.len; const token_index = c.tree.tokens.len; const new_token = try c.tree.tokens.addOne(); errdefer c.tree.tokens.shrink(token_index); @@ -4785,7 +4785,7 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, .start = start_index, .end = end_index, }; - try c.source_buffer.appendByte(' '); + try c.source_buffer.append(' '); return token_index; } diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index 70ed754cea..6adad9fa67 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -387,10 +387,10 @@ pub const Type = struct { }; errdefer comp.gpa().destroy(self); - var name_buf = try std.Buffer.initSize(comp.gpa(), 0); + var name_buf = std.ArrayList(u8).init(comp.gpa()); defer name_buf.deinit(); - const name_stream = &std.io.BufferOutStream.init(&name_buf).stream; + const name_stream = name_buf.outStream(); switch (key.data) { .Generic => |generic| { diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig index 4699b453ef..6585fd7c6f 100644 --- a/src-self-hosted/util.zig +++ b/src-self-hosted/util.zig @@ -16,11 +16,11 @@ pub fn getDarwinArchString(self: Target) [:0]const u8 { } } -pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target { +pub fn llvmTargetFromTriple(triple: [:0]const u8) !*llvm.Target { var result: *llvm.Target = undefined; var err_msg: [*:0]u8 = undefined; - if (llvm.GetTargetFromTriple(triple.span(), &result, &err_msg) != 0) { - std.debug.warn("triple: {s} error: {s}\n", .{ triple.span(), err_msg }); + if (llvm.GetTargetFromTriple(triple, &result, &err_msg) != 0) { + std.debug.warn("triple: {s} error: {s}\n", .{ triple, err_msg }); return error.UnsupportedTarget; } return result; @@ -34,14 +34,14 @@ pub fn initializeAllTargets() void { llvm.InitializeAllAsmParsers(); } -pub fn getLLVMTriple(allocator: *std.mem.Allocator, target: std.Target) !std.Buffer { - var result = try std.Buffer.initSize(allocator, 0); - errdefer result.deinit(); +pub fn getLLVMTriple(allocator: *std.mem.Allocator, target: std.Target) ![:0]u8 { + var result = try std.ArrayListSentineled(u8, 0).initSize(allocator, 0); + defer result.deinit(); try result.outStream().print( "{}-unknown-{}-{}", .{ @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi) }, ); - return result; + return result.toOwnedSlice(); } diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index c2d91eecab..c35289e238 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -3,7 +3,7 @@ const Scope = @import("scope.zig").Scope; const Compilation = @import("compilation.zig").Compilation; const ObjectFile = @import("codegen.zig").ObjectFile; const llvm = @import("llvm.zig"); -const Buffer = std.Buffer; +const ArrayListSentineled = std.ArrayListSentineled; const assert = std.debug.assert; /// Values are ref-counted, heap-allocated, and copy-on-write @@ -131,9 +131,9 @@ pub const Value = struct { /// The main external name that is used in the .o file. /// TODO https://github.com/ziglang/zig/issues/265 - symbol_name: Buffer, + symbol_name: ArrayListSentineled(u8, 0), - pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto { + pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: ArrayListSentineled(u8, 0)) !*FnProto { const self = try comp.gpa().create(FnProto); self.* = FnProto{ .base = Value{ @@ -171,7 +171,7 @@ pub const Value = struct { /// The main external name that is used in the .o file. /// TODO https://github.com/ziglang/zig/issues/265 - symbol_name: Buffer, + symbol_name: ArrayListSentineled(u8, 0), /// parent should be the top level decls or container decls fndef_scope: *Scope.FnDef, @@ -183,13 +183,13 @@ pub const Value = struct { block_scope: ?*Scope.Block, /// Path to the object file that contains this function - containing_object: Buffer, + containing_object: ArrayListSentineled(u8, 0), link_set_node: *std.TailQueue(?*Value.Fn).Node, /// Creates a Fn value with 1 ref /// Takes ownership of symbol_name - pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn { + pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: ArrayListSentineled(u8, 0)) !*Fn { const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node); link_set_node.* = Compilation.FnLinkSet.Node{ .data = null, @@ -209,7 +209,7 @@ pub const Value = struct { .child_scope = &fndef_scope.base, .block_scope = null, .symbol_name = symbol_name, - .containing_object = Buffer.initNull(comp.gpa()), + .containing_object = ArrayListSentineled(u8, 0).initNull(comp.gpa()), .link_set_node = link_set_node, }; fn_type.base.base.ref(); diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index 3cff34ea5c..c12d8f29ef 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -27,11 +27,17 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) { void cache_mem(CacheHash *ch, const char *ptr, size_t len) { assert(ch->manifest_file_path == nullptr); assert(ptr != nullptr); - // + 1 to include the null byte blake2b_update(&ch->blake, ptr, len); } +void cache_slice(CacheHash *ch, Slice slice) { + // mix the length into the hash so that two juxtaposed cached slices can't collide + cache_usize(ch, slice.len); + cache_mem(ch, slice.ptr, slice.len); +} + void cache_str(CacheHash *ch, const char *ptr) { + // + 1 to include the null byte cache_mem(ch, ptr, strlen(ptr) + 1); } diff --git a/src/cache_hash.hpp b/src/cache_hash.hpp index 9e4c41b1e0..ba2434076a 100644 --- a/src/cache_hash.hpp +++ b/src/cache_hash.hpp @@ -36,6 +36,7 @@ void cache_init(CacheHash *ch, Buf *manifest_dir); // Next, use the hash population functions to add the initial parameters. void cache_mem(CacheHash *ch, const char *ptr, size_t len); +void cache_slice(CacheHash *ch, Slice slice); void cache_str(CacheHash *ch, const char *ptr); void cache_int(CacheHash *ch, int x); void cache_bool(CacheHash *ch, bool x); diff --git a/src/codegen.cpp b/src/codegen.cpp index d36e398bf7..24e77e8689 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9123,21 +9123,29 @@ static void detect_libc(CodeGen *g) { g->libc_include_dir_len = 0; g->libc_include_dir_list = heap::c_allocator.allocate(dir_count); - g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->include_dir; + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_create_from_mem( + g->libc->include_dir, g->libc->include_dir_len)); g->libc_include_dir_len += 1; if (want_sys_dir) { - g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->sys_include_dir; + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_create_from_mem( + g->libc->sys_include_dir, g->libc->sys_include_dir_len)); g->libc_include_dir_len += 1; } if (want_um_and_shared_dirs != 0) { - g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf( - "%s" OS_SEP ".." OS_SEP "um", g->libc->include_dir)); + Buf *include_dir_parent = buf_alloc(); + os_path_join(buf_create_from_mem(g->libc->include_dir, g->libc->include_dir_len), + buf_create_from_str(".."), include_dir_parent); + + Buf *buff1 = buf_alloc(); + os_path_join(include_dir_parent, buf_create_from_str("um"), buff1); + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buff1); g->libc_include_dir_len += 1; - g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf( - "%s" OS_SEP ".." OS_SEP "shared", g->libc->include_dir)); + Buf *buff2 = buf_alloc(); + os_path_join(include_dir_parent, buf_create_from_str("shared"), buff2); + g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buff2); g->libc_include_dir_len += 1; } assert(g->libc_include_dir_len == dir_count); @@ -10546,11 +10554,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length); cache_list_of_str(ch, g->framework_dirs.items, g->framework_dirs.length); if (g->libc) { - cache_str(ch, g->libc->include_dir); - cache_str(ch, g->libc->sys_include_dir); - cache_str(ch, g->libc->crt_dir); - cache_str(ch, g->libc->msvc_lib_dir); - cache_str(ch, g->libc->kernel32_lib_dir); + cache_slice(ch, Slice{g->libc->include_dir, g->libc->include_dir_len}); + cache_slice(ch, Slice{g->libc->sys_include_dir, g->libc->sys_include_dir_len}); + cache_slice(ch, Slice{g->libc->crt_dir, g->libc->crt_dir_len}); + cache_slice(ch, Slice{g->libc->msvc_lib_dir, g->libc->msvc_lib_dir_len}); + cache_slice(ch, Slice{g->libc->kernel32_lib_dir, g->libc->kernel32_lib_dir_len}); } cache_buf_opt(ch, g->version_script_path); cache_buf_opt(ch, g->override_soname); diff --git a/src/link.cpp b/src/link.cpp index 0d7a8a410b..fba572de98 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1595,7 +1595,8 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } else { assert(parent->libc != nullptr); Buf *out_buf = buf_alloc(); - os_path_join(buf_create_from_str(parent->libc->crt_dir), buf_create_from_str(file), out_buf); + os_path_join(buf_create_from_mem(parent->libc->crt_dir, parent->libc->crt_dir_len), + buf_create_from_str(file), out_buf); return buf_ptr(out_buf); } } @@ -1860,7 +1861,7 @@ static void construct_linker_job_elf(LinkJob *lj) { if (g->libc_link_lib != nullptr) { if (g->libc != nullptr) { lj->args.append("-L"); - lj->args.append(g->libc->crt_dir); + lj->args.append(buf_ptr(buf_create_from_mem(g->libc->crt_dir, g->libc->crt_dir_len))); } if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) { @@ -2381,14 +2382,26 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path)))); if (g->libc_link_lib != nullptr && g->libc != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir))); + Buf *buff0 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff0, g->libc->crt_dir, g->libc->crt_dir_len); + lj->args.append(buf_ptr(buff0)); if (target_abi_is_gnu(g->zig_target->abi)) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->sys_include_dir))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->include_dir))); + Buf *buff1 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff1, g->libc->sys_include_dir, g->libc->sys_include_dir_len); + lj->args.append(buf_ptr(buff1)); + + Buf *buff2 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff2, g->libc->include_dir, g->libc->include_dir_len); + lj->args.append(buf_ptr(buff2)); } else { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->msvc_lib_dir))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->kernel32_lib_dir))); + Buf *buff1 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff1, g->libc->msvc_lib_dir, g->libc->msvc_lib_dir_len); + lj->args.append(buf_ptr(buff1)); + + Buf *buff2 = buf_create_from_str("-LIBPATH:"); + buf_append_mem(buff2, g->libc->kernel32_lib_dir, g->libc->kernel32_lib_dir_len); + lj->args.append(buf_ptr(buff2)); } } diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig index 603eeb43e1..411f2bfaf6 100644 --- a/test/standalone/brace_expansion/main.zig +++ b/test/standalone/brace_expansion/main.zig @@ -4,7 +4,7 @@ const mem = std.mem; const debug = std.debug; const assert = debug.assert; const testing = std.testing; -const Buffer = std.Buffer; +const ArrayListSentineled = std.ArrayListSentineled; const ArrayList = std.ArrayList; const maxInt = std.math.maxInt; @@ -111,7 +111,7 @@ fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node { } } -fn expandString(input: []const u8, output: *Buffer) !void { +fn expandString(input: []const u8, output: *ArrayListSentineled(u8, 0)) !void { const tokens = try tokenize(input); if (tokens.len == 1) { return output.resize(0); @@ -125,7 +125,7 @@ fn expandString(input: []const u8, output: *Buffer) !void { else => return error.InvalidInput, } - var result_list = ArrayList(Buffer).init(global_allocator); + var result_list = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator); defer result_list.deinit(); try expandNode(root, &result_list); @@ -133,41 +133,41 @@ fn expandString(input: []const u8, output: *Buffer) !void { try output.resize(0); for (result_list.span()) |buf, i| { if (i != 0) { - try output.appendByte(' '); + try output.append(' '); } - try output.append(buf.span()); + try output.appendSlice(buf.span()); } } const ExpandNodeError = error{OutOfMemory}; -fn expandNode(node: Node, output: *ArrayList(Buffer)) ExpandNodeError!void { +fn expandNode(node: Node, output: *ArrayList(ArrayListSentineled(u8, 0))) ExpandNodeError!void { assert(output.len == 0); switch (node) { Node.Scalar => |scalar| { - try output.append(try Buffer.init(global_allocator, scalar)); + try output.append(try ArrayListSentineled(u8, 0).init(global_allocator, scalar)); }, Node.Combine => |pair| { const a_node = pair[0]; const b_node = pair[1]; - var child_list_a = ArrayList(Buffer).init(global_allocator); + var child_list_a = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator); try expandNode(a_node, &child_list_a); - var child_list_b = ArrayList(Buffer).init(global_allocator); + var child_list_b = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator); try expandNode(b_node, &child_list_b); for (child_list_a.span()) |buf_a| { for (child_list_b.span()) |buf_b| { - var combined_buf = try Buffer.initFromBuffer(buf_a); - try combined_buf.append(buf_b.span()); + var combined_buf = try ArrayListSentineled(u8, 0).initFromBuffer(buf_a); + try combined_buf.appendSlice(buf_b.span()); try output.append(combined_buf); } } }, Node.List => |list| { for (list.span()) |child_node| { - var child_list = ArrayList(Buffer).init(global_allocator); + var child_list = ArrayList(ArrayListSentineled(u8, 0)).init(global_allocator); try expandNode(child_node, &child_list); for (child_list.span()) |buf| { @@ -187,13 +187,13 @@ pub fn main() !void { global_allocator = &arena.allocator; - var stdin_buf = try Buffer.initSize(global_allocator, 0); + var stdin_buf = try ArrayListSentineled(u8, 0).initSize(global_allocator, 0); defer stdin_buf.deinit(); var stdin_adapter = stdin_file.inStream(); try stdin_adapter.stream.readAllBuffer(&stdin_buf, maxInt(usize)); - var result_buf = try Buffer.initSize(global_allocator, 0); + var result_buf = try ArrayListSentineled(u8, 0).initSize(global_allocator, 0); defer result_buf.deinit(); try expandString(stdin_buf.span(), &result_buf); @@ -218,7 +218,7 @@ test "invalid inputs" { } fn expectError(test_input: []const u8, expected_err: anyerror) void { - var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable; + var output_buf = ArrayListSentineled(u8, 0).initSize(global_allocator, 0) catch unreachable; defer output_buf.deinit(); testing.expectError(expected_err, expandString(test_input, &output_buf)); @@ -251,7 +251,7 @@ test "valid inputs" { } fn expectExpansion(test_input: []const u8, expected_result: []const u8) void { - var result = Buffer.initSize(global_allocator, 0) catch unreachable; + var result = ArrayListSentineled(u8, 0).initSize(global_allocator, 0) catch unreachable; defer result.deinit(); expandString(test_input, &result) catch unreachable; diff --git a/test/tests.zig b/test/tests.zig index 28459d84c1..7f3e55ec7a 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -4,7 +4,6 @@ const debug = std.debug; const warn = debug.warn; const build = std.build; const CrossTarget = std.zig.CrossTarget; -const Buffer = std.Buffer; const io = std.io; const fs = std.fs; const mem = std.mem; @@ -640,7 +639,7 @@ pub const StackTracesContext = struct { // - replace address with symbolic string // - skip empty lines const got: []const u8 = got_result: { - var buf = try Buffer.initSize(b.allocator, 0); + var buf = ArrayList(u8).init(b.allocator); defer buf.deinit(); if (stderr.len != 0 and stderr[stderr.len - 1] == '\n') stderr = stderr[0 .. stderr.len - 1]; var it = mem.separate(stderr, "\n"); @@ -652,21 +651,21 @@ pub const StackTracesContext = struct { var pos: usize = if (std.Target.current.os.tag == .windows) 2 else 0; for (delims) |delim, i| { marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse { - try buf.append(line); - try buf.append("\n"); + try buf.appendSlice(line); + try buf.appendSlice("\n"); continue :process_lines; }; pos = marks[i] + delim.len; } pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse { - try buf.append(line); - try buf.append("\n"); + try buf.appendSlice(line); + try buf.appendSlice("\n"); continue :process_lines; }; - try buf.append(line[pos + 1 .. marks[2] + delims[2].len]); - try buf.append(" [address]"); - try buf.append(line[marks[3]..]); - try buf.append("\n"); + try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]); + try buf.appendSlice(" [address]"); + try buf.appendSlice(line[marks[3]..]); + try buf.appendSlice("\n"); } break :got_result buf.toOwnedSlice(); };