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#ifndef ECMASCRIPT_JS_SEGMENTS_H
17#define ECMASCRIPT_JS_SEGMENTS_H
18
19#include "ecmascript/ecma_string.h"
20#include "ecmascript/ecma_vm.h"
21#include "ecmascript/ecma_macros.h"
22#include "ecmascript/global_env.h"
23#include "ecmascript/js_hclass.h"
24#include "ecmascript/js_intl.h"
25#include "ecmascript/js_locale.h"
26#include "ecmascript/js_object.h"
27#include "ecmascript/js_segmenter.h"
28#include "ecmascript/js_tagged_value.h"
29#include "ecmascript/object_factory.h"
30
31#include "unicode/locdspnm.h"
32
33namespace panda::ecmascript {
34class JSSegments : public JSObject {
35public:
36    CAST_CHECK(JSSegments, IsJSSegments);
37
38    static constexpr size_t ICU_FIELD_OFFSET = JSObject::SIZE;
39    ACCESSORS(IcuField, ICU_FIELD_OFFSET, SEGMENTS_STRING_OFFSET)
40    ACCESSORS(SegmentsString, SEGMENTS_STRING_OFFSET, UNICODE_STRING_OFFSET)
41    ACCESSORS(UnicodeString, UNICODE_STRING_OFFSET, BIT_FIELD_OFFSET)
42    ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
43    DEFINE_ALIGN_SIZE(LAST_OFFSET);
44
45    // define BitField
46    static constexpr size_t GRANULARITY_BITS = 3;
47    FIRST_BIT_FIELD(BitField, Granularity, GranularityOption, GRANULARITY_BITS)
48
49    DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ICU_FIELD_OFFSET, BIT_FIELD_OFFSET)
50    DECL_DUMP()
51
52    // 18.5.1 CreateSegmentsObject ( segmenter, string )
53    static JSHandle<JSSegments> CreateSegmentsObject(JSThread *thread,
54                                                     const JSHandle<JSSegmenter> &segmenter,
55                                                     const JSHandle<EcmaString> &string);
56    // Get icu break iterator from icu field
57    icu::BreakIterator *GetIcuBreakIterator() const
58    {
59        ASSERT(GetIcuField().IsJSNativePointer());
60        auto result = JSNativePointer::Cast(GetIcuField().GetTaggedObject())->GetExternalPointer();
61        return reinterpret_cast<icu::BreakIterator *>(result);
62    }
63
64    static void FreeIcuBreakIterator([[maybe_unused]] void *env, void *pointer, [[maybe_unused]] void* hint)
65    {
66        if (pointer == nullptr) {
67            return;
68        }
69        auto icuBreakIterator = reinterpret_cast<icu::BreakIterator *>(pointer);
70        delete icuBreakIterator;
71    }
72
73    static void SetIcuBreakIterator(JSThread *thread, const JSHandle<JSSegments> &segments,
74                                    icu::BreakIterator* icuBreakIterator, const NativePointerCallback &callback);
75
76    static void FreeUString([[maybe_unused]] void *env, void *pointer, [[maybe_unused]] void* hint)
77    {
78        if (pointer == nullptr) {
79            return;
80        }
81        auto unicodeString = reinterpret_cast<icu::UnicodeString *>(pointer);
82        delete unicodeString;
83    }
84
85    static void SetUString(JSThread *thread, const JSHandle<JSSegments> &segments,
86                           icu::UnicodeString* icuUnicodeString, const NativePointerCallback &callback);
87
88    icu::UnicodeString *GetUString() const
89    {
90        ASSERT(GetUnicodeString().IsJSNativePointer());
91        auto result = JSNativePointer::Cast(GetUnicodeString().GetTaggedObject())->GetExternalPointer();
92        return reinterpret_cast<icu::UnicodeString *>(result);
93    }
94
95    static JSTaggedValue Containing(JSThread *thread, const JSHandle<JSSegments> &segments, double index);
96
97    // 18.7.1 CreateSegmentDataObject ( segmenter, string, startIndex, endIndex )
98    static JSHandle<JSObject> CreateSegmentDataObject(JSThread *thread, GranularityOption granularity,
99        icu::BreakIterator* breakIterator, const JSHandle<EcmaString> &inputString,
100        const icu::UnicodeString& unicodeString, int32_t startIndex, int32_t endIndex);
101};
102}  // namespace panda::ecmascript
103#endif  // ECMASCRIPT_JS_SEGMENTS_H