Panda3D
|
00001 // Filename: dSearchPath.cxx 00002 // Created by: drose (01Jul00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "dSearchPath.h" 00016 #include "filename.h" 00017 00018 #include <algorithm> 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: DSearchPath::Results::Constructor 00022 // Access: Published 00023 // Description: 00024 //////////////////////////////////////////////////////////////////// 00025 DSearchPath::Results:: 00026 Results() { 00027 } 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: DSearchPath::Results::Copy Constructor 00031 // Access: Published 00032 // Description: 00033 //////////////////////////////////////////////////////////////////// 00034 DSearchPath::Results:: 00035 Results(const DSearchPath::Results ©) : 00036 _files(copy._files) 00037 { 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: DSearchPath::Results::Copy Assignment Operator 00042 // Access: Published 00043 // Description: 00044 //////////////////////////////////////////////////////////////////// 00045 void DSearchPath::Results:: 00046 operator = (const DSearchPath::Results ©) { 00047 _files = copy._files; 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: DSearchPath::Results::Destructor 00052 // Access: Published 00053 // Description: 00054 //////////////////////////////////////////////////////////////////// 00055 DSearchPath::Results:: 00056 ~Results() { 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: DSearchPath::Results::clear 00061 // Access: Published 00062 // Description: Removes all the files from the list. 00063 //////////////////////////////////////////////////////////////////// 00064 void DSearchPath::Results:: 00065 clear() { 00066 _files.clear(); 00067 } 00068 00069 //////////////////////////////////////////////////////////////////// 00070 // Function: DSearchPath::Results::get_num_files 00071 // Access: Published 00072 // Description: Returns the number of files on the result list. 00073 //////////////////////////////////////////////////////////////////// 00074 int DSearchPath::Results:: 00075 get_num_files() const { 00076 return _files.size(); 00077 } 00078 00079 //////////////////////////////////////////////////////////////////// 00080 // Function: DSearchPath::Results::get_file 00081 // Access: Published 00082 // Description: Returns the nth file on the result list. 00083 //////////////////////////////////////////////////////////////////// 00084 const Filename &DSearchPath::Results:: 00085 get_file(int n) const { 00086 assert(n >= 0 && n < (int)_files.size()); 00087 return _files[n]; 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: DSearchPath::Results::add_file 00092 // Access: Published 00093 // Description: Adds a new file to the result list. 00094 //////////////////////////////////////////////////////////////////// 00095 void DSearchPath::Results:: 00096 add_file(const Filename &file) { 00097 _files.push_back(file); 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 // Function: DSearchPath::Results::output 00102 // Access: Published 00103 // Description: 00104 //////////////////////////////////////////////////////////////////// 00105 void DSearchPath::Results:: 00106 output(ostream &out) const { 00107 out << "[ "; 00108 if (!_files.empty()) { 00109 Files::const_iterator fi = _files.begin(); 00110 out << (*fi); 00111 ++fi; 00112 while (fi != _files.end()) { 00113 out << ", " << (*fi); 00114 ++fi; 00115 } 00116 } 00117 out << " ]"; 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: DSearchPath::Results::write 00122 // Access: Published 00123 // Description: 00124 //////////////////////////////////////////////////////////////////// 00125 void DSearchPath::Results:: 00126 write(ostream &out, int indent_level) const { 00127 Files::const_iterator fi; 00128 for (fi = _files.begin(); fi != _files.end(); ++fi) { 00129 for (int i = 0; i < indent_level; ++i) { 00130 out << ' '; 00131 } 00132 out << (*fi) << "\n"; 00133 } 00134 } 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: DSearchPath::Default Constructor 00138 // Access: Published 00139 // Description: Creates an empty search path. 00140 //////////////////////////////////////////////////////////////////// 00141 DSearchPath:: 00142 DSearchPath() { 00143 } 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: DSearchPath::Constructor 00147 // Access: Published 00148 // Description: 00149 //////////////////////////////////////////////////////////////////// 00150 DSearchPath:: 00151 DSearchPath(const string &path, const string &separator) { 00152 append_path(path, separator); 00153 } 00154 00155 //////////////////////////////////////////////////////////////////// 00156 // Function: DSearchPath::Constructor 00157 // Access: Published 00158 // Description: 00159 //////////////////////////////////////////////////////////////////// 00160 DSearchPath:: 00161 DSearchPath(const Filename &directory) { 00162 append_directory(directory); 00163 } 00164 00165 //////////////////////////////////////////////////////////////////// 00166 // Function: DSearchPath::Copy Constructor 00167 // Access: Published 00168 // Description: 00169 //////////////////////////////////////////////////////////////////// 00170 DSearchPath:: 00171 DSearchPath(const DSearchPath ©) : 00172 _directories(copy._directories) 00173 { 00174 } 00175 00176 //////////////////////////////////////////////////////////////////// 00177 // Function: DSearchPath::Copy Assignment Operator 00178 // Access: Published 00179 // Description: 00180 //////////////////////////////////////////////////////////////////// 00181 void DSearchPath:: 00182 operator = (const DSearchPath ©) { 00183 _directories = copy._directories; 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: DSearchPath::Destructor 00188 // Access: Published 00189 // Description: 00190 //////////////////////////////////////////////////////////////////// 00191 DSearchPath:: 00192 ~DSearchPath() { 00193 } 00194 00195 //////////////////////////////////////////////////////////////////// 00196 // Function: DSearchPath::clear 00197 // Access: Published 00198 // Description: Removes all the directories from the search list. 00199 //////////////////////////////////////////////////////////////////// 00200 void DSearchPath:: 00201 clear() { 00202 _directories.clear(); 00203 } 00204 00205 //////////////////////////////////////////////////////////////////// 00206 // Function: DSearchPath::append_directory 00207 // Access: Published 00208 // Description: Adds a new directory to the end of the search list. 00209 //////////////////////////////////////////////////////////////////// 00210 void DSearchPath:: 00211 append_directory(const Filename &directory) { 00212 _directories.push_back(directory); 00213 } 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: DSearchPath::prepend_directory 00217 // Access: Published 00218 // Description: Adds a new directory to the front of the search list. 00219 //////////////////////////////////////////////////////////////////// 00220 void DSearchPath:: 00221 prepend_directory(const Filename &directory) { 00222 _directories.insert(_directories.begin(), directory); 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: DSearchPath::append_path 00227 // Access: Published 00228 // Description: Adds all of the directories listed in the search path 00229 // to the end of the search list. 00230 //////////////////////////////////////////////////////////////////// 00231 void DSearchPath:: 00232 append_path(const string &path, const string &separator) { 00233 string pathsep = separator; 00234 if (pathsep.empty()) { 00235 pathsep = DEFAULT_PATHSEP; 00236 } 00237 00238 if (pathsep.empty()) { 00239 append_directory(path); 00240 00241 } else { 00242 size_t p = 0; 00243 while (p < path.length()) { 00244 size_t q = path.find_first_of(pathsep, p); 00245 if (q == string::npos) { 00246 _directories.push_back(Filename::from_os_specific(path.substr(p))); 00247 return; 00248 } 00249 if (q != p) { 00250 _directories.push_back(Filename::from_os_specific(path.substr(p, q - p))); 00251 } 00252 p = q + 1; 00253 } 00254 } 00255 } 00256 00257 //////////////////////////////////////////////////////////////////// 00258 // Function: DSearchPath::append_path 00259 // Access: Published 00260 // Description: Adds all of the directories listed in the search path 00261 // to the end of the search list. 00262 //////////////////////////////////////////////////////////////////// 00263 void DSearchPath:: 00264 append_path(const DSearchPath &path) { 00265 copy(path._directories.begin(), path._directories.end(), 00266 back_inserter(_directories)); 00267 } 00268 00269 //////////////////////////////////////////////////////////////////// 00270 // Function: DSearchPath::prepend_path 00271 // Access: Published 00272 // Description: Adds all of the directories listed in the search path 00273 // to the beginning of the search list. 00274 //////////////////////////////////////////////////////////////////// 00275 void DSearchPath:: 00276 prepend_path(const DSearchPath &path) { 00277 if (!path._directories.empty()) { 00278 Directories new_directories = path._directories; 00279 copy(_directories.begin(), _directories.end(), 00280 back_inserter(new_directories)); 00281 _directories.swap(new_directories); 00282 } 00283 } 00284 00285 //////////////////////////////////////////////////////////////////// 00286 // Function: DSearchPath::is_empty 00287 // Access: Published 00288 // Description: Returns true if the search list is empty, false 00289 // otherwise. 00290 //////////////////////////////////////////////////////////////////// 00291 bool DSearchPath:: 00292 is_empty() const { 00293 return _directories.empty(); 00294 } 00295 00296 //////////////////////////////////////////////////////////////////// 00297 // Function: DSearchPath::get_num_directories 00298 // Access: Published 00299 // Description: Returns the number of directories on the search list. 00300 //////////////////////////////////////////////////////////////////// 00301 int DSearchPath:: 00302 get_num_directories() const { 00303 return _directories.size(); 00304 } 00305 00306 //////////////////////////////////////////////////////////////////// 00307 // Function: DSearchPath::get_directory 00308 // Access: Published 00309 // Description: Returns the nth directory on the search list. 00310 //////////////////////////////////////////////////////////////////// 00311 const Filename &DSearchPath:: 00312 get_directory(int n) const { 00313 assert(n >= 0 && n < (int)_directories.size()); 00314 return _directories[n]; 00315 } 00316 00317 //////////////////////////////////////////////////////////////////// 00318 // Function: DSearchPath::find_file 00319 // Access: Published 00320 // Description: Searches all the directories in the search list for 00321 // the indicated file, in order. Returns the full 00322 // matching pathname of the first match if found, or the 00323 // empty string if not found. 00324 //////////////////////////////////////////////////////////////////// 00325 Filename DSearchPath:: 00326 find_file(const Filename &filename) const { 00327 if (filename.is_local()) { 00328 if (_directories.empty()) { 00329 // Let's say an empty search path is the same as a search path 00330 // containing just ".". 00331 if (filename.exists()) { 00332 return filename; 00333 } 00334 00335 } else { 00336 Directories::const_iterator di; 00337 for (di = _directories.begin(); di != _directories.end(); ++di) { 00338 Filename match((*di), filename); 00339 if (match.exists()) { 00340 if ((*di) == "." && filename.is_fully_qualified()) { 00341 // A special case for the "." directory: to avoid prefixing 00342 // an endless stream of ./ in front of files, if the 00343 // filename already has a ./ prefixed 00344 // (i.e. is_fully_qualified() is true), we don't 00345 // prefix another one. 00346 return filename; 00347 } else { 00348 return match; 00349 } 00350 } 00351 } 00352 } 00353 } 00354 00355 return string(); 00356 } 00357 00358 //////////////////////////////////////////////////////////////////// 00359 // Function: DSearchPath::find_all_files 00360 // Access: Published 00361 // Description: Searches all the directories in the search list for 00362 // the indicated file, in order. Fills up the results 00363 // list with *all* of the matching filenames found, if 00364 // any. Returns the number of matches found. 00365 // 00366 // It is the responsibility of the the caller to clear 00367 // the results list first; otherwise, the newly-found 00368 // files will be appended to the list. 00369 //////////////////////////////////////////////////////////////////// 00370 int DSearchPath:: 00371 find_all_files(const Filename &filename, 00372 DSearchPath::Results &results) const { 00373 int num_added = 0; 00374 00375 if (filename.is_local()) { 00376 if (_directories.empty()) { 00377 // Let's say an empty search path is the same as a search path 00378 // containing just ".". 00379 if (filename.exists()) { 00380 results.add_file(filename); 00381 } 00382 00383 } else { 00384 Directories::const_iterator di; 00385 for (di = _directories.begin(); di != _directories.end(); ++di) { 00386 Filename match((*di), filename); 00387 if (match.exists()) { 00388 if ((*di) == "." && filename.is_fully_qualified()) { 00389 // A special case for the "." directory: to avoid prefixing 00390 // an endless stream of ./ in front of files, if the 00391 // filename already has a ./ prefixed 00392 // (i.e. is_fully_qualified() is true), we don't 00393 // prefix another one. 00394 results.add_file(filename); 00395 } else { 00396 results.add_file(match); 00397 } 00398 num_added++; 00399 } 00400 } 00401 } 00402 } 00403 00404 return num_added; 00405 } 00406 00407 //////////////////////////////////////////////////////////////////// 00408 // Function: DSearchPath::output 00409 // Access: Published 00410 // Description: 00411 //////////////////////////////////////////////////////////////////// 00412 void DSearchPath:: 00413 output(ostream &out, const string &separator) const { 00414 string pathsep = separator; 00415 if (pathsep.empty()) { 00416 pathsep = DEFAULT_PATHSEP; 00417 if (!pathsep.empty()) { 00418 pathsep = pathsep[0]; 00419 } 00420 } 00421 00422 if (!_directories.empty()) { 00423 Directories::const_iterator di = _directories.begin(); 00424 out << (*di); 00425 ++di; 00426 while (di != _directories.end()) { 00427 out << pathsep << (*di); 00428 ++di; 00429 } 00430 } 00431 } 00432 00433 //////////////////////////////////////////////////////////////////// 00434 // Function: DSearchPath::write 00435 // Access: Published 00436 // Description: 00437 //////////////////////////////////////////////////////////////////// 00438 void DSearchPath:: 00439 write(ostream &out, int indent_level) const { 00440 Directories::const_iterator di; 00441 for (di = _directories.begin(); di != _directories.end(); ++di) { 00442 for (int i = 0; i < indent_level; ++i) { 00443 out << ' '; 00444 } 00445 out << (*di) << "\n"; 00446 } 00447 } 00448 00449