#include #include #include #include namespace euler { //read-only with no error bits for now struct file_t { syscall::file_handle handle; //TODO: variable size buffer? maybe a multiple of block size for device? char buffer[1024]; //in bytes, aligned to buffer size; 1 for no buffer loaded uint64_t buffer_start; bool is_offset_in_buffer() { return buffer_start != 1 && offset >= buffer_start && offset < buffer_start + 1024; } syscall::file_result ensure_offset_in_buffer() { if (is_offset_in_buffer()) return syscall::file_result::success; uint64_t new_buffer_start = (offset / 1024) * 1024; uint64_t new_buffer_end = new_buffer_start + 1024; if (length < new_buffer_end) new_buffer_end = length; syscall::file_result result = _syscall_read_from_file( handle, new_buffer_start, new_buffer_end - new_buffer_start, buffer); if (result == syscall::file_result::success) buffer_start = new_buffer_start; return result; } uint64_t offset; uint64_t length; }; } namespace std { FILE *fopen(const char *path, const char *mode) { assert(mode[0] == 'r' && mode[1] == '\0'); euler::syscall::file_handle handle; euler::syscall::file_result result = _syscall_open_file(path, strlen(path), handle); if (result != euler::syscall::file_result::success) return 0; uint64_t length; result = _syscall_get_file_length(handle, length); if (result != euler::syscall::file_result::success) { _syscall_close_file(handle); return 0; } return new FILE { .handle = handle, .buffer = {}, .buffer_start = 1, .offset = 0, .length = length }; } int fclose(FILE *file) { _syscall_close_file(file->handle); delete file; return 0; } int fgetc(FILE *from) { if (from->offset >= from->length) return EOF; assert( from->ensure_offset_in_buffer() == euler::syscall::file_result::success); char ch = from->buffer[from->offset - from->buffer_start]; ++from->offset; return ch; } int ungetc(int ch, FILE *from) { if (ch == EOF || from->offset == 0) return EOF; --from->offset; if (!from->is_offset_in_buffer()) { ++from->offset; return EOF; } from->buffer[from->offset - from->buffer_start] = ch; return ch; } }