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