Skip to content

Commit

Permalink
Implement error handling (#8)
Browse files Browse the repository at this point in the history
- tmp::path constructor accepts an already created temp path
- tmp::file and tmp::directory create temp paths by themselves
  • Loading branch information
bugdea1er authored Jan 28, 2024
1 parent 125c7a6 commit a30be23
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 9 deletions.
14 changes: 13 additions & 1 deletion include/tmp/directory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class directory final : public path {
/// for temporary files. If a prefix is provided to the constructor, the
/// directory is created in the path <temp dir>/prefix/. The prefix can be
/// a path consisting of multiple segments.
explicit directory(std::string_view prefix = "") : path(prefix, mkdtemp) {}
explicit directory(std::string_view prefix = "") : path(create(prefix)) {}

/// Concatenates this directory path with a given @p source
std::filesystem::path operator/(std::string_view source) const {
Expand All @@ -58,6 +58,18 @@ class directory final : public path {
directory& operator=(directory&&) noexcept = default; ///< move-assignable
directory(const directory&) = delete; ///< not copy-constructible
auto operator=(const directory&) = delete; ///< not copy-assignable

private:
/// Creates a unique temporary directory based on the given @p prefix
static std::filesystem::path create(std::string_view prefix) {
auto pattern = make_pattern(prefix);
if (mkdtemp(pattern.data()) == nullptr) {
auto ec = std::error_code(errno, std::system_category());
throw error("Cannot create temporary directory", ec);
}

return pattern;
}
};

} // namespace tmp
13 changes: 12 additions & 1 deletion include/tmp/file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,20 @@ class file final : public path {
/// for temporary files. If a prefix is provided to the constructor, the
/// directory is created in the path <temp dir>/prefix/. The prefix can be
/// a path consisting of multiple segments.
explicit file(std::string_view prefix, bool binary) : path(prefix, mkstemp),
explicit file(std::string_view prefix, bool binary) : path(create(prefix)),
binary(binary) {}

/// Creates a unique temporary file based on the given @p prefix
static std::filesystem::path create(std::string_view prefix) {
auto pattern = make_pattern(prefix);
if (mkstemp(pattern.data()) == -1) {
auto ec = std::error_code(errno, std::system_category());
throw error("Cannot create temporary file", ec);
}

return pattern;
}

/// Returns a stream for this file
std::ofstream stream(bool append) const noexcept {
std::ios::openmode mode = append ? std::ios::app : std::ios::trunc;
Expand Down
19 changes: 12 additions & 7 deletions include/tmp/path.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,23 @@ class path {
}

protected:
/// Exception type that should be used by subclasses to signal errors
using error = std::filesystem::filesystem_error;

std::filesystem::path underlying; ///< This file path

/// Creates a unique temporary path using the given constructor function
template<typename C>
explicit path(std::string_view prefix, C constructor) {
/// Creates a unique temporary path using the given constructor function.
/// @param prefix the path between system temp
/// @param creator wrapped mktemp-like function that returns resulting path
explicit path(std::filesystem::path path) : underlying(std::move(path)) {}

/// Creates a pattern for the mktemp-like functions.
/// If @p prefix is not empty, it is appended to the tempdir
static std::string make_pattern(std::string_view prefix) {
const auto parent = std::filesystem::temp_directory_path() / prefix;
std::filesystem::create_directories(parent);

std::string arg = parent / "XXXXXX";
constructor(arg.data());

this->underlying = std::move(arg);
return parent / "XXXXXX";
}

private:
Expand Down

0 comments on commit a30be23

Please sign in to comment.