-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
279 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#include "nth/io/writer/file.h" | ||
|
||
#include "nth/debug/debug.h" | ||
#include "nth/process/syscall/lseek.h" | ||
#include "nth/process/syscall/open.h" | ||
#include "nth/process/syscall/write.h" | ||
|
||
namespace nth::io { | ||
|
||
std::optional<file_writer> file_writer::try_open(file_path const &f, | ||
int flags) { | ||
int file_descriptor = nth::sys::open(f.path().c_str(), flags); | ||
if (file_descriptor > 0) { | ||
return file_writer(file_descriptor); | ||
} else { | ||
return std::nullopt; | ||
} | ||
} | ||
|
||
std::optional<file_writer::cursor_type> file_writer::allocate(size_t) { | ||
NTH_UNIMPLEMENTED("This action is not supported."); | ||
} | ||
|
||
file_writer::cursor_type file_writer::cursor() const { | ||
off_t result = nth::sys::lseek(file_descriptor_, 0, SEEK_CUR); | ||
NTH_REQUIRE((v.debug), result != off_t{-1}); | ||
return result; | ||
} | ||
|
||
bool file_writer::write(std::span<std::byte const> data) { | ||
if (data.empty()) { return true; } | ||
ssize_t result = nth::sys::write(file_descriptor_, data.data(), data.size()); | ||
return result != -1; | ||
} | ||
|
||
bool file_writer::write_at(cursor_type, std::span<std::byte const>) { | ||
NTH_UNIMPLEMENTED("This action is not supported."); | ||
} | ||
|
||
} // namespace nth::io |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#ifndef NTH_IO_WRITER_FILE_H | ||
#define NTH_IO_WRITER_FILE_H | ||
|
||
#include <fcntl.h> | ||
|
||
#include <optional> | ||
#include <span> | ||
|
||
#include "nth/io/file_path.h" | ||
#include "nth/io/writer/writer.h" | ||
|
||
namespace nth::io { | ||
|
||
// Writes data to a file referenced by the writer. | ||
struct file_writer { | ||
enum class flags : int { | ||
// If specified, the file will be created if it does not exist. If not | ||
// specified, `try_open` will return `std::nullopt` if the file does not | ||
// exist. | ||
create = O_CREAT, | ||
}; | ||
using enum flags; | ||
|
||
using cursor_type = ptrdiff_t; | ||
|
||
static std::optional<file_writer> try_open( | ||
file_path const &f, std::same_as<flags> auto... flags) { | ||
return try_open(f, (O_WRONLY | ... | static_cast<int>(flags))); | ||
} | ||
|
||
std::optional<cursor_type> allocate(size_t n); | ||
cursor_type cursor() const; | ||
|
||
bool write(std::span<std::byte const> data); | ||
|
||
bool write_at(cursor_type c, std::span<std::byte const> data); | ||
|
||
private: | ||
static std::optional<file_writer> try_open(file_path const &f, int flags); | ||
|
||
explicit file_writer(int file_descriptor) | ||
: file_descriptor_(file_descriptor) {} | ||
|
||
int file_descriptor_; | ||
}; | ||
|
||
} // namespace nth::io | ||
|
||
#endif // NTH_IO_WRITER_FILE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#include "nth/io/writer/file.h" | ||
|
||
#include <unistd.h> | ||
|
||
#include "nth/io/writer/test.h" | ||
#include "nth/process/syscall/lseek.h" | ||
#include "nth/process/syscall/open.h" | ||
#include "nth/process/syscall/write.h" | ||
#include "nth/test/test.h" | ||
|
||
NTH_FAKE_IMPLEMENTATION(int, nth::sys::open, (char const *, ptr)(int, n)); | ||
NTH_FAKE_IMPLEMENTATION(ssize_t, nth::sys::write, | ||
(int, fd)(void const *, ptr)(size_t, count)); | ||
NTH_FAKE_IMPLEMENTATION(off_t, nth::sys::lseek, | ||
(int, fd)(off_t, offset)(int, whence)); | ||
|
||
namespace nth::io { | ||
namespace { | ||
|
||
NTH_TEST("file_writer/open/succeed", | ||
std::same_as<file_writer::flags> auto... flags) { | ||
std::optional path = file_path::try_construct("file"); | ||
NTH_ASSERT(path.has_value()); | ||
auto handle = nth::test::fake<nth::sys::open>.with( | ||
+[](char const *, int) { return 17; }); | ||
std::optional r = file_writer::try_open(*path, flags...); | ||
NTH_ASSERT(r.has_value()); | ||
} | ||
|
||
NTH_TEST("file_writer/open/fails", | ||
std::same_as<file_writer::flags> auto... flags) { | ||
std::optional path = file_path::try_construct("file.txt"); | ||
NTH_ASSERT(path.has_value()); | ||
auto handle = nth::test::fake<nth::sys::open>.with( | ||
+[](char const *, int) { return -1; }); | ||
std::optional r = file_writer::try_open(*path, flags...); | ||
NTH_ASSERT(not r.has_value()); | ||
} | ||
|
||
NTH_INVOKE_TEST("file_writer/open/*") { | ||
// TODO: Test with no arguments. | ||
co_yield file_writer::create; | ||
} | ||
|
||
std::optional<file_writer> try_open(std::string_view name) { | ||
std::optional path = file_path::try_construct(name); | ||
if (not path.has_value()) { return std::nullopt; } | ||
return file_writer::try_open(*path); | ||
} | ||
|
||
NTH_TEST("file_writer/write/succeeds") { | ||
auto open_handle = nth::test::fake<nth::sys::open>.with( | ||
+[](char const *, int) { return 17; }); | ||
std::array<std::byte, 10> data = { | ||
std::byte{'a'}, std::byte{'b'}, std::byte{'c'}, std::byte{'d'}, | ||
std::byte{'e'}, std::byte{'f'}, std::byte{'g'}, std::byte{'h'}, | ||
std::byte{'i'}, std::byte{'j'}}; | ||
std::string content; | ||
auto write_handle = nth::test::fake<nth::sys::write>.with( | ||
[&](int, void const *ptr, size_t count) -> ssize_t { | ||
content.append(std::string_view(static_cast<char const *>(ptr), count)); | ||
return count; | ||
}); | ||
|
||
std::optional r = try_open("file.txt"); | ||
NTH_ASSERT(r.has_value()); | ||
NTH_ASSERT(r->write(data)); | ||
NTH_EXPECT(content == "abcdefghij"); | ||
} | ||
|
||
NTH_TEST("file_writer/write/empty") { | ||
auto open_handle = nth::test::fake<nth::sys::open>.with( | ||
+[](char const *, int) { return 17; }); | ||
auto write_handle = nth::test::fake<nth::sys::write>.with( | ||
+[](int, void const *, size_t) -> ssize_t { std::abort(); }); | ||
|
||
std::optional r = try_open("file.txt"); | ||
NTH_ASSERT(r.has_value()); | ||
|
||
std::array<std::byte, 0> data; | ||
NTH_EXPECT(r->write(data)); | ||
} | ||
|
||
NTH_TEST("file_writer/write/partial-write") { | ||
auto open_handle = nth::test::fake<nth::sys::open>.with( | ||
+[](char const *, int) { return 17; }); | ||
std::array<std::byte, 10> data{ | ||
std::byte{'a'}, | ||
std::byte{'b'}, | ||
std::byte{'c'}, | ||
std::byte{'d'}, | ||
}; | ||
std::string content; | ||
auto write_handle = nth::test::fake<nth::sys::write>.with( | ||
[&](int, void const *ptr, size_t) -> ssize_t { | ||
content.append(std::string_view(static_cast<char const *>(ptr), 4)); | ||
return 4; | ||
}); | ||
std::optional r = try_open("file.txt"); | ||
NTH_ASSERT(r.has_value()); | ||
NTH_ASSERT(r->write(data)); | ||
NTH_EXPECT(content == "abcd"); | ||
} | ||
|
||
NTH_TEST("file_writer/cursor/allocate") { | ||
// TODO: Implement | ||
// auto open_handle = nth::test::fake<nth::sys::open>.with( | ||
// +[](char const *, int) { return 17; }); | ||
// auto lseek_handle = nth::test::fake<nth::sys::lseek>.with( | ||
// [n = off_t{}](int, off_t offset, int) mutable -> off_t { | ||
// return std::exchange(n, n + offset); | ||
// }); | ||
|
||
// std::optional r = try_open("file.txt"); | ||
// NTH_ASSERT(r.has_value()); | ||
// NTH_EXPECT(r->cursor() == 0); | ||
// NTH_EXPECT(r->skip(4)); | ||
// NTH_EXPECT(r->cursor() == 4); | ||
// NTH_EXPECT(r->skip(2)); | ||
// NTH_EXPECT(r->cursor() == 6); | ||
} | ||
|
||
} // namespace | ||
} // namespace nth::io |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include "nth/process/syscall/write.h" | ||
|
||
#include <unistd.h> | ||
|
||
#include "nth/base/attributes.h" | ||
|
||
namespace nth::sys { | ||
|
||
NTH_REAL_IMPLEMENTATION(ssize_t, write, | ||
(int, fd)(void const*, ptr)(size_t, count)) { | ||
return ::write(fd, ptr, count); | ||
} | ||
|
||
} // namespace nth::sys | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#ifndef NTH_PROCESS_SYSCALL_WRITE_H | ||
#define NTH_PROCESS_SYSCALL_WRITE_H | ||
|
||
#include <sys/types.h> | ||
|
||
#include "nth/debug/fakeable_function.h" | ||
|
||
namespace nth::sys { | ||
|
||
NTH_FAKEABLE(ssize_t, write, (int, fd)(void const*, ptr)(size_t, count)); | ||
|
||
} // namespace nth::sys | ||
|
||
#endif // NTH_PROCESS_SYSCALL_WRITE_H |