authorgravatar for dec05eba@protonmail.comdec05eba <dec05eba@protonmail.com> 2020-09-05 11:24:05+02:00
committergravatar for dec05eba@protonmail.comdec05eba <dec05eba@protonmail.com> 2020-09-05 11:24:05+02:00
loge297b4815ca6a30c6d20fc8dc8aa186faa1384b7
tree7535d89f23e6e94d0c41b3864d2bb0f9af06fde6
parent50c52e013541550c7c89c30d336bc4991218f888

Create skipping table

Also fallback to naive implementation if haystack is small or if the needle is small or if sizeof type is not 1.

1 files changed, 53 insertions(+), 15 deletions(-)

lib/std/mem.zig+53-15
...@@ -850,20 +850,56 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val...@@ -850,20 +850,56 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val
850pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {850pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
851 return indexOfPos(T, haystack, 0, needle);851 return indexOfPos(T, haystack, 0, needle);
852}852}
853
854/// Find the index in a slice of a sub-slice, searching from the end backwards.
855/// To start looking at a different index, slice the haystack first.
856fn lastIndexOfNaive(comptime T: type, haystack: []const T, needle: []const T) ?usize {
857 if (needle.len > haystack.len) return null;
858
859 var i: usize = haystack.len - needle.len;
860 while (true) : (i -= 1) {
861 if (mem.eql(T, haystack[i .. i + needle.len], needle)) return i;
862 if (i == 0) return null;
863 }
864}
865
866fn indexOfPosNaive(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
867 if (needle.len > haystack.len) return null;
868
869 var i: usize = start_index;
870 const end = haystack.len - needle.len;
871 while (i <= end) : (i += 1) {
872 if (eql(T, haystack[i .. i + needle.len], needle)) return i;
873 }
874 return null;
875}
876
877fn boyerMooreHorspoolPreprocess(pattern: []const u8, table: []usize) void {
878 for (table) |*c| {
879 c.* = pattern.len;
880 }
881
882 var i: usize = 0;
883 while (i < pattern.len - 1) : (i += 1) {
884 table[pattern[i]] = pattern.len - 1 - i;
885 }
886}
853/// Find the index in a slice of a sub-slice, searching from the end backwards.887/// Find the index in a slice of a sub-slice, searching from the end backwards.
854/// To start looking at a different index, slice the haystack first.888/// To start looking at a different index, slice the haystack first.
855// Reverse boyer-moore-horspool algorithm889// Reverse boyer-moore-horspool algorithm
856pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {890pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
891 if (T != u8 or haystack.len < 32 or needle.len <= 2)
892 return lastIndexOfNaive(T, haystack, needle);
893
857 if (needle.len > haystack.len or needle.len == 0) return null;894 if (needle.len > haystack.len or needle.len == 0) return null;
895 var table: [256]usize = undefined;
896 boyerMooreHorspoolPreprocess(needle, table[0..]);
858897
859 var i: usize = needle.len - 1;898 var i: usize = 0;
860 while (i < haystack.len) {899 while (i <= haystack.len - needle.len) {
861 const reverseIndex = haystack.len - i - 1;900 const reverseIndex = haystack.len - i - needle.len - 1;
862 if (indexOfScalar(T, needle, haystack[reverseIndex])) |index| {901 if (mem.eql(T, haystack[reverseIndex .. reverseIndex + needle.len], needle)) return i;
863 const haystackIndex = reverseIndex - index;902 i += table[haystack[reverseIndex + needle.len - 1]];
864 if (haystackIndex + needle.len <= haystack.len and mem.eql(T, haystack[haystackIndex .. haystackIndex + needle.len], needle)) return haystackIndex;
865 }
866 i += needle.len;
867 }903 }
868904
869 return null;905 return null;
...@@ -871,15 +907,17 @@ pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?us...@@ -871,15 +907,17 @@ pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?us
871907
872// Boyer-moore-horspool algorithm908// Boyer-moore-horspool algorithm
873pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {909pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
910 if (T != u8 or haystack.len < 32 or needle.len <= 2)
911 return indexOfPosNaive(T, haystack, start_index, needle);
912
874 if (needle.len > haystack.len or needle.len == 0) return null;913 if (needle.len > haystack.len or needle.len == 0) return null;
914 var table: [256]usize = undefined;
915 boyerMooreHorspoolPreprocess(needle, table[0..]);
875916
876 var i: usize = start_index + needle.len - 1;917 var i: usize = start_index;
877 while (i < haystack.len) {918 while (i <= haystack.len - needle.len) {
878 if (lastIndexOfScalar(T, needle, haystack[i])) |index| {919 if (mem.eql(T, haystack[i .. i + needle.len], needle)) return i;
879 const haystackIndex = i - index;920 i += table[haystack[i + needle.len - 1]];
880 if (haystackIndex + needle.len <= haystack.len and mem.eql(T, haystack[haystackIndex .. haystackIndex + needle.len], needle)) return haystackIndex;
881 }
882 i += needle.len;
883 }921 }
884922
885 return null;923 return null;