1 //===-- FileSpecList.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/FileSpecList.h"
11 
12 // C Includes
13 // C++ Includes
14 #include <algorithm>
15 
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Utility/Stream.h"
19 #include "llvm/Support/FileSystem.h"
20 
21 using namespace lldb_private;
22 using namespace std;
23 
24 FileSpecList::FileSpecList() : m_files() {}
25 
26 FileSpecList::FileSpecList(const FileSpecList &rhs) = default;
27 
28 FileSpecList::~FileSpecList() = default;
29 
30 //------------------------------------------------------------------
31 // Assignment operator
32 //------------------------------------------------------------------
33 const FileSpecList &FileSpecList::operator=(const FileSpecList &rhs) {
34   if (this != &rhs)
35     m_files = rhs.m_files;
36   return *this;
37 }
38 
39 //------------------------------------------------------------------
40 // Append the "file_spec" to the end of the file spec list.
41 //------------------------------------------------------------------
42 void FileSpecList::Append(const FileSpec &file_spec) {
43   m_files.push_back(file_spec);
44 }
45 
46 //------------------------------------------------------------------
47 // Only append the "file_spec" if this list doesn't already contain
48 // it.
49 //
50 // Returns true if "file_spec" was added, false if this list already
51 // contained a copy of "file_spec".
52 //------------------------------------------------------------------
53 bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) {
54   collection::iterator pos, end = m_files.end();
55   if (find(m_files.begin(), end, file_spec) == end) {
56     m_files.push_back(file_spec);
57     return true;
58   }
59   return false;
60 }
61 
62 //------------------------------------------------------------------
63 // Clears the file list.
64 //------------------------------------------------------------------
65 void FileSpecList::Clear() { m_files.clear(); }
66 
67 //------------------------------------------------------------------
68 // Dumps the file list to the supplied stream pointer "s".
69 //------------------------------------------------------------------
70 void FileSpecList::Dump(Stream *s, const char *separator_cstr) const {
71   collection::const_iterator pos, end = m_files.end();
72   for (pos = m_files.begin(); pos != end; ++pos) {
73     pos->Dump(s);
74     if (separator_cstr && ((pos + 1) != end))
75       s->PutCString(separator_cstr);
76   }
77 }
78 
79 //------------------------------------------------------------------
80 // Find the index of the file in the file spec list that matches
81 // "file_spec" starting "start_idx" entries into the file spec list.
82 //
83 // Returns the valid index of the file that matches "file_spec" if
84 // it is found, else std::numeric_limits<uint32_t>::max() is returned.
85 //------------------------------------------------------------------
86 size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
87                                    bool full, bool remove_dots) const {
88   const size_t num_files = m_files.size();
89 
90   // When looking for files, we will compare only the filename if the
91   // FILE_SPEC argument is empty
92   bool compare_filename_only = file_spec.GetDirectory().IsEmpty();
93 
94   for (size_t idx = start_idx; idx < num_files; ++idx) {
95     if (compare_filename_only) {
96       if (ConstString::Equals(
97               m_files[idx].GetFilename(), file_spec.GetFilename(),
98               file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
99         return idx;
100     } else {
101       if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots))
102         return idx;
103     }
104   }
105 
106   // We didn't find the file, return an invalid index
107   return UINT32_MAX;
108 }
109 
110 //------------------------------------------------------------------
111 // Returns the FileSpec object at index "idx". If "idx" is out of
112 // range, then an empty FileSpec object will be returned.
113 //------------------------------------------------------------------
114 const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const {
115   if (idx < m_files.size())
116     return m_files[idx];
117   static FileSpec g_empty_file_spec;
118   return g_empty_file_spec;
119 }
120 
121 const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const {
122   if (idx < m_files.size())
123     return &m_files[idx];
124   return nullptr;
125 }
126 
127 //------------------------------------------------------------------
128 // Return the size in bytes that this object takes in memory. This
129 // returns the size in bytes of this object's member variables and
130 // any FileSpec objects its member variables contain, the result
131 // doesn't not include the string values for the directories any
132 // filenames as those are in shared string pools.
133 //------------------------------------------------------------------
134 size_t FileSpecList::MemorySize() const {
135   size_t mem_size = sizeof(FileSpecList);
136   collection::const_iterator pos, end = m_files.end();
137   for (pos = m_files.begin(); pos != end; ++pos) {
138     mem_size += pos->MemorySize();
139   }
140 
141   return mem_size;
142 }
143 
144 //------------------------------------------------------------------
145 // Return the number of files in the file spec list.
146 //------------------------------------------------------------------
147 size_t FileSpecList::GetSize() const { return m_files.size(); }
148 
149 size_t FileSpecList::GetFilesMatchingPartialPath(const char *path,
150                                                  bool dir_okay,
151                                                  FileSpecList &matches) {
152 #if 0 // FIXME: Just sketching...
153     matches.Clear();
154     using namespace llvm::sys::fs;
155     file_status stats;
156     if (status(path, stats, false))
157       return 0;
158     if (exists(stats)) {
159       if (is_symlink_file(stats)) {
160         // Shouldn't there be a method that realpath's a file?
161       }
162       if (is_regular_file(stats) || (is_directory(stats) && dir_okay)) {
163         matches.Append(FileSpec(path));
164         return 1;
165       } else if (is_directory(stats)) {
166         // Fill the match list with all the files in the directory:
167       } else {
168         return 0;
169       }
170     } else {
171         ConstString dir_name = path_spec.GetDirectory();
172         ConstString file_name = GetFilename();
173         if (dir_name == nullptr)
174         {
175             // Match files in the CWD.
176         }
177         else
178         {
179             // Match files in the given directory:
180         }
181     }
182 #endif
183   return 0;
184 }
185