Merge branch 'std.fs.Dir.openRead'
This commit is contained in:
commit
e3404e3c78
@ -1711,7 +1711,12 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||
const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
|
||||
|
||||
gop.kv.value = MachOFile{
|
||||
.bytes = try std.io.readFileAllocAligned(di.ofiles.allocator, ofile_path, @alignOf(macho.mach_header_64)),
|
||||
.bytes = try std.fs.Dir.cwd().readFileAllocAligned(
|
||||
di.ofiles.allocator,
|
||||
ofile_path,
|
||||
maxInt(usize),
|
||||
@alignOf(macho.mach_header_64),
|
||||
),
|
||||
.sect_debug_info = null,
|
||||
.sect_debug_line = null,
|
||||
};
|
||||
|
@ -415,7 +415,8 @@ pub fn openPosix(
|
||||
pub fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t {
|
||||
switch (builtin.os) {
|
||||
.macosx, .linux, .freebsd, .netbsd, .dragonfly => {
|
||||
const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
|
||||
return openPosix(loop, path, flags, File.default_mode);
|
||||
},
|
||||
|
||||
@ -448,7 +449,8 @@ pub fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.OpenEr
|
||||
.netbsd,
|
||||
.dragonfly,
|
||||
=> {
|
||||
const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
|
||||
return openPosix(loop, path, flags, File.default_mode);
|
||||
},
|
||||
.windows => return windows.CreateFile(
|
||||
@ -472,7 +474,8 @@ pub fn openReadWrite(
|
||||
) File.OpenError!fd_t {
|
||||
switch (builtin.os) {
|
||||
.macosx, .linux, .freebsd, .netbsd, .dragonfly => {
|
||||
const flags = os.O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC;
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC;
|
||||
return openPosix(loop, path, flags, mode);
|
||||
},
|
||||
|
||||
|
@ -856,7 +856,8 @@ pub const Loop = struct {
|
||||
},
|
||||
.Close => |*msg| noasync os.close(msg.fd),
|
||||
.WriteFile => |*msg| blk: {
|
||||
const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT |
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT |
|
||||
os.O_CLOEXEC | os.O_TRUNC;
|
||||
const fd = noasync os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
|
||||
msg.result = err;
|
||||
|
111
lib/std/fs.zig
111
lib/std/fs.zig
@ -6,6 +6,7 @@ const base64 = std.base64;
|
||||
const crypto = std.crypto;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const math = std.math;
|
||||
|
||||
pub const path = @import("fs/path.zig");
|
||||
pub const File = @import("fs/file.zig").File;
|
||||
@ -698,17 +699,81 @@ pub const Dir = struct {
|
||||
|
||||
/// Call `File.close` on the result when done.
|
||||
pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
|
||||
return self.openReadW(&path_w);
|
||||
}
|
||||
const path_c = try os.toPosixPath(sub_path);
|
||||
return self.openReadC(&path_c);
|
||||
}
|
||||
|
||||
/// Call `File.close` on the result when done.
|
||||
pub fn openReadC(self: Dir, sub_path: [*]const u8) File.OpenError!File {
|
||||
const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
|
||||
return self.openReadW(&path_w);
|
||||
}
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
|
||||
const fd = try os.openatC(self.fd, sub_path, flags, 0);
|
||||
return File.openHandle(fd);
|
||||
}
|
||||
|
||||
pub fn openReadW(self: Dir, sub_path_w: [*]const u16) File.OpenError!File {
|
||||
const w = os.windows;
|
||||
|
||||
var result = File{ .handle = undefined };
|
||||
|
||||
const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
|
||||
error.Overflow => return error.NameTooLong,
|
||||
};
|
||||
var nt_name = w.UNICODE_STRING{
|
||||
.Length = path_len_bytes,
|
||||
.MaximumLength = path_len_bytes,
|
||||
.Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
|
||||
};
|
||||
var attr = w.OBJECT_ATTRIBUTES{
|
||||
.Length = @sizeOf(w.OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = if (path.isAbsoluteW(sub_path_w)) null else self.fd,
|
||||
.Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
|
||||
.ObjectName = &nt_name,
|
||||
.SecurityDescriptor = null,
|
||||
.SecurityQualityOfService = null,
|
||||
};
|
||||
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
|
||||
return error.IsDir;
|
||||
}
|
||||
if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
|
||||
return error.IsDir;
|
||||
}
|
||||
var io: w.IO_STATUS_BLOCK = undefined;
|
||||
const rc = w.ntdll.NtCreateFile(
|
||||
&result.handle,
|
||||
w.GENERIC_READ | w.SYNCHRONIZE,
|
||||
&attr,
|
||||
&io,
|
||||
null,
|
||||
w.FILE_ATTRIBUTE_NORMAL,
|
||||
w.FILE_SHARE_READ,
|
||||
w.FILE_OPEN,
|
||||
w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
null,
|
||||
0,
|
||||
);
|
||||
switch (rc) {
|
||||
w.STATUS.SUCCESS => return result,
|
||||
w.STATUS.OBJECT_NAME_INVALID => unreachable,
|
||||
w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||
w.STATUS.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
|
||||
w.STATUS.INVALID_PARAMETER => unreachable,
|
||||
w.STATUS.SHARING_VIOLATION => return error.SharingViolation,
|
||||
w.STATUS.ACCESS_DENIED => return error.AccessDenied,
|
||||
w.STATUS.PIPE_BUSY => return error.PipeBusy,
|
||||
w.STATUS.OBJECT_PATH_SYNTAX_BAD => unreachable,
|
||||
else => return w.unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `close` on the result when done.
|
||||
pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir {
|
||||
if (builtin.os == .windows) {
|
||||
@ -866,6 +931,34 @@ pub const Dir = struct {
|
||||
return os.readlinkatC(self.fd, sub_path_c, buffer);
|
||||
}
|
||||
|
||||
/// On success, caller owns returned buffer.
|
||||
/// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
|
||||
pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 {
|
||||
return self.readFileAllocAligned(allocator, file_path, max_bytes, @alignOf(u8));
|
||||
}
|
||||
|
||||
/// On success, caller owns returned buffer.
|
||||
/// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
|
||||
pub fn readFileAllocAligned(
|
||||
self: Dir,
|
||||
allocator: *mem.Allocator,
|
||||
file_path: []const u8,
|
||||
max_bytes: usize,
|
||||
comptime A: u29,
|
||||
) ![]align(A) u8 {
|
||||
var file = try self.openRead(file_path);
|
||||
defer file.close();
|
||||
|
||||
const size = math.cast(usize, try file.getEndPos()) catch math.maxInt(usize);
|
||||
if (size > max_bytes) return error.FileTooBig;
|
||||
|
||||
const buf = try allocator.alignedAlloc(u8, A, size);
|
||||
errdefer allocator.free(buf);
|
||||
|
||||
try file.inStream().stream.readNoEof(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
pub const DeleteTreeError = error{
|
||||
AccessDenied,
|
||||
FileTooBig,
|
||||
@ -1150,9 +1243,9 @@ pub fn openSelfExe() OpenSelfExeError!File {
|
||||
return File.openReadC(c"/proc/self/exe");
|
||||
}
|
||||
if (builtin.os == .windows) {
|
||||
var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
const wide_slice = try selfExePathW(&buf);
|
||||
return File.openReadW(wide_slice.ptr);
|
||||
const wide_slice = selfExePathW();
|
||||
const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice);
|
||||
return Dir.cwd().openReadW(&prefixed_path_w);
|
||||
}
|
||||
var buf: [MAX_PATH_BYTES]u8 = undefined;
|
||||
const self_exe_path = try selfExePath(&buf);
|
||||
@ -1203,8 +1296,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
|
||||
return mem.toSlice(u8, out_buffer);
|
||||
},
|
||||
.windows => {
|
||||
var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
const utf16le_slice = try selfExePathW(&utf16le_buf);
|
||||
const utf16le_slice = selfExePathW();
|
||||
// Trust that Windows gives us valid UTF-16LE.
|
||||
const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
|
||||
return out_buffer[0..end_index];
|
||||
@ -1213,9 +1305,10 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as `selfExePath` except the result is UTF16LE-encoded.
|
||||
pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) SelfExePathError![]u16 {
|
||||
return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len);
|
||||
/// The result is UTF16LE-encoded.
|
||||
pub fn selfExePathW() []const u16 {
|
||||
const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;
|
||||
return mem.toSliceConst(u16, image_path_name.Buffer);
|
||||
}
|
||||
|
||||
/// `selfExeDirPath` except allocates the result on the heap.
|
||||
|
@ -25,42 +25,23 @@ pub const File = struct {
|
||||
|
||||
pub const OpenError = windows.CreateFileError || os.OpenError;
|
||||
|
||||
/// Call close to clean up.
|
||||
/// Deprecated; call `std.fs.Dir.openRead` directly.
|
||||
pub fn openRead(path: []const u8) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.sliceToPrefixedFileW(path);
|
||||
return openReadW(&path_w);
|
||||
}
|
||||
const path_c = try os.toPosixPath(path);
|
||||
return openReadC(&path_c);
|
||||
return std.fs.Dir.cwd().openRead(path);
|
||||
}
|
||||
|
||||
/// `openRead` except with a null terminated path
|
||||
pub fn openReadC(path: [*]const u8) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.cStrToPrefixedFileW(path);
|
||||
return openReadW(&path_w);
|
||||
}
|
||||
const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC;
|
||||
const fd = try os.openC(path, flags, 0);
|
||||
return openHandle(fd);
|
||||
/// Deprecated; call `std.fs.Dir.openReadC` directly.
|
||||
pub fn openReadC(path_c: [*]const u8) OpenError!File {
|
||||
return std.fs.Dir.cwd().openReadC(path_c);
|
||||
}
|
||||
|
||||
/// `openRead` except with a null terminated UTF16LE encoded path
|
||||
/// Deprecated; call `std.fs.Dir.openReadW` directly.
|
||||
pub fn openReadW(path_w: [*]const u16) OpenError!File {
|
||||
const handle = try windows.CreateFileW(
|
||||
path_w,
|
||||
windows.GENERIC_READ,
|
||||
windows.FILE_SHARE_READ,
|
||||
null,
|
||||
windows.OPEN_EXISTING,
|
||||
windows.FILE_ATTRIBUTE_NORMAL,
|
||||
null,
|
||||
);
|
||||
return openHandle(handle);
|
||||
return std.fs.Dir.cwd().openReadW(path_w);
|
||||
}
|
||||
|
||||
/// Calls `openWriteMode` with `default_mode` for the mode.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWrite(path: []const u8) OpenError!File {
|
||||
return openWriteMode(path, default_mode);
|
||||
}
|
||||
@ -68,6 +49,7 @@ pub const File = struct {
|
||||
/// If the path does not exist it will be created.
|
||||
/// If a file already exists in the destination it will be truncated.
|
||||
/// Call close to clean up.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.sliceToPrefixedFileW(path);
|
||||
@ -78,17 +60,20 @@ 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 {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.cStrToPrefixedFileW(path);
|
||||
return openWriteModeW(&path_w, file_mode);
|
||||
}
|
||||
const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC;
|
||||
const fd = try os.openC(path, flags, file_mode);
|
||||
return openHandle(fd);
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
const handle = try windows.CreateFileW(
|
||||
path_w,
|
||||
@ -105,6 +90,7 @@ pub const File = struct {
|
||||
/// If the path does not exist it will be created.
|
||||
/// If a file already exists in the destination this returns OpenError.PathAlreadyExists
|
||||
/// Call close to clean up.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.sliceToPrefixedFileW(path);
|
||||
@ -114,16 +100,19 @@ pub const File = struct {
|
||||
return openWriteNoClobberC(&path_c, file_mode);
|
||||
}
|
||||
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File {
|
||||
if (builtin.os == .windows) {
|
||||
const path_w = try windows.cStrToPrefixedFileW(path);
|
||||
return openWriteNoClobberW(&path_w, file_mode);
|
||||
}
|
||||
const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL;
|
||||
const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0;
|
||||
const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL;
|
||||
const fd = try os.openC(path, flags, file_mode);
|
||||
return openHandle(fd);
|
||||
}
|
||||
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn openWriteNoClobberW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
|
||||
const handle = try windows.CreateFileW(
|
||||
path_w,
|
||||
@ -146,16 +135,19 @@ pub const File = struct {
|
||||
/// In general it is recommended to avoid this function. For example,
|
||||
/// instead of testing if a file exists and then opening it, just
|
||||
/// open it and handle the error for file not found.
|
||||
/// TODO: deprecate this and move it to `std.fs.Dir`.
|
||||
pub fn access(path: []const u8) !void {
|
||||
return os.access(path, os.F_OK);
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
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 {
|
||||
return os.accessW(path, os.F_OK);
|
||||
}
|
||||
|
@ -69,24 +69,9 @@ pub fn writeFile(path: []const u8, data: []const u8) !void {
|
||||
}
|
||||
|
||||
/// On success, caller owns returned buffer.
|
||||
/// TODO move this to `std.fs` and add a version to `std.fs.Dir`.
|
||||
/// This function is deprecated; use `std.fs.Dir.readFileAlloc`.
|
||||
pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
|
||||
return readFileAllocAligned(allocator, path, @alignOf(u8));
|
||||
}
|
||||
|
||||
/// On success, caller owns returned buffer.
|
||||
/// TODO move this to `std.fs` and add a version to `std.fs.Dir`.
|
||||
pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptime A: u29) ![]align(A) u8 {
|
||||
var file = try File.openRead(path);
|
||||
defer file.close();
|
||||
|
||||
const size = try math.cast(usize, try file.getEndPos());
|
||||
const buf = try allocator.alignedAlloc(u8, A, size);
|
||||
errdefer allocator.free(buf);
|
||||
|
||||
var adapter = file.inStream();
|
||||
try adapter.stream.readNoEof(buf[0..size]);
|
||||
return buf;
|
||||
return fs.Dir.cwd().readFileAlloc(allocator, path, math.maxInt(usize));
|
||||
}
|
||||
|
||||
pub fn BufferedInStream(comptime Error: type) type {
|
||||
|
@ -267,7 +267,6 @@ pub const SA_USERTRAMP = 0x0100;
|
||||
/// signal handler with SA_SIGINFO args with 64bit regs information
|
||||
pub const SA_64REGSET = 0x0200;
|
||||
|
||||
pub const O_LARGEFILE = 0x0000;
|
||||
pub const O_PATH = 0x0000;
|
||||
|
||||
pub const F_OK = 0;
|
||||
|
@ -241,7 +241,6 @@ pub const KERN_MAXID = 37;
|
||||
|
||||
pub const HOST_NAME_MAX = 255;
|
||||
|
||||
pub const O_LARGEFILE = 0; // faked support
|
||||
pub const O_RDONLY = 0;
|
||||
pub const O_NDELAY = O_NONBLOCK;
|
||||
pub const O_WRONLY = 1;
|
||||
|
@ -300,7 +300,6 @@ pub const O_CLOEXEC = 0x00100000;
|
||||
|
||||
pub const O_ASYNC = 0x0040;
|
||||
pub const O_DIRECT = 0x00010000;
|
||||
pub const O_LARGEFILE = 0;
|
||||
pub const O_NOATIME = 0o1000000;
|
||||
pub const O_PATH = 0o10000000;
|
||||
pub const O_TMPFILE = 0o20200000;
|
||||
|
@ -292,7 +292,6 @@ pub const O_CLOEXEC = 0x00400000;
|
||||
|
||||
pub const O_ASYNC = 0x0040;
|
||||
pub const O_DIRECT = 0x00080000;
|
||||
pub const O_LARGEFILE = 0;
|
||||
pub const O_NOATIME = 0;
|
||||
pub const O_PATH = 0;
|
||||
pub const O_TMPFILE = 0;
|
||||
|
@ -927,6 +927,24 @@ pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 {
|
||||
return sliceToPrefixedSuffixedFileW(s, [_]u16{0});
|
||||
}
|
||||
|
||||
/// Assumes an absolute path.
|
||||
pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 {
|
||||
// TODO https://github.com/ziglang/zig/issues/2765
|
||||
var result: [PATH_MAX_WIDE + 1]u16 = undefined;
|
||||
|
||||
const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: {
|
||||
const prefix = [_]u16{ '\\', '?', '?', '\\' };
|
||||
mem.copy(u16, result[0..], prefix);
|
||||
break :blk prefix.len;
|
||||
};
|
||||
const end_index = start_index + s.len;
|
||||
if (end_index + 1 > result.len) return error.NameTooLong;
|
||||
mem.copy(u16, result[start_index..], s);
|
||||
result[end_index] = 0;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 {
|
||||
// TODO https://github.com/ziglang/zig/issues/2765
|
||||
var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined;
|
||||
@ -948,7 +966,6 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
|
||||
break :blk prefix.len;
|
||||
};
|
||||
const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);
|
||||
assert(end_index <= result.len);
|
||||
if (end_index + suffix.len > result.len) return error.NameTooLong;
|
||||
mem.copy(u16, result[end_index..], suffix);
|
||||
return result;
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user