blob: 6f517edb20b8b36dca0d04224668cb639980fbd7 [file] [log] [blame]
// 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<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
} else {
is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
}
} else {
if (state_2_.is_one_byte_) {
is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
} else {
is_equal = Equals<uint16_t, uint16_t>(&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