• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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_PUBLIC_PB_MACROS_H_
18 #define INCLUDE_PERFETTO_PUBLIC_PB_MACROS_H_
19 
20 #include "perfetto/public/compiler.h"   // IWYU pragma: export
21 #include "perfetto/public/pb_msg.h"     // IWYU pragma: export
22 #include "perfetto/public/pb_packed.h"  // IWYU pragma: export
23 #include "perfetto/public/pb_utils.h"   // IWYU pragma: export
24 
25 // This header contains macros that define types and accessors for protobuf
26 // messages.
27 //
28 // Example usage:
29 //
30 // PERFETTO_PB_ENUM(perfetto_protos_BuiltinClock){
31 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_UNKNOWN) = 0,
32 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_REALTIME) = 1,
33 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_REALTIME_COARSE)
34 //         = 2,
35 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_MONOTONIC) = 3,
36 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_MONOTONIC_COARSE)
37 //         = 4,
38 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_MONOTONIC_RAW) = 5,
39 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_BOOTTIME) = 6,
40 //     PERFETTO_PB_ENUM_ENTRY(perfetto_protos_BUILTIN_CLOCK_MAX_ID) = 63,
41 // };
42 //
43 // PERFETTO_PB_MSG(perfetto_protos_TraceConfig_BuiltinDataSource);
44 // PERFETTO_PB_FIELD(perfetto_protos_TraceConfig_BuiltinDataSource,
45 //                   VARINT,
46 //                   perfetto_protos_BuiltinClock,
47 //                   primary_trace_clock,
48 //                   5);
49 //
50 // PERFETTO_PB_MSG(perfetto_protos_TraceConfig);
51 // PERFETTO_PB_ENUM_IN_MSG(perfetto_protos_TraceConfig, LockdownModeOperation){
52 //     PERFETTO_PB_ENUM_IN_MSG_ENTRY(perfetto_protos_TraceConfig,
53 //         LOCKDOWN_UNCHANGED) = 0,
54 //     PERFETTO_PB_ENUM_IN_MSG_ENTRY(perfetto_protos_TraceConfig,
55 //         LOCKDOWN_CLEAR) = 1,
56 //     PERFETTO_PB_ENUM_IN_MSG_ENTRY(perfetto_protos_TraceConfig,
57 //         LOCKDOWN_SET) = 2,
58 // };
59 // PERFETTO_PB_FIELD(perfetto_protos_TraceConfig,
60 //                   VARINT,
61 //                   perfetto_protos_TraceConfig_LockdownModeOperation,
62 //                   lockdown_mode,
63 //                   5);
64 //
65 // PERFETTO_PB_MSG_DECL(perfetto_protos_DebugAnnotation);
66 // PERFETTO_PB_MSG_DECL(perfetto_protos_TestEvent_TestPayload);
67 //
68 // PERFETTO_PB_MSG(perfetto_protos_TestEvent);
69 // PERFETTO_PB_FIELD(perfetto_protos_TestEvent, STRING, const char*, str, 1);
70 // PERFETTO_PB_FIELD(perfetto_protos_TestEvent, VARINT, uint32_t, seq_value, 2);
71 // PERFETTO_PB_FIELD(perfetto_protos_TestEvent, VARINT, uint64_t, counter, 3);
72 // PERFETTO_PB_FIELD(perfetto_protos_TestEvent,
73 //                   MSG,
74 //                   perfetto_protos_TestEvent_TestPayload,
75 //                   payload,
76 //                   5);
77 //
78 // PERFETTO_PB_MSG(perfetto_protos_TestEvent_TestPayload);
79 // PERFETTO_PB_FIELD(perfetto_protos_TestEvent_TestPayload,
80 //                   STRING,
81 //                   const char*,
82 //                   str,
83 //                   1);
84 // PERFETTO_PB_FIELD(perfetto_protos_TestEvent_TestPayload,
85 //                   MSG,
86 //                   perfetto_protos_DebugAnnotation,
87 //                   debug_annotations,
88 //                   7);
89 
90 #define PERFETTO_I_PB_CONCAT_4_(A, B, C, D) A##B##C##D
91 #define PERFETTO_I_PB_CONCAT_4(A, B, C, D) PERFETTO_I_PB_CONCAT_4_(A, B, C, D)
92 
93 #define PERFETTO_I_PB_CONCAT_3_(A, B, C) A##B##C
94 #define PERFETTO_I_PB_CONCAT_3(A, B, C) PERFETTO_I_PB_CONCAT_3_(A, B, C)
95 
96 #define PERFETTO_I_PB_SETTER_NAME(PROTO, NAME) \
97   PERFETTO_I_PB_CONCAT_3(PROTO, _set_, NAME)
98 
99 #define PERFETTO_I_PB_SETTER_CSTR_NAME(PROTO, NAME) \
100   PERFETTO_I_PB_CONCAT_3(PROTO, _set_cstr_, NAME)
101 
102 #define PERFETTO_I_PB_SETTER_BEGIN_NAME(PROTO, NAME) \
103   PERFETTO_I_PB_CONCAT_3(PROTO, _begin_, NAME)
104 
105 #define PERFETTO_I_PB_SETTER_END_NAME(PROTO, NAME) \
106   PERFETTO_I_PB_CONCAT_3(PROTO, _end_, NAME)
107 
108 #define PERFETTO_I_PB_NUM_FIELD_NAME(PROTO, NAME) \
109   PERFETTO_I_PB_CONCAT_4(PROTO, _, NAME, _field_number)
110 
111 #define PERFETTO_I_PB_GET_MSG(C_TYPE) PERFETTO_I_PB_CONCAT_3(C_TYPE, _, get_msg)
112 
113 #define PERFETTO_I_PB_FIELD_STRING(PREFIX, PROTO, C_TYPE, NAME, NUM)      \
114   static inline void PERFETTO_I_PB_SETTER_CSTR_NAME(PREFIX, NAME)(        \
115       struct PROTO * msg, const char* value) {                            \
116     PerfettoPbMsgAppendCStrField(&msg->msg, NUM, value);                  \
117   }                                                                       \
118   static inline void PERFETTO_I_PB_SETTER_NAME(PREFIX, NAME)(             \
119       struct PROTO * msg, const void* data, size_t len) {                 \
120     PerfettoPbMsgAppendType2Field(                                        \
121         &msg->msg, NUM, PERFETTO_STATIC_CAST(const uint8_t*, data), len); \
122   }                                                                       \
123   static inline void PERFETTO_I_PB_SETTER_BEGIN_NAME(PREFIX, NAME)(       \
124       struct PROTO * msg, struct PerfettoPbMsg * nested) {                \
125     PerfettoPbMsgBeginNested(&msg->msg, nested, NUM);                     \
126   }                                                                       \
127   static inline void PERFETTO_I_PB_SETTER_END_NAME(PREFIX, NAME)(         \
128       struct PROTO * msg, struct PerfettoPbMsg * nested) {                \
129     (void)nested;                                                         \
130     PerfettoPbMsgEndNested(&msg->msg);                                    \
131   }
132 
133 #define PERFETTO_I_PB_FIELD_VARINT(PREFIX, PROTO, C_TYPE, NAME, NUM)      \
134   static inline void PERFETTO_I_PB_SETTER_NAME(PREFIX, NAME)(             \
135       struct PROTO * msg, C_TYPE value) {                                 \
136     PerfettoPbMsgAppendType0Field(&msg->msg, NUM,                         \
137                                   PERFETTO_STATIC_CAST(uint64_t, value)); \
138   }
139 
140 #define PERFETTO_I_PB_FIELD_ZIGZAG(PREFIX, PROTO, C_TYPE, NAME, NUM)    \
141   static inline void PERFETTO_I_PB_SETTER_NAME(PREFIX, NAME)(           \
142       struct PROTO * msg, C_TYPE value) {                               \
143     uint64_t encoded =                                                  \
144         PerfettoPbZigZagEncode64(PERFETTO_STATIC_CAST(int64_t, value)); \
145     PerfettoPbMsgAppendType0Field(&msg->msg, NUM, encoded);             \
146   }
147 
148 #define PERFETTO_I_PB_FIELD_FIXED64(PREFIX, PROTO, C_TYPE, NAME, NUM) \
149   static inline void PERFETTO_I_PB_SETTER_NAME(PREFIX, NAME)(         \
150       struct PROTO * msg, C_TYPE value) {                             \
151     uint64_t val;                                                     \
152     memcpy(&val, &value, sizeof val);                                 \
153     PerfettoPbMsgAppendFixed64Field(&msg->msg, NUM, val);             \
154   }
155 
156 #define PERFETTO_I_PB_FIELD_FIXED32(PREFIX, PROTO, C_TYPE, NAME, NUM) \
157   static inline void PERFETTO_I_PB_SETTER_NAME(PREFIX, NAME)(         \
158       struct PROTO * msg, C_TYPE value) {                             \
159     uint32_t val;                                                     \
160     memcpy(&val, &value, sizeof val);                                 \
161     PerfettoPbMsgAppendFixed32Field(&msg->msg, NUM, val);             \
162   }
163 
164 #define PERFETTO_I_PB_FIELD_MSG(PREFIX, PROTO, C_TYPE, NAME, NUM)   \
165   static inline void PERFETTO_I_PB_SETTER_BEGIN_NAME(PREFIX, NAME)( \
166       struct PROTO * msg, struct C_TYPE * nested) {                 \
167     struct PerfettoPbMsg* nested_msg =                              \
168         PERFETTO_REINTERPRET_CAST(struct PerfettoPbMsg*, nested);   \
169     PerfettoPbMsgBeginNested(&msg->msg, nested_msg, NUM);           \
170   }                                                                 \
171   static inline void PERFETTO_I_PB_SETTER_END_NAME(PREFIX, NAME)(   \
172       struct PROTO * msg, struct C_TYPE * nested) {                 \
173     (void)nested;                                                   \
174     PerfettoPbMsgEndNested(&msg->msg);                              \
175   }
176 
177 #define PERFETTO_I_PB_FIELD_PACKED(PREFIX, PROTO, C_TYPE, NAME, NUM)      \
178   static inline void PERFETTO_I_PB_SETTER_NAME(PREFIX, NAME)(             \
179       struct PROTO * msg, const void* data, size_t len) {                 \
180     PerfettoPbMsgAppendType2Field(                                        \
181         &msg->msg, NUM, PERFETTO_STATIC_CAST(const uint8_t*, data), len); \
182   }                                                                       \
183   static inline void PERFETTO_I_PB_SETTER_BEGIN_NAME(PREFIX, NAME)(       \
184       struct PROTO * msg, struct PerfettoPbPackedMsg##C_TYPE * nested) {  \
185     struct PerfettoPbMsg* nested_msg =                                    \
186         PERFETTO_REINTERPRET_CAST(struct PerfettoPbMsg*, nested);         \
187     PerfettoPbMsgBeginNested(&msg->msg, nested_msg, NUM);                 \
188   }                                                                       \
189   static inline void PERFETTO_I_PB_SETTER_END_NAME(PREFIX, NAME)(         \
190       struct PROTO * msg, struct PerfettoPbPackedMsg##C_TYPE * nested) {  \
191     (void)nested;                                                         \
192     PerfettoPbMsgEndNested(&msg->msg);                                    \
193   }
194 
195 #define PERFETTO_I_PB_NUM_FIELD(PROTO, NAME, NUM) \
196   enum { PERFETTO_I_PB_NUM_FIELD_NAME(PROTO, NAME) = NUM }
197 
198 // Below are public macros that can be used to define protos. All the macros
199 // above are just implementation details and can change at any time.
200 
201 // Defines the type for a protobuf message.
202 // `PROTO` is the name of the message type. For nested messages, an underscore
203 // should be used as a separator.
204 #define PERFETTO_PB_MSG(PROTO) \
205   struct PROTO {               \
206     struct PerfettoPbMsg msg;  \
207   }
208 
209 // Declares the type for a protobuf message. Useful when a file references a
210 // type (because it is used as type for a field), but doesn't need the full
211 // definition.
212 #define PERFETTO_PB_MSG_DECL(PROTO) struct PROTO
213 
214 // Defines accessors for a field of a message.
215 // * `PROTO`: The message that contains this field. This should be the same
216 //   identifier passed to PERFETTO_PB_MSG.
217 // * `NAME`: The name of the field. It will be concatenated with `PROTO` to
218 //   produce the name for the accessors.
219 // * `NUM`: The numeric identifier for this field.
220 // * `TYPE`: The protobuf type of the field. Possible options:
221 //   * `VARINT`: For most integer (scalar and repeated non-packed) and enum
222 //     field types. `CTYPE` is the corresponding C type of the field. Generates
223 //     a single NAMESPACE_PROTO_set_NAME(CTYPE value accessor).
224 //   * `ZIGZAG`: For sint* (scalar and repeated non-packed) field types. `CTYPE`
225 //     is the corresponding C type of the field. Generates a single
226 //     PROTO_set_NAME(struct PROTO*, CTYPE) value setter.
227 //   * `FIXED32`: For fixed32, sfixed32 and float (scalar and repeated
228 //     non-packed) field types. `CTYPE` can be uint32_t, int32_t or float.
229 //     Generates a single PROTO_set_NAME(struct PROTO*, CTYPE) value setter.
230 //   * `FIXED64`: For fixed64, sfixed64 or double (scalar and repeated
231 //     non-packed) field types. `CTYPE` can be uint64_t or int64_t or double.
232 //     Generates a single PROTO_set_NAME(struct PROTO*, CTYPE) value setter.
233 //   * `MSG`: for nested (scalar and repeated) messages field types. `CTYPE` is
234 //     the type of the nested message (full type, including the namespace).
235 //     Generates
236 //     `PROTO_begin_NAME(struct PROTO*, struct CTYPE* nested)` and
237 //     `PROTO_end_NAME(struct PROTO*, struct CTYPE* nested)` that allows to
238 //     begin and end a nested submessage. `*nested` doesn't need to be
239 //     initialized.
240 //   * `STRING`: for bytes and string field types. `CTYPE` should be
241 //     `const char *`. Generates multiple accessors:
242 //      * PROTO_set_cstr_NAME(struct PROTO*, const char*): Sets the value of the
243 //        field by copying from a null terminated string.
244 //      * PROTO_set_NAME(struct PROTO*, const void*, size_t): Sets the value of
245 //        the field by copying from a buffer at an address with the specified
246 //        size.
247 //      * PROTO_begin_NAME(struct PROTO*, struct PerfettoPbMsg* nested) and
248 //        PROTO_end_NAME(struct PROTO*, struct PerfettoPbMsg* nested):
249 //        Begins (and ends) a nested submessage to allow users to generate part
250 //        of the length delimited buffer piece by piece.
251 //   * `PACKED`: for packed repeated field types. `CTYPE` should be
252 //     one of `PerfettoPbPacked*`. Generates multiple accessors:
253 //      * PROTO_set_NAME(struct PROTO*, const void*, size_t): Sets the value of
254 //        the field by copying from a buffer at an address with the specified
255 //        size.
256 //      * PROTO_begin_NAME(struct PROTO*, struct PerfettoPbPackedMsgCTYPE*
257 //        nested) and
258 //        PROTO_end_NAME(struct PROTO*, struct PerfettoPbPackedMsgCTYPE*
259 //        nested): Begins (and ends) a packed helper nested submessage (of the
260 //        right type) to allow users to push repeated entries one by one
261 //        directly into the stream writer buffer.
262 #define PERFETTO_PB_FIELD(PROTO, TYPE, C_TYPE, NAME, NUM)     \
263   PERFETTO_I_PB_FIELD_##TYPE(PROTO, PROTO, C_TYPE, NAME, NUM) \
264       PERFETTO_I_PB_NUM_FIELD(PROTO, NAME, NUM)
265 
266 // Defines accessors for a field of a message for an extension.
267 // * `EXTENSION`: The name of the extension. it's going to be used as a prefix.
268 //    There doesn't need to be a PERFETTO_PB_MSG definition for this.
269 // * `PROTO`: The (base) message that contains this field. This should be the
270 //   same identifier passed to PERFETTO_PB_MSG.
271 // The rest of the params are the same as the PERFETTO_PB_FIELD macro.
272 #define PERFETTO_PB_EXTENSION_FIELD(EXTENSION, PROTO, TYPE, C_TYPE, NAME, NUM) \
273   PERFETTO_I_PB_FIELD_##TYPE(EXTENSION, PROTO, C_TYPE, NAME, NUM)              \
274       PERFETTO_I_PB_NUM_FIELD(EXTENSION, NAME, NUM)
275 
276 // Defines an enum type nested inside a message (PROTO).
277 #define PERFETTO_PB_ENUM_IN_MSG(PROTO, ENUM) \
278   enum PERFETTO_I_PB_CONCAT_3(PROTO, _, ENUM)
279 
280 // Defines an entry for an enum tpye nested inside a message.
281 #define PERFETTO_PB_ENUM_IN_MSG_ENTRY(PROTO, NAME) \
282   PERFETTO_I_PB_CONCAT_3(PROTO, _, NAME)
283 
284 // Defines a global enum type.
285 #define PERFETTO_PB_ENUM(ENUM) enum ENUM
286 
287 // Defines an entry for global enum type.
288 #define PERFETTO_PB_ENUM_ENTRY(NAME) NAME
289 
290 #endif  // INCLUDE_PERFETTO_PUBLIC_PB_MACROS_H_
291