/* * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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. */ #include "ecmascript/js_segment_iterator.h" #include "ecmascript/js_iterator.h" #include "ecmascript/js_segments.h" #include "ecmascript/object_factory-inl.h" namespace panda::ecmascript { void JSSegmentIterator::SetIcuBreakIterator(JSThread *thread, const JSHandle &iterator, icu::BreakIterator* icuBreakIterator, const NativePointerCallback &callback) { EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); ASSERT(icuBreakIterator != nullptr); JSTaggedValue data = iterator->GetIcuField(); if (data.IsJSNativePointer()) { JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject()); native->ResetExternalPointer(thread, icuBreakIterator); return; } JSHandle pointer = factory->NewJSNativePointer(icuBreakIterator, callback); iterator->SetIcuField(thread, pointer.GetTaggedValue()); } void JSSegmentIterator::SetUString(JSThread *thread, const JSHandle &iterator, icu::UnicodeString* icuUnicodeString, const NativePointerCallback &callback) { EcmaVM *ecmaVm = thread->GetEcmaVM(); ObjectFactory *factory = ecmaVm->GetFactory(); ASSERT(icuUnicodeString != nullptr); JSTaggedValue data = iterator->GetUnicodeString(); if (data.IsJSNativePointer()) { JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject()); native->ResetExternalPointer(thread, icuUnicodeString); return; } JSHandle pointer = factory->NewJSNativePointer(icuUnicodeString, callback); iterator->SetUnicodeString(thread, pointer.GetTaggedValue()); } JSHandle JSSegmentIterator::CreateSegmentIterator(JSThread *thread, icu::BreakIterator* icuBreakIterator, const JSHandle &string, GranularityOption granularity) { // 1. Let internalSlotsList be « [[IteratingSegmenter]], [[IteratedString]], // [[IteratedStringNextSegmentCodeUnitIndex]] ». // 2. Let iterator be OrdinaryObjectCreate(%SegmentIteratorPrototype%, internalSlotsList). JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle segIterCtor(env->GetSegmentIterator()); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle iterator(factory->NewJSObjectByConstructor(segIterCtor)); icuBreakIterator = icuBreakIterator->clone(); // 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0. icuBreakIterator->first(); icu::UnicodeString* uString = new icu::UnicodeString(); icuBreakIterator->getText().getText(*uString); // 3. Set iterator.[[IteratingSegmenter]] to segmenter. SetIcuBreakIterator(thread, iterator, icuBreakIterator, JSSegmentIterator::FreeIcuBreakIterator); iterator->SetGranularity(granularity); // 4. Set iterator.[[IteratedString]] to string. iterator->SetIteratedString(thread, string); SetUString(thread, iterator, uString, JSSegmentIterator::FreeUString); // 6. Return iterator. return iterator; } JSTaggedValue JSSegmentIterator::Next(JSThread *thread, const JSHandle &iterator) { icu::BreakIterator* icuBreakIterator = iterator->GetIcuBreakIterator(); // 5. Let startIndex be iterator.[[IteratedStringNextSegmentCodeUnitIndex]]. int32_t startIndex = icuBreakIterator->current(); // 6. Let endIndex be ! FindBoundary(segmenter, string, startIndex, after). int32_t endIndex = icuBreakIterator->next(); // 7. If endIndex is not finite, then if (endIndex == icu::BreakIterator::DONE) { // a. Return CreateIterResultObject(undefined, true). JSHandle result(thread, JSTaggedValue::Undefined()); return JSIterator::CreateIterResultObject(thread, result, true).GetTaggedValue(); } // 8. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to endIndex. // 9. Let segmentData be ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex). icu::UnicodeString unicodeString; icuBreakIterator->getText().getText(unicodeString); JSHandle segmentData = JSSegments::CreateSegmentDataObject(thread, iterator->GetGranularity(), icuBreakIterator, JSHandle(thread, iterator->GetIteratedString()), unicodeString, startIndex, endIndex); // 10. Return CreateIterResultObject(segmentData, false). return JSIterator::CreateIterResultObject(thread, JSHandle::Cast(segmentData), false) .GetTaggedValue(); } } // namespace panda::ecmascript