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 
308  bool operator==(const Path &x) const {
309  return _str == x._str;
310  }
311 
313  bool operator!=(const Path &x) const {
314  return _str != x._str;
315  }
316 
320  bool equals(const Path &x) const {
321  return _str.equals(x._str);
322  }
327  bool equalsIgnoreCase(const Path &x) const;
332  bool equalsIgnoreCaseAndMac(const Path &x) const;
333 
337  uint hash() const;
341  uint hashIgnoreCase() const;
346  uint hashIgnoreCaseAndMac() const;
347 
348  bool operator<(const Path &x) const;
349 
351  bool empty() const {
352  return _str.empty();
353  }
354 
356  Path &operator=(const Path &path) {
357  _str = path._str;
358  return *this;
359  }
360 
362  Path &operator=(const char *str) {
363  set(str);
364  return *this;
365  }
366 
368  Path &operator=(const String &str) {
369  set(str.c_str());
370  return *this;
371  }
372 
373  void set(const char *str, char separator = '/') {
374  if (needsEncoding(str, separator)) {
375  _str = encode(str, separator);
376  } else {
377  _str = str;
378  }
379  }
380 
385  Path &appendInPlace(const Path &x);
386 
388  Path &appendInPlace(const String &str, char separator = '/') {
389  appendInPlace(str.c_str(), separator);
390  return *this;
391  }
392 
394  Path &appendInPlace(const char *str, char separator = '/');
395 
400  WARN_UNUSED_RESULT Path append(const Path &x) const {
401  Path temp(*this);
402  temp.appendInPlace(x);
403  return temp;
404  }
405 
407  WARN_UNUSED_RESULT Path append(const String &str, char separator = '/') const {
408  return append(str.c_str(), separator);
409  }
410 
412  WARN_UNUSED_RESULT Path append(const char *str, char separator = '/') const {
413  Path temp(*this);
414  temp.appendInPlace(str, separator);
415  return temp;
416  }
417 
422  WARN_UNUSED_RESULT Path appendComponent(const char *str) const;
423 
425  WARN_UNUSED_RESULT Path appendComponent(const String &x) const {
426  return appendComponent(x.c_str());
427  }
428 
433  Path &joinInPlace(const Path &x);
434 
436  Path &joinInPlace(const String &str, char separator = '/') {
437  return joinInPlace(str.c_str(), separator);
438  }
439 
441  Path &joinInPlace(const char *str, char separator = '/');
442 
447  WARN_UNUSED_RESULT Path join(const Path &x) const {
448  Path temp(*this);
449  temp.joinInPlace(x);
450  return temp;
451  }
452 
454  WARN_UNUSED_RESULT Path join(const String &str, char separator = '/') const {
455  return join(str.c_str(), separator);
456  }
457 
459  WARN_UNUSED_RESULT Path join(const char *str, char separator = '/') const {
460  Path temp(*this);
461  temp.joinInPlace(str, separator);
462  return temp;
463  }
464 
469 
473  bool isSeparatorTerminated() const { return _str.lastChar() == SEPARATOR; }
474 
478  bool isRelativeTo(const Common::Path &other) const { return getSuffix(other) != nullptr; }
479 
484  Path relativeTo(const Common::Path &other) const;
485 
489  Path punycodeDecode() const;
490 
494  Path punycodeEncode() const;
495 
502  void toLowercase() {
503  // Escapism is not changed by changing case
504  _str.toLowercase();
505  }
506 
513  void toUppercase() {
514  // Escapism is not changed by changing case
515  _str.toUppercase();
516  }
517 
521  bool matchPattern(const Path &pattern) const;
522 
532  Path normalize() const;
533 
542 
547  static Path joinComponents(const StringArray &c) {
548  return joinComponents(c.begin(), c.end());
549  }
550 
555  String toConfig() const {
556  return punycodeEncode().toString('/');
557  }
558 
562  static Path fromConfig(const String &value);
563 };
564 
567 } // End of namespace Common
568 
569 #endif
void toUppercase()
Definition: path.h:513
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:454
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:339
iterator begin()
Definition: array.h:334
Definition: path.h:227
Path(const char *str, char separator='/')
Definition: path.h:254
Path & joinInPlace(const String &str, char separator='/')
Definition: path.h:436
Definition: path.h:52
bool operator==(const Path &x) const
Definition: path.h:308
Path & appendInPlace(const Path &x)
Path & appendInPlace(const String &str, char separator='/')
Definition: path.h:388
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:478
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:407
bool equalsIgnoreCaseAndMac(const Path &x) const
Path & operator=(const Path &path)
Definition: path.h:356
bool empty() const
Definition: path.h:351
bool matchPattern(const Path &pattern) const
bool operator!=(const Path &x) const
Definition: path.h:313
bool equals(const Path &x) const
Definition: path.h:320
bool isSeparatorTerminated() const
Definition: path.h:473
void toLowercase()
Definition: path.h:502
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:368
WARN_UNUSED_RESULT Path append(const char *str, char separator='/') const
Definition: path.h:412
WARN_UNUSED_RESULT Path append(const Path &x) const
Definition: path.h:400
uint hashIgnoreCaseAndMac() const
WARN_UNUSED_RESULT Path join(const char *str, char separator='/') const
Definition: path.h:459
WARN_UNUSED_RESULT Path appendComponent(const String &x) const
Definition: path.h:425
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:362
Path(const String &str, char separator='/')
Definition: path.h:266
WARN_UNUSED_RESULT Path join(const Path &x) const
Definition: path.h:447
String toConfig() const
Definition: path.h:555
StringArray splitComponents() const
Definition: path.h:231