1 /*
2  * Copyright (C) 2024 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 #ifndef OHOS_ARCH_LITE
16 #include <unicode/ucnv.h>
17 #endif // OHOS_ARCH_LITE
18 #include <iostream>
19 #include <string>
20 #include <cstring>
21 #include <cstdlib>
22 #include <securec.h>
23 #include "wifi_code_convert.h"
24 
25 namespace OHOS {
26 namespace Wifi {
IsUtf8(const std::string & stf)27 bool WifiCodeConvertUtil::IsUtf8(const std::string &stf)
28 {
29     return Utf8Check(stf.c_str(), stf.length());
30 }
31 
Utf8Check(const char * str,size_t length)32 bool WifiCodeConvertUtil::Utf8Check(const char *str, size_t length)
33 {
34     size_t i = 0;
35     int32_t nBytes = 0;
36     unsigned char chr = 0;
37     while (i < length) {
38         chr = *(str + i);
39         if (!IsUtf8Char(chr, nBytes)) {
40             return false;
41         }
42         i++;
43     }
44     return true;
45 }
46 
47 const unsigned char MASK_80 = 0x80;
48 const unsigned char MASK_C0 = 0xC0;
49 const int MIN_BYTES = 2;
50 const int MAX_BYTES = 6;
IsUtf8Char(unsigned char chr,int32_t & nBytes)51 bool WifiCodeConvertUtil::IsUtf8Char(unsigned char chr, int32_t &nBytes)
52 {
53     if (nBytes == 0) {
54         if ((chr & MASK_80) == 0) {
55             return true;
56         }
57         while ((chr & MASK_80) == MASK_80) {
58             chr <<= 1;
59             nBytes++;
60         }
61 
62         if (nBytes < MIN_BYTES || nBytes > MAX_BYTES) {
63             return false;
64         }
65         nBytes--;
66     } else {
67         if ((chr & MASK_C0) != MASK_80) {
68             return false;
69         }
70         nBytes--;
71     }
72     return true;
73 }
74 
GbkToUtf8(const std::string & strGbk)75 std::string WifiCodeConvertUtil::GbkToUtf8(const std::string &strGbk)
76 {
77 #ifdef OHOS_ARCH_LITE
78     return strGbk;
79 #else
80     if (strGbk.length() == 0 || IsUtf8(strGbk)) {
81         return strGbk;
82     }
83     std::string result = Convert(strGbk, "gb2312", "utf8");
84     if (result.length() == 0) {
85         return strGbk;
86     }
87     return result;
88 #endif // OHOS_ARCH_LITE
89 }
90 
Utf8ToGbk(const std::string & strUtf8)91 std::string WifiCodeConvertUtil::Utf8ToGbk(const std::string &strUtf8)
92 {
93 #ifdef OHOS_ARCH_LITE
94     return strUtf8;
95 #else
96     if (strUtf8.length() == 0 || !IsUtf8(strUtf8)) {
97         return strUtf8;
98     }
99 
100     std::string result = Convert(strUtf8, "utf8", "gb2312");
101     if (result.length() == 0) {
102         return strUtf8;
103     }
104     return result;
105 #endif // OHOS_ARCH_LITE
106 }
107 
Convert(const std::string & str,const std::string & fromCharset,const std::string & toCharset)108 std::string WifiCodeConvertUtil::Convert(const std::string &str, const std::string &fromCharset,
109     const std::string &toCharset)
110 {
111 #ifdef OHOS_ARCH_LITE
112     return str;
113 #else
114     UErrorCode status = U_ZERO_ERROR;
115     int32_t resultlen  = ucnv_convert(toCharset.c_str(), fromCharset.c_str(), nullptr, 0, str.c_str(),
116         str.length(), &status);
117     std::unique_ptr<char[]> result = std::make_unique<char[]>(resultlen + 1);
118     memset_s(result.get(), resultlen + 1, 0, resultlen + 1);
119     status = U_ZERO_ERROR;
120     ucnv_convert(toCharset.c_str(), fromCharset.c_str(), result.get(), resultlen + 1,
121         str.c_str(), str.length(), &status);
122     if (U_FAILURE(status)) {
123         return str;
124     }
125     return std::string(result.get());
126 #endif // OHOS_ARCH_LITE
127 }
128 } // namespace Wifi
129 } // namespace OHOS
130