libos: Make os::File a wrapper around stdio's FILE
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This way, os::File benefits from the same buffering as stdio.h does.
This commit is contained in:
parent
358493a7bc
commit
eeb9e16a74
@ -14,6 +14,7 @@
|
|||||||
#include <luna/SharedPtr.h>
|
#include <luna/SharedPtr.h>
|
||||||
#include <luna/StringView.h>
|
#include <luna/StringView.h>
|
||||||
#include <os/Path.h>
|
#include <os/Path.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
@ -164,9 +165,14 @@ namespace os
|
|||||||
*/
|
*/
|
||||||
int fd() const
|
int fd() const
|
||||||
{
|
{
|
||||||
return m_fd;
|
return fileno(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flushes the stream's buffers.
|
||||||
|
*/
|
||||||
|
void flush();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Move this File's file pointer back to the beginning.
|
* @brief Move this File's file pointer back to the beginning.
|
||||||
*/
|
*/
|
||||||
@ -182,7 +188,7 @@ namespace os
|
|||||||
Result<usize> raw_read(u8* buf, usize length);
|
Result<usize> raw_read(u8* buf, usize length);
|
||||||
Result<usize> raw_write(const u8* buf, usize length);
|
Result<usize> raw_write(const u8* buf, usize length);
|
||||||
|
|
||||||
int m_fd { -1 };
|
FILE* m_file { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <luna/StringBuilder.h>
|
#include <luna/StringBuilder.h>
|
||||||
#include <os/File.h>
|
#include <os/File.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -16,6 +17,21 @@ static SharedPtr<os::File> g_stdin = {};
|
|||||||
static SharedPtr<os::File> g_stdout = {};
|
static SharedPtr<os::File> g_stdout = {};
|
||||||
static SharedPtr<os::File> g_stderr = {};
|
static SharedPtr<os::File> g_stderr = {};
|
||||||
|
|
||||||
|
static const char* stdio_mode_from_openmode(int mode)
|
||||||
|
{
|
||||||
|
mode &= ~(O_CREAT | O_EXCL);
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case os::File::ReadOnly: return "r";
|
||||||
|
case os::File::ReadWrite: return "w+";
|
||||||
|
case os::File::WriteOnly: return "w";
|
||||||
|
case os::File::ReadAppend: return "a+";
|
||||||
|
case os::File::Append: return "a";
|
||||||
|
default: fail("Mode incompatible with fdopen()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace os
|
namespace os
|
||||||
{
|
{
|
||||||
File::File(Badge<File>)
|
File::File(Badge<File>)
|
||||||
@ -24,22 +40,22 @@ namespace os
|
|||||||
|
|
||||||
File::~File()
|
File::~File()
|
||||||
{
|
{
|
||||||
if (m_fd >= 0) close(m_fd);
|
if (m_file) fclose(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::initialize_standard_streams()
|
void File::initialize_standard_streams()
|
||||||
{
|
{
|
||||||
g_stdin = adopt_shared_if_nonnull(new (std::nothrow) File({}))
|
g_stdin = adopt_shared_if_nonnull(new (std::nothrow) File({}))
|
||||||
.expect_release_value("Cannot open standard input stream");
|
.expect_release_value("Cannot open standard input stream");
|
||||||
g_stdin->m_fd = STDIN_FILENO;
|
g_stdin->m_file = stdin;
|
||||||
|
|
||||||
g_stdout = adopt_shared_if_nonnull(new (std::nothrow) File({}))
|
g_stdout = adopt_shared_if_nonnull(new (std::nothrow) File({}))
|
||||||
.expect_release_value("Cannot open standard output stream");
|
.expect_release_value("Cannot open standard output stream");
|
||||||
g_stdout->m_fd = STDOUT_FILENO;
|
g_stdout->m_file = stdout;
|
||||||
|
|
||||||
g_stderr = adopt_shared_if_nonnull(new (std::nothrow) File({}))
|
g_stderr = adopt_shared_if_nonnull(new (std::nothrow) File({}))
|
||||||
.expect_release_value("Cannot open standard error stream");
|
.expect_release_value("Cannot open standard error stream");
|
||||||
g_stderr->m_fd = STDERR_FILENO;
|
g_stderr->m_file = stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<File> File::standard_input()
|
SharedPtr<File> File::standard_input()
|
||||||
@ -70,7 +86,8 @@ namespace os
|
|||||||
long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode);
|
long rc = syscall(SYS_openat, path.dirfd(), path.name().chars(), flags, mode);
|
||||||
int fd = TRY(Result<int>::from_syscall(rc));
|
int fd = TRY(Result<int>::from_syscall(rc));
|
||||||
|
|
||||||
file->m_fd = fd;
|
file->m_file = fdopen(fd, stdio_mode_from_openmode(flags));
|
||||||
|
if (!file->m_file) return err(errno);
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@ -99,14 +116,16 @@ namespace os
|
|||||||
|
|
||||||
Result<usize> File::raw_read(u8* buf, usize length)
|
Result<usize> File::raw_read(u8* buf, usize length)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_read, m_fd, buf, length);
|
size_t nread = fread(buf, 1, length, m_file);
|
||||||
return Result<usize>::from_syscall(rc);
|
if (nread == 0 && ferror(m_file)) return err(errno);
|
||||||
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<usize> File::raw_write(const u8* buf, usize length)
|
Result<usize> File::raw_write(const u8* buf, usize length)
|
||||||
{
|
{
|
||||||
long rc = syscall(SYS_write, m_fd, buf, length);
|
size_t nwrite = fwrite(buf, 1, length, m_file);
|
||||||
return Result<usize>::from_syscall(rc);
|
if (nwrite == 0 && ferror(m_file)) return err(errno);
|
||||||
|
return nwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> File::write(StringView str)
|
Result<void> File::write(StringView str)
|
||||||
@ -130,7 +149,7 @@ namespace os
|
|||||||
int current;
|
int current;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
current = TRY(getchar());
|
current = fgetc(m_file);
|
||||||
|
|
||||||
if (current == -1) break;
|
if (current == -1) break;
|
||||||
|
|
||||||
@ -189,29 +208,31 @@ namespace os
|
|||||||
|
|
||||||
Result<int> File::getchar()
|
Result<int> File::getchar()
|
||||||
{
|
{
|
||||||
u8 value;
|
return fgetc(m_file);
|
||||||
|
|
||||||
usize nread = TRY(raw_read(&value, 1));
|
|
||||||
if (!nread) return -1;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::set_close_on_exec()
|
void File::set_close_on_exec()
|
||||||
{
|
{
|
||||||
fcntl(m_fd, F_SETFD, FD_CLOEXEC);
|
fcntl(fd(), F_SETFD, FD_CLOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::rewind()
|
void File::rewind()
|
||||||
{
|
{
|
||||||
lseek(m_fd, 0, SEEK_SET);
|
::rewind(m_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void File::flush()
|
||||||
|
{
|
||||||
|
fflush(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Do not allocate memory for printing.
|
// FIXME: Do not allocate memory for printing.
|
||||||
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
|
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
|
||||||
{
|
{
|
||||||
auto str = TRY(String::vformat(fmt, ap));
|
auto str = TRY(String::vformat(fmt, ap));
|
||||||
return f->write(str.view());
|
auto rc = f->write(str.view());
|
||||||
|
f->flush();
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> print(StringView fmt, ...)
|
Result<void> print(StringView fmt, ...)
|
||||||
|
Loading…
Reference in New Issue
Block a user