2#ifndef LIBSBX_FILESYSTEM_NATIVE_FILE_HPP_
3#define LIBSBX_FILESYSTEM_NATIVE_FILE_HPP_
10#include <system_error>
13#include <libsbx/utility/lockable.hpp>
15#include <libsbx/filesystem/file_base.hpp>
16#include <libsbx/filesystem/file_info.hpp>
18namespace sbx::filesystem {
20template<
typename Lockable>
25 using handle_type = std::FILE*;
26 using lockable_type = Lockable;
39 [[nodiscard]]
auto info()
const ->
const file_info&
override {
40 auto lock = std::scoped_lock{_mutex};
45 [[nodiscard]]
auto size()
const -> std::uint64_t
override {
46 auto lock = std::scoped_lock{_mutex};
52 auto ec = std::error_code{};
53 auto size = std::filesystem::file_size(_info.native_path(), ec);
55 return ec ? 0 :
static_cast<std::uint64_t
>(size);
58 [[nodiscard]]
auto is_read_only()
const ->
bool override {
59 auto lock = std::scoped_lock{_mutex};
61 return !file_base::mode_has_flag(_mode, mode::write);
65 auto open(mode mode) ->
bool override {
66 auto lock = std::scoped_lock{_mutex};
68 if (!file_base::is_mode_valid(mode)) {
72 if (_file && _mode == mode) {
73 std::fseek(_file, 0, SEEK_SET);
79 const auto is_read = file_base::mode_has_flag(mode, mode::read);
80 const auto is_write = file_base::mode_has_flag(mode, mode::write);
81 const auto is_append = file_base::mode_has_flag(mode, mode::append);
82 const auto is_truncate = file_base::mode_has_flag(mode, mode::truncate);
84 auto mode_string = std::string{};
86 if (is_read && !is_write) {
88 }
else if (is_write && !is_read) {
89 mode_string = is_append ?
"ab" : (is_truncate ?
"wb" :
"r+b");
90 }
else if (is_read && is_write) {
91 mode_string = is_append ?
"a+b" : (is_truncate ?
"w+b" :
"r+b");
96 _file = std::fopen(_info.native_path().c_str(), mode_string.c_str());
98 return _file !=
nullptr;
101 auto close() ->
void override {
102 auto lock = std::scoped_lock{_mutex};
111 [[nodiscard]]
auto is_open()
const ->
bool override {
112 auto lock = std::scoped_lock{_mutex};
114 return _file !=
nullptr;
117 auto seek(std::uint64_t offset, origin origin) -> std::uint64_t
override {
118 auto lock = std::scoped_lock{_mutex};
124 auto whence = SEEK_SET;
127 case origin::begin: {
141 if (std::fseek(_file,
static_cast<long>(offset), whence) != 0) {
145 const auto position = std::ftell(_file);
147 return (position != -1L) ?
static_cast<std::uint64_t
>(position) : 0;
150 [[nodiscard]]
auto tell()
const -> std::uint64_t
override {
151 auto lock = std::scoped_lock{_mutex};
157 const auto position = std::ftell(_file);
159 return (position != -1L) ?
static_cast<std::uint64_t
>(position) : 0;
162 auto read(std::span<std::uint8_t> buffer) -> std::uint64_t
override {
163 auto lock = std::scoped_lock{_mutex};
165 if (!_file || !file_base::mode_has_flag(_mode, mode::read)) {
169 const auto read_count = std::fread(buffer.data(), 1, buffer.size(), _file);
171 return static_cast<std::uint64_t
>(read_count);
174 auto read(std::vector<std::uint8_t>& buffer, std::uint64_t size) -> std::uint64_t
override {
176 return read(std::span<std::uint8_t>{buffer});
179 auto write(std::span<const std::uint8_t> buffer) -> std::uint64_t
override {
180 auto lock = std::scoped_lock{_mutex};
182 if (!_file || !file_base::mode_has_flag(_mode, mode::write)) {
186 if (buffer.empty()) {
190 const auto written = std::fwrite(buffer.data(), 1, buffer.size(), _file);
192 return static_cast<std::uint64_t
>(written);
195 auto write(
const std::vector<std::uint8_t>& buffer) -> std::uint64_t
override {
196 return write(std::span<const std::uint8_t>{buffer});
201 mutable lockable_type _mutex;
204 handle_type _file =
nullptr;
205 mode _mode = mode::read;
Definition: native_file.hpp:21
Definition: file_base.hpp:15
Definition: file_info.hpp:10