Skip to content

Commit

Permalink
more sentinel-terminated pointers std lib integration
Browse files Browse the repository at this point in the history
See #3767
  • Loading branch information
andrewrk committed Nov 25, 2019
1 parent 15d415e commit 29e438f
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 94 deletions.
2 changes: 1 addition & 1 deletion doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -4865,7 +4865,7 @@ const mem = std.mem;
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
const window_name = [1][*]const u8{"window name"};
const x: [*]const ?[*]const u8 = &window_name;
assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
assert(mem.eql(u8, std.mem.toSliceConst(u8, @ptrCast([*:0]const u8, x[0].?)), "window name"));
}
{#code_end#}
{#header_close#}
Expand Down
2 changes: 1 addition & 1 deletion lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub extern "c" fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [
pub extern "c" fn dup(fd: fd_t) c_int;
pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int;
pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;
pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
Expand Down
16 changes: 8 additions & 8 deletions lib/std/debug.zig
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
const vaddr_end = vaddr_start + proc_sym.CodeSize;
if (relative_address >= vaddr_start and relative_address < vaddr_end) {
break mem.toSliceConst(u8, @ptrCast([*]u8, proc_sym) + @sizeOf(pdb.ProcSym));
break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym));
}
},
else => {},
Expand Down Expand Up @@ -703,9 +703,9 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
return;
};

const symbol_name = mem.toSliceConst(u8, di.strings.ptr + symbol.nlist.n_strx);
const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
const compile_unit_name = if (symbol.ofile) |ofile| blk: {
const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
break :blk fs.path.basename(ofile_path);
} else "???";
if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
Expand Down Expand Up @@ -915,7 +915,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
for (present) |_| {
const name_offset = try pdb_stream.stream.readIntLittle(u32);
const name_index = try pdb_stream.stream.readIntLittle(u32);
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
const name = mem.toSlice(u8, @ptrCast([*:0]u8, name_bytes.ptr + name_offset));
if (mem.eql(u8, name, "/names")) {
break :str_tab_index name_index;
}
Expand Down Expand Up @@ -1708,7 +1708,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
const gop = try di.ofiles.getOrPut(ofile);
const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: {
errdefer _ = di.ofiles.remove(ofile);
const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));

gop.kv.value = MachOFile{
.bytes = try std.fs.Dir.cwd().readFileAllocAligned(
Expand Down Expand Up @@ -1741,7 +1741,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
(sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)
{
const sect_name = mem.toSliceConst(u8, &sect.sectname);
const sect_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &sect.sectname));
if (mem.eql(u8, sect_name, "__debug_line")) {
gop.kv.value.sect_debug_line = sect;
} else if (mem.eql(u8, sect_name, "__debug_info")) {
Expand Down Expand Up @@ -2323,8 +2323,8 @@ fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
}
}

