Tweak String.indexOf(_,_) a bit.
- Simplify the arithmetic a little in wrenStringFind(). - Allow the start to be negative. - Even more tests. - Docs.
This commit is contained in:
+10
-9
@@ -879,14 +879,14 @@ DEF_PRIMITIVE(string_endsWith)
|
||||
ObjString* string = AS_STRING(args[0]);
|
||||
ObjString* search = AS_STRING(args[1]);
|
||||
|
||||
// Corner case, if the search string is longer than return false right away.
|
||||
// Edge case: If the search string is longer then return false right away.
|
||||
if (search->length > string->length) RETURN_FALSE;
|
||||
|
||||
RETURN_BOOL(memcmp(string->value + string->length - search->length,
|
||||
search->value, search->length) == 0);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_indexOf)
|
||||
DEF_PRIMITIVE(string_indexOf1)
|
||||
{
|
||||
if (!validateString(vm, args[1], "Argument")) return false;
|
||||
|
||||
@@ -897,15 +897,16 @@ DEF_PRIMITIVE(string_indexOf)
|
||||
RETURN_NUM(index == UINT32_MAX ? -1 : (int)index);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_indexOf_with_startIndex)
|
||||
DEF_PRIMITIVE(string_indexOf2)
|
||||
{
|
||||
if (!validateString(vm, args[1], "Argument")) return false;
|
||||
|
||||
ObjString* string = AS_STRING(args[0]);
|
||||
ObjString* search = AS_STRING(args[1]);
|
||||
uint32_t startIndex = AS_NUM(args[2]);
|
||||
|
||||
uint32_t index = wrenStringFind(string, search, startIndex);
|
||||
uint32_t start = validateIndex(vm, args[2], string->length, "Start");
|
||||
if (start == UINT32_MAX) return false;
|
||||
|
||||
uint32_t index = wrenStringFind(string, search, start);
|
||||
RETURN_NUM(index == UINT32_MAX ? -1 : (int)index);
|
||||
}
|
||||
|
||||
@@ -974,7 +975,7 @@ DEF_PRIMITIVE(string_startsWith)
|
||||
ObjString* string = AS_STRING(args[0]);
|
||||
ObjString* search = AS_STRING(args[1]);
|
||||
|
||||
// Corner case, if the search string is longer than return false right away.
|
||||
// Edge case: If the search string is longer then return false right away.
|
||||
if (search->length > string->length) RETURN_FALSE;
|
||||
|
||||
RETURN_BOOL(memcmp(string->value, search->value, search->length) == 0);
|
||||
@@ -1263,8 +1264,8 @@ void wrenInitializeCore(WrenVM* vm)
|
||||
PRIMITIVE(vm->stringClass, "codePointAt_(_)", string_codePointAt);
|
||||
PRIMITIVE(vm->stringClass, "contains(_)", string_contains);
|
||||
PRIMITIVE(vm->stringClass, "endsWith(_)", string_endsWith);
|
||||
PRIMITIVE(vm->stringClass, "indexOf(_)", string_indexOf);
|
||||
PRIMITIVE(vm->stringClass, "indexOf(_,_)", string_indexOf_with_startIndex);
|
||||
PRIMITIVE(vm->stringClass, "indexOf(_)", string_indexOf1);
|
||||
PRIMITIVE(vm->stringClass, "indexOf(_,_)", string_indexOf2);
|
||||
PRIMITIVE(vm->stringClass, "iterate(_)", string_iterate);
|
||||
PRIMITIVE(vm->stringClass, "iterateByte_(_)", string_iterateByte);
|
||||
PRIMITIVE(vm->stringClass, "iteratorValue(_)", string_iteratorValue);
|
||||
|
||||
+11
-11
@@ -854,16 +854,16 @@ Value wrenStringCodePointAt(WrenVM* vm, ObjString* string, uint32_t index)
|
||||
}
|
||||
|
||||
// Uses the Boyer-Moore-Horspool string matching algorithm.
|
||||
uint32_t wrenStringFind(ObjString* haystack, ObjString* needle, uint32_t startIndex)
|
||||
uint32_t wrenStringFind(ObjString* haystack, ObjString* needle, uint32_t start)
|
||||
{
|
||||
// Corner case, an empty needle is always found.
|
||||
if (needle->length == 0) return 0;
|
||||
// Edge case: An empty needle is always found.
|
||||
if (needle->length == 0) return start;
|
||||
|
||||
// If the needle is longer than the haystack it won't be found.
|
||||
if (needle->length > (haystack->length - startIndex)) return UINT32_MAX;
|
||||
// If the needle goes past the haystack it won't be found.
|
||||
if (start + needle->length > haystack->length) return UINT32_MAX;
|
||||
|
||||
// If the startIndex is too far it also won't be found.
|
||||
if (startIndex >= haystack->length) return UINT32_MAX;
|
||||
if (start >= haystack->length) return UINT32_MAX;
|
||||
|
||||
// Pre-calculate the shift table. For each character (8-bit value), we
|
||||
// determine how far the search window can be advanced if that character is
|
||||
@@ -893,18 +893,18 @@ uint32_t wrenStringFind(ObjString* haystack, ObjString* needle, uint32_t startIn
|
||||
// Slide the needle across the haystack, looking for the first match or
|
||||
// stopping if the needle goes off the end.
|
||||
char lastChar = needle->value[needleEnd];
|
||||
uint32_t range = (haystack->length - startIndex) - needle->length;
|
||||
uint32_t range = haystack->length - needle->length;
|
||||
|
||||
for (uint32_t index = 0; index <= range; )
|
||||
for (uint32_t index = start; index <= range; )
|
||||
{
|
||||
// Compare the last character in the haystack's window to the last character
|
||||
// in the needle. If it matches, see if the whole needle matches.
|
||||
char c = haystack->value[startIndex + (index + needleEnd)];
|
||||
char c = haystack->value[index + needleEnd];
|
||||
if (lastChar == c &&
|
||||
memcmp(haystack->value + startIndex + index, needle->value, needleEnd) == 0)
|
||||
memcmp(haystack->value + index, needle->value, needleEnd) == 0)
|
||||
{
|
||||
// Found a match.
|
||||
return index + startIndex;
|
||||
return index;
|
||||
}
|
||||
|
||||
// Otherwise, slide the needle forward.
|
||||
|
||||
Reference in New Issue
Block a user