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