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