// Copyright 2019 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/objects/string-comparator.h" #include "src/objects/string-inl.h" namespace v8 { namespace internal { void StringComparator::State::Init(String string) { ConsString cons_string = String::VisitFlat(this, string); iter_.Reset(cons_string); if (!cons_string.is_null()) { int offset; string = iter_.Next(&offset); String::VisitFlat(this, string, offset); } } void StringComparator::State::Advance(int consumed) { DCHECK(consumed <= length_); // Still in buffer. if (length_ != consumed) { if (is_one_byte_) { buffer8_ += consumed; } else { buffer16_ += consumed; } length_ -= consumed; return; } // Advance state. int offset; String next = iter_.Next(&offset); DCHECK_EQ(0, offset); DCHECK(!next.is_null()); String::VisitFlat(this, next); } bool StringComparator::Equals(String string_1, String string_2) { int length = string_1.length(); state_1_.Init(string_1); state_2_.Init(string_2); while (true) { int to_check = Min(state_1_.length_, state_2_.length_); DCHECK(to_check > 0 && to_check <= length); bool is_equal; if (state_1_.is_one_byte_) { if (state_2_.is_one_byte_) { is_equal = Equals(&state_1_, &state_2_, to_check); } else { is_equal = Equals(&state_1_, &state_2_, to_check); } } else { if (state_2_.is_one_byte_) { is_equal = Equals(&state_1_, &state_2_, to_check); } else { is_equal = Equals(&state_1_, &state_2_, to_check); } } // Looping done. if (!is_equal) return false; length -= to_check; // Exit condition. Strings are equal. if (length == 0) return true; state_1_.Advance(to_check); state_2_.Advance(to_check); } } } // namespace internal } // namespace v8