//----------------------------------------------------------------------------- // ___ __ _ _ // / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __ // / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ / // / ___/ (_| | | \__ \ __/ /__| | | | | < // \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ . // //----------------------------------------------------------------------------- // 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 #include #include #include #include #include #include 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 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(-*file))); } } inline tl::expected, std::error_code> read_some( handle file, std::size_t amount) noexcept { std::vector data; if (!file) { return tl::make_unexpected( std::make_error_code(static_cast(-*file))); } data.resize(amount); auto amt_read = ::read(*file, data.data(), amount); if (amt_read < data.size()) { data.resize(amt_read); } return data; } template requires(std::is_trivially_default_constructible_v && sizeof(T) == 1) inline tl::expected, std::error_code> read( handle file) noexcept { std::vector data; if (!file) { return tl::make_unexpected( std::make_error_code(static_cast(-*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