*** NEW CODING POLICY ***
[ardour.git] / libs / pbd / pathscanner.cc
1 /*
2     Copyright (C) 1998-99 Paul Barton-Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <cstring>
22 #include <cstdlib>
23 #include <cstdio>
24 #include <cstring>
25 #include <vector>
26 #include <dirent.h>
27
28 #include "pbd/error.h"
29 #include "pbd/pathscanner.h"
30 #include "pbd/stl_delete.h"
31
32 using namespace PBD;
33
34 vector<string *> *
35 PathScanner::operator() (const string &dirpath, const string &regexp,
36                          bool match_fullpath, bool return_fullpath, 
37                          long limit)
38
39 {
40         int err;
41         char msg[256];
42
43         if ((err = regcomp (&compiled_pattern, regexp.c_str(),
44                             REG_EXTENDED|REG_NOSUB))) {
45                 
46                 regerror (err, &compiled_pattern,
47                           msg, sizeof (msg));
48                 
49                 error << "Cannot compile soundfile regexp for use (" 
50                       << msg 
51                       << ")" 
52                       << endmsg;
53                 
54                 return 0;
55         }
56         
57         return run_scan (dirpath, &PathScanner::regexp_filter, 
58                          (bool (*)(const string &, void *)) 0,
59                          0,
60                          match_fullpath,
61                          return_fullpath,
62                          limit);
63 }       
64
65 vector<string *> *
66 PathScanner::run_scan (const string &dirpath, 
67                        bool (PathScanner::*memberfilter)(const string &),
68                        bool (*filter)(const string &, void *),
69                        void *arg,
70                        bool match_fullpath, bool return_fullpath,
71                        long limit)
72
73 {
74         vector<string *> *result = 0;
75         DIR *dir;
76         struct dirent *finfo;
77         char *pathcopy = strdup (dirpath.c_str());
78         char *thisdir;
79         char fullpath[PATH_MAX+1];
80         string search_str;
81         string *newstr;
82         long nfound = 0;
83
84         if ((thisdir = strtok (pathcopy, ":")) == 0 ||
85             strlen (thisdir) == 0) {
86                 free (pathcopy);
87                 return 0;
88         }
89
90         result = new vector<string *>;
91
92         do {
93
94                 if ((dir = opendir (thisdir)) == 0) {
95                         continue;
96                 }
97                 
98                 while ((finfo = readdir (dir)) != 0) {
99
100                         snprintf (fullpath, sizeof(fullpath), "%s/%s",
101                                   thisdir, finfo->d_name);
102
103                         if (match_fullpath) {
104                                 search_str = fullpath;
105                         } else {
106                                 search_str = finfo->d_name;
107                         }
108
109                         /* handle either type of function ptr */
110
111                         if (memberfilter) {
112                                 if (!(this->*memberfilter)(search_str)) {
113                                         continue;
114                                 } 
115                         } else {
116                                 if (!filter(search_str, arg)) {
117                                         continue;
118                                 }
119                         }
120
121                         if (return_fullpath) {
122                                 newstr = new string (fullpath);
123                         } else {
124                                 newstr = new string (finfo->d_name);
125                         } 
126
127                         result->push_back (newstr);
128                         nfound++;
129                 }
130
131                 closedir (dir);
132                 
133         } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
134
135         free (pathcopy);
136         return result;
137 }
138
139 string *
140 PathScanner::find_first (const string &dirpath,
141                          const string &regexp,
142                          bool match_fullpath,
143                          bool return_fullpath)
144 {
145         vector<string *> *res;
146         string *ret;
147         int err;
148         char msg[256];
149
150         if ((err = regcomp (&compiled_pattern, regexp.c_str(),
151                             REG_EXTENDED|REG_NOSUB))) {
152                 
153                 regerror (err, &compiled_pattern,
154                           msg, sizeof (msg));
155                 
156                 error << "Cannot compile soundfile regexp for use (" << msg << ")" << endmsg;
157
158                 
159                 return 0;
160         }
161         
162         res = run_scan (dirpath, 
163                         &PathScanner::regexp_filter,
164                         (bool (*)(const string &, void *)) 0,
165                         0,
166                         match_fullpath,
167                         return_fullpath, 
168                         1);
169         
170         if (res->size() == 0) {
171                 ret = 0;
172         } else {
173                 ret = res->front();
174         }
175         vector_delete (res);
176         delete res;
177         return ret;
178 }
179
180 string *
181 PathScanner::find_first (const string &dirpath,
182                          bool (*filter)(const string &, void *),
183                          void *arg,
184                          bool match_fullpath,
185                          bool return_fullpath)
186 {
187         vector<string *> *res;
188         string *ret;
189
190         res = run_scan (dirpath, 
191                         (bool (PathScanner::*)(const string &)) 0,
192                         filter,
193                         0,
194                         match_fullpath,
195                         return_fullpath, 1);
196         
197         if (res->size() == 0) {
198                 ret = 0;
199         } else {
200                 ret = res->front();
201         }
202         vector_delete (res);
203         delete res;
204         return ret;
205 }