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/Host/PosixApi.h" 21 #include "lldb/Target/PathMappingList.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 //---------------------------------------------------------------------- 27 // PathMappingList constructor 28 //---------------------------------------------------------------------- 29 PathMappingList::PathMappingList() 30 : m_pairs(), m_callback(nullptr), m_callback_baton(nullptr), m_mod_id(0) {} 31 32 PathMappingList::PathMappingList(ChangedCallback callback, void *callback_baton) 33 : m_pairs(), m_callback(callback), m_callback_baton(callback_baton), 34 m_mod_id(0) {} 35 36 PathMappingList::PathMappingList(const PathMappingList &rhs) 37 : m_pairs(rhs.m_pairs), m_callback(nullptr), m_callback_baton(nullptr), 38 m_mod_id(0) {} 39 40 const PathMappingList &PathMappingList::operator=(const PathMappingList &rhs) { 41 if (this != &rhs) { 42 m_pairs = rhs.m_pairs; 43 m_callback = nullptr; 44 m_callback_baton = nullptr; 45 m_mod_id = rhs.m_mod_id; 46 } 47 return *this; 48 } 49 50 PathMappingList::~PathMappingList() = default; 51 52 void PathMappingList::Append(const ConstString &path, 53 const ConstString &replacement, bool notify) { 54 ++m_mod_id; 55 m_pairs.push_back(pair(path, replacement)); 56 if (notify && m_callback) 57 m_callback(*this, m_callback_baton); 58 } 59 60 void PathMappingList::Append(const PathMappingList &rhs, bool notify) { 61 ++m_mod_id; 62 if (!rhs.m_pairs.empty()) { 63 const_iterator pos, end = rhs.m_pairs.end(); 64 for (pos = rhs.m_pairs.begin(); pos != end; ++pos) 65 m_pairs.push_back(*pos); 66 if (notify && m_callback) 67 m_callback(*this, m_callback_baton); 68 } 69 } 70 71 void PathMappingList::Insert(const ConstString &path, 72 const ConstString &replacement, uint32_t index, 73 bool notify) { 74 ++m_mod_id; 75 iterator insert_iter; 76 if (index >= m_pairs.size()) 77 insert_iter = m_pairs.end(); 78 else 79 insert_iter = m_pairs.begin() + index; 80 m_pairs.insert(insert_iter, pair(path, replacement)); 81 if (notify && m_callback) 82 m_callback(*this, m_callback_baton); 83 } 84 85 bool PathMappingList::Replace(const ConstString &path, 86 const ConstString &replacement, uint32_t index, 87 bool notify) { 88 iterator insert_iter; 89 if (index >= m_pairs.size()) 90 return false; 91 ++m_mod_id; 92 m_pairs[index] = pair(path, replacement); 93 if (notify && m_callback) 94 m_callback(*this, m_callback_baton); 95 return true; 96 } 97 98 bool PathMappingList::Remove(size_t index, bool notify) { 99 if (index >= m_pairs.size()) 100 return false; 101 102 ++m_mod_id; 103 iterator iter = m_pairs.begin() + index; 104 m_pairs.erase(iter); 105 if (notify && m_callback) 106 m_callback(*this, m_callback_baton); 107 return true; 108 } 109 110 // For clients which do not need the pair index dumped, pass a pair_index >= 0 111 // to only dump the indicated pair. 112 void PathMappingList::Dump(Stream *s, int pair_index) { 113 unsigned int numPairs = m_pairs.size(); 114 115 if (pair_index < 0) { 116 unsigned int index; 117 for (index = 0; index < numPairs; ++index) 118 s->Printf("[%d] \"%s\" -> \"%s\"\n", index, 119 m_pairs[index].first.GetCString(), 120 m_pairs[index].second.GetCString()); 121 } else { 122 if (static_cast<unsigned int>(pair_index) < numPairs) 123 s->Printf("%s -> %s", m_pairs[pair_index].first.GetCString(), 124 m_pairs[pair_index].second.GetCString()); 125 } 126 } 127 128 void PathMappingList::Clear(bool notify) { 129 if (!m_pairs.empty()) 130 ++m_mod_id; 131 m_pairs.clear(); 132 if (notify && m_callback) 133 m_callback(*this, m_callback_baton); 134 } 135 136 bool PathMappingList::RemapPath(const ConstString &path, 137 ConstString &new_path) const { 138 const char *path_cstr = path.GetCString(); 139 // CLEANUP: Convert this function to use StringRefs internally instead 140 // of raw c-strings. 141 if (!path_cstr) 142 return false; 143 144 const_iterator pos, end = m_pairs.end(); 145 for (pos = m_pairs.begin(); pos != end; ++pos) { 146 const size_t prefixLen = pos->first.GetLength(); 147 148 if (::strncmp(pos->first.GetCString(), path_cstr, prefixLen) == 0) { 149 std::string new_path_str(pos->second.GetCString()); 150 new_path_str.append(path.GetCString() + prefixLen); 151 new_path.SetCString(new_path_str.c_str()); 152 return true; 153 } 154 } 155 return false; 156 } 157 158 bool PathMappingList::RemapPath(llvm::StringRef path, 159 std::string &new_path) const { 160 if (m_pairs.empty() || path.empty()) 161 return false; 162 163 const_iterator pos, end = m_pairs.end(); 164 for (pos = m_pairs.begin(); pos != end; ++pos) { 165 if (!path.consume_front(pos->first.GetStringRef())) 166 continue; 167 168 new_path = pos->second.GetStringRef(); 169 new_path.append(path); 170 return true; 171 } 172 return false; 173 } 174 175 bool PathMappingList::ReverseRemapPath(const ConstString &path, 176 ConstString &new_path) const { 177 const char *path_cstr = path.GetCString(); 178 if (!path_cstr) 179 return false; 180 181 for (const auto &it : m_pairs) { 182 // FIXME: This should be using FileSpec API's to do the path appending. 183 const size_t prefixLen = it.second.GetLength(); 184 if (::strncmp(it.second.GetCString(), path_cstr, prefixLen) == 0) { 185 std::string new_path_str(it.first.GetCString()); 186 new_path_str.append(path.GetCString() + prefixLen); 187 new_path.SetCString(new_path_str.c_str()); 188 return true; 189 } 190 } 191 return false; 192 } 193 194 bool PathMappingList::FindFile(const FileSpec &orig_spec, 195 FileSpec &new_spec) const { 196 if (!m_pairs.empty()) { 197 char orig_path[PATH_MAX]; 198 const size_t orig_path_len = 199 orig_spec.GetPath(orig_path, sizeof(orig_path)); 200 if (orig_path_len > 0) { 201 const_iterator pos, end = m_pairs.end(); 202 for (pos = m_pairs.begin(); pos != end; ++pos) { 203 const size_t prefix_len = pos->first.GetLength(); 204 205 if (orig_path_len >= prefix_len) { 206 if (::strncmp(pos->first.GetCString(), orig_path, prefix_len) == 0) { 207 new_spec.SetFile(pos->second.GetCString(), false); 208 new_spec.AppendPathComponent(orig_path + prefix_len); 209 if (new_spec.Exists()) 210 return true; 211 } 212 } 213 } 214 } 215 } 216 new_spec.Clear(); 217 return false; 218 } 219 220 bool PathMappingList::Replace(const ConstString &path, 221 const ConstString &new_path, bool notify) { 222 uint32_t idx = FindIndexForPath(path); 223 if (idx < m_pairs.size()) { 224 ++m_mod_id; 225 m_pairs[idx].second = new_path; 226 if (notify && m_callback) 227 m_callback(*this, m_callback_baton); 228 return true; 229 } 230 return false; 231 } 232 233 bool PathMappingList::Remove(const ConstString &path, bool notify) { 234 iterator pos = FindIteratorForPath(path); 235 if (pos != m_pairs.end()) { 236 ++m_mod_id; 237 m_pairs.erase(pos); 238 if (notify && m_callback) 239 m_callback(*this, m_callback_baton); 240 return true; 241 } 242 return false; 243 } 244 245 PathMappingList::const_iterator 246 PathMappingList::FindIteratorForPath(const ConstString &path) const { 247 const_iterator pos; 248 const_iterator begin = m_pairs.begin(); 249 const_iterator end = m_pairs.end(); 250 251 for (pos = begin; pos != end; ++pos) { 252 if (pos->first == path) 253 break; 254 } 255 return pos; 256 } 257 258 PathMappingList::iterator 259 PathMappingList::FindIteratorForPath(const ConstString &path) { 260 iterator pos; 261 iterator begin = m_pairs.begin(); 262 iterator end = m_pairs.end(); 263 264 for (pos = begin; pos != end; ++pos) { 265 if (pos->first == path) 266 break; 267 } 268 return pos; 269 } 270 271 bool PathMappingList::GetPathsAtIndex(uint32_t idx, ConstString &path, 272 ConstString &new_path) const { 273 if (idx < m_pairs.size()) { 274 path = m_pairs[idx].first; 275 new_path = m_pairs[idx].second; 276 return true; 277 } 278 return false; 279 } 280 281 uint32_t PathMappingList::FindIndexForPath(const ConstString &path) const { 282 const_iterator pos; 283 const_iterator begin = m_pairs.begin(); 284 const_iterator end = m_pairs.end(); 285 286 for (pos = begin; pos != end; ++pos) { 287 if (pos->first == path) 288 return std::distance(begin, pos); 289 } 290 return UINT32_MAX; 291 } 292