diff --git a/BoyerMoore.h b/BoyerMoore.h index 830f4eb..0e16902 100644 --- a/BoyerMoore.h +++ b/BoyerMoore.h @@ -73,7 +73,7 @@ void prepare_goodsuffix_heuristic(const uint8_t *normal, const size_t size, int /* * Boyer-Moore search algorithm */ -const uint8_t *boyermoore_search(const uint8_t *haystack, size_t haystack_len, const uint8_t *needle, size_t needle_len) { +const uint8_t *boyermoore_search(const uint8_t *haystack, size_t haystack_len, const uint8_t *needle, size_t needle_len, bool reverse = false) { /* * Simple checks */ @@ -96,28 +96,54 @@ const uint8_t *boyermoore_search(const uint8_t *haystack, size_t haystack_len, c /* * Boyer-Moore search */ - size_t s = 0; - while(s <= (haystack_len - needle_len)) - { - size_t j = needle_len; - while(j > 0 && needle[j-1] == haystack[s+j-1]) - j--; - - if(j > 0) - { - int k = badcharacter[haystack[s+j-1]]; - int m; - if(k < (int)j && (m = j-k-1) > goodsuffix[j]) - s+= m; - else - s+= goodsuffix[j]; - } - else - { - delete[] goodsuffix; - return haystack + s; - } - } + size_t len = haystack_len - needle_len; + if (!reverse) { + size_t s = 0; + while(s <= len) + { + size_t j = needle_len; + while(j > 0 && needle[j-1] == haystack[s+j-1]) + j--; + + if(j > 0) + { + int k = badcharacter[haystack[s+j-1]]; + int m; + if(k < (int)j && (m = j-k-1) > goodsuffix[j]) + s+= m; + else + s+= goodsuffix[j]; + } + else + { + delete[] goodsuffix; + return haystack + s; + } + } + } else { + ptrdiff_t s = haystack_len; + while(s >= 0) + { + size_t j = needle_len; + while(j > 0 && needle[j-1] == haystack[s+(j-needle_len)-(s == haystack_len ? 1 : 0)]) + --j; + + if(j > 0) + { + int k = badcharacter[haystack[s+(j-needle_len)-(s == haystack_len ? 1 : 0)]]; + int m; + if(k < (int)j && (m = j-k-1) > goodsuffix[j]) + s-= m - (s == haystack_len ? 1 : 0); + else + s-= goodsuffix[j]; + } + else + { + delete[] goodsuffix; + return haystack + (s - needle_len) + (s == haystack_len ? 0 : 1); + } + } + } delete[] goodsuffix; /* not found */ diff --git a/buffertools.cc b/buffertools.cc index ddfbf88..061c243 100644 --- a/buffertools.cc +++ b/buffertools.cc @@ -177,6 +177,34 @@ struct IndexOfAction: BinaryAction { } }; +struct LastIndexOfAction: BinaryAction { + Handle apply(Handle& buffer, const uint8_t* data2, size_t size2, const Arguments& args, HandleScope& scope) { + const uint8_t* data = (const uint8_t*) Buffer::Data(buffer); + const size_t size = Buffer::Length(buffer); + size_t len = 0; + int32_t start; + + if (args[1]->IsInt32()) { + start = args[1]->Int32Value(); + + if (start < 0) + start = size - std::min(size, -start); + else if (static_cast(start) > size) + start = size; + + if (start > 0) + len = size - start; + } else + len = size; + + const uint8_t* p = boyermoore_search( + data, len, data2, size2, true); + + const ptrdiff_t offset = p ? (p - data) : -1; + return scope.Close(Integer::New(offset)); + } +}; + static char toHexTable[] = "0123456789abcdef"; // CHECKME is this cache efficient? @@ -276,6 +304,10 @@ Handle IndexOf(const Arguments& args) { return IndexOfAction()(args); } +Handle LastIndexOf(const Arguments& args) { + return LastIndexOfAction()(args); +} + Handle FromHex(const Arguments& args) { return FromHexAction()(args); } @@ -341,6 +373,7 @@ void RegisterModule(Handle target) { target->Set(String::NewSymbol("equals"), FunctionTemplate::New(Equals)->GetFunction()); target->Set(String::NewSymbol("compare"), FunctionTemplate::New(Compare)->GetFunction()); target->Set(String::NewSymbol("indexOf"), FunctionTemplate::New(IndexOf)->GetFunction()); + target->Set(String::NewSymbol("lastIndexOf"), FunctionTemplate::New(LastIndexOf)->GetFunction()); target->Set(String::NewSymbol("fromHex"), FunctionTemplate::New(FromHex)->GetFunction()); target->Set(String::NewSymbol("toHex"), FunctionTemplate::New(ToHex)->GetFunction()); }