1 //===-- PathMappingList.cpp -------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 #include <climits> 13 #include <cstring> 14 15 // Other libraries and framework includes 16 // Project includes 17 #include "lldb/Core/Error.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Host/FileSpec.h" 20 #include "lldb/Target/PathMappingList.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 25 //---------------------------------------------------------------------- 26 // PathMappingList constructor 27 //---------------------------------------------------------------------- 28 PathMappingList::PathMappingList () : 29 m_pairs(), 30 m_callback(nullptr), 31 m_callback_baton(nullptr), 32 m_mod_id(0) 33 { 34 } 35 36 PathMappingList::PathMappingList (ChangedCallback callback, 37 void *callback_baton) : 38 m_pairs (), 39 m_callback (callback), 40 m_callback_baton (callback_baton), 41 m_mod_id (0) 42 { 43 } 44 45 PathMappingList::PathMappingList (const PathMappingList &rhs) : 46 m_pairs(rhs.m_pairs), 47 m_callback(nullptr), 48 m_callback_baton(nullptr), 49 m_mod_id(0) 50 { 51 } 52 53 const PathMappingList & 54 PathMappingList::operator =(const PathMappingList &rhs) 55 { 56 if (this != &rhs) 57 { 58 m_pairs = rhs.m_pairs; 59 m_callback = nullptr; 60 m_callback_baton = nullptr; 61 m_mod_id = rhs.m_mod_id; 62 } 63 return *this; 64 } 65 66 PathMappingList::~PathMappingList() = default; 67 68 void 69 PathMappingList::Append (const ConstString &path, 70 const ConstString &replacement, 71 bool notify) 72 { 73 ++m_mod_id; 74 m_pairs.push_back(pair(path, replacement)); 75 if (notify && m_callback) 76 m_callback (*this, m_callback_baton); 77 } 78 79 void 80 PathMappingList::Append (const PathMappingList &rhs, bool notify) 81 { 82 ++m_mod_id; 83 if (!rhs.m_pairs.empty()) 84 { 85 const_iterator pos, end = rhs.m_pairs.end(); 86 for (pos = rhs.m_pairs.begin(); pos != end; ++pos) 87 m_pairs.push_back(*pos); 88 if (notify && m_callback) 89 m_callback (*this, m_callback_baton); 90 } 91 } 92 93 void 94 PathMappingList::Insert (const ConstString &path, 95 const ConstString &replacement, 96 uint32_t index, 97 bool notify) 98 { 99 ++m_mod_id; 100 iterator insert_iter; 101 if (index >= m_pairs.size()) 102 insert_iter = m_pairs.end(); 103 else 104 insert_iter = m_pairs.begin() + index; 105 m_pairs.insert(insert_iter, pair(path, replacement)); 106 if (notify && m_callback) 107 m_callback (*this, m_callback_baton); 108 } 109 110 bool 111 PathMappingList::Replace (const ConstString &path, 112 const ConstString &replacement, 113 uint32_t index, 114 bool notify) 115 { 116 iterator insert_iter; 117 if (index >= m_pairs.size()) 118 return false; 119 ++m_mod_id; 120 m_pairs[index] = pair(path, replacement); 121 if (notify && m_callback) 122 m_callback (*this, m_callback_baton); 123 return true; 124 } 125 126 bool 127 PathMappingList::Remove (size_t index, bool notify) 128 { 129 if (index >= m_pairs.size()) 130 return false; 131 132 ++m_mod_id; 133 iterator iter = m_pairs.begin() + index; 134 m_pairs.erase(iter); 135 if (notify && m_callback) 136 m_callback (*this, m_callback_baton); 137 return true; 138 } 139 140 // For clients which do not need the pair index dumped, pass a pair_index >= 0 141 // to only dump the indicated pair. 142 void 143 PathMappingList::Dump (Stream *s, int pair_index) 144 { 145 unsigned int numPairs = m_pairs.size(); 146 147 if (pair_index < 0) 148 { 149 unsigned int index; 150 for (index = 0; index < numPairs; ++index) 151 s->Printf("[%d] \"%s\" -> \"%s\"\n", 152 index, m_pairs[index].first.GetCString(), m_pairs[index].second.GetCString()); 153 } 154 else 155 { 156 if (static_cast<unsigned int>(pair_index) < numPairs) 157 s->Printf("%s -> %s", 158 m_pairs[pair_index].first.GetCString(), m_pairs[pair_index].second.GetCString()); 159 } 160 } 161 162 void 163 PathMappingList::Clear (bool notify) 164 { 165 if (!m_pairs.empty()) 166 ++m_mod_id; 167 m_pairs.clear(); 168 if (notify && m_callback) 169 m_callback (*this, m_callback_baton); 170 } 171 172 bool 173 PathMappingList::RemapPath (const ConstString &path, ConstString &new_path) const 174 { 175 const char *path_cstr = path.GetCString(); 176 177 if (!path_cstr) 178 return false; 179 180 const_iterator pos, end = m_pairs.end(); 181 for (pos = m_pairs.begin(); pos != end; ++pos) 182 { 183 const size_t prefixLen = pos->first.GetLength(); 184 185 if (::strncmp (pos->first.GetCString(), path_cstr, prefixLen) == 0) 186 { 187 std::string new_path_str (pos->second.GetCString()); 188 new_path_str.append(path.GetCString() + prefixLen); 189 new_path.SetCString(new_path_str.c_str()); 190 return true; 191 } 192 } 193 return false; 194 } 195 196 bool 197 PathMappingList::RemapPath (const char *path, std::string &new_path) const 198 { 199 if (m_pairs.empty() || path == nullptr || path[0] == '\0') 200 return false; 201 202 const_iterator pos, end = m_pairs.end(); 203 for (pos = m_pairs.begin(); pos != end; ++pos) 204 { 205 const size_t prefix_len = pos->first.GetLength(); 206 207 if (::strncmp (pos->first.GetCString(), path, prefix_len) == 0) 208 { 209 new_path = pos->second.GetCString(); 210 new_path.append(path + prefix_len); 211 return true; 212 } 213 } 214 return false; 215 } 216 217 bool 218 PathMappingList::FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const 219 { 220 if (!m_pairs.empty()) 221 { 222 char orig_path[PATH_MAX]; 223 char new_path[PATH_MAX]; 224 const size_t orig_path_len = orig_spec.GetPath (orig_path, sizeof(orig_path)); 225 if (orig_path_len > 0) 226 { 227 const_iterator pos, end = m_pairs.end(); 228 for (pos = m_pairs.begin(); pos != end; ++pos) 229 { 230 const size_t prefix_len = pos->first.GetLength(); 231 232 if (orig_path_len >= prefix_len) 233 { 234 if (::strncmp (pos->first.GetCString(), orig_path, prefix_len) == 0) 235 { 236 const size_t new_path_len = snprintf(new_path, sizeof(new_path), "%s/%s", pos->second.GetCString(), orig_path + prefix_len); 237 if (new_path_len < sizeof(new_path)) 238 { 239 new_spec.SetFile (new_path, true); 240 if (new_spec.Exists()) 241 return true; 242 } 243 } 244 } 245 } 246 } 247 } 248 new_spec.Clear(); 249 return false; 250 } 251 252 bool 253 PathMappingList::Replace (const ConstString &path, const ConstString &new_path, bool notify) 254 { 255 uint32_t idx = FindIndexForPath (path); 256 if (idx < m_pairs.size()) 257 { 258 ++m_mod_id; 259 m_pairs[idx].second = new_path; 260 if (notify && m_callback) 261 m_callback (*this, m_callback_baton); 262 return true; 263 } 264 return false; 265 } 266 267 bool 268 PathMappingList::Remove (const ConstString &path, bool notify) 269 { 270 iterator pos = FindIteratorForPath (path); 271 if (pos != m_pairs.end()) 272 { 273 ++m_mod_id; 274 m_pairs.erase (pos); 275 if (notify && m_callback) 276 m_callback (*this, m_callback_baton); 277 return true; 278 } 279 return false; 280 } 281 282 PathMappingList::const_iterator 283 PathMappingList::FindIteratorForPath (const ConstString &path) const 284 { 285 const_iterator pos; 286 const_iterator begin = m_pairs.begin(); 287 const_iterator end = m_pairs.end(); 288 289 for (pos = begin; pos != end; ++pos) 290 { 291 if (pos->first == path) 292 break; 293 } 294 return pos; 295 } 296 297 PathMappingList::iterator 298 PathMappingList::FindIteratorForPath (const ConstString &path) 299 { 300 iterator pos; 301 iterator begin = m_pairs.begin(); 302 iterator end = m_pairs.end(); 303 304 for (pos = begin; pos != end; ++pos) 305 { 306 if (pos->first == path) 307 break; 308 } 309 return pos; 310 } 311 312 bool 313 PathMappingList::GetPathsAtIndex (uint32_t idx, ConstString &path, ConstString &new_path) const 314 { 315 if (idx < m_pairs.size()) 316 { 317 path = m_pairs[idx].first; 318 new_path = m_pairs[idx].second; 319 return true; 320 } 321 return false; 322 } 323 324 uint32_t 325 PathMappingList::FindIndexForPath (const ConstString &path) const 326 { 327 const_iterator pos; 328 const_iterator begin = m_pairs.begin(); 329 const_iterator end = m_pairs.end(); 330 331 for (pos = begin; pos != end; ++pos) 332 { 333 if (pos->first == path) 334 return std::distance (begin, pos); 335 } 336 return UINT32_MAX; 337 } 338