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 #include <array>
16 #include <cctype>
17 #include <climits>
18 #include <cmath>
19 #include <cstring>
20 #include <iomanip>
21 #include <numeric>
22 #include <sstream>
23 #include <utility>
24 
25 #include "image_log.h"
26 #include "data_buf.h"
27 
28 #undef LOG_DOMAIN
29 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
30 
31 #undef LOG_TAG
32 #define LOG_TAG "DataBuffer"
33 
34 namespace OHOS {
35 namespace Media {
36 const uint32_t BYTE_1_MASK = 0x000000ffU;
37 const uint32_t BYTE_2_MASK = 0x0000ff00U;
38 const uint32_t BYTE_3_MASK = 0x00ff0000U;
39 const uint32_t BYTE_4_MASK = 0xff000000U;
40 
41 const uint32_t BYTE_1_SHIFT = 0;
42 const uint32_t BYTE_2_SHIFT = 8;
43 const uint32_t BYTE_3_SHIFT = 16;
44 const uint32_t BYTE_4_SHIFT = 24;
45 
46 const uint32_t BYTE_1_POSITION = 0;
47 const uint32_t BYTE_2_POSITION = 1;
48 const uint32_t BYTE_3_POSITION = 2;
49 const uint32_t BYTE_4_POSITION = 3;
50 
51 const size_t UINT32_SIZE = 4;
52 
53 const uint16_t LOWER_BYTE_MASK = 0x00ffU;
54 const uint16_t UPPER_BYTE_MASK = 0xff00U;
55 
DataBuf(size_t size)56 DataBuf::DataBuf(size_t size) : pData_(size) {}
57 
DataBuf(const byte * pData,size_t size)58 DataBuf::DataBuf(const byte *pData, size_t size) : pData_(size)
59 {
60     std::copy_n(pData, size, pData_.begin());
61 }
62 
Resize(size_t size)63 void DataBuf::Resize(size_t size)
64 {
65     pData_.resize(size);
66 }
67 
Reset()68 void DataBuf::Reset()
69 {
70     pData_.clear();
71 }
72 
ReadUInt8(size_t offset) const73 uint8_t DataBuf::ReadUInt8(size_t offset) const
74 {
75     if (offset >= pData_.size()) {
76         IMAGE_LOGE("Attempted to read beyond the buffer size while reading an 8-bit unsigned integer. "
77             "Offset: %{public}zu, Buffer size: %{public}zu",
78             offset, pData_.size());
79         return 0;
80     }
81     return pData_[offset];
82 }
83 
WriteUInt8(size_t offset,uint8_t value)84 void DataBuf::WriteUInt8(size_t offset, uint8_t value)
85 {
86     if (offset >= pData_.size()) {
87         IMAGE_LOGE("Attempted to write beyond the buffer size while writing an 8-bit unsigned integer. "
88             "Offset: %{public}zu, Buffer size: %{public}zu",
89             offset, pData_.size());
90         return;
91     }
92     pData_[offset] = value;
93 }
94 
WriteUInt32(size_t offset,uint32_t x,ByteOrder byteOrder)95 void DataBuf::WriteUInt32(size_t offset, uint32_t x, ByteOrder byteOrder)
96 {
97     if (pData_.size() < UINT32_SIZE || offset > (pData_.size() - UINT32_SIZE)) {
98         IMAGE_LOGE("Attempted to write beyond the buffer size while writing a 32-bit unsigned integer. "
99             "Offset: %{public}zu, Buffer size: %{public}zu",
100             offset, pData_.size());
101         return;
102     }
103     UL2Data(&pData_[offset], x, byteOrder);
104 }
105 
ReadUInt32(size_t offset,ByteOrder byteOrder)106 uint32_t DataBuf::ReadUInt32(size_t offset, ByteOrder byteOrder)
107 {
108     if (pData_.size() < UINT32_SIZE || offset > (pData_.size() - UINT32_SIZE)) {
109         IMAGE_LOGE("Attempted to read beyond the buffer size while reading a 32-bit unsigned integer. "
110             "Offset: %{public}zu, Buffer size: %{public}zu",
111             offset, pData_.size());
112         return 0;
113     }
114     return GetULong(&pData_[offset], byteOrder);
115 }
116 
CmpBytes(size_t offset,const void * buf,size_t bufsize) const117 int DataBuf::CmpBytes(size_t offset, const void *buf, size_t bufsize) const
118 {
119     if (pData_.size() < bufsize || offset > pData_.size() - bufsize) {
120         IMAGE_LOGE("Attempted to compare bytes beyond the buffer size. "
121             "Offset: %{public}zu, Buffer size: %{public}zu, Compare size: %{public}zu",
122             offset, pData_.size(), bufsize);
123         return -1;
124     }
125     return memcmp(&pData_[offset], buf, bufsize);
126 }
127 
Data(size_t offset)128 byte *DataBuf::Data(size_t offset)
129 {
130     return const_cast<byte *>(CData(offset));
131 }
132 
CData(size_t offset) const133 const byte *DataBuf::CData(size_t offset) const
134 {
135     if (pData_.empty() || offset == pData_.size()) {
136         return nullptr;
137     }
138     if (offset > pData_.size()) {
139         IMAGE_LOGE("Attempted to access beyond the buffer size. "
140             "Offset: %{public}zu, Buffer size: %{public}zu",
141             offset, pData_.size());
142         return nullptr;
143     }
144     return &pData_[offset];
145 }
146 
GetUShort(const byte * buf,ByteOrder byteOrder)147 uint16_t GetUShort(const byte *buf, ByteOrder byteOrder)
148 {
149     if (byteOrder == littleEndian) {
150         return static_cast<byte>(buf[1]) << DATA_BUF_BYTE_SIZE | static_cast<byte>(buf[0]);
151     }
152     return static_cast<byte>(buf[0]) << DATA_BUF_BYTE_SIZE | static_cast<byte>(buf[1]);
153 }
154 
US2Data(byte * buf,uint16_t value,ByteOrder byteOrder)155 void US2Data(byte *buf, uint16_t value, ByteOrder byteOrder)
156 {
157     if (byteOrder == littleEndian) {
158         buf[0] = static_cast<byte>(value & LOWER_BYTE_MASK);
159         buf[1] = static_cast<byte>((value & UPPER_BYTE_MASK) >> DATA_BUF_BYTE_SIZE);
160     } else {
161         buf[0] = static_cast<byte>((value & UPPER_BYTE_MASK) >> DATA_BUF_BYTE_SIZE);
162         buf[1] = static_cast<byte>(value & LOWER_BYTE_MASK);
163     }
164 }
165 
UL2Data(byte * buf,uint32_t l,ByteOrder byteOrder)166 size_t UL2Data(byte *buf, uint32_t l, ByteOrder byteOrder)
167 {
168     if (buf == nullptr) {
169         return 0;
170     }
171     if (byteOrder == littleEndian) {
172         buf[BYTE_1_POSITION] = static_cast<byte>(l & BYTE_1_MASK);
173         buf[BYTE_2_POSITION] = static_cast<byte>((l & BYTE_2_MASK) >> BYTE_2_SHIFT);
174         buf[BYTE_3_POSITION] = static_cast<byte>((l & BYTE_3_MASK) >> BYTE_3_SHIFT);
175         buf[BYTE_4_POSITION] = static_cast<byte>((l & BYTE_4_MASK) >> BYTE_4_SHIFT);
176     } else {
177         buf[BYTE_1_POSITION] = static_cast<byte>((l & BYTE_4_MASK) >> BYTE_4_SHIFT);
178         buf[BYTE_2_POSITION] = static_cast<byte>((l & BYTE_3_MASK) >> BYTE_3_SHIFT);
179         buf[BYTE_3_POSITION] = static_cast<byte>((l & BYTE_2_MASK) >> BYTE_2_SHIFT);
180         buf[BYTE_4_POSITION] = static_cast<byte>(l & BYTE_1_MASK);
181     }
182     return UINT32_SIZE;
183 }
184 
GetULong(const byte * buf,ByteOrder byteOrder)185 uint32_t GetULong(const byte *buf, ByteOrder byteOrder)
186 {
187     if (buf == nullptr) {
188         return 0;
189     }
190     if (byteOrder == littleEndian) {
191         return (buf[BYTE_4_POSITION] << BYTE_4_SHIFT) | (buf[BYTE_3_POSITION] << BYTE_3_SHIFT) |
192             (buf[BYTE_2_POSITION] << BYTE_2_SHIFT) | (buf[BYTE_1_POSITION] << BYTE_1_SHIFT);
193     }
194     return (buf[BYTE_1_POSITION] << BYTE_4_SHIFT) | (buf[BYTE_2_POSITION] << BYTE_3_SHIFT) |
195         (buf[BYTE_3_POSITION] << BYTE_2_SHIFT) | (buf[BYTE_4_POSITION] << BYTE_1_SHIFT);
196 }
197 } // namespace Media
198 } // namespace OHOS
199