OSDN Git Service

Using cherry Pick implement combine commits to avoid the rebase start by command...
[tortoisegit/TortoiseGitJp.git] / src / Utils / DirFileEnum.h
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2005 - 2006 - Jon Foster\r
4 \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
9 \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
14 \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
18 #pragma once\r
19 \r
20 /**\r
21  * \ingroup Utils\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
33  *    automatically.\r
34  * 4) No dynamic memory allocation.\r
35  */\r
36 class CSimpleFileFind {\r
37 private:\r
38    /**\r
39     * Windows FindFirstFile() handle.\r
40     */\r
41    HANDLE m_hFindFile;\r
42 \r
43    /**\r
44     * Windows error code - if all is well, ERROR_SUCCESS.\r
45     * At end of directory, ERROR_NO_MORE_FILES.\r
46     */\r
47    DWORD m_dError;\r
48 \r
49    /**\r
50     * Flag indicating that FindNextFile() has not yet been\r
51     * called.\r
52     */\r
53    BOOL m_bFirst;\r
54 \r
55 protected:\r
56    /**\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
60     * legal anyway.)\r
61     */\r
62    CString m_sPathPrefix;\r
63 \r
64    /**\r
65     * The file data returned by FindFirstFile()/FindNextFile().\r
66     */\r
67    WIN32_FIND_DATA m_FindFileData;\r
68 \r
69 public:\r
70 \r
71    /**\r
72     * Constructor.\r
73     *\r
74     * \param sPath    The path to search in.\r
75     * \param sPattern The filename pattern - default all files.\r
76     */\r
77    CSimpleFileFind(const CString &sPath, LPCTSTR pPattern = _T("*.*"));\r
78    ~CSimpleFileFind();\r
79 \r
80    /**\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
84     *\r
85     * \return TRUE if a file was found, FALSE on error or\r
86     * end-of-directory (use IsError() and IsPastEnd() to\r
87     * disambiguate).\r
88     */\r
89    BOOL FindNextFile();\r
90 \r
91    /**\r
92     * Advance to the next file, ignoring the "." and ".."\r
93     * pseudo-directories (if seen).\r
94     *\r
95     * Behaves like FindNextFile(), apart from ignoring "."\r
96     * and "..".\r
97     *\r
98     * \return TRUE if a file was found, FALSE on error or\r
99     * end-of-directory.\r
100     */\r
101    BOOL FindNextFileNoDots();\r
102 \r
103    /**\r
104     * Advance to the next file, ignoring all directories.\r
105     *\r
106     * Behaves like FindNextFile(), apart from ignoring\r
107     * directories.\r
108     *\r
109     * \return TRUE if a file was found, FALSE on error or\r
110     * end-of-directory.\r
111     */\r
112    BOOL FindNextFileNoDirectories();\r
113 \r
114    /**\r
115     * Get the Windows error code.\r
116     * Only useful when IsError() returns true.\r
117     *\r
118     * \return Windows error code.\r
119     */\r
120    inline DWORD GetError() const\r
121    {\r
122       return m_dError;\r
123    }\r
124 \r
125    /**\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
129     *\r
130     * \return TRUE iff the current file data is valid.\r
131     */\r
132    inline BOOL IsValid() const\r
133    {\r
134       return (m_dError == ERROR_SUCCESS);\r
135    }\r
136 \r
137    /**\r
138     * Check if we have passed the end of the directory.\r
139     *\r
140     * \return TRUE iff we have passed the end of the directory.\r
141     */\r
142    inline BOOL IsPastEnd() const\r
143    {\r
144       return (m_dError == ERROR_NO_MORE_FILES);\r
145    }\r
146 \r
147    /**\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
150     *\r
151     * \return TRUE iff there has been an unexpected error.\r
152     */\r
153    inline BOOL IsError() const\r
154    {\r
155       return (m_dError != ERROR_SUCCESS)\r
156           && (m_dError != ERROR_NO_MORE_FILES);\r
157    }\r
158 \r
159    /**\r
160     * Check if the current file is a directory.\r
161     *\r
162     * \return TRUE iff the current file is a directory.\r
163     */\r
164    inline bool IsDirectory() const\r
165    {\r
166       return !!(m_FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
167    }\r
168 \r
169    /**\r
170     * Get the current file name (excluding the path).\r
171     *\r
172     * \return the current file name.\r
173     */\r
174    inline CString GetFileName() const\r
175    {\r
176       return m_FindFileData.cFileName;\r
177    }\r
178 \r
179    /*\r
180     * Get the current file name, including the path.\r
181     *\r
182     * \return the current file path.\r
183     */\r
184    inline CString GetFilePath() const\r
185    {\r
186       return m_sPathPrefix + m_FindFileData.cFileName;\r
187    }\r
188 \r
189    /**\r
190     * Check if the current file is the "." or ".."\r
191     * pseudo-directory.\r
192     *\r
193     * \return TRUE iff the current file is the "." or ".."\r
194     * pseudo-directory.\r
195     */\r
196    inline BOOL IsDots() const \r
197    {\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
203    }\r
204 };\r
205 \r
206 /**\r
207  * \ingroup Utils\r
208  * Enumerates over a directory tree, recursively.\r
209  *\r
210  * \par requirements\r
211  * win95 or later\r
212  * winNT4 or later\r
213  * MFC\r
214  *\r
215  * \version 1.0\r
216  * first version\r
217  *\r
218  * \date 18-Feb-2004\r
219  *\r
220  * \author Jon Foster\r
221  *\r
222  * \par license\r
223  * This code is GPL'd.\r
224  */\r
225 class CDirFileEnum\r
226 {\r
227 private:\r
228 \r
229    class CDirStackEntry : public CSimpleFileFind {\r
230    public:\r
231       CDirStackEntry(CDirStackEntry * seNext, const CString& sDirName);\r
232       ~CDirStackEntry();\r
233 \r
234       CDirStackEntry * m_seNext;\r
235    };\r
236 \r
237    CDirStackEntry * m_seStack;\r
238    BOOL m_bIsNew;\r
239 \r
240    inline void PopStack();\r
241    inline void PushStack(const CString& sDirName);\r
242 \r
243 public:\r
244    /**\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
250     *\r
251     * @param dirName The directory to search in.\r
252     */\r
253         CDirFileEnum(const CString& dirName);\r
254 \r
255    /**\r
256     * Destructor.  Frees all resources.\r
257     */\r
258    ~CDirFileEnum();\r
259 \r
260    /**\r
261     * Get the next file from this iterator.\r
262     *\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
270     */\r
271    BOOL NextFile(CString &result, bool* pbIsDirectory);\r
272 };\r
273 \r