licornea_tools
filesystem.win.cc
Go to the documentation of this file.
1 #include "os.h"
2 #if defined(LICORNEA_OS_WINDOWS)
3 #include "filesystem.h"
4 #include <windows.h>
5 #include <string>
6 #include <fstream>
7 #include <deque>
8 
9 namespace {
10 
11 template<typename Char>
12 struct temp_string_holder {
13  std::basic_string<Char> str;
14 
15  explicit temp_string_holder(const std::string& in_str) :
16  str(in_str.begin(), in_str.end()) { }
17  operator const Char* () const
18  { return str.c_str(); }
19 };
20 template<>
21 struct temp_string_holder<char> {
22  const std::string& str;
23 
24  explicit temp_string_holder(const std::string& in_str) :
25  str(in_str) { }
26  operator const char* () const
27  { return str.c_str(); }
28 };
29 
30 temp_string_holder<char> to_LPCSTR(const std::string& str) {
31  return temp_string_holder<char>(str);
32 }
33 temp_string_holder<wchar_t> to_LPCWSTR(const std::string& str) {
34  return temp_string_holder<wchar_t>(str);
35 }
36 temp_string_holder<TCHAR> to_LPCTSTR(const std::string& str) {
37  return temp_string_holder<TCHAR>(str);
38 }
39 
40 }
41 
42 namespace tlz {
43 
44 namespace {
45  constexpr std::size_t path_max_length = 1024;
46 }
47 
48 std::string filename_parent(const std::string& path_) {
49  std::string path(path_);
50  if(path.back() == '/' || path.back() == '\\') path = path.substr(0, path.length() - 1);
51  auto pos = path.find_last_of("/\\");
52  if(pos != std::string::npos) return path.substr(0, pos + 1);
53  else if(path != "." && path != ".." && path != "" && !(path.length() <= 3 && path[1] == ':')) return ".";
54  else throw std::invalid_argument("cannot get parent path of " + path);
55 }
56 
57 std::string filename_append(const std::string& a, const std::string& b) {
58  if(a.back() == '/' || a.back() == '\\') return a + b;
59  else return a + "\\" + b;
60 }
61 
62 std::string get_current_directory() {
63  TCHAR buffer[path_max_length];
64  DWORD length = GetCurrentDirectory(path_max_length, buffer);
65  if(length == 0 || length > path_max_length)
66  throw std::system_error(GetLastError(), std::system_category(), "GetCurrentDirectory() failed");
67 
68  return std::string(buffer, buffer + length);
69 }
70 
71 bool file_exists(const std::string& filename) {
72  DWORD attr = GetFileAttributes(to_LPCTSTR(filename));
73  return (attr != INVALID_FILE_ATTRIBUTES);
74 }
75 
76 bool is_directory(const std::string& filename) {
77  DWORD attr = GetFileAttributes(to_LPCTSTR(filename));
78  if(attr == INVALID_FILE_ATTRIBUTES)
79  throw std::system_error(GetLastError(), std::system_category(), "GetFileAttributes() failed");
80  return (attr & FILE_ATTRIBUTE_DIRECTORY);
81 }
82 
83 bool is_file(const std::string& filename) {
84  DWORD attr = GetFileAttributes(to_LPCTSTR(filename));
85  if(attr == INVALID_FILE_ATTRIBUTES)
86  throw std::system_error(GetLastError(), std::system_category(), "GetFileAttributes() failed");
87  return (attr == FILE_ATTRIBUTE_NORMAL);
88 }
89 
90 std::size_t file_size(const std::string& filename) {
91  std::ifstream stream(filename, std::ios_base::ate | std::ios_base::binary);
92  return stream.tellg();
93 }
94 
95 void make_directory(const std::string& dirname) {
96  BOOL ret = CreateDirectory(to_LPCTSTR(dirname), NULL);
97  if(ret == 0) throw std::system_error(GetLastError(), std::system_category(), "CreateDirectory() failed");
98 }
99 
100 void make_parent_directories(const std::string& filename) {
101  std::deque<std::string> new_dirs;
102 
103  std::string dir = filename_parent(filename);
104  while(! file_exists(dir) && dir != "/" && dir != "\\") {
105  new_dirs.push_front(dir);
106  dir = filename_parent(dir);
107  }
108  for(const std::string& dir : new_dirs) {
109  make_directory(dir);
110  }
111 }
112 
113 void delete_file(const std::string& filename) {
114  BOOL ret = DeleteFile(to_LPCTSTR(filename));
115  if(ret == 0) throw std::system_error(GetLastError(), std::system_category(), "DeleteFile() failed");
116 }
117 
118 }
119 
120 
121 #endif
std::string filename_append(const std::string &a, const std::string &b)
bool file_exists(const std::string &filename)
bool is_file(const std::string &filename)
bool is_directory(const std::string &filename)
std::size_t file_size(const std::string &filename)
std::string get_current_directory()
void delete_file(const std::string &filename)
std::string filename_parent(const std::string &filename)
void make_directory(const std::string &dirname)
void make_parent_directories(const std::string &filename)