Add PBD API to hard-link files
[ardour.git] / libs / pbd / search_path.cc
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/tokenizer.h"
29 #include "pbd/search_path.h"
30 #include "pbd/error.h"
31
32 using namespace std;
33
34 namespace PBD {
35
36 Searchpath::Searchpath ()
37 {
38
39 }
40
41 Searchpath::Searchpath (const string& path)
42 {
43         vector<std::string> tmp;
44
45         if (tokenize (path, string(G_SEARCHPATH_SEPARATOR_S), std::back_inserter (tmp))) {
46                 add_directories (tmp);
47         }
48 }
49
50 Searchpath::Searchpath (const vector<std::string>& paths)
51 {
52         add_directories (paths);
53 }
54
55 void
56 Searchpath::remove_directory (const std::string& directory_path)
57 {
58         if (directory_path.empty()) {
59                 return;
60         }
61
62         for (vector<std::string>::iterator i = begin(); i != end();) {
63                 if (*i == directory_path) {
64                         i = erase (i);
65                 } else {
66                         ++i;
67                 }
68         }
69 }
70
71 void
72 Searchpath::remove_directories (const vector<std::string>& paths)
73 {
74         for(vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
75                 remove_directory (*i);
76         }
77 }
78
79 void
80 Searchpath::add_directory (const std::string& directory_path)
81 {
82         if (directory_path.empty()) {
83                 return;
84         }
85         for (vector<std::string>::const_iterator i = begin(); i != end(); ++i) {
86                 if (*i == directory_path) {
87                         return;
88                 }
89         }
90         push_back(directory_path);
91 }
92
93 void
94 Searchpath::add_directories (const vector<std::string>& paths)
95 {
96         for(vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
97                 add_directory (*i);
98         }
99 }
100
101 const string
102 Searchpath::to_string () const
103 {
104         string path;
105
106         for (vector<std::string>::const_iterator i = begin(); i != end(); ++i) {
107                 path += *i;
108                 path += G_SEARCHPATH_SEPARATOR;
109         }
110
111         path = path.substr (0, path.length() - 1); // drop final separator
112
113         return path;
114 }
115
116 Searchpath&
117 Searchpath::operator+= (const Searchpath& spath)
118 {
119         insert(end(), spath.begin(), spath.end());
120         return *this;
121 }
122
123 Searchpath&
124 Searchpath::operator+= (const std::string& directory_path)
125 {
126         add_directory (directory_path);
127         return *this;
128 }
129
130 const Searchpath
131 Searchpath::operator+ (const std::string& directory_path)
132 {
133         return Searchpath (*this) += directory_path;
134 }
135
136 const Searchpath
137 Searchpath::operator+ (const Searchpath& spath)
138 {
139         return Searchpath (*this) += spath;
140 }
141
142 Searchpath&
143 Searchpath::operator-= (const Searchpath& spath)
144 {
145         remove_directories (spath);
146         return *this;
147 }
148
149 Searchpath&
150 Searchpath::operator-= (const std::string& directory_path)
151 {
152         remove_directory (directory_path);
153         return *this;
154 }
155
156
157 Searchpath&
158 Searchpath::add_subdirectory_to_paths (const string& subdir)
159 {
160         for (vector<std::string>::iterator i = begin(); i != end(); ++i) {
161                 // should these new paths just be added to the end of
162                 // the search path rather than replace?
163                 *i = Glib::build_filename (*i, subdir);
164         }
165
166         return *this;
167 }
168
169 bool
170 Searchpath::contains (const string& path) const
171 {
172         std::vector<std::string>::const_iterator i = find(begin(), end(), path);
173
174         if (i == end()) {
175                 return false;
176         }
177         return true;
178 }
179
180 /* This is not part of the Searchpath object, but is closely related to the
181  * whole idea, and we put it here for convenience.
182  */
183
184 void
185 export_search_path (const string& base_dir, const char* varname, const char* dir)
186 {
187         string path;
188         const char * cstr = g_getenv (varname);
189
190         if (cstr) {
191                 path = cstr;
192                 path += G_SEARCHPATH_SEPARATOR;
193         } else {
194                 path = "";
195         }
196         path += base_dir;
197         path += dir;
198
199         g_setenv (varname, path.c_str(), 1);
200 }
201
202 } // namespace PBD