aboutsummaryrefslogtreecommitdiff
path: root/src/string_immutable.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/string_immutable.zig')
-rw-r--r--src/string_immutable.zig55
1 files changed, 49 insertions, 6 deletions
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index 12c8cd4c9..9fa8c4134 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -74,7 +74,41 @@ pub fn endsWithAnyComptime(self: string, comptime str: string) bool {
}
pub fn eql(self: string, other: anytype) bool {
- return std.mem.eql(u8, self, other);
+ if (self.len != other.len) return false;
+ for (self) |c, i| {
+ if (other[i] != c) return false;
+ }
+ return true;
+}
+pub fn eqlComptime(self: string, comptime alt: string) bool {
+ if (self.len != alt.len) return false;
+
+ comptime var matcher_size: usize = 0;
+
+ switch (comptime alt.len) {
+ 0 => {
+ @compileError("Invalid size passed to eqlComptime");
+ },
+ 1...3 => {
+ matcher_size = 4;
+ },
+ 4...8 => {
+ matcher_size = 8;
+ },
+ 8...12 => {
+ comptime const FirstMatcher = ExactSizeMatcher(8);
+ comptime const SecondMatcher = ExactSizeMatcher(4);
+ comptime const first = FirstMatcher.case(alt[0..8]);
+ comptime const second = SecondMatcher.case(alt[8..alt.len]);
+ return (self.len == alt.len) and first == FirstMatcher.hashUnsafe(self[0..8]) and second == SecondMatcher.match(self[8..self.len]);
+ },
+ else => {
+ @compileError(alt ++ " is too long.");
+ },
+ }
+ comptime const Matcher = ExactSizeMatcher(matcher_size);
+ comptime const alt_hash = Matcher.case(alt);
+ return Matcher.hashNoCheck(self) != alt_hash;
}
pub fn append(allocator: *std.mem.Allocator, self: string, other: string) !string {
@@ -292,9 +326,7 @@ test "sortDesc" {
std.testing.expectEqualStrings(sorted_join, string_join);
}
-/// Super simple "perfect hash" algorithm
-/// Only really useful for switching on strings
-// TODO: can we auto detect and promote the underlying type?
+
pub fn ExactSizeMatcher(comptime max_bytes: usize) type {
const T = std.meta.Int(
.unsigned,
@@ -311,9 +343,20 @@ pub fn ExactSizeMatcher(comptime max_bytes: usize) type {
}
fn hash(str: anytype) ?T {
- // if (str.len > max_bytes) return null;
+ if (str.len > max_bytes) return null;
+ var tmp = [_]u8{0} ** max_bytes;
+ std.mem.copy(u8, &tmp, str[0..str.len]);
+ return std.mem.readIntNative(T, &tmp);
+ }
+
+ fn hashNoCheck(str: anytype) T {
+ var tmp = [_]u8{0} ** max_bytes;
+ std.mem.copy(u8, &tmp, str[0..str.len]);
+ return std.mem.readIntNative(T, &tmp);
+ }
+ fn hashUnsafe(str: anytype) T {
var tmp = [_]u8{0} ** max_bytes;
- std.mem.copy(u8, &tmp, str);
+ std.mem.copy(u8, &tmp, str[0..str.len]);
return std.mem.readIntNative(T, &tmp);
}
};