Panda3D
Loading...
Searching...
No Matches
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 */
17INLINE Filename::
18Filename(const std::string &filename) {
19 _flags = 0;
20 (*this) = filename;
21}
22
23/**
24 *
25 */
26INLINE Filename::
27Filename(const std::wstring &filename) {
28 _flags = 0;
29 (*this) = filename;
30}
31
32/**
33 *
34 */
35INLINE Filename::
36Filename(const char *filename) {
37 _flags = 0;
38 (*this) = filename;
39}
40
41/**
42 *
43 */
44INLINE Filename::
45Filename(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 */
60INLINE Filename::
61Filename(std::string &&filename) noexcept : _flags(0) {
62 (*this) = std::move(filename);
63}
64
65/**
66 *
67 */
68INLINE Filename::
69Filename(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 */
84INLINE Filename::
85Filename() :
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 */
98INLINE Filename Filename::
99text_filename(const Filename &filename) {
100 Filename result(filename);
101 result.set_text();
102 return result;
103}
104
105/**
106 *
107 */
108INLINE Filename Filename::
109text_filename(const std::string &filename) {
110 Filename result(filename);
111 result.set_text();
112 return result;
113}
114
115/**
116 *
117 */
118INLINE Filename Filename::
119binary_filename(const Filename &filename) {
120 Filename result(filename);
121 result.set_binary();
122 return result;
123}
124
125/**
126 *
127 */
128INLINE Filename Filename::
129binary_filename(const std::string &filename) {
130 Filename result(filename);
131 result.set_binary();
132 return result;
133}
134
135/**
136 *
137 */
138INLINE Filename Filename::
139dso_filename(const std::string &filename) {
140 Filename result(filename);
141 result.set_type(T_dso);
142 return result;
143}
144
145/**
146 *
147 */
148INLINE Filename Filename::
149executable_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 */
159INLINE Filename Filename::
160pattern_filename(const std::string &filename) {
161 Filename result(filename);
162 result.set_pattern(true);
163 return result;
164}
165
166/**
167 *
168 */
169INLINE Filename &Filename::
170operator = (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 */
182INLINE Filename &Filename::
183operator = (const std::wstring &filename) {
184 TextEncoder encoder;
186 encoder.set_wtext(filename);
187 return operator = (encoder.get_text());
188}
189
190/**
191 *
192 */
193INLINE Filename &Filename::
194operator = (const char *filename) {
195 assert(filename != nullptr);
196 return (*this) = std::string(filename);
197}
198
199/**
200 *
201 */
202INLINE Filename &Filename::
203operator = (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 */
218INLINE Filename &Filename::
219operator = (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 */
231INLINE Filename &Filename::
232operator = (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 */
247INLINE Filename::
248operator const std::string & () const {
249 return _filename;
250}
251
252/**
253 *
254 */
255INLINE const char *Filename::
256c_str() const {
257 return _filename.c_str();
258}
259
260/**
261 *
262 */
263INLINE bool Filename::
264empty() const {
265 return _filename.empty();
266}
267
268/**
269 *
270 */
271INLINE size_t Filename::
272length() const {
273 return _filename.length();
274}
275
276/**
277 *
278 */
279INLINE char Filename::
280operator [] (size_t n) const {
281 assert(n < _filename.length());
282 return _filename[n];
283}
284
285/**
286 *
287 */
288INLINE std::string Filename::
289substr(size_t begin) const {
290 return _filename.substr(begin);
291}
292
293/**
294 *
295 */
296INLINE std::string Filename::
297substr(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 */
306INLINE void Filename::
307operator += (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 */
317INLINE Filename Filename::
318operator + (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 */
328INLINE Filename Filename::
329operator / (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 */
337INLINE std::string Filename::
338get_fullpath() const {
339 return _filename;
340}
341
342/**
343 * Returns the entire filename as a wide-character string.
344 */
345INLINE std::wstring Filename::
346get_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 */
357INLINE std::string Filename::
358get_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 */
366INLINE std::string Filename::
367get_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 */
376INLINE std::string Filename::
377get_fullpath_wo_extension() const {
378 return _filename.substr(0, _basename_end);
379}
380
381
382/**
383 * Returns the basename part of the filename, without the file extension.
384 */
385INLINE std::string Filename::
386get_basename_wo_extension() const {
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 */
399INLINE std::string Filename::
400get_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 */
413INLINE void Filename::
414set_binary() {
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 */
423INLINE void Filename::
424set_text() {
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 */
434INLINE bool Filename::
435is_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 */
444INLINE bool Filename::
445is_binary_or_text() const {
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 */
455INLINE bool Filename::
456is_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 */
467INLINE void Filename::
468set_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 */
484INLINE Filename::Type Filename::
485get_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 */
502INLINE void Filename::
503set_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 */
518INLINE bool Filename::
519get_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 */
530INLINE bool Filename::
531has_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 */
539INLINE std::string Filename::
540get_hash_to_end() const {
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 */
548INLINE bool Filename::
549is_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 */
561INLINE bool Filename::
562is_fully_qualified() const {
563 return
564 (_filename.size() > 2 && _filename[0] == '.' && _filename[1] == '/') ||
565 (!_filename.empty() && _filename[0] == '/');
566}
567
568/**
569 *
570 */
571INLINE bool Filename::
572operator == (const std::string &other) const {
573 return (*(std::string *)this) == other;
574}
575
576/**
577 *
578 */
579INLINE bool Filename::
580operator != (const std::string &other) const {
581 return (*(std::string *)this) != other;
582}
583
584/**
585 *
586 */
587INLINE bool Filename::
588operator < (const std::string &other) const {
589 return (*(std::string *)this) < other;
590}
591
592/**
593 *
594 */
595INLINE int Filename::
596compare_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 */
610INLINE bool Filename::
611__nonzero__() const {
612 return !_filename.empty();
613}
614
615/**
616 *
617 */
618INLINE void Filename::
619output(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 */
629INLINE void Filename::
630set_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 */
638INLINE TextEncoder::Encoding Filename::
639get_filesystem_encoding() {
640 return _filesystem_encoding;
641}
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
Filename()
Creates an empty Filename.
Definition filename.I:85
void set_binary()
Indicates that the filename represents a binary file.
Definition filename.I:414
static TextEncoder::Encoding get_filesystem_encoding()
Specifies the default encoding to be used for all subsequent Filenames objects.
Definition filename.I:639
bool get_pattern() const
Returns the flag indicating whether this is a filename pattern.
Definition filename.I:519
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition filename.I:338
void set_pattern(bool pattern)
Sets the flag indicating whether this is a filename pattern.
Definition filename.I:503
This class can be used to convert text between multiple representations, e.g.
Definition textEncoder.h:33
set_text
Changes the text that is stored in the encoder.
void set_encoding(Encoding encoding)
Specifies how the string set via set_text() is to be interpreted.
Definition textEncoder.I:48
get_text
Returns the current text, as encoded via the current encoding system.
const std::wstring & get_wtext() const
Returns the text associated with the TextEncoder, as a wide-character string.
void set_wtext(const std::wstring &wtext)
Changes the text that is stored in the encoder.
STL namespace.