| ... | @@ -63,26 +63,42 @@ pub const EnvMap = struct { | ... | @@ -63,26 +63,42 @@ pub const EnvMap = struct { |
| 63 | ); | 63 | ); |
| 64 | | 64 | |
| 65 | pub const EnvNameHashContext = struct { | 65 | pub const EnvNameHashContext = struct { |
| | 66 | fn upcase(c: u21) u21 { |
| | 67 | if (c <= std.math.maxInt(u16)) |
| | 68 | return std.os.windows.ntdll.RtlUpcaseUnicodeChar(c); |
| | 69 | return c; |
| | 70 | } |
| | 71 | |
| 66 | pub fn hash(self: @This(), s: []const u8) u64 { | 72 | pub fn hash(self: @This(), s: []const u8) u64 { |
| 67 | _ = self; | 73 | _ = self; |
| 68 | if (builtin.os.tag == .windows) { | 74 | if (builtin.os.tag == .windows) { |
| 69 | const h = std.hash.Wyhash.init(0); | 75 | const h = std.hash.Wyhash.init(0); |
| 70 | // TODO: improve this, instead of iterating over ascii, | 76 | var it = std.unicode.Utf8View(s).iterator(); |
| 71 | // iterate over with unicode | 77 | while (it.nextCodepoint()) |cp| { |
| 72 | for (s) |c| { | 78 | const cp_upper = upcase(cp); |
| 73 | var s_upper = [_]u8 { std.ascii.toLower(c) }; | 79 | h.update(&[_]u8{ |
| 74 | h.update(s_upper); | 80 | @intCast(u8, (cp_upper >> 16) & 0xff), |
| | 81 | @intCast(u8, (cp_upper >> 8) & 0xff), |
| | 82 | @intCast(u8, (cp_upper >> 0) & 0xff), |
| | 83 | }); |
| 75 | } | 84 | } |
| 76 | return h.final(); | 85 | return h.final(); |
| 77 | } | 86 | } |
| 78 | return std.hash_map.hashString(s); | 87 | return std.hash_map.hashString(s); |
| 79 | } | 88 | } |
| | 89 | |
| 80 | pub fn eql(self: @This(), a: []const u8, b: []const u8) bool { | 90 | pub fn eql(self: @This(), a: []const u8, b: []const u8) bool { |
| 81 | _ = self; | 91 | _ = self; |
| 82 | if (builtin.os.tag == .windows) { | 92 | if (builtin.os.tag == .windows) { |
| 83 | // TODO: improve this, instead of comparing ascii | 93 | var it_a = std.unicode.Utf8View(a).iterator(); |
| 84 | // compare with unicode | 94 | var it_b = std.unicode.Utf8View(b).iterator(); |
| 85 | return std.ascii.eqlIgnoreCase(a, b); | 95 | while (true) { |
| | 96 | const c_a = it_a.nextCodepoint() orelse break; |
| | 97 | const c_b = it_b.nextCodepoint() orelse return false; |
| | 98 | if (upcase(c_a) != upcase(c_b)) |
| | 99 | return false; |
| | 100 | } |
| | 101 | if (it_b.nextCodepoint()) return false; |
| 86 | } | 102 | } |
| 87 | return std.hash_map.eqlString(a, b); | 103 | return std.hash_map.eqlString(a, b); |
| 88 | } | 104 | } |