move path_expand() and search_path_expand() into libpbd, and use them to expand searc...
[ardour.git] / libs / pbd / pathscanner.cc
index eb913cc910d923b7f5e7d43471056639df411c97..fac2dcfd965258debf26a13a3d65cd4839e76548 100644 (file)
     $Id$
 */
 
-#include <cstring>
 #include <cstdlib>
 #include <cstdio>
+#include <cstring>
 #include <vector>
 #include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <glibmm/miscutils.h>
 
-#include <pbd/error.h>
-#include <pbd/pathscanner.h>
-#include <pbd/stl_delete.h>
+#include "pbd/error.h"
+#include "pbd/pathexpand.h"
+#include "pbd/pathscanner.h"
+#include "pbd/stl_delete.h"
 
+using namespace std;
 using namespace PBD;
 
 vector<string *> *
 PathScanner::operator() (const string &dirpath, const string &regexp,
                         bool match_fullpath, bool return_fullpath, 
-                        long limit)
+                        long limit, bool recurse)
 
 {
        int err;
@@ -58,7 +64,7 @@ PathScanner::operator() (const string &dirpath, const string &regexp,
                         0,
                         match_fullpath,
                         return_fullpath,
-                        limit);
+                        limit, recurse);
 }      
 
 vector<string *> *
@@ -67,15 +73,27 @@ PathScanner::run_scan (const string &dirpath,
                       bool (*filter)(const string &, void *),
                       void *arg,
                       bool match_fullpath, bool return_fullpath,
-                      long limit)
-
+                      long limit,
+                      bool recurse)
+{
+       return run_scan_internal ((vector<string*>*) 0, dirpath, memberfilter, filter, arg, match_fullpath, return_fullpath, limit, recurse);
+}
+       
+vector<string *> *
+PathScanner::run_scan_internal (vector<string *> *result,
+                               const string &dirpath, 
+                               bool (PathScanner::*memberfilter)(const string &),
+                               bool (*filter)(const string &, void *),
+                               void *arg,
+                               bool match_fullpath, bool return_fullpath,
+                               long limit,
+                               bool recurse)
 {
-       vector<string *> *result = 0;
        DIR *dir;
        struct dirent *finfo;
-       char *pathcopy = strdup (dirpath.c_str());
+       char *pathcopy = strdup (search_path_expand (dirpath).c_str());
        char *thisdir;
-       char fullpath[PATH_MAX+1];
+       string fullpath;
        string search_str;
        string *newstr;
        long nfound = 0;
@@ -86,7 +104,9 @@ PathScanner::run_scan (const string &dirpath,
                return 0;
        }
 
-       result = new vector<string *>;
+       if (result == 0) {
+               result = new vector<string *>;
+       }
 
        do {
 
@@ -96,37 +116,50 @@ PathScanner::run_scan (const string &dirpath,
                
                while ((finfo = readdir (dir)) != 0) {
 
-                       snprintf (fullpath, sizeof(fullpath), "%s/%s",
-                                 thisdir, finfo->d_name);
-
-                       if (match_fullpath) {
-                               search_str = fullpath;
-                       } else {
-                               search_str = finfo->d_name;
+                       if ((finfo->d_name[0] == '.' && finfo->d_name[1] == '\0') ||
+                           (finfo->d_name[0] == '.' && finfo->d_name[1] == '.' && finfo->d_name[2] == '\0')) {
+                               continue;
                        }
+                        
+                        fullpath = Glib::build_filename (thisdir, finfo->d_name);
 
-                       /* handle either type of function ptr */
-
-                       if (memberfilter) {
-                               if (!(this->*memberfilter)(search_str)) {
-                                       continue;
-                               } 
-                       } else {
-                               if (!filter(search_str, arg)) {
-                                       continue;
-                               }
+                       struct stat statbuf;
+                       if (stat (fullpath.c_str(), &statbuf) < 0) {
+                               continue;
                        }
 
-                       if (return_fullpath) {
-                               newstr = new string (fullpath);
+                       if (statbuf.st_mode & S_IFDIR && recurse) {
+                               run_scan_internal (result, fullpath, memberfilter, filter, arg, match_fullpath, return_fullpath, limit, recurse);
                        } else {
-                               newstr = new string (finfo->d_name);
-                       } 
+                               
+                               if (match_fullpath) {
+                                       search_str = fullpath;
+                               } else {
+                                       search_str = finfo->d_name;
+                               }
+                               
+                               /* handle either type of function ptr */
+                               
+                               if (memberfilter) {
+                                       if (!(this->*memberfilter)(search_str)) {
+                                               continue;
+                                       } 
+                               } else {
+                                       if (!filter(search_str, arg)) {
+                                               continue;
+                                       }
+                               }
 
-                       result->push_back (newstr);
-                       nfound++;
+                               if (return_fullpath) {
+                                       newstr = new string (fullpath);
+                               } else {
+                                       newstr = new string (finfo->d_name);
+                               } 
+                               
+                               result->push_back (newstr);
+                               nfound++;
+                       }
                }
-
                closedir (dir);
                
        } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
@@ -179,7 +212,7 @@ PathScanner::find_first (const string &dirpath,
 string *
 PathScanner::find_first (const string &dirpath,
                         bool (*filter)(const string &, void *),
-                        void *arg,
+                        void * /*arg*/,
                         bool match_fullpath,
                         bool return_fullpath)
 {