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.zig82
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;