Panda3D
filename.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file filename.I
10  * @author drose
11  * @date 1999-01-18
12  */
13 
14 /**
15  *
16  */
17 INLINE Filename::
18 Filename(const std::string &filename) {
19  _flags = 0;
20  (*this) = filename;
21 }
22 
23 /**
24  *
25  */
26 INLINE Filename::
27 Filename(const std::wstring &filename) {
28  _flags = 0;
29  (*this) = filename;
30 }
31 
32 /**
33  *
34  */
35 INLINE Filename::
36 Filename(const char *filename) {
37  _flags = 0;
38  (*this) = filename;
39 }
40 
41 /**
42  *
43  */
44 INLINE Filename::
45 Filename(const Filename &copy) :
46  _filename(copy._filename.c_str()),
47  _dirname_end(copy._dirname_end),
48  _basename_start(copy._basename_start),
49  _basename_end(copy._basename_end),
50  _extension_start(copy._extension_start),
51  _hash_start(copy._hash_start),
52  _hash_end(copy._hash_end),
53  _flags(copy._flags)
54 {
55 }
56 
57 /**
58  *
59  */
60 INLINE Filename::
61 Filename(std::string &&filename) noexcept : _flags(0) {
62  (*this) = std::move(filename);
63 }
64 
65 /**
66  *
67  */
68 INLINE Filename::
69 Filename(Filename &&from) noexcept :
70  _filename(std::move(from._filename)),
71  _dirname_end(from._dirname_end),
72  _basename_start(from._basename_start),
73  _basename_end(from._basename_end),
74  _extension_start(from._extension_start),
75  _hash_start(from._hash_start),
76  _hash_end(from._hash_end),
77  _flags(from._flags)
78 {
79 }
80 
81 /**
82  * Creates an empty Filename.
83  */
84 INLINE Filename::
86  _dirname_end(0),
87  _basename_start(0),
88  _basename_end(std::string::npos),
89  _extension_start(std::string::npos),
90  _hash_start(std::string::npos),
91  _hash_end(std::string::npos),
92  _flags(0) {
93 }
94 
95 /**
96  *
97  */
98 INLINE Filename Filename::
99 text_filename(const Filename &filename) {
100  Filename result(filename);
101  result.set_text();
102  return result;
103 }
104 
105 /**
106  *
107  */
108 INLINE Filename Filename::
109 text_filename(const std::string &filename) {
110  Filename result(filename);
111  result.set_text();
112  return result;
113 }
114 
115 /**
116  *
117  */
118 INLINE Filename Filename::
119 binary_filename(const Filename &filename) {
120  Filename result(filename);
121  result.set_binary();
122  return result;
123 }
124 
125 /**
126  *
127  */
128 INLINE Filename Filename::
129 binary_filename(const std::string &filename) {
130  Filename result(filename);
131  result.set_binary();
132  return result;
133 }
134 
135 /**
136  *
137  */
138 INLINE Filename Filename::
139 dso_filename(const std::string &filename) {
140  Filename result(filename);
141  result.set_type(T_dso);
142  return result;
143 }
144 
145 /**
146  *
147  */
148 INLINE Filename Filename::
149 executable_filename(const std::string &filename) {
150  Filename result(filename);
151  result.set_type(T_executable);
152  return result;
153 }
154 
155 /**
156  * Constructs a filename that represents a sequence of numbered files. See
157  * set_pattern().
158  */
159 INLINE Filename Filename::
160 pattern_filename(const std::string &filename) {
161  Filename result(filename);
162  result.set_pattern(true);
163  return result;
164 }
165 
166 /**
167  *
168  */
169 INLINE Filename &Filename::
170 operator = (const std::string &filename) {
171  _filename = filename;
172 
173  locate_basename();
174  locate_extension();
175  locate_hash();
176  return *this;
177 }
178 
179 /**
180  *
181  */
182 INLINE Filename &Filename::
183 operator = (const std::wstring &filename) {
184  TextEncoder encoder;
186  encoder.set_wtext(filename);
187  return operator = (encoder.get_text());
188 }
189 
190 /**
191  *
192  */
193 INLINE Filename &Filename::
194 operator = (const char *filename) {
195  assert(filename != nullptr);
196  return (*this) = std::string(filename);
197 }
198 
199 /**
200  *
201  */
202 INLINE Filename &Filename::
203 operator = (const Filename &copy) {
204  _filename = copy._filename;
205  _dirname_end = copy._dirname_end;
206  _basename_start = copy._basename_start;
207  _basename_end = copy._basename_end;
208  _extension_start = copy._extension_start;
209  _hash_start = copy._hash_start;
210  _hash_end = copy._hash_end;
211  _flags = copy._flags;
212  return *this;
213 }
214 
215 /**
216  *
217  */
218 INLINE Filename &Filename::
219 operator = (std::string &&filename) noexcept {
220  _filename = std::move(filename);
221 
222  locate_basename();
223  locate_extension();
224  locate_hash();
225  return *this;
226 }
227 
228 /**
229  *
230  */
231 INLINE Filename &Filename::
232 operator = (Filename &&from) noexcept {
233  _filename = std::move(from._filename);
234  _dirname_end = from._dirname_end;
235  _basename_start = from._basename_start;
236  _basename_end = from._basename_end;
237  _extension_start = from._extension_start;
238  _hash_start = from._hash_start;
239  _hash_end = from._hash_end;
240  _flags = from._flags;
241  return *this;
242 }
243 
244 /**
245  *
246  */
247 INLINE Filename::
248 operator const std::string & () const {
249  return _filename;
250 }
251 
252 /**
253  *
254  */
255 INLINE const char *Filename::
256 c_str() const {
257  return _filename.c_str();
258 }
259 
260 /**
261  *
262  */
263 INLINE bool Filename::
264 empty() const {
265  return _filename.empty();
266 }
267 
268 /**
269  *
270  */
271 INLINE size_t Filename::
272 length() const {
273  return _filename.length();
274 }
275 
276 /**
277  *
278  */
279 INLINE char Filename::
280 operator [] (size_t n) const {
281  assert(n < _filename.length());
282  return _filename[n];
283 }
284 
285 /**
286  *
287  */
288 INLINE std::string Filename::
289 substr(size_t begin) const {
290  return _filename.substr(begin);
291 }
292 
293 /**
294  *
295  */
296 INLINE std::string Filename::
297 substr(size_t begin, size_t end) const {
298  return _filename.substr(begin, end);
299 }
300 
301 /**
302  * Appends the other filename onto the end of this one. This does not
303  * introduce an intervening slash, but see the Filename constructor that takes
304  * two parameters.
305  */
306 INLINE void Filename::
307 operator += (const std::string &other) {
308  _filename += other;
309  locate_basename();
310  locate_extension();
311  locate_hash();
312 }
313 
314 /**
315  * Returns a new Filename representing the concatenation of the two filenames.
316  */
317 INLINE Filename Filename::
318 operator + (const std::string &other) const {
319  Filename a(*this);
320  a += other;
321  return a;
322 }
323 
324 /**
325  * Returns a new Filename that is composed of the other filename added to the
326  * end of this filename, with an intervening slash added if necessary.
327  */
328 INLINE Filename Filename::
329 operator / (const Filename &other) const {
330  return Filename(*this, other);
331 }
332 
333 /**
334  * Returns the entire filename: directory, basename, extension. This is the
335  * same thing returned by the string typecast operator.
336  */
337 INLINE std::string Filename::
338 get_fullpath() const {
339  return _filename;
340 }
341 
342 /**
343  * Returns the entire filename as a wide-character string.
344  */
345 INLINE std::wstring Filename::
346 get_fullpath_w() const {
347  TextEncoder encoder;
349  encoder.set_text(get_fullpath());
350  return encoder.get_wtext();
351 }
352 
353 /**
354  * Returns the directory part of the filename. This is everything in the
355  * filename up to, but not including the rightmost slash.
356  */
357 INLINE std::string Filename::
358 get_dirname() const {
359  return _filename.substr(0, _dirname_end);
360 }
361 
362 /**
363  * Returns the basename part of the filename. This is everything in the
364  * filename after the rightmost slash, including any extensions.
365  */
366 INLINE std::string Filename::
367 get_basename() const {
368  return _filename.substr(_basename_start);
369 }
370 
371 
372 /**
373  * Returns the full filename--directory and basename parts--except for the
374  * extension.
375  */
376 INLINE std::string Filename::
378  return _filename.substr(0, _basename_end);
379 }
380 
381 
382 /**
383  * Returns the basename part of the filename, without the file extension.
384  */
385 INLINE std::string Filename::
387  if (_basename_end == std::string::npos) {
388  return _filename.substr(_basename_start);
389  } else {
390  return _filename.substr(_basename_start, _basename_end - _basename_start);
391  }
392 }
393 
394 
395 /**
396  * Returns the file extension. This is everything after the rightmost dot, if
397  * there is one, or the empty string if there is not.
398  */
399 INLINE std::string Filename::
400 get_extension() const {
401  if (_extension_start == std::string::npos) {
402  return std::string();
403  } else {
404  return _filename.substr(_extension_start);
405  }
406 }
407 
408 /**
409  * Indicates that the filename represents a binary file. This is primarily
410  * relevant to the read_file() and write_file() methods, so they can set the
411  * appropriate flags to the OS.
412  */
413 INLINE void Filename::
415  _flags = (_flags & ~F_text) | F_binary;
416 }
417 
418 /**
419  * Indicates that the filename represents a text file. This is primarily
420  * relevant to the read_file() and write_file() methods, so they can set the
421  * appropriate flags to the OS.
422  */
423 INLINE void Filename::
425  _flags = (_flags & ~F_binary) | F_text;
426 }
427 
428 /**
429  * Returns true if the Filename has been indicated to represent a binary file
430  * via a previous call to set_binary(). It is possible that neither
431  * is_binary() nor is_text() will be true, if neither set_binary() nor
432  * set_text() was ever called.
433  */
434 INLINE bool Filename::
435 is_binary() const {
436  return ((_flags & F_binary) != 0);
437 }
438 
439 /**
440  * Returns true either is_binary() or is_text() is true; that is, that the
441  * filename has been specified as either binary or text. If this is false,
442  * the filename has not been specified.
443  */
444 INLINE bool Filename::
446  return ((_flags & (F_binary | F_text)) != 0);
447 }
448 
449 /**
450  * Returns true if the Filename has been indicated to represent a text file
451  * via a previous call to set_text(). It is possible that neither is_binary()
452  * nor is_text() will be true, if neither set_binary() nor set_text() was ever
453  * called.
454  */
455 INLINE bool Filename::
456 is_text() const {
457  return ((_flags & F_text) != 0);
458 }
459 
460 /**
461  * Sets the type of the file represented by the filename. This is useful for
462  * to_os_specific(), resolve_filename(), test_existence(), and all such real-
463  * world access functions. It helps the Filename know how to map the internal
464  * filename to the OS-specific filename (for instance, maybe executables
465  * should have an .exe extension).
466  */
467 INLINE void Filename::
468 set_type(Filename::Type type) {
469  _flags = (_flags & ~F_type) | type;
470  switch (type) {
471  case T_dso:
472  case T_executable:
473  set_binary();
474 
475  case T_general:
476  break;
477  }
478 }
479 
480 /**
481  * Returns the type of the file represented by the filename, as previously set
482  * by set_type().
483  */
484 INLINE Filename::Type Filename::
485 get_type() const {
486  return (Type)(_flags & (int)F_type);
487 }
488 
489 /**
490  * Sets the flag indicating whether this is a filename pattern. When this is
491  * true, the filename is understood to be a placeholder for a numbered
492  * sequence of filename, such as an image sequence. In this case, a sequence
493  * of one or more hash characters ("#") should appear in the filename string;
494  * these characters will be filled in with the corresponding number (or more)
495  * of digits representing the sequence number. Sequence numbers always begin
496  * counting at 0.
497  *
498  * When this is true, methods like has_hash() and get_hash_to_end() and
499  * get_filename_index() may be called. Methods like is_exists() will
500  * implicitly test for existance of filename sequence 0.
501  */
502 INLINE void Filename::
503 set_pattern(bool pattern) {
504  if (pattern != get_pattern()) {
505  if (pattern) {
506  _flags |= F_pattern;
507  } else {
508  _flags &= ~F_pattern;
509  }
510  locate_hash();
511  }
512 }
513 
514 /**
515  * Returns the flag indicating whether this is a filename pattern. See
516  * set_pattern().
517  */
518 INLINE bool Filename::
519 get_pattern() const {
520  return (_flags & F_pattern) != 0;
521 }
522 
523 /**
524  * Returns true if the filename is indicated to be a filename pattern (that
525  * is, set_pattern(true) was called), and the filename pattern did include a
526  * sequence of hash marks, or false if it was not a filename pattern or did
527  * not include hash marks. If this is true, then get_filename_index() will
528  * return a different filename each time.
529  */
530 INLINE bool Filename::
531 has_hash() const {
532  return (_hash_start != _hash_end);
533 }
534 
535 /**
536  * Returns the part of the filename beginning at the hash sequence (if any),
537  * and continuing to the end of the filename.
538  */
539 INLINE std::string Filename::
541  return _filename.substr(_hash_start);
542 }
543 
544 /**
545  * Returns true if the filename is local, e.g. does not begin with a slash,
546  * or false if the filename is fully specified from the root.
547  */
548 INLINE bool Filename::
549 is_local() const {
550  return _filename.empty() || _filename[0] != '/';
551 }
552 
553 /**
554  * Returns true if the filename is fully qualified, e.g. begins with a slash.
555  * This is almost, but not quite, the same thing as !is_local(). It's not
556  * exactly the same because a special case is made for filenames that begin
557  * with a single dot followed by a slash--these are considered to be fully
558  * qualified (they are explicitly relative to the current directory, and do
559  * not refer to a filename on a search path somewhere).
560  */
561 INLINE bool Filename::
563  return
564  (_filename.size() > 2 && _filename[0] == '.' && _filename[1] == '/') ||
565  (!_filename.empty() && _filename[0] == '/');
566 }
567 
568 /**
569  *
570  */
571 INLINE bool Filename::
572 operator == (const std::string &other) const {
573  return (*(std::string *)this) == other;
574 }
575 
576 /**
577  *
578  */
579 INLINE bool Filename::
580 operator != (const std::string &other) const {
581  return (*(std::string *)this) != other;
582 }
583 
584 /**
585  *
586  */
587 INLINE bool Filename::
588 operator < (const std::string &other) const {
589  return (*(std::string *)this) < other;
590 }
591 
592 /**
593  *
594  */
595 INLINE int Filename::
596 compare_to(const Filename &other) const {
597  return strcmp(_filename.c_str(), other._filename.c_str());
598 }
599 
600 
601 /**
602  * Returns true if the Filename is valid (not empty), or false if it is an
603  * empty string.
604  *
605  * This implements the Python equivalent to operator bool. Defining an actual
606  * operator bool method for C++ use would work too, but it seems to cause too
607  * many ambiguities for the C++ compiler, so we use this Python-only approach
608  * instead.
609  */
610 INLINE bool Filename::
611 __nonzero__() const {
612  return !_filename.empty();
613 }
614 
615 /**
616  *
617  */
618 INLINE void Filename::
619 output(std::ostream &out) const {
620  out << _filename;
621 }
622 
623 /**
624  * Specifies the default encoding to be used for all subsequent Filenames.
625  * This is used to represent wide-character (Unicode) filenames internally.
626  * On non-Windows-based systems, the encoded filename is also passed to the
627  * underlying operating system.
628  */
629 INLINE void Filename::
630 set_filesystem_encoding(TextEncoder::Encoding encoding) {
631  _filesystem_encoding = encoding;
632 }
633 
634 /**
635  * Specifies the default encoding to be used for all subsequent Filenames
636  * objects. See set_filesystem_encoding().
637  */
638 INLINE TextEncoder::Encoding Filename::
640  return _filesystem_encoding;
641 }
std::string get_dirname() const
Returns the directory part of the filename.
Definition: filename.I:358
bool get_pattern() const
Returns the flag indicating whether this is a filename pattern.
Definition: filename.I:519
Filename()
Creates an empty Filename.
Definition: filename.I:85
Filename operator/(const Filename &other) const
Returns a new Filename that is composed of the other filename added to the end of this filename,...
Definition: filename.I:329
std::string get_hash_to_end() const
Returns the part of the filename beginning at the hash sequence (if any), and continuing to the end o...
Definition: filename.I:540
This class can be used to convert text between multiple representations, e.g.
Definition: textEncoder.h:33
void set_type(Type type)
Sets the type of the file represented by the filename.
Definition: filename.I:468
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:386
void set_binary()
Indicates that the filename represents a binary file.
Definition: filename.I:414
void set_text()
Indicates that the filename represents a text file.
Definition: filename.I:424
bool __nonzero__() const
Returns true if the Filename is valid (not empty), or false if it is an empty string.
Definition: filename.I:611
bool is_fully_qualified() const
Returns true if the filename is fully qualified, e.g.
Definition: filename.I:562
bool is_binary() const
Returns true if the Filename has been indicated to represent a binary file via a previous call to set...
Definition: filename.I:435
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
Type get_type() const
Returns the type of the file represented by the filename, as previously set by set_type().
Definition: filename.I:485
static void set_filesystem_encoding(TextEncoder::Encoding encoding)
Specifies the default encoding to be used for all subsequent Filenames.
Definition: filename.I:630
static TextEncoder::Encoding get_filesystem_encoding()
Specifies the default encoding to be used for all subsequent Filenames objects.
Definition: filename.I:639
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition: filename.I:338
Filename operator+(const std::string &other) const
Returns a new Filename representing the concatenation of the two filenames.
Definition: filename.I:318
bool is_local() const
Returns true if the filename is local, e.g.
Definition: filename.I:549
get_text
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.h:124
bool is_text() const
Returns true if the Filename has been indicated to represent a text file via a previous call to set_t...
Definition: filename.I:456
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
std::string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:367
void operator+=(const std::string &other)
Appends the other filename onto the end of this one.
Definition: filename.I:307
void set_encoding(Encoding encoding)
Specifies how the string set via set_text() is to be interpreted.
Definition: textEncoder.I:48
const std::wstring & get_wtext() const
Returns the text associated with the TextEncoder, as a wide-character string.
Definition: textEncoder.I:456
static Filename pattern_filename(const std::string &filename)
Constructs a filename that represents a sequence of numbered files.
Definition: filename.I:160
bool has_hash() const
Returns true if the filename is indicated to be a filename pattern (that is, set_pattern(true) was ca...
Definition: filename.I:531
std::string get_fullpath_wo_extension() const
Returns the full filename–directory and basename parts–except for the extension.
Definition: filename.I:377
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
Definition: textEncoder.I:443
void set_pattern(bool pattern)
Sets the flag indicating whether this is a filename pattern.
Definition: filename.I:503
bool is_binary_or_text() const
Returns true either is_binary() or is_text() is true; that is, that the filename has been specified a...
Definition: filename.I:445
std::wstring get_fullpath_w() const
Returns the entire filename as a wide-character string.
Definition: filename.I:346