36 #include <boost/algorithm/string.hpp> 37 #include <boost/utility/string_ref.hpp> 38 #include <boost/lexical_cast.hpp> 39 #include <boost/regex.hpp> 40 #include <boost/algorithm/string/regex.hpp> 49 std::function<void(const ROSMessage*, StringTreeNode*, MessageTreeNode* )> recursiveTreeCreator;
54 const size_t NUM_FIELDS = msg_definition->
fields().size();
56 string_node->children().reserve( NUM_FIELDS );
57 msg_node->children().reserve( NUM_FIELDS );
61 if(field.isConstant() ==
false) {
64 string_node->addChild( field.name() );
65 StringTreeNode* new_string_node = &(string_node->children().back());
68 new_string_node->
children().reserve(1);
69 new_string_node = new_string_node->
addChild(
"#");
74 if( field.type().isBuiltin() ==
false)
77 if( next_msg ==
nullptr)
79 throw std::runtime_error(
"This type was not registered " );
81 msg_node->addChild( next_msg );
83 recursiveTreeCreator(next_msg, new_string_node, new_msg_node);
93 recursiveTreeCreator( &info.
type_list.front(),
100 return ( a.size() == b.
size() && std::strncmp( a.data(), b.
data(), a.size()) == 0);
103 inline bool FindPattern(
const std::vector<absl::string_view> &pattern,
107 if( tail->
value() == pattern[index] )
120 if( index == pattern.size()){
127 for (
auto& child: tail->
children() ) {
129 found =
FindPattern( pattern, index, &child, head);
139 for(
const auto& rule: given_rules)
141 if( rule_set.find( rule ) == rule_set.end() )
143 rule_set.insert( rule );
160 const ROSType& type = rule_it.first;
161 const std::unordered_set<SubstitutionRule>& rule_set = rule_it.second;
165 const std::string& msg_identifier = msg_it.first;
170 std::vector<RulesCache>& cache_vector =
_rule_caches[msg_identifier];
171 for(
const auto& rule: rule_set )
177 && std::find( cache_vector.begin(), cache_vector.end(), cache) == cache_vector.end()
180 cache_vector.push_back( std::move(cache) );
192 const std::string &definition)
200 const boost::regex msg_separation_regex(
"^=+\\n+");
202 std::vector<std::string> split;
203 std::vector<const ROSType*> all_types;
205 boost::split_regex(split, definition, msg_separation_regex);
210 for (
size_t i = 0;
i < split.size(); ++
i)
218 info.
type_list.push_back( std::move(msg) );
219 all_types.push_back( &(info.
type_list.back().type()) );
240 return &(it->second);
249 if( msg.
type() == type )
264 if( msg_info ==
nullptr)
266 throw std::runtime_error(
"extractField: msg_identifier not registered. Use registerMessageDefinition" );
274 std::function<void(const MessageTreeNode*)> recursiveImpl;
275 size_t buffer_offset = 0;
279 const ROSMessage* msg_definition = msg_node->value();
282 const bool matching = ( msg_type == monitored_type );
284 uint8_t* prev_buffer_ptr = buffer.
data() + buffer_offset;
285 size_t prev_offset = buffer_offset;
291 if(field.isConstant() )
continue;
295 int32_t array_size = field.arraySize();
296 if( array_size == -1)
305 for (
int i=0;
i<array_size;
i++ )
313 for (
int i=0;
i<array_size;
i++ )
315 recursiveImpl( msg_node->child(index_m) );
323 callback( monitored_type, view );
334 const uint32_t max_array_size )
const 337 bool entire_message_parse =
true;
340 size_t value_index = 0;
341 size_t name_index = 0;
342 size_t blob_index = 0;
344 if( msg_info ==
nullptr)
346 throw std::runtime_error(
"deserializeIntoFlatContainer: msg_identifier not registerd. Use registerMessageDefinition" );
348 size_t buffer_offset = 0;
350 std::function<void(const MessageTreeNode*,StringTreeLeaf,bool)> deserializeImpl;
352 deserializeImpl = [&](
363 if(field.isConstant() )
continue;
367 auto new_tree_leaf = tree_leaf;
368 new_tree_leaf.node_ptr = tree_leaf.node_ptr->child(index_s);
370 int32_t array_size = field.arraySize();
371 if( array_size == -1)
377 new_tree_leaf.index_array.push_back(0);
378 new_tree_leaf.node_ptr = new_tree_leaf.node_ptr->child(0);
381 bool IS_BLOB =
false;
384 if( array_size > static_cast<int32_t>(max_array_size))
393 entire_message_parse =
false;
399 if( flat_container->
blob.size() <= blob_index)
401 const size_t increased_size = std::max(
size_t(32), flat_container->
blob.size() * 3/2);
402 flat_container->
blob.resize( increased_size );
404 if( buffer_offset + array_size > buffer.
size() )
406 throw std::runtime_error(
"Buffer overrun in deserializeIntoFlatContainer (blob)");
410 flat_container->
blob[blob_index].first = new_tree_leaf ;
411 std::vector<uint8_t>& blob = flat_container->
blob[blob_index].second;
413 blob.resize( array_size );
414 std::memcpy( blob.data(), &buffer[buffer_offset], array_size);
416 buffer_offset += array_size;
420 bool DO_STORE_ARRAY = DO_STORE;
421 for (
int i=0;
i<array_size;
i++ )
423 if( DO_STORE_ARRAY &&
i >= max_array_size )
425 DO_STORE_ARRAY =
false;
428 if( field.isArray() && DO_STORE_ARRAY )
430 new_tree_leaf.index_array.back() =
i;
435 if( flat_container->
name.size() <= name_index)
437 const size_t increased_size = std::max(
size_t(32), flat_container->
name.size() * 3/2);
438 flat_container->
name.resize( increased_size );
440 std::string&
name = flat_container->
name[name_index].second;
441 ReadFromBuffer<std::string>( buffer, buffer_offset, name );
445 flat_container->
name[name_index].first = new_tree_leaf ;
451 if( flat_container->
value.size() <= value_index)
453 const size_t increased_size = std::max(
size_t(32), flat_container->
value.size() * 3/2);
454 flat_container->
value.resize( increased_size );
462 flat_container->
value[value_index] = std::make_pair( new_tree_leaf, std::move(var) );
468 deserializeImpl(msg_node->
child(index_m),
493 flat_container->
name.resize( name_index );
494 flat_container->
value.resize( value_index );
495 flat_container->
blob.resize( blob_index );
497 if( buffer_offset != buffer.
size() )
499 throw std::runtime_error(
"buildRosFlatType: There was an error parsing the buffer" );
501 return entire_message_parse;
506 return s.
size() == 1 && s[0] ==
'#';
511 return s.
size() == 1 && s[0] ==
'@';
525 if( node_ptr != pattern_head )
535 node_ptr = node_ptr->
parent();
540 template <
typename VectorType>
541 inline void JoinStrings(
const VectorType& vect,
const char separator, std::string& destination)
544 for(
const auto &
v: vect ) count +=
v.size();
549 destination.resize( count + vect.size() -1 );
551 char* buffer = &destination[0];
554 for (
size_t c = 0; c < vect.size()-1; c++)
556 const size_t S = vect[c].size();
557 std::memcpy( &buffer[buff_pos], vect[c].
data(), S );
559 buffer[buff_pos++] = separator;
561 std::memcpy( &buffer[buff_pos], vect.back().data(), vect.back().size() );
574 const size_t num_values = container.
value.size();
575 const size_t num_names = container.
name.size();
577 renamed_value->resize( container.
value.size() );
591 const std::vector<RulesCache>& rules_cache = rule_found->second;
599 if( !pattern_head || !alias_head )
continue;
601 for (
size_t n=0;
n<num_names;
n++)
607 for(
size_t value_index = 0; value_index<num_values; value_index++)
611 const auto& value_leaf = container.
value[value_index];
617 if( pattern_array_pos>= 0)
619 const std::string* new_name =
nullptr;
621 for (
size_t n=0;
n < num_names;
n++)
623 const auto & it = container.
name[
n];
631 new_name = &(it.second);
646 while( node_ptr != pattern_head)
661 node_ptr = node_ptr->
parent();
670 concatenated_name.
push_back( *new_name );
673 else{ concatenated_name.
push_back( str_val ); }
676 for (
size_t p = 0; p < rule->
pattern().size() && node_ptr; p++)
678 node_ptr = node_ptr->
parent();
696 node_ptr = node_ptr->
parent();
700 auto& renamed_pair = (*renamed_value)[value_index];
702 std::reverse(concatenated_name.
begin(), concatenated_name.
end());
703 JoinStrings( concatenated_name,
'/', renamed_pair.first);
704 renamed_pair.second = value_leaf.second ;
714 for(
size_t value_index=0; value_index< container.
value.size(); value_index++)
718 const std::pair<StringTreeLeaf, Variant> & value_leaf = container.
value[value_index];
720 std::string& destination = (*renamed_value)[value_index].first;
721 value_leaf.first.toStr( destination );
722 (*renamed_value)[value_index].second = value_leaf.second ;
std::function< void(const ROSType &, absl::Span< uint8_t > &)> VisitingCallback
const ROSMessageInfo * getMessageInfo(const std::string &msg_identifier) const
getMessageInfo provides some metadata amout a registered ROSMessage.
const ChildrenVector & children() const
int print_number(char *buffer, uint16_t value)
The StringTreeLeaf is, as the name suggests, a leaf (terminal node) of a StringTree. It provides the pointer to the node and a list of numbers that represent the index that corresponds to the placeholder "#".
std::vector< std::string > _formatted_string
std::vector< std::pair< StringTreeLeaf, std::string > > name
bool _discard_large_array
Variant ReadFromBufferToVariant(const absl::Span< uint8_t > &buffer, size_t &offset)
void push_back(const value_type &t)
const std::vector< ROSField > & fields() const
Vector of fields.
const StringTree * tree
Tree that the StringTreeLeaf(s) refer to.
TreeNode< T > * root()
Mutable pointer to the root of the tree.
std::vector< int > _alias_array_pos
void applyVisitorToBuffer(const std::string &msg_identifier, const ROSType &monitored_type, absl::Span< uint8_t > &buffer, VisitingCallback callback) const
applyVisitorToBuffer is used to pass a callback that is invoked every time a chunk of memory storing ...
std::vector< ROSMessage > type_list
Element of the tree. it has a single parent and N >= 0 children.
const ROSMessage * getMessageByType(const ROSType &type, const ROSMessageInfo &info) const
getMessageByType provides a pointer to a ROSMessage stored in ROSMessageInfo.
const TreeNode * parent() const
constexpr pointer data() const noexcept
std::unordered_map< std::string, std::vector< RulesCache > > _rule_caches
int PatternMatchAndIndexPosition(const StringTreeLeaf &leaf, const StringTreeNode *pattern_head)
void applyNameTransform(const std::string &msg_identifier, const FlatMessage &container, RenamedValues *renamed_value)
applyNameTransform is used to create a vector of type RenamedValues from the vector FlatMessage::valu...
const TreeNode< T > * croot() const
Constant pointer to the root of the tree.
const std::vector< absl::string_view > & alias() const
bool operator==(const std::string &a, const absl::string_view &b)
void JoinStrings(const VectorType &vect, const char separator, std::string &destination)
bool isSubstitutionPlaceholder(const absl::string_view &s)
const std::vector< absl::string_view > & substitution() const
constexpr size_type size() const noexcept
constexpr size_type size() const noexcept
std::unordered_map< ROSType, std::unordered_set< SubstitutionRule > > _registered_rules
int builtinSize(const BuiltinType c)
std::unordered_map< std::string, ROSMessageInfo > _registered_messages
InlinedVector< uint16_t, 8 > index_array
const SubstitutionRule * rule
void mutateType(const ROSType &new_type)
std::vector< std::pair< StringTreeLeaf, Variant > > value
const TreeNode * child(size_t index) const
const std::vector< absl::string_view > & pattern() const
bool deserializeIntoFlatContainer(const std::string &msg_identifier, absl::Span< uint8_t > buffer, FlatMessage *flat_container_output, const uint32_t max_array_size) const
deserializeIntoFlatContainer takes a raw buffer of memory and extract information from it...
std::vector< int8_t > _substituted
void ReadFromBuffer(const absl::Span< uint8_t > &buffer, size_t &offset, T &destination)
bool isNumberPlaceholder(const absl::string_view &s)
const StringTreeNode * node_ptr
const StringTreeNode * pattern_head
bool FindPattern(const std::vector< absl::string_view > &pattern, size_t index, const StringTreeNode *tail, const StringTreeNode **head)
const ROSType & type() const
const StringTreeNode * alias_head
std::vector< std::pair< StringTreeLeaf, std::vector< uint8_t > > > blob
std::vector< std::pair< std::string, Variant > > RenamedValues
constexpr const_pointer data() const noexcept
TreeNode * addChild(const T &child)
A ROSMessage will contain one or more ROSField(s). Each field is little more than a name / type pair...
void updateMissingPkgNames(const std::vector< const ROSType * > &all_types)
empty_struct data[sizeof(T)/sizeof(empty_struct)]
iterator begin() noexcept
BuiltinType typeID() const
If type is builtin, returns the id. BuiltinType::OTHER otherwise.
bool isBuiltin() const
True if the type is ROS builtin.
void registerRenamingRules(const ROSType &type, const std::vector< SubstitutionRule > &rules)
registerRenamingRules is used to register the renaming rules. You MUST use registerMessageDefinition ...
void registerMessageDefinition(const std::string &message_identifier, const ROSType &main_type, const std::string &definition)
A single message definition will (most probably) generate myltiple ROSMessage(s). In fact the "child"...
void createTrees(ROSMessageInfo &info, const std::string &type_name) const