* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_STRING_TREE_STRING_INL_H
#define ECMASCRIPT_STRING_TREE_STRING_INL_H
#include "securec.h"
#include "ecmascript/string/base_string.h"
#include "ecmascript/string/tree_string.h"
namespace panda::ecmascript {
template <typename Allocator, typename WriteBarrier,
panda::objects_traits::enable_if_is_allocate<Allocator, common::BaseObject *>,
common::objects_traits::enable_if_is_write_barrier<WriteBarrier>>
TreeString *TreeString::Create(Allocator &&allocator, WriteBarrier &&writeBarrier,
common::ReadOnlyHandle<BaseString> left, common::ReadOnlyHandle<BaseString> right,
uint32_t length, bool compressed)
{
auto string = TreeString::Cast(std::invoke(std::forward<Allocator>(allocator),
TreeString::SIZE, EcmaStringType::TREE_STRING));
string->InitLengthAndFlags(length, compressed);
string->SetMixHashcode(0);
string->SetLeftSubString(std::forward<WriteBarrier>(writeBarrier), left.GetBaseObject());
string->SetRightSubString(std::forward<WriteBarrier>(writeBarrier), right.GetBaseObject());
return string;
}
template <typename ReadBarrier>
bool TreeString::IsFlat(ReadBarrier &&readBarrier) const
{
auto strRight = BaseString::Cast(GetRightSubString<BaseObject *>(std::forward<ReadBarrier>(readBarrier)));
return strRight->GetLength() == 0;
}
template <bool VERIFY, typename ReadBarrier>
uint16_t TreeString::Get(ReadBarrier &&readBarrier, int32_t index) const
{
auto length = static_cast<int32_t>(GetLength());
if constexpr (VERIFY) {
if ((index < 0) || (index >= length)) {
return 0;
}
}
if (IsFlat(std::forward<ReadBarrier>(readBarrier))) {
BaseString *left = BaseString::Cast(GetLeftSubString<BaseObject *>(std::forward<ReadBarrier>(readBarrier)));
return left->At<VERIFY>(std::forward<ReadBarrier>(readBarrier), index);
}
const BaseString *string = this;
while (true) {
if (string->IsTreeString()) {
BaseString *left = BaseString::Cast(
TreeString::ConstCast(string)->GetLeftSubString<BaseObject *>(std::forward<ReadBarrier>(readBarrier)));
if (static_cast<int32_t>(left->GetLength()) > index) {
string = left;
} else {
index -= static_cast<int32_t>(left->GetLength());
string = BaseString::Cast(TreeString::ConstCast(string)->GetRightSubString<BaseObject *>(
std::forward<ReadBarrier>(readBarrier)));
}
} else {
return string->At<VERIFY>(std::forward<ReadBarrier>(readBarrier), index);
}
}
UNREACHABLE_CC();
}
}
#endif