• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "base_message.h"
16 
17 #include "securec.h"
18 #include "varint_encode.h"
19 
20 namespace OHOS {
21 namespace Developtools {
22 namespace Profiler {
23 namespace ProtoEncoder {
AllocateSubMessage()24 bool BaseMessage::AllocateSubMessage()
25 {
26     if (subMessageStack_ == nullptr) {
27         subMessage_ = new (std::nothrow) BaseMessage(writeCtx_);
28     } else {
29         subMessage_ = subMessageStack_->Get();
30     }
31 
32     if (subMessage_ == nullptr) {
33         return false;
34     }
35     subMessage_->Reset(writeCtx_, subMessageStack_);
36     return true;
37 }
38 
FinishSubMessage()39 void BaseMessage::FinishSubMessage()
40 {
41     int32_t subSize = subMessage_->Finish();
42     if (subMessageStack_ == nullptr) {
43         delete subMessage_;
44     } else {
45         subMessageStack_->Release();
46     }
47     subMessage_ = nullptr;
48     if (subSize < 0) {
49         Drop();
50         return;
51     }
52 
53     uint8_t* fieldMemory = nullptr;
54     // backfill length
55     writeCtx_->seek(writeCtx_, backfillOffset_);
56     if (!writeCtx_->getMemory(writeCtx_, SIZE_RESERVED_LEN,
57                               &fieldMemory, &backfillOffset_)) {
58         Drop();
59         return;
60     }
61 
62     if (subSize == 0) {
63         // reduce the size
64         *fieldMemory = 0;
65         writeCtx_->seek(writeCtx_, backfillOffset_ + 1);
66         size_++;
67         return;
68     }
69 
70     // varint(Length)
71     EncodeVarintPadding(fieldMemory, subSize, SIZE_RESERVED_LEN);
72     size_ += SIZE_RESERVED_LEN + subSize;
73     // seek to tail
74     writeCtx_->seek(writeCtx_, backfillOffset_ + SIZE_RESERVED_LEN + subSize);
75 }
76 
AddBytes(uint32_t fieldId,const void * data,uint32_t dataSize)77 void BaseMessage::AddBytes(uint32_t fieldId, const void* data, uint32_t dataSize)
78 {
79     if (subMessage_ != nullptr) {
80         FinishSubMessage();
81     }
82     if (!isWriting_) {
83         return;
84     }
85 
86     uint8_t* fieldMemory = nullptr;
87     uint32_t fieldOffset = 0;
88     // max field size = varint(fieldId + type) + varint(dataSize) + dataSize
89     if (!writeCtx_->getMemory(writeCtx_, VARINT_ENCODE_MAX_SIZE + SIZE_RESERVED_LEN + dataSize,
90                               &fieldMemory, &fieldOffset)) {
91         Drop();
92         return;
93     }
94 
95     uint32_t fieldSize = EncodeVarint(fieldMemory, (fieldId << FIELDID_SHIFT) | ProtoMessageType::LEN);
96     fieldSize += EncodeVarint(fieldMemory + fieldSize, dataSize);
97     if (dataSize != 0) {
98         if (memcpy_s(fieldMemory + fieldSize, dataSize, data, dataSize) != EOK) {
99             Drop();
100             return;
101         }
102     }
103     fieldSize += dataSize;
104     size_ += static_cast<int32_t>(fieldSize);
105     // seek to tail
106     writeCtx_->seek(writeCtx_, fieldOffset + fieldSize);
107 }
108 
StartAddBytes(uint32_t fieldId)109 RandomWriteCtx* BaseMessage::StartAddBytes(uint32_t fieldId)
110 {
111     if (subMessage_ != nullptr) {
112         FinishSubMessage();
113     }
114     if (!isWriting_) {
115         // finished or dropped
116         return nullptr;
117     }
118 
119     uint8_t* fieldMemory = nullptr;
120     // max field size = varint(fieldId + type) + varint(len)
121     if (!writeCtx_->getMemory(writeCtx_, VARINT_ENCODE_MAX_SIZE + SIZE_RESERVED_LEN,
122                               &fieldMemory, &backfillOffset_)) {
123         Drop();
124         return nullptr;
125     }
126 
127     uint32_t tagSize = EncodeVarint(fieldMemory, (fieldId << FIELDID_SHIFT) | ProtoMessageType::LEN);
128     backfillOffset_ += tagSize;
129     size_ += static_cast<int32_t>(tagSize);
130     // reserve length space
131     writeCtx_->seek(writeCtx_, backfillOffset_ + SIZE_RESERVED_LEN);
132     return writeCtx_;
133 }
134 
FinishAddBytes(int32_t size)135 void BaseMessage::FinishAddBytes(int32_t size)
136 {
137     if (size < 0) {
138         Drop();
139         return;
140     }
141 
142     uint8_t* fieldMemory = nullptr;
143     // backfill length
144     writeCtx_->seek(writeCtx_, backfillOffset_);
145     if (!writeCtx_->getMemory(writeCtx_, SIZE_RESERVED_LEN, &fieldMemory, &backfillOffset_)) {
146         Drop();
147         return;
148     }
149 
150     if (size == 0) {
151         // reduce the size
152         *fieldMemory = 0;
153         writeCtx_->seek(writeCtx_, backfillOffset_ + 1);
154         size_++;
155         return;
156     }
157 
158     // varint(Length)
159     EncodeVarintPadding(fieldMemory, size, SIZE_RESERVED_LEN);
160     size_ += SIZE_RESERVED_LEN + size;
161     // seek to tail
162     writeCtx_->seek(writeCtx_, backfillOffset_ + SIZE_RESERVED_LEN + size);
163 }
164 
AddBytesByCallBack(uint32_t fieldId,GetDataCallback getData)165 void BaseMessage::AddBytesByCallBack(uint32_t fieldId, GetDataCallback getData)
166 {
167     if (!getData) {
168         return;
169     }
170 
171     if (subMessage_ != nullptr) {
172         FinishSubMessage();
173     }
174     if (!isWriting_) {
175         return;
176     }
177 
178     uint8_t* fieldMemory = nullptr;
179     uint32_t fieldOffset = 0;
180     // max field size = varint(fieldId + type) + varint(len)
181     if (!writeCtx_->getMemory(writeCtx_, VARINT_ENCODE_MAX_SIZE + SIZE_RESERVED_LEN,
182                               &fieldMemory, &fieldOffset)) {
183         Drop();
184         return;
185     }
186 
187     uint32_t tagSize = EncodeVarint(fieldMemory, (fieldId << FIELDID_SHIFT) | ProtoMessageType::LEN);
188     fieldOffset += tagSize;
189     size_ += static_cast<int32_t>(tagSize);
190     // reserve length space
191     writeCtx_->seek(writeCtx_, fieldOffset + SIZE_RESERVED_LEN);
192 
193     int32_t dataSize = getData(writeCtx_);
194     if (dataSize < 0) {
195         Drop();
196         return;
197     }
198 
199     // backfill length
200     writeCtx_->seek(writeCtx_, fieldOffset);
201     if (!writeCtx_->getMemory(writeCtx_, SIZE_RESERVED_LEN, &fieldMemory, &fieldOffset)) {
202         Drop();
203         return;
204     }
205 
206     if (dataSize == 0) {
207         // reduce the size
208         *fieldMemory = 0;
209         writeCtx_->seek(writeCtx_, fieldOffset + 1);
210         size_++;
211         return;
212     }
213 
214     EncodeVarintPadding(fieldMemory, dataSize, SIZE_RESERVED_LEN);
215     size_ += SIZE_RESERVED_LEN + dataSize;
216     // seek to tail
217     writeCtx_->seek(writeCtx_, fieldOffset + SIZE_RESERVED_LEN + dataSize);
218 }
219 } // namespace ProtoEncoder
220 } // namespace Profiler
221 } // namespace Developtools
222 } // namespace OHOS
223