| ... | @@ -70,11 +70,15 @@ pub fn StaticStringMapWithEql( | ... | @@ -70,11 +70,15 @@ pub fn StaticStringMapWithEql( |
| 70 | /// (only keys) tuples if `V` is `void`. | 70 | /// (only keys) tuples if `V` is `void`. |
| 71 | pub inline fn initComptime(comptime kvs_list: anytype) Self { | 71 | pub inline fn initComptime(comptime kvs_list: anytype) Self { |
| 72 | comptime { | 72 | comptime { |
| 73 | @setEvalBranchQuota(30 * kvs_list.len); | | |
| 74 | var self = Self{}; | 73 | var self = Self{}; |
| 75 | if (kvs_list.len == 0) | 74 | if (kvs_list.len == 0) |
| 76 | return self; | 75 | return self; |
| 77 | | 76 | |
| | 77 | // Since the KVs are sorted, a linearly-growing bound will never |
| | 78 | // be sufficient for extreme cases. So we grow proportional to |
| | 79 | // N*log2(N). |
| | 80 | @setEvalBranchQuota(10 * kvs_list.len * std.math.log2_int_ceil(usize, kvs_list.len)); |
| | 81 | |
| 78 | var sorted_keys: [kvs_list.len][]const u8 = undefined; | 82 | var sorted_keys: [kvs_list.len][]const u8 = undefined; |
| 79 | var sorted_vals: [kvs_list.len]V = undefined; | 83 | var sorted_vals: [kvs_list.len]V = undefined; |
| 80 | | 84 | |
| ... | @@ -212,8 +216,12 @@ pub fn StaticStringMapWithEql( | ... | @@ -212,8 +216,12 @@ pub fn StaticStringMapWithEql( |
| 212 | } | 216 | } |
| 213 | } | 217 | } |
| 214 | | 218 | |
| 215 | /// Returns the longest key, value pair where key is a prefix of `str` | 219 | /// Returns the key-value pair where key is the longest prefix of `str` |
| 216 | /// else null. | 220 | /// else null. |
| | 221 | /// |
| | 222 | /// This is effectively an O(N) algorithm which loops from `max_len` to |
| | 223 | /// `min_len` and calls `getIndex()` to check all keys with the given |
| | 224 | /// len. |
| 217 | pub fn getLongestPrefix(self: Self, str: []const u8) ?KV { | 225 | pub fn getLongestPrefix(self: Self, str: []const u8) ?KV { |
| 218 | if (self.kvs.len == 0) | 226 | if (self.kvs.len == 0) |
| 219 | return null; | 227 | return null; |
| ... | @@ -497,6 +505,33 @@ test "getLongestPrefix2" { | ... | @@ -497,6 +505,33 @@ test "getLongestPrefix2" { |
| 497 | try testing.expectEqual(null, map.getLongestPrefix("xxx")); | 505 | try testing.expectEqual(null, map.getLongestPrefix("xxx")); |
| 498 | } | 506 | } |
| 499 | | 507 | |
| 500 | test "long kvs_list doesn't exceed @setEvalBranchQuota" { | 508 | test "sorting kvs doesn't exceed eval branch quota" { |
| 501 | _ = TestMapVoid.initComptime([1]TestKVVoid{.{"x"}} ** 1_000); | 509 | // from https://github.com/ziglang/zig/issues/19803 |
| | 510 | const TypeToByteSizeLUT = std.StaticStringMap(u32).initComptime(.{ |
| | 511 | .{ "bool", 0 }, |
| | 512 | .{ "c_int", 0 }, |
| | 513 | .{ "c_long", 0 }, |
| | 514 | .{ "c_longdouble", 0 }, |
| | 515 | .{ "t20", 0 }, |
| | 516 | .{ "t19", 0 }, |
| | 517 | .{ "t18", 0 }, |
| | 518 | .{ "t17", 0 }, |
| | 519 | .{ "t16", 0 }, |
| | 520 | .{ "t15", 0 }, |
| | 521 | .{ "t14", 0 }, |
| | 522 | .{ "t13", 0 }, |
| | 523 | .{ "t12", 0 }, |
| | 524 | .{ "t11", 0 }, |
| | 525 | .{ "t10", 0 }, |
| | 526 | .{ "t9", 0 }, |
| | 527 | .{ "t8", 0 }, |
| | 528 | .{ "t7", 0 }, |
| | 529 | .{ "t6", 0 }, |
| | 530 | .{ "t5", 0 }, |
| | 531 | .{ "t4", 0 }, |
| | 532 | .{ "t3", 0 }, |
| | 533 | .{ "t2", 0 }, |
| | 534 | .{ "t1", 1 }, |
| | 535 | }); |
| | 536 | try testing.expectEqual(1, TypeToByteSizeLUT.get("t1")); |
| 502 | } | 537 | } |