| ... | ... | @@ -63,26 +63,42 @@ pub const EnvMap = struct { |
| 63 | 63 | ); |
| 64 | 64 | |
| 65 | 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 | 72 | pub fn hash(self: @This(), s: []const u8) u64 { |
| 67 | 73 | _ = self; |
| 68 | 74 | if (builtin.os.tag == .windows) { |
| 69 | 75 | const h = std.hash.Wyhash.init(0); |
| 70 | | // TODO: improve this, instead of iterating over ascii, |
| 71 | | // iterate over with unicode |
| 72 | | for (s) |c| { |
| 73 | | var s_upper = [_]u8 { std.ascii.toLower(c) }; |
| 74 | | h.update(s_upper); |
| 76 | var it = std.unicode.Utf8View(s).iterator(); |
| 77 | while (it.nextCodepoint()) |cp| { |
| 78 | const cp_upper = upcase(cp); |
| 79 | h.update(&[_]u8{ |
| 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 | 85 | return h.final(); |
| 77 | 86 | } |
| 78 | 87 | return std.hash_map.hashString(s); |
| 79 | 88 | } |
| 89 | |
| 80 | 90 | pub fn eql(self: @This(), a: []const u8, b: []const u8) bool { |
| 81 | 91 | _ = self; |
| 82 | 92 | if (builtin.os.tag == .windows) { |
| 83 | | // TODO: improve this, instead of comparing ascii |
| 84 | | // compare with unicode |
| 85 | | return std.ascii.eqlIgnoreCase(a, b); |
| 93 | var it_a = std.unicode.Utf8View(a).iterator(); |
| 94 | var it_b = std.unicode.Utf8View(b).iterator(); |
| 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 | 103 | return std.hash_map.eqlString(a, b); |
| 88 | 104 | } |