not completely tested new structure for VST/FST build
[ardour.git] / libs / pbd / path.cc
1 /*
2    Copyright (C) 2006  Paul Davis
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License
6    as published by the Free Software Foundation; either version 2
7    of the License, or (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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 */
18
19 #include <cerrno>
20
21 #include <glib.h>
22 #include <glib/gstdio.h>
23
24 #include <glibmm/miscutils.h>
25 #include <glibmm/fileutils.h>
26
27 #include <pbd/path.h>
28 #include <pbd/tokenizer.h>
29
30 namespace PBD {
31
32 Path::Path ()
33 {
34
35 }
36
37 Path::Path (const string& path)
38 {
39         vector<string> tmp;
40
41         if(!tokenize ( path, string(":;"), std::back_inserter (tmp))) {
42                 g_warning ("%s : %s\n", G_STRLOC, G_STRFUNC);
43                 return;
44         }
45
46         add_readable_directories (tmp);
47 }
48
49 Path::Path (const vector<string>& paths)
50 {
51         add_readable_directories (paths);
52 }
53
54 Path::Path (const Path& other)
55         : m_dirs(other.m_dirs)
56 {
57
58 }
59
60 bool
61 Path::readable_directory (const string& directory_path)
62 {
63         if (g_access (directory_path.c_str(), R_OK) == 0) {
64                 if (Glib::file_test(directory_path, Glib::FILE_TEST_IS_DIR)) {
65                         return true;
66                 } else {
67                         g_warning (" %s : Path exists but is not a directory\n", G_STRLOC); 
68                 }
69         } else {
70                 g_warning ("%s : %s : %s\n", G_STRLOC, directory_path.c_str(), g_strerror(errno));
71         }
72         return false;
73 }
74
75 void
76 Path::add_readable_directory (const string& directory_path)
77 {
78         if(readable_directory(directory_path)) {
79                 m_dirs.push_back(directory_path);
80         }
81 }
82
83 void
84 Path::add_readable_directories (const vector<string>& paths)
85 {
86         for(vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
87                 add_readable_directory (*i);
88         }
89 }
90
91 const string
92 Path::path_string() const
93 {
94         string path;
95
96         for (vector<string>::const_iterator i = m_dirs.begin(); i != m_dirs.end(); ++i) {
97                 path += (*i);
98                 path += G_SEARCHPATH_SEPARATOR;
99         }
100
101         g_message ("%s : %s", G_STRLOC, path.c_str());
102
103         return path.substr (0, path.length() - 1); // drop final colon
104 }
105
106 const Path&
107 Path::operator= (const Path& path)
108 {
109         m_dirs = path.m_dirs;
110         return *this;
111 }
112
113 const Path& 
114 Path::operator+= (const string& directory_path)
115 {
116         add_readable_directory (directory_path);
117         return *this;
118 }
119
120 const Path 
121 operator+ (const Path& lhs_path, const Path& rhs_path)
122 {
123         Path tmp_path(lhs_path); // does this do what I think it does.
124         // concatenate paths into new Path
125         tmp_path.m_dirs.insert(tmp_path.m_dirs.end(), rhs_path.m_dirs.begin(), rhs_path.m_dirs.end());
126         return tmp_path;
127 }
128
129 Path&
130 Path::add_subdirectory_to_path (const string& subdir)
131 {
132         vector<string> tmp;
133         string directory_path;
134
135         for (vector<string>::iterator i = m_dirs.begin(); i != m_dirs.end(); ++i) {
136                 directory_path = Glib::build_filename (*i, subdir);
137                 if(readable_directory(directory_path)) {
138                         tmp.push_back(directory_path);
139                 }
140         }
141         m_dirs = tmp;
142         return *this;
143 }
144
145 bool
146 find_file_in_path (const Path& path, const string& filename, string& resulting_path)
147 {
148         for (vector<string>::const_iterator i = path.dirs().begin(); i != path.dirs().end(); ++i) {
149                 resulting_path = Glib::build_filename ((*i), filename);
150                 if (g_access (resulting_path.c_str(), R_OK) == 0) {
151                         g_message ("File %s found in Path : %s\n", resulting_path.c_str(),
152                                         path.path_string().c_str());
153                         return true;
154                 }
155         }
156
157         g_warning ("%s : Could not locate file %s in path %s\n", G_STRLOC, filename.c_str(),
158                         path.path_string().c_str());
159         
160         return false;
161 }
162
163 } // namespace PBD
164