diff tango/tango/io/FileScan.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/tango/io/FileScan.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,202 @@
+/*******************************************************************************
+
+        copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
+
+        license:        BSD style: $(LICENSE)
+
+        version:        Jun 2004: Initial release
+        version:        Dec 2006: Pacific release
+
+        author:         Kris
+
+*******************************************************************************/
+
+module tango.io.FileScan;
+
+public  import tango.io.FilePath;
+
+private import tango.core.Exception;
+
+/*******************************************************************************
+
+        Recursively scan files and directories, adding filtered files to
+        an output structure as we go. This can be used to produce a list
+        of subdirectories and the files contained therein. The following
+        example lists all files with suffix ".d" located via the current
+        directory, along with the folders containing them:
+        ---
+        auto scan = new FileScan;
+
+        scan (".", ".d");
+
+        Stdout.formatln ("{} Folders", scan.folders.length);
+        foreach (folder; scan.folders)
+                 Stdout.formatln ("{}", folder);
+
+        Stdout.formatln ("\n{} Files", scan.files.length);
+        foreach (file; scan.files)
+                 Stdout.formatln ("{}", file);
+        ---
+
+        This is unlikely the most efficient method to scan a vast number of
+        files, but operates in a convenient manner
+        
+*******************************************************************************/
+
+class FileScan
+{       
+        alias sweep     opCall;
+
+        FilePath[]      fileSet;
+        char[][]        errorSet;
+        FilePath[]      folderSet;
+        
+        /***********************************************************************
+
+            Alias for Filter delegate. Accepts a FilePath & a bool as 
+            arguments and returns a bool.
+
+            The FilePath argument represents a file found by the scan, 
+            and the bool whether the FilePath represents a folder.
+
+            The filter should return true, if matched by the filter. Note
+            that returning false where the path is a folder will result 
+            in all files contained being ignored. To always recurse folders, 
+            do something like this:
+            ---
+            return (isDir || match (fp.name));
+            ---
+
+        ***********************************************************************/
+
+        alias FilePath.Filter Filter;
+
+       /***********************************************************************
+
+                Return all the errors found in the last scan
+
+        ***********************************************************************/
+
+        public char[][] errors ()
+        {
+                return errorSet;
+        }
+
+        /***********************************************************************
+
+                Return all the files found in the last scan
+
+        ***********************************************************************/
+
+        public FilePath[] files ()
+        {
+                return fileSet;
+        }
+
+        /***********************************************************************
+        
+                Return all directories found in the last scan
+
+        ***********************************************************************/
+
+        public FilePath[] folders ()
+        {
+                return folderSet;
+        }
+
+        /***********************************************************************
+
+                Sweep a set of files and directories from the given parent
+                path, with no filtering applied
+        
+        ***********************************************************************/
+        
+        FileScan sweep (char[] path, bool recurse=true)
+        {
+                return sweep (path, cast(Filter) null, recurse);
+        }
+
+        /***********************************************************************
+
+                Sweep a set of files and directories from the given parent
+                path, where the files are filtered by the given suffix
+        
+        ***********************************************************************/
+        
+        FileScan sweep (char[] path, char[] match, bool recurse=true)
+        {
+                return sweep (path, (FilePath fp, bool isDir)
+                             {return isDir || fp.suffix == match;}, recurse);
+        }
+
+        /***********************************************************************
+
+                Sweep a set of files and directories from the given parent
+                path, where the files are filtered by the provided delegate
+
+        ***********************************************************************/
+        
+        FileScan sweep (char[] path, Filter filter, bool recurse=true)
+        {
+                errorSet = null, fileSet = folderSet = null;
+                return scan (new FilePath(path), filter, recurse);
+        }
+
+        /***********************************************************************
+
+                Internal routine to locate files and sub-directories. We
+                skip entries with names composed only of '.' characters. 
+
+        ***********************************************************************/
+
+        private FileScan scan (FilePath folder, Filter filter, bool recurse) 
+        {
+                try {
+                    auto paths = folder.toList (filter);
+                
+                    auto count = fileSet.length;
+                    foreach (path; paths)
+                             if (! path.isFolder)
+                                   fileSet ~= path;
+                             else
+                                if (recurse)
+                                    scan (path, filter, recurse);
+                
+                    // add packages only if there's something in them
+                    if (fileSet.length > count)
+                        folderSet ~= folder;
+
+                    } catch (IOException e)
+                             errorSet ~= e.toString;
+                return this;
+        }
+}
+
+
+/*******************************************************************************
+
+*******************************************************************************/
+
+debug (FileScan)
+{
+        import tango.io.Stdout;
+
+        void main()
+        {
+                auto scan = new FileScan;
+
+                scan (".");
+
+                Stdout.formatln ("{} Folders", scan.folders.length);
+                foreach (folder; scan.folders)
+                         Stdout (folder).newline;
+
+                Stdout.formatln ("\n{} Files", scan.files.length);
+                foreach (file; scan.files)
+                         Stdout (file).newline;
+
+                Stdout.formatln ("\n{} Errors", scan.errors.length);
+                foreach (error; scan.errors)
+                         Stdout (error).newline;
+        }
+}