9 std::shared_ptr<MessageParser::Node>
10 MessageParser::findType(
const std::string &name,
const std::string &ns) {
12 auto it = _data->type_map.find(name);
13 if (it != _data->type_map.end()) {
17 if (name ==
"Header") {
18 return findType(
"std_msgs/Header");
21 return findType(ns +
"/" + name);
23 throw std::runtime_error(
"Unknown message type: " + name);
26 void MessageParser::parseDefinition(
27 const std::shared_ptr<const MessageType> &type) {
29 PROFILER(
"MessageParser::parseDefinition");
31 if (_node && _node->hash == type->hash()) {
35 static std::mutex cache_mutex;
36 static std::unordered_map<std::string, std::shared_ptr<Node>> cache_map;
39 std::lock_guard<std::mutex> lock(cache_mutex);
40 auto it = cache_map.find(type->hash());
41 if (it != cache_map.end()) {
47 LOG_INFO(
"parsing message description " << type->name() <<
" " 50 std::vector<std::function<void()>> linker_jobs;
52 registerPrimitiveType<uint8_t>(
"bool");
53 registerPrimitiveType<int8_t>(
"byte");
54 registerPrimitiveType<uint8_t>(
"char");
55 registerPrimitiveType<int8_t>(
"int8");
56 registerPrimitiveType<uint8_t>(
"uint8");
57 registerPrimitiveType<int16_t>(
"int16");
58 registerPrimitiveType<uint16_t>(
"uint16");
59 registerPrimitiveType<int32_t>(
"int32");
60 registerPrimitiveType<uint32_t>(
"uint32");
61 registerPrimitiveType<int64_t>(
"int64");
62 registerPrimitiveType<uint64_t>(
"uint64");
63 registerPrimitiveType<float>(
"float32");
64 registerPrimitiveType<double>(
"float64");
65 registerType<TimeNode>(
"time");
66 registerType<DurationNode>(
"duration");
67 registerType<StringNode>(
"string");
69 std::string multi_definition =
70 "MSG: " + type->name() +
"\n" + type->definition();
72 static std::regex message_seperator(
"\\n\\s*========+\\s*",
73 std::regex_constants::optimize);
74 std::vector<std::string> message_definitions(
75 std::sregex_token_iterator(multi_definition.begin(),
76 multi_definition.end(), message_seperator, -1),
77 std::sregex_token_iterator());
79 std::shared_ptr<MessageNode> root_node;
81 for (
auto &message_type_and_definition : message_definitions) {
83 static std::regex message_type_and_definition_regex(
84 "\\s*MSG:\\s*(\\S+)\\s*\\n([\\s\\S]*)");
85 std::smatch message_type_and_definition_match;
86 if (!std::regex_match(message_type_and_definition,
87 message_type_and_definition_match,
88 message_type_and_definition_regex)) {
89 throw std::runtime_error(
"Message definition format error");
91 std::string message_type_name = message_type_and_definition_match[1];
92 std::string message_definition = message_type_and_definition_match[2];
96 auto message_node = std::make_shared<MessageNode>();
97 registerType(message_type_name, message_node);
100 root_node = message_node;
103 std::string message_namespace;
105 auto end = message_node->name.find(
'/');
106 if (end != std::string::npos) {
107 message_namespace = message_node->name.substr(0, end);
112 std::stringstream message_definition_stream(message_definition);
113 while (std::getline(message_definition_stream, line)) {
115 for (
size_t i = 0; i < line.size(); i++) {
116 if (line[i] ==
'#') {
125 static std::regex regex(
"\\s*", std::regex_constants::optimize);
126 if (std::regex_match(line, match, regex)) {
132 static std::regex regex(
"\\s*(\\S+)\\s+([^\\s=]+)\\s*\\=\\s*(.*)",
133 std::regex_constants::optimize);
134 if (std::regex_match(line, match, regex)) {
136 auto const_node = std::make_shared<ConstNode>();
138 const_node->type_name = match[1];
139 const_node->name = match[2];
140 const_node->value_string = match[3];
142 message_node->const_map[const_node->name] =
143 message_node->const_nodes.size();
144 message_node->const_nodes.push_back(const_node);
151 static std::regex regex(
152 "\\s*([^\\s\\[]+)\\s*(\\[([^\\]]*)\\])?\\s+(\\S+)\\s*",
153 std::regex_constants::optimize);
154 if (std::regex_match(line, match, regex)) {
156 std::string field_name = match[4];
157 std::string type_name = match[1];
158 size_t field_index = message_node->field_nodes.size();
160 message_node->field_map[field_name] = field_index;
161 message_node->field_names.push_back(field_name);
163 if (match[2].str().empty()) {
164 linker_jobs.emplace_back([
this, message_node, field_index,
165 type_name, message_namespace]() {
166 message_node->field_nodes[field_index] =
167 findType(type_name, message_namespace);
169 message_node->field_nodes.push_back(
nullptr);
171 auto array_node = std::make_shared<ArrayNode>();
172 if (!match[3].str().empty()) {
173 array_node->has_fixed_element_count =
true;
174 array_node->fixed_element_count = std::stoull(match[3]);
176 linker_jobs.emplace_back([
this, type_name, array_node,
177 message_namespace]() {
178 array_node->element_node = findType(type_name, message_namespace);
180 message_node->field_nodes.push_back(array_node);
187 throw std::runtime_error(
"Malformed message definition line: " + line);
191 for (
auto &job : linker_jobs) {
195 root_node->init(*
this);
196 root_node->hash = type->hash();
201 std::lock_guard<std::mutex> lock(cache_mutex);
202 cache_map[type->hash()] = root_node;
206 void MessageParser::parse(
const std::shared_ptr<const Message> &message) {
207 if (_data ==
nullptr || _data.use_count() > 1) {
209 _data = std::make_shared<Data>();
210 _data->index = std::make_shared<Index>();
212 _data->message = message;
213 parseDefinition(message->type());
218 _data->index->clear();
220 _node->index(*
this, p);
225 static void printIndent(std::ostream &stream,
size_t indent) {
226 for (
size_t i = 0; i < indent; i++) {
231 static void printImpl(
const MessageParser &message, std::ostream &stream,
233 if (message.isMessage()) {
234 for (
size_t i = 0; i < message.size(); i++) {
235 printIndent(stream, indent);
236 stream << message.fieldName(i) <<
": ";
238 printImpl(message[i], stream, indent + 1);
242 if (message.isArray()) {
243 for (
size_t i = 0; i < message.size(); i++) {
244 printIndent(stream, indent);
246 printImpl(message[i], stream, indent + 1);
250 printIndent(stream, indent);
251 stream << message.toString() <<
"\n";
254 void MessageParser::print(std::ostream &stream)
const {
255 printImpl(*
this, stream, 0);
258 std::string MessageParser::print()
const {
259 std::stringstream stream;