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