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 { 33 } 34 35 PathMappingList::PathMappingList 36 ( 37 ChangedCallback callback, 38 void *callback_baton 39 ) : 40 m_pairs (), 41 m_callback (callback), 42 m_callback_baton (callback_baton) 43 { 44 } 45 46 47 PathMappingList::PathMappingList (const PathMappingList &rhs) : 48 m_pairs (rhs.m_pairs), 49 m_callback (NULL), 50 m_callback_baton (NULL) 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 } 64 return *this; 65 } 66 67 68 //---------------------------------------------------------------------- 69 // Destructor 70 //---------------------------------------------------------------------- 71 PathMappingList::~PathMappingList () 72 { 73 } 74 75 void 76 PathMappingList::Append (const ConstString &path, 77 const ConstString &replacement, 78 bool notify) 79 { 80 m_pairs.push_back(pair(path, replacement)); 81 if (notify && m_callback) 82 m_callback (*this, m_callback_baton); 83 } 84 85 void 86 PathMappingList::Append (const PathMappingList &rhs, bool notify) 87 { 88 if (!rhs.m_pairs.empty()) 89 { 90 const_iterator pos, end = rhs.m_pairs.end(); 91 for (pos = rhs.m_pairs.begin(); pos != end; ++pos) 92 m_pairs.push_back(*pos); 93 if (notify && m_callback) 94 m_callback (*this, m_callback_baton); 95 } 96 } 97 98 void 99 PathMappingList::Insert (const ConstString &path, 100 const ConstString &replacement, 101 uint32_t index, 102 bool notify) 103 { 104 iterator insert_iter; 105 if (index >= m_pairs.size()) 106 insert_iter = m_pairs.end(); 107 else 108 insert_iter = m_pairs.begin() + index; 109 m_pairs.insert(insert_iter, pair(path, replacement)); 110 if (notify && m_callback) 111 m_callback (*this, m_callback_baton); 112 } 113 114 bool 115 PathMappingList::Replace (const ConstString &path, 116 const ConstString &replacement, 117 uint32_t index, 118 bool notify) 119 { 120 iterator insert_iter; 121 if (index >= m_pairs.size()) 122 return false; 123 m_pairs[index] = pair(path, replacement); 124 if (notify && m_callback) 125 m_callback (*this, m_callback_baton); 126 return true; 127 } 128 129 bool 130 PathMappingList::Remove (off_t index, bool notify) 131 { 132 if (index >= m_pairs.size()) 133 return false; 134 135 iterator iter = m_pairs.begin() + index; 136 m_pairs.erase(iter); 137 if (notify && m_callback) 138 m_callback (*this, m_callback_baton); 139 return true; 140 } 141 142 // For clients which do not need the pair index dumped, pass a pair_index >= 0 143 // to only dump the indicated pair. 144 void 145 PathMappingList::Dump (Stream *s, int pair_index) 146 { 147 unsigned int numPairs = m_pairs.size(); 148 149 if (pair_index < 0) 150 { 151 unsigned int index; 152 for (index = 0; index < numPairs; ++index) 153 s->Printf("[%d] \"%s\" -> \"%s\"\n", 154 index, m_pairs[index].first.GetCString(), m_pairs[index].second.GetCString()); 155 } 156 else 157 { 158 if (pair_index < numPairs) 159 s->Printf("%s -> %s", 160 m_pairs[pair_index].first.GetCString(), m_pairs[pair_index].second.GetCString()); 161 } 162 } 163 164 void 165 PathMappingList::Clear (bool notify) 166 { 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 == NULL || 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_pairs[idx].second = new_path; 259 if (notify && m_callback) 260 m_callback (*this, m_callback_baton); 261 return true; 262 } 263 return false; 264 } 265 266 bool 267 PathMappingList::Remove (const ConstString &path, bool notify) 268 { 269 iterator pos = FindIteratorForPath (path); 270 if (pos != m_pairs.end()) 271 { 272 m_pairs.erase (pos); 273 if (notify && m_callback) 274 m_callback (*this, m_callback_baton); 275 return true; 276 } 277 return false; 278 } 279 280 PathMappingList::const_iterator 281 PathMappingList::FindIteratorForPath (const ConstString &path) const 282 { 283 const_iterator pos; 284 const_iterator begin = m_pairs.begin(); 285 const_iterator end = m_pairs.end(); 286 287 for (pos = begin; pos != end; ++pos) 288 { 289 if (pos->first == path) 290 break; 291 } 292 return pos; 293 } 294 295 PathMappingList::iterator 296 PathMappingList::FindIteratorForPath (const ConstString &path) 297 { 298 iterator pos; 299 iterator begin = m_pairs.begin(); 300 iterator end = m_pairs.end(); 301 302 for (pos = begin; pos != end; ++pos) 303 { 304 if (pos->first == path) 305 break; 306 } 307 return pos; 308 } 309 310 bool 311 PathMappingList::GetPathsAtIndex (uint32_t idx, ConstString &path, ConstString &new_path) const 312 { 313 if (idx < m_pairs.size()) 314 { 315 path = m_pairs[idx].first; 316 new_path = m_pairs[idx].second; 317 return true; 318 } 319 return false; 320 } 321 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 339