Skip to content

Commit

Permalink
Use std::filesystem in filesys_tools (#748)
Browse files Browse the repository at this point in the history
* Refactor dl_wrapper to use updated filesys_tools
* Use unordered_set in dl_wrapper
  • Loading branch information
RainerKuemmerle authored Dec 2, 2023
1 parent b03c874 commit 0a0430f
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 197 deletions.
31 changes: 6 additions & 25 deletions g2o/apps/g2o_cli/dl_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@

#include <sys/types.h>

#include <algorithm>
#include <cstdio>
#include <regex>

#include "g2o/stuff/filesys_tools.h"
#include "g2o/stuff/logger.h"
Expand All @@ -38,19 +38,6 @@
#include <dlfcn.h>
#endif

#ifdef __APPLE__
#define SO_EXT "dylib"
#define SO_EXT_LEN 5
#elif defined(WINDOWS) || defined(CYGWIN)
#define SO_EXT "dll"
#define SO_EXT_LEN 3
#else // Linux
#define SO_EXT "so"
#define SO_EXT_LEN 2
#endif

using namespace std;

namespace g2o {

DlWrapper::DlWrapper() {}
Expand All @@ -62,18 +49,12 @@ DlWrapper::~DlWrapper() {
int DlWrapper::openLibraries(const std::string& directory,
const std::string& pattern) {
G2O_TRACE("Loading libraries from {} pattern {}", directory, pattern);
// cerr << "# loading libraries from " << directory << "\t pattern: " <<
// pattern << endl;
string searchPattern = directory + "/" + pattern;
if (pattern == "") searchPattern = directory + "/*";
vector<string> matchingFiles = getFilesByPattern(searchPattern.c_str());
std::vector<std::string> matchingFiles =
getFilesByPattern(directory, std::regex(pattern));

int numLibs = 0;
for (size_t i = 0; i < matchingFiles.size(); ++i) {
const string& filename = matchingFiles[i];
if (find(_filenames.begin(), _filenames.end(), filename) !=
_filenames.end())
continue;
for (const std::string& filename : matchingFiles) {
if (_filenames.count(filename) != 0) continue;

// open the lib
G2O_TRACE("Loading {}", filename);
Expand Down Expand Up @@ -117,7 +98,7 @@ bool DlWrapper::openLibrary(const std::string& filename) {

// cerr << "loaded " << filename << endl;

_filenames.push_back(filename);
_filenames.insert(filename);
_handles.push_back(handle);
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion g2o/apps/g2o_cli/dl_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
// clang-format on

#include <string>
#include <unordered_set>
#include <vector>

#include "g2o_cli_api.h"
Expand Down Expand Up @@ -77,7 +78,7 @@ class G2O_CLI_API DlWrapper {
#elif defined(WINDOWS)
std::vector<HMODULE> _handles;
#endif
std::vector<std::string> _filenames;
std::unordered_set<std::string> _filenames;
};

} // namespace g2o
Expand Down
6 changes: 4 additions & 2 deletions g2o/apps/g2o_cli/g2o_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ HMODULE getMyInstance() {
}
#endif

static constexpr std::string_view TYPES_PATTERN = "*_types_*." SO_EXT;
static constexpr std::string_view SOLVERS_PATTERN = "*_solver_*." SO_EXT;
static constexpr std::string_view TYPES_PATTERN =
"^.*g2o_types_.*\\." SO_EXT "$";
static constexpr std::string_view SOLVERS_PATTERN =
"^.*g2o_solver_.*\\." SO_EXT "$";

namespace g2o {

Expand Down
159 changes: 50 additions & 109 deletions g2o/stuff/filesys_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,134 +24,75 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/***************************************************************************
* filesysTools.cpp
*
* Fr 02 Mär 2007 23:14:08 CET
* Copyright 2007 Rainer Kümmerle
* Email [email protected]
****************************************************************************/
#include "filesys_tools.h"

// clang-format off
#ifdef WINDOWS
#include <windows.h>
#endif
// clang-format on

#include <sys/stat.h>
#include <sys/types.h>

#include <cstdio>
#include <ctime>
#include <iostream>

#if (defined(UNIX) || defined(CYGWIN)) && !defined(ANDROID)
#include <wordexp.h>
#endif

#ifdef __APPLE__
// #include <chrono>
// #include <thread>
#endif

using namespace ::std;
#include <filesystem>
#include <regex>
#include <string_view>

namespace g2o {

std::string getFileExtension(const std::string& filename) {
std::string::size_type lastDot = filename.find_last_of('.');
if (lastDot != std::string::npos)
return filename.substr(lastDot + 1);
else
return "";
std::string getFileExtension(std::string_view filename) {
const std::filesystem::path path(filename);
const std::string result = path.extension().string();
if (!result.empty() && result.front() == '.') return result.substr(1);
return result;
}

std::string getPureFilename(const std::string& filename) {
std::string::size_type lastDot = filename.find_last_of('.');
if (lastDot != std::string::npos)
return filename.substr(0, lastDot);
else
return filename;
std::string getPureFilename(std::string_view filename) {
const std::filesystem::path path(filename);
if (path.has_parent_path()) {
return (path.parent_path() / path.stem()).string();
}
return path.stem().string();
}

std::string getBasename(const std::string& filename) {
#ifdef WINDOWS
std::string::size_type lastSlash = filename.find_last_of('\\');
#else
std::string::size_type lastSlash = filename.find_last_of('/');
#endif
if (lastSlash != std::string::npos)
return filename.substr(lastSlash + 1);
else
return filename;
std::string getBasename(std::string_view filename) {
const std::filesystem::path path(filename);
return path.filename().string();
}

std::string getDirname(const std::string& filename) {
#ifdef WINDOWS
std::string::size_type lastSlash = filename.find_last_of('\\');
#else
std::string::size_type lastSlash = filename.find_last_of('/');
#endif
if (lastSlash != std::string::npos)
return filename.substr(0, lastSlash);
else
return "";
std::string getDirname(std::string_view filename) {
const std::filesystem::path path(filename);
return path.parent_path().string();
}

std::string changeFileExtension(const std::string& filename,
const std::string& newExt, bool stripDot) {
std::string::size_type lastDot = filename.find_last_of('.');
if (lastDot != std::string::npos) {
if (stripDot)
return filename.substr(0, lastDot) + newExt;
else
return filename.substr(0, lastDot + 1) + newExt;
} else
return filename;
std::string changeFileExtension(std::string_view filename,
std::string_view newExt) {
std::filesystem::path path(filename);
if (!path.has_extension()) {
return path.string();
}
path.replace_extension(std::filesystem::path(newExt));
return path.string();
}

bool fileExists(const char* filename) {
struct stat statInfo;
return (stat(filename, &statInfo) == 0);
bool fileExists(std::string_view filename) {
const std::filesystem::path path(filename);
return std::filesystem::exists(path);
}

std::vector<std::string> getFilesByPattern(const char* pattern) {
std::vector<std::string> result;

#ifdef WINDOWS

HANDLE hFind;
WIN32_FIND_DATA FData;
if ((hFind = FindFirstFile(pattern, &FData)) != INVALID_HANDLE_VALUE) {
do {
result.push_back(FData.cFileName);
} while (FindNextFile(hFind, &FData));
FindClose(hFind);
}

#elif (defined(UNIX) || defined(CYGWIN)) && !defined(ANDROID)

wordexp_t p;
wordexp(pattern, &p, 0);
std::vector<std::string> getFilesByPattern(std::string_view directory,
const std::regex& pattern) {
auto match = [&pattern](const std::filesystem::path& entry) {
return std::regex_search(entry.filename().string(), pattern);
};

// For some reason, wordexp sometimes fails on an APPLE machine to
// return anything; therefore, run it several times until we do find
// something - or give up
#ifdef __APPLE__
for (int k = 0; (k < 100) && (p.we_wordc == 0); k++) {
// chrono::milliseconds duration(20);
// this_thread::sleep_for(duration);
wordexp(pattern, &p, WRDE_APPEND);
std::vector<std::string> result;
for (const auto& dir_entry :
std::filesystem::directory_iterator(std::filesystem::path(directory))) {
if (dir_entry.is_regular_file() && match(dir_entry)) {
result.emplace_back(dir_entry.path().string());
continue;
}
if (dir_entry.is_symlink() &&
std::filesystem::is_regular_file(
std::filesystem::read_symlink(dir_entry)) &&
match(dir_entry)) {
result.emplace_back(dir_entry.path().string());
continue;
}
}
#endif

result.reserve(p.we_wordc);
for (size_t i = 0; i < p.we_wordc; ++i) result.push_back(p.we_wordv[i]);

wordfree(&p);

#endif

return result;
}
Expand Down
30 changes: 12 additions & 18 deletions g2o/stuff/filesys_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/***************************************************************************
* filesysTools.h
*
* Fr 02 Mär 2007 23:14:21 CET
* Copyright 2007 Rainer Kümmerle
* Email [email protected]
****************************************************************************/

#ifndef G2O_FILESYS_TOOLS_H
#define G2O_FILESYS_TOOLS_H

Expand All @@ -44,7 +36,9 @@
* \brief utility functions for handling files, directory on Linux/Unix
*/

#include <regex>
#include <string>
#include <string_view>
#include <vector>

namespace g2o {
Expand All @@ -53,43 +47,43 @@ namespace g2o {
* get filename extension (the part after the last .), e.g.
* the extension of file.txt is txt
*/
G2O_STUFF_API std::string getFileExtension(const std::string& filename);
G2O_STUFF_API std::string getFileExtension(std::string_view filename);

/**
* get the filename without the extension.
* file.txt -> file
*/
G2O_STUFF_API std::string getPureFilename(const std::string& filename);
G2O_STUFF_API std::string getPureFilename(std::string_view filename);

/**
* change the fileextension of a given filename.
* Only if filename contains an extension, otherwise filename is returned.
*/
G2O_STUFF_API std::string changeFileExtension(const std::string& filename,
const std::string& newExt,
bool stripDot = false);
G2O_STUFF_API std::string changeFileExtension(std::string_view filename,
std::string_view newExt);

/**
* return the basename of the given filename
* /etc/fstab -> fstab
*/
G2O_STUFF_API std::string getBasename(const std::string& filename);
G2O_STUFF_API std::string getBasename(std::string_view filename);

/**
* return the directory of a given filename
* /etc/fstab -> /etc
*/
G2O_STUFF_API std::string getDirname(const std::string& filename);
G2O_STUFF_API std::string getDirname(std::string_view filename);

/**
* check if file exists (note a directory is also a file)
*/
G2O_STUFF_API bool fileExists(const char* filename);
G2O_STUFF_API bool fileExists(std::string_view filename);

/**
* return all files that match a given pattern, e.g., ~/blaa*.txt, /tmp/a*
* return all files that match a given regexp in the directory.
*/
G2O_STUFF_API std::vector<std::string> getFilesByPattern(const char* pattern);
G2O_STUFF_API std::vector<std::string> getFilesByPattern(
std::string_view directory, const std::regex& pattern);

} // namespace g2o
// @}
Expand Down
Loading

0 comments on commit 0a0430f

Please sign in to comment.