ScummVM API documentation
path.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef COMMON_PATH_H
23#define COMMON_PATH_H
24
25#include "common/scummsys.h"
26#include "common/str.h"
27#include "common/str-array.h"
28
29#ifdef CXXTEST_RUNNING
30class PathTestSuite;
31#endif
32
33namespace Common {
34
52class Path {
53#ifdef CXXTEST_RUNNING
54 friend class ::PathTestSuite;
55#endif
56
57private:
58#ifndef RELEASE_BUILD
59 static bool _shownSeparatorCollisionWarning;
60#endif
61
62 // The directory separator
63 static const char SEPARATOR = '/';
64 // The escape prefix character
65 static const char ESCAPE = '|';
66 // How the prefix character is escaped (doubling)
67 static const char ESCAPED_ESCAPE = '|';
68 // How the separator is escaped
69 static const char ESCAPED_SEPARATOR = '\\';
70
71 String _str;
72
84 static void escape(String &dst, char srcSeparator, const char *src, const char *end = nullptr);
85
97 static String unescape(char dstSeparator, const char *src, const char *end = nullptr);
98
107 static bool canUnescape(bool willBeAtBegin, bool wasAtBegin,
108 const char *begin, const char *end = nullptr);
109
116 static inline bool needsEncoding(const char *str, char separator) {
117 return str && *str && // String is not empty and
118 (separator != SEPARATOR || // separator is not the one we use
119 *str == ESCAPE); // or string begins with ESCAPE
120 }
121
133 static String encode(const char *str, char separator);
134
143 Path extract(const char *begin, const char *end = nullptr) const;
144
146 size_t findLastSeparator(size_t last = String::npos) const;
147
155 template<typename T>
156 T reduceComponents(T (*reducer)(T value, const String &element, bool last), T value) const;
157
165 bool compareComponents(bool (*comparator)(const String &x, const String &y), const Path &other) const;
166
170 inline bool isEscaped() const {
171 // c_str() returns a null terminated string, if _str is empty we get \0
172 return *_str.c_str() == ESCAPE;
173 }
174
179 const char *getSuffix(const Common::Path &other) const;
180
181public:
186 static const char kNoSeparator = '\x00';
187
192#if defined(WIN32)
193 static const char kNativeSeparator = '\\';
194#else
195 static const char kNativeSeparator = '/';
196#endif
197
208 bool operator()(const Path &x, const Path &y) const { return x.equalsIgnoreCaseAndMac(y); }
209 };
210
212 uint operator()(const Path &x) const { return x.hashIgnoreCaseAndMac(); }
213 };
214
221 bool operator()(const Path &x, const Path &y) const { return x.equalsIgnoreCase(y); }
222 };
223
225 uint operator()(const Path &x) const { return x.hashIgnoreCase(); }
226 };
227
228 struct EqualTo {
229 bool operator()(const Path &x, const Path &y) const { return x.equals(y); }
230 };
231
232 struct Hash {
233 uint operator()(const Path &x) const { return x.hash(); }
234 };
235
237 Path() {}
238
240 Path(const Path &path) : _str(path._str) { }
241
251 Path(const char *str, char separator = '/') :
252 _str(needsEncoding(str, separator) ? encode(str, separator) : str) { }
253
263 explicit Path(const String &str, char separator = '/') :
264 _str(needsEncoding(str.c_str(), separator) ? encode(str.c_str(), separator) : str) { }
265
274 String toString(char separator = '/') const;
275
279 void clear() { _str.clear(); }
280
288
296
303
307 int numComponents() const;
308
310 bool operator==(const Path &x) const {
311 return _str == x._str;
312 }
313
315 bool operator!=(const Path &x) const {
316 return _str != x._str;
317 }
318
322 bool equals(const Path &x) const {
323 return _str.equals(x._str);
324 }
329 bool equalsIgnoreCase(const Path &x) const;
334 bool equalsIgnoreCaseAndMac(const Path &x) const;
335
339 uint hash() const;
343 uint hashIgnoreCase() const;
349
350 bool operator<(const Path &x) const;
351
353 bool empty() const {
354 return _str.empty();
355 }
356
358 Path &operator=(const Path &path) {
359 _str = path._str;
360 return *this;
361 }
362
364 Path &operator=(const char *str) {
365 set(str);
366 return *this;
367 }
368
370 Path &operator=(const String &str) {
371 set(str.c_str());
372 return *this;
373 }
374
375 void set(const char *str, char separator = '/') {
376 if (needsEncoding(str, separator)) {
377 _str = encode(str, separator);
378 } else {
379 _str = str;
380 }
381 }
382
388
390 Path &appendInPlace(const String &str, char separator = '/') {
391 appendInPlace(str.c_str(), separator);
392 return *this;
393 }
394
396 Path &appendInPlace(const char *str, char separator = '/');
397
403 Path &operator+=(const Path &x) {
404 return appendInPlace(x);
405 }
406
408 Path &operator+=(const String &str) {
409 return appendInPlace(str);
410 }
411
413 Path &operator+=(const char *str) {
414 return appendInPlace(str);
415 }
416
421 WARN_UNUSED_RESULT Path append(const Path &x) const {
422 Path temp(*this);
423 temp.appendInPlace(x);
424 return temp;
425 }
426
428 WARN_UNUSED_RESULT Path append(const String &str, char separator = '/') const {
429 return append(str.c_str(), separator);
430 }
431
433 WARN_UNUSED_RESULT Path append(const char *str, char separator = '/') const {
434 Path temp(*this);
435 temp.appendInPlace(str, separator);
436 return temp;
437 }
438
443 WARN_UNUSED_RESULT Path appendComponent(const char *str) const;
444
446 WARN_UNUSED_RESULT Path appendComponent(const String &x) const {
447 return appendComponent(x.c_str());
448 }
449
455
457 Path &joinInPlace(const String &str, char separator = '/') {
458 return joinInPlace(str.c_str(), separator);
459 }
460
462 Path &joinInPlace(const char *str, char separator = '/');
463
469 Path &operator/=(const Path &x) {
470 return joinInPlace(x);
471 }
472
474 Path &operator/=(const String &str) {
475 return joinInPlace(str);
476 }
477
479 Path &operator/=(const char *str) {
480 return joinInPlace(str);
481 }
482
487 WARN_UNUSED_RESULT Path join(const Path &x) const {
488 Path temp(*this);
489 temp.joinInPlace(x);
490 return temp;
491 }
492
494 WARN_UNUSED_RESULT Path join(const String &str, char separator = '/') const {
495 return join(str.c_str(), separator);
496 }
497
499 WARN_UNUSED_RESULT Path join(const char *str, char separator = '/') const {
500 Path temp(*this);
501 temp.joinInPlace(str, separator);
502 return temp;
503 }
504
510 WARN_UNUSED_RESULT Path operator/(const Path &x) const {
511 return join(x);
512 }
513
515 WARN_UNUSED_RESULT Path operator/(const String &str) const {
516 return join(str);
517 }
518
520 WARN_UNUSED_RESULT Path operator/(const char *str) const {
521 return join(str);
522 }
523
528
540 Path &removeExtension(const char *ext = nullptr);
541
545 bool isSeparatorTerminated() const { return _str.lastChar() == SEPARATOR; }
546
550 bool isRelativeTo(const Common::Path &other) const { return getSuffix(other) != nullptr; }
551
556 Path relativeTo(const Common::Path &other) const;
557
562
567
572
579 bool punycodeIsEncoded() const;
580
587 void toLowercase() {
588 // Escapism is not changed by changing case
589 _str.toLowercase();
590 }
591
598 void toUppercase() {
599 // Escapism is not changed by changing case
600 _str.toUppercase();
601 }
602
606 bool matchPattern(const Path &pattern) const;
607
618
627
632 static Path joinComponents(const StringArray &c) {
633 return joinComponents(c.begin(), c.end());
634 }
635
643
647 static Path fromConfig(const String &value);
648
652 static Path fromCommandLine(const String &value);
653};
654
657} // End of namespace Common
658
659#endif
iterator end()
Definition: array.h:380
iterator begin()
Definition: array.h:375
bool equals(const BaseString &x) const
Definition: path.h:52
static Path joinComponents(StringArray::const_iterator begin, StringArray::const_iterator end)
WARN_UNUSED_RESULT Path join(const char *str, char separator='/') const
Definition: path.h:499
int numComponents() const
Path & removeTrailingSeparators()
WARN_UNUSED_RESULT Path appendComponent(const char *str) const
Path()
Definition: path.h:237
String toConfig() const
bool equals(const Path &x) const
Definition: path.h:322
String toString(char separator='/') const
Path punycodeDecode() const
Path & joinInPlace(const String &str, char separator='/')
Definition: path.h:457
bool operator==(const Path &x) const
Definition: path.h:310
Path & operator=(const String &str)
Definition: path.h:370
bool equalsIgnoreCase(const Path &x) const
bool isSeparatorTerminated() const
Definition: path.h:545
bool punycodeNeedsEncode() const
Path & operator+=(const char *str)
Definition: path.h:413
Path & appendInPlace(const Path &x)
Path(const Path &path)
Definition: path.h:240
WARN_UNUSED_RESULT Path append(const char *str, char separator='/') const
Definition: path.h:433
WARN_UNUSED_RESULT Path join(const String &str, char separator='/') const
Definition: path.h:494
Path & operator/=(const String &str)
Definition: path.h:474
Path(const char *str, char separator='/')
Definition: path.h:251
uint hashIgnoreCaseAndMac() const
WARN_UNUSED_RESULT Path append(const Path &x) const
Definition: path.h:421
Path & removeExtension(const char *ext=nullptr)
StringArray splitComponents() const
Path normalize() const
Path & joinInPlace(const Path &x)
Path & appendInPlace(const String &str, char separator='/')
Definition: path.h:390
WARN_UNUSED_RESULT Path operator/(const String &str) const
Definition: path.h:515
WARN_UNUSED_RESULT Path operator/(const Path &x) const
Definition: path.h:510
static Path fromCommandLine(const String &value)
bool equalsIgnoreCaseAndMac(const Path &x) const
static const char kNoSeparator
Definition: path.h:186
Path getLastComponent() const
Path(const String &str, char separator='/')
Definition: path.h:263
WARN_UNUSED_RESULT Path append(const String &str, char separator='/') const
Definition: path.h:428
Path & joinInPlace(const char *str, char separator='/')
void toLowercase()
Definition: path.h:587
void toUppercase()
Definition: path.h:598
void clear()
Definition: path.h:279
Path & appendInPlace(const char *str, char separator='/')
bool isRelativeTo(const Common::Path &other) const
Definition: path.h:550
static Path fromConfig(const String &value)
Path & operator+=(const String &str)
Definition: path.h:408
Path relativeTo(const Common::Path &other) const
WARN_UNUSED_RESULT Path join(const Path &x) const
Definition: path.h:487
Path & operator+=(const Path &x)
Definition: path.h:403
String baseName() const
static const char kNativeSeparator
Definition: path.h:195
uint hash() const
Path & operator/=(const char *str)
Definition: path.h:479
Path & operator=(const char *str)
Definition: path.h:364
uint hashIgnoreCase() const
Path & operator=(const Path &path)
Definition: path.h:358
bool matchPattern(const Path &pattern) const
bool empty() const
Definition: path.h:353
bool operator!=(const Path &x) const
Definition: path.h:315
Path getParent() const
WARN_UNUSED_RESULT Path operator/(const char *str) const
Definition: path.h:520
WARN_UNUSED_RESULT Path appendComponent(const String &x) const
Definition: path.h:446
bool punycodeIsEncoded() const
Path & operator/=(const Path &x)
Definition: path.h:469
Path punycodeEncode() const
Definition: str.h:59
Definition: algorithm.h:29
Definition: path.h:228
Definition: path.h:232
Definition: path.h:220
Definition: path.h:224