Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/File/Path.h
5654 views
1
#pragma once
2
3
#include "ppsspp_config.h"
4
5
#include <string>
6
#include <string_view>
7
8
#ifdef HAVE_LIBRETRO_VFS
9
#include "libretro/LibretroFileStreamTransforms.h"
10
#endif
11
12
#if defined(__APPLE__)
13
14
#if TARGET_OS_IPHONE
15
#define HOST_IS_CASE_SENSITIVE 1
16
#elif TARGET_IPHONE_SIMULATOR
17
#define HOST_IS_CASE_SENSITIVE 0
18
#else
19
// Mac OSX case sensitivity defaults off, but is user configurable (when
20
// creating a filesytem), so assume the worst:
21
#define HOST_IS_CASE_SENSITIVE 1
22
#endif
23
24
#elif defined(_WIN32)
25
#define HOST_IS_CASE_SENSITIVE 0
26
27
#else // Android, Linux, BSD (and the rest?)
28
#define HOST_IS_CASE_SENSITIVE 1
29
30
#endif
31
32
enum class PathType {
33
UNDEFINED = 0,
34
NATIVE = 1, // Can be relative.
35
CONTENT_URI = 2, // Android only. Can only be absolute!
36
HTTP = 3, // http://, https://
37
};
38
39
// Windows paths are always stored with '/' slashes in a Path.
40
// On .ToWString(), they are flipped back to '\'.
41
42
class Path {
43
private:
44
void Init(std::string_view str);
45
46
public:
47
Path() : type_(PathType::UNDEFINED) {}
48
explicit Path(std::string_view str);
49
50
#if PPSSPP_PLATFORM(WINDOWS)
51
explicit Path(const std::wstring &str);
52
#endif
53
54
PathType Type() const {
55
return type_;
56
}
57
bool IsLocalType() const {
58
return type_ == PathType::NATIVE || type_ == PathType::CONTENT_URI;
59
}
60
61
bool Valid() const { return !path_.empty(); }
62
bool IsRoot() const { return path_ == "/"; } // Special value - only path that can end in a slash.
63
64
// Some std::string emulation for simplicity.
65
bool empty() const { return !Valid(); }
66
void clear() {
67
type_ = PathType::UNDEFINED;
68
path_.clear();
69
}
70
size_t size() const {
71
return path_.size();
72
}
73
74
// WARNING: Potentially unsafe usage, if it's not NATIVE.
75
const char *c_str() const {
76
return path_.c_str();
77
}
78
79
bool IsAbsolute() const;
80
81
// Returns a path extended with a subdirectory.
82
Path operator /(std::string_view subdir) const;
83
84
// Navigates down into a subdir.
85
void operator /=(std::string_view subdir);
86
87
// File extension manipulation.
88
Path WithExtraExtension(std::string_view ext) const;
89
Path WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
90
Path WithReplacedExtension(const std::string &newExtension) const;
91
92
std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory. Includes the extension.
93
std::string GetFileExtension() const; // Always lowercase return. Includes the dot.
94
// Removes the last component.
95
std::string GetDirectory() const;
96
97
const std::string &ToString() const;
98
99
#if PPSSPP_PLATFORM(WINDOWS)
100
std::wstring ToWString() const;
101
std::string ToCString() const; // Flips the slashes back to Windows standard, but string still UTF-8.
102
#else
103
std::string ToCString() const {
104
return ToString();
105
}
106
#endif
107
108
// Pass in a relative root to turn the path into a relative path - if it is one!
109
std::string ToVisualString(const char *relativeRoot = nullptr) const;
110
111
bool CanNavigateUp() const;
112
Path NavigateUp() const;
113
114
// Navigates as far up as possible from this path. If not possible to navigate upwards, returns the same path.
115
// Not actually always the root of the volume, especially on systems like Mac and Linux where things are often mounted.
116
// For Android directory trees, navigates to the root of the tree.
117
Path GetRootVolume() const;
118
119
bool ComputePathTo(const Path &other, std::string &path) const;
120
121
bool operator ==(const Path &other) const {
122
return path_ == other.path_ && type_ == other.type_;
123
}
124
bool operator !=(const Path &other) const {
125
return path_ != other.path_ || type_ != other.type_;
126
}
127
128
bool FilePathContainsNoCase(std::string_view needle) const;
129
130
// WARNING: This can return wrong results if two ContentURI have different root paths.
131
bool StartsWith(const Path &other) const;
132
133
// This handles ContentURI with different paths "correctly". Very specific use case.
134
bool StartsWithGlobalAndNotEqual(const Path &other) const;
135
136
bool operator <(const Path &other) const {
137
return path_ < other.path_;
138
}
139
bool operator >(const Path &other) const {
140
return path_ > other.path_;
141
}
142
143
private:
144
// The internal representation is currently always the plain string.
145
// For CPU efficiency we could keep an AndroidStorageContentURI too,
146
// but I don't think the encode/decode cost is significant. We simply create
147
// those for processing instead.
148
std::string path_;
149
150
PathType type_;
151
};
152
153
// Utility function for fixing the case of paths. Only necessary on Unix-like systems.
154
155
enum FixPathCaseBehavior {
156
FPC_FILE_MUST_EXIST, // all path components must exist (rmdir, move from)
157
FPC_PATH_MUST_EXIST, // all except the last one must exist - still tries to fix last one (fopen, move to)
158
FPC_PARTIAL_ALLOWED, // don't care how many exist (mkdir recursive)
159
};
160
161
bool FixPathCase(const Path &basePath, std::string &path, FixPathCaseBehavior behavior);
162
163