1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2005 - 2006 - Jon Foster
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
22 * Enumerates over a directory tree, non-recursively.
\r
23 * Advantages over CFileFind:
\r
24 * 1) Return values are not broken. An error return from
\r
25 * CFileFind::FindNext() indicates that the *next*
\r
26 * call to CFileFind::FindNext() will fail.
\r
27 * A failure from CSimpleFileFind means *that* call
\r
28 * failed, which is what I'd expect.
\r
29 * 2) Error handling. If you use CFileFind, you are
\r
30 * required to call ::GetLastError() yourself, there
\r
31 * is no abstraction.
\r
32 * 3) Support for ignoring the "." and ".." directories
\r
34 * 4) No dynamic memory allocation.
\r
36 class CSimpleFileFind {
\r
39 * Windows FindFirstFile() handle.
\r
44 * Windows error code - if all is well, ERROR_SUCCESS.
\r
45 * At end of directory, ERROR_NO_MORE_FILES.
\r
50 * Flag indicating that FindNextFile() has not yet been
\r
57 * The prefix for files in this directory.
\r
58 * Ends with a "\", unless it's a drive letter only
\r
59 * ("C:" is different from "C:\", and "C:filename" is
\r
62 CString m_sPathPrefix;
\r
65 * The file data returned by FindFirstFile()/FindNextFile().
\r
67 WIN32_FIND_DATA m_FindFileData;
\r
74 * \param sPath The path to search in.
\r
75 * \param sPattern The filename pattern - default all files.
\r
77 CSimpleFileFind(const CString &sPath, LPCTSTR pPattern = _T("*.*"));
\r
81 * Advance to the next file.
\r
82 * Note that the state of this object is undefined until
\r
83 * this method is called the first time.
\r
85 * \return TRUE if a file was found, FALSE on error or
\r
86 * end-of-directory (use IsError() and IsPastEnd() to
\r
89 BOOL FindNextFile();
\r
92 * Advance to the next file, ignoring the "." and ".."
\r
93 * pseudo-directories (if seen).
\r
95 * Behaves like FindNextFile(), apart from ignoring "."
\r
98 * \return TRUE if a file was found, FALSE on error or
\r
101 BOOL FindNextFileNoDots();
\r
104 * Advance to the next file, ignoring all directories.
\r
106 * Behaves like FindNextFile(), apart from ignoring
\r
109 * \return TRUE if a file was found, FALSE on error or
\r
110 * end-of-directory.
\r
112 BOOL FindNextFileNoDirectories();
\r
115 * Get the Windows error code.
\r
116 * Only useful when IsError() returns true.
\r
118 * \return Windows error code.
\r
120 inline DWORD GetError() const
\r
126 * Check if the current file data is valid.
\r
127 * (I.e. there has not been an error and we are not past
\r
128 * the end of the directory).
\r
130 * \return TRUE iff the current file data is valid.
\r
132 inline BOOL IsValid() const
\r
134 return (m_dError == ERROR_SUCCESS);
\r
138 * Check if we have passed the end of the directory.
\r
140 * \return TRUE iff we have passed the end of the directory.
\r
142 inline BOOL IsPastEnd() const
\r
144 return (m_dError == ERROR_NO_MORE_FILES);
\r
148 * Check if there has been an unexpected error - i.e.
\r
149 * any error other than passing the end of the directory.
\r
151 * \return TRUE iff there has been an unexpected error.
\r
153 inline BOOL IsError() const
\r
155 return (m_dError != ERROR_SUCCESS)
\r
156 && (m_dError != ERROR_NO_MORE_FILES);
\r
160 * Check if the current file is a directory.
\r
162 * \return TRUE iff the current file is a directory.
\r
164 inline bool IsDirectory() const
\r
166 return !!(m_FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
\r
170 * Get the current file name (excluding the path).
\r
172 * \return the current file name.
\r
174 inline CString GetFileName() const
\r
176 return m_FindFileData.cFileName;
\r
180 * Get the current file name, including the path.
\r
182 * \return the current file path.
\r
184 inline CString GetFilePath() const
\r
186 return m_sPathPrefix + m_FindFileData.cFileName;
\r
190 * Check if the current file is the "." or ".."
\r
191 * pseudo-directory.
\r
193 * \return TRUE iff the current file is the "." or ".."
\r
194 * pseudo-directory.
\r
196 inline BOOL IsDots() const
\r
198 return IsDirectory()
\r
199 && m_FindFileData.cFileName[0] == _T('.')
\r
200 && ( (m_FindFileData.cFileName[1] == 0)
\r
201 || (m_FindFileData.cFileName[1] == _T('.')
\r
202 && m_FindFileData.cFileName[2] == 0) );
\r
208 * Enumerates over a directory tree, recursively.
\r
210 * \par requirements
\r
218 * \date 18-Feb-2004
\r
220 * \author Jon Foster
\r
223 * This code is GPL'd.
\r
229 class CDirStackEntry : public CSimpleFileFind {
\r
231 CDirStackEntry(CDirStackEntry * seNext, const CString& sDirName);
\r
234 CDirStackEntry * m_seNext;
\r
237 CDirStackEntry * m_seStack;
\r
240 inline void PopStack();
\r
241 inline void PushStack(const CString& sDirName);
\r
245 * Iterate through the specified directory and all subdirectories.
\r
246 * It does not matter whether or not the specified directory ends
\r
247 * with a slash. Both relative and absolute paths are allowed,
\r
248 * the results of this iterator will be consistent with the style
\r
249 * passed to this constructor.
\r
251 * @param dirName The directory to search in.
\r
253 CDirFileEnum(const CString& dirName);
\r
256 * Destructor. Frees all resources.
\r
261 * Get the next file from this iterator.
\r
263 * \param result On successful return, holds the full path to the found
\r
264 * file. (If this function returns FALSE, the value of
\r
265 * result is unspecified).
\r
266 * \param pbIsDirectory Pointer to a bool variable which will hold
\r
267 * TRUE if the \c result path is a directory, FALSE
\r
268 * if it's a file. Pass NULL if you don't need that information.
\r
269 * \return TRUE iff a file was found, false at end of the iteration.
\r
271 BOOL NextFile(CString &result, bool* pbIsDirectory);
\r