authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-13 18:50:11-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-13 18:50:11-05:00
log0afb86868423b454708608f9faa9bf27ce3233f3
tree84c5b8ce41886b3740970e76506050c82a718183
parente98ba5fc4044cd84ab88b10cb8c88d765884462f
parentfff6e471259071d9ad8466bcdb0ce42c9d7a90d4
signature Commit is signed but in an unrecognized format.

Merge branch 'suirad-windows-wide-imports'


3 files changed, 63 insertions(+), 23 deletions(-)

std/buf_map.zig+27-9
...@@ -16,7 +16,7 @@ pub const BufMap = struct {...@@ -16,7 +16,7 @@ pub const BufMap = struct {
16 return self;16 return self;
17 }17 }
1818
19 pub fn deinit(self: *const BufMap) void {19 pub fn deinit(self: *BufMap) void {
20 var it = self.hash_map.iterator();20 var it = self.hash_map.iterator();
21 while (true) {21 while (true) {
22 const entry = it.next() orelse break;22 const entry = it.next() orelse break;
...@@ -27,16 +27,34 @@ pub const BufMap = struct {...@@ -27,16 +27,34 @@ pub const BufMap = struct {
27 self.hash_map.deinit();27 self.hash_map.deinit();
28 }28 }
2929
30 /// Same as `set` but the key and value become owned by the BufMap rather
31 /// than being copied.
32 /// If `setMove` fails, the ownership of key and value does not transfer.
33 pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
34 const get_or_put = try self.hash_map.getOrPut(key);
35 if (get_or_put.found_existing) {
36 self.free(get_or_put.kv.key);
37 get_or_put.kv.key = key;
38 }
39 get_or_put.kv.value = value;
40 }
41
42 /// `key` and `value` are copied into the BufMap.
30 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {43 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
31 self.delete(key);
32 const key_copy = try self.copy(key);
33 errdefer self.free(key_copy);
34 const value_copy = try self.copy(value);44 const value_copy = try self.copy(value);
35 errdefer self.free(value_copy);45 errdefer self.free(value_copy);
36 _ = try self.hash_map.put(key_copy, value_copy);46 // Avoid copying key if it already exists
47 const get_or_put = try self.hash_map.getOrPut(key);
48 if (!get_or_put.found_existing) {
49 get_or_put.kv.key = self.copy(key) catch |err| {
50 _ = self.hash_map.remove(key);
51 return err;
52 };
53 }
54 get_or_put.kv.value = value_copy;
37 }55 }
3856
39 pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {57 pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
40 const entry = self.hash_map.get(key) orelse return null;58 const entry = self.hash_map.get(key) orelse return null;
41 return entry.value;59 return entry.value;
42 }60 }
...@@ -47,7 +65,7 @@ pub const BufMap = struct {...@@ -47,7 +65,7 @@ pub const BufMap = struct {
47 self.free(entry.value);65 self.free(entry.value);
48 }66 }
4967
50 pub fn count(self: *const BufMap) usize {68 pub fn count(self: BufMap) usize {
51 return self.hash_map.count();69 return self.hash_map.count();
52 }70 }
5371
...@@ -55,11 +73,11 @@ pub const BufMap = struct {...@@ -55,11 +73,11 @@ pub const BufMap = struct {
55 return self.hash_map.iterator();73 return self.hash_map.iterator();
56 }74 }
5775
58 fn free(self: *const BufMap, value: []const u8) void {76 fn free(self: BufMap, value: []const u8) void {
59 self.hash_map.allocator.free(value);77 self.hash_map.allocator.free(value);
60 }78 }
6179
62 fn copy(self: *const BufMap, value: []const u8) ![]const u8 {80 fn copy(self: BufMap, value: []const u8) ![]u8 {
63 return mem.dupe(self.hash_map.allocator, u8, value);81 return mem.dupe(self.hash_map.allocator, u8, value);
64 }82 }
65};83};
std/os/index.zig+33-11
...@@ -702,8 +702,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -702,8 +702,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
702 errdefer result.deinit();702 errdefer result.deinit();
703703
704 if (is_windows) {704 if (is_windows) {
705 const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;705 const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
706 defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);706 defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
707707
708 var i: usize = 0;708 var i: usize = 0;
709 while (true) {709 while (true) {
...@@ -712,17 +712,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -712,17 +712,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
712 const key_start = i;712 const key_start = i;
713713
714 while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}714 while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
715 const key = ptr[key_start..i];715 const key_w = ptr[key_start..i];
716 const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w);
717 errdefer allocator.free(key);
716718
717 if (ptr[i] == '=') i += 1;719 if (ptr[i] == '=') i += 1;
718720
719 const value_start = i;721 const value_start = i;
720 while (ptr[i] != 0) : (i += 1) {}722 while (ptr[i] != 0) : (i += 1) {}
721 const value = ptr[value_start..i];723 const value_w = ptr[value_start..i];
724 const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w);
725 errdefer allocator.free(value);
722726
723 i += 1; // skip over null byte727 i += 1; // skip over null byte
724728
725 try result.set(key, value);729 try result.setMove(key, value);
726 }730 }
727 } else {731 } else {
728 for (posix_environ_raw) |ptr| {732 for (posix_environ_raw) |ptr| {
...@@ -740,6 +744,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -740,6 +744,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
740 }744 }
741}745}
742746
747test "os.getEnvMap" {
748 var env = try getEnvMap(std.debug.global_allocator);
749 defer env.deinit();
750}
751
743/// TODO make this go through libc when we have it752/// TODO make this go through libc when we have it
744pub fn getEnvPosix(key: []const u8) ?[]const u8 {753pub fn getEnvPosix(key: []const u8) ?[]const u8 {
745 for (posix_environ_raw) |ptr| {754 for (posix_environ_raw) |ptr| {
...@@ -760,21 +769,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {...@@ -760,21 +769,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
760pub const GetEnvVarOwnedError = error{769pub const GetEnvVarOwnedError = error{
761 OutOfMemory,770 OutOfMemory,
762 EnvironmentVariableNotFound,771 EnvironmentVariableNotFound,
772
773 /// See https://github.com/ziglang/zig/issues/1774
774 InvalidUtf8,
763};775};
764776
765/// Caller must free returned memory.777/// Caller must free returned memory.
766/// TODO make this go through libc when we have it778/// TODO make this go through libc when we have it
767pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {779pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
768 if (is_windows) {780 if (is_windows) {
769 const key_with_null = try cstr.addNullByte(allocator, key);781 const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
770 defer allocator.free(key_with_null);782 defer allocator.free(key_with_null);
771783
772 var buf = try allocator.alloc(u8, 256);784 var buf = try allocator.alloc(u16, 256);
773 errdefer allocator.free(buf);785 defer allocator.free(buf);
774786
775 while (true) {787 while (true) {
776 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;788 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
777 const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);789 const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len);
778790
779 if (result == 0) {791 if (result == 0) {
780 const err = windows.GetLastError();792 const err = windows.GetLastError();
...@@ -788,11 +800,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -788,11 +800,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
788 }800 }
789801
790 if (result > buf.len) {802 if (result > buf.len) {
791 buf = try allocator.realloc(u8, buf, result);803 buf = try allocator.realloc(u16, buf, result);
792 continue;804 continue;
793 }805 }
794806
795 return allocator.shrink(u8, buf, result);807 return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) {
808 error.DanglingSurrogateHalf => return error.InvalidUtf8,
809 error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
810 error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
811 error.OutOfMemory => return error.OutOfMemory,
812 };
796 }813 }
797 } else {814 } else {
798 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;815 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
...@@ -800,6 +817,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -800,6 +817,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
800 }817 }
801}818}
802819
820test "os.getEnvVarOwned" {
821 var ga = debug.global_allocator;
822 debug.assertError(getEnvVarOwned(ga, "BADENV"), error.EnvironmentVariableNotFound);
823}
824
803/// Caller must free the returned memory.825/// Caller must free the returned memory.
804pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {826pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
805 var buf: [MAX_PATH_BYTES]u8 = undefined;827 var buf: [MAX_PATH_BYTES]u8 = undefined;
std/os/windows/kernel32.zig+3-3
...@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi...@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
50pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;50pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
51pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;51pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
5252
53pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;53pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
5454
55pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;55pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
5656
...@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp...@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
63pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;63pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
64pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;64pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
6565
66pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;66pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
6767
68pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;68pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
6969
70pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;70pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
7171