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