authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-02 15:04:42-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-02 15:04:42-04:00
log8bf7cffe29b520cda094756309bca1d354af0d6b
treea71b69111bbd63390e7b3a435a3f1932aaaf5fa5
parentba1a8b64c44b9b99e9f0002555b9b4a35092e8f6
signaturelock-open Commit is signed but in an unrecognized format.

slight modification of the semantics of std.os.getenvW

Now, this function first attempts a case-sensitive lookup. If no match is found, and `key` is ASCII, then it attempts a second case-insensitive lookup. It is not planned to support full Unicode case-insensitivity on Windows, and in fact relying on non-ASCII case-insensitive environment variables is fundamentally problematic.

1 files changed, 16 insertions(+), 16 deletions(-)

lib/std/os.zig+16-16
...@@ -21,7 +21,6 @@ const assert = std.debug.assert;...@@ -21,7 +21,6 @@ const assert = std.debug.assert;
21const math = std.math;21const math = std.math;
22const mem = std.mem;22const mem = std.mem;
23const elf = std.elf;23const elf = std.elf;
24const unicode = std.unicode;
25const dl = @import("dynamic_library.zig");24const dl = @import("dynamic_library.zig");
26const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;25const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
2726
...@@ -1207,27 +1206,17 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {...@@ -1207,27 +1206,17 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {
1207 return getenv(mem.spanZ(key));1206 return getenv(mem.spanZ(key));
1208}1207}
12091208
1210fn utf16LeAsciiEqlIgnoreCase(a: []const u16, b: []const u16) bool {
1211 if (a.len != b.len) return false;
1212 var a_it = unicode.Utf16LeIterator.init(a);
1213 var b_it = unicode.Utf16LeIterator.init(b);
1214 while (a_it.nextCodepoint() catch return false) |a_codepoint| {
1215 const b_codepoint = (b_it.nextCodepoint() catch return false) orelse return false;
1216 const upper_a = if (a_codepoint >= 97 and a_codepoint <= 122) a_codepoint & 0b11011111 else a_codepoint;
1217 const upper_b = if (b_codepoint >= 97 and b_codepoint <= 122) b_codepoint & 0b11011111 else b_codepoint;
1218 if (upper_a != upper_b) return false;
1219 }
1220 return true;
1221}
1222
1223/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.1209/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.
1224/// See also `getenv`.1210/// See also `getenv`.
1211/// This function first attempts a case-sensitive lookup. If no match is found, and `key`
1212/// is ASCII, then it attempts a second case-insensitive lookup.
1225pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {1213pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
1226 if (builtin.os.tag != .windows) {1214 if (builtin.os.tag != .windows) {
1227 @compileError("std.os.getenvW is a Windows-only API");1215 @compileError("std.os.getenvW is a Windows-only API");
1228 }1216 }
1229 const key_slice = mem.spanZ(key);1217 const key_slice = mem.spanZ(key);
1230 const ptr = windows.peb().ProcessParameters.Environment;1218 const ptr = windows.peb().ProcessParameters.Environment;
1219 var ascii_match: ?[:0]const u16 = null;
1231 var i: usize = 0;1220 var i: usize = 0;
1232 while (ptr[i] != 0) {1221 while (ptr[i] != 0) {
1233 const key_start = i;1222 const key_start = i;
...@@ -1241,11 +1230,22 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {...@@ -1241,11 +1230,22 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
1241 while (ptr[i] != 0) : (i += 1) {}1230 while (ptr[i] != 0) : (i += 1) {}
1242 const this_value = ptr[value_start..i :0];1231 const this_value = ptr[value_start..i :0];
12431232
1244 if (utf16LeAsciiEqlIgnoreCase(key_slice, this_key)) return this_value;1233 if (mem.eql(u16, key_slice, this_key)) return this_value;
1234
1235 ascii_check: {
1236 if (ascii_match != null) break :ascii_check;
1237 if (key_slice.len != this_key.len) break :ascii_check;
1238 for (key_slice) |a_c, key_index| {
1239 const a = math.cast(u8, a_c) catch break :ascii_check;
1240 const b = math.cast(u8, this_key[key_index]) catch break :ascii_check;
1241 if (std.ascii.toLower(a) != std.ascii.toLower(b)) break :ascii_check;
1242 }
1243 ascii_match = this_value;
1244 }
12451245
1246 i += 1; // skip over null byte1246 i += 1; // skip over null byte
1247 }1247 }
1248 return null;1248 return ascii_match;
1249}1249}
12501250
1251pub const GetCwdError = error{1251pub const GetCwdError = error{