blob: 1ad6f506459ee3edc64a5c73c11b3f37f69f6a9e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
/*
* mrustc common code
* - by John Hodge (Mutabah)
*
* tools/common/path.h
* - Generic representation of a filesystem path (HEADER)
*/
#pragma once
#include <string>
#include <stdexcept>
#include "helpers.h"
namespace helpers {
/// Path helper class (because I don't want to include boost)
class path
{
#ifdef _WIN32
static const char SEP = '\\';
#else
static const char SEP = '/';
#endif
::std::string m_str;
public:
path()
{
}
path(const ::std::string& s):
path(s.c_str())
{
}
path(const char* s);
bool is_valid() const {
return m_str != "";
}
bool operator==(const path& p) const {
return m_str == p.m_str;
}
bool operator!=(const path& p) const {
return m_str != p.m_str;
}
path& operator/=(const path& p)
{
if(!p.is_valid())
throw ::std::runtime_error("Appending from an invalid path");
return *this /= p.m_str.c_str();
}
path& operator/=(const char* o)
{
if(!this->is_valid())
throw ::std::runtime_error("Appending to an invalid path");
if(o[0] == '/')
throw ::std::runtime_error("Appending an absolute path to another path");
this->m_str.push_back(SEP);
this->m_str.append(o);
return *this;
}
path& operator/=(const string_view& o)
{
if(!this->is_valid())
throw ::std::runtime_error("Appending to an invalid path");
if(o[0] == '/')
throw ::std::runtime_error("Appending an absolute path to another path");
this->m_str.push_back(SEP);
this->m_str += o;
return *this;
}
path operator/(const path& p) const
{
auto rv = *this;
rv /= p;
return rv;
}
/// Append a relative path
path operator/(const char* o) const
{
auto rv = *this;
rv /= o;
return rv;
}
/// Add an arbitary string to the final component
path operator+(const char* o) const
{
if(!this->is_valid())
throw ::std::runtime_error("Appending a string to an invalid path");
if( ::std::strchr(o, SEP) != nullptr )
throw ::std::runtime_error("Appending a string containing the path separator (with operator+)");
auto rv = *this;
rv.m_str.append(o);
return rv;
}
bool pop_component()
{
if(!this->is_valid())
throw ::std::runtime_error("Calling pop_component() on an invalid path");
auto pos = m_str.find_last_of(SEP);
if(pos == ::std::string::npos || pos == 0)
{
return false;
}
else
{
this->m_str.resize(pos);
return true;
}
}
path parent() const
{
if(!this->is_valid())
throw ::std::runtime_error("Calling parent() on an invalid path");
auto pos = m_str.find_last_of(SEP);
if(pos == ::std::string::npos)
{
return *this;
}
else
{
path rv;
rv.m_str = m_str.substr(0, pos);
return rv;
}
}
path to_absolute() const;
::std::string basename() const
{
if(!this->is_valid())
throw ::std::runtime_error("Calling basename() on an invalid path");
auto pos = m_str.find_last_of(SEP);
if(pos == ::std::string::npos)
{
return m_str;
}
else
{
return m_str.substr(pos+1);
}
}
const ::std::string& str() const
{
return m_str;
}
operator ::std::string() const
{
return m_str;
}
class ComponentsIter
{
const path& p;
size_t pos;
size_t end;
friend class path;
ComponentsIter(const path& p, size_t i): p(p), pos(i) {
end = p.m_str.find(SEP, pos);
if(end == ::std::string::npos)
end = p.m_str.size();
}
public:
string_view operator*() const {
return string_view(p.m_str.c_str() + pos, end - pos);
}
void operator++();
bool operator!=(const ComponentsIter& x) const {
return pos != x.pos;
}
};
ComponentsIter begin() const {
return ComponentsIter(*this, 0);
}
ComponentsIter end() const {
return ComponentsIter(*this, m_str.size());
}
path normalise() const;
//void normalise_in_place();
friend ::std::ostream& operator<<(::std::ostream& os, const path& p)
{
return os << p.m_str;
}
};
}
|