Panda3D

dSearchPath.cxx

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 &copy) :
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 &copy) {
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 &copy) :
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 &copy) {
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 
 All Classes Functions Variables Enumerations