/* * libfud * Copyright 2024 Dominick Allen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FUD_FILE_HPP #define FUD_FILE_HPP #include "fud_option.hpp" #include "fud_permissions.hpp" #include "fud_result.hpp" #include "fud_status.hpp" #include "fud_string_view.hpp" #include "fud_vector.hpp" #include "fud_drain.hpp" #include namespace fud { /** \brief Access Modes for File */ enum class FileAccessMode : uint8_t { Read = 0x01, Write = 0x02, ReadWrite = Read | Write }; // enum class OpenFlagEnum : uint32_t enum class OpenFlagEnum : uint8_t { Append = 0x01, Truncate = Append << 1, CloseOnExec = Truncate << 1, DataSync = CloseOnExec << 1, Direct = DataSync << 1, NoAtime = Direct << 1, NonBlock = NoAtime << 1, FileSync = NonBlock << 1 }; class OpenFlags { public: using FlagType = std::underlying_type_t; constexpr OpenFlags() noexcept = default; constexpr OpenFlags(const OpenFlags& rhs) noexcept = default; constexpr OpenFlags(OpenFlags&& rhs) noexcept = default; constexpr ~OpenFlags() noexcept = default; constexpr OpenFlags& operator=(const OpenFlags& rhs) noexcept = default; constexpr OpenFlags& operator=(OpenFlags&& rhs) noexcept = default; constexpr OpenFlags(OpenFlagEnum mode) noexcept : m_mask{static_cast(mode)} { } constexpr OpenFlags operator|(OpenFlags rhs) const noexcept { OpenFlags mode{*this}; mode.m_mask |= rhs.m_mask; return mode; } constexpr OpenFlags& operator|=(OpenFlags rhs) noexcept { m_mask |= rhs.m_mask; return *this; } constexpr OpenFlags& operator|=(OpenFlagEnum rhs) noexcept { m_mask |= static_cast(rhs); return *this; } constexpr OpenFlags operator|(OpenFlagEnum rhs) const noexcept { OpenFlags mode{*this}; mode.m_mask |= static_cast(rhs); return mode; } constexpr uint32_t flags() const noexcept { uint32_t openFlags = 0; openFlags |= static_cast(hasFlag(OpenFlagEnum::Append)) * O_APPEND; openFlags |= static_cast(hasFlag(OpenFlagEnum::Truncate)) * O_TRUNC; openFlags |= static_cast(hasFlag(OpenFlagEnum::CloseOnExec)) * O_CLOEXEC; openFlags |= static_cast(hasFlag(OpenFlagEnum::DataSync)) * O_DSYNC; openFlags |= static_cast(hasFlag(OpenFlagEnum::Direct)) * O_DIRECT; openFlags |= static_cast(hasFlag(OpenFlagEnum::NoAtime)) * O_NOATIME; openFlags |= static_cast(hasFlag(OpenFlagEnum::NonBlock)) * O_NONBLOCK; openFlags |= static_cast(hasFlag(OpenFlagEnum::FileSync)) * O_SYNC; return openFlags; } constexpr bool hasFlag(OpenFlagEnum flag) const noexcept { return (m_mask & static_cast(flag)) != 0; } private: FlagType m_mask{0}; }; constexpr OpenFlags operator|(OpenFlagEnum lhs, OpenFlagEnum rhs) { OpenFlags mode{lhs}; return mode | rhs; } class RegularFile; using FileResult = Result; class RegularFile { public: static FileResult open( StringView filename, FileAccessMode mode, OpenFlags flags, Option dirFdoption); static FileResult create( StringView filename, FileAccessMode mode, OpenFlags flags, Permissions permissions, bool exclusive, Option dirFdOption); FudStatus close(); FudStatus take(RegularFile& rhs); Result size() const; private: RegularFile() = default; public: RegularFile(const RegularFile& rhs) = delete; RegularFile(RegularFile&& rhs) noexcept; ~RegularFile(); RegularFile& operator=(const RegularFile& rhs) = delete; RegularFile& operator=(RegularFile&& rhs) noexcept; private: int m_fd{-1}; OpenFlags m_openFlags{}; FileAccessMode m_modeFlags{}; }; enum class ReadPolicy { Unbuffered, ReadAhead, }; class BufferedRegularFile { public: /** \brief Write from source to file as sink. */ DrainResult write(const std::byte* source, size_t sourceSize, size_t length, size_t offset); /** \brief Read from file as source to sink. */ DrainResult read(std::byte* sink, size_t sinkSize, size_t length, size_t offset); private: Vector m_readBuffer{Vector::NullVector()}; Vector m_writeBuffer{Vector::NullVector()}; RegularFile m_file; bool m_readBuffered{false}; bool m_writeBuffered{false}; }; } // namespace fud #endif