00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "ros/names.h"
00029 #include "ros/this_node.h"
00030
00031 #include <ros/console.h>
00032 #include <ros/assert.h>
00033
00034 #include <cstring>
00035
00036 namespace ros
00037 {
00038
00039 namespace names
00040 {
00041
00042 M_string g_remappings;
00043 M_string g_unresolved_remappings;
00044
00045 const M_string& getRemappings()
00046 {
00047 return g_remappings;
00048 }
00049
00050 const M_string& getUnresolvedRemappings()
00051 {
00052 return g_unresolved_remappings;
00053 }
00054
00055 bool isValidCharInName(char c)
00056 {
00057 if (isalnum(c) || c == '/' || c == '_')
00058 {
00059 return true;
00060 }
00061
00062 return false;
00063 }
00064
00065 bool validate(const std::string& name, std::string& error)
00066 {
00067 if (name.empty())
00068 {
00069 return true;
00070 }
00071
00072
00073 char c = name[0];
00074 if (!isalpha(c) && c != '/' && c != '~')
00075 {
00076 std::stringstream ss;
00077 ss << "Character [" << c << "] is not valid as the first character in Graph Resource Name [" << name << "]. Valid characters are a-z, A-Z, / and in some cases ~.";
00078 error = ss.str();
00079 return false;
00080 }
00081
00082 for (size_t i = 1; i < name.size(); ++i)
00083 {
00084 c = name[i];
00085 if (!isValidCharInName(c))
00086 {
00087 std::stringstream ss;
00088 ss << "Character [" << c << "] at element [" << i << "] is not valid in Graph Resource Name [" << name <<"]. Valid characters are a-z, A-Z, 0-9, / and _.";
00089 error = ss.str();
00090
00091 return false;
00092 }
00093 }
00094
00095 return true;
00096 }
00097
00098 std::string clean(const std::string& name)
00099 {
00100 std::string clean = name;
00101
00102 size_t pos = clean.find("//");
00103 while (pos != std::string::npos)
00104 {
00105 clean.erase(pos, 1);
00106 pos = clean.find("//", pos);
00107 }
00108
00109 if (*clean.rbegin() == '/')
00110 {
00111 clean.erase(clean.size() - 1, 1);
00112 }
00113
00114 return clean;
00115 }
00116
00117 std::string append(const std::string& left, const std::string& right)
00118 {
00119 return clean(left + "/" + right);
00120 }
00121
00122 std::string remap(const std::string& name)
00123 {
00124 std::string resolved = resolve(name, false);
00125
00126 M_string::const_iterator it = g_remappings.find(resolved);
00127 if (it != g_remappings.end())
00128 {
00129 return it->second;
00130 }
00131
00132 return name;
00133 }
00134
00135 std::string resolve(const std::string& name, bool _remap)
00136 {
00137 return resolve(this_node::getNamespace(), name, _remap);
00138 }
00139
00140 std::string resolve(const std::string& ns, const std::string& name, bool _remap)
00141 {
00142 std::string error;
00143 if (!validate(name, error))
00144 {
00145 throw InvalidNameException(error);
00146 }
00147
00148 if (name.empty())
00149 {
00150 if (ns.empty())
00151 {
00152 return "/";
00153 }
00154
00155 if (ns[0] == '/')
00156 {
00157 return ns;
00158 }
00159
00160 return append("/", ns);
00161 }
00162
00163 std::string copy = name;
00164
00165 if (copy[0] == '~')
00166 {
00167 copy = append(this_node::getName(), copy.substr(1));
00168 }
00169
00170 if (copy[0] != '/')
00171 {
00172 copy = append("/", append(ns, copy));
00173 }
00174
00175 copy = clean(copy);
00176
00177 if (_remap)
00178 {
00179 copy = remap(copy);
00180 }
00181
00182 return copy;
00183 }
00184
00185 void init(const M_string& remappings)
00186 {
00187 M_string::const_iterator it = remappings.begin();
00188 M_string::const_iterator end = remappings.end();
00189 for (; it != end; ++it)
00190 {
00191 const std::string& left = it->first;
00192 const std::string& right = it->second;
00193 if (!left.empty() && left[0] != '_')
00194 {
00195 std::string resolved_left = resolve(left, false);
00196 std::string resolved_right = resolve(right, false);
00197 g_remappings[resolved_left] = resolved_right;
00198 g_unresolved_remappings[left] = right;
00199 }
00200 }
00201 }
00202
00203 std::string parentNamespace(const std::string& name)
00204 {
00205 std::string error;
00206 if (!validate(name, error))
00207 {
00208 throw InvalidNameException(error);
00209 }
00210
00211 if (!name.compare("")) return "";
00212 if (!name.compare("/")) return "/";
00213
00214 std::string stripped_name;
00215
00216
00217 if (name.find_last_of('/') == name.size()-1)
00218 stripped_name = name.substr(0, name.size() -2);
00219 else
00220 stripped_name = name;
00221
00222
00223 size_t last_pos = stripped_name.find_last_of('/');
00224 if (last_pos == std::string::npos)
00225 {
00226 return "";
00227 }
00228 else if (last_pos == 0)
00229 return "/";
00230 return stripped_name.substr(0, last_pos);
00231 }
00232
00233 }
00234
00235 }