12a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci/* 22a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * Copyright (C) 2017 The Android Open Source Project 32a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * 42a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * Licensed under the Apache License, Version 2.0 (the "License"); 52a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * you may not use this file except in compliance with the License. 62a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * You may obtain a copy of the License at 72a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * 82a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * http://www.apache.org/licenses/LICENSE-2.0 92a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * 102a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * Unless required by applicable law or agreed to in writing, software 112a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * distributed under the License is distributed on an "AS IS" BASIS, 122a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * See the License for the specific language governing permissions and 142a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci * limitations under the License. 152a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci */ 162a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 17e1e56b63c369ffe22dc30fb2eeaac1556266d3ecHector Dearman#include "perfetto/protozero/message.h" 182a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 192a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#include <type_traits> 202a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 214f9b6d7b7b2ad7b86e1577a18dc6e2df91b98164Primiano Tucci#include "perfetto/base/logging.h" 22e1e56b63c369ffe22dc30fb2eeaac1556266d3ecHector Dearman#include "perfetto/protozero/message_handle.h" 232a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 242a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 252a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// The memcpy() for float and double below needs to be adjusted if we want to 262a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// support big endian CPUs. There doesn't seem to be a compelling need today. 272a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#error Unimplemented for big endian archs. 282a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#endif 292a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 302a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tuccinamespace protozero { 312a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 322a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// static 33aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanconstexpr uint32_t Message::kMaxNestingDepth; 342a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 352a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// Do NOT put any code in the constructor or use default initialization. 362a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// Use the Reset() method below instead. See the header for the reason why. 372a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 382a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// This method is called to initialize both root and nested messages. 39aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanvoid Message::Reset(ScatteredStreamWriter* stream_writer) { 402a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci// Older versions of libstdcxx don't have is_trivially_constructible. 412a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20170516 42aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman static_assert(std::is_trivially_constructible<Message>::value, 43aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman "Message must be trivially constructible"); 442a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#endif 452a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 46aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman static_assert(std::is_trivially_destructible<Message>::value, 47aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman "Message must be trivially destructible"); 482a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 492a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci static_assert( 50aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman sizeof(Message::nested_messages_arena_) >= 51aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman kMaxNestingDepth * 52aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman (sizeof(Message) - sizeof(Message::nested_messages_arena_)), 53aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearman "Message::nested_messages_arena_ is too small"); 542a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 552a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci stream_writer_ = stream_writer; 562a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci size_ = 0; 573a91887aa1252133dc1250459271ad574be69e27Primiano Tucci size_field_ = nullptr; 583a91887aa1252133dc1250459271ad574be69e27Primiano Tucci size_already_written_ = 0; 592a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci nested_message_ = nullptr; 602a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci nesting_depth_ = 0; 613a91887aa1252133dc1250459271ad574be69e27Primiano Tucci finalized_ = false; 628a8044f71ef345f8c41d4e566461db4454d7a933Florian Mayer#if PERFETTO_DCHECK_IS_ON() 632a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci handle_ = nullptr; 648a8044f71ef345f8c41d4e566461db4454d7a933Florian Mayer generation_++; 652a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#endif 662a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} 672a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 68aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanvoid Message::AppendString(uint32_t field_id, const char* str) { 692a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci AppendBytes(field_id, str, strlen(str)); 702a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} 712a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 72aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanvoid Message::AppendBytes(uint32_t field_id, const void* src, size_t size) { 732a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci if (nested_message_) 742a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci EndNestedMessage(); 752a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 76d7d1be012aea4ed5229a74b22c588ca8d7d527f4Primiano Tucci PERFETTO_DCHECK(size < proto_utils::kMaxMessageLength); 772a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci // Write the proto preamble (field id, type and length of the field). 782a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci uint8_t buffer[proto_utils::kMaxSimpleFieldEncodedSize]; 792a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci uint8_t* pos = buffer; 802a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci pos = proto_utils::WriteVarInt(proto_utils::MakeTagLengthDelimited(field_id), 812a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci pos); 822a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci pos = proto_utils::WriteVarInt(static_cast<uint32_t>(size), pos); 832a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci WriteToStream(buffer, pos); 842a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 852a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci const uint8_t* src_u8 = reinterpret_cast<const uint8_t*>(src); 862a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci WriteToStream(src_u8, src_u8 + size); 872a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} 882a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 89aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanuint32_t Message::Finalize() { 902c1b2d8098a0f4492fae12739786ef950875f209Hector Dearman if (finalized_) 912c1b2d8098a0f4492fae12739786ef950875f209Hector Dearman return size_; 922c1b2d8098a0f4492fae12739786ef950875f209Hector Dearman 932a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci if (nested_message_) 942a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci EndNestedMessage(); 952a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 962a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci // Write the length of the nested message a posteriori, using a leading-zero 972a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci // redundant varint encoding. 983a91887aa1252133dc1250459271ad574be69e27Primiano Tucci if (size_field_) { 993a91887aa1252133dc1250459271ad574be69e27Primiano Tucci PERFETTO_DCHECK(!finalized_); 100d7d1be012aea4ed5229a74b22c588ca8d7d527f4Primiano Tucci PERFETTO_DCHECK(size_ < proto_utils::kMaxMessageLength); 1013a91887aa1252133dc1250459271ad574be69e27Primiano Tucci PERFETTO_DCHECK(size_ >= size_already_written_); 1023a91887aa1252133dc1250459271ad574be69e27Primiano Tucci proto_utils::WriteRedundantVarInt(size_ - size_already_written_, 1033a91887aa1252133dc1250459271ad574be69e27Primiano Tucci size_field_); 1043a91887aa1252133dc1250459271ad574be69e27Primiano Tucci size_field_ = nullptr; 1052a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci } 1062a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 1073a91887aa1252133dc1250459271ad574be69e27Primiano Tucci finalized_ = true; 1088a8044f71ef345f8c41d4e566461db4454d7a933Florian Mayer#if PERFETTO_DCHECK_IS_ON() 1092a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci if (handle_) 1102a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci handle_->reset_message(); 1112a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci#endif 1122a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 1132a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci return size_; 1142a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} 1152a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 116aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanvoid Message::BeginNestedMessageInternal(uint32_t field_id, Message* message) { 1172a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci if (nested_message_) 1182a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci EndNestedMessage(); 1192a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 1202a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci // Write the proto preamble for the nested message. 1212a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci uint8_t data[proto_utils::kMaxTagEncodedSize]; 1222a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci uint8_t* data_end = proto_utils::WriteVarInt( 1232a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci proto_utils::MakeTagLengthDelimited(field_id), data); 1242a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci WriteToStream(data, data_end); 1252a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 1262a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci message->Reset(stream_writer_); 127d7d1be012aea4ed5229a74b22c588ca8d7d527f4Primiano Tucci PERFETTO_CHECK(nesting_depth_ < kMaxNestingDepth); 1282a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci message->nesting_depth_ = nesting_depth_ + 1; 1292a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 1302a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci // The length of the nested message cannot be known upfront. So right now 1312a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci // just reserve the bytes to encode the size after the nested message is done. 1322a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci message->set_size_field( 1332a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci stream_writer_->ReserveBytes(proto_utils::kMessageLengthFieldSize)); 1342a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci size_ += proto_utils::kMessageLengthFieldSize; 1352a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci nested_message_ = message; 1362a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} 1372a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 138aaa4c1997f110dee086ee93b83bfc7ac11bfc102Hector Dearmanvoid Message::EndNestedMessage() { 1392a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci size_ += nested_message_->Finalize(); 1402a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci nested_message_ = nullptr; 1412a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} 1422a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci 1432a29ac77885d86bcbd878ac7adb1789c9f9cffa4Primiano Tucci} // namespace protozero 144