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