Browse Source

Made filesystem methods thread safe

merge-requests/386/merge
eidheim 5 years ago
parent
commit
ddaca98476
  1. 100
      src/filesystem.cpp
  2. 24
      tests/filesystem_test.cpp

100
src/filesystem.cpp

@ -83,48 +83,47 @@ std::string filesystem::unescape_argument(const std::string &argument) {
} }
boost::filesystem::path filesystem::get_current_path() noexcept { boost::filesystem::path filesystem::get_current_path() noexcept {
static boost::filesystem::path current_path; auto current_path = [] {
if(!current_path.empty())
return current_path;
#ifdef _WIN32 #ifdef _WIN32
boost::system::error_code ec; boost::system::error_code ec;
auto path = boost::filesystem::current_path(ec); auto path = boost::filesystem::current_path(ec);
if(!ec) { if(!ec)
current_path = std::move(path); return path;
return current_path; return boost::filesystem::path();
}
return boost::filesystem::path();
#else #else
std::string path; std::string path;
TinyProcessLib::Process process("pwd", "", [&path](const char *buffer, size_t length) { TinyProcessLib::Process process("pwd", "", [&path](const char *buffer, size_t length) {
path += std::string(buffer, length); path += std::string(buffer, length);
}); });
if(process.get_exit_status() == 0) { if(process.get_exit_status() == 0) {
if(!path.empty() && path.back() == '\n') if(!path.empty() && path.back() == '\n')
path.pop_back(); path.pop_back();
current_path = boost::filesystem::path(path); return boost::filesystem::path(path);
return current_path; }
} return boost::filesystem::path();
return boost::filesystem::path();
#endif #endif
};
static boost::filesystem::path path = current_path();
return path;
} }
boost::filesystem::path filesystem::get_home_path() noexcept { boost::filesystem::path filesystem::get_home_path() noexcept {
static boost::filesystem::path home_path; auto home_path = [] {
if(!home_path.empty()) std::vector<std::string> environment_variables = {"HOME", "AppData"};
return home_path; for(auto &variable : environment_variables) {
std::vector<std::string> environment_variables = {"HOME", "AppData"}; if(auto ptr = std::getenv(variable.c_str())) {
for(auto &variable : environment_variables) { boost::system::error_code ec;
if(auto ptr = std::getenv(variable.c_str())) { boost::filesystem::path path(ptr);
boost::system::error_code ec; if(boost::filesystem::exists(path, ec))
boost::filesystem::path path(ptr); return path;
if(boost::filesystem::exists(path, ec)) {
home_path = std::move(path);
return home_path;
} }
} }
} return boost::filesystem::path();
return boost::filesystem::path(); };
static boost::filesystem::path path = home_path();
return path;
} }
boost::filesystem::path filesystem::get_short_path(const boost::filesystem::path &path) noexcept { boost::filesystem::path filesystem::get_short_path(const boost::filesystem::path &path) noexcept {
@ -260,22 +259,25 @@ boost::filesystem::path filesystem::get_executable(const boost::filesystem::path
// Based on https://stackoverflow.com/a/11295568 // Based on https://stackoverflow.com/a/11295568
const std::vector<boost::filesystem::path> &filesystem::get_executable_search_paths() { const std::vector<boost::filesystem::path> &filesystem::get_executable_search_paths() {
static std::vector<boost::filesystem::path> result; auto executable_search_paths = [] {
if(!result.empty()) std::vector<boost::filesystem::path> paths;
return result;
const std::string env = getenv("PATH");
const std::string env = getenv("PATH"); const char delimiter = ':';
const char delimiter = ':';
size_t previous = 0;
size_t previous = 0; size_t pos;
size_t pos; while((pos = env.find(delimiter, previous)) != std::string::npos) {
while((pos = env.find(delimiter, previous)) != std::string::npos) { paths.emplace_back(env.substr(previous, pos - previous));
result.emplace_back(env.substr(previous, pos - previous)); previous = pos + 1;
previous = pos + 1; }
} paths.emplace_back(env.substr(previous));
result.emplace_back(env.substr(previous));
return paths;
};
return result; static std::vector<boost::filesystem::path> paths = executable_search_paths();
return paths;
} }
boost::filesystem::path filesystem::find_executable(const std::string &executable_name) { boost::filesystem::path filesystem::find_executable(const std::string &executable_name) {

24
tests/filesystem_test.cpp

@ -3,14 +3,26 @@
int main() { int main() {
{ {
auto home_path = filesystem::get_home_path(); auto path = filesystem::get_home_path();
g_assert(!home_path.empty()); g_assert(!path.empty());
g_assert(boost::filesystem::exists(path));
g_assert(boost::filesystem::is_directory(path));
} }
{ {
auto home_path = filesystem::get_current_path(); auto path = filesystem::get_current_path();
g_assert(!home_path.empty()); g_assert(!path.empty());
g_assert(boost::filesystem::exists(home_path)); g_assert(boost::filesystem::exists(path));
g_assert(boost::filesystem::is_directory(home_path)); g_assert(boost::filesystem::is_directory(path));
}
{
auto paths = filesystem::get_executable_search_paths();
g_assert(!paths.empty());
for(auto &path : paths) {
g_assert(!path.empty());
g_assert(boost::filesystem::exists(path));
g_assert(boost::filesystem::is_directory(path));
}
} }
{ {

Loading…
Cancel
Save