diff options
| author | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
|---|---|---|
| committer | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
| commit | d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d (patch) | |
| tree | e9fa3caec533a0d1e2b434868b2fde1f9240e5c8 /std/os/get_app_data_dir.zig | |
| parent | 06614b3fa09954464c2e2f32756cacedc178a282 (diff) | |
| parent | 63a23e848a62d5f167f8d5478de9766cb24aa6eb (diff) | |
| download | zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.tar.gz zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.zip | |
Merge branch 'master' into zen_stdlib
Diffstat (limited to 'std/os/get_app_data_dir.zig')
| -rw-r--r-- | std/os/get_app_data_dir.zig | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/std/os/get_app_data_dir.zig b/std/os/get_app_data_dir.zig new file mode 100644 index 0000000000..e8ae5dd490 --- /dev/null +++ b/std/os/get_app_data_dir.zig @@ -0,0 +1,69 @@ +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. +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)); + const global_dir = unicode.utf16leToUtf8(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, + } + }, + 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); + }, + builtin.Os.linux => { + 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); + }, + 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]; +} + +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; +} + |
