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