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#include "sms_pdu_buffer.h"
17
18#include "securec.h"
19#include "telephony_log_wrapper.h"
20
21namespace OHOS {
22namespace Telephony {
23static constexpr uint16_t PDU_BUFFER_MAX_SIZE = 0xFF;
24static constexpr uint16_t PDU_BUFFER_MIN_SIZE = 2;
25
26SmsPduBuffer::~SmsPduBuffer()
27{
28    if (data_ != nullptr) {
29        data_.reset();
30    }
31}
32
33bool SmsPduBuffer::IsEmpty()
34{
35    return data_ == nullptr;
36}
37
38uint16_t SmsPduBuffer::GetIndex()
39{
40    return index_;
41}
42
43uint16_t SmsPduBuffer::GetSize()
44{
45    return length_;
46}
47
48bool SmsPduBuffer::SetIndex(uint16_t index)
49{
50    if (bitIndex_ != BIT0) {
51        TELEPHONY_LOGE("buffer in bit mode");
52        return false;
53    }
54    if (index > length_) {
55        TELEPHONY_LOGE("index over buffer");
56        return false;
57    }
58
59    index_ = index;
60    return true;
61}
62
63uint16_t SmsPduBuffer::MoveForward(uint16_t len)
64{
65    if (bitIndex_ != BIT0) {
66        TELEPHONY_LOGE("buffer in bit mode");
67        return index_;
68    }
69    if (index_ + len > length_) {
70        TELEPHONY_LOGE("move over buffer");
71        return index_;
72    }
73
74    uint16_t pos = index_;
75    index_ += len;
76    return pos;
77}
78
79uint16_t SmsPduBuffer::MoveBack(uint16_t len)
80{
81    if (bitIndex_ != BIT0) {
82        TELEPHONY_LOGE("buffer in bit mode");
83        return index_;
84    }
85    if (index_ < len) {
86        TELEPHONY_LOGE("back over buffer");
87        return index_;
88    }
89
90    uint16_t pos = index_;
91    index_ -= len;
92    return pos;
93}
94
95uint16_t SmsPduBuffer::SkipBits()
96{
97    if (bitIndex_ > BIT0) {
98        index_++;
99        bitIndex_ = BIT0;
100    }
101    return index_;
102}
103
104std::unique_ptr<std::vector<uint8_t>> SmsPduBuffer::GetPduBuffer()
105{
106    if (data_ == nullptr || index_ == 0) {
107        TELEPHONY_LOGE("data is null");
108        return nullptr;
109    }
110    if (bitIndex_ != BIT0) {
111        TELEPHONY_LOGE("buffer in bit mode");
112        return nullptr;
113    }
114
115    if (index_ >= length_) {
116        TELEPHONY_LOGE("data error.");
117        return nullptr;
118    }
119
120    std::unique_ptr<std::vector<uint8_t>> data =
121        std::make_unique<std::vector<uint8_t>>(data_.get(), data_.get() + index_);
122    if (data == nullptr) {
123        TELEPHONY_LOGE("make unique error");
124        return nullptr;
125    }
126    return data;
127}
128
129SmsReadBuffer::SmsReadBuffer(const std::string &hex)
130{
131    size_t len = hex.length();
132    if (len < PDU_BUFFER_MIN_SIZE || len > PDU_BUFFER_MAX_SIZE + 1) {
133        TELEPHONY_LOGE("invalid PDU");
134        return;
135    }
136
137    data_ = std::make_unique<uint8_t[]>(len);
138    if (data_ == nullptr) {
139        TELEPHONY_LOGE("make_unique error");
140        return;
141    }
142    if (memset_s(data_.get(), len, 0x00, len) != EOK) {
143        TELEPHONY_LOGE("memset_s error");
144        data_.reset();
145        data_ = nullptr;
146        return;
147    }
148    if (memcpy_s(data_.get(), len, hex.c_str(), len) != EOK) {
149        TELEPHONY_LOGE("memcpy_s error");
150        data_.reset();
151        data_ = nullptr;
152        return;
153    }
154    length_ = len;
155}
156
157bool SmsReadBuffer::ReadByte(uint8_t &v)
158{
159    if (data_ == nullptr) {
160        TELEPHONY_LOGE("data is null");
161        return false;
162    }
163    if (bitIndex_ != BIT0) {
164        return ReadBits(v, BIT8);
165    }
166
167    if (index_ == length_) {
168        TELEPHONY_LOGW("read over buffer");
169        return false;
170    }
171
172    v = data_[index_++];
173    return true;
174}
175
176bool SmsReadBuffer::PickOneByte(uint8_t &v)
177{
178    if (data_ == nullptr || index_ >= length_) {
179        TELEPHONY_LOGE("peek one byte fail.");
180        return false;
181    }
182    v = data_[index_];
183    return true;
184}
185
186bool SmsReadBuffer::PickOneByteFromIndex(uint16_t index, uint8_t &v)
187{
188    if (data_ == nullptr || length_ == 0 || index >= length_) {
189        TELEPHONY_LOGE("peek index byte fail.");
190        return false;
191    }
192    v = data_[index];
193    return true;
194}
195
196bool SmsReadBuffer::ReadWord(uint16_t &v)
197{
198    if (data_ != nullptr && index_ < (length_ - 1) && bitIndex_ == BIT0) {
199        v = data_[index_++];
200        v = (v << BIT8) | data_[index_++];
201        return true;
202    }
203    TELEPHONY_LOGE("read word error");
204    return false;
205}
206
207bool SmsReadBuffer::ReadBits(uint8_t &v, uint8_t l)
208{
209    if (data_ == nullptr) {
210        TELEPHONY_LOGE("data is null");
211        return false;
212    }
213    if (l == BIT0 || l > BIT8) {
214        TELEPHONY_LOGE("read bits : invalid length");
215        return false;
216    }
217
218    if (bitIndex_ + l <= BIT8) {
219        if (index_ == length_) {
220            TELEPHONY_LOGE("read bits over buffer");
221            return false;
222        }
223        v = data_[index_] << bitIndex_;
224        v = v >> (BIT8 - l);
225        bitIndex_ += l;
226        if (bitIndex_ == BIT8) {
227            bitIndex_ = BIT0;
228            index_++;
229        }
230    } else {
231        if (index_ == length_ - 1) {
232            TELEPHONY_LOGE("read bits over buffer");
233            return false;
234        }
235        v = data_[index_++] << bitIndex_;
236        bitIndex_ = l + bitIndex_ - BIT8;
237        v = (v >> (BIT8 - l)) | (data_[index_] >> (BIT8 - bitIndex_));
238    }
239    return true;
240}
241
242SmsWriteBuffer::SmsWriteBuffer()
243{
244    length_ = PDU_BUFFER_MAX_SIZE + 1;
245    data_ = std::make_unique<uint8_t[]>(length_);
246    if (data_ == nullptr) {
247        TELEPHONY_LOGE("make_unique create data error");
248        length_ = 0;
249        return;
250    }
251}
252
253bool SmsWriteBuffer::WriteByte(uint8_t v)
254{
255    if (bitIndex_ != BIT0) {
256        return WriteBits(v, BIT8);
257    }
258    if (data_ != nullptr && index_ < length_) {
259        data_[index_++] = v;
260        return true;
261    }
262    TELEPHONY_LOGE("write byte error");
263    return false;
264}
265
266bool SmsWriteBuffer::WriteWord(uint16_t v)
267{
268    if (data_ != nullptr && index_ < (length_ - 1) && bitIndex_ == BIT0) {
269        data_[index_++] = (0xff00 & v) >> BIT8;
270        data_[index_++] = (0x00ff & v);
271        return true;
272    }
273    TELEPHONY_LOGE("write word error");
274    return false;
275}
276
277bool SmsWriteBuffer::WriteBits(uint8_t v, uint8_t l)
278{
279    if (data_ == nullptr) {
280        TELEPHONY_LOGE("data is null");
281        return false;
282    }
283    if (l == BIT0 || l > BIT8) {
284        TELEPHONY_LOGE("write bits : invalid length");
285        return false;
286    }
287
288    if (bitIndex_ + l <= BIT8) {
289        if (index_ == length_) {
290            TELEPHONY_LOGE("write bits over buffer[%d]", l);
291            return false;
292        }
293        data_[index_] |= v << (BIT8 - bitIndex_ - l);
294        bitIndex_ += l;
295        if (bitIndex_ == BIT8) {
296            bitIndex_ = BIT0;
297            index_++;
298        }
299    } else {
300        if (index_ == length_ - 1) {
301            TELEPHONY_LOGE("write bits over buffer[%d]", l);
302            return false;
303        }
304        data_[index_++] |= v >> (l + bitIndex_ - BIT8);
305        bitIndex_ = l + bitIndex_ - BIT8;
306        data_[index_] |= v << (BIT8 - bitIndex_);
307    }
308    return true;
309}
310
311bool SmsWriteBuffer::InsertByte(uint8_t v, uint16_t index)
312{
313    if (data_ != nullptr && index < length_ && bitIndex_ == BIT0) {
314        data_[index] = v;
315        return true;
316    }
317    TELEPHONY_LOGE("insert byte error");
318    return false;
319}
320
321bool SmsWriteBuffer::GetTopValue(uint8_t &oneByte)
322{
323    if (data_ == nullptr || length_ == 0 || index_ >= length_) {
324        TELEPHONY_LOGE("buffer error");
325        return false;
326    }
327    oneByte = data_[index_];
328    return true;
329}
330
331bool SmsWriteBuffer::GetValueFromIndex(uint16_t index, uint8_t &v)
332{
333    if (data_ == nullptr || length_ == 0 || index >= length_) {
334        TELEPHONY_LOGE("buffer error");
335        return false;
336    }
337    v = data_[index];
338    return true;
339}
340} // namespace Telephony
341} // namespace OHOS
342