path.h
Go to the documentation of this file.
1 /*
2  path.h -- A simple class for manipulating paths on Linux/Windows/Mac OS
3 
4  Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #pragma once
11 
12 #include "fwd.h"
13 #include <string>
14 #include <vector>
15 #include <stdexcept>
16 #include <sstream>
17 #include <cctype>
18 #include <cstdlib>
19 #include <cerrno>
20 #include <cstring>
21 
22 #if defined(_WIN32)
23 # include <windows.h>
24 #else
25 # include <unistd.h>
26 #endif
27 #include <sys/stat.h>
28 
29 #if defined(__linux)
30 # include <linux/limits.h>
31 #endif
32 
33 NAMESPACE_BEGIN(filesystem)
34 
35 
42 class path {
43 public:
44  enum path_type {
45  windows_path = 0,
46  posix_path = 1,
47 #if defined(_WIN32)
48  native_path = windows_path
49 #else
50  native_path = posix_path
51 #endif
52  };
53 
54  path() : m_type(native_path), m_absolute(false) { }
55 
56  path(const path &path)
57  : m_type(path.m_type), m_path(path.m_path), m_absolute(path.m_absolute) {}
58 
59  path(path &&path)
60  : m_type(path.m_type), m_path(std::move(path.m_path)),
61  m_absolute(path.m_absolute) {}
62 
63  path(const char *string) { set(string); }
64 
65  path(const std::string &string) { set(string); }
66 
67 #if defined(_WIN32)
68  path(const std::wstring &wstring) { set(wstring); }
69  path(const wchar_t *wstring) { set(wstring); }
70 #endif
71 
72  size_t length() const { return m_path.size(); }
73 
74  bool empty() const { return m_path.empty(); }
75 
76  bool is_absolute() const { return m_absolute; }
77 
78  path make_absolute() const {
79 #if !defined(_WIN32)
80  char temp[PATH_MAX];
81  if (realpath(str().c_str(), temp) == NULL)
82  throw std::runtime_error("Internal error in realpath(): " + std::string(strerror(errno)));
83  return path(temp);
84 #else
85  std::wstring value = wstr(), out(MAX_PATH, '\0');
86  DWORD length = GetFullPathNameW(value.c_str(), MAX_PATH, &out[0], NULL);
87  if (length == 0)
88  throw std::runtime_error("Internal error in realpath(): " + std::to_string(GetLastError()));
89  return path(out.substr(0, length));
90 #endif
91  }
92 
93  bool exists() const {
94 #if defined(_WIN32)
95  return GetFileAttributesW(wstr().c_str()) != INVALID_FILE_ATTRIBUTES;
96 #else
97  struct stat sb;
98  return stat(str().c_str(), &sb) == 0;
99 #endif
100  }
101 
102  size_t file_size() const {
103 #if defined(_WIN32)
104  struct _stati64 sb;
105  if (_wstati64(wstr().c_str(), &sb) != 0)
106  throw std::runtime_error("path::file_size(): cannot stat file \"" + str() + "\"!");
107 #else
108  struct stat sb;
109  if (stat(str().c_str(), &sb) != 0)
110  throw std::runtime_error("path::file_size(): cannot stat file \"" + str() + "\"!");
111 #endif
112  return (size_t) sb.st_size;
113  }
114 
115  bool is_directory() const {
116 #if defined(_WIN32)
117  DWORD result = GetFileAttributesW(wstr().c_str());
118  if (result == INVALID_FILE_ATTRIBUTES)
119  return false;
120  return (result & FILE_ATTRIBUTE_DIRECTORY) != 0;
121 #else
122  struct stat sb;
123  if (stat(str().c_str(), &sb))
124  return false;
125  return S_ISDIR(sb.st_mode);
126 #endif
127  }
128 
129  bool is_file() const {
130 #if defined(_WIN32)
131  DWORD attr = GetFileAttributesW(wstr().c_str());
132  return (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0);
133 #else
134  struct stat sb;
135  if (stat(str().c_str(), &sb))
136  return false;
137  return S_ISREG(sb.st_mode);
138 #endif
139  }
140 
141  std::string extension() const {
142  const std::string &name = filename();
143  size_t pos = name.find_last_of(".");
144  if (pos == std::string::npos)
145  return "";
146  return name.substr(pos+1);
147  }
148 
149  std::string filename() const {
150  if (empty())
151  return "";
152  const std::string &last = m_path[m_path.size()-1];
153  return last;
154  }
155 
156  path parent_path() const {
157  path result;
158  result.m_absolute = m_absolute;
159 
160  if (m_path.empty()) {
161  if (!m_absolute)
162  result.m_path.push_back("..");
163  } else {
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]);
167  }
168  return result;
169  }
170 
171  path operator/(const path &other) const {
172  if (other.m_absolute)
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!");
176 
177  path result(*this);
178 
179  for (size_t i=0; i<other.m_path.size(); ++i)
180  result.m_path.push_back(other.m_path[i]);
181 
182  return result;
183  }
184 
185  std::string str(path_type type = native_path) const {
186  std::ostringstream oss;
187 
188  if (m_type == posix_path && m_absolute)
189  oss << "/";
190 
191  for (size_t i=0; i<m_path.size(); ++i) {
192  oss << m_path[i];
193  if (i+1 < m_path.size()) {
194  if (type == posix_path)
195  oss << '/';
196  else
197  oss << '\\';
198  }
199  }
200 
201  return oss.str();
202  }
203 
204  void set(const std::string &str, path_type type = native_path) {
205  m_type = type;
206  if (type == windows_path) {
207  m_path = tokenize(str, "/\\");
208  m_absolute = str.size() >= 2 && std::isalpha(str[0]) && str[1] == ':';
209  } else {
210  m_path = tokenize(str, "/");
211  m_absolute = !str.empty() && str[0] == '/';
212  }
213  }
214 
215  path &operator=(const path &path) {
216  m_type = path.m_type;
217  m_path = path.m_path;
218  m_absolute = path.m_absolute;
219  return *this;
220  }
221 
222  path &operator=(path &&path) {
223  if (this != &path) {
224  m_type = path.m_type;
225  m_path = std::move(path.m_path);
226  m_absolute = path.m_absolute;
227  }
228  return *this;
229  }
230 
231  friend std::ostream &operator<<(std::ostream &os, const path &path) {
232  os << path.str();
233  return os;
234  }
235 
236  bool remove_file() {
237 #if !defined(_WIN32)
238  return std::remove(str().c_str()) == 0;
239 #else
240  return DeleteFileW(wstr().c_str()) != 0;
241 #endif
242  }
243 
244  bool resize_file(size_t target_length) {
245 #if !defined(_WIN32)
246  return ::truncate(str().c_str(), (off_t) target_length) == 0;
247 #else
248  HANDLE handle = CreateFileW(wstr().c_str(), GENERIC_WRITE, 0, nullptr, 0, FILE_ATTRIBUTE_NORMAL, nullptr);
249  if (handle == INVALID_HANDLE_VALUE)
250  return false;
251  LARGE_INTEGER size;
252  size.QuadPart = (LONGLONG) target_length;
253  if (SetFilePointerEx(handle, size, NULL, FILE_BEGIN) == 0) {
254  CloseHandle(handle);
255  return false;
256  }
257  if (SetEndOfFile(handle) == 0) {
258  CloseHandle(handle);
259  return false;
260  }
261  CloseHandle(handle);
262  return true;
263 #endif
264  }
265 
266  static path getcwd() {
267 #if !defined(_WIN32)
268  char temp[PATH_MAX];
269  if (::getcwd(temp, PATH_MAX) == NULL)
270  throw std::runtime_error("Internal error in getcwd(): " + std::string(strerror(errno)));
271  return path(temp);
272 #else
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());
277 #endif
278  }
279 
280 #if defined(_WIN32)
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);
286  return result;
287  }
288 
289 
290  void set(const std::wstring &wstring, path_type type = native_path) {
291  std::string string;
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);
298  }
299  set(string, type);
300  }
301 
302  path &operator=(const std::wstring &str) { set(str); return *this; }
303 #endif
304 
305  bool operator==(const path &p) const { return p.m_path == m_path; }
306  bool operator!=(const path &p) const { return p.m_path != m_path; }
307 
308 protected:
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;
312 
313  while (lastPos != std::string::npos) {
314  if (pos != lastPos)
315  tokens.push_back(string.substr(lastPos, pos - lastPos));
316  lastPos = pos;
317  if (lastPos == std::string::npos || lastPos + 1 == string.length())
318  break;
319  pos = string.find_first_of(delim, ++lastPos);
320  }
321 
322  return tokens;
323  }
324 
325 protected:
327  std::vector<std::string> m_path;
329 };
330 
331 inline bool create_directory(const path& p) {
332 #if defined(_WIN32)
333  return CreateDirectoryW(p.wstr().c_str(), NULL) != 0;
334 #else
335  return mkdir(p.str().c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == 0;
336 #endif
337 }
338 
339 NAMESPACE_END(filesystem)
#define NAMESPACE_END(name)
Definition: fwd.h:16
friend std::ostream & operator<<(std::ostream &os, const path &path)
Definition: path.h:231
path & operator=(const path &path)
Definition: path.h:215
#define NAMESPACE_BEGIN(name)
Definition: fwd.h:13
static path getcwd()
Definition: path.h:266
bool operator!=(const path &p) const
Definition: path.h:306
bool m_absolute
Definition: path.h:328
path_type
Definition: path.h:44
path make_absolute() const
Definition: path.h:78
Definition: any.hpp:455
path_type m_type
Definition: path.h:326
path()
Definition: path.h:54
bool is_absolute() const
Definition: path.h:76
std::vector< std::string > m_path
Definition: path.h:327
bool exists() const
Definition: path.h:93
bool resize_file(size_t target_length)
Definition: path.h:244
bool is_file() const
Definition: path.h:129
path & operator=(path &&path)
Definition: path.h:222
static std::vector< std::string > tokenize(const std::string &string, const std::string &delim)
Definition: path.h:309
size_t length() const
Definition: path.h:72
std::string extension() const
Definition: path.h:141
path(path &&path)
Definition: path.h:59
path(const path &path)
Definition: path.h:56
path parent_path() const
Definition: path.h:156
Simple class for manipulating paths on Linux/Windows/Mac OS.
Definition: path.h:42
bool create_directory(const path &p)
Definition: path.h:331
size_t file_size() const
Definition: path.h:102
bool remove_file()
Definition: path.h:236
path(const std::string &string)
Definition: path.h:65
path operator/(const path &other) const
Definition: path.h:171
bool is_directory() const
Definition: path.h:115
path(const char *string)
Definition: path.h:63
std::basic_string< CharT, Traits > to_string(basic_string_view< CharT, Traits > v)
bool empty() const
Definition: path.h:74
std::string str(path_type type=native_path) const
Definition: path.h:185
std::string filename() const
Definition: path.h:149
bool operator==(const path &p) const
Definition: path.h:305


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:25