1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 "codec_cov.h"
17
18#include <memory>
19#ifdef _WIN32
20#include <windows.h>
21#endif
22
23namespace SysTuning {
24namespace base {
25int32_t PreNum(unsigned char byte)
26{
27    constexpr uint32_t BITS = 8;
28    unsigned char mask = 0x80;
29    int32_t num = 0;
30    for (uint32_t i = 0; i < BITS; i++) {
31        if ((byte & mask) == mask) {
32            mask = mask >> 1;
33            num++;
34        } else {
35            break;
36        }
37    }
38    return num;
39}
40
41bool IsUTF8(const uint8_t *data, int32_t len)
42{
43    constexpr uint8_t mask = 0x80;
44    constexpr uint8_t firstByte = 0xc0;
45    constexpr int32_t target = 2;
46    int32_t num = 0;
47    int32_t i = 0;
48    while (i < len) {
49        if ((data[i] & mask) == 0x00) {
50            i++;
51            continue;
52        }
53        if ((num = PreNum(data[i])) <= target) {
54            return false;
55        }
56        i++;
57        for (int32_t j = 0; j < num - 1; j++) {
58            if ((data[i] & firstByte) != mask) {
59                return false;
60            }
61            i++;
62        }
63    }
64    return true;
65}
66
67bool IsGBK(const uint8_t *data, int32_t len)
68{
69    constexpr int32_t step = 2;
70    constexpr uint8_t asciiEnd = 0x7f;
71    constexpr uint8_t firstByte = 0x81;
72    constexpr uint8_t firstByteEnd = 0xfe;
73    constexpr uint8_t secondByteOne = 0x40;
74    constexpr uint8_t secondByteTwoEnd = 0xfe;
75    constexpr uint8_t gbkMask = 0xf7;
76    int32_t i = 0;
77    while (i < len) {
78        if (data[i] <= asciiEnd) {
79            i++;
80            continue;
81        } else {
82            if (data[i] >= firstByte && data[i] <= firstByteEnd && data[i + 1] >= secondByteOne &&
83                data[i + 1] <= secondByteTwoEnd && data[i + 1] != gbkMask) {
84                i += step;
85                continue;
86            } else {
87                return false;
88            }
89        }
90    }
91    return true;
92}
93
94CODING GetCoding(const uint8_t *data, int32_t len)
95{
96    CODING coding;
97    if (IsUTF8(data, len)) {
98        coding = UTF8;
99    } else if (IsGBK(data, len)) {
100        coding = GBK;
101    } else {
102        coding = UNKOWN;
103    }
104    return coding;
105}
106
107#ifdef _WIN32
108std::string GbkToUtf8(const char *srcStr)
109{
110    int32_t len = MultiByteToWideChar(CP_ACP, 0, srcStr, -1, NULL, 0);
111    std::unique_ptr<wchar_t[]> wstr = std::make_unique<wchar_t[]>(len + 1);
112    MultiByteToWideChar(CP_ACP, 0, srcStr, -1, wstr.get(), len);
113    len = WideCharToMultiByte(CP_UTF8, 0, wstr.get(), -1, NULL, 0, NULL, NULL);
114    std::unique_ptr<char[]> str = std::make_unique<char[]>(len + 1);
115    WideCharToMultiByte(CP_UTF8, 0, wstr.get(), -1, str.get(), len, NULL, NULL);
116    return std::string(str.get());
117}
118#endif
119} // namespace base
120} // namespace SysTuning
121