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