b8b26ee3创建于 2023年8月10日历史提交
/*
 * Copyright (C) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sms_pdu_buffer.h"

#include "securec.h"
#include "telephony_log_wrapper.h"

namespace OHOS {
namespace Telephony {
static constexpr uint16_t PDU_BUFFER_MAX_SIZE = 0xFF;
static constexpr uint16_t PDU_BUFFER_MIN_SIZE = 2;

SmsPduBuffer::~SmsPduBuffer()
{
    if (data_ != nullptr) {
        data_.reset();
    }
}

bool SmsPduBuffer::IsEmpty()
{
    return data_ == nullptr;
}

uint16_t SmsPduBuffer::GetIndex()
{
    return index_;
}

uint16_t SmsPduBuffer::GetSize()
{
    return length_;
}

bool SmsPduBuffer::SetIndex(uint16_t index)
{
    if (bitIndex_ != BIT0) {
        TELEPHONY_LOGE("buffer in bit mode");
        return false;
    }
    if (index > length_) {
        TELEPHONY_LOGE("index over buffer");
        return false;
    }

    index_ = index;
    return true;
}

uint16_t SmsPduBuffer::MoveForward(uint16_t len)
{
    if (bitIndex_ != BIT0) {
        TELEPHONY_LOGE("buffer in bit mode");
        return index_;
    }
    if (index_ + len > length_) {
        TELEPHONY_LOGE("move over buffer");
        return index_;
    }

    uint16_t pos = index_;
    index_ += len;
    return pos;
}

uint16_t SmsPduBuffer::MoveBack(uint16_t len)
{
    if (bitIndex_ != BIT0) {
        TELEPHONY_LOGE("buffer in bit mode");
        return index_;
    }
    if (index_ < len) {
        TELEPHONY_LOGE("back over buffer");
        return index_;
    }

    uint16_t pos = index_;
    index_ -= len;
    return pos;
}

uint16_t SmsPduBuffer::SkipBits()
{
    if (bitIndex_ > BIT0) {
        index_++;
        bitIndex_ = BIT0;
    }
    return index_;
}

std::unique_ptr<std::vector<uint8_t>> SmsPduBuffer::GetPduBuffer()
{
    if (data_ == nullptr || index_ == 0) {
        TELEPHONY_LOGE("data is null");
        return nullptr;
    }
    if (bitIndex_ != BIT0) {
        TELEPHONY_LOGE("buffer in bit mode");
        return nullptr;
    }

    if (index_ >= length_) {
        TELEPHONY_LOGE("data error.");
        return nullptr;
    }

    std::unique_ptr<std::vector<uint8_t>> data =
        std::make_unique<std::vector<uint8_t>>(data_.get(), data_.get() + index_);
    if (data == nullptr) {
        TELEPHONY_LOGE("make unique error");
        return nullptr;
    }
    return data;
}

SmsReadBuffer::SmsReadBuffer(const std::string &hex)
{
    size_t len = hex.length();
    if (len < PDU_BUFFER_MIN_SIZE || len > PDU_BUFFER_MAX_SIZE + 1) {
        TELEPHONY_LOGE("invalid PDU");
        return;
    }

    data_ = std::make_unique<uint8_t[]>(len);
    if (data_ == nullptr) {
        TELEPHONY_LOGE("make_unique error");
        return;
    }
    if (memset_s(data_.get(), len, 0x00, len) != EOK) {
        TELEPHONY_LOGE("memset_s error");
        data_.reset();
        data_ = nullptr;
        return;
    }
    if (memcpy_s(data_.get(), len, hex.c_str(), len) != EOK) {
        TELEPHONY_LOGE("memcpy_s error");
        data_.reset();
        data_ = nullptr;
        return;
    }
    length_ = len;
}

bool SmsReadBuffer::ReadByte(uint8_t &v)
{
    if (data_ == nullptr) {
        TELEPHONY_LOGE("data is null");
        return false;
    }
    if (bitIndex_ != BIT0) {
        return ReadBits(v, BIT8);
    }

    if (index_ == length_) {
        TELEPHONY_LOGW("read over buffer");
        return false;
    }

    v = data_[index_++];
    return true;
}

bool SmsReadBuffer::PickOneByte(uint8_t &v)
{
    if (data_ == nullptr || index_ >= length_) {
        TELEPHONY_LOGE("peek one byte fail.");
        return false;
    }
    v = data_[index_];
    return true;
}

bool SmsReadBuffer::PickOneByteFromIndex(uint16_t index, uint8_t &v)
{
    if (data_ == nullptr || length_ == 0 || index >= length_) {
        TELEPHONY_LOGE("peek index byte fail.");
        return false;
    }
    v = data_[index];
    return true;
}

bool SmsReadBuffer::ReadWord(uint16_t &v)
{
    if (data_ != nullptr && index_ < (length_ - 1) && bitIndex_ == BIT0) {
        v = data_[index_++];
        v = (v << BIT8) | data_[index_++];
        return true;
    }
    TELEPHONY_LOGE("read word error");
    return false;
}

bool SmsReadBuffer::ReadBits(uint8_t &v, uint8_t l)
{
    if (data_ == nullptr) {
        TELEPHONY_LOGE("data is null");
        return false;
    }
    if (l == BIT0 || l > BIT8) {
        TELEPHONY_LOGE("read bits : invalid length");
        return false;
    }

    if (bitIndex_ + l <= BIT8) {
        if (index_ == length_) {
            TELEPHONY_LOGE("read bits over buffer");
            return false;
        }
        v = data_[index_] << bitIndex_;
        v = v >> (BIT8 - l);
        bitIndex_ += l;
        if (bitIndex_ == BIT8) {
            bitIndex_ = BIT0;
            index_++;
        }
    } else {
        if (index_ == length_ - 1) {
            TELEPHONY_LOGE("read bits over buffer");
            return false;
        }
        v = data_[index_++] << bitIndex_;
        bitIndex_ = l + bitIndex_ - BIT8;
        v = (v >> (BIT8 - l)) | (data_[index_] >> (BIT8 - bitIndex_));
    }
    return true;
}

SmsWriteBuffer::SmsWriteBuffer()
{
    length_ = PDU_BUFFER_MAX_SIZE + 1;
    data_ = std::make_unique<uint8_t[]>(length_);
    if (data_ == nullptr) {
        TELEPHONY_LOGE("make_unique create data error");
        length_ = 0;
        return;
    }
}

bool SmsWriteBuffer::WriteByte(uint8_t v)
{
    if (bitIndex_ != BIT0) {
        return WriteBits(v, BIT8);
    }
    if (data_ != nullptr && index_ < length_) {
        data_[index_++] = v;
        return true;
    }
    TELEPHONY_LOGE("write byte error");
    return false;
}

bool SmsWriteBuffer::WriteWord(uint16_t v)
{
    if (data_ != nullptr && index_ < (length_ - 1) && bitIndex_ == BIT0) {
        data_[index_++] = (0xff00 & v) >> BIT8;
        data_[index_++] = (0x00ff & v);
        return true;
    }
    TELEPHONY_LOGE("write word error");
    return false;
}

bool SmsWriteBuffer::WriteBits(uint8_t v, uint8_t l)
{
    if (data_ == nullptr) {
        TELEPHONY_LOGE("data is null");
        return false;
    }
    if (l == BIT0 || l > BIT8) {
        TELEPHONY_LOGE("write bits : invalid length");
        return false;
    }

    if (bitIndex_ + l <= BIT8) {
        if (index_ == length_) {
            TELEPHONY_LOGE("write bits over buffer[%d]", l);
            return false;
        }
        data_[index_] |= v << (BIT8 - bitIndex_ - l);
        bitIndex_ += l;
        if (bitIndex_ == BIT8) {
            bitIndex_ = BIT0;
            index_++;
        }
    } else {
        if (index_ == length_ - 1) {
            TELEPHONY_LOGE("write bits over buffer[%d]", l);
            return false;
        }
        data_[index_++] |= v >> (l + bitIndex_ - BIT8);
        bitIndex_ = l + bitIndex_ - BIT8;
        data_[index_] |= v << (BIT8 - bitIndex_);
    }
    return true;
}

bool SmsWriteBuffer::InsertByte(uint8_t v, uint16_t index)
{
    if (data_ != nullptr && index < length_ && bitIndex_ == BIT0) {
        data_[index] = v;
        return true;
    }
    TELEPHONY_LOGE("insert byte error");
    return false;
}

bool SmsWriteBuffer::GetTopValue(uint8_t &oneByte)
{
    if (data_ == nullptr || length_ == 0 || index_ >= length_) {
        TELEPHONY_LOGE("buffer error");
        return false;
    }
    oneByte = data_[index_];
    return true;
}

bool SmsWriteBuffer::GetValueFromIndex(uint16_t index, uint8_t &v)
{
    if (data_ == nullptr || length_ == 0 || index >= length_) {
        TELEPHONY_LOGE("buffer error");
        return false;
    }
    v = data_[index];
    return true;
}
} // namespace Telephony
} // namespace OHOS