diff options
Diffstat (limited to 'src/string_immutable.zig')
-rw-r--r-- | src/string_immutable.zig | 82 |
1 files changed, 56 insertions, 26 deletions
diff --git a/src/string_immutable.zig b/src/string_immutable.zig index 618764072..4b8db5cb4 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -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; |