@@ -7,7 +7,42 @@ const mem = std.mem;
7
7
///
8
8
/// `kvs_list` expects a list of `struct { []const u8, V }` (key-value pair) tuples.
9
9
/// You can pass `struct { []const u8 }` (only keys) tuples if `V` is `void`.
10
- pub fn ComptimeStringMap (comptime V : type , comptime kvs_list : anytype ) type {
10
+ pub fn ComptimeStringMap (
11
+ comptime V : type ,
12
+ comptime kvs_list : anytype ,
13
+ ) type {
14
+ return ComptimeStringMapWithEql (V , kvs_list , defaultEql );
15
+ }
16
+
17
+ /// Like `std.mem.eql`, but takes advantage of the fact that the lengths
18
+ /// of `a` and `b` are known to be equal.
19
+ pub fn defaultEql (a : []const u8 , b : []const u8 ) bool {
20
+ if (a .ptr == b .ptr ) return true ;
21
+ for (a , b ) | a_elem , b_elem | {
22
+ if (a_elem != b_elem ) return false ;
23
+ }
24
+ return true ;
25
+ }
26
+
27
+ /// Like `std.ascii.eqlIgnoreCase` but takes advantage of the fact that
28
+ /// the lengths of `a` and `b` are known to be equal.
29
+ pub fn eqlAsciiIgnoreCase (a : []const u8 , b : []const u8 ) bool {
30
+ if (a .ptr == b .ptr ) return true ;
31
+ for (a , b ) | a_c , b_c | {
32
+ if (std .ascii .toLower (a_c ) != std .ascii .toLower (b_c )) return false ;
33
+ }
34
+ return true ;
35
+ }
36
+
37
+ /// ComptimeStringMap, but accepts an equality function (`eql`).
38
+ /// The `eql` function is only called to determine the equality
39
+ /// of equal length strings. Any strings that are not equal length
40
+ /// are never compared using the `eql` function.
41
+ pub fn ComptimeStringMapWithEql (
42
+ comptime V : type ,
43
+ comptime kvs_list : anytype ,
44
+ comptime eql : fn (a : []const u8 , b : []const u8 ) bool ,
45
+ ) type {
11
46
const precomputed = comptime blk : {
12
47
@setEvalBranchQuota (1500 );
13
48
const KV = struct {
@@ -76,7 +111,7 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type {
76
111
const kv = precomputed .sorted_kvs [i ];
77
112
if (kv .key .len != str .len )
78
113
return null ;
79
- if (mem . eql (u8 , kv .key , str ))
114
+ if (eql (kv .key , str ))
80
115
return kv .value ;
81
116
i += 1 ;
82
117
if (i >= precomputed .sorted_kvs .len )
@@ -180,3 +215,20 @@ fn testSet(comptime map: anytype) !void {
180
215
try std .testing .expect (! map .has ("missing" ));
181
216
try std .testing .expect (map .has ("these" ));
182
217
}
218
+
219
+ test "ComptimeStringMapWithEql" {
220
+ const map = ComptimeStringMapWithEql (TestEnum , .{
221
+ .{ "these" , .D },
222
+ .{ "have" , .A },
223
+ .{ "nothing" , .B },
224
+ .{ "incommon" , .C },
225
+ .{ "samelen" , .E },
226
+ }, eqlAsciiIgnoreCase );
227
+
228
+ try testMap (map );
229
+ try std .testing .expectEqual (TestEnum .A , map .get ("HAVE" ).? );
230
+ try std .testing .expectEqual (TestEnum .E , map .get ("SameLen" ).? );
231
+ try std .testing .expect (null == map .get ("SameLength" ));
232
+
233
+ try std .testing .expect (map .has ("ThESe" ));
234
+ }
0 commit comments