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) /* [out] */
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) /* [in] */
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) /* [in] */
48 {
49 sptr<IChar> object = new Char(value);
50 return object;
51 }
52
Unbox(IChar * object)53 zchar Char::Unbox(IChar *object) /* [in] */
54 {
55 zchar value;
56 object->GetValue(value);
57 return value;
58 }
59
Parse(const std::string & str)60 sptr<IChar> Char::Parse(const std::string &str) /* [in] */
61 {
62 return Box(GetChar(str, 0));
63 }
64
GetByteSize(zchar c)65 int Char::GetByteSize(zchar c) /* [in] */
66 {
67 if ((c > MAX_CODE_POINT) || (c >= MIN_HIGH_SURROGATE && c <= MAX_LOW_SURROGATE)) {
68 return 0;
69 }
70
71 int bsize = BYTE_COUNT_4;
72 if (c < 0x00000080) {
73 bsize = BYTE_COUNT_1;
74 } else if (c < 0x00000800) {
75 bsize = BYTE_COUNT_2;
76 } else if (c < 0x00010000) {
77 bsize = BYTE_COUNT_3;
78 }
79 return bsize;
80 }
81
WriteUTF8Bytes(char * dst,zchar c,int size)82 void Char::WriteUTF8Bytes(char *dst, /* [in] */
83 zchar c, /* [in] */
84 int size) /* [in] */
85 {
86 uint32_t uc = static_cast<uint32_t>(c);
87 dst += size;
88 switch (size) {
89 /* note: everything falls through. */
90 case BYTE_COUNT_4: {
91 *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK);
92 uc >>= BYTE_SHIFT;
93 }
94 [[clang::fallthrough]];
95 case BYTE_COUNT_3: {
96 *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK);
97 uc >>= BYTE_SHIFT;
98 }
99 [[clang::fallthrough]];
100 case BYTE_COUNT_2: {
101 *(--dst) = ((uc | BYTE_MARK) & BYTE_MASK);
102 uc >>= BYTE_SHIFT;
103 }
104 [[clang::fallthrough]];
105 case BYTE_COUNT_1: {
106 *(--dst) = (uc | FIRST_BYTE_MARK[size]);
107 }
108 [[clang::fallthrough]];
109 default:
110 break;
111 }
112 }
113
GetChar(const std::string & str,int index)114 zchar Char::GetChar(const std::string &str, /* [in] */
115 int index) /* [in] */
116 {
117 if (str.empty() || index < 0) {
118 return INVALID_CHAR;
119 }
120
121 int bsize;
122 const char *p = str.c_str();
123 const char *end = p + str.length() + 1;
124 while (*p && p < end) {
125 zchar unicode = GetCharInternal((unsigned char *)p, bsize);
126 if (bsize == 0 || p + bsize >= end) {
127 break;
128 }
129
130 if (index == 0) {
131 return unicode;
132 }
133 p += bsize;
134 index -= 1;
135 }
136
137 return INVALID_CHAR;
138 }
139
GetCharInternal(const unsigned char * cur,int & size)140 zchar Char::GetCharInternal(const unsigned char *cur, /* [in] */
141 int &size) /* [in] */
142 {
143 if (isascii(*cur) != 0) {
144 size = 1;
145 return *cur;
146 }
147
148 const unsigned char firstChar = *cur++;
149 zchar result = firstChar;
150 zchar mask, ignoreMask;
151 unsigned int num2Read;
152 for (num2Read = 1, mask = 0x40, ignoreMask = 0xFFFFFF80; (firstChar & mask);
153 num2Read++, ignoreMask |= mask, mask >>= 1) {
154 result = (result << BYTE_SHIFT) + (*cur++ & 0x3F);
155 }
156 ignoreMask |= mask;
157 result &= ~(ignoreMask << (BYTE_SHIFT * (num2Read - 1)));
158 size = static_cast<int>(num2Read);
159 return result;
160 }
161 } // namespace AAFwk
162 } // namespace OHOS