123 lines
3.4 KiB
C++
123 lines
3.4 KiB
C++
// See boost/filesystem/src/filesystem.cpp
|
|
|
|
#include "filesystem.h"
|
|
#include <utility>
|
|
#include <string>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <unistd.h>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <dirent.h>
|
|
#include <sys/stat.h>
|
|
|
|
namespace std {
|
|
namespace filesystem {
|
|
|
|
typedef path::value_type value_type;
|
|
typedef path::string_type string_type;
|
|
typedef string_type::size_type size_type;
|
|
|
|
inline size_type find_separator(const value_type* p, size_type size) noexcept
|
|
{
|
|
const value_type* sep = static_cast< const value_type* >(std::memchr(p, path::preferred_separator, size));
|
|
size_type pos = size;
|
|
if (!!sep)
|
|
pos = sep - p;
|
|
return pos;
|
|
}
|
|
|
|
path operator/(path lhs, path const& rhs)
|
|
{
|
|
return lhs /= rhs;
|
|
}
|
|
|
|
path current_path()
|
|
{
|
|
char buf[path::max_path];
|
|
memset(buf, 0, path::max_path);
|
|
const auto rv = _ksys_getcwd(buf, path::max_path - 1u);
|
|
return (rv == NULL) ? path{} : path{buf};
|
|
}
|
|
|
|
path absolute(path const& p)
|
|
{
|
|
return p; // TODO
|
|
}
|
|
|
|
void scan_directory (path const& directory, std::list<path>& paths)
|
|
{
|
|
static const auto scopedCloseDir = [](DIR* pdir)
|
|
{
|
|
closedir(pdir);
|
|
};
|
|
|
|
std::unique_ptr<DIR, decltype(scopedCloseDir)> pdir(opendir (directory.c_str()), scopedCloseDir);
|
|
dirent *pent = NULL;
|
|
|
|
while (pent = readdir (pdir.get()))
|
|
{
|
|
if (pent->d_name[0] == path::dot)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
path fileName(directory.c_str());
|
|
fileName /= pent->d_name;
|
|
|
|
if (is_directory(fileName))
|
|
{
|
|
scan_directory (fileName, paths);
|
|
}
|
|
else if (is_regular_file(fileName))
|
|
{
|
|
paths.emplace_back(std::move(fileName));
|
|
}
|
|
}
|
|
}
|
|
|
|
// pos is position of the separator
|
|
bool is_root_separator(string_type const& str, size_type root_dir_pos, size_type pos);
|
|
|
|
// Returns: Size of the filename element that ends at end_pos (which is past-the-end position). 0 if no filename found.
|
|
size_type find_filename_size(string_type const& str, size_type root_name_size, size_type end_pos);
|
|
|
|
// Returns: starting position of root directory or size if not found. Sets root_name_size to length
|
|
// of the root name if the characters before the returned position (if any) are considered a root name.
|
|
size_type find_root_directory_start(const value_type* path, size_type size, size_type& root_name_size);
|
|
|
|
// Finds position and size of the first element of the path
|
|
void first_element(string_type const& src, size_type& element_pos, size_type& element_size, size_type size);
|
|
|
|
// Finds position and size of the first element of the path
|
|
inline void first_element(string_type const& src, size_type& element_pos, size_type& element_size)
|
|
{
|
|
first_element(src, element_pos, element_size, src.size());
|
|
}
|
|
|
|
// Checks if the second string overlaps in memory with the first string
|
|
inline bool is_overlapping(string_type const& str, const value_type* arg)
|
|
{
|
|
std::less< const value_type* > ptr_less{};
|
|
return !(ptr_less(arg, str.data()) || ptr_less(str.data() + str.size(), arg));
|
|
}
|
|
|
|
inline size_type find_filename_size(string_type const& str, size_type root_name_size, size_type end_pos)
|
|
{
|
|
size_type pos = end_pos;
|
|
while (pos > root_name_size)
|
|
{
|
|
--pos;
|
|
|
|
if (path::is_directory_separator(str[pos]))
|
|
{
|
|
++pos; // filename starts past the separator
|
|
break;
|
|
}
|
|
}
|
|
|
|
return end_pos - pos;
|
|
}
|
|
|
|
} // namespace filesystem
|
|
} // namespace std
|