Fixed issue #1619: TortoiseGitMerge: Ribbon UI/toolbars can be toggled
[TortoiseGit.git] / src / Utils / DirFileEnum.h
bloba6297220932c3735c3219d9e6b2edc769bc2e30f
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2005 - 2006, 2010-2011, 2013 - TortoiseSVN
4 // Copyright (C) 2013 - TortoiseGit
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #pragma once
21 /**
22 * \ingroup Utils
23 * Enumerates over a directory tree, non-recursively.
24 * Advantages over CFileFind:
25 * 1) Return values are not broken. An error return from
26 * CFileFind::FindNext() indicates that the *next*
27 * call to CFileFind::FindNext() will fail.
28 * A failure from CSimpleFileFind means *that* call
29 * failed, which is what I'd expect.
30 * 2) Error handling. If you use CFileFind, you are
31 * required to call ::GetLastError() yourself, there
32 * is no abstraction.
33 * 3) Support for ignoring the "." and ".." directories
34 * automatically.
35 * 4) No dynamic memory allocation.
37 class CSimpleFileFind {
38 private:
39 /**
40 * Windows FindFirstFile() handle.
42 HANDLE m_hFindFile;
44 /**
45 * Windows error code - if all is well, ERROR_SUCCESS.
46 * At end of directory, ERROR_NO_MORE_FILES.
48 DWORD m_dError;
50 /**
51 * Flag indicating that FindNextFile() has not yet been
52 * called.
54 BOOL m_bFirst;
56 protected:
57 /**
58 * The prefix for files in this directory.
59 * Ends with a "\", unless it's a drive letter only
60 * ("C:" is different from "C:\", and "C:filename" is
61 * legal anyway.)
63 CString m_sPathPrefix;
65 /**
66 * The file data returned by FindFirstFile()/FindNextFile().
68 WIN32_FIND_DATA m_FindFileData;
70 public:
72 /**
73 * Constructor.
75 * \param sPath The path to search in.
76 * \param pPattern The filename pattern - default all files.
78 CSimpleFileFind(const CString &sPath, LPCTSTR pPattern = _T("*.*"));
79 ~CSimpleFileFind();
81 /**
82 * Advance to the next file.
83 * Note that the state of this object is undefined until
84 * this method is called the first time.
86 * \return TRUE if a file was found, FALSE on error or
87 * end-of-directory (use IsError() and IsPastEnd() to
88 * disambiguate).
90 BOOL FindNextFile();
92 /**
93 * Advance to the next file, ignoring the "." and ".."
94 * pseudo-directories (if seen).
96 * Behaves like FindNextFile(), apart from ignoring "."
97 * and "..".
99 * \return TRUE if a file was found, FALSE on error or
100 * end-of-directory.
102 BOOL FindNextFileNoDots();
105 * Advance to the next file, ignoring all directories.
107 * Behaves like FindNextFile(), apart from ignoring
108 * directories.
110 * \return TRUE if a file was found, FALSE on error or
111 * end-of-directory.
113 BOOL FindNextFileNoDirectories();
116 * Get the Windows error code.
117 * Only useful when IsError() returns true.
119 * \return Windows error code.
121 inline DWORD GetError() const
123 return m_dError;
127 * Check if the current file data is valid.
128 * (I.e. there has not been an error and we are not past
129 * the end of the directory).
131 * \return TRUE iff the current file data is valid.
133 inline BOOL IsValid() const
135 return (m_dError == ERROR_SUCCESS);
139 * Check if we have passed the end of the directory.
141 * \return TRUE iff we have passed the end of the directory.
143 inline BOOL IsPastEnd() const
145 return (m_dError == ERROR_NO_MORE_FILES);
149 * Check if there has been an unexpected error - i.e.
150 * any error other than passing the end of the directory.
152 * \return TRUE iff there has been an unexpected error.
154 inline BOOL IsError() const
156 return (m_dError != ERROR_SUCCESS)
157 && (m_dError != ERROR_NO_MORE_FILES);
161 * Check if the current file is a directory.
163 * \return TRUE iff the current file is a directory.
165 inline bool IsDirectory() const
167 return !!(m_FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
171 * Get the current file name (excluding the path).
173 * \return the current file name.
175 inline CString GetFileName() const
177 return m_FindFileData.cFileName;
181 * Get the current file name, including the path.
183 * \return the current file path.
185 inline CString GetFilePath() const
187 return m_sPathPrefix + m_FindFileData.cFileName;
190 UINT64 GetSize() const
192 return ((UINT64)m_FindFileData.nFileSizeHigh << 32) | m_FindFileData.nFileSizeLow;
196 * Returns the last write time of the path
198 FILETIME GetLastWriteTime() const
200 return m_FindFileData.ftLastWriteTime;
202 FILETIME GetCreateTime() const
204 return m_FindFileData.ftCreationTime;
208 * Check if the current file is the "." or ".."
209 * pseudo-directory.
211 * \return TRUE iff the current file is the "." or ".."
212 * pseudo-directory.
214 inline BOOL IsDots() const
216 return IsDirectory()
217 && m_FindFileData.cFileName[0] == _T('.')
218 && ( (m_FindFileData.cFileName[1] == 0)
219 || (m_FindFileData.cFileName[1] == _T('.')
220 && m_FindFileData.cFileName[2] == 0) );
225 * \ingroup Utils
226 * Enumerates over a directory tree, recursively.
228 * \par requirements
229 * win95 or later
230 * winNT4 or later
231 * MFC
233 * \version 1.0
234 * first version
236 * \date 18-Feb-2004
238 * \author Jon Foster
240 * \par license
241 * This code is GPL'd.
243 class CDirFileEnum
245 private:
247 class CDirStackEntry : public CSimpleFileFind {
248 public:
249 CDirStackEntry(CDirStackEntry * seNext, const CString& sDirName);
250 ~CDirStackEntry();
252 CDirStackEntry * m_seNext;
255 CDirStackEntry * m_seStack;
256 BOOL m_bIsNew;
258 inline void PopStack();
259 inline void PushStack(const CString& sDirName);
261 public:
263 * Iterate through the specified directory and all subdirectories.
264 * It does not matter whether or not the specified directory ends
265 * with a slash. Both relative and absolute paths are allowed,
266 * the results of this iterator will be consistent with the style
267 * passed to this constructor.
269 * @param dirName The directory to search in.
271 CDirFileEnum(const CString& dirName);
274 * Destructor. Frees all resources.
276 ~CDirFileEnum();
279 * Get the next file from this iterator.
281 * \param result On successful return, holds the full path to the found
282 * file. (If this function returns FALSE, the value of
283 * result is unspecified).
284 * \param pbIsDirectory Pointer to a bool variable which will hold
285 * TRUE if the \c result path is a directory, FALSE
286 * if it's a file. Pass NULL if you don't need that information.
287 * \param bRecurse if the last result was a directory, specifies whether to
288 * recurse into that directory or skip it.
289 * \return TRUE iff a file was found, false at end of the iteration.
291 BOOL NextFile(CString &result, bool* pbIsDirectory, bool bRecurse = true);
293 BOOL CDirFileEnum::NextFileGetSize(UINT64 &iSize, bool* pbIsDirectory, bool bRecurse = true);
295 UINT64 GetSize();