ScummVM API documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
30 class PathTestSuite;
31 #endif
32 
33 namespace Common {
34 
52 class Path {
53 #ifdef CXXTEST_RUNNING
54  friend class ::PathTestSuite;
55 #endif
56 
57 private:
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 
181 public:
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 
287  Path getParent() const;
288 
295  Path getLastComponent() const;
296 
302  String baseName() const;
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;
348  uint hashIgnoreCaseAndMac() 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 
387  Path &appendInPlace(const Path &x);
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 
402  WARN_UNUSED_RESULT Path append(const Path &x) const {
403  Path temp(*this);
404  temp.appendInPlace(x);
405  return temp;
406  }
407 
409  WARN_UNUSED_RESULT Path append(const String &str, char separator = '/') const {
410  return append(str.c_str(), separator);
411  }
412 
414  WARN_UNUSED_RESULT Path append(const char *str, char separator = '/') const {
415  Path temp(*this);
416  temp.appendInPlace(str, separator);
417  return temp;
418  }
419 
424  WARN_UNUSED_RESULT Path appendComponent(const char *str) const;
425 
427  WARN_UNUSED_RESULT Path appendComponent(const String &x) const {
428  return appendComponent(x.c_str());
429  }
430 
435  Path &joinInPlace(const Path &x);
436 
438  Path &joinInPlace(const String &str, char separator = '/') {
439  return joinInPlace(str.c_str(), separator);
440  }
441 
443  Path &joinInPlace(const char *str, char separator = '/');
444 
449  WARN_UNUSED_RESULT Path join(const Path &x) const {
450  Path temp(*this);
451  temp.joinInPlace(x);
452  return temp;
453  }
454 
456  WARN_UNUSED_RESULT Path join(const String &str, char separator = '/') const {
457  return join(str.c_str(), separator);
458  }
459 
461  WARN_UNUSED_RESULT Path join(const char *str, char separator = '/') const {
462  Path temp(*this);
463  temp.joinInPlace(str, separator);
464  return temp;
465  }
466 
471 
475  bool isSeparatorTerminated() const { return _str.lastChar() == SEPARATOR; }
476 
480  bool isRelativeTo(const Common::Path &other) const { return getSuffix(other) != nullptr; }
481 
486  Path relativeTo(const Common::Path &other) const;
487 
491  Path punycodeDecode() const;
492 
496  Path punycodeEncode() const;
497 
501  bool punycodeNeedsEncode() const;
502 
509  void toLowercase() {
510  // Escapism is not changed by changing case
511  _str.toLowercase();
512  }
513 
520  void toUppercase() {
521  // Escapism is not changed by changing case
522  _str.toUppercase();
523  }
524 
528  bool matchPattern(const Path &pattern) const;
529 
539  Path normalize() const;
540 
549 
554  static Path joinComponents(const StringArray &c) {
555  return joinComponents(c.begin(), c.end());
556  }
557 
564  String toConfig() const;
565 
569  static Path fromConfig(const String &value);
570 
574  static Path fromCommandLine(const String &value);
575 };
576 
579 } // End of namespace Common
580 
581 #endif
static Path fromCommandLine(const String &value)
void toUppercase()
Definition: path.h:520
Definition: path.h:220
static const char kNoSeparator
Definition: path.h:186
Path getParent() const
Definition: str.h:59
Path normalize() const
WARN_UNUSED_RESULT Path join(const String &str, char separator='/') const
Definition: path.h:456
bool equals(const BaseString &x) const
Path getLastComponent() const
WARN_UNUSED_RESULT Path appendComponent(const char *str) const
void clear()
Definition: path.h:279
iterator end()
Definition: array.h:379
iterator begin()
Definition: array.h:374
Definition: path.h:224
Path(const char *str, char separator='/')
Definition: path.h:251
Path & joinInPlace(const String &str, char separator='/')
Definition: path.h:438
Definition: path.h:52
bool operator==(const Path &x) const
Definition: path.h:310
Path & appendInPlace(const Path &x)
Path & appendInPlace(const String &str, char separator='/')
Definition: path.h:390
static Path joinComponents(StringArray::const_iterator begin, StringArray::const_iterator end)
Path punycodeDecode() const
uint hash() const
bool isRelativeTo(const Common::Path &other) const
Definition: path.h:480
static const char kNativeSeparator
Definition: path.h:195
static Path fromConfig(const String &value)
WARN_UNUSED_RESULT Path append(const String &str, char separator='/') const
Definition: path.h:409
bool equalsIgnoreCaseAndMac(const Path &x) const
bool punycodeNeedsEncode() const
Path & operator=(const Path &path)
Definition: path.h:358
int numComponents() const
bool empty() const
Definition: path.h:353
bool matchPattern(const Path &pattern) const
bool operator!=(const Path &x) const
Definition: path.h:315
bool equals(const Path &x) const
Definition: path.h:322
bool isSeparatorTerminated() const
Definition: path.h:475
void toLowercase()
Definition: path.h:509
bool equalsIgnoreCase(const Path &x) const
Definition: algorithm.h:29
uint hashIgnoreCase() const
String toString(char separator='/') const
String baseName() const
Path()
Definition: path.h:237
Path relativeTo(const Common::Path &other) const
Path & operator=(const String &str)
Definition: path.h:370
WARN_UNUSED_RESULT Path append(const char *str, char separator='/') const
Definition: path.h:414
WARN_UNUSED_RESULT Path append(const Path &x) const
Definition: path.h:402
uint hashIgnoreCaseAndMac() const
WARN_UNUSED_RESULT Path join(const char *str, char separator='/') const
Definition: path.h:461
WARN_UNUSED_RESULT Path appendComponent(const String &x) const
Definition: path.h:427
Path(const Path &path)
Definition: path.h:240
Path & removeTrailingSeparators()
Path & joinInPlace(const Path &x)
Path punycodeEncode() const
Definition: path.h:232
Path & operator=(const char *str)
Definition: path.h:364
Path(const String &str, char separator='/')
Definition: path.h:263
WARN_UNUSED_RESULT Path join(const Path &x) const
Definition: path.h:449
String toConfig() const
StringArray splitComponents() const
Definition: path.h:228