1/*
2 * Copyright (c) 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#ifndef UTIL_JS_TEXTDECODER_H
17#define UTIL_JS_TEXTDECODER_H
18
19#include <memory.h>
20#include <string>
21#include <vector>
22#include "napi/native_api.h"
23#include "napi/native_node_api.h"
24#include "unicode/ucnv.h"
25
26using TransformToolPointer = std::unique_ptr<UConverter, void(*)(UConverter*)>;
27namespace OHOS::Util {
28    struct DecodeArr {
29        DecodeArr(UChar *tarPos, size_t tarStaPos, size_t limLen)
30        {
31            this->target = tarPos;
32            this->tarStartPos = tarStaPos;
33            this->limitLen = limLen;
34        }
35        UChar *target = 0;
36        size_t tarStartPos = 0;
37        size_t limitLen = 0;
38    };
39
40    class TextDecoder {
41    public:
42        enum class ConverterFlags {
43            FLUSH_FLG = 0x1,
44            FATAL_FLG = 0x2,
45            IGNORE_BOM_FLG = 0x4,
46            UNICODE_FLG = 0x8,
47            BOM_SEEN_FLG = 0x10,
48        };
49
50    public:
51        /**
52         * Constructor of textdecoder
53         *
54         * @param buff Encoding format.
55         * @param optionVec There are two attributes of code related option parameters: fatal and ignorebom.
56         */
57        TextDecoder(const std::string &buff, int32_t flags);
58
59        /**
60         * Destructor of textencoder.
61         */
62        virtual ~TextDecoder() {}
63
64        /**
65         * Destructor of textencoder.
66         *
67         * @param env NAPI environment parameters.
68         * @param src An array that matches the format and needs to be decoded.
69         * @param iflag Decoding related option parameters.
70         */
71        napi_value Decode(napi_env env, napi_value src, bool iflag);
72
73        napi_value DecodeToString(napi_env env, napi_value src, bool iflag);
74
75        /**
76         * Gets the size of minimum byte.
77         */
78        size_t GetMinByteSize() const;
79
80        /**
81         * Reset function.
82         */
83        void Reset() const;
84
85        /**
86         * Gets the pointer to the converter.
87         */
88        UConverter *GetConverterPtr() const
89        {
90            return tranTool_.get();
91        }
92
93        /**
94         * Determine whether it is the flag of BOM.
95         */
96        bool IsBomFlag() const
97        {
98            int32_t temp = label_ & static_cast<int32_t>(ConverterFlags::BOM_SEEN_FLG);
99            return temp == static_cast<int32_t>(ConverterFlags::BOM_SEEN_FLG);
100        }
101
102        /**
103         * Determine whether it is Unicode.
104         */
105        bool IsUnicode() const
106        {
107            int32_t temp = label_ & static_cast<int32_t>(ConverterFlags::UNICODE_FLG);
108            return temp == static_cast<int32_t>(ConverterFlags::UNICODE_FLG);
109        }
110
111        /**
112         * Determine whether it is an ignored BOM.
113         */
114        bool IsIgnoreBom() const
115        {
116            int32_t temp = label_ & static_cast<int32_t>(ConverterFlags::IGNORE_BOM_FLG);
117            return temp == static_cast<int32_t>(ConverterFlags::IGNORE_BOM_FLG);
118        }
119
120        /**
121         * Close the pointer of converter.
122         */
123        static void ConverterClose(UConverter *pointer)
124        {
125            ucnv_close(pointer);
126        }
127
128    private:
129        static constexpr uint32_t TEMP_CHAR_LENGTH = 128;
130        static bool IsASCIICharacter(uint16_t data)
131        {
132            return data > 0 && data <= 0x7F;
133        }
134        static bool CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len);
135        std::pair<char *, bool> ConvertToChar(UChar* uchar, size_t length, char* tempCharArray);
136        napi_value GetResultStr(napi_env env, UChar *arrDat, size_t length);
137        void SetBomFlag(const UChar *arr, const UErrorCode codeFlag, const DecodeArr decArr,
138                        size_t& rstLen, bool& bomFlag);
139        void SetIgnoreBOM(const UChar *arr, size_t resultLen, bool& bomFlag);
140        void FreedMemory(UChar *&pData);
141        const char* ReplaceNull(void *data, size_t length) const;
142        napi_value ThrowError(napi_env env, const char* errMessage);
143        int32_t label_ {};
144        std::string encStr_ {};
145        TransformToolPointer tranTool_;
146    };
147}
148#endif // UTIL_JS_TEXTDECODER_H
149