xref: /llvm-project/lldb/include/lldb/Utility/FileSpecList.h (revision 47721d46187f89c12a13d07b5857496301cf5d6e)
1 //===-- FileSpecList.h ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_CORE_FILESPECLIST_H
10 #define LLDB_CORE_FILESPECLIST_H
11 
12 #include "lldb/Utility/FileSpec.h"
13 #include "lldb/Utility/SupportFile.h"
14 #include "lldb/lldb-forward.h"
15 
16 #include <cstddef>
17 #include <vector>
18 
19 namespace lldb_private {
20 class Stream;
21 
22 /// A list of support files for a CompileUnit.
23 class SupportFileList {
24 public:
25   SupportFileList(){};
26   SupportFileList(const SupportFileList &) = delete;
27   SupportFileList(SupportFileList &&other) = default;
28 
29   typedef std::vector<std::shared_ptr<SupportFile>> collection;
30   typedef collection::const_iterator const_iterator;
31   const_iterator begin() const { return m_files.begin(); }
32   const_iterator end() const { return m_files.end(); }
33 
34   void Append(const FileSpec &file) {
35     return Append(std::make_shared<SupportFile>(file));
36   }
37   void Append(std::shared_ptr<SupportFile> &&file) {
38     m_files.push_back(std::move(file));
39   }
40   // FIXME: Only used by SymbolFilePDB. Replace with a DenseSet at call site.
41   bool AppendIfUnique(const FileSpec &file);
42   size_t GetSize() const { return m_files.size(); }
43   const FileSpec &GetFileSpecAtIndex(size_t idx) const;
44   lldb::SupportFileSP GetSupportFileAtIndex(size_t idx) const;
45   size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const;
46   /// Find a compatible file index.
47   ///
48   /// Find the index of a compatible file in the file spec list that matches \a
49   /// file starting \a idx entries into the file spec list. A file is considered
50   /// compatible if:
51   /// - The file matches exactly (only filename if \a file has no directory)
52   /// - If \a file is relative and any file in the list has this same suffix
53   /// - If any file in the list is relative and the relative path is a suffix
54   ///   of \a file
55   ///
56   /// This is used to implement better matching for setting breakpoints in
57   /// source files where an IDE might specify a full path when setting the
58   /// breakpoint and debug info contains relative paths, if a user specifies
59   /// a relative path when setting a breakpoint.
60   ///
61   /// \param[in] idx
62   ///     An index into the file list.
63   ///
64   /// \param[in] file
65   ///     The file specification to search for.
66   ///
67   /// \param[in] realpath_prefixes
68   ///     Paths that start with one of the prefixes in this list will be
69   ///     realpath'ed to resolve any symlinks.
70   ///
71   /// \return
72   ///     The index of the file that matches \a file if it is found,
73   ///     else UINT32_MAX is returned.
74   size_t
75   FindCompatibleIndex(size_t idx, const FileSpec &file,
76                       RealpathPrefixes *realpath_prefixes = nullptr) const;
77 
78   template <class... Args> void EmplaceBack(Args &&...args) {
79     m_files.push_back(
80         std::make_shared<SupportFile>(std::forward<Args>(args)...));
81   }
82 
83 protected:
84   collection m_files; ///< A collection of FileSpec objects.
85 };
86 
87 /// \class FileSpecList FileSpecList.h "lldb/Utility/FileSpecList.h"
88 /// A file collection class.
89 ///
90 /// A class that contains a mutable list of FileSpec objects.
91 class FileSpecList {
92 public:
93   typedef std::vector<FileSpec> collection;
94   typedef collection::const_iterator const_iterator;
95 
96   /// Default constructor.
97   ///
98   /// Initialize this object with an empty file list.
99   FileSpecList();
100 
101   /// Copy constructor.
102   FileSpecList(const FileSpecList &rhs) = default;
103 
104   /// Move constructor
105   FileSpecList(FileSpecList &&rhs) = default;
106 
107   /// Initialize this object from a vector of FileSpecs
108   FileSpecList(std::vector<FileSpec> &&rhs) : m_files(std::move(rhs)) {}
109 
110   /// Destructor.
111   ~FileSpecList();
112 
113   /// Assignment operator.
114   ///
115   /// Replace the file list in this object with the file list from \a rhs.
116   ///
117   /// \param[in] rhs
118   ///     A file list object to copy.
119   ///
120   /// \return
121   ///     A const reference to this object.
122   FileSpecList &operator=(const FileSpecList &rhs) = default;
123 
124   /// Move-assignment operator.
125   FileSpecList &operator=(FileSpecList &&rhs) = default;
126 
127   /// Append a FileSpec object to the list.
128   ///
129   /// Appends \a file to the end of the file list.
130   ///
131   /// \param[in] file
132   ///     A new file to append to this file list.
133   void Append(const FileSpec &file);
134 
135   /// Append a FileSpec object if unique.
136   ///
137   /// Appends \a file to the end of the file list if it doesn't already exist
138   /// in the file list.
139   ///
140   /// \param[in] file
141   ///     A new file to append to this file list.
142   ///
143   /// \return
144   ///     \b true if the file was appended, \b false otherwise.
145   bool AppendIfUnique(const FileSpec &file);
146 
147   /// Inserts a new FileSpec into the FileSpecList constructed in-place with
148   /// the given arguments.
149   ///
150   /// \param[in] args
151   ///     Arguments to create the FileSpec
152   template <class... Args> void EmplaceBack(Args &&...args) {
153     m_files.emplace_back(std::forward<Args>(args)...);
154   }
155 
156   /// Clears the file list.
157   void Clear();
158 
159   /// Dumps the file list to the supplied stream pointer "s".
160   ///
161   /// \param[in] s
162   ///     The stream that will be used to dump the object description.
163   void Dump(Stream *s, const char *separator_cstr = "\n") const;
164 
165   /// Find a file index.
166   ///
167   /// Find the index of the file in the file spec list that matches \a file
168   /// starting \a idx entries into the file spec list.
169   ///
170   /// \param[in] idx
171   ///     An index into the file list.
172   ///
173   /// \param[in] file
174   ///     The file specification to search for.
175   ///
176   /// \param[in] full
177   ///     Should FileSpec::Equal be called with "full" true or false.
178   ///
179   /// \return
180   ///     The index of the file that matches \a file if it is found,
181   ///     else UINT32_MAX is returned.
182   size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const;
183 
184   /// Get file at index.
185   ///
186   /// Gets a file from the file list. If \a idx is not a valid index, an empty
187   /// FileSpec object will be returned. The file objects that are returned can
188   /// be tested using FileSpec::operator void*().
189   ///
190   /// \param[in] idx
191   ///     An index into the file list.
192   ///
193   /// \return
194   ///     A copy of the FileSpec object at index \a idx. If \a idx
195   ///     is out of range, then an empty FileSpec object will be
196   ///     returned.
197   const FileSpec &GetFileSpecAtIndex(size_t idx) const;
198 
199   /// Get the memory cost of this object.
200   ///
201   /// Return the size in bytes that this object takes in memory. This returns
202   /// the size in bytes of this object, not any shared string values it may
203   /// refer to.
204   ///
205   /// \return
206   ///     The number of bytes that this object occupies in memory.
207   size_t MemorySize() const;
208 
209   bool IsEmpty() const { return m_files.empty(); }
210 
211   /// Get the number of files in the file list.
212   ///
213   /// \return
214   ///     The number of files in the file spec list.
215   size_t GetSize() const;
216 
217   bool Insert(size_t idx, const FileSpec &file) {
218     if (idx < m_files.size()) {
219       m_files.insert(m_files.begin() + idx, file);
220       return true;
221     } else if (idx == m_files.size()) {
222       m_files.push_back(file);
223       return true;
224     }
225     return false;
226   }
227 
228   bool Replace(size_t idx, const FileSpec &file) {
229     if (idx < m_files.size()) {
230       m_files[idx] = file;
231       return true;
232     }
233     return false;
234   }
235 
236   bool Remove(size_t idx) {
237     if (idx < m_files.size()) {
238       m_files.erase(m_files.begin() + idx);
239       return true;
240     }
241     return false;
242   }
243 
244   const_iterator begin() const { return m_files.begin(); }
245   const_iterator end() const { return m_files.end(); }
246 
247   llvm::iterator_range<const_iterator> files() const {
248     return llvm::make_range(begin(), end());
249   }
250 
251 protected:
252   collection m_files; ///< A collection of FileSpec objects.
253 };
254 
255 } // namespace lldb_private
256 
257 #endif // LLDB_CORE_FILESPECLIST_H
258