CFugue
FileEnumerator.h
1 #ifndef __FILE_ENUMERATOR_H_EEF8FBA5_B0F1_4682_9614_2027C16002F4
2 #define __FILE_ENUMERATOR_H_EEF8FBA5_B0F1_4682_9614_2027C16002F4
3 
4 #include "PathHelper.h"
5 
6 typedef bool (*PFN_EnumeratorCallback)(LPCTSTR lpszItemName, LPCTSTR lpszItemDir, LPWIN32_FIND_DATA lpszItemFindData, LPVOID lpUserData);
7 
8 // Recursively enumerates the given directory for the specified file types. Invokes the supplied callback for each file found.
9 // Can be used to enumerate sub-directories too.
10 // (Does not support modifying the search properties while enumeration is in progress).
12 {
13  CString m_strSearchDir; // The search directory.
14 
15  CString m_strFileToSearch; // Pattern of the file that should be searched for. Valid only for file enumeration
16 
17  bool m_bRecurseSubDirectories; // Indicates if sub-directories should be recursed during an enumeration
18 
19  bool m_bIgnoreDots; // Valid only for directory listing.
20 
21  bool m_bReportMatchingDirsAlso; // Valid only for File Listing. Indicates if the directories should be included in the reporting while searching for files
22 
23  PFN_EnumeratorCallback m_pfnEnumCallback; // Callback function for the enumeration
24 
25  inline static bool EnumCallback(LPCTSTR, LPCTSTR, LPWIN32_FIND_DATA, LPVOID)
26  {
27  return false; // returning false stops the enumeration at that point
28  }
29 public:
30 
31  CFileEnumerator(PFN_EnumeratorCallback pfnEnumCallback = CFileEnumerator::EnumCallback, // Callback function for the enumeration
32  LPCTSTR lpszSearchDir = _T("."), // Should be a directory path (excluding the file name and wild cards) eg. "c:\\" or "C:\\Dir1"
33  LPCTSTR lpszFileToSearch = _T("*.*"),// Should be a file name or wild card eg. "*.*"
34  bool bRecurseSubDirectories = true,// Should the sub-directories be recursed?
35  bool bReportMatchingDirsAlso = true,// Should the matching directories also be reported while searching for files? - Valid only for file enumeration
36  bool bIgnoreDots = true // Should . and .. be informed ?? - Valid Only when Listing Directories
37  )
38  {
39  m_pfnEnumCallback = pfnEnumCallback;
40  m_strSearchDir = lpszSearchDir;
41  m_strFileToSearch = lpszFileToSearch;
42  m_bRecurseSubDirectories = bRecurseSubDirectories;
43  m_bReportMatchingDirsAlso = bReportMatchingDirsAlso;
44  m_bIgnoreDots = bIgnoreDots;
45  }
46 
47  ~CFileEnumerator(void)
48  {
49  }
50 
51  PFN_EnumeratorCallback& FileEnumeratorCallback()
52  {
53  return m_pfnEnumCallback;
54  }
55 
56  bool& IgnoreDots() { return m_bIgnoreDots; } // Indicates if Dots will be processed for the Callback (only in sub-directory listing mode)
57 
58  bool& RecurseSubDirectories() { return m_bRecurseSubDirectories; } // Indicates if sub-directories will be recursively searched or not
59 
60  CString& FileToSearch() { return m_strFileToSearch; } // The Files being searched for
61 
62  LPCTSTR FileToSearch() const { return m_strFileToSearch; } // The Files being searched for
63 
64  CString& SearchDir() { return m_strSearchDir; } // The directory being searched
65 
66  LPCTSTR SearchDir() const { return m_strSearchDir; } // The directory being searched
67 
68  bool& ReportMatchingDirsAlso() { return m_bReportMatchingDirsAlso; } // Indicates if Directories should also be reported while searching for files if the pattern matches
69 
70  HANDLE FindFirstSubDir(LPCTSTR lpszDir, LPWIN32_FIND_DATA pFindData) const
71  {
72  HANDLE hFind = FindFirstFile(CString(lpszDir) + _T("*.*"), pFindData);
73  if(hFind == INVALID_HANDLE_VALUE) return hFind;
74 
75  do
76  {
77  if(PathIsDots(pFindData->cFileName))
78  {
79  if(m_bIgnoreDots == false)
80  return hFind;
81  continue;
82  }
83 
84  if(!(pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;
85 
86  return hFind;
87 
88  }while(FindNextFile(hFind, pFindData));
89 
90  return INVALID_HANDLE_VALUE;
91  }
92 
93  BOOL FindNextSubDir(HANDLE hFind, LPWIN32_FIND_DATA pFindData) const
94  {
95  while(FindNextFile(hFind, pFindData))
96  {
97  if(PathIsDots(pFindData->cFileName)) //!_tcscmp(pFindData->cFileName, _T(".")) || !_tcscmp(pFindData->cFileName, _T("..")))
98  {
99  if(m_bIgnoreDots == false)
100  return true;
101  continue;
102  }
103 
104  if(!(pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue;
105 
106  return true;
107  }
108  return false;
109  }
110 
111  //
112  // ListAllDirectories: Enumerates all directories in the SearchDir folder; Doesnt take FileToSearch() into account;
113  // The optional lpUserData parameter would be sent back to the caller in the EnumeratorCallback.
114  // (Does not support modifying the search properties while listing is in progress)
115  // Returns true if search is complete. False if the callback requested to stop the search.
116  bool ListAllDirectories(LPVOID lpUserData = NULL) const
117  {
118  WIN32_FIND_DATA ffData;
119 
120  CString strSearchDir((LPCTSTR)SearchDir());
121  PathAddBackSlash(strSearchDir);
122 
123  HANDLE hFind = FindFirstSubDir(strSearchDir, &ffData);
124  if(hFind == INVALID_HANDLE_VALUE) return true;
125 
126  bool bContinue = true;
127 
128  do
129  {
130  if(false == (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData))
131  return false;
132 
133  if(m_bRecurseSubDirectories)
134  {
135  if(PathIsDots(ffData.cFileName)) continue;
136 
137  CFileEnumerator feDir(m_pfnEnumCallback,
138  strSearchDir + ffData.cFileName,
139  _T("*.*"),
140  m_bRecurseSubDirectories,
141  m_bReportMatchingDirsAlso,
142  m_bIgnoreDots);
143  bContinue = feDir.ListAllDirectories(lpUserData);
144  }
145  }while(bContinue && FindNextSubDir(hFind, &ffData));
146 
147  FindClose(hFind);
148 
149  return true;
150  }
151 
152  //
153  // EnumerateFiles: Enumerates all files of type FileToSearch() in the SearchDir() folder;
154  // Subdirectories will be considered for enumeration based on the RecurseSubDirectories() property.
155  // The optional lpUserData parameter would be sent back to the caller in the EnumeratorCallback.
156  // (Does not support modifying the search properties while enumeration is in progress)
157  // Returns true if search is complete. False if the callback requested to stop the search.
158  bool EnumerateFiles(LPVOID lpUserData = NULL) const
159  {
160  bool bContinue = true;
161 
162  CString strSearchDir((LPCTSTR)SearchDir());
163 
164  PathAddBackSlash(strSearchDir);
165 
166  WIN32_FIND_DATA ffData;
167 
168  HANDLE hFind = FindFirstFile(strSearchDir + (LPCTSTR)FileToSearch(), &ffData);
169  if(hFind == INVALID_HANDLE_VALUE)
170  {
171  if(m_bRecurseSubDirectories) // If this dir doesn't contain the wild card files, check in the subdirs
172  {
173  CFileEnumerator feDir(EnumCallback,
174  strSearchDir,
175  _T("*.*"),
176  m_bRecurseSubDirectories,
177  m_bReportMatchingDirsAlso,
178  true); // important to ignore the dots for subdir enumeration
179  hFind = feDir.FindFirstSubDir(strSearchDir, &ffData);
180  if(hFind == INVALID_HANDLE_VALUE) return true;
181  do
182  {
183  bContinue = CFileEnumerator( m_pfnEnumCallback,
184  strSearchDir + ffData.cFileName,
185  FileToSearch(),
186  m_bRecurseSubDirectories,
187  m_bReportMatchingDirsAlso,
188  m_bIgnoreDots).EnumerateFiles(lpUserData);
189  }while(bContinue && feDir.FindNextSubDir(hFind, &ffData));
190 
191  FindClose(hFind);
192 
193  return bContinue;
194  }
195  else
196  return true;
197  }
198 
199  do // this directory contains some files that match the wild card..
200  {
201  if(PathIsDots(ffData.cFileName))
202  {
203  if(m_bIgnoreDots == false)
204  bContinue = (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData);
205  continue;
206  }
207 
208  if((ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
209  {
210  if(m_bReportMatchingDirsAlso) // Do we need to report the matching directories too?
211  bContinue = (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData);
212  }
213  else
214  {
215  bContinue = (*m_pfnEnumCallback)(ffData.cFileName, strSearchDir, &ffData, lpUserData);
216  }
217 
218  }while(bContinue && FindNextFile(hFind, &ffData));
219 
220  FindClose(hFind);
221 
222  if(bContinue && m_bRecurseSubDirectories) //List the files from sub-directories, if required
223  {
224  CFileEnumerator feDir(EnumCallback,
225  strSearchDir,
226  _T("*.*"),
227  m_bRecurseSubDirectories,
228  m_bReportMatchingDirsAlso,
229  true); // important to ignore the dots for subdir enumeration
230  hFind = feDir.FindFirstSubDir(strSearchDir, &ffData);
231  if(hFind == INVALID_HANDLE_VALUE) return true;
232  do
233  {
234  bContinue = CFileEnumerator( m_pfnEnumCallback,
235  strSearchDir + ffData.cFileName,
236  FileToSearch(),
237  m_bRecurseSubDirectories,
238  m_bReportMatchingDirsAlso,
239  m_bIgnoreDots).EnumerateFiles(lpUserData);
240  }while(bContinue && feDir.FindNextSubDir(hFind, &ffData));
241 
242  FindClose(hFind);
243  }
244 
245  return bContinue;
246  }
247 };
248 
249 #endif
BOOL FindNextSubDir(HANDLE hFind, LPWIN32_FIND_DATA pFindData) const

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem