-
Notifications
You must be signed in to change notification settings - Fork 116
/
demangle.cpp
145 lines (138 loc) · 4.82 KB
/
demangle.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2016-2018 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <algorithm>
#include <string>
#include <vector>
#include "rcutils/logging_macros.h"
#include "rcutils/types.h"
#include "namespace_prefix.hpp"
/// Return the demangle ROS topic or the original if not a ROS topic.
std::string
_demangle_if_ros_topic(const std::string & topic_name)
{
return _strip_ros_prefix_if_exists(topic_name);
}
/// Return the demangled ROS type or the original if not a ROS type.
std::string
_demangle_if_ros_type(const std::string & dds_type_string)
{
std::string substring = "::msg::dds_::";
size_t substring_position = dds_type_string.find(substring);
if (
dds_type_string[dds_type_string.size() - 1] == '_' &&
substring_position != std::string::npos)
{
std::string pkg = dds_type_string.substr(0, substring_position);
size_t start = substring_position + substring.size();
std::string type_name = dds_type_string.substr(start, dds_type_string.length() - 1 - start);
return pkg + "/" + type_name;
}
// not a ROS type
return dds_type_string;
}
/// Return the service name for a given topic if it is part of one, else "".
std::string
_demangle_service_from_topic(const std::string & topic_name)
{
std::string prefix = _get_ros_prefix_if_exists(topic_name);
if (!prefix.length()) {
// not a ROS topic or service
return "";
}
std::vector<std::string> prefixes = {
ros_service_response_prefix,
ros_service_requester_prefix,
};
if (
std::none_of(
prefixes.cbegin(), prefixes.cend(),
[&prefix](auto x) {
return prefix == x;
}))
{
// not a ROS service topic
return "";
}
std::vector<std::string> suffixes = {
"Reply",
"Request",
};
std::string found_suffix;
size_t suffix_position = std::string::npos;
for (auto suffix : suffixes) {
suffix_position = topic_name.rfind(suffix);
if (suffix_position != std::string::npos) {
if (topic_name.length() - suffix_position - suffix.length() != 0) {
RCUTILS_LOG_WARN_NAMED("rmw_fastrtps_shared_cpp",
"service topic has service prefix and a suffix, but not at the end"
", report this: '%s'", topic_name.c_str())
continue;
}
found_suffix = suffix;
break;
}
}
if (std::string::npos == suffix_position) {
RCUTILS_LOG_WARN_NAMED("rmw_fastrtps_shared_cpp",
"service topic has prefix but no suffix"
", report this: '%s'", topic_name.c_str())
return "";
}
// strip off the suffix first
std::string service_name = topic_name.substr(0, suffix_position + 1);
// then the prefix
size_t start = prefix.length(); // explicitly leave / after prefix
return service_name.substr(start, service_name.length() - 1 - start);
}
/// Return the demangled service type if it is a ROS srv type, else "".
std::string
_demangle_service_type_only(const std::string & dds_type_name)
{
std::string ns_substring = "::srv::dds_::";
size_t ns_substring_position = dds_type_name.find(ns_substring);
if (std::string::npos == ns_substring_position) {
// not a ROS service type
return "";
}
auto suffixes = {
std::string("_Response_"),
std::string("_Request_"),
};
std::string found_suffix = "";
size_t suffix_position = 0;
for (auto suffix : suffixes) {
suffix_position = dds_type_name.rfind(suffix);
if (suffix_position != std::string::npos) {
if (dds_type_name.length() - suffix_position - suffix.length() != 0) {
RCUTILS_LOG_WARN_NAMED("rmw_fastrtps_shared_cpp",
"service type contains '::srv::dds_::' and a suffix, but not at the end"
", report this: '%s'", dds_type_name.c_str())
continue;
}
found_suffix = suffix;
break;
}
}
if (std::string::npos == suffix_position) {
RCUTILS_LOG_WARN_NAMED("rmw_fastrtps_shared_cpp",
"service type contains '::srv::dds_::' but does not have a suffix"
", report this: '%s'", dds_type_name.c_str())
return "";
}
// everything checks out, reformat it from '<pkg>::srv::dds_::<type><suffix>' to '<pkg>/<type>'
std::string pkg = dds_type_name.substr(0, ns_substring_position);
size_t start = ns_substring_position + ns_substring.length();
std::string type_name = dds_type_name.substr(start, suffix_position - start);
return pkg + "/" + type_name;
}