summaryrefslogtreecommitdiff
path: root/libraries/euler/cstdio.cpp
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-01-20 17:59:40 -0500
committerBenji Dial <benji@benjidial.net>2024-01-20 17:59:40 -0500
commit7199e74aa22e592a3b77bdd81f735edca5470596 (patch)
tree66e935372acc5d6e013f764965f2a9d81814f809 /libraries/euler/cstdio.cpp
parent53135e2592c21cb9b2609bf95242aaf1f19233da (diff)
downloadhilbert-os-7199e74aa22e592a3b77bdd81f735edca5470596.tar.gz
update
Diffstat (limited to 'libraries/euler/cstdio.cpp')
-rw-r--r--libraries/euler/cstdio.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/libraries/euler/cstdio.cpp b/libraries/euler/cstdio.cpp
new file mode 100644
index 0000000..367e7e0
--- /dev/null
+++ b/libraries/euler/cstdio.cpp
@@ -0,0 +1,102 @@
+#include <euler/syscall.hpp>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
+
+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;
+ }
+
+}