aboutsummaryrefslogtreecommitdiff
path: root/lib/std/comptime_string_map.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/comptime_string_map.zig')
-rw-r--r--lib/std/comptime_string_map.zig56
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"));
+}