Panda3D
dSearchPath.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file dSearchPath.cxx
10 * @author drose
11 * @date 2000-07-01
12 */
13
14#include "dSearchPath.h"
15#include "filename.h"
16
17#include <algorithm>
18#include <iterator>
19
20using std::ostream;
21using std::string;
22
23/**
24 *
25 */
26DSearchPath::Results::
27Results() {
28}
29
30/**
31 *
32 */
33DSearchPath::Results::
34Results(const DSearchPath::Results &copy) :
35 _files(copy._files)
36{
37}
38
39/**
40 *
41 */
42void DSearchPath::Results::
43operator = (const DSearchPath::Results &copy) {
44 _files = copy._files;
45}
46
47/**
48 *
49 */
50DSearchPath::Results::
51~Results() {
52}
53
54/**
55 * Removes all the files from the list.
56 */
58clear() {
59 _files.clear();
60}
61
62/**
63 * Returns the number of files on the result list.
64 */
66get_num_files() const {
67 return _files.size();
68}
69
70/**
71 * Returns the nth file on the result list.
72 */
74get_file(size_t n) const {
75 assert(n < _files.size());
76 return _files[n];
77}
78
79/**
80 * Adds a new file to the result list.
81 */
83add_file(const Filename &file) {
84 _files.push_back(file);
85}
86
87/**
88 *
89 */
90void DSearchPath::Results::
91output(ostream &out) const {
92 out << "[ ";
93 if (!_files.empty()) {
94 Files::const_iterator fi = _files.begin();
95 out << (*fi);
96 ++fi;
97 while (fi != _files.end()) {
98 out << ", " << (*fi);
99 ++fi;
100 }
101 }
102 out << " ]";
103}
104
105/**
106 *
107 */
108void DSearchPath::Results::
109write(ostream &out, int indent_level) const {
110 Files::const_iterator fi;
111 for (fi = _files.begin(); fi != _files.end(); ++fi) {
112 for (int i = 0; i < indent_level; ++i) {
113 out << ' ';
114 }
115 out << (*fi) << "\n";
116 }
117}
118
119/**
120 *
121 */
122DSearchPath::
123DSearchPath(const string &path, const string &separator) {
124 append_path(path, separator);
125}
126
127/**
128 *
129 */
130DSearchPath::
131DSearchPath(const Filename &directory) {
132 append_directory(directory);
133}
134
135/**
136 * Removes all the directories from the search list.
137 */
139clear() {
140 _directories.clear();
141}
142
143/**
144 * Adds a new directory to the end of the search list.
145 */
147append_directory(const Filename &directory) {
148 _directories.push_back(directory);
149}
150
151/**
152 * Adds a new directory to the front of the search list.
153 */
155prepend_directory(const Filename &directory) {
156 _directories.insert(_directories.begin(), directory);
157}
158
159/**
160 * Adds all of the directories listed in the search path to the end of the
161 * search list.
162 */
164append_path(const string &path, const string &separator) {
165 string pathsep = separator;
166 if (pathsep.empty()) {
167 pathsep = DEFAULT_PATHSEP;
168 }
169
170 if (pathsep.empty()) {
171 append_directory(path);
172
173 } else {
174 size_t p = 0;
175 while (p < path.length()) {
176 size_t q = path.find_first_of(pathsep, p);
177 if (q == string::npos) {
178 _directories.push_back(Filename::from_os_specific(path.substr(p)));
179 return;
180 }
181 if (q != p) {
182 _directories.push_back(Filename::from_os_specific(path.substr(p, q - p)));
183 }
184 p = q + 1;
185 }
186 }
187}
188
189/**
190 * Adds all of the directories listed in the search path to the end of the
191 * search list.
192 */
194append_path(const DSearchPath &path) {
195 std::copy(path._directories.begin(), path._directories.end(),
196 std::back_inserter(_directories));
197}
198
199/**
200 * Adds all of the directories listed in the search path to the beginning of
201 * the search list.
202 */
204prepend_path(const DSearchPath &path) {
205 if (!path._directories.empty()) {
206 Directories new_directories = path._directories;
207 std::copy(_directories.begin(), _directories.end(),
208 std::back_inserter(new_directories));
209 _directories.swap(new_directories);
210 }
211}
212
213/**
214 * Returns true if the search list is empty, false otherwise.
215 */
217is_empty() const {
218 return _directories.empty();
219}
220
221/**
222 * Returns the number of directories on the search list.
223 */
224size_t DSearchPath::
225get_num_directories() const {
226 return _directories.size();
227}
228
229/**
230 * Returns the nth directory on the search list.
231 */
233get_directory(size_t n) const {
234 assert(n < _directories.size());
235 return _directories[n];
236}
237
238/**
239 * Searches all the directories in the search list for the indicated file, in
240 * order. Returns the full matching pathname of the first match if found, or
241 * the empty string if not found.
242 */
244find_file(const Filename &filename) const {
245 if (filename.is_local()) {
246 if (_directories.empty()) {
247 // Let's say an empty search path is the same as a search path
248 // containing just ".".
249 if (filename.exists()) {
250 return filename;
251 }
252
253 } else {
254 Directories::const_iterator di;
255 for (di = _directories.begin(); di != _directories.end(); ++di) {
256 Filename match((*di), filename);
257 if (match.exists()) {
258 if ((*di) == "." && filename.is_fully_qualified()) {
259 // A special case for the "." directory: to avoid prefixing an
260 // endless stream of . in front of files, if the filename already
261 // has a . prefixed (i.e. is_fully_qualified() is true), we don't
262 // prefix another one.
263 return filename;
264 } else {
265 return match;
266 }
267 }
268 }
269 }
270 }
271
272 return string();
273}
274
275/**
276 * Searches all the directories in the search list for the indicated file, in
277 * order. Fills up the results list with *all* of the matching filenames
278 * found, if any. Returns the number of matches found.
279 *
280 * It is the responsibility of the the caller to clear the results list first;
281 * otherwise, the newly-found files will be appended to the list.
282 */
284find_all_files(const Filename &filename,
285 DSearchPath::Results &results) const {
286 size_t num_added = 0;
287
288 if (filename.is_local()) {
289 if (_directories.empty()) {
290 // Let's say an empty search path is the same as a search path
291 // containing just ".".
292 if (filename.exists()) {
293 results.add_file(filename);
294 }
295
296 } else {
297 Directories::const_iterator di;
298 for (di = _directories.begin(); di != _directories.end(); ++di) {
299 Filename match((*di), filename);
300 if (match.exists()) {
301 if ((*di) == "." && filename.is_fully_qualified()) {
302 // A special case for the "." directory: to avoid prefixing an
303 // endless stream of . in front of files, if the filename already
304 // has a . prefixed (i.e. is_fully_qualified() is true), we don't
305 // prefix another one.
306 results.add_file(filename);
307 } else {
308 results.add_file(match);
309 }
310 num_added++;
311 }
312 }
313 }
314 }
315
316 return num_added;
317}
318
319/**
320 *
321 */
322void DSearchPath::
323output(ostream &out, const string &separator) const {
324 string pathsep = separator;
325 if (pathsep.empty()) {
326 pathsep = DEFAULT_PATHSEP;
327 if (!pathsep.empty()) {
328 pathsep = pathsep[0];
329 }
330 }
331
332 if (!_directories.empty()) {
333 Directories::const_iterator di = _directories.begin();
334 out << (*di);
335 ++di;
336 while (di != _directories.end()) {
337 out << pathsep << (*di);
338 ++di;
339 }
340 }
341}
342
343/**
344 *
345 */
346void DSearchPath::
347write(ostream &out, int indent_level) const {
348 Directories::const_iterator di;
349 for (di = _directories.begin(); di != _directories.end(); ++di) {
350 for (int i = 0; i < indent_level; ++i) {
351 out << ' ';
352 }
353 out << (*di) << "\n";
354 }
355}
void clear()
Removes all the files from the list.
Definition: dSearchPath.cxx:58
const Filename & get_file(size_t n) const
Returns the nth file on the result list.
Definition: dSearchPath.cxx:74
void add_file(const Filename &file)
Adds a new file to the result list.
Definition: dSearchPath.cxx:83
size_t get_num_files() const
Returns the number of files on the result list.
Definition: dSearchPath.cxx:66
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition: dSearchPath.h:28
Filename find_file(const Filename &filename) const
Searches all the directories in the search list for the indicated file, in order.
bool is_empty() const
Returns true if the search list is empty, false otherwise.
void append_path(const std::string &path, const std::string &separator=std::string())
Adds all of the directories listed in the search path to the end of the search list.
get_num_directories
Returns the number of directories on the search list.
Definition: dSearchPath.h:76
size_t find_all_files(const Filename &filename, Results &results) const
Searches all the directories in the search list for the indicated file, in order.
void prepend_path(const DSearchPath &path)
Adds all of the directories listed in the search path to the beginning of the search list.
void prepend_directory(const Filename &directory)
Adds a new directory to the front of the search list.
void clear()
Removes all the directories from the search list.
void append_directory(const Filename &directory)
Adds a new directory to the end of the search list.
get_directory
Returns the nth directory on the search list.
Definition: dSearchPath.h:76
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool is_fully_qualified() const
Returns true if the filename is fully qualified, e.g.
Definition: filename.I:562
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
bool is_local() const
Returns true if the filename is local, e.g.
Definition: filename.I:549
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.