Panda3D
|
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 ©) : 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 ©) { 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 }