authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-22 05:34:49-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-22 20:51:17-04:00
logd7bf4f80703d16a6485f605c89d24acf427b4680
tree593497e2164ab048826f32f367b600102ac4a19d
parent8c87a981f185ca46d0da48cb46f57680e562631a

fix Boyer-Moore-Horspool algorithm in indexOfPos and lastIndexOf when element type is larger than a byte


1 files changed, 34 insertions(+), 2 deletions(-)

lib/std/mem.zig+34-2
......@@ -1107,7 +1107,9 @@ pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?us
11071107
11081108 var i: usize = haystack_bytes.len - needle_bytes.len;
11091109 while (true) {
1110 if (mem.eql(u8, haystack_bytes[i .. i + needle_bytes.len], needle_bytes)) return i;
1110 if (i % @sizeOf(T) == 0 and mem.eql(u8, haystack_bytes[i .. i + needle_bytes.len], needle_bytes)) {
1111 return @divExact(i, @sizeOf(T));
1112 }
11111113 const skip = skip_table[haystack_bytes[i]];
11121114 if (skip > i) break;
11131115 i -= skip;
......@@ -1132,7 +1134,9 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee
11321134
11331135 var i: usize = start_index * @sizeOf(T);
11341136 while (i <= haystack_bytes.len - needle_bytes.len) {
1135 if (mem.eql(u8, haystack_bytes[i .. i + needle_bytes.len], needle_bytes)) return i;
1137 if (i % @sizeOf(T) == 0 and mem.eql(u8, haystack_bytes[i .. i + needle_bytes.len], needle_bytes)) {
1138 return @divExact(i, @sizeOf(T));
1139 }
11361140 i += skip_table[haystack_bytes[i + needle_bytes.len - 1]];
11371141 }
11381142
......@@ -1164,6 +1168,34 @@ test "mem.indexOf" {
11641168 try testing.expect(lastIndexOfScalar(u8, "boo", 'o').? == 2);
11651169}
11661170
1171test "mem.indexOf multibyte" {
1172 {
1173 // make haystack and needle long enough to trigger boyer-moore-horspool algorithm
1174 const haystack = [1]u16{0} ** 100 ++ [_]u16 { 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff };
1175 const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee };
1176 try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needle), 100);
1177
1178 // check for misaligned false positives (little and big endian)
1179 const needleLE = [_]u16{ 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff };
1180 try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needleLE), null);
1181 const needleBE = [_]u16{ 0xaacc, 0xbbdd, 0xccee, 0xddff, 0xee00 };
1182 try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needleBE), null);
1183 }
1184
1185 {
1186 // make haystack and needle long enough to trigger boyer-moore-horspool algorithm
1187 const haystack = [_]u16 { 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ [1]u16{0} ** 100;
1188 const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee };
1189 try testing.expectEqual(lastIndexOf(u16, &haystack, &needle), 0);
1190
1191 // check for misaligned false positives (little and big endian)
1192 const needleLE = [_]u16{ 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff };
1193 try testing.expectEqual(lastIndexOf(u16, &haystack, &needleLE), null);
1194 const needleBE = [_]u16{ 0xaacc, 0xbbdd, 0xccee, 0xddff, 0xee00 };
1195 try testing.expectEqual(lastIndexOf(u16, &haystack, &needleBE), null);
1196 }
1197}
1198
11671199/// Returns the number of needles inside the haystack
11681200/// needle.len must be > 0
11691201/// does not count overlapping needles