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