Panda3D

filename.I

00001 // Filename: filename.I
00002 // Created by:  drose (18Jan99)
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 ////////////////////////////////////////////////////////////////////
00016 //     Function: Filename::Constructor
00017 //       Access: Published
00018 //  Description:
00019 ////////////////////////////////////////////////////////////////////
00020 INLINE Filename::
00021 Filename(const string &filename) {
00022   _flags = 0;
00023   (*this) = filename;
00024 }
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: Filename::Constructor
00028 //       Access: Published
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 INLINE Filename::
00032 Filename(const char *filename) {
00033   _flags = 0;
00034   (*this) = filename;
00035 }
00036 
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: Filename::Copy Constructor
00040 //       Access: Published
00041 //  Description:
00042 ////////////////////////////////////////////////////////////////////
00043 INLINE Filename::
00044 Filename(const Filename &copy) :
00045   _filename(copy._filename.c_str()),
00046   _dirname_end(copy._dirname_end),
00047   _basename_start(copy._basename_start),
00048   _basename_end(copy._basename_end),
00049   _extension_start(copy._extension_start),
00050   _hash_start(copy._hash_start),
00051   _hash_end(copy._hash_end),
00052   _flags(copy._flags)
00053 {
00054 }
00055 
00056 ////////////////////////////////////////////////////////////////////
00057 //     Function: Filename::text_filename named constructor
00058 //       Access: Published
00059 //  Description:
00060 ////////////////////////////////////////////////////////////////////
00061 INLINE Filename Filename::
00062 text_filename(const string &filename) {
00063   Filename result(filename);
00064   result.set_text();
00065   return result;
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: Filename::binary_filename named constructor
00070 //       Access: Published
00071 //  Description:
00072 ////////////////////////////////////////////////////////////////////
00073 INLINE Filename Filename::
00074 binary_filename(const string &filename) {
00075   Filename result(filename);
00076   result.set_binary();
00077   return result;
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 //     Function: Filename::dso_filename named constructor
00082 //       Access: Published
00083 //  Description:
00084 ////////////////////////////////////////////////////////////////////
00085 INLINE Filename Filename::
00086 dso_filename(const string &filename) {
00087   Filename result(filename);
00088   result.set_type(T_dso);
00089   return result;
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: Filename::executable_filename named constructor
00094 //       Access: Published
00095 //  Description:
00096 ////////////////////////////////////////////////////////////////////
00097 INLINE Filename Filename::
00098 executable_filename(const string &filename) {
00099   Filename result(filename);
00100   result.set_type(T_executable);
00101   return result;
00102 }
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: Filename::pattern_filename named constructor
00106 //       Access: Published
00107 //  Description: Constructs a filename that represents a sequence of
00108 //               numbered files.  See set_pattern().
00109 ////////////////////////////////////////////////////////////////////
00110 INLINE Filename Filename::
00111 pattern_filename(const string &filename) {
00112   Filename result(filename);
00113   result.set_pattern(true);
00114   return result;
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: Filename::Destructor
00119 //       Access: Published
00120 //  Description:
00121 ////////////////////////////////////////////////////////////////////
00122 INLINE Filename::
00123 ~Filename() {
00124 }
00125 
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: Filename::Assignment operator
00129 //       Access: Published
00130 //  Description:
00131 ////////////////////////////////////////////////////////////////////
00132 INLINE Filename &Filename::
00133 operator = (const string &filename) {
00134   _filename = filename;
00135 
00136   locate_basename();
00137   locate_extension();
00138   locate_hash();
00139   return *this;
00140 }
00141 
00142 ////////////////////////////////////////////////////////////////////
00143 //     Function: Filename::Assignment operator
00144 //       Access: Published
00145 //  Description:
00146 ////////////////////////////////////////////////////////////////////
00147 INLINE Filename &Filename::
00148 operator = (const char *filename) {
00149   assert(filename != NULL);
00150   return (*this) = string(filename);
00151 }
00152 
00153 ////////////////////////////////////////////////////////////////////
00154 //     Function: Filename::Copy assignment operator
00155 //       Access: Published
00156 //  Description:
00157 ////////////////////////////////////////////////////////////////////
00158 INLINE Filename &Filename::
00159 operator = (const Filename &copy) {
00160   _filename = copy._filename;
00161   _dirname_end = copy._dirname_end;
00162   _basename_start = copy._basename_start;
00163   _basename_end = copy._basename_end;
00164   _extension_start = copy._extension_start;
00165   _hash_start = copy._hash_start;
00166   _hash_end = copy._hash_end;
00167   _flags = copy._flags;
00168   return *this;
00169 }
00170 
00171 
00172 ////////////////////////////////////////////////////////////////////
00173 //     Function: Filename::string typecast operator
00174 //       Access: Published
00175 //  Description:
00176 ////////////////////////////////////////////////////////////////////
00177 INLINE Filename::
00178 operator const string & () const {
00179   return _filename;
00180 }
00181 
00182 ////////////////////////////////////////////////////////////////////
00183 //     Function: Filename::c_str
00184 //       Access: Published
00185 //  Description:
00186 ////////////////////////////////////////////////////////////////////
00187 INLINE const char *Filename::
00188 c_str() const {
00189   return _filename.c_str();
00190 }
00191 
00192 ////////////////////////////////////////////////////////////////////
00193 //     Function: Filename::empty
00194 //       Access: Published
00195 //  Description:
00196 ////////////////////////////////////////////////////////////////////
00197 INLINE bool Filename::
00198 empty() const {
00199   return _filename.empty();
00200 }
00201 
00202 ////////////////////////////////////////////////////////////////////
00203 //     Function: Filename::length
00204 //       Access: Published
00205 //  Description:
00206 ////////////////////////////////////////////////////////////////////
00207 INLINE size_t Filename::
00208 length() const {
00209   return _filename.length();
00210 }
00211 
00212 ////////////////////////////////////////////////////////////////////
00213 //     Function: Filename::Indexing operator
00214 //       Access: Published
00215 //  Description:
00216 ////////////////////////////////////////////////////////////////////
00217 INLINE char Filename::
00218 operator [] (int n) const {
00219   assert(n >= 0 && n < (int)_filename.length());
00220   return _filename[n];
00221 }
00222 
00223 ////////////////////////////////////////////////////////////////////
00224 //     Function: Filename::substr
00225 //       Access: Published
00226 //  Description:
00227 ////////////////////////////////////////////////////////////////////
00228 INLINE string Filename::
00229 substr(size_t begin, size_t end) const {
00230   return _filename.substr(begin, end);
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: Filename::operator +=
00235 //       Access: Published
00236 //  Description: Appends the other filename onto the end of this one.
00237 //               This does not introduce an intervening slash, but see
00238 //               the Filename constructor that takes two parameters.
00239 ////////////////////////////////////////////////////////////////////
00240 INLINE void Filename::
00241 operator += (const string &other) {
00242   _filename += other;
00243   locate_basename();
00244   locate_extension();
00245   locate_hash();
00246 }
00247 
00248 ////////////////////////////////////////////////////////////////////
00249 //     Function: Filename::operator +
00250 //       Access: Published
00251 //  Description: Returns a new Filename representing the concatenation
00252 //               of the two filenames.
00253 ////////////////////////////////////////////////////////////////////
00254 INLINE Filename Filename::
00255 operator + (const string &other) const {
00256   Filename a(*this);
00257   a += other;
00258   return a;
00259 }
00260 
00261 
00262 ////////////////////////////////////////////////////////////////////
00263 //     Function: Filename::get_fullpath
00264 //       Access: Published
00265 //  Description: Returns the entire filename: directory, basename,
00266 //               extension.  This is the same thing returned by the
00267 //               string typecast operator, so this function is a
00268 //               little redundant.
00269 ////////////////////////////////////////////////////////////////////
00270 INLINE string Filename::
00271 get_fullpath() const {
00272   return _filename.c_str();
00273 }
00274 
00275 ////////////////////////////////////////////////////////////////////
00276 //     Function: Filename::get_dirname
00277 //       Access: Published
00278 //  Description: Returns the directory part of the filename.  This is
00279 //               everything in the filename up to, but not including
00280 //               the rightmost slash.
00281 ////////////////////////////////////////////////////////////////////
00282 INLINE string Filename::
00283 get_dirname() const {
00284   return _filename.substr(0, _dirname_end);
00285 }
00286 
00287 ////////////////////////////////////////////////////////////////////
00288 //     Function: Filename::get_basename
00289 //       Access: Published
00290 //  Description: Returns the basename part of the filename.  This is
00291 //               everything in the filename after the rightmost slash,
00292 //               including any extensions.
00293 ////////////////////////////////////////////////////////////////////
00294 INLINE string Filename::
00295 get_basename() const {
00296   return _filename.substr(_basename_start);
00297 }
00298 
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: Filename::get_fullpath_wo_extension
00302 //       Access: Published
00303 //  Description: Returns the full filename--directory and basename
00304 //               parts--except for the extension.
00305 ////////////////////////////////////////////////////////////////////
00306 INLINE string Filename::
00307 get_fullpath_wo_extension() const {
00308   return _filename.substr(0, _basename_end);
00309 }
00310 
00311 
00312 ////////////////////////////////////////////////////////////////////
00313 //     Function: Filename::get_basename_wo_extension
00314 //       Access: Published
00315 //  Description: Returns the basename part of the filename, without
00316 //               the file extension.
00317 ////////////////////////////////////////////////////////////////////
00318 INLINE string Filename::
00319 get_basename_wo_extension() const {
00320   if (_basename_end == string::npos) {
00321     return _filename.substr(_basename_start);
00322   } else {
00323     return _filename.substr(_basename_start, _basename_end - _basename_start);
00324   }
00325 }
00326 
00327 
00328 ////////////////////////////////////////////////////////////////////
00329 //     Function: Filename::get_extension
00330 //       Access: Published
00331 //  Description: Returns the file extension.  This is everything after
00332 //               the rightmost dot, if there is one, or the empty
00333 //               string if there is not.
00334 ////////////////////////////////////////////////////////////////////
00335 INLINE string Filename::
00336 get_extension() const {
00337   if (_extension_start == string::npos) {
00338     return string();
00339   } else {
00340     return _filename.substr(_extension_start);
00341   }
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: Filename::set_binary
00346 //       Access: Published
00347 //  Description: Indicates that the filename represents a binary file.
00348 //               This is primarily relevant to the read_file() and
00349 //               write_file() methods, so they can set the appropriate
00350 //               flags to the OS.
00351 ////////////////////////////////////////////////////////////////////
00352 INLINE void Filename::
00353 set_binary() {
00354   _flags = (_flags & ~F_text) | F_binary;
00355 }
00356 
00357 ////////////////////////////////////////////////////////////////////
00358 //     Function: Filename::set_text
00359 //       Access: Published
00360 //  Description: Indicates that the filename represents a text file.
00361 //               This is primarily relevant to the read_file() and
00362 //               write_file() methods, so they can set the appropriate
00363 //               flags to the OS.
00364 ////////////////////////////////////////////////////////////////////
00365 INLINE void Filename::
00366 set_text() {
00367   _flags = (_flags & ~F_binary) | F_text;
00368 }
00369 
00370 ////////////////////////////////////////////////////////////////////
00371 //     Function: Filename::is_binary
00372 //       Access: Published
00373 //  Description: Returns true if the Filename has been indicated to
00374 //               represent a binary file via a previous call to
00375 //               set_binary().  It is possible that neither
00376 //               is_binary() nor is_text() will be true, if neither
00377 //               set_binary() nor set_text() was ever called.
00378 ////////////////////////////////////////////////////////////////////
00379 INLINE bool Filename::
00380 is_binary() const {
00381   return ((_flags & F_binary) != 0);
00382 }
00383 
00384 ////////////////////////////////////////////////////////////////////
00385 //     Function: Filename::is_text
00386 //       Access: Published
00387 //  Description: Returns true if the Filename has been indicated to
00388 //               represent a text file via a previous call to
00389 //               set_text().  It is possible that neither is_binary()
00390 //               nor is_text() will be true, if neither set_binary()
00391 //               nor set_text() was ever called.
00392 ////////////////////////////////////////////////////////////////////
00393 INLINE bool Filename::
00394 is_text() const {
00395   return ((_flags & F_text) != 0);
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: Filename::set_type
00400 //       Access: Published
00401 //  Description: Sets the type of the file represented by the
00402 //               filename.  This is useful for to_os_specific(),
00403 //               resolve_filename(), test_existence(), and all such
00404 //               real-world access functions.  It helps the Filename
00405 //               know how to map the internal filename to the
00406 //               OS-specific filename (for instance, maybe executables
00407 //               should have an .exe extension).
00408 ////////////////////////////////////////////////////////////////////
00409 INLINE void Filename::
00410 set_type(Filename::Type type) {
00411   _flags = (_flags & ~F_type) | type;
00412   switch (type) {
00413   case T_dso:
00414   case T_executable:
00415     set_binary();
00416 
00417   case T_general:
00418     break;
00419   }
00420 }
00421 
00422 ////////////////////////////////////////////////////////////////////
00423 //     Function: Filename::get_type
00424 //       Access: Published
00425 //  Description: Returns the type of the file represented by the
00426 //               filename, as previously set by set_type().
00427 ////////////////////////////////////////////////////////////////////
00428 INLINE Filename::Type Filename::
00429 get_type() const {
00430   return (Type)(_flags & (int)F_type);
00431 }
00432 
00433 ////////////////////////////////////////////////////////////////////
00434 //     Function: Filename::set_pattern
00435 //       Access: Published
00436 //  Description: Sets the flag indicating whether this is a filename
00437 //               pattern.  When this is true, the filename is
00438 //               understood to be a placeholder for a numbered
00439 //               sequence of filename, such as an image sequence.  In
00440 //               this case, a sequence of one or more hash characters
00441 //               ("#") should appear in the filename string; these
00442 //               characters will be filled in with the corresponding
00443 //               number (or more) of digits representing the sequence
00444 //               number.  Sequence numbers always begin counting at 0.
00445 //
00446 //               When this is true, methods like has_hash() and
00447 //               get_hash_to_end() and get_filename_index() may be
00448 //               called.  Methods like is_exists() will implicitly
00449 //               test for existance of filename sequence 0.
00450 ////////////////////////////////////////////////////////////////////
00451 INLINE void Filename::
00452 set_pattern(bool pattern) {
00453   if (pattern != get_pattern()) {
00454     if (pattern) {
00455       _flags |= F_pattern;
00456     } else {
00457       _flags &= ~F_pattern;
00458     }
00459     locate_hash();
00460   }
00461 }
00462 
00463 ////////////////////////////////////////////////////////////////////
00464 //     Function: Filename::get_pattern
00465 //       Access: Published
00466 //  Description: Returns the flag indicating whether this is a
00467 //               filename pattern.  See set_pattern().
00468 ////////////////////////////////////////////////////////////////////
00469 INLINE bool Filename::
00470 get_pattern() const {
00471   return (_flags & F_pattern) != 0;
00472 }
00473 
00474 ////////////////////////////////////////////////////////////////////
00475 //     Function: Filename::has_hash
00476 //       Access: Published
00477 //  Description: Returns true if the filename is indicated to be a
00478 //               filename pattern (that is, set_pattern(true) was
00479 //               called), and the filename pattern did include a
00480 //               sequence of hash marks, or false if it was not a
00481 //               filename pattern or did not include hash marks.  If
00482 //               this is true, then get_filename_index() will return a
00483 //               different filename each time.
00484 ////////////////////////////////////////////////////////////////////
00485 INLINE bool Filename::
00486 has_hash() const {
00487   return (_hash_start != _hash_end);
00488 }
00489 
00490 ////////////////////////////////////////////////////////////////////
00491 //     Function: Filename::get_hash_to_end
00492 //       Access: Published
00493 //  Description: Returns the part of the filename beginning at the
00494 //               hash sequence (if any), and continuing to the end of
00495 //               the filename.
00496 ////////////////////////////////////////////////////////////////////
00497 INLINE string Filename::
00498 get_hash_to_end() const {
00499   return _filename.substr(_hash_start);
00500 }
00501 
00502 ////////////////////////////////////////////////////////////////////
00503 //     Function: Filename::is_local
00504 //       Access: Published
00505 //  Description: Returns true if the filename is local, e.g. does not
00506 //               begin with a slash, or false if the filename is fully
00507 //               specified from the root.
00508 ////////////////////////////////////////////////////////////////////
00509 INLINE bool Filename::
00510 is_local() const {
00511   return _filename.empty() || _filename[0] != '/';
00512 }
00513 
00514 ////////////////////////////////////////////////////////////////////
00515 //     Function: Filename::is_fully_qualified
00516 //       Access: Published
00517 //  Description: Returns true if the filename is fully qualified,
00518 //               e.g. begins with a slash.  This is almost, but not
00519 //               quite, the same thing as !is_local().  It's not
00520 //               exactly the same because a special case is made for
00521 //               filenames that begin with a single dot followed by a
00522 //               slash--these are considered to be fully qualified
00523 //               (they are explicitly relative to the current
00524 //               directory, and do not refer to a filename on a search
00525 //               path somewhere).
00526 ////////////////////////////////////////////////////////////////////
00527 INLINE bool Filename::
00528 is_fully_qualified() const {
00529   return
00530     (_filename.size() > 2 && _filename[0] == '.' && _filename[1] == '/') ||
00531     (!_filename.empty() && _filename[0] == '/');
00532 }
00533 
00534 ////////////////////////////////////////////////////////////////////
00535 //     Function: Filename::Equality operator
00536 //       Access: Published
00537 //  Description:
00538 ////////////////////////////////////////////////////////////////////
00539 INLINE bool Filename::
00540 operator == (const string &other) const {
00541   return (*(string *)this) == other;
00542 }
00543 
00544 ////////////////////////////////////////////////////////////////////
00545 //     Function: Filename::Inequality operator
00546 //       Access: Published
00547 //  Description:
00548 ////////////////////////////////////////////////////////////////////
00549 INLINE bool Filename::
00550 operator != (const string &other) const {
00551   return (*(string *)this) != other;
00552 }
00553 
00554 ////////////////////////////////////////////////////////////////////
00555 //     Function: Filename::Ordering operator
00556 //       Access: Published
00557 //  Description:
00558 ////////////////////////////////////////////////////////////////////
00559 INLINE bool Filename::
00560 operator < (const string &other) const {
00561   return (*(string *)this) < other;
00562 }
00563 
00564 ////////////////////////////////////////////////////////////////////
00565 //     Function: Filename::compare_to
00566 //       Access: Published
00567 //  Description:
00568 ////////////////////////////////////////////////////////////////////
00569 INLINE int Filename::
00570 compare_to(const Filename &other) const {
00571   return strcmp(_filename.c_str(), other._filename.c_str());
00572 }
00573 
00574 
00575 ////////////////////////////////////////////////////////////////////
00576 //     Function: Filename::__nonzero__
00577 //       Access: Published
00578 //  Description: Returns true if the Filename is valid (not empty),
00579 //               or false if it is an empty string.
00580 //
00581 //               This implements the Python equivalent to operator
00582 //               bool.  Defining an actual operator bool method for
00583 //               C++ use would work too, but it seems to cause too
00584 //               many ambiguities for the C++ compiler, so we use this
00585 //               Python-only approach instead.
00586 ////////////////////////////////////////////////////////////////////
00587 INLINE bool Filename::
00588 __nonzero__() const {
00589   return !_filename.empty();
00590 }
00591 
00592 ////////////////////////////////////////////////////////////////////
00593 //     Function: Filename::output
00594 //       Access: Published
00595 //  Description:
00596 ////////////////////////////////////////////////////////////////////
00597 INLINE void Filename::
00598 output(ostream &out) const {
00599   out << _filename;
00600 }
 All Classes Functions Variables Enumerations