As a side-project, I'm trying to implement a distributed object storage. I've decided to use C++ and libuv, two technologies I had never played with, since it gave me a good reason to learn them.
For this project, I needed an abstraction over the filesystem. This was required in order to use libuv as a backend. This was also a good way to learn how C++11 behaves.
However, I'm alone on this project, and I'm trying to figure out whether I use templates, lvalues, rvalues, universal pointers etc. correctly. It's better to break the bad practices early.
Could I have a code review on it? I've linked the repository.
By the way, it's not completed. I still need to abstract file descriptors, stat structures and provide type-erased containers for them. I'm also very late on unit tests. However, I'd still like a code review on what has been done so far.
The two main interfaces are path and filesystem. I've put their definitions and the declaration of all implementations. In the future, I want to add an interface for stat, fd and buffer.
class path
{
public:
virtual ~path() noexcept
{};
virtual bool is_root() const noexcept = 0;
virtual bool is_absolute() const noexcept = 0;
virtual bool is_relative() const noexcept = 0;
virtual bool is_valid() const noexcept = 0;
virtual const std::string &str() const noexcept = 0;
virtual path &prepend(path &path) noexcept = 0;
virtual path &prepend(std::string &str) noexcept = 0;
virtual path &prepend(std::string &&str) noexcept = 0;
virtual path &append(path &path) noexcept = 0;
virtual path &append(std::string &str) noexcept = 0;
virtual path &append(std::string &&str) noexcept = 0;
virtual path &parent() noexcept = 0;
virtual path &filename() noexcept = 0;
};
template<typename t_path>
class base_path : public path;
class any_path : public base_path<any_path>;
class unix_path : public base_path<unix_path>;
template<typename t_path, typename t_stat, typename t_file, typename t_buffer>
class filesystem
{
public:
using exists_cb = std::function<
void(t_path &, int, bool)>;
using stat_cb = std::function<
void(t_path &, int, t_stat)>;
using mkdir_cb = std::function<
void(t_path &, int)>;
using mkdirs_cb = std::function<
void(t_path &, int)>;
using create_cb = std::function<
void(t_path &, int)>;
using move_cb = std::function<
void(t_path &, t_path &, int)>;
using copy_cb = std::function<
void(t_path &, t_path &, int)>;
using link_cb = std::function<
void(t_path &, t_path &, int)>;
using symlink_cb = std::function<
void(t_path &, t_path &, int)>;
using unlink_cb = std::function<
void(t_path &, int)>;
using open_cb = std::function<
void(t_path &, int, t_file &)>;
using fstat_cb = std::function<
void(t_file &, int, t_stat)>;
using read_cb = std::function<
void(t_file &, int, vfs::buffer &)>;
using write_cb = std::function<
void(t_file &, int, vfs::buffer &)>;
using truncate_cb = std::function<
void(t_file &, int, uint64_t)>;
using close_cb = std::function<
void(t_file &, int)>;
virtual ~filesystem() noexcept
{};
virtual int exists(t_path &&path, exists_cb cb) noexcept = 0;
virtual int stat(t_path &&path, stat_cb cb) noexcept = 0;
virtual int mkdir(t_path &&path, int32_t mode, mkdir_cb cb) noexcept = 0;
virtual int mkdirs(t_path &&path, int32_t mode, mkdirs_cb cb) noexcept = 0;
virtual int create(t_path &&path, int32_t mode, create_cb cb) noexcept = 0;
virtual int move(t_path &&path, t_path &&move_path, move_cb cb) noexcept = 0;
virtual int copy(t_path &&path, t_path &©_path, copy_cb cb) noexcept = 0;
virtual int link(t_path &&path, t_path &&other_path, link_cb cb) noexcept = 0;
virtual int symlink(t_path &&path, t_path &&other_path, symlink_cb cb) noexcept = 0;
virtual int unlink(t_path &&path, unlink_cb cb) noexcept = 0;
virtual int open(t_path &&path, int32_t mode, int32_t flags, open_cb cb) noexcept = 0;
virtual int stat(t_file &file, fstat_cb cb) noexcept = 0;
virtual int read(t_file &file, t_buffer &&buf, off64_t off, read_cb cb) noexcept = 0;
virtual int write(t_file &file, t_buffer &&buf, off64_t off, write_cb cb) noexcept = 0;
virtual int truncate(t_file &file, uint64_t size, off64_t off, truncate_cb cb) noexcept = 0;
virtual int close(t_file &file, close_cb cb) noexcept = 0;
};
class uv_filesystem : public filesystem<vfs::any_path, uv_stat_t, uv_file, uv_buf_t>;