106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci#include "base_message.h"
1606f6ba60Sopenharmony_ci
1706f6ba60Sopenharmony_ci#include "securec.h"
1806f6ba60Sopenharmony_ci#include "varint_encode.h"
1906f6ba60Sopenharmony_ci
2006f6ba60Sopenharmony_cinamespace OHOS {
2106f6ba60Sopenharmony_cinamespace Developtools {
2206f6ba60Sopenharmony_cinamespace Profiler {
2306f6ba60Sopenharmony_cinamespace ProtoEncoder {
2406f6ba60Sopenharmony_cibool BaseMessage::AllocateSubMessage()
2506f6ba60Sopenharmony_ci{
2606f6ba60Sopenharmony_ci    if (subMessageStack_ == nullptr) {
2706f6ba60Sopenharmony_ci        subMessage_ = new (std::nothrow) BaseMessage(writeCtx_);
2806f6ba60Sopenharmony_ci    } else {
2906f6ba60Sopenharmony_ci        subMessage_ = subMessageStack_->Get();
3006f6ba60Sopenharmony_ci    }
3106f6ba60Sopenharmony_ci
3206f6ba60Sopenharmony_ci    if (subMessage_ == nullptr) {
3306f6ba60Sopenharmony_ci        return false;
3406f6ba60Sopenharmony_ci    }
3506f6ba60Sopenharmony_ci    subMessage_->Reset(writeCtx_, subMessageStack_);
3606f6ba60Sopenharmony_ci    return true;
3706f6ba60Sopenharmony_ci}
3806f6ba60Sopenharmony_ci
3906f6ba60Sopenharmony_civoid BaseMessage::FinishSubMessage()
4006f6ba60Sopenharmony_ci{
4106f6ba60Sopenharmony_ci    int32_t subSize = subMessage_->Finish();
4206f6ba60Sopenharmony_ci    if (subMessageStack_ == nullptr) {
4306f6ba60Sopenharmony_ci        delete subMessage_;
4406f6ba60Sopenharmony_ci    } else {
4506f6ba60Sopenharmony_ci        subMessageStack_->Release();
4606f6ba60Sopenharmony_ci    }
4706f6ba60Sopenharmony_ci    subMessage_ = nullptr;
4806f6ba60Sopenharmony_ci    if (subSize < 0) {
4906f6ba60Sopenharmony_ci        Drop();
5006f6ba60Sopenharmony_ci        return;
5106f6ba60Sopenharmony_ci    }
5206f6ba60Sopenharmony_ci
5306f6ba60Sopenharmony_ci    uint8_t* fieldMemory = nullptr;
5406f6ba60Sopenharmony_ci    // backfill length
5506f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, backfillOffset_);
5606f6ba60Sopenharmony_ci    if (!writeCtx_->getMemory(writeCtx_, SIZE_RESERVED_LEN,
5706f6ba60Sopenharmony_ci                              &fieldMemory, &backfillOffset_)) {
5806f6ba60Sopenharmony_ci        Drop();
5906f6ba60Sopenharmony_ci        return;
6006f6ba60Sopenharmony_ci    }
6106f6ba60Sopenharmony_ci
6206f6ba60Sopenharmony_ci    if (subSize == 0) {
6306f6ba60Sopenharmony_ci        // reduce the size
6406f6ba60Sopenharmony_ci        *fieldMemory = 0;
6506f6ba60Sopenharmony_ci        writeCtx_->seek(writeCtx_, backfillOffset_ + 1);
6606f6ba60Sopenharmony_ci        size_++;
6706f6ba60Sopenharmony_ci        return;
6806f6ba60Sopenharmony_ci    }
6906f6ba60Sopenharmony_ci
7006f6ba60Sopenharmony_ci    // varint(Length)
7106f6ba60Sopenharmony_ci    EncodeVarintPadding(fieldMemory, subSize, SIZE_RESERVED_LEN);
7206f6ba60Sopenharmony_ci    size_ += SIZE_RESERVED_LEN + subSize;
7306f6ba60Sopenharmony_ci    // seek to tail
7406f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, backfillOffset_ + SIZE_RESERVED_LEN + subSize);
7506f6ba60Sopenharmony_ci}
7606f6ba60Sopenharmony_ci
7706f6ba60Sopenharmony_civoid BaseMessage::AddBytes(uint32_t fieldId, const void* data, uint32_t dataSize)
7806f6ba60Sopenharmony_ci{
7906f6ba60Sopenharmony_ci    if (subMessage_ != nullptr) {
8006f6ba60Sopenharmony_ci        FinishSubMessage();
8106f6ba60Sopenharmony_ci    }
8206f6ba60Sopenharmony_ci    if (!isWriting_) {
8306f6ba60Sopenharmony_ci        return;
8406f6ba60Sopenharmony_ci    }
8506f6ba60Sopenharmony_ci
8606f6ba60Sopenharmony_ci    uint8_t* fieldMemory = nullptr;
8706f6ba60Sopenharmony_ci    uint32_t fieldOffset = 0;
8806f6ba60Sopenharmony_ci    if (!writeCtx_->getMemory(writeCtx_, VARINT_ENCODE_MAX_SIZE + SIZE_RESERVED_LEN + dataSize,
8906f6ba60Sopenharmony_ci                              &fieldMemory, &fieldOffset)) {
9006f6ba60Sopenharmony_ci        Drop();
9106f6ba60Sopenharmony_ci        return;
9206f6ba60Sopenharmony_ci    }
9306f6ba60Sopenharmony_ci
9406f6ba60Sopenharmony_ci    uint32_t fieldSize = EncodeVarint(fieldMemory, (fieldId << FIELDID_SHIFT) | ProtoMessageType::LEN);
9506f6ba60Sopenharmony_ci    fieldSize += EncodeVarint(fieldMemory + fieldSize, dataSize);
9606f6ba60Sopenharmony_ci    if (dataSize != 0) {
9706f6ba60Sopenharmony_ci        if (memcpy_s(fieldMemory + fieldSize, dataSize, data, dataSize) != EOK) {
9806f6ba60Sopenharmony_ci            Drop();
9906f6ba60Sopenharmony_ci            return;
10006f6ba60Sopenharmony_ci        }
10106f6ba60Sopenharmony_ci    }
10206f6ba60Sopenharmony_ci    fieldSize += dataSize;
10306f6ba60Sopenharmony_ci    size_ += static_cast<int32_t>(fieldSize);
10406f6ba60Sopenharmony_ci    // seek to tail
10506f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, fieldOffset + fieldSize);
10606f6ba60Sopenharmony_ci}
10706f6ba60Sopenharmony_ci
10806f6ba60Sopenharmony_ciRandomWriteCtx* BaseMessage::StartAddBytes(uint32_t fieldId)
10906f6ba60Sopenharmony_ci{
11006f6ba60Sopenharmony_ci    if (subMessage_ != nullptr) {
11106f6ba60Sopenharmony_ci        FinishSubMessage();
11206f6ba60Sopenharmony_ci    }
11306f6ba60Sopenharmony_ci    if (!isWriting_) {
11406f6ba60Sopenharmony_ci        // finished or dropped
11506f6ba60Sopenharmony_ci        return nullptr;
11606f6ba60Sopenharmony_ci    }
11706f6ba60Sopenharmony_ci
11806f6ba60Sopenharmony_ci    uint8_t* fieldMemory = nullptr;
11906f6ba60Sopenharmony_ci    // max field size = varint(fieldId + type) + varint(len)
12006f6ba60Sopenharmony_ci    if (!writeCtx_->getMemory(writeCtx_, VARINT_ENCODE_MAX_SIZE + SIZE_RESERVED_LEN,
12106f6ba60Sopenharmony_ci                              &fieldMemory, &backfillOffset_)) {
12206f6ba60Sopenharmony_ci        Drop();
12306f6ba60Sopenharmony_ci        return nullptr;
12406f6ba60Sopenharmony_ci    }
12506f6ba60Sopenharmony_ci
12606f6ba60Sopenharmony_ci    uint32_t tagSize = EncodeVarint(fieldMemory, (fieldId << FIELDID_SHIFT) | ProtoMessageType::LEN);
12706f6ba60Sopenharmony_ci    backfillOffset_ += tagSize;
12806f6ba60Sopenharmony_ci    size_ += static_cast<int32_t>(tagSize);
12906f6ba60Sopenharmony_ci    // reserve length space
13006f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, backfillOffset_ + SIZE_RESERVED_LEN);
13106f6ba60Sopenharmony_ci    return writeCtx_;
13206f6ba60Sopenharmony_ci}
13306f6ba60Sopenharmony_ci
13406f6ba60Sopenharmony_civoid BaseMessage::FinishAddBytes(int32_t size)
13506f6ba60Sopenharmony_ci{
13606f6ba60Sopenharmony_ci    if (size < 0) {
13706f6ba60Sopenharmony_ci        Drop();
13806f6ba60Sopenharmony_ci        return;
13906f6ba60Sopenharmony_ci    }
14006f6ba60Sopenharmony_ci
14106f6ba60Sopenharmony_ci    uint8_t* fieldMemory = nullptr;
14206f6ba60Sopenharmony_ci    // backfill length
14306f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, backfillOffset_);
14406f6ba60Sopenharmony_ci    if (!writeCtx_->getMemory(writeCtx_, SIZE_RESERVED_LEN, &fieldMemory, &backfillOffset_)) {
14506f6ba60Sopenharmony_ci        Drop();
14606f6ba60Sopenharmony_ci        return;
14706f6ba60Sopenharmony_ci    }
14806f6ba60Sopenharmony_ci
14906f6ba60Sopenharmony_ci    if (size == 0) {
15006f6ba60Sopenharmony_ci        // reduce the size
15106f6ba60Sopenharmony_ci        *fieldMemory = 0;
15206f6ba60Sopenharmony_ci        writeCtx_->seek(writeCtx_, backfillOffset_ + 1);
15306f6ba60Sopenharmony_ci        size_++;
15406f6ba60Sopenharmony_ci        return;
15506f6ba60Sopenharmony_ci    }
15606f6ba60Sopenharmony_ci
15706f6ba60Sopenharmony_ci    // varint(Length)
15806f6ba60Sopenharmony_ci    EncodeVarintPadding(fieldMemory, size, SIZE_RESERVED_LEN);
15906f6ba60Sopenharmony_ci    size_ += SIZE_RESERVED_LEN + size;
16006f6ba60Sopenharmony_ci    // seek to tail
16106f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, backfillOffset_ + SIZE_RESERVED_LEN + size);
16206f6ba60Sopenharmony_ci}
16306f6ba60Sopenharmony_ci
16406f6ba60Sopenharmony_civoid BaseMessage::AddBytesByCallBack(uint32_t fieldId, GetDataCallback getData)
16506f6ba60Sopenharmony_ci{
16606f6ba60Sopenharmony_ci    if (!getData) {
16706f6ba60Sopenharmony_ci        return;
16806f6ba60Sopenharmony_ci    }
16906f6ba60Sopenharmony_ci
17006f6ba60Sopenharmony_ci    if (subMessage_ != nullptr) {
17106f6ba60Sopenharmony_ci        FinishSubMessage();
17206f6ba60Sopenharmony_ci    }
17306f6ba60Sopenharmony_ci    if (!isWriting_) {
17406f6ba60Sopenharmony_ci        return;
17506f6ba60Sopenharmony_ci    }
17606f6ba60Sopenharmony_ci
17706f6ba60Sopenharmony_ci    uint8_t* fieldMemory = nullptr;
17806f6ba60Sopenharmony_ci    uint32_t fieldOffset = 0;
17906f6ba60Sopenharmony_ci    // max field size = varint(fieldId + type) + varint(len)
18006f6ba60Sopenharmony_ci    if (!writeCtx_->getMemory(writeCtx_, VARINT_ENCODE_MAX_SIZE + SIZE_RESERVED_LEN,
18106f6ba60Sopenharmony_ci                              &fieldMemory, &fieldOffset)) {
18206f6ba60Sopenharmony_ci        Drop();
18306f6ba60Sopenharmony_ci        return;
18406f6ba60Sopenharmony_ci    }
18506f6ba60Sopenharmony_ci
18606f6ba60Sopenharmony_ci    uint32_t tagSize = EncodeVarint(fieldMemory, (fieldId << FIELDID_SHIFT) | ProtoMessageType::LEN);
18706f6ba60Sopenharmony_ci    fieldOffset += tagSize;
18806f6ba60Sopenharmony_ci    size_ += static_cast<int32_t>(tagSize);
18906f6ba60Sopenharmony_ci    // reserve length space
19006f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, fieldOffset + SIZE_RESERVED_LEN);
19106f6ba60Sopenharmony_ci
19206f6ba60Sopenharmony_ci    int32_t dataSize = getData(writeCtx_);
19306f6ba60Sopenharmony_ci    if (dataSize < 0) {
19406f6ba60Sopenharmony_ci        Drop();
19506f6ba60Sopenharmony_ci        return;
19606f6ba60Sopenharmony_ci    }
19706f6ba60Sopenharmony_ci
19806f6ba60Sopenharmony_ci    // backfill length
19906f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, fieldOffset);
20006f6ba60Sopenharmony_ci    if (!writeCtx_->getMemory(writeCtx_, SIZE_RESERVED_LEN, &fieldMemory, &fieldOffset)) {
20106f6ba60Sopenharmony_ci        Drop();
20206f6ba60Sopenharmony_ci        return;
20306f6ba60Sopenharmony_ci    }
20406f6ba60Sopenharmony_ci
20506f6ba60Sopenharmony_ci    if (dataSize == 0) {
20606f6ba60Sopenharmony_ci        // reduce the size
20706f6ba60Sopenharmony_ci        *fieldMemory = 0;
20806f6ba60Sopenharmony_ci        writeCtx_->seek(writeCtx_, fieldOffset + 1);
20906f6ba60Sopenharmony_ci        size_++;
21006f6ba60Sopenharmony_ci        return;
21106f6ba60Sopenharmony_ci    }
21206f6ba60Sopenharmony_ci
21306f6ba60Sopenharmony_ci    EncodeVarintPadding(fieldMemory, dataSize, SIZE_RESERVED_LEN);
21406f6ba60Sopenharmony_ci    size_ += SIZE_RESERVED_LEN + dataSize;
21506f6ba60Sopenharmony_ci    // seek to tail
21606f6ba60Sopenharmony_ci    writeCtx_->seek(writeCtx_, fieldOffset + SIZE_RESERVED_LEN + dataSize);
21706f6ba60Sopenharmony_ci}
21806f6ba60Sopenharmony_ci} // namespace ProtoEncoder
21906f6ba60Sopenharmony_ci} // namespace Profiler
22006f6ba60Sopenharmony_ci} // namespace Developtools
22106f6ba60Sopenharmony_ci} // namespace OHOS
222