1 /*
2 * Copyright (C) 2007-2015 Tim Mayberry <mojofunk@gmail.com>
3 * Copyright (C) 2008-2009 David Robillard <d@drobilla.net>
4 * Copyright (C) 2008-2015 Paul Davis <paul@linuxaudiosystems.com>
5 * Copyright (C) 2013-2014 John Emmas <john@creativepost.co.uk>
6 * Copyright (C) 2014-2015 Robin Gareus <robin@gareus.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include <string>
24
25 #include <glib.h>
26 #include <glibmm/miscutils.h>
27
28 #include "pbd/replace_all.h"
29 #include "pbd/tokenizer.h"
30 #include "pbd/search_path.h"
31 #include "pbd/error.h"
32
33 using namespace std;
34
35 namespace PBD {
36
Searchpath()37 Searchpath::Searchpath ()
38 {
39
40 }
41
Searchpath(const string & path)42 Searchpath::Searchpath (const string& path)
43 {
44 vector<std::string> tmp;
45
46 if (tokenize (path, string(G_SEARCHPATH_SEPARATOR_S), std::back_inserter (tmp))) {
47 add_directories (tmp);
48 }
49 }
50
Searchpath(const vector<std::string> & paths)51 Searchpath::Searchpath (const vector<std::string>& paths)
52 {
53 add_directories (paths);
54 }
55
56 void
remove_directory(const std::string & directory_path)57 Searchpath::remove_directory (const std::string& directory_path)
58 {
59 if (directory_path.empty()) {
60 return;
61 }
62
63 for (vector<std::string>::iterator i = begin(); i != end();) {
64 if (*i == directory_path) {
65 i = erase (i);
66 } else {
67 ++i;
68 }
69 }
70 }
71
72 void
remove_directories(const vector<std::string> & paths)73 Searchpath::remove_directories (const vector<std::string>& paths)
74 {
75 for(vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
76 remove_directory (*i);
77 }
78 }
79
80 void
add_directory(const std::string & directory_path)81 Searchpath::add_directory (const std::string& directory_path)
82 {
83 if (directory_path.empty()) {
84 return;
85 }
86 for (vector<std::string>::const_iterator i = begin(); i != end(); ++i) {
87 if (poor_mans_glob (*i) == poor_mans_glob(directory_path)) {
88 return;
89 }
90 }
91 push_back(directory_path);
92 }
93
94 void
add_directories(const vector<std::string> & paths)95 Searchpath::add_directories (const vector<std::string>& paths)
96 {
97 for(vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
98 add_directory (*i);
99 }
100 }
101
102 const string
to_string() const103 Searchpath::to_string () const
104 {
105 string path;
106
107 for (vector<std::string>::const_iterator i = begin(); i != end(); ++i) {
108 path += *i;
109 path += G_SEARCHPATH_SEPARATOR;
110 }
111
112 path = path.substr (0, path.length() - 1); // drop final separator
113
114 return path;
115 }
116
117 Searchpath&
operator +=(const Searchpath & spath)118 Searchpath::operator+= (const Searchpath& spath)
119 {
120 for (vector<std::string>::const_iterator i = spath.begin(); i != spath.end(); ++i) {
121 add_directory (*i);
122 }
123 return *this;
124 }
125
126 Searchpath&
operator +=(const std::string & directory_path)127 Searchpath::operator+= (const std::string& directory_path)
128 {
129 add_directory (directory_path);
130 return *this;
131 }
132
133 const Searchpath
operator +(const std::string & directory_path)134 Searchpath::operator+ (const std::string& directory_path)
135 {
136 return Searchpath (*this) += directory_path;
137 }
138
139 const Searchpath
operator +(const Searchpath & spath)140 Searchpath::operator+ (const Searchpath& spath)
141 {
142 return Searchpath (*this) += spath;
143 }
144
145 Searchpath&
operator -=(const Searchpath & spath)146 Searchpath::operator-= (const Searchpath& spath)
147 {
148 remove_directories (spath);
149 return *this;
150 }
151
152 Searchpath&
operator -=(const std::string & directory_path)153 Searchpath::operator-= (const std::string& directory_path)
154 {
155 remove_directory (directory_path);
156 return *this;
157 }
158
159
160 Searchpath&
add_subdirectory_to_paths(const string & subdir)161 Searchpath::add_subdirectory_to_paths (const string& subdir)
162 {
163 for (vector<std::string>::iterator i = begin(); i != end(); ++i) {
164 // should these new paths just be added to the end of
165 // the search path rather than replace?
166 *i = Glib::build_filename (*i, subdir);
167 }
168
169 return *this;
170 }
171
172 bool
contains(const string & path) const173 Searchpath::contains (const string& path) const
174 {
175 std::vector<std::string>::const_iterator i = find(begin(), end(), path);
176
177 if (i == end()) {
178 return false;
179 }
180 return true;
181 }
182
183 /* This is not part of the Searchpath object, but is closely related to the
184 * whole idea, and we put it here for convenience.
185 */
186
187 void
export_search_path(const string & base_dir,const char * varname,const char * dir)188 export_search_path (const string& base_dir, const char* varname, const char* dir)
189 {
190 string path;
191 const char * cstr = g_getenv (varname);
192
193 if (cstr) {
194 path = cstr;
195 path += G_SEARCHPATH_SEPARATOR;
196 } else {
197 path = "";
198 }
199 path += base_dir;
200 path += dir;
201
202 g_setenv (varname, path.c_str(), 1);
203 }
204
205 } // namespace PBD
206