134 lines
3.2 KiB
C++
134 lines
3.2 KiB
C++
//-----------------------------------------------------------------------------
|
|
// ___ __ _ _
|
|
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Author: Kurt Sassenrath
|
|
// Module: Utility
|
|
//
|
|
// Utility wrappers for dealing with files.
|
|
//
|
|
// Copyright (c) 2023 Kurt Sassenrath.
|
|
//
|
|
// License TBD.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef utility_file_8b49e5e471a7c3e5
|
|
#define utility_file_8b49e5e471a7c3e5
|
|
|
|
#include <fmt/format.h>
|
|
#include <tl/expected.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <fcntl.h>
|
|
#include <system_error>
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
|
|
namespace parselink {
|
|
namespace utility {
|
|
namespace file {
|
|
|
|
struct [[nodiscard]] handle {
|
|
constexpr handle() noexcept = default;
|
|
|
|
constexpr handle(int fd) noexcept
|
|
: fd_(fd) {
|
|
if (fd_ < 0) fd_ = -errno;
|
|
}
|
|
|
|
constexpr handle(handle const&) noexcept = delete;
|
|
|
|
constexpr handle(handle&& other) noexcept
|
|
: fd_(other.fd_) {
|
|
other.fd_ = -1;
|
|
}
|
|
|
|
constexpr handle& operator=(handle const&) noexcept = delete;
|
|
|
|
constexpr handle& operator=(handle&& other) noexcept {
|
|
close();
|
|
fd_ = other.fd_;
|
|
return *this;
|
|
}
|
|
|
|
constexpr operator bool() const noexcept { return fd_ >= 0; }
|
|
|
|
constexpr int operator*() const noexcept { return fd_; }
|
|
|
|
void close() {
|
|
if (*this) {
|
|
::close(fd_);
|
|
fd_ = -1;
|
|
}
|
|
}
|
|
|
|
int fd_{-1};
|
|
};
|
|
|
|
inline tl::expected<handle, std::error_code> open(
|
|
std::string_view path, int flags) noexcept {
|
|
handle file(::open(std::string{path}.c_str(), flags));
|
|
if (file) {
|
|
return file;
|
|
} else {
|
|
return tl::make_unexpected(
|
|
std::make_error_code(static_cast<std::errc>(-*file)));
|
|
}
|
|
}
|
|
|
|
inline tl::expected<std::vector<std::byte>, std::error_code> read_some(
|
|
handle file, std::size_t amount) noexcept {
|
|
std::vector<std::byte> data;
|
|
|
|
if (!file) {
|
|
return tl::make_unexpected(
|
|
std::make_error_code(static_cast<std::errc>(-*file)));
|
|
}
|
|
|
|
data.resize(amount);
|
|
|
|
auto amt_read = ::read(*file, data.data(), amount);
|
|
|
|
if (amt_read < data.size()) {
|
|
data.resize(amt_read);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
template <typename T>
|
|
requires(std::is_trivially_default_constructible_v<T> && sizeof(T) == 1)
|
|
inline tl::expected<std::vector<T>, std::error_code> read(
|
|
handle file) noexcept {
|
|
std::vector<T> data;
|
|
|
|
if (!file) {
|
|
return tl::make_unexpected(
|
|
std::make_error_code(static_cast<std::errc>(-*file)));
|
|
}
|
|
|
|
auto cur = lseek(*file, 0, SEEK_CUR);
|
|
auto end = lseek(*file, 0, SEEK_END);
|
|
std::size_t amount = end - cur;
|
|
lseek(*file, SEEK_SET, cur);
|
|
data.resize(amount);
|
|
|
|
auto amt_read = ::read(*file, data.data(), amount);
|
|
|
|
if (amt_read < data.size()) {
|
|
data.resize(amt_read);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
} // namespace file
|
|
} // namespace utility
|
|
} // namespace parselink
|
|
|
|
#endif // utility_file_8b49e5e471a7c3e5
|