1 /*
2 * Copyright (c) 2021-2022 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 "zchar_wrapper.h"
17
18 namespace OHOS {
19 namespace AAFwk {
20 IINTERFACE_IMPL_1(Char, Object, IChar);
21
GetValue(zchar & value)22 ErrCode Char::GetValue(zchar &value)
23 {
24 VALIDATE_NOT_NULL(&value);
25
26 value = value_;
27 return ERR_OK;
28 }
29
Equals(IObject & other)30 bool Char::Equals(IObject &other)
31 {
32 Char *otherObj = static_cast<Char *>(IChar::Query(&other));
33 return otherObj != nullptr && otherObj->value_ == value_;
34 }
35
ToString()36 std::string Char::ToString()
37 {
38 constexpr int MAX_BYTE_SIZE = 4;
39
40 int byteSize = GetByteSize(value_);
41 char buf[MAX_BYTE_SIZE + 1];
42 WriteUTF8Bytes(buf, value_, byteSize);
43 buf[byteSize] = '\0';
44 return std::string(buf);
45 }
46
Box(zchar value)47 sptr<IChar> Char::Box(zchar value)
48 {
49 sptr<IChar> object = new Char(value);
50 return object;
51 }
52
Unbox(IChar * object)53 zchar Char::Unbox(IChar *object)
54 {
55 zchar value = u'\0';
56 if (object == nullptr) {
57 return value;
58 }
59 object->GetValue(value);
60 return value;
61 }
62
Parse(const std::string & str)63 sptr<IChar> Char::Parse(const std::string &str)
64 {
65 return Box(GetChar(str, 0));
66 }
67
GetByteSize(zchar c)68 int Char::GetByteSize(zchar c)
69 {
70 if ((c > MAX_CODE_POINT) || (c >= MIN_HIGH_SURROGATE && c <= MAX_LOW_SURROGATE)) {
71 return 0;
72 }
73
74 int bsize = BYTE_COUNT_4;
75 if (c < 0x00000080) {
76 bsize = BYTE_COUNT_1;
77 } else if (c < 0x00000800) {
78 bsize = BYTE_COUNT_2;
79 } else if (c < 0x00010000) {
80 bsize = BYTE_COUNT_3;
81 }
82 return bsize;
83 }
84
WriteUTF8Bytes(char * dst,zchar c,int size)85 void Char::WriteUTF8Bytes(char *dst,
86 zchar c,
87 int size)
88 {
89 uint32_t uc = static_cast<uint32_t>(c);
90 dst += size;
91 switch (size) {
92 /* note: everything falls through. */
93 case BYTE_COUNT_4: {
94 *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK);
95 uc >>= BYTE_SHIFT;
96 }
97 [[clang::fallthrough]];
98 case BYTE_COUNT_3: {
99 *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK);
100 uc >>= BYTE_SHIFT;
101 }
102 [[clang::fallthrough]];
103 case BYTE_COUNT_2: {
104 *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK);
105 uc >>= BYTE_SHIFT;
106 }
107 [[clang::fallthrough]];
108 case BYTE_COUNT_1: {
109 *(--dst) = (uc | FIRST_BYTE_MARK[size]);
110 }
111 [[clang::fallthrough]];
112 default:
113 break;
114 }
115 }
116
GetChar(const std::string & str,int index)117 zchar Char::GetChar(const std::string &str,
118 int index)
119 {
120 if (str.empty() || index < 0) {
121 return INVALID_CHAR;
122 }
123
124 unsigned int bsize;
125 const char *p = str.c_str();
126 const char *end = p + str.length() + 1;
127 unsigned int size = str.length();
128 unsigned int now = 0;
129 while (*p && p < end) {
130 zchar unicode = GetCharInternal((unsigned char *)p, bsize);
131 if (bsize == 0 || now + bsize > size) {
132 break;
133 }
134
135 if (index == 0) {
136 return unicode;
137 }
138 p += bsize;
139 now += bsize;
140 index -= 1;
141 }
142
143 return INVALID_CHAR;
144 }
145
GetCharInternal(const unsigned char * cur,unsigned int & size)146 zchar Char::GetCharInternal(const unsigned char *cur,
147 unsigned int &size)
148 {
149 if (isascii(*cur) != 0) {
150 size = 1;
151 return *cur;
152 }
153
154 const unsigned char firstChar = *cur++;
155 zchar result = firstChar;
156 zchar mask = 0x40;
157 zchar ignoreMask = 0xFFFFFF80;
158 unsigned int num2Read = 1;
159 for (; (firstChar & mask); num2Read++, ignoreMask |= mask, mask >>= 1) {
160 result = (result << BYTE_SHIFT) + (*cur++ & 0x3F);
161 }
162 ignoreMask |= mask;
163 result &= ~(ignoreMask << (BYTE_SHIFT * (num2Read - 1)));
164 size = num2Read;
165 return result;
166 }
167 } // namespace AAFwk
168 } // namespace OHOS
169