mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
std.CompTimeStringMap*: support empty initialization list
Add tests for empty initialization, and some more corner cases (empty key, very long key, duplicate keys). Fixes #18212
This commit is contained in:
parent
45836678d7
commit
04ac028a2c
@ -43,12 +43,15 @@ pub fn ComptimeStringMapWithEql(
|
||||
comptime kvs_list: anytype,
|
||||
comptime eql: fn (a: []const u8, b: []const u8) bool,
|
||||
) type {
|
||||
const precomputed = comptime blk: {
|
||||
const empty_list = kvs_list.len == 0;
|
||||
const precomputed = blk: {
|
||||
@setEvalBranchQuota(1500);
|
||||
const KV = struct {
|
||||
key: []const u8,
|
||||
value: V,
|
||||
};
|
||||
if (empty_list)
|
||||
break :blk .{};
|
||||
var sorted_kvs: [kvs_list.len]KV = undefined;
|
||||
for (kvs_list, 0..) |kv, i| {
|
||||
if (V != void) {
|
||||
@ -103,10 +106,16 @@ pub fn ComptimeStringMapWithEql(
|
||||
|
||||
/// Returns the value for the key if any, else null.
|
||||
pub fn get(str: []const u8) ?V {
|
||||
if (empty_list)
|
||||
return null;
|
||||
|
||||
return precomputed.sorted_kvs[getIndex(str) orelse return null].value;
|
||||
}
|
||||
|
||||
pub fn getIndex(str: []const u8) ?usize {
|
||||
if (empty_list)
|
||||
return null;
|
||||
|
||||
if (str.len < precomputed.min_len or str.len > precomputed.max_len)
|
||||
return null;
|
||||
|
||||
@ -143,6 +152,9 @@ test "ComptimeStringMap list literal of list literals" {
|
||||
});
|
||||
|
||||
try testMap(map);
|
||||
|
||||
// Default comparison is case sensitive
|
||||
try std.testing.expect(null == map.get("NOTHING"));
|
||||
}
|
||||
|
||||
test "ComptimeStringMap array of structs" {
|
||||
@ -181,6 +193,9 @@ fn testMap(comptime map: anytype) !void {
|
||||
|
||||
try std.testing.expect(!map.has("missing"));
|
||||
try std.testing.expect(map.has("these"));
|
||||
|
||||
try std.testing.expect(null == map.get(""));
|
||||
try std.testing.expect(null == map.get("averylongstringthathasnomatches"));
|
||||
}
|
||||
|
||||
test "ComptimeStringMap void value type, slice of structs" {
|
||||
@ -195,6 +210,9 @@ test "ComptimeStringMap void value type, slice of structs" {
|
||||
const map = ComptimeStringMap(void, slice);
|
||||
|
||||
try testSet(map);
|
||||
|
||||
// Default comparison is case sensitive
|
||||
try std.testing.expect(null == map.get("NOTHING"));
|
||||
}
|
||||
|
||||
test "ComptimeStringMap void value type, list literal of list literals" {
|
||||
@ -218,6 +236,9 @@ fn testSet(comptime map: anytype) !void {
|
||||
|
||||
try std.testing.expect(!map.has("missing"));
|
||||
try std.testing.expect(map.has("these"));
|
||||
|
||||
try std.testing.expect(null == map.get(""));
|
||||
try std.testing.expect(null == map.get("averylongstringthathasnomatches"));
|
||||
}
|
||||
|
||||
test "ComptimeStringMapWithEql" {
|
||||
@ -236,3 +257,45 @@ test "ComptimeStringMapWithEql" {
|
||||
|
||||
try std.testing.expect(map.has("ThESe"));
|
||||
}
|
||||
|
||||
test "ComptimeStringMap empty" {
|
||||
const m1 = ComptimeStringMap(usize, .{});
|
||||
try std.testing.expect(null == m1.get("anything"));
|
||||
|
||||
const m2 = ComptimeStringMapWithEql(usize, .{}, eqlAsciiIgnoreCase);
|
||||
try std.testing.expect(null == m2.get("anything"));
|
||||
}
|
||||
|
||||
test "ComptimeStringMap redundant entries" {
|
||||
const map = ComptimeStringMap(TestEnum, .{
|
||||
.{ "redundant", .D },
|
||||
.{ "theNeedle", .A },
|
||||
.{ "redundant", .B },
|
||||
.{ "re" ++ "dundant", .C },
|
||||
.{ "redun" ++ "dant", .E },
|
||||
});
|
||||
|
||||
// No promises about which one you get:
|
||||
try std.testing.expect(null != map.get("redundant"));
|
||||
|
||||
// Default map is not case sensitive:
|
||||
try std.testing.expect(null == map.get("REDUNDANT"));
|
||||
|
||||
try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?);
|
||||
}
|
||||
|
||||
test "ComptimeStringMap redundant insensitive" {
|
||||
const map = ComptimeStringMapWithEql(TestEnum, .{
|
||||
.{ "redundant", .D },
|
||||
.{ "theNeedle", .A },
|
||||
.{ "redundanT", .B },
|
||||
.{ "RE" ++ "dundant", .C },
|
||||
.{ "redun" ++ "DANT", .E },
|
||||
}, eqlAsciiIgnoreCase);
|
||||
|
||||
// No promises about which result you'll get ...
|
||||
try std.testing.expect(null != map.get("REDUNDANT"));
|
||||
try std.testing.expect(null != map.get("ReDuNdAnT"));
|
||||
|
||||
try std.testing.expectEqual(TestEnum.A, map.get("theNeedle").?);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user