[internal] Make string comparisons faster

This commit is contained in:
Jarred Sumner
2022-12-04 06:53:53 -08:00
parent 34b2e9acc2
commit 714ce7619d
25 changed files with 150 additions and 256 deletions

View File

@@ -166,7 +166,22 @@ pub inline fn lastIndexOf(self: string, str: string) ?usize {
}
pub inline fn indexOf(self: string, str: string) ?usize {
return std.mem.indexOf(u8, self, str);
const self_ptr = self.ptr;
const self_len = self.len;
const str_ptr = str.ptr;
const str_len = str.len;
// > Both old and new libc's have the bug that if needle is empty,
// > haystack-1 (instead of haystack) is returned. And glibc 2.0 makes it
// > worse, returning a pointer to the last byte of haystack. This is fixed
// > in glibc 2.1.
if (self_len == 0 or str_len == 0 or self_len < str_len)
return null;
const start = bun.C.memmem(self_ptr, self_len, str_ptr, str_len) orelse return null;
return @ptrToInt(start) - @ptrToInt(self_ptr);
}
// --
@@ -729,58 +744,73 @@ pub fn eqlCaseInsensitiveASCII(a: string, comptime b: anytype, comptime check_le
return true;
}
pub fn eqlLong(a_: string, b: string, comptime check_len: bool) bool {
pub fn eqlLong(a_str: string, b_str: string, comptime check_len: bool) bool {
const len = b_str.len;
if (comptime check_len) {
if (a_.len == 0) {
return b.len == 0;
if (len == 0) {
return a_str.len == 0;
}
if (a_.len != b.len) {
if (a_str.len != len) {
return false;
}
} else {
std.debug.assert(b_str.len == a_str.len);
}
const len = b.len;
var dword_length = b.len >> 3;
var b_ptr: usize = 0;
const a = a_.ptr;
const end = b_str.ptr + len;
var a = a_str.ptr;
var b = b_str.ptr;
while (dword_length > 0) : (dword_length -= 1) {
const slice = b.ptr;
if (@bitCast(usize, a[b_ptr..len][0..@sizeOf(usize)].*) != @bitCast(usize, (slice[b_ptr..b.len])[0..@sizeOf(usize)].*))
return false;
b_ptr += @sizeOf(usize);
if (b_ptr == b.len) return true;
if (a == b)
return true;
{
var dword_length = len >> 3;
while (dword_length > 0) : (dword_length -= 1) {
if (@bitCast(usize, a[0..@sizeOf(usize)].*) != @bitCast(usize, b[0..@sizeOf(usize)].*))
return false;
b += @sizeOf(usize);
if (b == end) return true;
a += @sizeOf(usize);
}
}
if (comptime @sizeOf(usize) == 8) {
if ((len & 4) != 0) {
const slice = b.ptr;
if (@bitCast(u32, a[b_ptr..len][0..@sizeOf(u32)].*) != @bitCast(u32, (slice[b_ptr..b.len])[0..@sizeOf(u32)].*))
if (@bitCast(u32, a[0..@sizeOf(u32)].*) != @bitCast(u32, b[0..@sizeOf(u32)].*))
return false;
b_ptr += @sizeOf(u32);
if (b_ptr == b.len) return true;
b += @sizeOf(u32);
if (b == end) return true;
a += @sizeOf(u32);
}
}
if ((len & 2) != 0) {
if (@bitCast(u16, a[b_ptr..len][0..@sizeOf(u16)].*) != @bitCast(u16, b.ptr[b_ptr..len][0..@sizeOf(u16)].*))
if (@bitCast(u16, a[0..@sizeOf(u16)].*) != @bitCast(u16, b[0..@sizeOf(u16)].*))
return false;
b_ptr += @sizeOf(u16);
b += @sizeOf(u16);
if (b_ptr == b.len) return true;
if (b == end) return true;
a += @sizeOf(u16);
}
if (((len & 1) != 0) and a[b_ptr] != b[b_ptr]) return false;
if (((len & 1) != 0) and a[0] != b[0]) return false;
return true;
}
pub inline fn append(allocator: std.mem.Allocator, self: string, other: string) ![]u8 {
return std.fmt.allocPrint(allocator, "{s}{s}", .{ self, other });
var buf = try allocator.alloc(u8, self.len + other.len);
if (self.len > 0)
@memcpy(buf.ptr, self.ptr, self.len);
if (other.len > 0)
@memcpy(buf.ptr + self.len, other.ptr, other.len);
return buf;
}
pub inline fn joinBuf(out: []u8, parts: anytype, comptime parts_len: usize) []u8 {
@@ -798,7 +828,7 @@ pub inline fn joinBuf(out: []u8, parts: anytype, comptime parts_len: usize) []u8
}
pub fn index(self: string, str: string) i32 {
if (std.mem.indexOf(u8, self, str)) |i| {
if (strings.indexOf(self, str)) |i| {
return @intCast(i32, i);
} else {
return -1;