CoolProp  6.6.0
An open-source fluid property and humid air property database
CPfilepaths.cpp
Go to the documentation of this file.
2 #include "Exceptions.h"
3 #include "CPfilepaths.h"
4 #include "CPstrings.h"
5 #include "CoolPropTools.h"
6 
7 #include <fstream>
8 #include <algorithm>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <cerrno>
12 
13 // This will kill the horrible min and max macros
14 #ifndef NOMINMAX
15 # define NOMINMAX
16 #endif
17 
18 #if defined(__ISWINDOWS__)
19 # define UNICODE
20 # define _UNICODE
21 # include "Windows.h"
22 # include <windows.h> // for the CreateDirectory function
23 #else
24 # include <unistd.h>
25 # if !defined(__powerpc__)
26 # include <pwd.h>
27 # endif
28 #endif
29 
30 #if defined(__ISWINDOWS__)
32 bool IsBrowsePath(const std::wstring& path) {
33  return (path == L"." || path == L"..");
34 }
35 unsigned long long CalculateDirSize(const std::wstring& path, std::vector<std::wstring>* errVect) {
36  unsigned long long size = 0;
37  WIN32_FIND_DATAW data;
38  HANDLE sh = NULL;
39  sh = FindFirstFileW((path + L"\\*").c_str(), &data);
40 
41  if (sh == INVALID_HANDLE_VALUE) {
42  //if we want, store all happened error
43  if (errVect != NULL) errVect->push_back(path);
44  return size;
45  }
46 
47  do {
48  // skip current and parent
49  if (!IsBrowsePath(data.cFileName)) {
50  // if found object is ...
51  if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
52  // directory, then search it recursievly
53  size += CalculateDirSize(path + L"\\" + data.cFileName, NULL);
54  else
55  // otherwise get object size and add it to directory size
56  size += data.nFileSizeHigh * (unsigned long long)(MAXDWORD) + data.nFileSizeLow;
57  }
58 
59  } while (FindNextFileW(sh, &data)); // do
60 
61  FindClose(sh);
62 
63  return size;
64 }
65 #elif defined(__ANDROID__) || defined(__powerpc__)
66 // Android doesn't have ftw.h, also doesn't accept not having this file
67 unsigned long long CalculateDirSize(const std::string& path) {
68  return 0;
69 }
70 #else
71 # include <ftw.h>
72 # include <stdint.h>
73 # include <iostream>
74 
75 static thread_local unsigned long long ftw_summer; // An evil global variable for the ftw function
76 int ftw_function(const char* fpath, const struct stat* sb, int tflag, struct FTW* ftwbuf) {
77  ftw_summer += sb->st_size;
78  return 0; /* To tell nftw() to continue */
79 }
80 unsigned long long CalculateDirSize(const std::string& path) {
81  ftw_summer = 0;
82  int flags = 0 | FTW_DEPTH | FTW_PHYS;
83  nftw(path.c_str(), ftw_function, 20, flags);
84  double temp = ftw_summer;
85  ftw_summer = 0;
86  return temp;
87 }
88 #endif
89 
90 std::vector<char> get_binary_file_contents(const char* filename) {
91  std::ifstream in(filename, std::ios::in | std::ios::binary);
92  if (in) {
93  std::vector<char> contents;
94  in.seekg(0, std::ios::end);
95  contents.resize((unsigned int)in.tellg());
96  in.seekg(0, std::ios::beg);
97  in.read(&contents[0], contents.size());
98  in.close();
99  return (contents);
100  }
101  throw(errno);
102 }
103 
104 void make_dirs(std::string file_path) {
105  std::replace(file_path.begin(), file_path.end(), '\\', '/'); // replace all '\' with '/'
106 
107 #if defined(__ISWINDOWS__)
108  const char sep = '\\'; // well, Windows (and DOS) allows forward slash "/", too :)
109 #else
110  const char sep = '/';
111 #endif
112 
113  std::vector<std::string> pathsplit = strsplit(file_path, '/');
114  std::string path = pathsplit[0]; // will throw if pathsplit.size() == 0
115  for (std::size_t i = 0, sz = pathsplit.size(); i < sz; i++) {
116  if (!path_exists(path)) {
117 #if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows
118  int errcode = CreateDirectoryA((LPCSTR)path.c_str(), NULL);
119  if (errcode == 0) {
120  switch (GetLastError()) {
121  case ERROR_ALREADY_EXISTS:
122  break;
123  case ERROR_PATH_NOT_FOUND:
124  throw CoolProp::ValueError(format("Unable to make the directory %s", path.c_str()));
125  default:
126  break;
127  }
128  }
129 #else
130 # if defined(__powerpc__)
131 # else
132  mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
133 # endif
134 #endif
135  }
136  if (i < (sz - 1)) path += format("%c%s", sep, pathsplit[i + 1].c_str());
137  }
138 };
139 
140 std::string get_separator(void) {
141 #if defined(__ISLINUX__)
142  return std::string("/");
143 #elif defined(__ISAPPLE__)
144  return std::string("/");
145 #elif defined(__ISWINDOWS__)
146  return std::string("\\");
147 #else
148  throw CoolProp::NotImplementedError("This function is not defined for your platform.");
149 #endif
150 }
151 
152 std::string get_home_dir(void) {
153 // See http://stackoverflow.com/questions/2552416/how-can-i-find-the-users-home-dir-in-a-cross-platform-manner-using-c
154 #if defined(__ISLINUX__)
155  char* home = NULL;
156  home = getenv("HOME");
157  return std::string(home);
158 #elif defined(__ISAPPLE__)
159  char* home = NULL;
160  home = getenv("HOME");
161  if (home == NULL) {
162  struct passwd* pwd = getpwuid(getuid());
163  if (pwd) {
164  home = pwd->pw_dir;
165  }
166  }
167  if (home == NULL) {
168  throw CoolProp::NotImplementedError("Could not detect home directory.");
169  }
170  return std::string(home);
171 #elif defined(__ISWINDOWS__)
172 # if defined(_MSC_VER)
173 # pragma warning(push)
174 # pragma warning(disable : 4996)
175 # endif
176  char* pUSERPROFILE = getenv("USERPROFILE");
177  if (pUSERPROFILE != NULL) {
178  return std::string(pUSERPROFILE);
179  } else {
180  char* pHOMEDRIVE = getenv("HOMEDRIVE");
181  char* pHOMEPATH = getenv("HOMEPATH");
182  if (pHOMEDRIVE != NULL && pHOMEPATH != NULL) {
183  return std::string(pHOMEDRIVE) + std::string(pHOMEPATH);
184  } else {
185  return std::string("");
186  }
187  }
188 # if defined(_MSC_VER)
189 # pragma warning(pop)
190 # endif
191 #else
192  throw CoolProp::NotImplementedError("This function is not defined for your platform.");
193 #endif
194 };
195 
196 bool path_exists(const std::string& path) {
197  std::string path_cpy;
198  if (endswith(path, get_separator())) {
199  path_cpy = path.substr(0, path.size() - 1);
200  } else {
201  path_cpy = path;
202  }
203 
204 #if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows
205  struct _stat buf;
206  // Get data associated with path using the windows libraries,
207  // and if you can (result == 0), the path exists
208  if (_stat(path_cpy.c_str(), &buf) == 0) {
209  return true;
210  } else {
211  return false;
212  }
213 #elif defined(__ISLINUX__) || defined(__ISAPPLE__)
214  struct stat st;
215  if (lstat(path_cpy.c_str(), &st) == 0) {
216  if (S_ISDIR(st.st_mode)) return true;
217  if (S_ISREG(st.st_mode)) return true;
218  return false;
219  } else {
220  return false;
221  }
222 #else
223  throw CoolProp::NotImplementedError("This function is not defined for your platform.");
224 #endif
225 };
226 
227 std::string join_path(const std::string& one, const std::string& two) {
228  std::string result;
229  std::string separator = get_separator();
230  if (!endswith(one, separator) && !one.empty()) {
231  result = one + separator;
232  } else {
233  result = one;
234  }
235  result.append(two);
236  return result;
237 }
238 
239 std::string get_file_contents(const char* filename) {
240  std::ifstream in(filename, std::ios::in | std::ios::binary);
241  if (in) {
242  std::string contents;
243  in.seekg(0, std::ios::end);
244  contents.resize((unsigned int)in.tellg());
245  in.seekg(0, std::ios::beg);
246  in.read(&contents[0], contents.size());
247  in.close();
248  return (contents);
249  }
250  throw(errno);
251 }