• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/js_segment_iterator.h"
17 
18 
19 #include "ecmascript/js_iterator.h"
20 #include "ecmascript/js_segments.h"
21 #include "ecmascript/object_factory-inl.h"
22 
23 namespace panda::ecmascript {
24 
SetIcuBreakIterator(JSThread * thread,const JSHandle<JSSegmentIterator> & iterator,icu::BreakIterator * icuBreakIterator,const NativePointerCallback & callback)25 void JSSegmentIterator::SetIcuBreakIterator(JSThread *thread, const JSHandle<JSSegmentIterator> &iterator,
26                                             icu::BreakIterator* icuBreakIterator, const NativePointerCallback &callback)
27 {
28     EcmaVM *ecmaVm = thread->GetEcmaVM();
29     ObjectFactory *factory = ecmaVm->GetFactory();
30 
31     ASSERT(icuBreakIterator != nullptr);
32     JSTaggedValue data = iterator->GetIcuField(thread);
33     if (data.IsJSNativePointer()) {
34         JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject());
35         native->ResetExternalPointer(thread, icuBreakIterator);
36         return;
37     }
38     JSHandle<JSNativePointer> pointer = factory->NewJSNativePointer(icuBreakIterator, callback);
39     iterator->SetIcuField(thread, pointer.GetTaggedValue());
40 }
41 
SetUString(JSThread * thread,const JSHandle<JSSegmentIterator> & iterator,icu::UnicodeString * icuUnicodeString,const NativePointerCallback & callback)42 void JSSegmentIterator::SetUString(JSThread *thread, const JSHandle<JSSegmentIterator> &iterator,
43                                    icu::UnicodeString* icuUnicodeString, const NativePointerCallback &callback)
44 {
45     EcmaVM *ecmaVm = thread->GetEcmaVM();
46     ObjectFactory *factory = ecmaVm->GetFactory();
47 
48     ASSERT(icuUnicodeString != nullptr);
49     JSTaggedValue data = iterator->GetUnicodeString(thread);
50     if (data.IsJSNativePointer()) {
51         JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject());
52         native->ResetExternalPointer(thread, icuUnicodeString);
53         return;
54     }
55     JSHandle<JSNativePointer> pointer = factory->NewJSNativePointer(icuUnicodeString, callback);
56     iterator->SetUnicodeString(thread, pointer.GetTaggedValue());
57 }
58 
CreateSegmentIterator(JSThread * thread,icu::BreakIterator * icuBreakIterator,const JSHandle<EcmaString> & string,GranularityOption granularity)59 JSHandle<JSSegmentIterator> JSSegmentIterator::CreateSegmentIterator(JSThread *thread,
60     icu::BreakIterator* icuBreakIterator, const JSHandle<EcmaString> &string, GranularityOption granularity)
61 {
62     // 1. Let internalSlotsList be « [[IteratingSegmenter]], [[IteratedString]],
63     //    [[IteratedStringNextSegmentCodeUnitIndex]] ».
64     // 2. Let iterator be OrdinaryObjectCreate(%SegmentIteratorPrototype%, internalSlotsList).
65     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
66     JSHandle<JSFunction> segIterCtor(env->GetSegmentIterator());
67     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
68     JSHandle<JSSegmentIterator> iterator(factory->NewJSObjectByConstructor(segIterCtor));
69     icuBreakIterator = icuBreakIterator->clone();
70     // 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0.
71     icuBreakIterator->first();
72     icu::UnicodeString* uString = new icu::UnicodeString();
73     icuBreakIterator->getText().getText(*uString);
74     // 3. Set iterator.[[IteratingSegmenter]] to segmenter.
75     SetIcuBreakIterator(thread, iterator, icuBreakIterator, JSSegmentIterator::FreeIcuBreakIterator);
76     iterator->SetGranularity(granularity);
77     // 4. Set iterator.[[IteratedString]] to string.
78     iterator->SetIteratedString(thread, string);
79     SetUString(thread, iterator, uString, JSSegmentIterator::FreeUString);
80     // 6. Return iterator.
81     return iterator;
82 }
83 
Next(JSThread * thread,const JSHandle<JSSegmentIterator> & iterator)84 JSTaggedValue JSSegmentIterator::Next(JSThread *thread, const JSHandle<JSSegmentIterator> &iterator)
85 {
86     icu::BreakIterator* icuBreakIterator = iterator->GetIcuBreakIterator(thread);
87     // 5. Let startIndex be iterator.[[IteratedStringNextSegmentCodeUnitIndex]].
88     int32_t startIndex = icuBreakIterator->current();
89     // 6. Let endIndex be ! FindBoundary(segmenter, string, startIndex, after).
90     int32_t endIndex = icuBreakIterator->next();
91     // 7. If endIndex is not finite, then
92     if (endIndex == icu::BreakIterator::DONE) {
93         // a. Return CreateIterResultObject(undefined, true).
94         JSHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
95         return JSIterator::CreateIterResultObject(thread, result, true).GetTaggedValue();
96     }
97 
98     // 8. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to endIndex.
99     // 9. Let segmentData be ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex).
100     icu::UnicodeString unicodeString;
101     icuBreakIterator->getText().getText(unicodeString);
102     JSHandle<JSObject> segmentData = JSSegments::CreateSegmentDataObject(thread, iterator->GetGranularity(),
103         icuBreakIterator, JSHandle<EcmaString>(thread, iterator->GetIteratedString(thread)),
104         unicodeString, startIndex, endIndex);
105 
106     // 10. Return CreateIterResultObject(segmentData, false).
107     return JSIterator::CreateIterResultObject(thread, JSHandle<JSTaggedValue>::Cast(segmentData), false)
108                                               .GetTaggedValue();
109 }
110 }  // namespace panda::ecmascript
111