]> git.saurik.com Git - wxWidgets.git/blob - src/unix/dir.cpp
attempt to optimize wxDirData::Read() - made absolutely no difference
[wxWidgets.git] / src / unix / dir.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: unix/dir.cpp
3 // Purpose: wxDir implementation for Unix/POSIX systems
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 08.12.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "dir.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34 #endif // PCH
35
36 #include "wx/dir.h"
37 #include "wx/filefn.h" // for wxMatchWild
38
39 #include <sys/types.h>
40
41 #include <dirent.h>
42
43 // ----------------------------------------------------------------------------
44 // macros
45 // ----------------------------------------------------------------------------
46
47 #define M_DIR ((wxDirData *)m_data)
48
49 // ----------------------------------------------------------------------------
50 // private classes
51 // ----------------------------------------------------------------------------
52
53 // this class stores everything we need to enumerate the files
54 class wxDirData
55 {
56 public:
57 wxDirData(const wxString& dirname);
58 ~wxDirData();
59
60 bool IsOk() const { return m_dir != NULL; }
61
62 void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
63 void SetFlags(int flags) { m_flags = flags; }
64
65 void Rewind() { rewinddir(m_dir); }
66 bool Read(wxString *filename);
67
68 const wxString& GetName() const { return m_dirname; }
69
70 private:
71 DIR *m_dir;
72
73 wxString m_dirname;
74 wxString m_filespec;
75
76 int m_flags;
77 };
78
79 // ============================================================================
80 // implementation
81 // ============================================================================
82
83 // ----------------------------------------------------------------------------
84 // wxDirData
85 // ----------------------------------------------------------------------------
86
87 #if !defined( __VMS__ ) || ( __VMS_VER >= 70000000 )
88
89 wxDirData::wxDirData(const wxString& dirname)
90 : m_dirname(dirname)
91 {
92 m_dir = NULL;
93
94 // throw away the trailing slashes
95 size_t n = m_dirname.length();
96 wxCHECK_RET( n, _T("empty dir name in wxDir") );
97
98 while ( n > 0 && m_dirname[--n] == '/' )
99 ;
100
101 m_dirname.Truncate(n + 1);
102
103 // do open the dir
104 m_dir = opendir(m_dirname.fn_str());
105 }
106
107 wxDirData::~wxDirData()
108 {
109 if ( m_dir )
110 {
111 if ( closedir(m_dir) != 0 )
112 {
113 wxLogLastError(_T("closedir"));
114 }
115 }
116 }
117
118 bool wxDirData::Read(wxString *filename)
119 {
120 dirent *de = (dirent *)NULL; // just to silence compiler warnings
121 bool matches = FALSE;
122
123 // speed up string concatenation in the loop a bit
124 wxString path = m_dirname;
125 path += _T('/');
126 path.reserve(path.length() + 255);
127
128 while ( !matches )
129 {
130 de = readdir(m_dir);
131 if ( !de )
132 return FALSE;
133
134 // don't return "." and ".." unless asked for
135 if ( de->d_name[0] == '.' &&
136 ((de->d_name[1] == '.' && de->d_name[2] == '\0') ||
137 (de->d_name[1] == '\0')) )
138 {
139 if ( !(m_flags & wxDIR_DOTDOT) )
140 continue;
141
142 // we found a valid match
143 break;
144 }
145
146 // check the type now
147 if ( !(m_flags & wxDIR_FILES) && !wxDir::Exists(path + de->d_name) )
148 {
149 // it's a file, but we don't want them
150 continue;
151 }
152 else if ( !(m_flags & wxDIR_DIRS) && wxDir::Exists(path + de->d_name) )
153 {
154 // it's a dir, and we don't want it
155 continue;
156 }
157
158 // finally, check the name
159 if ( m_filespec.empty() )
160 {
161 matches = m_flags & wxDIR_HIDDEN ? TRUE : de->d_name[0] != '.';
162 }
163 else
164 {
165 // test against the pattern
166 matches = wxMatchWild(m_filespec, de->d_name,
167 !(m_flags & wxDIR_HIDDEN));
168 }
169 }
170
171 *filename = de->d_name;
172
173 return TRUE;
174 }
175
176 #else // old VMS (TODO)
177
178 wxDirData::wxDirData(const wxString& WXUNUSED(dirname))
179 {
180 wxFAIL_MSG(_T("not implemented"));
181 }
182
183 wxDirData::~wxDirData()
184 {
185 }
186
187 bool wxDirData::Read(wxString * WXUNUSED(filename))
188 {
189 return FALSE;
190 }
191
192 #endif // not or new VMS/old VMS
193
194 // ----------------------------------------------------------------------------
195 // wxDir helpers
196 // ----------------------------------------------------------------------------
197
198 /* static */
199 bool wxDir::Exists(const wxString& dir)
200 {
201 return wxPathExists(dir);
202 }
203
204 // ----------------------------------------------------------------------------
205 // wxDir construction/destruction
206 // ----------------------------------------------------------------------------
207
208 wxDir::wxDir(const wxString& dirname)
209 {
210 m_data = NULL;
211
212 (void)Open(dirname);
213 }
214
215 bool wxDir::Open(const wxString& dirname)
216 {
217 delete M_DIR;
218 m_data = new wxDirData(dirname);
219
220 if ( !M_DIR->IsOk() )
221 {
222 wxLogSysError(_("Can not enumerate files in directory '%s'"),
223 dirname.c_str());
224
225 delete M_DIR;
226 m_data = NULL;
227
228 return FALSE;
229 }
230
231 return TRUE;
232 }
233
234 bool wxDir::IsOpened() const
235 {
236 return m_data != NULL;
237 }
238
239 wxString wxDir::GetName() const
240 {
241 wxString name;
242 if ( m_data )
243 {
244 name = M_DIR->GetName();
245 if ( !name.empty() && (name.Last() == _T('/')) )
246 {
247 // chop off the last (back)slash
248 name.Truncate(name.length() - 1);
249 }
250 }
251
252 return name;
253 }
254
255 wxDir::~wxDir()
256 {
257 delete M_DIR;
258 }
259
260 // ----------------------------------------------------------------------------
261 // wxDir enumerating
262 // ----------------------------------------------------------------------------
263
264 bool wxDir::GetFirst(wxString *filename,
265 const wxString& filespec,
266 int flags) const
267 {
268 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
269
270 M_DIR->Rewind();
271
272 M_DIR->SetFileSpec(filespec);
273 M_DIR->SetFlags(flags);
274
275 return GetNext(filename);
276 }
277
278 bool wxDir::GetNext(wxString *filename) const
279 {
280 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
281
282 wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
283
284 return M_DIR->Read(filename);
285 }