2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @file File.h
|
|
|
|
* @author apio (cloudapio.eu)
|
|
|
|
* @brief A C++-friendly API for file access.
|
|
|
|
*
|
|
|
|
* @copyright Copyright (c) 2023, the Luna authors.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2023-04-12 19:46:10 +00:00
|
|
|
#pragma once
|
2023-06-09 20:45:06 +00:00
|
|
|
#include <fcntl.h>
|
2024-03-29 13:41:45 +00:00
|
|
|
#include <luna/Attributes.h>
|
2023-04-12 19:46:10 +00:00
|
|
|
#include <luna/Buffer.h>
|
|
|
|
#include <luna/Result.h>
|
|
|
|
#include <luna/SharedPtr.h>
|
|
|
|
#include <luna/StringView.h>
|
2023-05-03 15:37:26 +00:00
|
|
|
#include <os/Path.h>
|
2023-07-22 10:40:02 +00:00
|
|
|
#include <stdio.h>
|
2023-04-12 19:46:10 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
namespace os
|
|
|
|
{
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief An object-oriented file handle, which is closed when all references to it go out of scope.
|
|
|
|
*/
|
2023-07-30 09:32:46 +00:00
|
|
|
class File : public Shareable
|
2023-04-12 19:46:10 +00:00
|
|
|
{
|
|
|
|
public:
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief The supported file opening modes.
|
|
|
|
*/
|
2023-04-12 19:46:10 +00:00
|
|
|
enum OpenMode
|
|
|
|
{
|
2023-06-09 20:45:06 +00:00
|
|
|
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.
|
2023-04-12 19:46:10 +00:00
|
|
|
};
|
|
|
|
|
2023-10-24 18:02:09 +00:00
|
|
|
enum class SeekMode
|
|
|
|
{
|
|
|
|
Beginning = SEEK_SET, // Seek from the beginning of the file.
|
|
|
|
Current = SEEK_CUR, // Seek from the current file position.
|
|
|
|
End = SEEK_END, // Seek from the end of the file.
|
|
|
|
};
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-05-03 15:37:26 +00:00
|
|
|
static Result<SharedPtr<File>> open(const Path& path, OpenMode flags);
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-05-03 15:37:26 +00:00
|
|
|
static Result<SharedPtr<File>> open_or_create(const Path& path, OpenMode flags, mode_t mode = 0644);
|
2023-04-12 19:46:10 +00:00
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @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);
|
2023-04-26 18:41:03 +00:00
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @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 "-".
|
|
|
|
*/
|
2023-04-26 18:41:03 +00:00
|
|
|
static Result<SharedPtr<File>> open_input_file(StringView path);
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Returns the File corresponding to standard input.
|
|
|
|
*
|
|
|
|
* @return SharedPtr<File> The File object for standard input.
|
|
|
|
*/
|
2023-04-13 15:31:21 +00:00
|
|
|
static SharedPtr<File> standard_input();
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns the File corresponding to standard output.
|
|
|
|
*
|
|
|
|
* @return SharedPtr<File> The File object for standard output.
|
|
|
|
*/
|
2023-04-13 15:31:21 +00:00
|
|
|
static SharedPtr<File> standard_output();
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns the File corresponding to standard error.
|
|
|
|
*
|
|
|
|
* @return SharedPtr<File> The File object for standard error.
|
|
|
|
*/
|
2023-04-13 15:31:21 +00:00
|
|
|
static SharedPtr<File> standard_error();
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
2023-06-09 21:35:23 +00:00
|
|
|
* @brief Make this File object automatically close on the next call to execve(2).
|
2023-06-09 20:45:06 +00:00
|
|
|
*/
|
2023-04-12 19:46:10 +00:00
|
|
|
void set_close_on_exec();
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Write a string to this File.
|
|
|
|
*
|
2024-03-29 13:25:14 +00:00
|
|
|
* @param str The string to write (doesn't have to be null-terminated).
|
2023-06-09 20:45:06 +00:00
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
2023-04-12 19:46:10 +00:00
|
|
|
Result<void> write(StringView str);
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Write a memory buffer to this File.
|
|
|
|
*
|
|
|
|
* @param buf The buffer to write.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
2023-04-18 14:41:17 +00:00
|
|
|
Result<void> write(const Buffer& buf);
|
2023-04-12 19:46:10 +00:00
|
|
|
|
2024-03-29 13:41:45 +00:00
|
|
|
/**
|
|
|
|
* @brief Write a formatted string to this File.
|
|
|
|
*
|
|
|
|
* @param format The format string.
|
|
|
|
* @param ... The format arguments.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
|
|
|
Result<usize> write_formatted(const char* format, ...) _format(2, 3);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Write a formatted string to this File.
|
|
|
|
*
|
|
|
|
* @param format The format string.
|
|
|
|
* @param args The format arguments.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
|
|
|
Result<usize> write_vformatted(const char* format, va_list args);
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-04-22 13:21:04 +00:00
|
|
|
Result<String> read_line();
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Read the entire File's contents as a string.
|
|
|
|
*
|
|
|
|
* @return Result<String> The file's contents as an owned String object.
|
|
|
|
*/
|
2023-04-26 18:34:09 +00:00
|
|
|
Result<String> read_all_as_string();
|
2023-04-13 15:31:21 +00:00
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-04-18 14:41:17 +00:00
|
|
|
Result<void> read(Buffer& buf, usize size);
|
2023-06-09 20:45:06 +00:00
|
|
|
|
2023-08-02 09:54:47 +00:00
|
|
|
/**
|
|
|
|
* @brief Read an object from this File.
|
|
|
|
*
|
|
|
|
* @tparam T The type of the object to read.
|
|
|
|
* @param object A reference to the object in question.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
|
|
|
template <typename T> Result<void> read_typed(T& object)
|
|
|
|
{
|
|
|
|
TRY(raw_read((u8*)&object, sizeof(T)));
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Read the entire File's contents.
|
|
|
|
*
|
|
|
|
* @return Result<Buffer> The file's contents as an owned Buffer object.
|
|
|
|
*/
|
2023-04-26 18:34:09 +00:00
|
|
|
Result<Buffer> read_all();
|
2023-04-18 14:41:17 +00:00
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2023-04-13 15:31:21 +00:00
|
|
|
Result<int> getchar();
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Returns the file descriptor associated with this File.
|
|
|
|
*
|
|
|
|
* @return int The file descriptor.
|
|
|
|
*/
|
2023-04-25 19:00:12 +00:00
|
|
|
int fd() const
|
|
|
|
{
|
2023-07-22 10:40:02 +00:00
|
|
|
return fileno(m_file);
|
2023-04-25 19:00:12 +00:00
|
|
|
}
|
|
|
|
|
2023-07-22 10:40:02 +00:00
|
|
|
/**
|
|
|
|
* @brief Flushes the stream's buffers.
|
|
|
|
*/
|
|
|
|
void flush();
|
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Move this File's file pointer back to the beginning.
|
|
|
|
*/
|
|
|
|
void rewind();
|
|
|
|
|
2023-10-24 18:02:09 +00:00
|
|
|
/**
|
|
|
|
* @brief Change the file pointer's position.
|
|
|
|
*
|
|
|
|
* @param offset The number of bytes to move the file pointer (can be negative, to move backwards).
|
|
|
|
* @param mode Where to seek from.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
|
|
|
Result<void> seek(off_t offset, SeekMode mode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Read the file pointer's current position.
|
|
|
|
*
|
|
|
|
* @return Result<off_t> An error, or the file pointer's position.
|
|
|
|
*/
|
|
|
|
Result<off_t> tell();
|
|
|
|
|
2023-08-02 11:15:51 +00:00
|
|
|
/**
|
|
|
|
* @brief Buffering modes for a File.
|
|
|
|
*/
|
2023-08-02 09:54:47 +00:00
|
|
|
enum BufferingMode
|
|
|
|
{
|
|
|
|
NotBuffered = _IONBF,
|
|
|
|
LineBuffered = _IOLBF,
|
|
|
|
FullyBuffered = _IOFBF,
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Change the buffering mode of this File.
|
|
|
|
*
|
|
|
|
* @param mode The buffering mode.
|
|
|
|
*/
|
|
|
|
void set_buffer(BufferingMode mode);
|
|
|
|
|
2023-04-12 19:46:10 +00:00
|
|
|
File(Badge<File>);
|
|
|
|
~File();
|
|
|
|
|
|
|
|
private:
|
2023-05-03 15:37:26 +00:00
|
|
|
static Result<SharedPtr<File>> construct(const Path& path, int flags, mode_t mode);
|
2023-04-13 15:31:21 +00:00
|
|
|
static void initialize_standard_streams();
|
2023-04-12 19:46:10 +00:00
|
|
|
|
|
|
|
Result<usize> raw_read(u8* buf, usize length);
|
|
|
|
Result<usize> raw_write(const u8* buf, usize length);
|
|
|
|
|
2023-07-22 10:40:02 +00:00
|
|
|
FILE* m_file { nullptr };
|
2023-04-12 19:46:10 +00:00
|
|
|
};
|
2023-05-01 17:31:15 +00:00
|
|
|
|
2023-06-09 20:45:06 +00:00
|
|
|
/**
|
|
|
|
* @brief Print a formatted string to standard output.
|
|
|
|
*
|
2024-03-29 13:41:45 +00:00
|
|
|
* @param format The format string (in the same format as printf(3)).
|
2023-06-09 20:45:06 +00:00
|
|
|
* @param ... The format arguments.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
2024-03-29 13:41:45 +00:00
|
|
|
Result<void> print(const char* format, ...) _format(1, 2);
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Print a newline-terminated formatted string to standard output.
|
|
|
|
*
|
2024-03-29 13:41:45 +00:00
|
|
|
* @param format The format string (in the same format as printf(3)).
|
2023-06-09 20:45:06 +00:00
|
|
|
* @param ... The format arguments.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
2024-03-29 13:41:45 +00:00
|
|
|
Result<void> println(const char* format, ...) _format(1, 2);
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Print a formatted string to standard error.
|
|
|
|
*
|
2024-03-29 13:41:45 +00:00
|
|
|
* @param format The format string (in the same format as printf(3)).
|
2023-06-09 20:45:06 +00:00
|
|
|
* @param ... The format arguments.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
2024-03-29 13:41:45 +00:00
|
|
|
Result<void> eprint(const char* format, ...) _format(1, 2);
|
2023-06-09 20:45:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Print a newline-terminated formatted string to standard error.
|
|
|
|
*
|
2024-03-29 13:41:45 +00:00
|
|
|
* @param format The format string (in the same format as printf(3)).
|
2023-06-09 20:45:06 +00:00
|
|
|
* @param ... The format arguments.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
|
|
|
*/
|
2024-03-29 13:41:45 +00:00
|
|
|
Result<void> eprintln(const char* format, ...) _format(1, 2);
|
2023-04-12 19:46:10 +00:00
|
|
|
}
|