Luna/libos/include/os/File.h

224 lines
7.4 KiB
C
Raw Normal View History

/**
* @file File.h
* @author apio (cloudapio.eu)
* @brief A C++-friendly API for file access.
*
* @copyright Copyright (c) 2023, the Luna authors.
*
*/
#pragma once
#include <fcntl.h>
#include <luna/Buffer.h>
#include <luna/Result.h>
#include <luna/SharedPtr.h>
#include <luna/StringView.h>
#include <os/Path.h>
#include <sys/types.h>
namespace os
{
/**
* @brief An object-oriented file handle, which is closed when all references to it go out of scope.
*/
class File
{
public:
/**
* @brief The supported file opening modes.
*/
enum OpenMode
{
ReadOnly = O_RDONLY, // Open the file read-only.
WriteOnly = O_WRONLY | O_TRUNC, // Open the file write-only, truncating it.
ReadWrite = O_RDWR | O_TRUNC, // Open the file read-write, truncating it.
Append = O_WRONLY | O_APPEND, // Open the file write-only, and append to it.
ReadAppend = O_RDWR | O_APPEND, // Open the file read-write, and append to it.
};
/**
* @brief Create a new File object from a file path, opening the file.
*
* @param path The path to open.
* @param flags The opening mode to pass to open(2).
* @return Result<SharedPtr<File>> A new File object, or ENOENT if the file did not exist.
*/
static Result<SharedPtr<File>> open(const Path& path, OpenMode flags);
/**
* @brief Create a new File object from a file path, opening the file or creating it if it does not exist.
*
* @param path The path to open.
* @param flags The opening mode to pass to open(2).
* @param mode If a new file is created, the file permissions to apply to it. (default: u=rw,g=r,o=r)
* @return Result<SharedPtr<File>> A new File object.
*/
static Result<SharedPtr<File>> open_or_create(const Path& path, OpenMode flags, mode_t mode = 0644);
/**
* @brief Create a new File object from a file path, creating the file but erroring out if the file already
* exists.
*
* @param path The path to open.
* @param flags The opening mode to pass to open(2).
* @param mode The file permissions to apply to the created file. (default: u=rw,g=r,o=r)
* @return Result<SharedPtr<File>> A new File object, or EEXIST if the file already existed.
*/
static Result<SharedPtr<File>> create(const Path& path, OpenMode flags, mode_t mode = 0644);
/**
* @brief If path is "-", return standard input (as is common for many CLI apps). Otherwise, open path for
* reading.
*
* @param path The path to open.
* @return Result<SharedPtr<File>> A new File object if path was not "-", or the File
* object for standard input if path was "-".
*/
static Result<SharedPtr<File>> open_input_file(StringView path);
/**
* @brief Returns the File corresponding to standard input.
*
* @return SharedPtr<File> The File object for standard input.
*/
static SharedPtr<File> standard_input();
/**
* @brief Returns the File corresponding to standard output.
*
* @return SharedPtr<File> The File object for standard output.
*/
static SharedPtr<File> standard_output();
/**
* @brief Returns the File corresponding to standard error.
*
* @return SharedPtr<File> The File object for standard error.
*/
static SharedPtr<File> standard_error();
/**
* @brief Make this File object automatically close on the next call to execve(3).
*/
void set_close_on_exec();
/**
* @brief Write a string to this File.
*
* @param str The string to write (can be not null-terminated).
* @return Result<void> Whether the operation succeeded.
*/
Result<void> write(StringView str);
/**
* @brief Write a memory buffer to this File.
*
* @param buf The buffer to write.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> write(const Buffer& buf);
/**
* @brief Read a line from this File.
*
* @return Result<String> The line as an owned String object, or an empty string if there is no more
* data to read.
*/
Result<String> read_line();
/**
* @brief Read the entire File's contents as a string.
*
* @return Result<String> The file's contents as an owned String object.
*/
Result<String> read_all_as_string();
/**
* @brief Read data from this File.
*
* @param buf The output buffer to store the data in. Will be resized to fit the data.
* @param size The maximum number of bytes to read.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> read(Buffer& buf, usize size);
/**
* @brief Read the entire File's contents.
*
* @return Result<Buffer> The file's contents as an owned Buffer object.
*/
Result<Buffer> read_all();
/**
* @brief Read a single character from the File.
*
* @return Result<int> A character value above 0 (to be cast to an unsigned char), or EOF (typically -1)
* if there is no more data to read.
*/
Result<int> getchar();
/**
* @brief Returns the file descriptor associated with this File.
*
* @return int The file descriptor.
*/
int fd() const
{
return m_fd;
}
/**
* @brief Move this File's file pointer back to the beginning.
*/
void rewind();
File(Badge<File>);
~File();
private:
static Result<SharedPtr<File>> construct(const Path& path, int flags, mode_t mode);
static void initialize_standard_streams();
Result<usize> raw_read(u8* buf, usize length);
Result<usize> raw_write(const u8* buf, usize length);
int m_fd { -1 };
};
/**
* @brief Print a formatted string to standard output.
*
* @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> print(StringView fmt, ...);
/**
* @brief Print a newline-terminated formatted string to standard output.
*
* @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> println(StringView fmt, ...);
/**
* @brief Print a formatted string to standard error.
*
* @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> eprint(StringView fmt, ...);
/**
* @brief Print a newline-terminated formatted string to standard error.
*
* @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> eprintln(StringView fmt, ...);
}