1254721Semaste//===-- PathMappingList.cpp -------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste// C Includes
11254721Semaste#include <limits.h>
12254721Semaste#include <string.h>
13254721Semaste
14254721Semaste// C++ Includes
15254721Semaste// Other libraries and framework includes
16254721Semaste// Project includes
17254721Semaste#include "lldb/Core/Error.h"
18254721Semaste#include "lldb/Core/Stream.h"
19254721Semaste#include "lldb/Host/FileSpec.h"
20254721Semaste#include "lldb/Target/PathMappingList.h"
21254721Semaste
22254721Semasteusing namespace lldb;
23254721Semasteusing namespace lldb_private;
24254721Semaste
25254721Semaste//----------------------------------------------------------------------
26254721Semaste// PathMappingList constructor
27254721Semaste//----------------------------------------------------------------------
28254721SemastePathMappingList::PathMappingList () :
29254721Semaste    m_pairs (),
30254721Semaste    m_callback (NULL),
31254721Semaste    m_callback_baton (NULL),
32254721Semaste    m_mod_id (0)
33254721Semaste{
34254721Semaste}
35254721Semaste
36254721SemastePathMappingList::PathMappingList (ChangedCallback callback,
37254721Semaste                                  void *callback_baton) :
38254721Semaste    m_pairs (),
39254721Semaste    m_callback (callback),
40254721Semaste    m_callback_baton (callback_baton),
41254721Semaste    m_mod_id (0)
42254721Semaste{
43254721Semaste}
44254721Semaste
45254721Semaste
46254721SemastePathMappingList::PathMappingList (const PathMappingList &rhs) :
47254721Semaste    m_pairs (rhs.m_pairs),
48254721Semaste    m_callback (NULL),
49254721Semaste    m_callback_baton (NULL),
50254721Semaste    m_mod_id (0)
51254721Semaste{
52254721Semaste
53254721Semaste}
54254721Semaste
55254721Semasteconst PathMappingList &
56254721SemastePathMappingList::operator =(const PathMappingList &rhs)
57254721Semaste{
58254721Semaste    if (this != &rhs)
59254721Semaste    {
60254721Semaste        m_pairs = rhs.m_pairs;
61254721Semaste        m_callback = NULL;
62254721Semaste        m_callback_baton = NULL;
63254721Semaste        m_mod_id = rhs.m_mod_id;
64254721Semaste    }
65254721Semaste    return *this;
66254721Semaste}
67254721Semaste
68254721Semaste
69254721Semaste//----------------------------------------------------------------------
70254721Semaste// Destructor
71254721Semaste//----------------------------------------------------------------------
72254721SemastePathMappingList::~PathMappingList ()
73254721Semaste{
74254721Semaste}
75254721Semaste
76254721Semastevoid
77254721SemastePathMappingList::Append (const ConstString &path,
78254721Semaste                         const ConstString &replacement,
79254721Semaste                         bool notify)
80254721Semaste{
81254721Semaste    ++m_mod_id;
82254721Semaste    m_pairs.push_back(pair(path, replacement));
83254721Semaste    if (notify && m_callback)
84254721Semaste        m_callback (*this, m_callback_baton);
85254721Semaste}
86254721Semaste
87254721Semastevoid
88254721SemastePathMappingList::Append (const PathMappingList &rhs, bool notify)
89254721Semaste{
90254721Semaste    ++m_mod_id;
91254721Semaste    if (!rhs.m_pairs.empty())
92254721Semaste    {
93254721Semaste        const_iterator pos, end = rhs.m_pairs.end();
94254721Semaste        for (pos = rhs.m_pairs.begin(); pos != end; ++pos)
95254721Semaste            m_pairs.push_back(*pos);
96254721Semaste        if (notify && m_callback)
97254721Semaste            m_callback (*this, m_callback_baton);
98254721Semaste    }
99254721Semaste}
100254721Semaste
101254721Semastevoid
102254721SemastePathMappingList::Insert (const ConstString &path,
103254721Semaste                         const ConstString &replacement,
104254721Semaste                         uint32_t index,
105254721Semaste                         bool notify)
106254721Semaste{
107254721Semaste    ++m_mod_id;
108254721Semaste    iterator insert_iter;
109254721Semaste    if (index >= m_pairs.size())
110254721Semaste        insert_iter = m_pairs.end();
111254721Semaste    else
112254721Semaste        insert_iter = m_pairs.begin() + index;
113254721Semaste    m_pairs.insert(insert_iter, pair(path, replacement));
114254721Semaste    if (notify && m_callback)
115254721Semaste        m_callback (*this, m_callback_baton);
116254721Semaste}
117254721Semaste
118254721Semastebool
119254721SemastePathMappingList::Replace (const ConstString &path,
120254721Semaste                          const ConstString &replacement,
121254721Semaste                          uint32_t index,
122254721Semaste                          bool notify)
123254721Semaste{
124254721Semaste    iterator insert_iter;
125254721Semaste    if (index >= m_pairs.size())
126254721Semaste        return false;
127254721Semaste    ++m_mod_id;
128254721Semaste    m_pairs[index] = pair(path, replacement);
129254721Semaste    if (notify && m_callback)
130254721Semaste        m_callback (*this, m_callback_baton);
131254721Semaste    return true;
132254721Semaste}
133254721Semaste
134254721Semastebool
135254721SemastePathMappingList::Remove (off_t index, bool notify)
136254721Semaste{
137254721Semaste    if (index >= m_pairs.size())
138254721Semaste        return false;
139254721Semaste
140254721Semaste    ++m_mod_id;
141254721Semaste    iterator iter = m_pairs.begin() + index;
142254721Semaste    m_pairs.erase(iter);
143254721Semaste    if (notify && m_callback)
144254721Semaste        m_callback (*this, m_callback_baton);
145254721Semaste    return true;
146254721Semaste}
147254721Semaste
148254721Semaste// For clients which do not need the pair index dumped, pass a pair_index >= 0
149254721Semaste// to only dump the indicated pair.
150254721Semastevoid
151254721SemastePathMappingList::Dump (Stream *s, int pair_index)
152254721Semaste{
153254721Semaste    unsigned int numPairs = m_pairs.size();
154254721Semaste
155254721Semaste    if (pair_index < 0)
156254721Semaste    {
157254721Semaste        unsigned int index;
158254721Semaste        for (index = 0; index < numPairs; ++index)
159254721Semaste            s->Printf("[%d] \"%s\" -> \"%s\"\n",
160254721Semaste                      index, m_pairs[index].first.GetCString(), m_pairs[index].second.GetCString());
161254721Semaste    }
162254721Semaste    else
163254721Semaste    {
164254721Semaste        if (pair_index < numPairs)
165254721Semaste            s->Printf("%s -> %s",
166254721Semaste                      m_pairs[pair_index].first.GetCString(), m_pairs[pair_index].second.GetCString());
167254721Semaste    }
168254721Semaste}
169254721Semaste
170254721Semastevoid
171254721SemastePathMappingList::Clear (bool notify)
172254721Semaste{
173254721Semaste    if (!m_pairs.empty())
174254721Semaste        ++m_mod_id;
175254721Semaste    m_pairs.clear();
176254721Semaste    if (notify && m_callback)
177254721Semaste        m_callback (*this, m_callback_baton);
178254721Semaste}
179254721Semaste
180254721Semastebool
181254721SemastePathMappingList::RemapPath (const ConstString &path, ConstString &new_path) const
182254721Semaste{
183254721Semaste    const char *path_cstr = path.GetCString();
184254721Semaste
185254721Semaste    if (!path_cstr)
186254721Semaste        return false;
187254721Semaste
188254721Semaste    const_iterator pos, end = m_pairs.end();
189254721Semaste    for (pos = m_pairs.begin(); pos != end; ++pos)
190254721Semaste    {
191254721Semaste        const size_t prefixLen = pos->first.GetLength();
192254721Semaste
193254721Semaste        if (::strncmp (pos->first.GetCString(), path_cstr, prefixLen) == 0)
194254721Semaste        {
195254721Semaste            std::string new_path_str (pos->second.GetCString());
196254721Semaste            new_path_str.append(path.GetCString() + prefixLen);
197254721Semaste            new_path.SetCString(new_path_str.c_str());
198254721Semaste            return true;
199254721Semaste        }
200254721Semaste    }
201254721Semaste    return false;
202254721Semaste}
203254721Semaste
204254721Semastebool
205254721SemastePathMappingList::RemapPath (const char *path, std::string &new_path) const
206254721Semaste{
207254721Semaste    if (m_pairs.empty() || path == NULL || path[0] == '\0')
208254721Semaste        return false;
209254721Semaste
210254721Semaste    const_iterator pos, end = m_pairs.end();
211254721Semaste    for (pos = m_pairs.begin(); pos != end; ++pos)
212254721Semaste    {
213254721Semaste        const size_t prefix_len = pos->first.GetLength();
214254721Semaste
215254721Semaste        if (::strncmp (pos->first.GetCString(), path, prefix_len) == 0)
216254721Semaste        {
217254721Semaste            new_path = pos->second.GetCString();
218254721Semaste            new_path.append(path + prefix_len);
219254721Semaste            return true;
220254721Semaste        }
221254721Semaste    }
222254721Semaste    return false;
223254721Semaste}
224254721Semaste
225254721Semastebool
226254721SemastePathMappingList::FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const
227254721Semaste{
228254721Semaste    if (!m_pairs.empty())
229254721Semaste    {
230254721Semaste        char orig_path[PATH_MAX];
231254721Semaste        char new_path[PATH_MAX];
232254721Semaste        const size_t orig_path_len = orig_spec.GetPath (orig_path, sizeof(orig_path));
233254721Semaste        if (orig_path_len > 0)
234254721Semaste        {
235254721Semaste            const_iterator pos, end = m_pairs.end();
236254721Semaste            for (pos = m_pairs.begin(); pos != end; ++pos)
237254721Semaste            {
238254721Semaste                const size_t prefix_len = pos->first.GetLength();
239254721Semaste
240254721Semaste                if (orig_path_len >= prefix_len)
241254721Semaste                {
242254721Semaste                    if (::strncmp (pos->first.GetCString(), orig_path, prefix_len) == 0)
243254721Semaste                    {
244254721Semaste                        const size_t new_path_len = snprintf(new_path, sizeof(new_path), "%s/%s", pos->second.GetCString(), orig_path + prefix_len);
245254721Semaste                        if (new_path_len < sizeof(new_path))
246254721Semaste                        {
247254721Semaste                            new_spec.SetFile (new_path, true);
248254721Semaste                            if (new_spec.Exists())
249254721Semaste                                return true;
250254721Semaste                        }
251254721Semaste                    }
252254721Semaste                }
253254721Semaste            }
254254721Semaste        }
255254721Semaste    }
256254721Semaste    new_spec.Clear();
257254721Semaste    return false;
258254721Semaste}
259254721Semaste
260254721Semastebool
261254721SemastePathMappingList::Replace (const ConstString &path, const ConstString &new_path, bool notify)
262254721Semaste{
263254721Semaste    uint32_t idx = FindIndexForPath (path);
264254721Semaste    if (idx < m_pairs.size())
265254721Semaste    {
266254721Semaste        ++m_mod_id;
267254721Semaste        m_pairs[idx].second = new_path;
268254721Semaste        if (notify && m_callback)
269254721Semaste            m_callback (*this, m_callback_baton);
270254721Semaste        return true;
271254721Semaste    }
272254721Semaste    return false;
273254721Semaste}
274254721Semaste
275254721Semastebool
276254721SemastePathMappingList::Remove (const ConstString &path, bool notify)
277254721Semaste{
278254721Semaste    iterator pos = FindIteratorForPath (path);
279254721Semaste    if (pos != m_pairs.end())
280254721Semaste    {
281254721Semaste        ++m_mod_id;
282254721Semaste        m_pairs.erase (pos);
283254721Semaste        if (notify && m_callback)
284254721Semaste            m_callback (*this, m_callback_baton);
285254721Semaste        return true;
286254721Semaste    }
287254721Semaste    return false;
288254721Semaste}
289254721Semaste
290254721SemastePathMappingList::const_iterator
291254721SemastePathMappingList::FindIteratorForPath (const ConstString &path) const
292254721Semaste{
293254721Semaste    const_iterator pos;
294254721Semaste    const_iterator begin = m_pairs.begin();
295254721Semaste    const_iterator end = m_pairs.end();
296254721Semaste
297254721Semaste    for (pos = begin; pos != end; ++pos)
298254721Semaste    {
299254721Semaste        if (pos->first == path)
300254721Semaste            break;
301254721Semaste    }
302254721Semaste    return pos;
303254721Semaste}
304254721Semaste
305254721SemastePathMappingList::iterator
306254721SemastePathMappingList::FindIteratorForPath (const ConstString &path)
307254721Semaste{
308254721Semaste    iterator pos;
309254721Semaste    iterator begin = m_pairs.begin();
310254721Semaste    iterator end = m_pairs.end();
311254721Semaste
312254721Semaste    for (pos = begin; pos != end; ++pos)
313254721Semaste    {
314254721Semaste        if (pos->first == path)
315254721Semaste            break;
316254721Semaste    }
317254721Semaste    return pos;
318254721Semaste}
319254721Semaste
320254721Semastebool
321254721SemastePathMappingList::GetPathsAtIndex (uint32_t idx, ConstString &path, ConstString &new_path) const
322254721Semaste{
323254721Semaste    if (idx < m_pairs.size())
324254721Semaste    {
325254721Semaste        path = m_pairs[idx].first;
326254721Semaste        new_path = m_pairs[idx].second;
327254721Semaste        return true;
328254721Semaste    }
329254721Semaste    return false;
330254721Semaste}
331254721Semaste
332254721Semaste
333254721Semaste
334254721Semasteuint32_t
335254721SemastePathMappingList::FindIndexForPath (const ConstString &path) const
336254721Semaste{
337254721Semaste    const_iterator pos;
338254721Semaste    const_iterator begin = m_pairs.begin();
339254721Semaste    const_iterator end = m_pairs.end();
340254721Semaste
341254721Semaste    for (pos = begin; pos != end; ++pos)
342254721Semaste    {
343254721Semaste        if (pos->first == path)
344254721Semaste            return std::distance (begin, pos);
345254721Semaste    }
346254721Semaste    return UINT32_MAX;
347254721Semaste}
348254721Semaste
349