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