Files
CoolProp/src/CPfilepaths.cpp

237 lines
7.1 KiB
C++

#include "PlatformDetermination.h"
#include "Exceptions.h"
#include "CPfilepaths.h"
#include "CPstrings.h"
#include "CoolPropTools.h"
#include <fstream>
#include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
// This will kill the horrible min and max macros
#ifndef NOMINMAX
#define NOMINMAX
#endif
#if defined(__ISWINDOWS__)
#define UNICODE
#define _UNICODE
#include "Windows.h"
#include <windows.h> // for the CreateDirectory function
#else
#include <unistd.h>
#if !defined(__powerpc__)
#include <pwd.h>
#endif
#endif
#if defined(__ISWINDOWS__)
/// From http://stackoverflow.com/a/17827724/1360263
bool IsBrowsePath(const std::wstring& path)
{
return (path == L"." || path == L"..");
}
unsigned long long CalculateDirSize(const std::wstring &path, std::vector<std::wstring> *errVect)
{
unsigned long long size = 0;
WIN32_FIND_DATAW data;
HANDLE sh = NULL;
sh = FindFirstFileW((path + L"\\*").c_str(), &data);
if (sh == INVALID_HANDLE_VALUE )
{
//if we want, store all happened error
if (errVect != NULL)
errVect ->push_back(path);
return size;
}
do
{
// skip current and parent
if (!IsBrowsePath(data.cFileName))
{
// if found object is ...
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
// directory, then search it recursievly
size += CalculateDirSize(path + L"\\" + data.cFileName, NULL);
else
// otherwise get object size and add it to directory size
size += data.nFileSizeHigh * (unsigned long long)(MAXDWORD) + data.nFileSizeLow;
}
} while (FindNextFileW(sh, &data)); // do
FindClose(sh);
return size;
}
#elif defined(__ANDROID__) || defined(__powerpc__)
// Android doesn't have ftw.h, also doesn't accept not having this file
unsigned long long CalculateDirSize(const std::string &path){
return 0;
}
#else
#include <ftw.h>
#include <stdint.h>
#include <iostream>
static thread_local unsigned long long ftw_summer; // An evil global variable for the ftw function
int ftw_function(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf){
ftw_summer += sb->st_size;
return 0; /* To tell nftw() to continue */
}
unsigned long long CalculateDirSize(const std::string &path){
ftw_summer = 0;
int flags = 0 | FTW_DEPTH | FTW_PHYS;
nftw(path.c_str(), ftw_function, 20, flags);
double temp = ftw_summer;
ftw_summer = 0;
return temp;
}
#endif
std::vector<char> get_binary_file_contents(const char *filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
if (in)
{
std::vector<char> contents;
in.seekg(0, std::ios::end);
contents.resize((unsigned int) in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
return(contents);
}
throw(errno);
}
void make_dirs(std::string file_path)
{
std::replace( file_path.begin(), file_path.end(), '\\', '/'); // replace all '\' with '/'
#if defined(__ISWINDOWS__)
const char sep = '\\'; // well, Windows (and DOS) allows forward slash "/", too :)
#else
const char sep = '/';
#endif
std::vector<std::string> pathsplit = strsplit(file_path,'/');
std::string path = pathsplit[0]; // will throw if pathsplit.size() == 0
for (std::size_t i = 0, sz = pathsplit.size(); i < sz; i++)
{
if (!path_exists(path))
{
#if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows
int errcode = CreateDirectoryA((LPCSTR)path.c_str(),NULL);
if (errcode == 0){
switch(GetLastError()){
case ERROR_ALREADY_EXISTS:
break;
case ERROR_PATH_NOT_FOUND:
throw CoolProp::ValueError(format("Unable to make the directory %s",path.c_str()));
default:
break;
}
}
#else
#if defined(__powerpc__)
#else
mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
#endif
}
if (i < (sz-1))
path += format("%c%s", sep, pathsplit[i+1].c_str());
}
};
std::string get_home_dir(void)
{
// See http://stackoverflow.com/questions/2552416/how-can-i-find-the-users-home-dir-in-a-cross-platform-manner-using-c
#if defined(__ISLINUX__)
char *home = NULL;
home = getenv("HOME");
return std::string(home);
#elif defined(__ISAPPLE__)
char *home = NULL;
home = getenv("HOME");
if (home==NULL) {
struct passwd* pwd = getpwuid(getuid());
if (pwd) {
home = pwd->pw_dir;
}
}
if (home==NULL) {
throw CoolProp::NotImplementedError("Could not detect home directory.");
}
return std::string(home);
#elif defined(__ISWINDOWS__)
#if defined(_MSC_VER)
#pragma warning (push)
#pragma warning (disable : 4996)
#endif
char * pUSERPROFILE = getenv("USERPROFILE");
if (pUSERPROFILE != NULL) {
return std::string(pUSERPROFILE);
} else {
char * pHOMEDRIVE = getenv("HOMEDRIVE");
char * pHOMEPATH = getenv("HOMEPATH");
if (pHOMEDRIVE != NULL && pHOMEPATH != NULL) {
return std::string(pHOMEDRIVE) + std::string(pHOMEPATH);
} else {
return std::string("");
}
}
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#else
throw CoolProp::NotImplementedError("This function is not defined for your platform.");
#endif
};
bool path_exists(const std::string &path)
{
#if defined(__ISWINDOWS__) // Defined for 32-bit and 64-bit windows
struct _stat buf;
// Get data associated with path using the windows libraries,
// and if you can (result == 0), the path exists
if ( _stat( path.c_str(), &buf) == 0)
return true;
else
return false;
#elif defined(__ISLINUX__) || defined(__ISAPPLE__)
struct stat st;
if(lstat(path.c_str(),&st) == 0) {
if(S_ISDIR(st.st_mode)) return true;
if(S_ISREG(st.st_mode)) return true;
return false;
} else {
return false;
}
#else
throw CoolProp::NotImplementedError("This function is not defined for your platform.");
#endif
};
std::string get_file_contents(const char *filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
if (in)
{
std::string contents;
in.seekg(0, std::ios::end);
contents.resize((unsigned int) in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
return(contents);
}
throw(errno);
}