message_parser.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020,
6  * TU Dortmund - Institute of Control Theory and Systems Engineering.
7  * All rights reserved.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  *
22  * Authors: Christoph Rösmann
23  *********************************************************************/
24 
25 #ifdef MESSAGE_SUPPORT
26 
28 #include <corbo-core/console.h>
29 
30 #include <limits>
31 #include <list>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 
36 namespace p = google::protobuf;
37 
38 namespace corbo {
39 
40 void MessageParser::consumeFieldMessage(p::Message* message, const p::Reflection* reflection, const p::FieldDescriptor* field, bool expand_oneof,
41  bool skip_inactive_oneof, std::list<std::string>* nested_names)
42 {
43  FieldInformation info;
44  getFieldInformation(message, field, info, nested_names, true);
45 
46  if (field->is_repeated())
47  {
48  for (int i = 0; i < reflection->FieldSize(*message, field); ++i)
49  {
50  p::Message* new_message = reflection->MutableRepeatedMessage(message, field, i);
51 
52  if (_fun_msg_event) _fun_msg_event(MessageEvent::MessageStart, info);
53 
54  parse(new_message, expand_oneof, skip_inactive_oneof, nested_names);
55 
56  if (_fun_msg_event) _fun_msg_event(MessageEvent::MessageEnd, info);
57  }
58  }
59  else
60  {
61  p::Message* new_message = reflection->MutableMessage(message, field);
62 
63  if (_fun_msg_event) _fun_msg_event(MessageEvent::MessageStart, info);
64 
65  parse(new_message, expand_oneof, skip_inactive_oneof, nested_names);
66 
67  if (_fun_msg_event) _fun_msg_event(MessageEvent::MessageEnd, info);
68  }
69 }
70 
71 void MessageParser::consumeFieldValue(p::Message* message, const p::Reflection* reflection, const p::FieldDescriptor* field,
72  std::list<std::string>* nested_names)
73 {
74  switch (field->cpp_type())
75  {
76  case p::FieldDescriptor::CPPTYPE_INT32:
77  {
78  if (field->is_repeated())
79  {
80  std::vector<std::int32_t> values;
81  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedInt32(*message, field, i));
82 
83  if (_fun_value_int32_array)
84  {
85  FieldInformation info;
86  getFieldInformation(message, field, info, nested_names, false);
87  _fun_value_int32_array(values, info);
88  }
89  else
90  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [int32 array] but no callback is registered.");
91  }
92  else
93  {
94  std::int32_t value = reflection->GetInt32(*message, field);
95  if (_fun_value_int32)
96  {
97  FieldInformation info;
98  getFieldInformation(message, field, info, nested_names, false);
99  _fun_value_int32(value, info);
100  }
101  else
102  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [int32] but no callback is registered.");
103  }
104  break;
105  }
106  case p::FieldDescriptor::CPPTYPE_UINT32:
107  {
108  if (field->is_repeated())
109  {
110  std::vector<std::uint32_t> values;
111  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedUInt32(*message, field, i));
112 
113  if (_fun_value_uint32_array)
114  {
115  FieldInformation info;
116  getFieldInformation(message, field, info, nested_names, false);
117  _fun_value_uint32_array(values, info);
118  }
119  else
120  PRINT_WARNING_COND(_verbose,
121  "MessageParser: found value '" << field->name() << "' [uint32 array] but no callback is registered.");
122  }
123  else
124  {
125  std::uint32_t value = reflection->GetUInt32(*message, field);
126  if (_fun_value_uint32)
127  {
128  FieldInformation info;
129  getFieldInformation(message, field, info, nested_names, false);
130  _fun_value_uint32(value, info);
131  }
132  else
133  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [uint32] but no callback is registered.");
134  }
135  break;
136  }
137  case p::FieldDescriptor::CPPTYPE_INT64:
138  {
139  if (field->is_repeated())
140  {
141  std::vector<std::int64_t> values;
142  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedInt64(*message, field, i));
143 
144  if (_fun_value_int64_array)
145  {
146  FieldInformation info;
147  getFieldInformation(message, field, info, nested_names, false);
148  _fun_value_int64_array(values, info);
149  }
150  else
151  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [int64 array] but no callback is registered.");
152  }
153  else
154  {
155  std::int64_t value = reflection->GetInt64(*message, field);
156  if (_fun_value_int64)
157  {
158  FieldInformation info;
159  getFieldInformation(message, field, info, nested_names, false);
160  _fun_value_int64(value, info);
161  }
162  else
163  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [int64] but no callback is registered.");
164  }
165  break;
166  }
167  case p::FieldDescriptor::CPPTYPE_UINT64:
168  {
169  if (field->is_repeated())
170  {
171  std::vector<std::uint64_t> values;
172  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedUInt64(*message, field, i));
173 
174  if (_fun_value_uint64_array)
175  {
176  FieldInformation info;
177  getFieldInformation(message, field, info, nested_names, false);
178  _fun_value_uint64_array(values, info);
179  }
180  else
181  PRINT_WARNING_COND(_verbose,
182  "MessageParser: found value '" << field->name() << "' [uint64 array] but no callback is registered.");
183  }
184  else
185  {
186  std::uint64_t value = reflection->GetUInt64(*message, field);
187  if (_fun_value_uint64)
188  {
189  FieldInformation info;
190  getFieldInformation(message, field, info, nested_names, false);
191  _fun_value_uint64(value, info);
192  }
193  else
194  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [uint64] but no callback is registered.");
195  }
196  break;
197  }
198  case p::FieldDescriptor::CPPTYPE_FLOAT:
199  {
200  if (field->is_repeated())
201  {
202  std::vector<float> values;
203  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedFloat(*message, field, i));
204 
205  if (_fun_value_float_array)
206  {
207  FieldInformation info;
208  getFieldInformation(message, field, info, nested_names, false);
209  _fun_value_float_array(values, info);
210  }
211  else
212  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [float array] but no callback is registered.");
213  }
214  else
215  {
216  float value = reflection->GetFloat(*message, field);
217  if (_fun_value_float)
218  {
219  FieldInformation info;
220  getFieldInformation(message, field, info, nested_names, false);
221  _fun_value_float(value, info);
222  }
223  else
224  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [float] but no callback is registered.");
225  }
226  break;
227  }
228  case p::FieldDescriptor::CPPTYPE_DOUBLE:
229  {
230  if (field->is_repeated())
231  {
232  std::vector<double> values;
233  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedDouble(*message, field, i));
234 
235  if (_fun_value_double_array)
236  {
237  FieldInformation info;
238  getFieldInformation(message, field, info, nested_names, false);
239  _fun_value_double_array(values, info);
240  }
241  else
242  PRINT_WARNING_COND(_verbose,
243  "MessageParser: found value '" << field->name() << "' [double array] but no callback is registered.");
244  }
245  else
246  {
247  double value = reflection->GetDouble(*message, field);
248  if (_fun_value_double)
249  {
250  FieldInformation info;
251  getFieldInformation(message, field, info, nested_names, false);
252  _fun_value_double(value, info);
253  }
254  else
255  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [double] but no callback is registered.");
256  }
257  break;
258  }
259  case p::FieldDescriptor::CPPTYPE_STRING:
260  {
261  if (field->is_repeated())
262  {
263  std::vector<std::string> values;
264  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedString(*message, field, i));
265 
266  if (_fun_value_string_array)
267  {
268  FieldInformation info;
269  getFieldInformation(message, field, info, nested_names, false);
270  _fun_value_string_array(values, info);
271  }
272  else
273  PRINT_WARNING_COND(_verbose,
274  "MessageParser: found value '" << field->name() << "' [string array] but no callback is registered.");
275  }
276  else
277  {
278  std::string text = reflection->GetString(*message, field);
279  FieldInformation info;
280  getFieldInformation(message, field, info, nested_names, false);
281 
282  if (info.info_text.first && info.info_text.second)
283  {
284  if (_fun_value_string_info)
285  _fun_value_string_info(text, info);
286  else
287  PRINT_WARNING_COND(_verbose,
288  "MessageParser: found value '" << field->name() << "' [string info] but no callback is registered.");
289  }
290  else
291  {
292  if (_fun_value_string)
293  _fun_value_string(text, info);
294  else
295  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [string] but no callback is registered.");
296  }
297  }
298  break;
299  }
300  case p::FieldDescriptor::CPPTYPE_BOOL:
301  {
302  if (field->is_repeated())
303  {
304  std::vector<bool> values;
305  for (int i = 0; i < reflection->FieldSize(*message, field); ++i) values.push_back(reflection->GetRepeatedBool(*message, field, i));
306 
307  if (_fun_value_bool_array)
308  {
309  FieldInformation info;
310  getFieldInformation(message, field, info, nested_names, false);
311  _fun_value_bool_array(values, info);
312  }
313  else
314  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [bool array] but no callback is registered.");
315  }
316  else
317  {
318  bool flag = reflection->GetBool(*message, field);
319  if (_fun_value_bool)
320  {
321  FieldInformation info;
322  getFieldInformation(message, field, info, nested_names, false);
323  _fun_value_bool(flag, info);
324  }
325  else
326  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [bool] but no callback is registered.");
327  }
328  break;
329  }
330  case p::FieldDescriptor::CPPTYPE_ENUM:
331  {
332  if (field->is_repeated())
333  {
334  std::vector<std::string> values;
335  for (int i = 0; i < reflection->FieldSize(*message, field); ++i)
336  {
337  const p::EnumValueDescriptor* enum_desc = reflection->GetRepeatedEnum(*message, field, i);
338  values.push_back(enum_desc->name());
339  }
340 
341  if (_fun_value_enum_array)
342  {
343  FieldInformation info;
344  getFieldInformation(message, field, info, nested_names, false);
345  _fun_value_enum_array(values, info);
346  }
347  else
348  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [enum array] but no callback is registered.");
349  }
350  else
351  {
352  const p::EnumValueDescriptor* enum_desc = reflection->GetEnum(*message, field);
353 
354  std::string name = enum_desc->name();
355  if (_fun_value_enum)
356  {
357  FieldInformation info;
358  getFieldInformation(message, field, info, nested_names, false);
359  _fun_value_enum(name, info);
360  }
361  else
362  PRINT_WARNING_COND(_verbose, "MessageParser: found value '" << field->name() << "' [enum] but no callback is registered.");
363  }
364  break;
365  }
366  case p::FieldDescriptor::CPPTYPE_MESSAGE:
367  {
368  PRINT_WARNING_COND(_verbose,
369  "MessageParser: CPPTYPE_MESSAGE '" << field->name() << "' should be handeld in a different parser method...");
370  break;
371  }
372  default:
373  {
374  PRINT_WARNING_COND(_verbose, "MessageParser: Field '" << field->name() << "' unknown / not implemented.");
375  break;
376  }
377  }
378 }
379 
380 void MessageParser::parseField(p::Message* message, const p::FieldDescriptor* field, bool expand_oneof, bool expand_first_oneof,
381  bool skip_inactive_oneof, std::list<std::string>* nested_names)
382 {
383  if (nested_names) nested_names->push_back(field->name());
384 
385  bool expand_field = true;
386 
387  // check for one-of field
388  const p::OneofDescriptor* oneof = field->containing_oneof();
389  if (oneof)
390  {
391  // inform about oneof
392  if (_fun_msg_event)
393  {
394  FieldInformation info;
395  getFieldInformation(message, field, info, nested_names);
396  _fun_msg_event(MessageEvent::OneOf, info);
397  }
398  if (expand_oneof || expand_first_oneof)
399  {
400  if (message->GetReflection()->HasOneof(*message, oneof))
401  {
402  const p::FieldDescriptor* oneof_field = message->GetReflection()->GetOneofFieldDescriptor(*message, oneof);
403  // skip if this is not the active oneof-field
404  if (skip_inactive_oneof && field != oneof_field) expand_field = false;
405  }
406  else
407  {
408  if (skip_inactive_oneof) expand_field = false; // skip also if no oneof is active
409  }
410  }
411  else
412  expand_field = false;
413  }
414 
415  if (expand_field)
416  {
417  // check if we have a separate message or a value
418  if (field->cpp_type() == p::FieldDescriptor::CPPTYPE_MESSAGE)
419  {
420  consumeFieldMessage(message, message->GetReflection(), field, expand_oneof, skip_inactive_oneof, nested_names);
421  }
422  else
423  {
424  consumeFieldValue(message, message->GetReflection(), field, nested_names);
425  }
426  }
427 
428  if (nested_names) nested_names->pop_back();
429 }
430 
431 void MessageParser::parse(p::Message* message, bool expand_oneof, bool skip_inactive_oneof, std::list<std::string>* nested_names)
432 {
433  // iterate
434  const p::Descriptor* desc = message->GetDescriptor();
435  // const p::Reflection* refl = message.GetReflection();
436 
437  int num_fields = desc->field_count();
438  for (int i = 0; i < num_fields; ++i)
439  {
440  const p::FieldDescriptor* field = desc->field(i);
441  parseField(message, field, expand_oneof, expand_oneof, skip_inactive_oneof, nested_names);
442  }
443 }
444 
445 void MessageParser::getFieldInformation(p::Message* message, const p::FieldDescriptor* field, FieldInformation& info,
446  std::list<std::string>* nested_names, bool is_message)
447 {
448  // extract name
449  info.field_name = field->name();
450  info.msg_type = message->GetTypeName();
451 
452  // check if group is new
453  if (is_message)
454  {
455  if (field->is_repeated())
456  {
457  info.new_message = message->GetReflection()->FieldSize(*message, field) == 0;
458  }
459  else
460  {
461  info.new_message = !message->GetReflection()->HasField(*message, field);
462  }
463  }
464  else
465  info.new_message = false;
466 
467  // store nested names if provided
468  if (nested_names) info.nested_names = *nested_names;
469 
470  // extract one-of descriptor (nullptr if no oneof)
471  info.oneof_descriptor = field->containing_oneof();
472  if (info.oneof_descriptor)
473  info.oneof_selected_field = message->GetReflection()->GetOneofFieldDescriptor(*message, info.oneof_descriptor); // returns 0 if not set
474 
475  // extract enum fields if field defines ane enumeration
476  const p::EnumDescriptor* enum_desc = field->enum_type();
477  if (enum_desc)
478  {
479  for (int i = 0; i < enum_desc->value_count(); ++i)
480  {
481  info.enum_list.push_back(enum_desc->value(i)->name());
482  }
483  }
484 
485  // support reflection api from outside and hence store relevant information:
486  info.field_raw = field;
487  info.message_raw = message;
488 
489  // check field options
490  const p::FieldOptions& options = field->options();
491 
492  // default value:
493  if (options.HasExtension(messages::default_value))
494  info.default_value = std::make_pair(true, options.GetExtension(messages::default_value));
495  else
496  info.default_value = std::make_pair(false, 0.0);
497 
498  // min value:
499  if (options.HasExtension(messages::min_value))
500  info.min_value = std::make_pair(true, options.GetExtension(messages::min_value));
501  else
502  info.min_value = std::make_pair(false, 0.0);
503 
504  // max value:
505  if (options.HasExtension(messages::max_value))
506  info.max_value = std::make_pair(true, options.GetExtension(messages::max_value));
507  else
508  info.max_value = std::make_pair(false, 0.0);
509 
510  // dynamic size:
511  if (options.HasExtension(messages::dynamic_size))
512  info.dynamic_size = options.GetExtension(messages::dynamic_size);
513  else
514  info.dynamic_size = false;
515 
516  // min size:
517  if (options.HasExtension(messages::min_size))
518  info.min_size = std::make_pair(true, options.GetExtension(messages::min_size));
519  else
520  info.min_size = std::make_pair(false, 0);
521 
522  // max size:
523  if (options.HasExtension(messages::max_size))
524  info.max_size = std::make_pair(true, options.GetExtension(messages::max_size));
525  else
526  info.max_size = std::make_pair(false, std::numeric_limits<int>::max());
527 
528  // info flag:
529  if (options.HasExtension(messages::info))
530  info.info_text = std::make_pair(true, options.GetExtension(messages::info));
531  else
532  info.info_text = std::make_pair(false, false);
533 
534  // description
535  if (options.HasExtension(messages::description))
536  info.description = std::make_pair(true, options.GetExtension(messages::description));
537  else
538  info.description = std::make_pair(false, "");
539 
540  // additional label:
541  if (options.HasExtension(messages::label))
542  info.label = std::make_pair(true, options.GetExtension(messages::label));
543  else
544  info.label = std::make_pair(false, "");
545 
546  // preferred gui type
547  if (options.HasExtension(messages::gui_type))
548  info.gui_type = std::make_pair(true, options.GetExtension(messages::gui_type));
549  else
550  info.gui_type = std::make_pair(false, (messages::GuiType)0);
551 
552  // collapsed
553  if (options.HasExtension(messages::collapsed)) info.collapsed = options.GetExtension(messages::collapsed);
554 
555  // update signals
556  if (options.HasExtension(messages::update_signals)) info.update_signals = options.GetExtension(messages::update_signals);
557 
558  // print_description
559  if (options.HasExtension(messages::print_description)) info.print_description = options.GetExtension(messages::print_description);
560 
561  // message only options
562  if (info.new_message)
563  {
564  const p::MessageOptions& msg_options = message->GetDescriptor()->options();
565 
566  // msg_description
567  if (msg_options.HasExtension(messages::msg_description))
568  info.msg_description = std::make_pair(true, msg_options.GetExtension(messages::msg_description));
569  else
570  info.msg_description = std::make_pair(false, "");
571  }
572 }
573 
574 std::string MessageParser::nestedNamesToString(const std::list<std::string>& namespaces)
575 {
576  std::string text;
577  if (namespaces.empty()) return text;
578  auto it = namespaces.begin();
579  text += *it;
580  for (it = std::next(it); it != namespaces.end(); ++it) text += "." + *it;
581  return text;
582 }
583 
584 } // namespace corbo
585 
586 // MESSAGE_SUPPORT
587 #endif
#define max(a, b)
Definition: datatypes.h:20
#define PRINT_WARNING_COND(cond, msg)
Print msg-stream only if cond == true.
Definition: console.h:159
else if n * info
Definition: cholesky.cpp:18


control_box_rst
Author(s): Christoph Rösmann
autogenerated on Mon Feb 28 2022 22:07:05