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:
SupportFileList()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;
begin()31   const_iterator begin() const { return m_files.begin(); }
end()32   const_iterator end() const { return m_files.end(); }
33 
Append(const FileSpec & file)34   void Append(const FileSpec &file) {
35     return Append(std::make_shared<SupportFile>(file));
36   }
Append(std::shared_ptr<SupportFile> && file)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);
GetSize()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 
EmplaceBack(Args &&...args)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
FileSpecList(std::vector<FileSpec> && rhs)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
EmplaceBack(Args &&...args)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 
IsEmpty()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 
Insert(size_t idx,const FileSpec & file)211   bool Insert(size_t idx, const FileSpec &file) {
212     if (idx < m_files.size()) {
213       m_files.insert(m_files.begin() + idx, file);
214       return true;
215     } else if (idx == m_files.size()) {
216       m_files.push_back(file);
217       return true;
218     }
219     return false;
220   }
221 
Replace(size_t idx,const FileSpec & file)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 
Remove(size_t idx)230   bool Remove(size_t idx) {
231     if (idx < m_files.size()) {
232       m_files.erase(m_files.begin() + idx);
233       return true;
234     }
235     return false;
236   }
237 
begin()238   const_iterator begin() const { return m_files.begin(); }
end()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