30 # include <linux/limits.h> 48 native_path = windows_path
50 native_path = posix_path
54 path() : m_type(native_path), m_absolute(false) { }
57 : m_type(path.m_type), m_path(path.m_path), m_absolute(path.m_absolute) {}
60 : m_type(path.m_type), m_path(
std::move(path.m_path)),
61 m_absolute(path.m_absolute) {}
63 path(
const char *
string) {
set(string); }
65 path(
const std::string &
string) {
set(string); }
68 path(
const std::wstring &wstring) {
set(wstring); }
69 path(
const wchar_t *wstring) {
set(wstring); }
72 size_t length()
const {
return m_path.size(); }
74 bool empty()
const {
return m_path.empty(); }
81 if (realpath(
str().c_str(), temp) == NULL)
82 throw std::runtime_error(
"Internal error in realpath(): " + std::string(strerror(errno)));
85 std::wstring value = wstr(), out(MAX_PATH,
'\0');
86 DWORD length = GetFullPathNameW(value.c_str(), MAX_PATH, &out[0], NULL);
88 throw std::runtime_error(
"Internal error in realpath(): " +
std::to_string(GetLastError()));
89 return path(out.substr(0, length));
95 return GetFileAttributesW(wstr().c_str()) != INVALID_FILE_ATTRIBUTES;
98 return stat(
str().c_str(), &sb) == 0;
105 if (_wstati64(wstr().c_str(), &sb) != 0)
106 throw std::runtime_error(
"path::file_size(): cannot stat file \"" +
str() +
"\"!");
109 if (stat(
str().c_str(), &sb) != 0)
110 throw std::runtime_error(
"path::file_size(): cannot stat file \"" +
str() +
"\"!");
112 return (
size_t) sb.st_size;
117 DWORD result = GetFileAttributesW(wstr().c_str());
118 if (result == INVALID_FILE_ATTRIBUTES)
120 return (result & FILE_ATTRIBUTE_DIRECTORY) != 0;
123 if (stat(
str().c_str(), &sb))
125 return S_ISDIR(sb.st_mode);
131 DWORD attr = GetFileAttributesW(wstr().c_str());
132 return (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0);
135 if (stat(
str().c_str(), &sb))
137 return S_ISREG(sb.st_mode);
142 const std::string &name = filename();
143 size_t pos = name.find_last_of(
".");
144 if (pos == std::string::npos)
146 return name.substr(pos+1);
152 const std::string &last = m_path[m_path.size()-1];
160 if (m_path.empty()) {
162 result.
m_path.push_back(
"..");
164 size_t until = m_path.size() - 1;
165 for (
size_t i = 0; i < until; ++i)
166 result.
m_path.push_back(m_path[i]);
173 throw std::runtime_error(
"path::operator/(): expected a relative path!");
174 if (m_type != other.
m_type)
175 throw std::runtime_error(
"path::operator/(): expected a path of the same type!");
179 for (
size_t i=0; i<other.
m_path.size(); ++i)
186 std::ostringstream oss;
188 if (m_type == posix_path && m_absolute)
191 for (
size_t i=0; i<m_path.size(); ++i) {
193 if (i+1 < m_path.size()) {
194 if (type == posix_path)
206 if (type == windows_path) {
207 m_path = tokenize(str,
"/\\");
208 m_absolute = str.size() >= 2 && std::isalpha(str[0]) && str[1] ==
':';
210 m_path = tokenize(str,
"/");
211 m_absolute = !str.empty() && str[0] ==
'/';
225 m_path = std::move(path.m_path);
226 m_absolute = path.m_absolute;
231 friend std::ostream &
operator<<(std::ostream &os,
const path &path) {
238 return std::remove(
str().c_str()) == 0;
240 return DeleteFileW(wstr().c_str()) != 0;
246 return ::truncate(
str().c_str(), (off_t) target_length) == 0;
248 HANDLE handle = CreateFileW(wstr().c_str(), GENERIC_WRITE, 0,
nullptr, 0, FILE_ATTRIBUTE_NORMAL,
nullptr);
249 if (handle == INVALID_HANDLE_VALUE)
252 size.QuadPart = (LONGLONG) target_length;
253 if (SetFilePointerEx(handle, size, NULL, FILE_BEGIN) == 0) {
257 if (SetEndOfFile(handle) == 0) {
269 if (::getcwd(temp, PATH_MAX) == NULL)
270 throw std::runtime_error(
"Internal error in getcwd(): " + std::string(strerror(errno)));
273 std::wstring temp(MAX_PATH,
'\0');
274 if (!_wgetcwd(&temp[0], MAX_PATH))
275 throw std::runtime_error(
"Internal error in getcwd(): " +
std::to_string(GetLastError()));
276 return path(temp.c_str());
281 std::wstring wstr(
path_type type = native_path)
const {
282 std::string temp =
str(type);
283 int size = MultiByteToWideChar(CP_UTF8, 0, &temp[0], (
int)temp.size(), NULL, 0);
284 std::wstring result(size, 0);
285 MultiByteToWideChar(CP_UTF8, 0, &temp[0], (
int)temp.size(), &result[0], size);
290 void set(
const std::wstring &wstring,
path_type type = native_path) {
292 if (!wstring.empty()) {
293 int size = WideCharToMultiByte(CP_UTF8, 0, &wstring[0], (
int)wstring.size(),
294 NULL, 0, NULL, NULL);
295 string.resize(size, 0);
296 WideCharToMultiByte(CP_UTF8, 0, &wstring[0], (
int)wstring.size(),
297 &
string[0], size, NULL, NULL);
302 path &operator=(
const std::wstring &str) {
set(
str);
return *
this; }
309 static std::vector<std::string>
tokenize(
const std::string &
string,
const std::string &delim) {
310 std::string::size_type lastPos = 0, pos =
string.find_first_of(delim, lastPos);
311 std::vector<std::string> tokens;
313 while (lastPos != std::string::npos) {
315 tokens.push_back(
string.substr(lastPos, pos - lastPos));
317 if (lastPos == std::string::npos || lastPos + 1 ==
string.length())
319 pos =
string.find_first_of(delim, ++lastPos);
333 return CreateDirectoryW(p.wstr().c_str(), NULL) != 0;
335 return mkdir(p.
str().c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == 0;
#define NAMESPACE_END(name)
friend std::ostream & operator<<(std::ostream &os, const path &path)
path & operator=(const path &path)
#define NAMESPACE_BEGIN(name)
bool operator!=(const path &p) const
path make_absolute() const
std::vector< std::string > m_path
bool resize_file(size_t target_length)
path & operator=(path &&path)
static std::vector< std::string > tokenize(const std::string &string, const std::string &delim)
std::string extension() const
Simple class for manipulating paths on Linux/Windows/Mac OS.
bool create_directory(const path &p)
path(const std::string &string)
path operator/(const path &other) const
bool is_directory() const
std::basic_string< CharT, Traits > to_string(basic_string_view< CharT, Traits > v)
std::string str(path_type type=native_path) const
std::string filename() const
bool operator==(const path &p) const