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/Core/Stream.h"
19 
20 using namespace lldb_private;
21 using namespace std;
22 
23 FileSpecList::FileSpecList() :
24     m_files()
25 {
26 }
27 
28 FileSpecList::FileSpecList(const FileSpecList& rhs) = default;
29 
30 FileSpecList::~FileSpecList() = default;
31 
32 //------------------------------------------------------------------
33 // Assignment operator
34 //------------------------------------------------------------------
35 const FileSpecList&
36 FileSpecList::operator= (const FileSpecList& rhs)
37 {
38     if (this != &rhs)
39         m_files = rhs.m_files;
40     return *this;
41 }
42 
43 //------------------------------------------------------------------
44 // Append the "file_spec" to the end of the file spec list.
45 //------------------------------------------------------------------
46 void
47 FileSpecList::Append(const FileSpec &file_spec)
48 {
49     m_files.push_back(file_spec);
50 }
51 
52 //------------------------------------------------------------------
53 // Only append the "file_spec" if this list doesn't already contain
54 // it.
55 //
56 // Returns true if "file_spec" was added, false if this list already
57 // contained a copy of "file_spec".
58 //------------------------------------------------------------------
59 bool
60 FileSpecList::AppendIfUnique(const FileSpec &file_spec)
61 {
62     collection::iterator pos, end = m_files.end();
63     if (find(m_files.begin(), end, file_spec) == end)
64     {
65         m_files.push_back(file_spec);
66         return true;
67     }
68     return false;
69 }
70 
71 //------------------------------------------------------------------
72 // Clears the file list.
73 //------------------------------------------------------------------
74 void
75 FileSpecList::Clear()
76 {
77     m_files.clear();
78 }
79 
80 //------------------------------------------------------------------
81 // Dumps the file list to the supplied stream pointer "s".
82 //------------------------------------------------------------------
83 void
84 FileSpecList::Dump(Stream *s, const char *separator_cstr) const
85 {
86     collection::const_iterator pos, end = m_files.end();
87     for (pos = m_files.begin(); pos != end; ++pos)
88     {
89         pos->Dump(s);
90         if (separator_cstr && ((pos + 1) != end))
91             s->PutCString(separator_cstr);
92     }
93 }
94 
95 //------------------------------------------------------------------
96 // Find the index of the file in the file spec list that matches
97 // "file_spec" starting "start_idx" entries into the file spec list.
98 //
99 // Returns the valid index of the file that matches "file_spec" if
100 // it is found, else std::numeric_limits<uint32_t>::max() is returned.
101 //------------------------------------------------------------------
102 size_t
103 FileSpecList::FindFileIndex (size_t start_idx, const FileSpec &file_spec, bool full, bool remove_dots) const
104 {
105     const size_t num_files = m_files.size();
106 
107     // When looking for files, we will compare only the filename if the
108     // FILE_SPEC argument is empty
109     bool compare_filename_only = file_spec.GetDirectory().IsEmpty();
110 
111     for (size_t idx = start_idx; idx < num_files; ++idx)
112     {
113         if (compare_filename_only)
114         {
115             if (ConstString::Equals(m_files[idx].GetFilename(), file_spec.GetFilename(),
116                                     file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
117                 return idx;
118         }
119         else
120         {
121             if (FileSpec::Equal (m_files[idx], file_spec, full, remove_dots))
122                 return idx;
123         }
124     }
125 
126     // We didn't find the file, return an invalid index
127     return UINT32_MAX;
128 }
129 
130 //------------------------------------------------------------------
131 // Returns the FileSpec object at index "idx". If "idx" is out of
132 // range, then an empty FileSpec object will be returned.
133 //------------------------------------------------------------------
134 const FileSpec &
135 FileSpecList::GetFileSpecAtIndex(size_t idx) const
136 {
137     if (idx < m_files.size())
138         return m_files[idx];
139     static FileSpec g_empty_file_spec;
140     return g_empty_file_spec;
141 }
142 
143 const FileSpec *
144 FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const
145 {
146     if (idx < m_files.size())
147         return &m_files[idx];
148     return nullptr;
149 }
150 
151 //------------------------------------------------------------------
152 // Return the size in bytes that this object takes in memory. This
153 // returns the size in bytes of this object's member variables and
154 // any FileSpec objects its member variables contain, the result
155 // doesn't not include the string values for the directories any
156 // filenames as those are in shared string pools.
157 //------------------------------------------------------------------
158 size_t
159 FileSpecList::MemorySize () const
160 {
161     size_t mem_size = sizeof(FileSpecList);
162     collection::const_iterator pos, end = m_files.end();
163     for (pos = m_files.begin(); pos != end; ++pos)
164     {
165         mem_size += pos->MemorySize();
166     }
167 
168     return mem_size;
169 }
170 
171 //------------------------------------------------------------------
172 // Return the number of files in the file spec list.
173 //------------------------------------------------------------------
174 size_t
175 FileSpecList::GetSize() const
176 {
177     return m_files.size();
178 }
179 
180 size_t
181 FileSpecList::GetFilesMatchingPartialPath (const char *path, bool dir_okay, FileSpecList &matches)
182 {
183 #if 0  // FIXME: Just sketching...
184     matches.Clear();
185     FileSpec path_spec = FileSpec (path);
186     if (path_spec.Exists ())
187     {
188         FileSpec::FileType type = path_spec.GetFileType();
189         if (type == FileSpec::eFileTypeSymbolicLink)
190             // Shouldn't there be a Resolve on a file spec that real-path's it?
191         {
192         }
193 
194         if (type == FileSpec::eFileTypeRegular
195             || (type == FileSpec::eFileTypeDirectory && dir_okay))
196         {
197             matches.Append (path_spec);
198             return 1;
199         }
200         else if (type == FileSpec::eFileTypeDirectory)
201         {
202             // Fill the match list with all the files in the directory:
203         }
204         else
205         {
206             return 0;
207         }
208     }
209     else
210     {
211         ConstString dir_name = path_spec.GetDirectory();
212         ConstString file_name = GetFilename();
213         if (dir_name == nullptr)
214         {
215             // Match files in the CWD.
216         }
217         else
218         {
219             // Match files in the given directory:
220         }
221     }
222 #endif
223     return 0;
224 }
225