$search
00001 /* 00002 * Copyright (C) 2009, Willow Garage, Inc. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * * Redistributions of source code must retain the above copyright notice, 00007 * this list of conditions and the following disclaimer. 00008 * * Redistributions in binary form must reproduce the above copyright 00009 * notice, this list of conditions and the following disclaimer in the 00010 * documentation and/or other materials provided with the distribution. 00011 * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its 00012 * contributors may be used to endorse or promote products derived from 00013 * this software without specific prior written permission. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00017 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00019 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00021 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00023 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00024 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00025 * POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "ros/names.h" 00029 #include "ros/this_node.h" 00030 #include "ros/file_log.h" 00031 00032 #include <ros/console.h> 00033 #include <ros/assert.h> 00034 00035 #include <cstring> 00036 00037 namespace ros 00038 { 00039 00040 namespace names 00041 { 00042 00043 M_string g_remappings; 00044 M_string g_unresolved_remappings; 00045 00046 const M_string& getRemappings() 00047 { 00048 return g_remappings; 00049 } 00050 00051 const M_string& getUnresolvedRemappings() 00052 { 00053 return g_unresolved_remappings; 00054 } 00055 00056 bool isValidCharInName(char c) 00057 { 00058 if (isalnum(c) || c == '/' || c == '_') 00059 { 00060 return true; 00061 } 00062 00063 return false; 00064 } 00065 00066 bool validate(const std::string& name, std::string& error) 00067 { 00068 if (name.empty()) 00069 { 00070 return true; 00071 } 00072 00073 // First element is special, can be only ~ / or alpha 00074 char c = name[0]; 00075 if (!isalpha(c) && c != '/' && c != '~') 00076 { 00077 std::stringstream ss; 00078 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 ~."; 00079 error = ss.str(); 00080 return false; 00081 } 00082 00083 for (size_t i = 1; i < name.size(); ++i) 00084 { 00085 c = name[i]; 00086 if (!isValidCharInName(c)) 00087 { 00088 std::stringstream ss; 00089 ss << "Character [" << c << "] at element [" << i << "] is not valid in Graph Resource Name [" << name <<"]. Valid characters are a-z, A-Z, 0-9, / and _."; 00090 error = ss.str(); 00091 00092 return false; 00093 } 00094 } 00095 00096 return true; 00097 } 00098 00099 std::string clean(const std::string& name) 00100 { 00101 std::string clean = name; 00102 00103 size_t pos = clean.find("//"); 00104 while (pos != std::string::npos) 00105 { 00106 clean.erase(pos, 1); 00107 pos = clean.find("//", pos); 00108 } 00109 00110 if (*clean.rbegin() == '/') 00111 { 00112 clean.erase(clean.size() - 1, 1); 00113 } 00114 00115 return clean; 00116 } 00117 00118 std::string append(const std::string& left, const std::string& right) 00119 { 00120 return clean(left + "/" + right); 00121 } 00122 00123 std::string remap(const std::string& name) 00124 { 00125 std::string resolved = resolve(name, false); 00126 00127 M_string::const_iterator it = g_remappings.find(resolved); 00128 if (it != g_remappings.end()) 00129 { 00130 return it->second; 00131 } 00132 00133 return name; 00134 } 00135 00136 std::string resolve(const std::string& name, bool _remap) 00137 { 00138 std::string s = resolve(this_node::getNamespace(), name, _remap); 00139 return s; 00140 } 00141 00142 std::string resolve(const std::string& ns, const std::string& name, bool _remap) 00143 { 00144 std::string error; 00145 if (!validate(name, error)) 00146 { 00147 throw InvalidNameException(error); 00148 } 00149 00150 if (name.empty()) 00151 { 00152 if (ns.empty()) 00153 { 00154 return "/"; 00155 } 00156 00157 if (ns[0] == '/') 00158 { 00159 return ns; 00160 } 00161 00162 return append("/", ns); 00163 } 00164 00165 std::string copy = name; 00166 00167 if (copy[0] == '~') 00168 { 00169 copy = append(this_node::getName(), copy.substr(1)); 00170 } 00171 00172 if (copy[0] != '/') 00173 { 00174 copy = append("/", append(ns, copy)); 00175 } 00176 00177 copy = clean(copy); 00178 00179 if (_remap) 00180 { 00181 copy = remap(copy); 00182 } 00183 00184 return copy; 00185 } 00186 00187 void init(const M_string& remappings) 00188 { 00189 M_string::const_iterator it = remappings.begin(); 00190 M_string::const_iterator end = remappings.end(); 00191 for (; it != end; ++it) 00192 { 00193 const std::string& left = it->first; 00194 const std::string& right = it->second; 00195 00196 if (!left.empty() && left[0] != '_' && left != this_node::getName()) 00197 { 00198 std::string resolved_left = resolve(left, false); 00199 std::string resolved_right = resolve(right, false); 00200 g_remappings[resolved_left] = resolved_right; 00201 g_unresolved_remappings[left] = right; 00202 } 00203 } 00204 } 00205 00206 std::string parentNamespace(const std::string& name) 00207 { 00208 std::string error; 00209 if (!validate(name, error)) 00210 { 00211 throw InvalidNameException(error); 00212 } 00213 00214 if (!name.compare("")) return ""; 00215 if (!name.compare("/")) return "/"; 00216 00217 std::string stripped_name; 00218 00219 // rstrip trailing slash 00220 if (name.find_last_of('/') == name.size()-1) 00221 stripped_name = name.substr(0, name.size() -2); 00222 else 00223 stripped_name = name; 00224 00225 //pull everything up to the last / 00226 size_t last_pos = stripped_name.find_last_of('/'); 00227 if (last_pos == std::string::npos) 00228 { 00229 return ""; 00230 } 00231 else if (last_pos == 0) 00232 return "/"; 00233 return stripped_name.substr(0, last_pos); 00234 } 00235 00236 } // namespace names 00237 00238 } // namespace ros