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