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
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 && // 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 
167  static Path &punycode_decodefilename_helper(Path &path, const String &in, bool last);
168  static Path &punycode_encodefilename_helper(Path &path, const String &in, bool last);
169 
173  inline bool isEscaped() const {
174  // c_str() returns a null terminated string, if _str is empty we get \0
175  return *_str.c_str() == ESCAPE;
176  }
177 
182  const char *getSuffix(const Common::Path &other) const;
183 
184 public:
189  static const char kNoSeparator = '\x00';
190 
195 #if defined(WIN32)
196  static const char kNativeSeparator = '\\';
197 #else
198  static const char kNativeSeparator = '/';
199 #endif
200 
211  bool operator()(const Path &x, const Path &y) const { return x.equalsIgnoreCaseAndMac(y); }
212  };
213 
215  uint operator()(const Path &x) const { return x.hashIgnoreCaseAndMac(); }
216  };
217 
224  bool operator()(const Path &x, const Path &y) const { return x.equalsIgnoreCase(y); }
225  };
226 
228  uint operator()(const Path &x) const { return x.hashIgnoreCase(); }
229  };
230 
231  struct EqualTo {
232  bool operator()(const Path &x, const Path &y) const { return x.equals(y); }
233  };
234 
235  struct Hash {
236  uint operator()(const Path &x) const { return x.hash(); }
237  };
238 
240  Path() {}
241 
243  Path(const Path &path) : _str(path._str) { }
244 
254  Path(const char *str, char separator = '/') :
255  _str(needsEncoding(str, separator) ? encode(str, separator) : str) { }
256 
266  explicit Path(const String &str, char separator = '/') :
267  _str(needsEncoding(str.c_str(), separator) ? encode(str.c_str(), separator) : str) { }
268 
277  String toString(char separator = '/') const;
278 
282  void clear() { _str.clear(); }
283 
290  Path getParent() const;
291 
298  Path getLastComponent() const;
299 
305  String baseName() const;
306 
310  int numComponents() const;
311 
313  bool operator==(const Path &x) const {
314  return _str == x._str;
315  }
316 
318  bool operator!=(const Path &x) const {
319  return _str != x._str;
320  }
321 
325  bool equals(const Path &x) const {
326  return _str.equals(x._str);
327  }
332  bool equalsIgnoreCase(const Path &x) const;
337  bool equalsIgnoreCaseAndMac(const Path &x) const;
338 
342  uint hash() const;
346  uint hashIgnoreCase() const;
351  uint hashIgnoreCaseAndMac() const;
352 
353  bool operator<(const Path &x) const;
354 
356  bool empty() const {
357  return _str.empty();
358  }
359 
361  Path &operator=(const Path &path) {
362  _str = path._str;
363  return *this;
364  }
365 
367  Path &operator=(const char *str) {
368  set(str);
369  return *this;
370  }
371 
373  Path &operator=(const String &str) {
374  set(str.c_str());
375  return *this;
376  }
377 
378  void set(const char *str, char separator = '/') {
379  if (needsEncoding(str, separator)) {
380  _str = encode(str, separator);
381  } else {
382  _str = str;
383  }
384  }
385 
390  Path &appendInPlace(const Path &x);
391 
393  Path &appendInPlace(const String &str, char separator = '/') {
394  appendInPlace(str.c_str(), separator);
395  return *this;
396  }
397 
399  Path &appendInPlace(const char *str, char separator = '/');
400 
405  WARN_UNUSED_RESULT Path append(const Path &x) const {
406  Path temp(*this);
407  temp.appendInPlace(x);
408  return temp;
409  }
410 
412  WARN_UNUSED_RESULT Path append(const String &str, char separator = '/') const {
413  return append(str.c_str(), separator);
414  }
415 
417  WARN_UNUSED_RESULT Path append(const char *str, char separator = '/') const {
418  Path temp(*this);
419  temp.appendInPlace(str, separator);
420  return temp;
421  }
422 
427  WARN_UNUSED_RESULT Path appendComponent(const char *str) const;
428 
430  WARN_UNUSED_RESULT Path appendComponent(const String &x) const {
431  return appendComponent(x.c_str());
432  }
433 
438  Path &joinInPlace(const Path &x);
439 
441  Path &joinInPlace(const String &str, char separator = '/') {
442  return joinInPlace(str.c_str(), separator);
443  }
444 
446  Path &joinInPlace(const char *str, char separator = '/');
447 
452  WARN_UNUSED_RESULT Path join(const Path &x) const {
453  Path temp(*this);
454  temp.joinInPlace(x);
455  return temp;
456  }
457 
459  WARN_UNUSED_RESULT Path join(const String &str, char separator = '/') const {
460  return join(str.c_str(), separator);
461  }
462 
464  WARN_UNUSED_RESULT Path join(const char *str, char separator = '/') const {
465  Path temp(*this);
466  temp.joinInPlace(str, separator);
467  return temp;
468  }
469 
474 
478  bool isSeparatorTerminated() const { return _str.lastChar() == SEPARATOR; }
479 
483  bool isRelativeTo(const Common::Path &other) const { return getSuffix(other) != nullptr; }
484 
489  Path relativeTo(const Common::Path &other) const;
490 
494  Path punycodeDecode() const;
495 
499  Path punycodeEncode() const;
500 
507  void toLowercase() {
508  // Escapism is not changed by changing case
509  _str.toLowercase();
510  }
511 
518  void toUppercase() {
519  // Escapism is not changed by changing case
520  _str.toUppercase();
521  }
522 
526  bool matchPattern(const Path &pattern) const;
527 
537  Path normalize() const;
538 
547 
552  static Path joinComponents(const StringArray &c) {
553  return joinComponents(c.begin(), c.end());
554  }
555 
560  String toConfig() const {
561  return punycodeEncode().toString('/');
562  }
563 
567  static Path fromConfig(const String &value);
568 
572  static Path fromCommandLine(const String &value);
573 };
574 
577 } // End of namespace Common
578 
579 #endif
static Path fromCommandLine(const String &value)
void toUppercase()
Definition: path.h:518
Definition: path.h:223
static const char kNoSeparator
Definition: path.h:189
Path getParent() const
Definition: str.h:59
Path normalize() const
WARN_UNUSED_RESULT Path join(const String &str, char separator='/') const
Definition: path.h:459
bool equals(const BaseString &x) const
Path getLastComponent() const
WARN_UNUSED_RESULT Path appendComponent(const char *str) const
void clear()
Definition: path.h:282
iterator end()
Definition: array.h:379
iterator begin()
Definition: array.h:374
Definition: path.h:227
Path(const char *str, char separator='/')
Definition: path.h:254
Path & joinInPlace(const String &str, char separator='/')
Definition: path.h:441
Definition: path.h:52
bool operator==(const Path &x) const
Definition: path.h:313
Path & appendInPlace(const Path &x)
Path & appendInPlace(const String &str, char separator='/')
Definition: path.h:393
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:483
static const char kNativeSeparator
Definition: path.h:198
static Path fromConfig(const String &value)
WARN_UNUSED_RESULT Path append(const String &str, char separator='/') const
Definition: path.h:412
bool equalsIgnoreCaseAndMac(const Path &x) const
Path & operator=(const Path &path)
Definition: path.h:361
int numComponents() const
bool empty() const
Definition: path.h:356
bool matchPattern(const Path &pattern) const
bool operator!=(const Path &x) const
Definition: path.h:318
bool equals(const Path &x) const
Definition: path.h:325
bool isSeparatorTerminated() const
Definition: path.h:478
void toLowercase()
Definition: path.h:507
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:240
Path relativeTo(const Common::Path &other) const
Path & operator=(const String &str)
Definition: path.h:373
WARN_UNUSED_RESULT Path append(const char *str, char separator='/') const
Definition: path.h:417
WARN_UNUSED_RESULT Path append(const Path &x) const
Definition: path.h:405
uint hashIgnoreCaseAndMac() const
WARN_UNUSED_RESULT Path join(const char *str, char separator='/') const
Definition: path.h:464
WARN_UNUSED_RESULT Path appendComponent(const String &x) const
Definition: path.h:430
Path(const Path &path)
Definition: path.h:243
Path & removeTrailingSeparators()
Path & joinInPlace(const Path &x)
Path punycodeEncode() const
Definition: path.h:235
Path & operator=(const char *str)
Definition: path.h:367
Path(const String &str, char separator='/')
Definition: path.h:266
WARN_UNUSED_RESULT Path join(const Path &x) const
Definition: path.h:452
String toConfig() const
Definition: path.h:560
StringArray splitComponents() const
Definition: path.h:231