@@ -7,7 +7,42 @@ const mem = std.mem;
77///
88/// `kvs_list` expects a list of `struct { []const u8, V }` (key-value pair) tuples.
99/// 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 {
1146 const precomputed = comptime blk : {
1247 @setEvalBranchQuota (1500 );
1348 const KV = struct {
@@ -76,7 +111,7 @@ pub fn ComptimeStringMap(comptime V: type, comptime kvs_list: anytype) type {
76111 const kv = precomputed .sorted_kvs [i ];
77112 if (kv .key .len != str .len )
78113 return null ;
79- if (mem . eql (u8 , kv .key , str ))
114+ if (eql (kv .key , str ))
80115 return kv .value ;
81116 i += 1 ;
82117 if (i >= precomputed .sorted_kvs .len )
@@ -180,3 +215,20 @@ fn testSet(comptime map: anytype) !void {
180215 try std .testing .expect (! map .has ("missing" ));
181216 try std .testing .expect (map .has ("these" ));
182217}
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