diff options
Diffstat (limited to 'lib/std/comptime_string_map.zig')
| -rw-r--r-- | lib/std/comptime_string_map.zig | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/lib/std/comptime_string_map.zig b/lib/std/comptime_string_map.zig index ee5e714c5d..2c1c260df2 100644 --- a/lib/std/comptime_string_map.zig +++ b/lib/std/comptime_string_map.zig @@ -7,7 +7,42 @@ const mem = std.mem; /// /// `kvs_list` expects a list of `struct { []const u8, V }` (key-value pair) tuples. /// You can pass `struct { []const u8 }` (only keys) tuples if `V` is `void`. -pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type { +pub fn ComptimeStringMap( + comptime V: type, + comptime kvs_list: anytype, +) type { + return ComptimeStringMapWithEql(V, kvs_list, defaultEql); +} + +/// Like `std.mem.eql`, but takes advantage of the fact that the lengths +/// of `a` and `b` are known to be equal. +pub fn defaultEql(a: []const u8, b: []const u8) bool { + if (a.ptr == b.ptr) return true; + for (a, b) |a_elem, b_elem| { + if (a_elem != b_elem) return false; + } + return true; +} + +/// Like `std.ascii.eqlIgnoreCase` but takes advantage of the fact that +/// the lengths of `a` and `b` are known to be equal. +pub fn eqlAsciiIgnoreCase(a: []const u8, b: []const u8) bool { + if (a.ptr == b.ptr) return true; + for (a, b) |a_c, b_c| { + if (std.ascii.toLower(a_c) != std.ascii.toLower(b_c)) return false; + } + return true; +} + +/// ComptimeStringMap, but accepts an equality function (`eql`). +/// The `eql` function is only called to determine the equality +/// of equal length strings. Any strings that are not equal length +/// are never compared using the `eql` function. +pub fn ComptimeStringMapWithEql( + comptime V: type, + comptime kvs_list: anytype, + comptime eql: fn (a: []const u8, b: []const u8) bool, +) type { const precomputed = comptime blk: { @setEvalBranchQuota(1500); const KV = struct { @@ -76,7 +111,7 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type { const kv = precomputed.sorted_kvs[i]; if (kv.key.len != str.len) return null; - if (mem.eql(u8, kv.key, str)) + if (eql(kv.key, str)) return kv.value; i += 1; if (i >= precomputed.sorted_kvs.len) @@ -180,3 +215,20 @@ fn testSet(comptime map: anytype) !void { try std.testing.expect(!map.has("missing")); try std.testing.expect(map.has("these")); } + +test "ComptimeStringMapWithEql" { + const map = ComptimeStringMapWithEql(TestEnum, .{ + .{ "these", .D }, + .{ "have", .A }, + .{ "nothing", .B }, + .{ "incommon", .C }, + .{ "samelen", .E }, + }, eqlAsciiIgnoreCase); + + try testMap(map); + try std.testing.expectEqual(TestEnum.A, map.get("HAVE").?); + try std.testing.expectEqual(TestEnum.E, map.get("SameLen").?); + try std.testing.expect(null == map.get("SameLength")); + + try std.testing.expect(map.has("ThESe")); +} |
