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 
20 using std::ostream;
21 using std::string;
22 
23 /**
24  *
25  */
26 DSearchPath::Results::
27 Results() {
28 }
29 
30 /**
31  *
32  */
33 DSearchPath::Results::
34 Results(const DSearchPath::Results &copy) :
35  _files(copy._files)
36 {
37 }
38 
39 /**
40  *
41  */
42 void DSearchPath::Results::
43 operator = (const DSearchPath::Results &copy) {
44  _files = copy._files;
45 }
46 
47 /**
48  *
49  */
50 DSearchPath::Results::
51 ~Results() {
52 }
53 
54 /**
55  * Removes all the files from the list.
56  */
58 clear() {
59  _files.clear();
60 }
61 
62 /**
63  * Returns the number of files on the result list.
64  */
66 get_num_files() const {
67  return _files.size();
68 }
69 
70 /**
71  * Returns the nth file on the result list.
72  */
74 get_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  */
83 add_file(const Filename &file) {
84  _files.push_back(file);
85 }
86 
87 /**
88  *
89  */
90 void DSearchPath::Results::
91 output(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  */
108 void DSearchPath::Results::
109 write(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  */
122 DSearchPath::
123 DSearchPath(const string &path, const string &separator) {
124  append_path(path, separator);
125 }
126 
127 /**
128  *
129  */
130 DSearchPath::
131 DSearchPath(const Filename &directory) {
132  append_directory(directory);
133 }
134 
135 /**
136  * Removes all the directories from the search list.
137  */
138 void DSearchPath::
139 clear() {
140  _directories.clear();
141 }
142 
143 /**
144  * Adds a new directory to the end of the search list.
145  */
146 void DSearchPath::
147 append_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  */
154 void DSearchPath::
155 prepend_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  */
163 void DSearchPath::
164 append_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  */
193 void DSearchPath::
194 append_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  */
203 void DSearchPath::
204 prepend_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  */
216 bool DSearchPath::
217 is_empty() const {
218  return _directories.empty();
219 }
220 
221 /**
222  * Returns the number of directories on the search list.
223  */
224 size_t DSearchPath::
225 get_num_directories() const {
226  return _directories.size();
227 }
228 
229 /**
230  * Returns the nth directory on the search list.
231  */
232 const Filename &DSearchPath::
233 get_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  */
244 find_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  */
283 size_t DSearchPath::
284 find_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  */
322 void DSearchPath::
323 output(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  */
346 void DSearchPath::
347 write(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 directories from the search list.
bool is_empty() const
Returns true if the search list is empty, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void append_directory(const Filename &directory)
Adds a new directory to the end of the search list.
void prepend_path(const DSearchPath &path)
Adds all of the directories listed in the search path to the beginning of the search list.
bool is_fully_qualified() const
Returns true if the filename is fully qualified, e.g.
Definition: filename.I:562
const Filename & get_file(size_t n) const
Returns the nth file on the result list.
Definition: dSearchPath.cxx:74
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.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool is_local() const
Returns true if the filename is local, e.g.
Definition: filename.I:549
get_directory
Returns the nth directory on the search list.
Definition: dSearchPath.h:76
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition: dSearchPath.h:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
void prepend_directory(const Filename &directory)
Adds a new directory to the front of the search list.
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
void add_file(const Filename &file)
Adds a new file to the result list.
Definition: dSearchPath.cxx:83
void clear()
Removes all the files from the list.
Definition: dSearchPath.cxx:58
size_t get_num_files() const
Returns the number of files on the result list.
Definition: dSearchPath.cxx:66
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
Filename find_file(const Filename &filename) const
Searches all the directories in the search list for the indicated file, in order.