1/*
2 * Copyright (c) 2023 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 DISPLAY_COMMAND_DATA_UNPACKER_H
17#define DISPLAY_COMMAND_DATA_UNPACKER_H
18
19#include <memory>
20#include "common/include/display_interface_utils.h"
21#include "hilog/log.h"
22
23namespace OHOS {
24namespace HDI {
25namespace Display {
26class CommandDataUnpacker {
27public:
28    CommandDataUnpacker() : packSize_(0), readPos_(0), curSecOffset_(0), curSecLen_(0), data_(nullptr) {}
29
30    void Init(char* unpackData, size_t size)
31    {
32        packSize_ = size;
33        data_ = unpackData;
34        return;
35    }
36
37    bool ReadUint64(uint64_t& value)
38    {
39        return Read<uint64_t>(value);
40    }
41
42    bool ReadUint32(uint32_t& value)
43    {
44        return Read<uint32_t>(value);
45    }
46
47    bool ReadUint8(uint8_t& value)
48    {
49        uint32_t intVal = 0;
50        bool ret = Read<uint32_t>(intVal);
51        if (ret == true) {
52            value = static_cast<uint8_t>(intVal & 0xFF);
53        }
54
55        return ret;
56    }
57
58    bool ReadInt32(int32_t& value)
59    {
60        return Read<int32_t>(value);
61    }
62
63    bool ReadBool(bool& value)
64    {
65        int32_t intVal = 0;
66        bool ret = Read<int32_t>(intVal);
67        if (ret == true) {
68            value = (intVal == 0 ? false : true);
69        }
70
71        return ret;
72    }
73
74    char *GetDataPtr()
75    {
76        return data_;
77    }
78
79    bool PackBegin(int32_t& beginCmd)
80    {
81        readPos_ = 0;
82        curSecLen_ = sizeof(int32_t);
83        curSecOffset_ = readPos_;
84
85        DISPLAY_CHK_RETURN(ReadInt32(beginCmd) == false, false,
86            HDF_LOGE("%{public}s, read beginCmd error", __func__));
87        return true;
88    }
89
90    bool BeginSection(int32_t& cmdId)
91    {
92        uint32_t magic;
93        curSecOffset_ = readPos_;
94
95        DISPLAY_CHK_RETURN(ReadUint32(magic) == false, false,
96            HDF_LOGE("%{public}s, read magic error", __func__));
97        DISPLAY_CHK_RETURN(magic != SECTION_END_MAGIC, false,
98            HDF_LOGE("%{public}s, err: magic number is corrupted", __func__));
99        DISPLAY_CHK_RETURN(ReadInt32(cmdId) == false, false,
100            HDF_LOGE("%{public}s, read cmdId error", __func__));
101        DISPLAY_CHK_RETURN(ReadUint32(curSecLen_) == false, false,
102            HDF_LOGE("%{public}s, read curSecLen_ error", __func__));
103        return true;
104    }
105
106    bool NextSection()
107    {
108        readPos_ = curSecOffset_ + curSecLen_;
109        if (readPos_ >= (packSize_ - COMMAND_ID_SIZE)) {
110            return false;
111        }
112        return true;
113    }
114
115    bool PackEnd(int32_t& endCmd)
116    {
117        DISPLAY_CHK_RETURN(ReadInt32(endCmd) == false, false,
118            HDF_LOGE("%{public}s, endCmd error", __func__));
119        DISPLAY_CHK_RETURN(readPos_ != packSize_, false,
120            HDF_LOGE("%{public}s, error: eadPos_ != packSize_", __func__));
121        return true;
122    }
123
124    void Dump()
125    {
126        HDF_LOGI("---------------------------------------------\n");
127        HDF_LOGI("SECTION_END_MAGIC =0x%{public}x\n", SECTION_END_MAGIC);
128        HDF_LOGI("COMMAND_ID_SIZE   =%{public}d\n", COMMAND_ID_SIZE);
129        HDF_LOGI("packSize_         =%{public}zu\n", packSize_);
130        HDF_LOGI("readPos_          =%{public}zu\n", readPos_);
131        HDF_LOGI("curSecOffset_     =%{public}zu\n", curSecOffset_);
132        HDF_LOGI("curSecLen_        =%{public}d\n", curSecLen_);
133        uint32_t i = 0;
134        for (; sizeof(int32_t) * i < packSize_;) {
135            HDF_LOGI("%{public}08x ", *reinterpret_cast<uint32_t *>(data_ + sizeof(int32_t) * i));
136            i++;
137            if (i % DUMP_LINE_LEN == 0) {
138                HDF_LOGI("\n");
139            } else if (i % SECTION_LEN_ALIGN == 0) {
140                HDF_LOGI(" ");
141            } else {
142            }
143        }
144        HDF_LOGI("\n");
145    }
146
147private:
148    template <typename T>
149    bool Read(T& value)
150    {
151        size_t dataSize = sizeof(T);
152
153        if (readPos_ + dataSize > packSize_) {
154            HDF_LOGE("Read overflow, readPos=%{public}zu + %{public}zu}, packSize=%{public}zu.",
155                readPos_, dataSize, packSize_);
156            return false;
157        }
158
159        value = *reinterpret_cast<T *>(data_ + readPos_);
160        readPos_ += dataSize;
161
162        return true;
163    }
164
165private:
166    static constexpr uint32_t SECTION_END_MAGIC = 0xB5B5B5B5;
167    static constexpr uint32_t COMMAND_ID_SIZE = sizeof(int32_t);
168    static constexpr int32_t SECTION_LEN_ALIGN = 4;
169    static constexpr uint32_t DUMP_HALF_LINE_SPACE = 4;
170    static constexpr uint32_t DUMP_LINE_LEN = 8;
171
172private:
173    size_t packSize_;
174    size_t readPos_;
175    size_t curSecOffset_;
176    uint32_t curSecLen_;
177    char *data_;
178};
179} // namespace Display
180} // namespace HDI
181} // namespace OHOS
182#endif // DISPLAY_COMMAND_DATA_UNPACKER_H
183