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