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