filename.I 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // Filename: filename.I
  2. // Created by: drose (18Jan99)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. ////////////////////////////////////////////////////////////////////
  15. // Function: Filename::Constructor
  16. // Access: Published
  17. // Description:
  18. ////////////////////////////////////////////////////////////////////
  19. INLINE Filename::
  20. Filename(const string &filename) {
  21. _flags = 0;
  22. (*this) = filename;
  23. }
  24. ////////////////////////////////////////////////////////////////////
  25. // Function: Filename::Constructor
  26. // Access: Published
  27. // Description:
  28. ////////////////////////////////////////////////////////////////////
  29. INLINE Filename::
  30. Filename(const char *filename) {
  31. _flags = 0;
  32. (*this) = filename;
  33. }
  34. ////////////////////////////////////////////////////////////////////
  35. // Function: Filename::Copy Constructor
  36. // Access: Published
  37. // Description:
  38. ////////////////////////////////////////////////////////////////////
  39. INLINE Filename::
  40. Filename(const Filename &copy) :
  41. _filename(copy._filename),
  42. _dirname_end(copy._dirname_end),
  43. _basename_start(copy._basename_start),
  44. _basename_end(copy._basename_end),
  45. _extension_start(copy._extension_start),
  46. _hash_start(copy._hash_start),
  47. _hash_end(copy._hash_end),
  48. _flags(copy._flags)
  49. {
  50. }
  51. ////////////////////////////////////////////////////////////////////
  52. // Function: Filename::text_filename named constructor
  53. // Access: Published
  54. // Description:
  55. ////////////////////////////////////////////////////////////////////
  56. INLINE Filename Filename::
  57. text_filename(const string &filename) {
  58. Filename result(filename);
  59. result.set_text();
  60. return result;
  61. }
  62. ////////////////////////////////////////////////////////////////////
  63. // Function: Filename::binary_filename named constructor
  64. // Access: Published
  65. // Description:
  66. ////////////////////////////////////////////////////////////////////
  67. INLINE Filename Filename::
  68. binary_filename(const string &filename) {
  69. Filename result(filename);
  70. result.set_binary();
  71. return result;
  72. }
  73. ////////////////////////////////////////////////////////////////////
  74. // Function: Filename::dso_filename named constructor
  75. // Access: Published
  76. // Description:
  77. ////////////////////////////////////////////////////////////////////
  78. INLINE Filename Filename::
  79. dso_filename(const string &filename) {
  80. Filename result(filename);
  81. result.set_type(T_dso);
  82. return result;
  83. }
  84. ////////////////////////////////////////////////////////////////////
  85. // Function: Filename::executable_filename named constructor
  86. // Access: Published
  87. // Description:
  88. ////////////////////////////////////////////////////////////////////
  89. INLINE Filename Filename::
  90. executable_filename(const string &filename) {
  91. Filename result(filename);
  92. result.set_type(T_executable);
  93. return result;
  94. }
  95. ////////////////////////////////////////////////////////////////////
  96. // Function: Filename::pattern_filename named constructor
  97. // Access: Published
  98. // Description: Constructs a filename that represents a sequence of
  99. // numbered files. See set_pattern().
  100. ////////////////////////////////////////////////////////////////////
  101. INLINE Filename Filename::
  102. pattern_filename(const string &filename) {
  103. Filename result(filename);
  104. result.set_pattern(true);
  105. return result;
  106. }
  107. ////////////////////////////////////////////////////////////////////
  108. // Function: Filename::Destructor
  109. // Access: Published
  110. // Description:
  111. ////////////////////////////////////////////////////////////////////
  112. INLINE Filename::
  113. ~Filename() {
  114. }
  115. ////////////////////////////////////////////////////////////////////
  116. // Function: Filename::Assignment operator
  117. // Access: Published
  118. // Description:
  119. ////////////////////////////////////////////////////////////////////
  120. INLINE Filename &Filename::
  121. operator = (const string &filename) {
  122. _filename = filename;
  123. locate_basename();
  124. locate_extension();
  125. locate_hash();
  126. return *this;
  127. }
  128. ////////////////////////////////////////////////////////////////////
  129. // Function: Filename::Assignment operator
  130. // Access: Published
  131. // Description:
  132. ////////////////////////////////////////////////////////////////////
  133. INLINE Filename &Filename::
  134. operator = (const char *filename) {
  135. assert(filename != NULL);
  136. return (*this) = string(filename);
  137. }
  138. ////////////////////////////////////////////////////////////////////
  139. // Function: Filename::Copy assignment operator
  140. // Access: Published
  141. // Description:
  142. ////////////////////////////////////////////////////////////////////
  143. INLINE Filename &Filename::
  144. operator = (const Filename &copy) {
  145. _filename = copy._filename;
  146. _dirname_end = copy._dirname_end;
  147. _basename_start = copy._basename_start;
  148. _basename_end = copy._basename_end;
  149. _extension_start = copy._extension_start;
  150. _hash_start = copy._hash_start;
  151. _hash_end = copy._hash_end;
  152. _flags = copy._flags;
  153. return *this;
  154. }
  155. ////////////////////////////////////////////////////////////////////
  156. // Function: Filename::string typecast operator
  157. // Access: Published
  158. // Description:
  159. ////////////////////////////////////////////////////////////////////
  160. INLINE Filename::
  161. operator const string & () const {
  162. return _filename;
  163. }
  164. ////////////////////////////////////////////////////////////////////
  165. // Function: Filename::c_str
  166. // Access: Published
  167. // Description:
  168. ////////////////////////////////////////////////////////////////////
  169. INLINE const char *Filename::
  170. c_str() const {
  171. return _filename.c_str();
  172. }
  173. ////////////////////////////////////////////////////////////////////
  174. // Function: Filename::empty
  175. // Access: Published
  176. // Description:
  177. ////////////////////////////////////////////////////////////////////
  178. INLINE bool Filename::
  179. empty() const {
  180. return _filename.empty();
  181. }
  182. ////////////////////////////////////////////////////////////////////
  183. // Function: Filename::length
  184. // Access: Published
  185. // Description:
  186. ////////////////////////////////////////////////////////////////////
  187. INLINE size_t Filename::
  188. length() const {
  189. return _filename.length();
  190. }
  191. ////////////////////////////////////////////////////////////////////
  192. // Function: Filename::Indexing operator
  193. // Access: Published
  194. // Description:
  195. ////////////////////////////////////////////////////////////////////
  196. INLINE char Filename::
  197. operator [] (int n) const {
  198. assert(n >= 0 && n < (int)_filename.length());
  199. return _filename[n];
  200. }
  201. ////////////////////////////////////////////////////////////////////
  202. // Function: Filename::substr
  203. // Access: Published
  204. // Description:
  205. ////////////////////////////////////////////////////////////////////
  206. INLINE string Filename::
  207. substr(size_t begin, size_t end) const {
  208. return _filename.substr(begin, end);
  209. }
  210. ////////////////////////////////////////////////////////////////////
  211. // Function: Filename::get_fullpath
  212. // Access: Published
  213. // Description: Returns the entire filename: directory, basename,
  214. // extension. This is the same thing returned by the
  215. // string typecast operator, so this function is a
  216. // little redundant.
  217. ////////////////////////////////////////////////////////////////////
  218. INLINE string Filename::
  219. get_fullpath() const {
  220. return _filename;
  221. }
  222. ////////////////////////////////////////////////////////////////////
  223. // Function: Filename::get_dirname
  224. // Access: Published
  225. // Description: Returns the directory part of the filename. This is
  226. // everything in the filename up to, but not including
  227. // the rightmost slash.
  228. ////////////////////////////////////////////////////////////////////
  229. INLINE string Filename::
  230. get_dirname() const {
  231. return _filename.substr(0, _dirname_end);
  232. }
  233. ////////////////////////////////////////////////////////////////////
  234. // Function: Filename::get_basename
  235. // Access: Published
  236. // Description: Returns the basename part of the filename. This is
  237. // everything in the filename after the rightmost slash,
  238. // including any extensions.
  239. ////////////////////////////////////////////////////////////////////
  240. INLINE string Filename::
  241. get_basename() const {
  242. return _filename.substr(_basename_start);
  243. }
  244. ////////////////////////////////////////////////////////////////////
  245. // Function: Filename::get_fullpath_wo_extension
  246. // Access: Published
  247. // Description: Returns the full filename--directory and basename
  248. // parts--except for the extension.
  249. ////////////////////////////////////////////////////////////////////
  250. INLINE string Filename::
  251. get_fullpath_wo_extension() const {
  252. return _filename.substr(0, _basename_end);
  253. }
  254. ////////////////////////////////////////////////////////////////////
  255. // Function: Filename::get_basename_wo_extension
  256. // Access: Published
  257. // Description: Returns the basename part of the filename, without
  258. // the file extension.
  259. ////////////////////////////////////////////////////////////////////
  260. INLINE string Filename::
  261. get_basename_wo_extension() const {
  262. if (_basename_end == string::npos) {
  263. return _filename.substr(_basename_start);
  264. } else {
  265. return _filename.substr(_basename_start, _basename_end - _basename_start);
  266. }
  267. }
  268. ////////////////////////////////////////////////////////////////////
  269. // Function: Filename::get_extension
  270. // Access: Published
  271. // Description: Returns the file extension. This is everything after
  272. // the rightmost dot, if there is one, or the empty
  273. // string if there is not.
  274. ////////////////////////////////////////////////////////////////////
  275. INLINE string Filename::
  276. get_extension() const {
  277. if (_extension_start == string::npos) {
  278. return string();
  279. } else {
  280. return _filename.substr(_extension_start);
  281. }
  282. }
  283. ////////////////////////////////////////////////////////////////////
  284. // Function: Filename::set_binary
  285. // Access: Published
  286. // Description: Indicates that the filename represents a binary file.
  287. // This is primarily relevant to the read_file() and
  288. // write_file() methods, so they can set the appropriate
  289. // flags to the OS.
  290. ////////////////////////////////////////////////////////////////////
  291. INLINE void Filename::
  292. set_binary() {
  293. _flags = (_flags & ~F_text) | F_binary;
  294. }
  295. ////////////////////////////////////////////////////////////////////
  296. // Function: Filename::set_text
  297. // Access: Published
  298. // Description: Indicates that the filename represents a text file.
  299. // This is primarily relevant to the read_file() and
  300. // write_file() methods, so they can set the appropriate
  301. // flags to the OS.
  302. ////////////////////////////////////////////////////////////////////
  303. INLINE void Filename::
  304. set_text() {
  305. _flags = (_flags & ~F_binary) | F_text;
  306. }
  307. ////////////////////////////////////////////////////////////////////
  308. // Function: Filename::is_binary
  309. // Access: Published
  310. // Description: Returns true if the Filename has been indicated to
  311. // represent a binary file via a previous call to
  312. // set_binary(). It is possible that neither
  313. // is_binary() nor is_text() will be true, if neither
  314. // set_binary() nor set_text() was ever called.
  315. ////////////////////////////////////////////////////////////////////
  316. INLINE bool Filename::
  317. is_binary() const {
  318. return ((_flags & F_binary) != 0);
  319. }
  320. ////////////////////////////////////////////////////////////////////
  321. // Function: Filename::is_text
  322. // Access: Published
  323. // Description: Returns true if the Filename has been indicated to
  324. // represent a text file via a previous call to
  325. // set_text(). It is possible that neither is_binary()
  326. // nor is_text() will be true, if neither set_binary()
  327. // nor set_text() was ever called.
  328. ////////////////////////////////////////////////////////////////////
  329. INLINE bool Filename::
  330. is_text() const {
  331. return ((_flags & F_text) != 0);
  332. }
  333. ////////////////////////////////////////////////////////////////////
  334. // Function: Filename::set_type
  335. // Access: Published
  336. // Description: Sets the type of the file represented by the
  337. // filename. This is useful for to_os_specific(),
  338. // resolve_filename(), test_existence(), and all such
  339. // real-world access functions. It helps the Filename
  340. // know how to map the internal filename to the
  341. // OS-specific filename (for instance, maybe executables
  342. // should have an .exe extension).
  343. ////////////////////////////////////////////////////////////////////
  344. INLINE void Filename::
  345. set_type(Filename::Type type) {
  346. _flags = (_flags & ~F_type) | type;
  347. switch (type) {
  348. case T_dso:
  349. case T_executable:
  350. set_binary();
  351. case T_general:
  352. break;
  353. }
  354. }
  355. ////////////////////////////////////////////////////////////////////
  356. // Function: Filename::get_type
  357. // Access: Published
  358. // Description: Returns the type of the file represented by the
  359. // filename, as previously set by set_type().
  360. ////////////////////////////////////////////////////////////////////
  361. INLINE Filename::Type Filename::
  362. get_type() const {
  363. return (Type)(_flags & (int)F_type);
  364. }
  365. ////////////////////////////////////////////////////////////////////
  366. // Function: Filename::set_pattern
  367. // Access: Published
  368. // Description: Sets the flag indicating whether this is a filename
  369. // pattern. When this is true, the filename is
  370. // understood to be a placeholder for a numbered
  371. // sequence of filename, such as an image sequence. In
  372. // this case, a sequence of one or more hash characters
  373. // ("#") should appear in the filename string; these
  374. // characters will be filled in with the corresponding
  375. // number (or more) of digits representing the sequence
  376. // number. Sequence numbers always begin counting at 0.
  377. //
  378. // When this is true, methods like has_hash() and
  379. // get_hash_to_end() and get_filename_index() may be
  380. // called. Methods like is_exists() will implicitly
  381. // test for existance of filename sequence 0.
  382. ////////////////////////////////////////////////////////////////////
  383. INLINE void Filename::
  384. set_pattern(bool pattern) {
  385. if (pattern != get_pattern()) {
  386. if (pattern) {
  387. _flags |= F_pattern;
  388. } else {
  389. _flags &= ~F_pattern;
  390. }
  391. locate_hash();
  392. }
  393. }
  394. ////////////////////////////////////////////////////////////////////
  395. // Function: Filename::get_pattern
  396. // Access: Published
  397. // Description: Returns the flag indicating whether this is a
  398. // filename pattern. See set_pattern().
  399. ////////////////////////////////////////////////////////////////////
  400. INLINE bool Filename::
  401. get_pattern() const {
  402. return (_flags & F_pattern) != 0;
  403. }
  404. ////////////////////////////////////////////////////////////////////
  405. // Function: Filename::has_hash
  406. // Access: Published
  407. // Description: Returns true if the filename is indicated to be a
  408. // filename pattern (that is, set_pattern(true) was
  409. // called), and the filename pattern did include a
  410. // sequence of hash marks, or false if it was not a
  411. // filename pattern or did not include hash marks. If
  412. // this is true, then get_filename_index() will return a
  413. // different filename each time.
  414. ////////////////////////////////////////////////////////////////////
  415. INLINE bool Filename::
  416. has_hash() const {
  417. return (_hash_start != _hash_end);
  418. }
  419. ////////////////////////////////////////////////////////////////////
  420. // Function: Filename::get_hash_to_end
  421. // Access: Published
  422. // Description: Returns the part of the filename beginning at the
  423. // hash sequence (if any), and continuing to the end of
  424. // the filename.
  425. ////////////////////////////////////////////////////////////////////
  426. INLINE string Filename::
  427. get_hash_to_end() const {
  428. return _filename.substr(_hash_start);
  429. }
  430. ////////////////////////////////////////////////////////////////////
  431. // Function: Filename::is_local
  432. // Access: Published
  433. // Description: Returns true if the filename is local, e.g. does not
  434. // begin with a slash, or false if the filename is fully
  435. // specified from the root.
  436. ////////////////////////////////////////////////////////////////////
  437. INLINE bool Filename::
  438. is_local() const {
  439. return _filename.empty() || _filename[0] != '/';
  440. }
  441. ////////////////////////////////////////////////////////////////////
  442. // Function: Filename::is_fully_qualified
  443. // Access: Published
  444. // Description: Returns true if the filename is fully qualified,
  445. // e.g. begins with a slash. This is almost, but not
  446. // quite, the same thing as !is_local(). It's not
  447. // exactly the same because a special case is made for
  448. // filenames that begin with a single dot followed by a
  449. // slash--these are considered to be fully qualified
  450. // (they are explicitly relative to the current
  451. // directory, and do not refer to a filename on a search
  452. // path somewhere).
  453. ////////////////////////////////////////////////////////////////////
  454. INLINE bool Filename::
  455. is_fully_qualified() const {
  456. return
  457. (_filename.size() > 2 && _filename[0] == '.' && _filename[1] == '/') ||
  458. (!_filename.empty() && _filename[0] == '/');
  459. }
  460. ////////////////////////////////////////////////////////////////////
  461. // Function: Filename::Equality operator
  462. // Access: Published
  463. // Description:
  464. ////////////////////////////////////////////////////////////////////
  465. INLINE bool Filename::
  466. operator == (const string &other) const {
  467. return (*(string *)this) == other;
  468. }
  469. ////////////////////////////////////////////////////////////////////
  470. // Function: Filename::Inequality operator
  471. // Access: Published
  472. // Description:
  473. ////////////////////////////////////////////////////////////////////
  474. INLINE bool Filename::
  475. operator != (const string &other) const {
  476. return (*(string *)this) != other;
  477. }
  478. ////////////////////////////////////////////////////////////////////
  479. // Function: Filename::Ordering operator
  480. // Access: Published
  481. // Description:
  482. ////////////////////////////////////////////////////////////////////
  483. INLINE bool Filename::
  484. operator < (const string &other) const {
  485. return (*(string *)this) < other;
  486. }
  487. ////////////////////////////////////////////////////////////////////
  488. // Function: Filename::compare_to
  489. // Access: Published
  490. // Description:
  491. ////////////////////////////////////////////////////////////////////
  492. INLINE int Filename::
  493. compare_to(const Filename &other) const {
  494. return strcmp(_filename.c_str(), other._filename.c_str());
  495. }
  496. ////////////////////////////////////////////////////////////////////
  497. // Function: Filename::output
  498. // Access: Published
  499. // Description:
  500. ////////////////////////////////////////////////////////////////////
  501. INLINE void Filename::
  502. output(ostream &out) const {
  503. out << _filename;
  504. }