Sleeping Wombat Common Library  0.50.0
swCommonLibrary
path.h
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 
23 
24 NAMESPACE_BEGIN(filesystem)
25 
26 
33 class path_impl {
34 public:
35  enum path_type {
36  windows_path = 0,
37  posix_path = 1,
38 #if defined(_WIN32)
39  native_path = windows_path
40 #else
41  native_path = posix_path
42 #endif
43  };
44 
45  path_impl() : m_type(native_path), m_absolute(false) { }
46 
47  path_impl(const path_impl &path)
48  : m_type(path.m_type), m_path(path.m_path), m_absolute(path.m_absolute) {}
49 
50  path_impl(path_impl &&path)
51  : m_type(path.m_type), m_path(std::move(path.m_path)),
52  m_absolute(path.m_absolute) {}
53 
54  path_impl(const char *string) { set(string); }
55 
56  path_impl(const std::string &string) { set(string); }
57 
58 #if defined(_WIN32)
59  path_impl(const std::wstring &wstring) { set(wstring); }
60  path_impl(const wchar_t *wstring) { set(wstring); }
61 #endif
62 
63  size_t length() const { return m_path.size(); }
64 
65  bool empty() const { return m_path.empty(); }
66 
67  bool is_absolute() const { return m_absolute; }
68 
69  path_impl make_absolute() const;
70 
71  bool exists() const;
72 
73  size_t file_size() const;
74 
75  bool is_directory() const;
76 
77  bool is_file() const;
78 
79  std::string extension() const {
80  const std::string &name = filename();
81  size_t pos = name.find_last_of(".");
82  if (pos == std::string::npos)
83  return "";
84 
85  // Ignore special cases
86  if( name == "." || name == ".." )
87  return "";
88 
89  return name.substr(pos);
90  }
91 
92  std::string filename() const {
93  if (empty())
94  return "";
95  const std::string &last = m_path[m_path.size()-1];
96  return last;
97  }
98 
99  path_impl parent_path() const {
100  path_impl result;
101  result.m_absolute = m_absolute;
102 
103  if (m_path.empty()) {
104  if (!m_absolute)
105  result.m_path.push_back("..");
106  } else {
107  size_t until = m_path.size() - 1;
108  for (size_t i = 0; i < until; ++i)
109  result.m_path.push_back(m_path[i]);
110  }
111  return result;
112  }
113 
114  path_impl operator/(const path_impl &other) const {
115  if (other.m_absolute)
116  throw std::runtime_error("path::operator/(): expected a relative path!");
117  if (m_type != other.m_type)
118  throw std::runtime_error("path::operator/(): expected a path of the same type!");
119 
120  path_impl result(*this);
121 
122  for (size_t i=0; i<other.m_path.size(); ++i)
123  result.m_path.push_back(other.m_path[i]);
124 
125  return result;
126  }
127 
128  std::string str(path_type type = native_path) const {
129  std::ostringstream oss;
130 
131  if (m_type == posix_path && m_absolute)
132  oss << "/";
133 
134  for (size_t i=0; i<m_path.size(); ++i) {
135  oss << m_path[i];
136  if (i+1 < m_path.size()) {
137  if (type == posix_path)
138  oss << '/';
139  else
140  oss << '\\';
141  }
142  }
143 
144  return oss.str();
145  }
146 
147  void set(const std::string &str, path_type type = native_path) {
148  m_type = type;
149  if (type == windows_path) {
150  m_path = tokenize(str, "/\\");
151  m_absolute = str.size() >= 2 && std::isalpha(str[0]) && str[1] == ':';
152  } else {
153  m_path = tokenize(str, "/");
154  m_absolute = !str.empty() && str[0] == '/';
155  }
156  }
157 
158  path_impl &operator=(const path_impl &path) {
159  m_type = path.m_type;
160  m_path = path.m_path;
161  m_absolute = path.m_absolute;
162  return *this;
163  }
164 
165  path_impl &operator=(path_impl &&path) {
166  if (this != &path) {
167  m_type = path.m_type;
168  m_path = std::move(path.m_path);
169  m_absolute = path.m_absolute;
170  }
171  return *this;
172  }
173 
174  friend std::ostream &operator<<(std::ostream &os, const path_impl &path) {
175  os << path.str();
176  return os;
177  }
178 
179  bool remove_file();
180 
181  bool resize_file( size_t target_length );
182 
183  static path_impl getcwd();
184 
185 #if defined(_WIN32)
186  std::wstring wstr( path_type type = native_path ) const;
187  void set( const std::wstring &wstring, path_type type = native_path );
188  path_impl &operator=(const std::wstring &str) { set(str); return *this; }
189 #endif
190 
191  bool operator==(const path_impl &p) const { return p.m_path == m_path; }
192  bool operator!=(const path_impl &p) const { return p.m_path != m_path; }
193 
194 protected:
195  static std::vector<std::string> tokenize(const std::string &string, const std::string &delim) {
196  std::string::size_type lastPos = 0, pos = string.find_first_of(delim, lastPos);
197  std::vector<std::string> tokens;
198 
199  while (lastPos != std::string::npos) {
200  if (pos != lastPos)
201  tokens.push_back(string.substr(lastPos, pos - lastPos));
202  lastPos = pos;
203  if (lastPos == std::string::npos || lastPos + 1 == string.length())
204  break;
205  pos = string.find_first_of(delim, ++lastPos);
206  }
207 
208  return tokens;
209  }
210 
211 protected:
212  path_type m_type;
213  std::vector<std::string> m_path;
214  bool m_absolute;
215 };
216 
217 bool create_directory( const path_impl& p );
218 
219 NAMESPACE_END(filesystem)
Definition: Dir.cpp:12
Simple class for manipulating paths on Linux/Windows/Mac OS.
Definition: path.h:33