fn readStringMem(ptr: *[*]const u8) []const u8 {
const result = mem.toSliceConst(u8, ptr.*);
fn readStringMem(ptr: *[*]const u8) [:0]const u8 {
const result = mem.toSliceConst(u8, @ptrCast([*:0]const u8, ptr.*));
ptr.* += result.len + 1;
return result;
}
Expand Down
8 changes: 4 additions & 4 deletions lib/std/dynamic_library.zig
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub const LinuxDynLib = struct {
};

pub const ElfLib = struct {
strings: [*]u8,
strings: [*:0]u8,
syms: [*]elf.Sym,
hashtab: [*]os.Elf_Symndx,
versym: ?[*]u16,
Expand Down Expand Up @@ -175,7 +175,7 @@ pub const ElfLib = struct {
const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;
if (base == maxInt(usize)) return error.BaseNotFound;

var maybe_strings: ?[*]u8 = null;
var maybe_strings: ?[*:0]u8 = null;
var maybe_syms: ?[*]elf.Sym = null;
var maybe_hashtab: ?[*]os.Elf_Symndx = null;
var maybe_versym: ?[*]u16 = null;
Expand All @@ -186,7 +186,7 @@ pub const ElfLib = struct {
while (dynv[i] != 0) : (i += 2) {
const p = base + dynv[i + 1];
switch (dynv[i]) {
elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
elf.DT_STRTAB => maybe_strings = @intToPtr([*:0]u8, p),
elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
Expand Down Expand Up @@ -230,7 +230,7 @@ pub const ElfLib = struct {
}
};

fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*]u8) bool {
fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*:0]u8) bool {
var def = def_arg;
const vsym = @bitCast(u32, vsym_arg) & 0x7fff;
while (true) {
Expand Down
6 changes: 2 additions & 4 deletions lib/std/event/fs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ pub const Request = struct {
};

pub const Open = struct {
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
path: []const u8,
path: [:0]const u8,
flags: u32,
mode: File.Mode,
result: Error!fd_t,
Expand All @@ -68,8 +67,7 @@ pub const Request = struct {
};

pub const WriteFile = struct {
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
path: []const u8,
path: [:0]const u8,
contents: []const u8,
mode: File.Mode,
result: Error!void,
Expand Down
44 changes: 23 additions & 21 deletions lib/std/fs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
/// This represents the maximum size of a UTF-8 encoded file path.
/// All file system operations which return a path are guaranteed to
/// fit into a UTF-8 encoded array of this length.
/// The byte count includes room for a null sentinel byte.
pub const MAX_PATH_BYTES = switch (builtin.os) {
.linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
Expand Down Expand Up @@ -227,7 +228,7 @@ pub const AtomicFile = struct {
try crypto.randomBytes(rand_buf[0..]);
b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);

const file = File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
const file = File.openWriteNoClobberC(@ptrCast([*:0]u8, &tmp_path_buf), mode) catch |err| switch (err) {
error.PathAlreadyExists => continue,
// TODO zig should figure out that this error set does not include PathAlreadyExists since
// it is handled in the above switch
Expand All @@ -247,7 +248,7 @@ pub const AtomicFile = struct {
pub fn deinit(self: *AtomicFile) void {
if (!self.finished) {
self.file.close();
deleteFileC(&self.tmp_path_buf) catch {};
deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
self.finished = true;
}
}
Expand All @@ -258,11 +259,11 @@ pub const AtomicFile = struct {
self.finished = true;
if (builtin.os == .windows) {
const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));
return os.renameW(&tmp_path_w, &dest_path_w);
}
const dest_path_c = try os.toPosixPath(self.dest_path);
return os.renameC(&self.tmp_path_buf, &dest_path_c);
return os.renameC(@ptrCast([*:0]u8, &self.tmp_path_buf), &dest_path_c);
}
};

Expand All @@ -274,12 +275,12 @@ pub fn makeDir(dir_path: []const u8) !void {
}

/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
pub fn makeDirC(dir_path: [*]const u8) !void {
pub fn makeDirC(dir_path: [*:0]const u8) !void {
return os.mkdirC(dir_path, default_new_dir_mode);
}

/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
pub fn makeDirW(dir_path: [*]const u16) !void {
pub fn makeDirW(dir_path: [*:0]const u16) !void {
return os.mkdirW(dir_path, default_new_dir_mode);
}

Expand Down Expand Up @@ -327,12 +328,12 @@ pub fn deleteDir(dir_path: []const u8) !void {
}

/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
pub fn deleteDirC(dir_path: [*]const u8) !void {
pub fn deleteDirC(dir_path: [*:0]const u8) !void {
return os.rmdirC(dir_path);
}

/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
pub fn deleteDirW(dir_path: [*]const u16) !void {
pub fn deleteDirW(dir_path: [*:0]const u16) !void {
return os.rmdirW(dir_path);
}

Expand Down Expand Up @@ -688,7 +689,7 @@ pub const Dir = struct {
}

/// Same as `open` except the parameter is null-terminated.
pub fn openC(dir_path_c: [*]const u8) OpenError!Dir {
pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir {
return cwd().openDirC(dir_path_c);
}

Expand All @@ -708,7 +709,7 @@ pub const Dir = struct {
}

/// Call `File.close` on the result when done.
pub fn openReadC(self: Dir, sub_path: [*]const u8) File.OpenError!File {
pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {
if (builtin.os == .windows) {
const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
return self.openReadW(&path_w);
Expand All @@ -719,7 +720,7 @@ pub const Dir = struct {
return File.openHandle(fd);
}

pub fn openReadW(self: Dir, sub_path_w: [*]const u16) File.OpenError!File {
pub fn openReadW(self: Dir, sub_path_w: [*:0]const u16) File.OpenError!File {
const w = os.windows;

var result = File{ .handle = undefined };
Expand Down Expand Up @@ -786,7 +787,7 @@ pub const Dir = struct {
}

/// Same as `openDir` except the parameter is null-terminated.
pub fn openDirC(self: Dir, sub_path_c: [*]const u8) OpenError!Dir {
pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
if (builtin.os == .windows) {
const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
return self.openDirW(&sub_path_w);
Expand All @@ -805,7 +806,7 @@ pub const Dir = struct {

/// Same as `openDir` except the path parameter is UTF16LE, NT-prefixed.
/// This function is Windows-only.
pub fn openDirW(self: Dir, sub_path_w: [*]const u16) OpenError!Dir {
pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
const w = os.windows;

var result = Dir{
Expand Down Expand Up @@ -868,7 +869,7 @@ pub const Dir = struct {
}

/// Same as `deleteFile` except the parameter is null-terminated.
pub fn deleteFileC(self: Dir, sub_path_c: [*]const u8) DeleteFileError!void {
pub fn deleteFileC(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
os.unlinkatC(self.fd, sub_path_c, 0) catch |err| switch (err) {
error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
else => |e| return e,
Expand Down Expand Up @@ -903,7 +904,7 @@ pub const Dir = struct {
}

/// Same as `deleteDir` except the parameter is null-terminated.
pub fn deleteDirC(self: Dir, sub_path_c: [*]const u8) DeleteDirError!void {
pub fn deleteDirC(self: Dir, sub_path_c: [*:0]const u8) DeleteDirError!void {
os.unlinkatC(self.fd, sub_path_c, os.AT_REMOVEDIR) catch |err| switch (err) {
error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
else => |e| return e,
Expand All @@ -912,7 +913,7 @@ pub const Dir = struct {

/// Same as `deleteDir` except the parameter is UTF16LE, NT prefixed.
/// This function is Windows-only.
pub fn deleteDirW(self: Dir, sub_path_w: [*]const u16) DeleteDirError!void {
pub fn deleteDirW(self: Dir, sub_path_w: [*:0]const u16) DeleteDirError!void {
os.unlinkatW(self.fd, sub_path_w, os.AT_REMOVEDIR) catch |err| switch (err) {
error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
else => |e| return e,
Expand All @@ -927,7 +928,7 @@ pub const Dir = struct {
}

/// Same as `readLink`, except the `pathname` parameter is null-terminated.
pub fn readLinkC(self: Dir, sub_path_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
pub fn readLinkC(self: Dir, sub_path_c: [*:0]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
return os.readlinkatC(self.fd, sub_path_c, buffer);
}

Expand Down Expand Up @@ -1250,7 +1251,8 @@ pub fn openSelfExe() OpenSelfExeError!File {
var buf: [MAX_PATH_BYTES]u8 = undefined;
const self_exe_path = try selfExePath(&buf);
buf[self_exe_path.len] = 0;
return File.openReadC(self_exe_path.ptr);
// TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
return File.openReadC(@ptrCast([*:0]u8, self_exe_path.ptr));
}

test "openSelfExe" {
Expand All @@ -1277,7 +1279,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
var u32_len: u32 = out_buffer.len;
const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
if (rc != 0) return error.NameTooLong;
return mem.toSlice(u8, out_buffer);
return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
}
switch (builtin.os) {
.linux => return os.readlinkC("/proc/self/exe", out_buffer),
Expand Down Expand Up @@ -1306,9 +1308,9 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
}

/// The result is UTF16LE-encoded.
pub fn selfExePathW() []const u16 {
pub fn selfExePathW() [:0]const u16 {
const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;
return mem.toSliceConst(u16, image_path_name.Buffer);
return mem.toSliceConst(u16, @ptrCast([*:0]const u16, image_path_name.Buffer));
}

/// `selfExeDirPath` except allocates the result on the heap.
Expand Down
14 changes: 7 additions & 7 deletions lib/std/fs/file.zig
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub const File = struct {
}

/// Deprecated; call `std.fs.Dir.openReadC` directly.
pub fn openReadC(path_c: [*]const u8) OpenError!File {
pub fn openReadC(path_c: [*:0]const u8) OpenError!File {
return std.fs.Dir.cwd().openReadC(path_c);
}

Expand Down Expand Up @@ -61,7 +61,7 @@ pub const File = struct {

/// Same as `openWriteMode` except `path` is null-terminated.
/// TODO: deprecate this and move it to `std.fs.Dir`.
pub fn openWriteModeC(path: [*]const u8, file_mode: Mode) OpenError!File {
pub fn openWriteModeC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
return openWriteModeW(&path_w, file_mode);
Expand All @@ -74,7 +74,7 @@ pub const File = struct {

/// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded
/// TODO: deprecate this and move it to `std.fs.Dir`.
pub fn openWriteModeW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
const handle = try windows.CreateFileW(
path_w,
windows.GENERIC_WRITE,
Expand All @@ -101,7 +101,7 @@ pub const File = struct {
}

/// TODO: deprecate this and move it to `std.fs.Dir`.
pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File {
pub fn openWriteNoClobberC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
return openWriteNoClobberW(&path_w, file_mode);
Expand All @@ -113,7 +113,7 @@ pub const File = struct {
}

/// TODO: deprecate this and move it to `std.fs.Dir`.
pub fn openWriteNoClobberW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
const handle = try windows.CreateFileW(
path_w,
windows.GENERIC_WRITE,
Expand Down Expand Up @@ -142,13 +142,13 @@ pub const File = struct {

/// Same as `access` except the parameter is null-terminated.
/// TODO: deprecate this and move it to `std.fs.Dir`.
pub fn accessC(path: [*]const u8) !void {
pub fn accessC(path: [*:0]const u8) !void {
return os.accessC(path, os.F_OK);
}

/// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
/// TODO: deprecate this and move it to `std.fs.Dir`.
pub fn accessW(path: [*]const u16) !void {
pub fn accessW(path: [*:0]const u16) !void {
return os.accessW(path, os.F_OK);
}

Expand Down
Loading

0 comments on commit 29e438f

Please sign in to comment.