1 /*
2 * Copyright (c) 2023 Huawei Device 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 "char_groups.h"
17
18 #include <algorithm>
19 #include <cassert>
20
21 #include "texgine_exception.h"
22
23 namespace OHOS {
24 namespace Rosen {
25 namespace TextEngine {
operator <<(std::ostream & os,const struct IndexRange & range)26 std::ostream &operator<<(std::ostream &os, const struct IndexRange &range)
27 {
28 os << "[" << range.start << ", " << range.end << ")";
29 return os;
30 }
31
CreateEmpty()32 CharGroups CharGroups::CreateEmpty()
33 {
34 CharGroups cgs;
35 cgs.pcgs_ = std::make_shared<std::vector<struct CharGroup>>();
36 cgs.range_ = {0, 0};
37 return cgs;
38 }
39
CreateWithInvalidRange(IndexRange range)40 CharGroups CharGroups::CreateWithInvalidRange(IndexRange range)
41 {
42 CharGroups cgs = CreateEmpty();
43 cgs.range_ = range;
44 return cgs;
45 }
46
GetNumberOfGlyph() const47 size_t CharGroups::GetNumberOfGlyph() const
48 {
49 if (!IsValid()) {
50 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
51 }
52
53 size_t sum = 0;
54 for (auto i = range_.start; i < range_.end; i++) {
55 sum += pcgs_->at(i).glyphs.size();
56 }
57 return sum;
58 }
59
GetNumberOfCharGroup() const60 size_t CharGroups::GetNumberOfCharGroup() const
61 {
62 if (!IsValid()) {
63 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
64 }
65
66 return range_.end - range_.start;
67 }
68
GetRange() const69 const IndexRange &CharGroups::GetRange() const
70 {
71 return range_;
72 }
73
GetBack() const74 CharGroup &CharGroups::GetBack() const
75 {
76 if (!IsValid()) {
77 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
78 }
79
80 if (GetSize() == 0) {
81 throw TEXGINE_EXCEPTION(OUT_OF_RANGE);
82 }
83
84 return *(pcgs_->begin() + range_.end - 1);
85 }
86
GetSize() const87 size_t CharGroups::GetSize() const
88 {
89 if (!IsValid()) {
90 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
91 }
92
93 return pcgs_->size();
94 }
95
IsValid() const96 bool CharGroups::IsValid() const
97 {
98 if (pcgs_ == nullptr) {
99 return false;
100 }
101
102 if (range_.start > range_.end || range_.start < 0 || range_.end < 0 ||
103 range_.end > static_cast<int>(pcgs_->size()) || range_.start > static_cast<int>(pcgs_->size())) {
104 throw TEXGINE_EXCEPTION(ERROR_STATUS);
105 }
106
107 return true;
108 }
109
IsSameCharGroups(const CharGroups & right) const110 bool CharGroups::IsSameCharGroups(const CharGroups &right) const
111 {
112 return pcgs_ == right.pcgs_;
113 }
114
IsIntersect(const CharGroups & right) const115 bool CharGroups::IsIntersect(const CharGroups &right) const
116 {
117 if (!IsValid()) {
118 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
119 }
120
121 try {
122 if (!right.IsValid()) {
123 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
124 }
125 } catch(const struct TexgineException &err) {
126 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
127 }
128
129 if (pcgs_ != right.pcgs_) {
130 return false;
131 }
132
133 return range_.start < right.range_.end && right.range_.start < range_.end;
134 }
135
GetSplit(const int & index) const136 CharGroupsPair CharGroups::GetSplit(const int &index) const
137 {
138 if (index < 0) {
139 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
140 }
141
142 return GetSplitAll(index + range_.start);
143 }
144
GetSplitAll(const int & index) const145 CharGroupsPair CharGroups::GetSplitAll(const int &index) const
146 {
147 if (!IsValid()) {
148 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
149 }
150
151 if (index <= range_.start || index >= range_.end) {
152 throw TEXGINE_EXCEPTION(OUT_OF_RANGE);
153 }
154 CharGroupsPair retval;
155 retval[0] = *this;
156 retval[0].range_.end = index;
157 retval[1] = *this;
158 retval[1].range_.start = index;
159 return retval;
160 }
161
GetSub(const int & start,const int & end) const162 CharGroups CharGroups::GetSub(const int &start, const int &end) const
163 {
164 if (!(0 <= start && start <= end)) {
165 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
166 }
167
168 return GetSubAll(start + range_.start, end + range_.start);
169 }
170
GetSubAll(const int & start,const int & end) const171 CharGroups CharGroups::GetSubAll(const int &start, const int &end) const
172 {
173 if (!IsValid()) {
174 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
175 }
176
177 if (!(0 <= start && start <= end && end <= static_cast<int>(GetSize()))) {
178 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
179 }
180
181 CharGroups cgs = *this;
182 cgs.range_ = {start, end};
183 return cgs;
184 }
185
GetSubFromU16RangeAll(const int & u16start,const int & u16end) const186 CharGroups CharGroups::GetSubFromU16RangeAll(const int &u16start, const int &u16end) const
187 {
188 if (!IsValid()) {
189 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
190 }
191
192 if (!(0 <= u16start && u16start <= u16end)) {
193 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
194 }
195
196 size_t sum = 0;
197 int startIndex = 0;
198 int endIndex = 1e9;
199 for (int i = -1; i <= static_cast<int>(pcgs_->size()); i++) {
200 if (static_cast<int>(sum) <= u16start) {
201 startIndex = std::max(startIndex, i);
202 }
203
204 if (0 <= i && i < static_cast<int>(pcgs_->size())) {
205 sum += pcgs_->at(i).chars.size();
206 }
207
208 if (static_cast<int>(sum) >= u16end) {
209 endIndex = std::min(endIndex, i);
210 }
211 }
212
213 return GetSubAll(startIndex, endIndex + 1);
214 }
215
GetIntersect(const CharGroups & right) const216 CharGroups CharGroups::GetIntersect(const CharGroups &right) const
217 {
218 if (!IsValid()) {
219 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
220 }
221
222 try {
223 if (!right.IsValid()) {
224 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
225 }
226 } catch(const TexgineException &err) {
227 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
228 }
229
230 if (!IsIntersect(right)) {
231 throw CustomException("these two cgs is not intersect");
232 }
233
234 CharGroups retval = *this;
235 retval.range_.start = std::max(range_.start, right.range_.start);
236 retval.range_.end = std::min(range_.end, right.range_.end);
237 return retval;
238 }
239
Get(const int32_t & index) const240 struct CharGroup &CharGroups::Get(const int32_t &index) const
241 {
242 if (index < 0) {
243 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
244 }
245
246 return GetAll(index + range_.start);
247 }
248
GetAll(const int32_t & index) const249 struct CharGroup &CharGroups::GetAll(const int32_t &index) const
250 {
251 if (!IsValid()) {
252 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
253 }
254
255 if (!(0 <= index && index < static_cast<int>(GetSize()))) {
256 throw TEXGINE_EXCEPTION(OUT_OF_RANGE);
257 }
258
259 return pcgs_->at(index);
260 }
261
ToUTF16() const262 std::vector<uint16_t> CharGroups::ToUTF16() const
263 {
264 if (!IsValid()) {
265 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
266 }
267
268 std::vector<uint16_t> u16;
269 for (auto i = range_.start; i < range_.end; i++) {
270 u16.insert(u16.end(), pcgs_->at(i).chars.begin(), pcgs_->at(i).chars.end());
271 }
272
273 return u16;
274 }
275
ToUTF16All() const276 std::vector<uint16_t> CharGroups::ToUTF16All() const
277 {
278 if (!IsValid()) {
279 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
280 }
281
282 std::vector<uint16_t> u16;
283 for (const auto &cg : *pcgs_) {
284 u16.insert(u16.end(), cg.chars.begin(), cg.chars.end());
285 }
286
287 return u16;
288 }
289
begin() const290 std::vector<struct CharGroup>::iterator CharGroups::begin() const
291 {
292 if (!IsValid()) {
293 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
294 }
295
296 return pcgs_->begin() + range_.start;
297 }
298
end() const299 std::vector<struct CharGroup>::iterator CharGroups::end() const
300 {
301 if (!IsValid()) {
302 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
303 }
304
305 return pcgs_->begin() + range_.end;
306 }
307
Clone() const308 CharGroups CharGroups::Clone() const
309 {
310 if (!IsValid()) {
311 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
312 }
313
314 auto ret = CharGroups::CreateEmpty();
315 *ret.pcgs_ = *pcgs_;
316 ret.range_ = range_;
317 return ret;
318 }
319
Merge(const CharGroups & right)320 void CharGroups::Merge(const CharGroups &right)
321 {
322 if (!IsValid()) {
323 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
324 }
325
326 try {
327 if (!right.IsValid()) {
328 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
329 }
330 } catch(const struct TexgineException &err) {
331 throw TEXGINE_EXCEPTION(INVALID_ARGUMENT);
332 }
333
334 if (range_.end != right.range_.start) {
335 throw CustomException("the right start not equal this end");
336 }
337
338 range_.end += right.range_.end - right.range_.start;
339 }
340
PushBack(const struct CharGroup & cg)341 void CharGroups::PushBack(const struct CharGroup &cg)
342 {
343 if (!IsValid()) {
344 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
345 }
346
347 if (!(range_.start == 0 && range_.end == static_cast<int>(pcgs_->size()))) {
348 throw CustomException("incomplete CharGroups cannot revert");
349 }
350
351 pcgs_->push_back(cg);
352 range_.end++;
353 }
354
ReverseAll()355 void CharGroups::ReverseAll()
356 {
357 if (!IsValid()) {
358 throw TEXGINE_EXCEPTION(INVALID_CHAR_GROUPS);
359 }
360
361 if (!(range_.start == 0 && range_.end == static_cast<int>(pcgs_->size()))) {
362 throw CustomException("incomplete CharGroups cannot revert");
363 }
364
365 std::reverse(pcgs_->begin(), pcgs_->end());
366 }
367
CheckCodePoint()368 bool CharGroups::CheckCodePoint()
369 {
370 if (!GetSize()) {
371 return false;
372 }
373 for (auto &charGroup : *pcgs_) {
374 if (!charGroup.CheckCodePoint()) {
375 return false;
376 }
377 }
378 return true;
379 };
380 } // namespace TextEngine
381 } // namespace Rosen
382 } // namespace OHOS
383