Fixes for GCC 4.3.
[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 <vector>
25 #include <dirent.h>
26
27 #include <pbd/error.h>
28 #include <pbd/pathscanner.h>
29 #include <pbd/stl_delete.h>
30
31 using namespace PBD;
32
33 vector<string *> *
34 PathScanner::operator() (const string &dirpath, const string &regexp,
35                          bool match_fullpath, bool return_fullpath, 
36                          long limit)
37
38 {
39         int err;
40         char msg[256];
41
42         if ((err = regcomp (&compiled_pattern, regexp.c_str(),
43                             REG_EXTENDED|REG_NOSUB))) {
44                 
45                 regerror (err, &compiled_pattern,
46                           msg, sizeof (msg));
47                 
48                 error << "Cannot compile soundfile regexp for use (" 
49                       << msg 
50                       << ")" 
51                       << endmsg;
52                 
53                 return 0;
54         }
55         
56         return run_scan (dirpath, &PathScanner::regexp_filter, 
57                          (bool (*)(const string &, void *)) 0,
58                          0,
59                          match_fullpath,
60                          return_fullpath,
61                          limit);
62 }       
63
64 vector<string *> *
65 PathScanner::run_scan (const string &dirpath, 
66                        bool (PathScanner::*memberfilter)(const string &),
67                        bool (*filter)(const string &, void *),
68                        void *arg,
69                        bool match_fullpath, bool return_fullpath,
70                        long limit)
71
72 {
73         vector<string *> *result = 0;
74         DIR *dir;
75         struct dirent *finfo;
76         char *pathcopy = strdup (dirpath.c_str());
77         char *thisdir;
78         char fullpath[PATH_MAX+1];
79         string search_str;
80         string *newstr;
81         long nfound = 0;
82
83         if ((thisdir = strtok (pathcopy, ":")) == 0 ||
84             strlen (thisdir) == 0) {
85                 free (pathcopy);
86                 return 0;
87         }
88
89         result = new vector<string *>;
90
91         do {
92
93                 if ((dir = opendir (thisdir)) == 0) {
94                         continue;
95                 }
96                 
97                 while ((finfo = readdir (dir)) != 0) {
98
99                         snprintf (fullpath, sizeof(fullpath), "%s/%s",
100                                   thisdir, finfo->d_name);
101
102                         if (match_fullpath) {
103                                 search_str = fullpath;
104                         } else {
105                                 search_str = finfo->d_name;
106                         }
107
108                         /* handle either type of function ptr */
109
110                         if (memberfilter) {
111                                 if (!(this->*memberfilter)(search_str)) {
112                                         continue;
113                                 } 
114                         } else {
115                                 if (!filter(search_str, arg)) {
116                                         continue;
117                                 }
118                         }
119
120                         if (return_fullpath) {
121                                 newstr = new string (fullpath);
122                         } else {
123                                 newstr = new string (finfo->d_name);
124                         } 
125
126                         result->push_back (newstr);
127                         nfound++;
128                 }
129
130                 closedir (dir);
131                 
132         } while ((limit < 0 || (nfound < limit)) && (thisdir = strtok (0, ":")));
133
134         free (pathcopy);
135         return result;
136 }
137
138 string *
139 PathScanner::find_first (const string &dirpath,
140                          const string &regexp,
141                          bool match_fullpath,
142                          bool return_fullpath)
143 {
144         vector<string *> *res;
145         string *ret;
146         int err;
147         char msg[256];
148
149         if ((err = regcomp (&compiled_pattern, regexp.c_str(),
150                             REG_EXTENDED|REG_NOSUB))) {
151                 
152                 regerror (err, &compiled_pattern,
153                           msg, sizeof (msg));
154                 
155                 error << "Cannot compile soundfile regexp for use (" << msg << ")" << endmsg;
156
157                 
158                 return 0;
159         }
160         
161         res = run_scan (dirpath, 
162                         &PathScanner::regexp_filter,
163                         (bool (*)(const string &, void *)) 0,
164                         0,
165                         match_fullpath,
166                         return_fullpath, 
167                         1);
168         
169         if (res->size() == 0) {
170                 ret = 0;
171         } else {
172                 ret = res->front();
173         }
174         vector_delete (res);
175         delete res;
176         return ret;
177 }
178
179 string *
180 PathScanner::find_first (const string &dirpath,
181                          bool (*filter)(const string &, void *),
182                          void *arg,
183                          bool match_fullpath,
184                          bool return_fullpath)
185 {
186         vector<string *> *res;
187         string *ret;
188
189         res = run_scan (dirpath, 
190                         (bool (PathScanner::*)(const string &)) 0,
191                         filter,
192                         0,
193                         match_fullpath,
194                         return_fullpath, 1);
195         
196         if (res->size() == 0) {
197                 ret = 0;
198         } else {
199                 ret = res->front();
200         }
201         vector_delete (res);
202         delete res;
203         return ret;
204 }