path.h
Go to the documentation of this file.
00001 /*
00002     path.h -- A simple class for manipulating paths on Linux/Windows/Mac OS
00003 
00004     Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
00005 
00006     All rights reserved. Use of this source code is governed by a
00007     BSD-style license that can be found in the LICENSE file.
00008 */
00009 
00010 #pragma once
00011 
00012 #include "fwd.h"
00013 #include <string>
00014 #include <vector>
00015 #include <stdexcept>
00016 #include <sstream>
00017 #include <cctype>
00018 #include <cstdlib>
00019 #include <cerrno>
00020 #include <cstring>
00021 
00022 #if defined(_WIN32)
00023 # include <windows.h>
00024 #else
00025 # include <unistd.h>
00026 #endif
00027 #include <sys/stat.h>
00028 
00029 #if defined(__linux)
00030 # include <linux/limits.h>
00031 #endif
00032 
00033 NAMESPACE_BEGIN(filesystem)
00034 
00035 
00042 class path {
00043 public:
00044     enum path_type {
00045         windows_path = 0,
00046         posix_path = 1,
00047 #if defined(_WIN32)
00048         native_path = windows_path
00049 #else
00050         native_path = posix_path
00051 #endif
00052     };
00053 
00054     path() : m_type(native_path), m_absolute(false) { }
00055 
00056     path(const path &path)
00057         : m_type(path.m_type), m_path(path.m_path), m_absolute(path.m_absolute) {}
00058 
00059     path(path &&path)
00060         : m_type(path.m_type), m_path(std::move(path.m_path)),
00061           m_absolute(path.m_absolute) {}
00062 
00063     path(const char *string) { set(string); }
00064 
00065     path(const std::string &string) { set(string); }
00066 
00067 #if defined(_WIN32)
00068     path(const std::wstring &wstring) { set(wstring); }
00069     path(const wchar_t *wstring) { set(wstring); }
00070 #endif
00071 
00072     size_t length() const { return m_path.size(); }
00073 
00074     bool empty() const { return m_path.empty(); }
00075 
00076     bool is_absolute() const { return m_absolute; }
00077 
00078     path make_absolute() const {
00079 #if !defined(_WIN32)
00080         char temp[PATH_MAX];
00081         if (realpath(str().c_str(), temp) == NULL)
00082             throw std::runtime_error("Internal error in realpath(): " + std::string(strerror(errno)));
00083         return path(temp);
00084 #else
00085         std::wstring value = wstr(), out(MAX_PATH, '\0');
00086         DWORD length = GetFullPathNameW(value.c_str(), MAX_PATH, &out[0], NULL);
00087         if (length == 0)
00088             throw std::runtime_error("Internal error in realpath(): " + std::to_string(GetLastError()));
00089         return path(out.substr(0, length));
00090 #endif
00091     }
00092 
00093     bool exists() const {
00094 #if defined(_WIN32)
00095         return GetFileAttributesW(wstr().c_str()) != INVALID_FILE_ATTRIBUTES;
00096 #else
00097         struct stat sb;
00098         return stat(str().c_str(), &sb) == 0;
00099 #endif
00100     }
00101 
00102     size_t file_size() const {
00103 #if defined(_WIN32)
00104         struct _stati64 sb;
00105         if (_wstati64(wstr().c_str(), &sb) != 0)
00106             throw std::runtime_error("path::file_size(): cannot stat file \"" + str() + "\"!");
00107 #else
00108         struct stat sb;
00109         if (stat(str().c_str(), &sb) != 0)
00110             throw std::runtime_error("path::file_size(): cannot stat file \"" + str() + "\"!");
00111 #endif
00112         return (size_t) sb.st_size;
00113     }
00114 
00115     bool is_directory() const {
00116 #if defined(_WIN32)
00117         DWORD result = GetFileAttributesW(wstr().c_str());
00118         if (result == INVALID_FILE_ATTRIBUTES)
00119             return false;
00120         return (result & FILE_ATTRIBUTE_DIRECTORY) != 0;
00121 #else
00122         struct stat sb;
00123         if (stat(str().c_str(), &sb))
00124             return false;
00125         return S_ISDIR(sb.st_mode);
00126 #endif
00127     }
00128 
00129     bool is_file() const {
00130 #if defined(_WIN32)
00131         DWORD attr = GetFileAttributesW(wstr().c_str());
00132         return (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0);
00133 #else
00134         struct stat sb;
00135         if (stat(str().c_str(), &sb))
00136             return false;
00137         return S_ISREG(sb.st_mode);
00138 #endif
00139     }
00140 
00141     std::string extension() const {
00142         const std::string &name = filename();
00143         size_t pos = name.find_last_of(".");
00144         if (pos == std::string::npos)
00145             return "";
00146         return name.substr(pos+1);
00147     }
00148 
00149     std::string filename() const {
00150         if (empty())
00151             return "";
00152         const std::string &last = m_path[m_path.size()-1];
00153         return last;
00154     }
00155 
00156     path parent_path() const {
00157         path result;
00158         result.m_absolute = m_absolute;
00159 
00160         if (m_path.empty()) {
00161             if (!m_absolute)
00162                 result.m_path.push_back("..");
00163         } else {
00164             size_t until = m_path.size() - 1;
00165             for (size_t i = 0; i < until; ++i)
00166                 result.m_path.push_back(m_path[i]);
00167         }
00168         return result;
00169     }
00170 
00171     path operator/(const path &other) const {
00172         if (other.m_absolute)
00173             throw std::runtime_error("path::operator/(): expected a relative path!");
00174         if (m_type != other.m_type)
00175             throw std::runtime_error("path::operator/(): expected a path of the same type!");
00176 
00177         path result(*this);
00178 
00179         for (size_t i=0; i<other.m_path.size(); ++i)
00180             result.m_path.push_back(other.m_path[i]);
00181 
00182         return result;
00183     }
00184 
00185     std::string str(path_type type = native_path) const {
00186         std::ostringstream oss;
00187 
00188         if (m_type == posix_path && m_absolute)
00189             oss << "/";
00190 
00191         for (size_t i=0; i<m_path.size(); ++i) {
00192             oss << m_path[i];
00193             if (i+1 < m_path.size()) {
00194                 if (type == posix_path)
00195                     oss << '/';
00196                 else
00197                     oss << '\\';
00198             }
00199         }
00200 
00201         return oss.str();
00202     }
00203 
00204     void set(const std::string &str, path_type type = native_path) {
00205         m_type = type;
00206         if (type == windows_path) {
00207             m_path = tokenize(str, "/\\");
00208             m_absolute = str.size() >= 2 && std::isalpha(str[0]) && str[1] == ':';
00209         } else {
00210             m_path = tokenize(str, "/");
00211             m_absolute = !str.empty() && str[0] == '/';
00212         }
00213     }
00214 
00215     path &operator=(const path &path) {
00216         m_type = path.m_type;
00217         m_path = path.m_path;
00218         m_absolute = path.m_absolute;
00219         return *this;
00220     }
00221 
00222     path &operator=(path &&path) {
00223         if (this != &path) {
00224             m_type = path.m_type;
00225             m_path = std::move(path.m_path);
00226             m_absolute = path.m_absolute;
00227         }
00228         return *this;
00229     }
00230 
00231     friend std::ostream &operator<<(std::ostream &os, const path &path) {
00232         os << path.str();
00233         return os;
00234     }
00235 
00236     bool remove_file() {
00237 #if !defined(_WIN32)
00238         return std::remove(str().c_str()) == 0;
00239 #else
00240         return DeleteFileW(wstr().c_str()) != 0;
00241 #endif
00242     }
00243 
00244     bool resize_file(size_t target_length) {
00245 #if !defined(_WIN32)
00246         return ::truncate(str().c_str(), (off_t) target_length) == 0;
00247 #else
00248         HANDLE handle = CreateFileW(wstr().c_str(), GENERIC_WRITE, 0, nullptr, 0, FILE_ATTRIBUTE_NORMAL, nullptr);
00249         if (handle == INVALID_HANDLE_VALUE)
00250             return false;
00251         LARGE_INTEGER size;
00252         size.QuadPart = (LONGLONG) target_length;
00253         if (SetFilePointerEx(handle, size, NULL, FILE_BEGIN) == 0) {
00254             CloseHandle(handle);
00255             return false;
00256         }
00257         if (SetEndOfFile(handle) == 0) {
00258             CloseHandle(handle);
00259             return false;
00260         }
00261         CloseHandle(handle);
00262         return true;
00263 #endif
00264     }
00265 
00266     static path getcwd() {
00267 #if !defined(_WIN32)
00268         char temp[PATH_MAX];
00269         if (::getcwd(temp, PATH_MAX) == NULL)
00270             throw std::runtime_error("Internal error in getcwd(): " + std::string(strerror(errno)));
00271         return path(temp);
00272 #else
00273         std::wstring temp(MAX_PATH, '\0');
00274         if (!_wgetcwd(&temp[0], MAX_PATH))
00275             throw std::runtime_error("Internal error in getcwd(): " + std::to_string(GetLastError()));
00276         return path(temp.c_str());
00277 #endif
00278     }
00279 
00280 #if defined(_WIN32)
00281     std::wstring wstr(path_type type = native_path) const {
00282         std::string temp = str(type);
00283         int size = MultiByteToWideChar(CP_UTF8, 0, &temp[0], (int)temp.size(), NULL, 0);
00284         std::wstring result(size, 0);
00285         MultiByteToWideChar(CP_UTF8, 0, &temp[0], (int)temp.size(), &result[0], size);
00286         return result;
00287     }
00288 
00289 
00290     void set(const std::wstring &wstring, path_type type = native_path) {
00291         std::string string;
00292         if (!wstring.empty()) {
00293             int size = WideCharToMultiByte(CP_UTF8, 0, &wstring[0], (int)wstring.size(),
00294                             NULL, 0, NULL, NULL);
00295             string.resize(size, 0);
00296             WideCharToMultiByte(CP_UTF8, 0, &wstring[0], (int)wstring.size(),
00297                                 &string[0], size, NULL, NULL);
00298         }
00299         set(string, type);
00300     }
00301 
00302     path &operator=(const std::wstring &str) { set(str); return *this; }
00303 #endif
00304 
00305     bool operator==(const path &p) const { return p.m_path == m_path; }
00306     bool operator!=(const path &p) const { return p.m_path != m_path; }
00307 
00308 protected:
00309     static std::vector<std::string> tokenize(const std::string &string, const std::string &delim) {
00310         std::string::size_type lastPos = 0, pos = string.find_first_of(delim, lastPos);
00311         std::vector<std::string> tokens;
00312 
00313         while (lastPos != std::string::npos) {
00314             if (pos != lastPos)
00315                 tokens.push_back(string.substr(lastPos, pos - lastPos));
00316             lastPos = pos;
00317             if (lastPos == std::string::npos || lastPos + 1 == string.length())
00318                 break;
00319             pos = string.find_first_of(delim, ++lastPos);
00320         }
00321 
00322         return tokens;
00323     }
00324 
00325 protected:
00326     path_type m_type;
00327     std::vector<std::string> m_path;
00328     bool m_absolute;
00329 };
00330 
00331 inline bool create_directory(const path& p) {
00332 #if defined(_WIN32)
00333     return CreateDirectoryW(p.wstr().c_str(), NULL) != 0;
00334 #else
00335     return mkdir(p.str().c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == 0;
00336 #endif
00337 }
00338 
00339 NAMESPACE_END(filesystem)


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Jun 8 2019 20:17:15