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(file: std::make_shared<SupportFile>(args: file)); |
36 | } |
37 | void Append(std::shared_ptr<SupportFile> &&file) { |
38 | m_files.push_back(x: 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 | /// \return |
68 | /// The index of the file that matches \a file if it is found, |
69 | /// else UINT32_MAX is returned. |
70 | size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const; |
71 | |
72 | template <class... Args> void EmplaceBack(Args &&...args) { |
73 | m_files.push_back( |
74 | std::make_shared<SupportFile>(std::forward<Args>(args)...)); |
75 | } |
76 | |
77 | protected: |
78 | collection m_files; ///< A collection of FileSpec objects. |
79 | }; |
80 | |
81 | /// \class FileSpecList FileSpecList.h "lldb/Utility/FileSpecList.h" |
82 | /// A file collection class. |
83 | /// |
84 | /// A class that contains a mutable list of FileSpec objects. |
85 | class FileSpecList { |
86 | public: |
87 | typedef std::vector<FileSpec> collection; |
88 | typedef collection::const_iterator const_iterator; |
89 | |
90 | /// Default constructor. |
91 | /// |
92 | /// Initialize this object with an empty file list. |
93 | FileSpecList(); |
94 | |
95 | /// Copy constructor. |
96 | FileSpecList(const FileSpecList &rhs) = default; |
97 | |
98 | /// Move constructor |
99 | FileSpecList(FileSpecList &&rhs) = default; |
100 | |
101 | /// Initialize this object from a vector of FileSpecs |
102 | FileSpecList(std::vector<FileSpec> &&rhs) : m_files(std::move(rhs)) {} |
103 | |
104 | /// Destructor. |
105 | ~FileSpecList(); |
106 | |
107 | /// Assignment operator. |
108 | /// |
109 | /// Replace the file list in this object with the file list from \a rhs. |
110 | /// |
111 | /// \param[in] rhs |
112 | /// A file list object to copy. |
113 | /// |
114 | /// \return |
115 | /// A const reference to this object. |
116 | FileSpecList &operator=(const FileSpecList &rhs) = default; |
117 | |
118 | /// Move-assignment operator. |
119 | FileSpecList &operator=(FileSpecList &&rhs) = default; |
120 | |
121 | /// Append a FileSpec object to the list. |
122 | /// |
123 | /// Appends \a file to the end of the file list. |
124 | /// |
125 | /// \param[in] file |
126 | /// A new file to append to this file list. |
127 | void Append(const FileSpec &file); |
128 | |
129 | /// Append a FileSpec object if unique. |
130 | /// |
131 | /// Appends \a file to the end of the file list if it doesn't already exist |
132 | /// in the file list. |
133 | /// |
134 | /// \param[in] file |
135 | /// A new file to append to this file list. |
136 | /// |
137 | /// \return |
138 | /// \b true if the file was appended, \b false otherwise. |
139 | bool AppendIfUnique(const FileSpec &file); |
140 | |
141 | /// Inserts a new FileSpec into the FileSpecList constructed in-place with |
142 | /// the given arguments. |
143 | /// |
144 | /// \param[in] args |
145 | /// Arguments to create the FileSpec |
146 | template <class... Args> void EmplaceBack(Args &&...args) { |
147 | m_files.emplace_back(std::forward<Args>(args)...); |
148 | } |
149 | |
150 | /// Clears the file list. |
151 | void Clear(); |
152 | |
153 | /// Dumps the file list to the supplied stream pointer "s". |
154 | /// |
155 | /// \param[in] s |
156 | /// The stream that will be used to dump the object description. |
157 | void Dump(Stream *s, const char *separator_cstr = "\n" ) const; |
158 | |
159 | /// Find a file index. |
160 | /// |
161 | /// Find the index of the file in the file spec list that matches \a file |
162 | /// starting \a idx entries into the file spec list. |
163 | /// |
164 | /// \param[in] idx |
165 | /// An index into the file list. |
166 | /// |
167 | /// \param[in] file |
168 | /// The file specification to search for. |
169 | /// |
170 | /// \param[in] full |
171 | /// Should FileSpec::Equal be called with "full" true or false. |
172 | /// |
173 | /// \return |
174 | /// The index of the file that matches \a file if it is found, |
175 | /// else UINT32_MAX is returned. |
176 | size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; |
177 | |
178 | /// Get file at index. |
179 | /// |
180 | /// Gets a file from the file list. If \a idx is not a valid index, an empty |
181 | /// FileSpec object will be returned. The file objects that are returned can |
182 | /// be tested using FileSpec::operator void*(). |
183 | /// |
184 | /// \param[in] idx |
185 | /// An index into the file list. |
186 | /// |
187 | /// \return |
188 | /// A copy of the FileSpec object at index \a idx. If \a idx |
189 | /// is out of range, then an empty FileSpec object will be |
190 | /// returned. |
191 | const FileSpec &GetFileSpecAtIndex(size_t idx) const; |
192 | |
193 | /// Get the memory cost of this object. |
194 | /// |
195 | /// Return the size in bytes that this object takes in memory. This returns |
196 | /// the size in bytes of this object, not any shared string values it may |
197 | /// refer to. |
198 | /// |
199 | /// \return |
200 | /// The number of bytes that this object occupies in memory. |
201 | size_t MemorySize() const; |
202 | |
203 | bool IsEmpty() const { return m_files.empty(); } |
204 | |
205 | /// Get the number of files in the file list. |
206 | /// |
207 | /// \return |
208 | /// The number of files in the file spec list. |
209 | size_t GetSize() const; |
210 | |
211 | bool Insert(size_t idx, const FileSpec &file) { |
212 | if (idx < m_files.size()) { |
213 | m_files.insert(position: m_files.begin() + idx, x: file); |
214 | return true; |
215 | } else if (idx == m_files.size()) { |
216 | m_files.push_back(x: file); |
217 | return true; |
218 | } |
219 | return false; |
220 | } |
221 | |
222 | bool Replace(size_t idx, const FileSpec &file) { |
223 | if (idx < m_files.size()) { |
224 | m_files[idx] = file; |
225 | return true; |
226 | } |
227 | return false; |
228 | } |
229 | |
230 | bool Remove(size_t idx) { |
231 | if (idx < m_files.size()) { |
232 | m_files.erase(position: m_files.begin() + idx); |
233 | return true; |
234 | } |
235 | return false; |
236 | } |
237 | |
238 | const_iterator begin() const { return m_files.begin(); } |
239 | const_iterator end() const { return m_files.end(); } |
240 | |
241 | protected: |
242 | collection m_files; ///< A collection of FileSpec objects. |
243 | }; |
244 | |
245 | } // namespace lldb_private |
246 | |
247 | #endif // LLDB_CORE_FILESPECLIST_H |
248 | |