Remove debug statements from KCal backends.
[beagle.git] / Util / DirectoryWalker.cs
blob285ab10e088ab868700303c69eb995e168ec288e
1 //
2 // DirectoryWalker.cs
3 //
4 // Copyright (C) 2005 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.IO;
30 using System.Runtime.InteropServices;
31 using System.Text;
33 namespace Beagle.Util {
35 public class DirectoryWalker {
37 public delegate bool FileFilter (string path, string name);
38 private delegate object FileObjectifier (string path, string name);
40 [DllImport ("libc", SetLastError = true)]
41 private static extern IntPtr opendir (string name);
43 [DllImport ("libc", SetLastError = true)]
44 private static extern int closedir (IntPtr dir);
46 [DllImport ("libbeagleglue", EntryPoint = "beagled_utils_readdir", SetLastError = true)]
47 private static extern int sys_readdir (IntPtr dir, [Out] StringBuilder name, int max_len);
49 private static string readdir (IntPtr dir, StringBuilder buffer)
51 int r = 0;
52 buffer.Length = 0;
53 while (r == 0 && buffer.Length == 0) {
54 r = sys_readdir (dir, buffer, buffer.Capacity);
57 if (r == -1)
58 return null;
60 return buffer.ToString ();
63 private class FileEnumerator : IEnumerator {
65 string path;
66 FileFilter file_filter;
67 FileObjectifier file_objectifier;
68 IntPtr dir_handle = IntPtr.Zero;
69 string current;
70 StringBuilder name_buffer = new StringBuilder (256);
72 public bool NamesOnly = false;
74 public FileEnumerator (string path,
75 FileFilter file_filter,
76 FileObjectifier file_objectifier)
78 this.path = path;
79 this.file_filter = file_filter;
80 this.file_objectifier = file_objectifier;
81 Reset ();
84 ~FileEnumerator ()
86 if (dir_handle != IntPtr.Zero)
87 closedir (dir_handle);
90 public object Current {
91 get {
92 object current_obj = null;
93 if (current != null) {
94 if (file_objectifier != null)
95 current_obj = file_objectifier (path, current);
96 else if (NamesOnly)
97 current_obj = current;
98 else
99 current_obj = Path.Combine (path, current);
102 return current_obj;
106 public bool MoveNext ()
108 bool skip_file = false;
110 do {
111 // FIXME? I think this might be a bug in mono, but the
112 // capacity of the StringBuilder can apparently shrink
113 // from underneath us. This leads to truncated filenames,
114 // and the DirectoryWalker drops them because the file
115 // doesn't exist. Adding an EnsureCapacity() here fixes
116 // this.
117 name_buffer.EnsureCapacity (256);
119 current = readdir (dir_handle, name_buffer);
120 if (current == null)
121 break;
123 skip_file = false;
125 if (current == "." || current == "..") {
126 skip_file = true;
128 } else if (file_filter != null) {
129 try {
130 if (! file_filter (path, current))
131 skip_file = true;
133 } catch (Exception ex) {
134 Logger.Log.Debug (ex, "Caught exception in file_filter");
136 // If we have a filter that fails on a file,
137 // it is probably safest to skip that file.
138 skip_file = true;
142 } while (skip_file);
144 if (current == null) {
145 closedir (dir_handle);
146 dir_handle = IntPtr.Zero;
149 return current != null;
152 public void Reset ()
154 current = null;
155 if (dir_handle != IntPtr.Zero)
156 closedir (dir_handle);
157 dir_handle = opendir (path);
158 if (dir_handle == IntPtr.Zero)
159 throw new DirectoryNotFoundException (path);
163 private class FileEnumerable : IEnumerable {
165 string path;
166 FileFilter file_filter;
167 FileObjectifier file_objectifier;
169 public bool NamesOnly = false;
171 public FileEnumerable (string path,
172 FileFilter file_filter,
173 FileObjectifier file_objectifier)
175 this.path = path;
176 this.file_filter = file_filter;
177 this.file_objectifier = file_objectifier;
180 public IEnumerator GetEnumerator ()
182 FileEnumerator e;
183 e = new FileEnumerator (path, file_filter, file_objectifier);
184 e.NamesOnly = this.NamesOnly;
185 return e;
189 static private bool IsFile (string path, string name)
191 return File.Exists (Path.Combine (path, name));
194 static private object FileInfoObjectifier (string path, string name)
196 return new FileInfo (Path.Combine (path, name));
199 /////////////////////////////////////////////////////////////////////////////////
201 static public bool IsWalkable (string path)
203 IntPtr dir_handle;
204 dir_handle = opendir (path);
205 if (dir_handle == IntPtr.Zero)
206 return false;
207 closedir (dir_handle);
208 return true;
211 /////////////////////////////////////////////////////////////////////////////////
213 static public IEnumerable GetFiles (string path)
215 return new FileEnumerable (path, new FileFilter (IsFile), null);
218 static public IEnumerable GetFiles (DirectoryInfo dirinfo)
220 return GetFiles (dirinfo.FullName);
223 static public IEnumerable GetFileInfos (string path)
225 return new FileEnumerable (path,
226 new FileFilter (IsFile),
227 new FileObjectifier (FileInfoObjectifier));
230 static public IEnumerable GetFileInfos (DirectoryInfo dirinfo)
232 return GetFileInfos (dirinfo.FullName);
235 static private bool IsDirectory (string path, string name)
237 return Directory.Exists (Path.Combine (path, name));
240 static private object DirectoryInfoObjectifier (string path, string name)
242 return new DirectoryInfo (Path.Combine (path, name));
245 static public IEnumerable GetDirectories (string path)
247 return new FileEnumerable (path, new FileFilter (IsDirectory), null);
250 static public IEnumerable GetDirectories (DirectoryInfo dirinfo)
252 return GetDirectories (dirinfo.FullName);
255 static public IEnumerable GetDirectoryNames (string path)
257 FileEnumerable fe;
258 fe = new FileEnumerable (path, new FileFilter (IsDirectory), null);
259 fe.NamesOnly = true;
260 return fe;
263 static public IEnumerable GetDirectoryInfos (string path)
265 return new FileEnumerable (path,
266 new FileFilter (IsDirectory),
267 new FileObjectifier (DirectoryInfoObjectifier));
270 static public IEnumerable GetDirectoryInfos (DirectoryInfo dirinfo)
272 return GetDirectoryInfos (dirinfo.FullName);
275 static public IEnumerable GetItems (string path, FileFilter filter)
277 return new FileEnumerable (path, filter, null);
280 static public IEnumerable GetFileInfosRecursive (string path)
282 foreach (FileInfo i in DirectoryWalker.GetFileInfos (path))
283 yield return i;
285 foreach (string dir in DirectoryWalker.GetDirectories (path)) {
286 foreach (FileInfo i in GetFileInfosRecursive (dir))
287 yield return i;
290 yield break;
293 static public IEnumerable GetFileInfosRecursive (DirectoryInfo dirinfo)
295 return GetFileInfosRecursive (dirinfo.FullName);