Skip to content
Snippets Groups Projects
util.cc 3.22 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <vereign/fs/util.hh>
    
    #include <vereign/fs/operations.hh>
    #include <vereign/fs/path.hh>
    #include <vereign/fs/errors.hh>
    
    #include <vereign/core/rand.hh>
    #include <vereign/core/string.hh>
    #include <boost/filesystem/operations.hpp>
    
    #include <boost/filesystem/fstream.hpp>
    
    // FIXME: remove
    #include <iostream>
    
    
    #ifdef _WIN32
    # include <shlobj_core.h>
    #endif
    
    namespace vereign::fs {
    
    namespace detail {
    
    auto PathToString(const boost::filesystem::path& path) -> std::string {
    #ifdef _WIN32
      return string::narrow(path.wstring());
    #else
      return path.string();
    #endif
    }
    
    auto StringToPath(std::string_view path) -> boost::filesystem::path {
    #ifdef _WIN32
      return boost::filesystem::path{string::widen(path)};
    #else
      return boost::filesystem::path{std::string{path}};
    #endif
    }
    
    }
    
    RemoveFileGuard::RemoveFileGuard(std::string path)
      : path_{std::move(path)}
    {
    }
    
    RemoveFileGuard::~RemoveFileGuard() {
      boost::filesystem::remove(detail::StringToPath(path_));
    }
    
    RemoveAllGuard::RemoveAllGuard(std::string path)
      : path_{std::move(path)}
    {
    }
    
    RemoveAllGuard::~RemoveAllGuard() {
      boost::filesystem::remove_all(detail::StringToPath(path_));
    }
    
    auto TempFilePath(std::string_view dir, std::string_view prefix) -> std::string {
      return path::Join(std::string(dir), std::string(prefix) + core::RandLowerAlpha(10));
    }
    
    auto TempFilePath(std::string_view prefix) -> std::string {
      return TempFilePath(detail::PathToString(boost::filesystem::temp_directory_path()), prefix);
    }
    
    auto TempDir(std::string_view prefix) -> std::string {
    
      auto dir = TempFilePath(prefix);
    
      CreateDir(dir);
    
    
      return dir;
    }
    
    auto HomePath() -> std::string {
    #ifdef _WIN32
      PWSTR home;
      SHGetKnownFolderPath(
        FOLDERID_LocalAppData,
        0,
        nullptr,
        &home
      );
    
      std::wstring wpath;
      try {
        wpath = home;
        CoTaskMemFree(home);
      } catch (...) {
        CoTaskMemFree(home);
        throw;
      }
    
      return "";
    
      auto path = boost::filesystem::path(wpath);
      if (boost::filesystem::exists(path) && boost::filesystem::is_directory(path)) {
        return detail::PathToString(path);
      }
    
      throw HomeNotFoundError{};
    #else
      auto home = std::getenv("HOME");
      if (home == nullptr) {
        throw HomeNotFoundError{};
      }
    
      auto path = boost::filesystem::path{home};
      if (boost::filesystem::exists(path) && boost::filesystem::is_directory(path)) {
        return detail::PathToString(path);
      }
    
      throw HomeNotFoundError{};
    #endif
    }
    
    
    auto ReadFile(std::string_view path) -> bytes::Buffer {
      boost::filesystem::ifstream file{
        detail::StringToPath(path),
        boost::filesystem::fstream::binary | boost::filesystem::fstream::ate,
      };
    
      if (!file.is_open()) {
        throw fs::Error("open file for reading failed");
      }
    
      auto size = file.tellg();
      bytes::Buffer result{static_cast<size_t>(size)};
      file.seekg(0);
    
      file.read((char*) result.end(), size);
      result.IncSize(file.gcount());
    
      file.close();
    
      return result;
    }
    
    void WriteFile(std::string_view path, bytes::View data) {
      boost::filesystem::ofstream file{
        detail::StringToPath(path),
        boost::filesystem::fstream::binary | boost::filesystem::fstream::trunc,
      };
    
      if (!file.is_open()) {
        throw fs::Error("open file for writing failed");
      }
    
      file.write(data.CharData(), data.Size());
      file.close();
    }
    
    
    } // namespace vereign::fs