zig/std/os/get_app_data_dir.zig

71 lines
2.7 KiB
Zig
Raw Normal View History

const std = @import("../index.zig");
const builtin = @import("builtin");
const unicode = std.unicode;
const mem = std.mem;
const os = std.os;
pub const GetAppDataDirError = error{
OutOfMemory,
AppDataDirUnavailable,
};
/// Caller owns returned memory.
2018-08-21 13:07:28 -07:00
/// TODO determine if we can remove the allocator requirement
pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataDirError![]u8 {
switch (builtin.os) {
builtin.Os.windows => {
var dir_path_ptr: [*]u16 = undefined;
switch (os.windows.SHGetKnownFolderPath(
&os.windows.FOLDERID_LocalAppData,
os.windows.KF_FLAG_CREATE,
null,
&dir_path_ptr,
)) {
os.windows.S_OK => {
defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr));
2018-08-21 13:07:28 -07:00
const global_dir = unicode.utf16leToUtf8Alloc(allocator, utf16lePtrSlice(dir_path_ptr)) catch |err| switch (err) {
error.UnexpectedSecondSurrogateHalf => return error.AppDataDirUnavailable,
error.ExpectedSecondSurrogateHalf => return error.AppDataDirUnavailable,
error.DanglingSurrogateHalf => return error.AppDataDirUnavailable,
error.OutOfMemory => return error.OutOfMemory,
};
defer allocator.free(global_dir);
return os.path.join(allocator, global_dir, appname);
},
os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
else => return error.AppDataDirUnavailable,
}
},
2018-07-18 07:45:17 -07:00
builtin.Os.macosx => {
const home_dir = os.getEnvPosix("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
return os.path.join(allocator, home_dir, "Library", "Application Support", appname);
},
2018-10-17 12:21:48 -07:00
builtin.Os.linux, builtin.Os.freebsd => {
2018-07-18 07:45:17 -07:00
const home_dir = os.getEnvPosix("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
return os.path.join(allocator, home_dir, ".local", "share", appname);
},
2018-07-18 07:45:17 -07:00
else => @compileError("Unsupported OS"),
}
}
fn utf16lePtrSlice(ptr: [*]const u16) []const u16 {
var index: usize = 0;
while (ptr[index] != 0) : (index += 1) {}
return ptr[0..index];
}
2018-07-18 07:45:17 -07:00
test "std.os.getAppDataDir" {
var buf: [512]u8 = undefined;
const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
// We can't actually validate the result
_ = getAppDataDir(allocator, "zig") catch return;
}