Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 20701a73edf89ec5cc5d13e3352ba397bab55fc5..86fd3a4af1c606e6a80985c660cb5e02d474526a 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -11636,6 +11636,118 @@ int String::IndexOf(Isolate* isolate, Handle<String> sub, Handle<String> pat, |
| return SearchString(isolate, seq_sub.ToUC16Vector(), pat_vector, start_index); |
| } |
| +namespace { // for String.Prototype.lastIndexOf |
| + |
| +template <typename schar, typename pchar> |
| +int StringMatchBackwards(Vector<const schar> subject, |
| + Vector<const pchar> pattern, int idx) { |
| + int pattern_length = pattern.length(); |
| + DCHECK(pattern_length >= 1); |
| + DCHECK(idx + pattern_length <= subject.length()); |
| + |
| + if (sizeof(schar) == 1 && sizeof(pchar) > 1) { |
| + for (int i = 0; i < pattern_length; i++) { |
| + uc16 c = pattern[i]; |
| + if (c > String::kMaxOneByteCharCode) { |
| + return -1; |
| + } |
| + } |
| + } |
| + |
| + pchar pattern_first_char = pattern[0]; |
| + for (int i = idx; i >= 0; i--) { |
| + if (subject[i] != pattern_first_char) continue; |
| + int j = 1; |
| + while (j < pattern_length) { |
| + if (pattern[j] != subject[i + j]) { |
| + break; |
| + } |
| + j++; |
| + } |
| + if (j == pattern_length) { |
| + return i; |
| + } |
| + } |
| + return -1; |
| +} |
| + |
| +} // namespace |
| + |
| +Object* String::LastIndexOf(Isolate* isolate, Handle<Object> receiver, |
| + Handle<Object> pattern, Handle<Object> position) { |
| + if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) { |
| + THROW_NEW_ERROR_RETURN_FAILURE( |
| + isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, |
| + isolate->factory()->NewStringFromAsciiChecked( |
| + "String.prototype.lastIndexOf"))); |
| + } |
| + Handle<String> sub; |
|
Franzi
2016/09/19 08:04:21
Can we use a better name than sub?
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sub, |
| + Object::ToString(isolate, receiver)); |
| + |
| + Handle<String> pat; |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, pat, |
| + Object::ToString(isolate, pattern)); |
| + |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position, |
| + Object::ToNumber(position)); |
| + |
| + uint32_t start_index; |
| + |
| + if (position->IsNaN()) { |
| + start_index = sub->length(); |
| + } else { |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position, |
| + Object::ToInteger(isolate, position)); |
| + |
| + double position_number = std::max(position->Number(), 0.0); |
| + position_number = |
| + std::min(position_number, static_cast<double>(sub->length())); |
| + start_index = static_cast<uint32_t>(position_number); |
| + } |
| + |
| + uint32_t pat_length = pat->length(); |
| + uint32_t sub_length = sub->length(); |
| + |
| + if (start_index + pat_length > sub_length) { |
| + start_index = sub_length - pat_length; |
| + } |
| + |
| + if (pat_length == 0) { |
| + return Smi::FromInt(start_index); |
| + } |
| + |
| + sub = String::Flatten(sub); |
| + pat = String::Flatten(pat); |
| + |
| + int last_index = -1; |
| + DisallowHeapAllocation no_gc; // ensure vectors stay valid |
| + |
| + String::FlatContent sub_content = sub->GetFlatContent(); |
| + String::FlatContent pat_content = pat->GetFlatContent(); |
| + |
| + if (pat_content.IsOneByte()) { |
| + Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector(); |
| + if (sub_content.IsOneByte()) { |
| + last_index = StringMatchBackwards(sub_content.ToOneByteVector(), |
| + pat_vector, start_index); |
| + } else { |
| + last_index = StringMatchBackwards(sub_content.ToUC16Vector(), pat_vector, |
| + start_index); |
| + } |
| + } else { |
| + Vector<const uc16> pat_vector = pat_content.ToUC16Vector(); |
| + if (sub_content.IsOneByte()) { |
| + last_index = StringMatchBackwards(sub_content.ToOneByteVector(), |
| + pat_vector, start_index); |
| + } else { |
| + last_index = StringMatchBackwards(sub_content.ToUC16Vector(), pat_vector, |
| + start_index); |
| + } |
| + } |
| + return Smi::FromInt(last_index); |
| +} |
| + |
| bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) { |
| int slen = length(); |
| // Can't check exact length equality, but we can check bounds. |