3 * Routines of building and reading Protocol Buffers Language grammar tree.
4 * Copyright 2019, Huang Qiangxiong <qiangxiong.huang@qq.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #ifndef __PROTOBUF_LANG_TREE_H__
14 #define __PROTOBUF_LANG_TREE_H__
16 #include <wireshark.h>
23 #endif /* __cplusplus */
25 #define PBL_DEFAULT_PACKAGE_NAME ""
27 typedef void(*pbl_report_error_cb_t
)(const char *msg_format
, ...);
29 /* Node types of protocol buffers language */
40 PBL_METHOD
, /* contains the rpc and stream node of service */
45 /* like google::protobuf::descriptor_pool of protobuf cpp library */
47 GQueue
* source_paths
; /* the directories in which to search for proto file */
48 pbl_report_error_cb_t error_cb
; /* error call back function */
49 GHashTable
* packages
; /* all packages parsed from proto files */
50 GHashTable
* proto_files
; /* all proto files that are parsed or to be parsed */
51 GQueue
* proto_files_to_be_parsed
; /* files is to be parsed */
52 struct _protobuf_lang_state_t
*parser_state
; /* current parser state */
53 } pbl_descriptor_pool_t
;
59 const char* package_name
;
60 int package_name_lineno
;
61 pbl_descriptor_pool_t
* pool
;
62 } pbl_file_descriptor_t
;
64 /* Basic information of node */
65 typedef struct pbl_node_t
{
66 pbl_node_type_t nodetype
;
68 char* full_name
; /* constructed during first access */
69 struct pbl_node_t
* parent
;
70 GQueue
* children
; /* child is a pbl_node_t */
71 GHashTable
* children_by_name
; /* take children names as keys */
72 pbl_file_descriptor_t
* file
;
76 /* like google::protobuf::MethodDescriptor of protobuf cpp library */
78 pbl_node_t basic_info
;
83 } pbl_method_descriptor_t
;
85 /* like google::protobuf::Descriptor of protobuf cpp library */
87 pbl_node_t basic_info
;
89 GHashTable
* fields_by_number
;
90 } pbl_message_descriptor_t
;
92 /* like google::protobuf::EnumValueDescriptor of protobuf cpp library */
94 pbl_node_t basic_info
;
96 } pbl_enum_value_descriptor_t
;
98 /* like google::protobuf::FieldDescriptor of protobuf cpp library */
100 pbl_node_t basic_info
;
102 int type
; /* refer to PROTOBUF_TYPE_XXX of protobuf-helper.h */
104 pbl_node_t
* options_node
;
107 bool has_default_value
; /* Does this field have an explicitly-declared default value? */
108 char* orig_default_value
;
109 int string_or_bytes_default_value_length
;
119 const pbl_enum_value_descriptor_t
* e
;
121 } pbl_field_descriptor_t
;
123 /* like google::protobuf::EnumDescriptor of protobuf cpp library */
125 pbl_node_t basic_info
;
127 GHashTable
* values_by_number
;
128 } pbl_enum_descriptor_t
;
130 /* Option node. The name of basic_info is optionName.
131 Now, we only care about fieldOption. */
133 pbl_node_t basic_info
;
135 } pbl_option_descriptor_t
;
137 /* the struct of token used by the parser */
138 typedef struct _protobuf_lang_token_t
{
139 char* v
; /* token string value */
140 int ln
; /* line number of this token in the .proto file */
141 } protobuf_lang_token_t
;
144 typedef struct _protobuf_lang_state_t
{
145 pbl_descriptor_pool_t
* pool
; /* pool will keep the parsing result */
146 pbl_file_descriptor_t
* file
; /* info of current parsing file */
147 GSList
* lex_string_tokens
;
148 GSList
* lex_struct_tokens
;
152 protobuf_lang_token_t
* tmp_token
; /* just for passing token value from protobuf_lang_lex() to ProtobufLangParser() */
153 } protobuf_lang_state_t
;
155 /* Store chars created by strdup or g_strconcat into protobuf_lang_state_t temporarily,
156 and return back the input chars pointer.
157 It will be freed when protobuf_lang_state_t is released */
159 pbl_store_string_token(protobuf_lang_state_t
* parser_state
, char* dupstr
)
161 parser_state
->lex_string_tokens
= g_slist_prepend(parser_state
->lex_string_tokens
, dupstr
);
165 /* Store a protobuf_lang_token_t in protobuf_lang_state_t temporarily, and return back
166 the input pointer. It will be freed when protobuf_lang_state_t is released */
167 static inline protobuf_lang_token_t
*
168 pbl_store_struct_token(protobuf_lang_state_t
* parser_state
, protobuf_lang_token_t
* newtoken
)
170 parser_state
->lex_struct_tokens
= g_slist_prepend(parser_state
->lex_struct_tokens
, newtoken
);
174 /* default error_cb */
176 pbl_printf(const char* fmt
, ...)
185 Reinitialize the protocol buffers pool according to proto files directories.
186 @param ppool The output descriptor_pool will be created. If *pool is not NULL, it will free it first.
187 @param directories The root directories containing proto files. Must end with NULL element.
188 @param error_cb The error reporter callback function. */
190 pbl_reinit_descriptor_pool(pbl_descriptor_pool_t
** ppool
, const char** directories
, pbl_report_error_cb_t error_cb
);
192 /* free all memory used by this protocol buffers language pool */
194 pbl_free_pool(pbl_descriptor_pool_t
* pool
);
196 /* add a proto file to pool. this file will not be parsed until run_pbl_parser function is invoked. */
198 pbl_add_proto_file_to_be_parsed(pbl_descriptor_pool_t
* pool
, const char* filepath
);
200 /* run C protocol buffers language parser, return 0 if success */
201 int run_pbl_parser(pbl_descriptor_pool_t
* pool
);
203 /* like descriptor_pool::FindMethodByName */
204 const pbl_method_descriptor_t
*
205 pbl_message_descriptor_pool_FindMethodByName(const pbl_descriptor_pool_t
* pool
, const char* name
);
207 /* like MethodDescriptor::name() */
209 pbl_method_descriptor_name(const pbl_method_descriptor_t
* method
);
211 /* like MethodDescriptor::full_name() */
213 pbl_method_descriptor_full_name(const pbl_method_descriptor_t
* method
);
215 /* like MethodDescriptor::input_type() */
216 const pbl_message_descriptor_t
*
217 pbl_method_descriptor_input_type(const pbl_method_descriptor_t
* method
);
219 /* like MethodDescriptor::output_type() */
220 const pbl_message_descriptor_t
*
221 pbl_method_descriptor_output_type(const pbl_method_descriptor_t
* method
);
223 /* like descriptor_pool::FindMessageTypeByName() */
224 const pbl_message_descriptor_t
*
225 pbl_message_descriptor_pool_FindMessageTypeByName(const pbl_descriptor_pool_t
* pool
, const char* name
);
227 /* like Descriptor::name() */
229 pbl_message_descriptor_name(const pbl_message_descriptor_t
* message
);
231 /* like Descriptor::full_name() */
233 pbl_message_descriptor_full_name(const pbl_message_descriptor_t
* message
);
235 /* like Descriptor::field_count() */
237 pbl_message_descriptor_field_count(const pbl_message_descriptor_t
* message
);
239 /* like Descriptor::field() */
240 const pbl_field_descriptor_t
*
241 pbl_message_descriptor_field(const pbl_message_descriptor_t
* message
, int field_index
);
243 /* like Descriptor::FindFieldByNumber() */
244 const pbl_field_descriptor_t
*
245 pbl_message_descriptor_FindFieldByNumber(const pbl_message_descriptor_t
* message
, int number
);
247 /* like Descriptor::FindFieldByName() */
248 const pbl_field_descriptor_t
*
249 pbl_message_descriptor_FindFieldByName(const pbl_message_descriptor_t
* message
, const char* name
);
251 /* like FieldDescriptor::full_name() */
253 pbl_field_descriptor_full_name(const pbl_field_descriptor_t
* field
);
255 /* like FieldDescriptor::name() */
257 pbl_field_descriptor_name(const pbl_field_descriptor_t
* field
);
259 /* like FieldDescriptor::number() */
261 pbl_field_descriptor_number(const pbl_field_descriptor_t
* field
);
263 /* like FieldDescriptor::type() */
265 pbl_field_descriptor_type(const pbl_field_descriptor_t
* field
);
267 /* like FieldDescriptor::is_repeated() */
269 pbl_field_descriptor_is_repeated(const pbl_field_descriptor_t
* field
);
271 /* like FieldDescriptor::is_packed() */
273 pbl_field_descriptor_is_packed(const pbl_field_descriptor_t
* field
);
275 /* like FieldDescriptor::TypeName() */
277 pbl_field_descriptor_TypeName(int field_type
);
279 /* like FieldDescriptor::message_type() */
280 const pbl_message_descriptor_t
*
281 pbl_field_descriptor_message_type(const pbl_field_descriptor_t
* field
);
283 /* like FieldDescriptor::enum_type() */
284 const pbl_enum_descriptor_t
*
285 pbl_field_descriptor_enum_type(const pbl_field_descriptor_t
* field
);
287 /* like FieldDescriptor::is_required() */
289 pbl_field_descriptor_is_required(const pbl_field_descriptor_t
* field
);
291 /* like FieldDescriptor::has_default_value().
292 * Does this field have an explicitly-declared default value? */
294 pbl_field_descriptor_has_default_value(const pbl_field_descriptor_t
* field
);
296 /* like FieldDescriptor::default_value_int32() */
298 pbl_field_descriptor_default_value_int32(const pbl_field_descriptor_t
* field
);
300 /* like FieldDescriptor::default_value_int64() */
302 pbl_field_descriptor_default_value_int64(const pbl_field_descriptor_t
* field
);
304 /* like FieldDescriptor::default_value_uint32() */
306 pbl_field_descriptor_default_value_uint32(const pbl_field_descriptor_t
* field
);
308 /* like FieldDescriptor::default_value_uint64() */
310 pbl_field_descriptor_default_value_uint64(const pbl_field_descriptor_t
* field
);
312 /* like FieldDescriptor::default_value_float() */
314 pbl_field_descriptor_default_value_float(const pbl_field_descriptor_t
* field
);
316 /* like FieldDescriptor::default_value_double() */
318 pbl_field_descriptor_default_value_double(const pbl_field_descriptor_t
* field
);
320 /* like FieldDescriptor::default_value_bool() */
322 pbl_field_descriptor_default_value_bool(const pbl_field_descriptor_t
* field
);
324 /* like FieldDescriptor::default_value_string() */
326 pbl_field_descriptor_default_value_string(const pbl_field_descriptor_t
* field
, int* size
);
328 /* like FieldDescriptor::default_value_enum() */
329 const pbl_enum_value_descriptor_t
*
330 pbl_field_descriptor_default_value_enum(const pbl_field_descriptor_t
* field
);
332 /* like EnumDescriptor::name() */
334 pbl_enum_descriptor_name(const pbl_enum_descriptor_t
* anEnum
);
336 /* like EnumDescriptor::full_name() */
338 pbl_enum_descriptor_full_name(const pbl_enum_descriptor_t
* anEnum
);
340 /* like EnumDescriptor::value_count() */
342 pbl_enum_descriptor_value_count(const pbl_enum_descriptor_t
* anEnum
);
344 /* like EnumDescriptor::value() */
345 const pbl_enum_value_descriptor_t
*
346 pbl_enum_descriptor_value(const pbl_enum_descriptor_t
* anEnum
, int value_index
);
348 /* like EnumDescriptor::FindValueByNumber() */
349 const pbl_enum_value_descriptor_t
*
350 pbl_enum_descriptor_FindValueByNumber(const pbl_enum_descriptor_t
* anEnum
, int number
);
352 /* like EnumDescriptor::FindValueByName() */
353 const pbl_enum_value_descriptor_t
*
354 pbl_enum_descriptor_FindValueByName(const pbl_enum_descriptor_t
* anEnum
, const char* name
);
356 /* like EnumValueDescriptor::name() */
358 pbl_enum_value_descriptor_name(const pbl_enum_value_descriptor_t
* enumValue
);
360 /* like EnumValueDescriptor::full_name() */
362 pbl_enum_value_descriptor_full_name(const pbl_enum_value_descriptor_t
* enumValue
);
364 /* like EnumValueDescriptor::number() */
366 pbl_enum_value_descriptor_number(const pbl_enum_value_descriptor_t
* enumValue
);
368 /* visit all message in this pool */
370 pbl_foreach_message(const pbl_descriptor_pool_t
* pool
, void (*cb
)(const pbl_message_descriptor_t
*, void*), void* userdata
);
373 * Following are tree building functions.
376 /* create a normal node */
378 pbl_create_node(pbl_file_descriptor_t
* file
, int lineno
, pbl_node_type_t nodetype
, const char* name
);
380 /* change the name of node */
382 pbl_set_node_name(pbl_node_t
* node
, int lineno
, const char* newname
);
384 /* get the name of node */
385 static inline const char*
386 pbl_get_node_name(pbl_node_t
* node
)
391 /* get the full name of node. if it is NULL, it will be built. */
393 pbl_get_node_full_name(pbl_node_t
* node
);
395 /* append a node as a child of the parent node, and return the parent pointer */
397 pbl_add_child(pbl_node_t
* parent
, pbl_node_t
* child
);
399 /* create an enumeration field node */
401 pbl_create_enum_value_node(pbl_file_descriptor_t
* file
, int lineno
, const char* name
, int number
);
403 /* merge one('from') node's children to another('to') node, and return the 'to' pointer */
405 pbl_merge_children(pbl_node_t
* to
, pbl_node_t
* from
);
407 /* create a field node */
409 pbl_create_field_node(pbl_file_descriptor_t
* file
, int lineno
, const char* label
, const char* type_name
, const char* name
, int number
, pbl_node_t
* options
);
411 /* create a map field node */
413 pbl_create_map_field_node(pbl_file_descriptor_t
* file
, int lineno
, const char* name
, int number
, pbl_node_t
* options
);
415 /* create a method (rpc or stream of service) node */
417 pbl_create_method_node(pbl_file_descriptor_t
* file
, int lineno
, const char* name
, const char* in_msg_type
, bool in_is_stream
, const char* out_msg_type
, bool out_is_stream
);
419 /* create an option node */
421 pbl_create_option_node(pbl_file_descriptor_t
* file
, int lineno
, const char* name
, const char* value
);
423 /* free a pbl_node_t and its children. */
425 pbl_free_node(void *anode
);
429 #endif /* __cplusplus */
431 #endif /* __PROTOBUF_LANG_TREE_H__ */
434 * Editor modelines - https://www.wireshark.org/tools/modelines.html
439 * indent-tabs-mode: nil
442 * vi: set shiftwidth=4 tabstop=8 expandtab:
443 * :indentSize=4:tabSize=8:noTabs=true: