rosx_introspection/src/ros_parser.cpp
Go to the documentation of this file.
1 /***** MIT License ****
2  *
3  * Copyright (c) 2016-2022 Davide Faconti
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include <functional>
25 
28 
29 namespace RosMsgParser
30 {
31 inline bool operator==(const std::string& a, const std::string_view& b)
32 {
33  return (a.size() == b.size() && std::strncmp(a.data(), b.data(), a.size()) == 0);
34 }
35 
36 Parser::Parser(const std::string& topic_name, const ROSType& msg_type,
37  const std::string& definition)
38  : _global_warnings(&std::cerr)
39  , _topic_name(topic_name)
40  , _discard_large_array(DISCARD_LARGE_ARRAYS)
41  , _max_array_size(100)
42  , _blob_policy(STORE_BLOB_AS_COPY)
43  , _dummy_root_field(new ROSField(msg_type, topic_name))
44 {
45  auto parsed_msgs = ParseMessageDefinitions(definition, msg_type);
46  _schema = BuildMessageSchema(topic_name, parsed_msgs);
47 }
48 
49 const std::shared_ptr<MessageSchema>& Parser::getSchema() const
50 {
51  return _schema;
52 }
53 
55 {
56  for (const auto& [msg_type, msg] : _schema->msg_library) // find in the list
57  {
58  if (msg_type == type)
59  {
60  return msg;
61  }
62  }
63  return {};
64 }
65 
66 template <typename Container>
67 inline void ExpandVectorIfNecessary(Container& container, size_t new_size)
68 {
69  if (container.size() <= new_size)
70  {
71  const size_t increased_size = std::max(size_t(32), container.size() * 2);
72  container.resize(increased_size);
73  }
74 }
75 
77  Deserializer* deserializer) const
78 {
79  deserializer->init(buffer);
80 
81  bool entire_message_parse = true;
82 
83  size_t value_index = 0;
84  size_t name_index = 0;
85  size_t blob_index = 0;
86  size_t blob_storage_index = 0;
87 
88  std::function<void(const ROSMessage*, FieldLeaf, bool)> deserializeImpl;
89 
90  deserializeImpl = [&](const ROSMessage* msg, FieldLeaf tree_leaf, bool store) {
91  size_t index_s = 0;
92  size_t index_m = 0;
93 
94  for (const ROSField& field : msg->fields())
95  {
96  bool DO_STORE = store;
97  if (field.isConstant())
98  {
99  continue;
100  }
101 
102  const ROSType& field_type = field.type();
103 
104  auto new_tree_leaf = tree_leaf;
105  new_tree_leaf.node = tree_leaf.node->child(index_s);
106 
107  int32_t array_size = field.arraySize();
108  if (array_size == -1)
109  {
110  array_size = deserializer->deserializeUInt32();
111  }
112  if (field.isArray())
113  {
114  new_tree_leaf.index_array.push_back(0);
115  }
116 
117  bool IS_BLOB = false;
118 
119  // Stop storing it if is NOT a blob and a very large array.
120  if (array_size > static_cast<int32_t>(_max_array_size) &&
121  field_type.typeID() == BuiltinType::OTHER)
122  {
123  if (builtinSize(field_type.typeID()) == 1)
124  {
125  IS_BLOB = true;
126  }
127  else
128  {
130  {
131  DO_STORE = false;
132  }
133  entire_message_parse = false;
134  }
135  }
136 
137  if (IS_BLOB) // special case. This is a "blob", typically an image, a map,
138  // pointcloud, etc.
139  {
140  ExpandVectorIfNecessary(flat_container->blob, blob_index);
141 
142  if (array_size > deserializer->bytesLeft())
143  {
144  throw std::runtime_error("Buffer overrun in deserializeIntoFlatContainer "
145  "(blob)");
146  }
147  if (DO_STORE)
148  {
149  flat_container->blob[blob_index].first = FieldsVector(new_tree_leaf);
150  auto& blob = flat_container->blob[blob_index].second;
151  blob_index++;
152 
154  {
155  ExpandVectorIfNecessary(flat_container->blob_storage, blob_storage_index);
156 
157  auto& storage = flat_container->blob_storage[blob_storage_index];
158  storage.resize(array_size);
159  std::memcpy(storage.data(), deserializer->getCurrentPtr(), array_size);
160  blob_storage_index++;
161 
162  blob = Span<const uint8_t>(storage.data(), storage.size());
163  }
164  else
165  {
166  blob = Span<const uint8_t>(deserializer->getCurrentPtr(), array_size);
167  }
168  }
169  deserializer->jump(array_size);
170  }
171  else // NOT a BLOB
172  {
173  bool DO_STORE_ARRAY = DO_STORE;
174  for (int i = 0; i < array_size; i++)
175  {
176  if (DO_STORE_ARRAY && i >= static_cast<int32_t>(_max_array_size))
177  {
178  DO_STORE_ARRAY = false;
179  }
180 
181  if (field.isArray() && DO_STORE_ARRAY)
182  {
183  new_tree_leaf.index_array.back() = i;
184  }
185 
186  if (field_type.typeID() == STRING)
187  {
188  ExpandVectorIfNecessary(flat_container->name, name_index);
189 
190  std::string str;
191  deserializer->deserializeString(str);
192 
193  if (DO_STORE_ARRAY)
194  {
195  flat_container->name[name_index].first = FieldsVector(new_tree_leaf);
196  flat_container->name[name_index].second = str;
197  name_index++;
198  }
199  }
200  else if (field_type.isBuiltin())
201  {
202  ExpandVectorIfNecessary(flat_container->value, value_index);
203 
204  Variant var = deserializer->deserialize(field_type.typeID());
205  if (DO_STORE_ARRAY)
206  {
207  flat_container->value[value_index] =
208  std::make_pair(new_tree_leaf, std::move(var));
209  value_index++;
210  }
211  }
212  else
213  { // field_type.typeID() == OTHER
214  auto msg_node = field.getMessagePtr(_schema->msg_library);
215  deserializeImpl(msg_node.get(), new_tree_leaf, DO_STORE_ARRAY);
216  }
217  } // end for array_size
218  }
219 
220  if (field_type.typeID() == OTHER)
221  {
222  index_m++;
223  }
224  index_s++;
225  } // end for fields
226  }; // end of lambda
227 
228  // pass the shared_ptr
229  flat_container->schema = _schema;
230 
231  FieldLeaf rootnode;
232  rootnode.node = _schema->field_tree.croot();
233  auto root_msg =
234  _schema->field_tree.croot()->value()->getMessagePtr(_schema->msg_library);
235 
236  deserializeImpl(root_msg.get(), rootnode, true);
237 
238  flat_container->name.resize(name_index);
239  flat_container->value.resize(value_index);
240  flat_container->blob.resize(blob_index);
241  flat_container->blob_storage.resize(blob_storage_index);
242 
243  return entire_message_parse;
244 }
245 
246 } // namespace RosMsgParser
RosMsgParser::ROSMessage::Ptr
std::shared_ptr< ROSMessage > Ptr
Definition: ros_message.hpp:37
RosMsgParser::Parser::_blob_policy
BlobPolicy _blob_policy
Definition: ros_parser.hpp:183
RosMsgParser::Deserializer::deserialize
virtual Variant deserialize(BuiltinType type)=0
RosMsgParser::ROSType
ROSType.
Definition: ros_type.hpp:39
RosMsgParser::FlatMessage::blob_storage
std::vector< std::vector< uint8_t > > blob_storage
Definition: ros_parser.hpp:48
RosMsgParser::FlatMessage::schema
std::shared_ptr< MessageSchema > schema
Definition: ros_parser.hpp:35
RosMsgParser::FieldLeaf::node
const FieldTreeNode * node
Definition: stringtree_leaf.hpp:87
definition
const char * definition()
RosMsgParser::Deserializer::init
virtual void init(Span< const uint8_t > buffer)
Definition: deserializer.hpp:23
RosMsgParser::ExpandVectorIfNecessary
void ExpandVectorIfNecessary(Container &container, size_t new_size)
Definition: rosx_introspection/src/ros_parser.cpp:67
RosMsgParser::Parser::_discard_large_array
MaxArrayPolicy _discard_large_array
Definition: ros_parser.hpp:181
RosMsgParser::operator==
bool operator==(const std::string &a, const std::string_view &b)
Definition: rosx_introspection/src/ros_parser.cpp:31
RosMsgParser::Deserializer::jump
virtual void jump(size_t bytes)=0
RosMsgParser::Deserializer::deserializeString
virtual void deserializeString(std::string &out)=0
mqtt_test_proto.msg
msg
Definition: mqtt_test_proto.py:43
RosMsgParser
Definition: builtin_types.hpp:34
sol::var
auto var(V &&v)
Definition: sol.hpp:18020
DataTamerParser::FieldsVector
std::vector< TypeField > FieldsVector
Definition: data_tamer_parser.hpp:75
RosMsgParser::ROSMessage
Definition: ros_message.hpp:34
RosMsgParser::Parser::Parser
Parser(const std::string &topic_name, const ROSType &msg_type, const std::string &definition)
Definition: rosx_introspection/src/ros_parser.cpp:36
backward::details::move
const T & move(const T &v)
Definition: backward.hpp:394
RosMsgParser::Deserializer::deserializeUInt32
virtual uint32_t deserializeUInt32()=0
RosMsgParser::Deserializer::getCurrentPtr
virtual const uint8_t * getCurrentPtr() const =0
RosMsgParser::Parser::_max_array_size
size_t _max_array_size
Definition: ros_parser.hpp:182
ros_parser.hpp
nlohmann::detail::void
j template void())
Definition: json.hpp:4061
RosMsgParser::Deserializer::bytesLeft
virtual size_t bytesLeft() const
Definition: deserializer.hpp:48
string_view
basic_string_view< char > string_view
Definition: core.h:518
RosMsgParser::FlatMessage::blob
std::vector< std::pair< FieldsVector, Span< const uint8_t > > > blob
Definition: ros_parser.hpp:46
RosMsgParser::OTHER
@ OTHER
Definition: builtin_types.hpp:61
RosMsgParser::Parser::STORE_BLOB_AS_COPY
@ STORE_BLOB_AS_COPY
Definition: ros_parser.hpp:96
RosMsgParser::Deserializer
Definition: deserializer.hpp:20
RosMsgParser::Parser::deserialize
bool deserialize(Span< const uint8_t > buffer, FlatMessage *flat_output, Deserializer *deserializer) const
deserializeIntoFlatContainer takes a raw buffer of memory and extract information from it....
Definition: rosx_introspection/src/ros_parser.cpp:76
RosMsgParser::FlatMessage::name
std::vector< std::pair< FieldsVector, std::string > > name
List of all those parsed fields that can be represented by a "string".
Definition: ros_parser.hpp:42
RosMsgParser::FlatMessage::value
std::vector< std::pair< FieldsVector, Variant > > value
Definition: ros_parser.hpp:39
RosMsgParser::Variant
Definition: variant.hpp:81
RosMsgParser::Parser::_schema
std::shared_ptr< MessageSchema > _schema
Definition: ros_parser.hpp:172
nonstd::span_lite::span
Definition: span.hpp:581
std
field_type
def field_type(f)
RosMsgParser::STRING
@ STRING
Definition: builtin_types.hpp:60
field
static void field(LexState *ls, ConsControl *cc)
Definition: lparser.c:891
RosMsgParser::BuildMessageSchema
MessageSchema::Ptr BuildMessageSchema(const std::string &topic_name, const std::vector< ROSMessage::Ptr > &parsed_msgs)
Definition: ros_message.cpp:170
RosMsgParser::Parser::getMessageByType
ROSMessage::Ptr getMessageByType(const ROSType &type) const
Definition: rosx_introspection/src/ros_parser.cpp:54
deserializer.hpp
msg_type
def msg_type(f)
RosMsgParser::builtinSize
int builtinSize(const BuiltinType c)
Definition: builtin_types.hpp:66
RosMsgParser::FieldLeaf
The FieldTreeLeaf is, as the name suggests, a leaf (terminal node) of a StringTree....
Definition: stringtree_leaf.hpp:85
RosMsgParser::Parser::getSchema
const std::shared_ptr< MessageSchema > & getSchema() const
getSchema provides some metadata amout a registered ROSMessage.
Definition: rosx_introspection/src/ros_parser.cpp:49
RosMsgParser::ROSField
A ROSMessage will contain one or more ROSField(s). Each field is little more than a name / type pair.
Definition: ros_field.hpp:46
RosMsgParser::ParseMessageDefinitions
std::vector< ROSMessage::Ptr > ParseMessageDefinitions(const std::string &multi_def, const ROSType &type)
Definition: ros_message.cpp:87
RosMsgParser::FlatMessage
Definition: ros_parser.hpp:33


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Aug 11 2024 02:24:25