1/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
18#define INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
19
20#include <memory>
21#include <string>
22#include <vector>
23
24#include "perfetto/base/export.h"
25#include "perfetto/protozero/root_message.h"
26#include "perfetto/protozero/scattered_stream_writer.h"
27
28namespace protozero {
29
30class Message;
31
32// A simple implementation of ScatteredStreamWriter::Delegate backed by a
33// fixed-size buffer. It doesn't support expansion. The caller needs to ensure
34// to never write more than the size of the buffer. Will CHECK() otherwise.
35class PERFETTO_EXPORT_COMPONENT StaticBufferDelegate
36 : public ScatteredStreamWriter::Delegate {
37 public:
38 StaticBufferDelegate(uint8_t* buf, size_t len) : range_{buf, buf + len} {}
39 ~StaticBufferDelegate() override;
40
41 // ScatteredStreamWriter::Delegate implementation.
42 ContiguousMemoryRange GetNewBuffer() override;
43
44 ContiguousMemoryRange const range_;
45 bool get_new_buffer_called_once_ = false;
46};
47
48// Helper function to create protozero messages backed by a fixed-size buffer
49// in one line. You can write:
50// protozero::Static<protozero::MyMessage> msg(buf.data(), buf.size());
51// msg->set_stuff(...);
52// size_t bytes_encoded = msg.Finalize();
53template <typename T /* protozero::Message */>
54class StaticBuffered {
55 public:
56 StaticBuffered(void* buf, size_t len)
57 : delegate_(reinterpret_cast<uint8_t*>(buf), len), writer_(&delegate_) {
58 msg_.Reset(&writer_);
59 }
60
61 // This can't be neither copied nor moved because Message hands out pointers
62 // to itself when creating submessages.
63 StaticBuffered(const StaticBuffered&) = delete;
64 StaticBuffered& operator=(const StaticBuffered&) = delete;
65 StaticBuffered(StaticBuffered&&) = delete;
66 StaticBuffered& operator=(StaticBuffered&&) = delete;
67
68 T* get() { return &msg_; }
69 T* operator->() { return &msg_; }
70
71 // The lack of a size() method is deliberate. It's to prevent that one
72 // accidentally calls size() before Finalize().
73
74 // Returns the number of encoded bytes (<= the size passed in the ctor).
75 size_t Finalize() {
76 msg_.Finalize();
77 return static_cast<size_t>(writer_.write_ptr() - delegate_.range_.begin);
78 }
79
80 private:
81 StaticBufferDelegate delegate_;
82 ScatteredStreamWriter writer_;
83 RootMessage<T> msg_;
84};
85
86// Helper function to create stack-based protozero messages in one line.
87// You can write:
88// protozero::StackBuffered<protozero::MyMessage, 16> msg;
89// msg->set_stuff(...);
90// size_t bytes_encoded = msg.Finalize();
91template <typename T /* protozero::Message */, size_t N>
92class StackBuffered : public StaticBuffered<T> {
93 public:
94 StackBuffered() : StaticBuffered<T>(&buf_[0], N) {}
95
96 private:
97 uint8_t buf_[N]; // Deliberately not initialized.
98};
99
100} // namespace protozero
101
102#endif // INCLUDE_PERFETTO_PROTOZERO_STATIC_BUFFER_H_
103

source code of dart_sdk/third_party/perfetto/include/perfetto/protozero/static_buffer.h