1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2005 - 2006, 2010-2011, 2013 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * Enumerates over a directory tree, non-recursively.
23 * Advantages over CFileFind:
24 * 1) Return values are not broken. An error return from
25 * CFileFind::FindNext() indicates that the *next*
26 * call to CFileFind::FindNext() will fail.
27 * A failure from CSimpleFileFind means *that* call
28 * failed, which is what I'd expect.
29 * 2) Error handling. If you use CFileFind, you are
30 * required to call ::GetLastError() yourself, there
32 * 3) Support for ignoring the "." and ".." directories
34 * 4) No dynamic memory allocation.
36 class CSimpleFileFind
{
39 * Windows FindFirstFile() handle.
44 * Windows error code - if all is well, ERROR_SUCCESS.
45 * At end of directory, ERROR_NO_MORE_FILES.
50 * Flag indicating that FindNextFile() has not yet been
57 * The prefix for files in this directory.
58 * Ends with a "\", unless it's a drive letter only
59 * ("C:" is different from "C:\", and "C:filename" is
62 CString m_sPathPrefix
;
65 * The file data returned by FindFirstFile()/FindNextFile().
67 WIN32_FIND_DATA m_FindFileData
;
73 * \param sPath The path to search in.
74 * \param pPattern The filename pattern - default all files.
76 CSimpleFileFind(const CString
& sPath
, LPCTSTR pPattern
= L
"*.*");
80 * Advance to the next file.
81 * Note that the state of this object is undefined until
82 * this method is called the first time.
84 * \return TRUE if a file was found, FALSE on error or
85 * end-of-directory (use IsError() and IsPastEnd() to
91 * Advance to the next file, ignoring the "." and ".."
92 * pseudo-directories (if seen).
94 * Behaves like FindNextFile(), apart from ignoring "."
97 * \return TRUE if a file was found, FALSE on error or
100 BOOL
FindNextFileNoDots();
103 * Advance to the next file, ignoring all directories.
105 * Behaves like FindNextFile(), apart from ignoring
108 * \return TRUE if a file was found, FALSE on error or
111 BOOL
FindNextFileNoDirectories();
114 * Get the Windows error code.
115 * Only useful when IsError() returns true.
117 * \return Windows error code.
119 inline DWORD
GetError() const
125 * Check if the current file data is valid.
126 * (I.e. there has not been an error and we are not past
127 * the end of the directory).
129 * \return TRUE iff the current file data is valid.
131 inline BOOL
IsValid() const
133 return (m_dError
== ERROR_SUCCESS
);
137 * Check if we have passed the end of the directory.
139 * \return TRUE iff we have passed the end of the directory.
141 inline BOOL
IsPastEnd() const
143 return (m_dError
== ERROR_NO_MORE_FILES
);
147 * Check if there has been an unexpected error - i.e.
148 * any error other than passing the end of the directory.
150 * \return TRUE iff there has been an unexpected error.
152 inline BOOL
IsError() const
154 return (m_dError
!= ERROR_SUCCESS
) && (m_dError
!= ERROR_NO_MORE_FILES
);
158 * Check if the current file is a directory.
160 * \return TRUE iff the current file is a directory.
162 inline bool IsDirectory() const
164 return !!(m_FindFileData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
168 * Get the current file name (excluding the path).
170 * \return the current file name.
172 inline CString
GetFileName() const
174 return m_FindFileData
.cFileName
;
178 * Get the current file name, including the path.
180 * \return the current file path.
182 inline CString
GetFilePath() const
184 return m_sPathPrefix
+ m_FindFileData
.cFileName
;
188 * Returns the last write time of the path
190 FILETIME
GetLastWriteTime() const
192 return m_FindFileData
.ftLastWriteTime
;
194 FILETIME
GetCreateTime() const
196 return m_FindFileData
.ftCreationTime
;
200 * Check if the current file is the "." or ".."
203 * \return TRUE iff the current file is the "." or ".."
206 inline BOOL
IsDots() const
209 && m_FindFileData
.cFileName
[0] == L
'.'
210 && ( (m_FindFileData
.cFileName
[1] == L
'\0')
211 || (m_FindFileData
.cFileName
[1] == L
'.'
212 && m_FindFileData
.cFileName
[2] == L
'\0'));
218 * Enumerates over a directory tree, recursively.
233 * This code is GPL'd.
238 class CDirStackEntry
: public CSimpleFileFind
242 CDirStackEntry(CDirStackEntry
* seNext
, const CString
& sDirName
);
245 CDirStackEntry
* m_seNext
;
248 CDirStackEntry
* m_seStack
;
251 inline void PopStack();
252 inline void PushStack(const CString
& sDirName
);
256 * Iterate through the specified directory and all subdirectories.
257 * It does not matter whether or not the specified directory ends
258 * with a slash. Both relative and absolute paths are allowed,
259 * the results of this iterator will be consistent with the style
260 * passed to this constructor.
262 * @param dirName The directory to search in.
264 CDirFileEnum(const CString
& dirName
);
267 * Destructor. Frees all resources.
272 * Get the next file from this iterator.
274 * \param result On successful return, holds the full path to the found
275 * file. (If this function returns FALSE, the value of
276 * result is unspecified).
277 * \param pbIsDirectory Pointer to a bool variable which will hold
278 * TRUE if the \c result path is a directory, FALSE
279 * if it's a file. Pass nullptr if you don't need that information.
280 * \param bRecurse if the last result was a directory, specifies whether to
281 * recurse into that directory or skip it.
282 * \return TRUE iff a file was found, false at end of the iteration.
284 BOOL
NextFile(CString
&result
, bool* pbIsDirectory
, bool bRecurse
= true);