From fbfc078e9f44c1c1e95c9c484f1d5650bcf631b7 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sat, 27 Jul 2024 16:57:39 -0400 Subject: lots and lots of userspace stuff --- euler/include/algorithm | 12 -- euler/include/cctype | 3 + euler/include/cstdio | 22 ++-- euler/include/cstring | 11 +- euler/include/euler/heap.hpp | 10 +- euler/include/euler/start_process.hpp | 30 ----- euler/include/euler/stream.hpp | 47 +++---- euler/include/euler/syscall.hpp | 234 +++++++++++++++++++--------------- euler/include/std/allocator.hpp | 30 +++++ euler/include/std/string.hpp | 80 ++++++++++++ euler/include/std/vector.hpp | 191 +++++++++++++++++++++++++++ euler/include/string | 13 ++ euler/include/type_traits | 23 ---- euler/include/utility | 12 -- euler/include/vector | 61 +-------- 15 files changed, 497 insertions(+), 282 deletions(-) delete mode 100644 euler/include/algorithm create mode 100644 euler/include/cctype delete mode 100644 euler/include/euler/start_process.hpp create mode 100644 euler/include/std/allocator.hpp create mode 100644 euler/include/std/string.hpp create mode 100644 euler/include/std/vector.hpp create mode 100644 euler/include/string delete mode 100644 euler/include/type_traits delete mode 100644 euler/include/utility (limited to 'euler/include') diff --git a/euler/include/algorithm b/euler/include/algorithm deleted file mode 100644 index 08702f9..0000000 --- a/euler/include/algorithm +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace std { - - template - void swap(t &a, t &b) { - t tmp = a; - a = b; - b = tmp; - } - -} diff --git a/euler/include/cctype b/euler/include/cctype new file mode 100644 index 0000000..2afc53d --- /dev/null +++ b/euler/include/cctype @@ -0,0 +1,3 @@ +#pragma once + +extern "C" int isspace(int ch); diff --git a/euler/include/cstdio b/euler/include/cstdio index 75472c1..0dc42d0 100644 --- a/euler/include/cstdio +++ b/euler/include/cstdio @@ -1,20 +1,16 @@ #pragma once #include -#include +#include -namespace std { +typedef euler::stream FILE; - typedef euler::stream FILE; +extern "C" FILE *fopen(const char *filename, const char *mode); +extern "C" void fclose(FILE *stream); - FILE *fopen(const char *filename, const char *mode); - int fclose(FILE *stream); +#define SEEK_CUR 2 +#define SEEK_END 1 +#define SEEK_SET 0 - int fseek(FILE *stream, long offset, int origin); - #define SEEK_SET 0 - #define SEEK_CUR 2 - #define SEEK_END 1 - - size_t fread(void *buffer, size_t size, size_t count, FILE *stream); - -} +extern "C" int fseek(FILE *stream, long offset, int origin); +extern "C" size_t fread(void *buffer, size_t size, size_t count, FILE *stream); diff --git a/euler/include/cstring b/euler/include/cstring index 45bc94e..cba5eb2 100644 --- a/euler/include/cstring +++ b/euler/include/cstring @@ -1,8 +1,9 @@ #pragma once -#include +#include -namespace std { - size_t strlen(const char *str); - void *memcpy(void *dest, const void *src, size_t count); -} +extern "C" void *memset(void *dest, int ch, size_t count); +extern "C" void *memcpy(void *dest, const void *src, size_t count); + +extern "C" int strcmp(const char *lhs, const char *rhs); +extern "C" size_t strlen(const char *str); diff --git a/euler/include/euler/heap.hpp b/euler/include/euler/heap.hpp index e2a4852..ce94eef 100644 --- a/euler/include/euler/heap.hpp +++ b/euler/include/euler/heap.hpp @@ -1,8 +1,10 @@ #pragma once -#include +#include + +namespace euler::heap { + + void *get_block(size_t length); + void return_block(void *start, size_t length); -namespace euler { - void *alloc(uint64_t bytes); - void dealloc(void *start, uint64_t bytes); } diff --git a/euler/include/euler/start_process.hpp b/euler/include/euler/start_process.hpp deleted file mode 100644 index 00ebbab..0000000 --- a/euler/include/euler/start_process.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -namespace euler { - - struct start_process { - - private: - const char *path; - uint64_t path_len; - std::vector<__euler_env_var_spec> env_var_specs; - std::vector<__euler_gift_stream_spec> gift_stream_specs; - - public: - //path needs to stay valid through any call to start - start_process(const char *path); - - //name and value need to stay valid through any call to start - void add_env_variable(const char *name, const char *value); - - void gift_stream( - __euler_stream_handle to_gifter, __euler_stream_handle to_giftee); - - __euler_stream_result start(__euler_process_handle &handle_out); - - }; - -} diff --git a/euler/include/euler/stream.hpp b/euler/include/euler/stream.hpp index a364ec4..741d863 100644 --- a/euler/include/euler/stream.hpp +++ b/euler/include/euler/stream.hpp @@ -7,41 +7,42 @@ namespace euler { class stream { public: - virtual ~stream(); - virtual bool try_read(void *into, uint64_t bytes) = 0; - virtual bool try_seek(__euler_seek_from from, int64_t offset) = 0; + virtual ~stream() {} - }; + virtual syscall::stream_result seek( + euler::syscall::seek_from from, int64_t offset) = 0; - class file_stream : public stream { + virtual std::pair + read(uint64_t bytes, void *into) = 0; - private: + virtual void close() = 0; - __euler_stream_handle handle; - bool is_readable; - bool is_writable; - uint64_t length; - uint64_t offset; + }; - uint8_t *buffer; - uint64_t buffer_offset; - uint64_t buffer_size; - bool buffer_dirty; + class file_stream : public stream { - void write_buffer(); + syscall::stream_handle handle; + bool may_read; - public: + bool buffer_loaded; + uint64_t buffer_start; + uint8_t buffer[1024]; - bool good; + uint64_t length; + uint64_t position; + public: file_stream( - __euler_stream_handle handle, bool is_readable, bool is_writable, - bool clear, bool seek_to_end); + syscall::stream_handle handle, bool may_read, + uint64_t length, uint64_t position); + + virtual syscall::stream_result seek( + syscall::seek_from from, int64_t offset) override; - ~file_stream(); + virtual std::pair + read(uint64_t bytes, void *into) override; - bool try_read(void *into, uint64_t bytes) override; - bool try_seek(__euler_seek_from from, int64_t offset) override; + virtual void close() override; }; diff --git a/euler/include/euler/syscall.hpp b/euler/include/euler/syscall.hpp index 981925f..64456ae 100644 --- a/euler/include/euler/syscall.hpp +++ b/euler/include/euler/syscall.hpp @@ -1,102 +1,136 @@ #pragma once -#include - -enum __euler_stream_result : uint64_t { - __EULER_SR_SUCCESS = 0, - __EULER_SR_BAD_HANDLE, - __EULER_SR_IO_ERROR, - __EULER_SR_OUT_OF_BOUNDS, - __EULER_SR_DOES_NOT_EXIST, - __EULER_SR_NOT_A_REGULAR_FILE, - __EULER_SR_NOT_AN_EXECUTABLE, - __EULER_SR_NOT_WRITABLE, - __EULER_SR_NOT_SEEKABLE, - __EULER_SR_SOCKET_ID_ALREADY_IN_USE, - __EULER_SR_SOCKET_ID_NOT_IN_USE, - __EULER_SR_SOCKET_LISTENER_CLOSED, - __EULER_SR_OTHER_END_CLOSED, - __EULER_SR_ALREADY_EXISTS, - __EULER_SR_NOT_SIZED -}; - -enum __euler_seek_from : uint8_t { - __EULER_SF_BEGINNING = 0, - __EULER_SF_END, - __EULER_SF_CURRENT_POSITION -}; - -typedef uint64_t __euler_stream_handle; -typedef uint64_t __euler_process_handle; - -extern "C" __euler_stream_result __euler_open_file( - const char *path, uint64_t path_len, __euler_stream_handle &handle_out, - bool allow_creation, bool only_allow_creation); - -extern "C" [[noreturn]] void __euler_end_this_thread(int32_t exit_code); - -extern "C" __euler_stream_result __euler_seek_stream( - __euler_stream_handle handle, __euler_seek_from from, int64_t offset); - -extern "C" __euler_stream_result __euler_set_stream_length( - __euler_stream_handle handle, uint64_t new_length); - -extern "C" void __euler_close_stream(__euler_stream_handle handle); - -extern "C" __euler_stream_result __euler_get_stream_length( - __euler_stream_handle handle, uint64_t &length_out); - -extern "C" void *__euler_get_new_pages(uint64_t count); - -extern "C" __euler_stream_result __euler_write_to_stream( - __euler_stream_handle handle, uint64_t count, const void *buffer); - -extern "C" __euler_stream_result __euler_read_from_stream( - __euler_stream_handle handle, uint64_t count, void *buffer); - -extern "C" uint32_t *__euler_get_framebuffer( - uint32_t &width_out, uint32_t &height_out, uint32_t &pitch_out); - -extern "C" uint32_t __euler_encode_color(uint8_t r, uint8_t g, uint8_t b); - -enum __euler_mouse_buttons : uint8_t { - __EULER_MB_LEFT = 1, - __EULER_MB_RIGHT = 2, - __EULER_MB_MIDDLE = 4 -}; - -enum __euler_input_packet_type : uint8_t { - __EULER_IPT_MOUSE = 1, - __EULER_IPT_KEYBOARD = 2 -}; - -extern "C" __euler_input_packet_type __euler_get_input_packet( - __euler_mouse_buttons &buttons_out, int16_t &x_change_out, - int16_t &y_change_out, uint32_t &keyboard_packet_out); - -struct [[gnu::packed]] __euler_env_var_spec { - uint64_t name_len; - const char *name; - uint64_t value_len; - const char *value; -}; - -struct [[gnu::packed]] __euler_gift_stream_spec { - __euler_stream_handle stream_handle_to_gifter; - __euler_stream_handle stream_handle_to_giftee; -}; - -struct [[gnu::packed]] __euler_process_start_info { - uint64_t file_path_length; - const char *file_path; - uint64_t env_var_count; - const __euler_env_var_spec *env_vars; - uint64_t gift_stream_count; - const __euler_gift_stream_spec *gift_streams; -}; - -extern "C" __euler_stream_result __euler_start_process( - const __euler_process_start_info &info, __euler_process_handle &handle_out); - -extern "C" __euler_stream_result __euler_get_other_end_process_handle( - __euler_stream_handle handle_in, __euler_process_handle &handle_out); +#include +#include +#include +#include +#include +#include + +namespace euler::syscall { + + enum class stream_result : uint64_t { + success, + bad_handle, + io_error, + out_of_bounds, + does_not_exist, + not_a_regular_file, + not_an_executable, + not_writable, + not_seekable, + socket_id_already_used, + socket_id_not_in_use, + socket_listener_closed, + other_end_closed, + already_exists, + not_sized, + not_readable + }; + + enum class seek_from : uint8_t { + beginning, + end, + current_position + }; + + struct mouse_packet { + bool left_button_down; + bool right_button_down; + bool middle_button_down; + int16_t x_changed; + int16_t y_changed; + }; + + struct key_packet { + bool was_key_up_event; + bool num_lock; + bool caps_lock; + bool right_win; + bool left_win; + bool right_alt; + bool left_alt; + bool right_ctrl; + bool left_ctrl; + bool right_shift; + bool left_shift; + uint8_t key_code; + }; + + typedef uint32_t encoded_color; + typedef uint64_t stream_handle; + typedef uint64_t listener_handle; + typedef uint64_t process_handle; + + encoded_color encode_color( + uint8_t r, uint8_t g, uint8_t b); + + void get_framebuffer( + encoded_color *&buffer_out, uint32_t &width_out, + uint32_t &height_out, uint32_t &pitch_out); + + stream_result open_file( + const std::string &file_path, bool allow_creation, + bool only_allow_creation, stream_handle &handle_out); + + [[noreturn]] void end_this_thread(int32_t exit_code); + + void *get_new_pages(uint64_t n_pages); + + std::variant get_input_packet(); + + void create_private_socket( + stream_handle &end_1_out, stream_handle &end_2_out); + + stream_result create_socket_listener( + const std::string &id, listener_handle &handle_out); + + void stop_socket_listener(listener_handle handle); + + stream_result accept_socket_connection( + listener_handle listener, stream_handle &stream_out); + + stream_result connect_to_socket( + const std::string &id, stream_handle &handle_out); + + void close_stream(stream_handle handle); + + stream_result seek_stream( + stream_handle handle, seek_from from, int64_t offset); + + stream_result read_from_stream( + stream_handle handle, uint64_t bytes, void *into); + + stream_result write_to_stream( + stream_handle handle, uint64_t bytes, const void *from); + + stream_result get_stream_length( + stream_handle handle, uint64_t &length_out); + + stream_result start_process( + const std::string &file_path, + const std::vector> &environment_variables, + const std::vector> &gifted_streams, + process_handle &handle_out); + + [[noreturn]] void end_this_process(int32_t exit_code); + + stream_result set_stream_length( + stream_handle handle, uint64_t new_length); + + stream_result get_other_end_process_handle( + stream_handle stream, process_handle &process_out); + + //entry_point must not return + void start_thread(void (*entry_point)(uint64_t), uint64_t arg); + + //entry_point must not return + void start_thread(void (*entry_point)()); + + //return value is number of bytes cleared + uint64_t clear_socket_read_queue(stream_handle handle); + + std::optional try_get_environment_variable( + const std::string &name); + +} diff --git a/euler/include/std/allocator.hpp b/euler/include/std/allocator.hpp new file mode 100644 index 0000000..32ba005 --- /dev/null +++ b/euler/include/std/allocator.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace std { + + template + struct allocator { + + using value_type = T; + + constexpr allocator() noexcept {} + constexpr allocator(const allocator &other) noexcept {} + + template + constexpr allocator(const allocator &other) noexcept {} + + constexpr ~allocator() {} + + constexpr T *allocate(size_t n) { + return (T *)euler::heap::get_block(n * sizeof(T)); + } + + constexpr void deallocate(T *p, size_t n) { + euler::heap::return_block(p, n * sizeof(T)); + } + + }; + +} diff --git a/euler/include/std/string.hpp b/euler/include/std/string.hpp new file mode 100644 index 0000000..7ccdbc2 --- /dev/null +++ b/euler/include/std/string.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + +namespace std { + + class string { + + std::vector characters; + + public: + constexpr string() : characters({'\0'}) {} + + constexpr string(const string &other) + : characters(other.characters) {} + + constexpr string(string &&other) noexcept + : characters(std::move(other.characters)) { + other.characters.push_back('\0'); + } + + constexpr string(const char *s) { + size_t count = 0; + while (s[count] != '\0') + ++count; + characters.resize(count + 1); + for (size_t i = 0; i <= count; ++i) + characters[i] = s[i]; + } + + constexpr ~string() {} + + constexpr string &operator =(const string &str) { + characters = str.characters; + return *this; + } + + constexpr string &operator =(string &&str) noexcept { + characters = std::move(str.characters); + str.characters.push_back('\0'); + return *this; + } + + constexpr size_t size() const noexcept { + return characters.size() - 1; + } + + constexpr void resize(size_t count) { + if (count < characters.size() - 1) { + characters.resize(count + 1); + characters[count] = '\0'; + } + else if (count > characters.size() - 1) + characters.resize(count + 1); + } + + constexpr void clear() noexcept { + resize(0); + } + + constexpr const char *data() const noexcept { + return characters.data(); + } + + constexpr char *data() noexcept { + return characters.data(); + } + + constexpr char &operator[](size_t pos) { + return characters[pos]; + } + + constexpr const char &operator[](size_t pos) const { + return characters[pos]; + } + + }; + +} diff --git a/euler/include/std/vector.hpp b/euler/include/std/vector.hpp new file mode 100644 index 0000000..a1ac21d --- /dev/null +++ b/euler/include/std/vector.hpp @@ -0,0 +1,191 @@ +#pragma once + +#include + +namespace std { + + template > + class vector { + + public: + using size_type = size_t; + using value_type = T; + using reference = value_type &; + using const_reference = const value_type &; + + private: + Allocator _alloc; + size_type _capacity; + size_type _size; + T *_data; + + constexpr void expand_capacity_to(size_type at_least) { + + size_type new_capacity = _capacity == 0 ? 1 : _capacity; + while (new_capacity < at_least) + new_capacity *= 2; + if (new_capacity == _capacity) + return; + + T *new_data = _alloc.allocate(new_capacity); + for (size_type i = 0; i < _size; ++i) { + std::construct_at(new_data + i, std::move(_data[i])); + std::destroy_at(_data + i); + } + if (_capacity > 0) + _alloc.deallocate(_data, _capacity); + + _capacity = new_capacity; + _data = new_data; + + } + + public: + constexpr vector() noexcept(noexcept(Allocator())) + : _alloc(), _capacity(0), _size(0), _data(0) {} + + constexpr vector(const vector &other) + : _alloc(), _capacity(other._size), _size(other._size), + _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i, other._data[i]); + } + + constexpr vector(vector &&other) noexcept + : _alloc(std::move(other._alloc)), _capacity(other._capacity), + _size(other._size), _data(other._data) { + other._capacity = 0; + other._size = 0; + } + + constexpr vector( + std::initializer_list init, const Allocator &alloc = Allocator()) + : _alloc(alloc), _capacity(init.size()), + _size(init.size()), _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i, init.begin()[i]); + } + + explicit vector(size_type count) + : _alloc(), _capacity(count), _size(count), + _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i); + } + + constexpr ~vector() { + if (_capacity > 0) { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _alloc.deallocate(_data, _capacity); + } + } + + constexpr vector &operator =(const vector &other) { + + if (&other == this) + return *this; + + expand_capacity_to(other._size); + + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + + for (size_type i = 0; i < other._size; ++i) { + std::construct_at(_data + i, std::move(other._data[i])); + std::destroy_at(other._data + i); + } + + _size = other._size; + return *this; + + } + + constexpr vector &operator =(vector &&other) + noexcept( + std::allocator_traits:: + propagate_on_container_move_assignment::value || + std::allocator_traits:: + is_always_equal::value) { + + if (&other == this) + return *this; + + if (_capacity > 0) { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _alloc.deallocate(_data, _capacity); + } + + _alloc = std::move(other._alloc); + _capacity = other._capacity; + _size = other._size; + _data = other._data; + + other._capacity = 0; + other._size = 0; + + return *this; + + } + + constexpr size_type size() const noexcept { + return _size; + } + + constexpr T *data() noexcept { + return _data; + } + + constexpr const T *data() const noexcept { + return _data; + } + + constexpr reference operator[](size_type pos) { + return _data[pos]; + } + + constexpr const_reference operator[](size_type pos) const { + return _data[pos]; + } + + constexpr reference back() { + return _data[_size - 1]; + } + + constexpr const_reference back() const { + return _data[_size - 1]; + } + + constexpr void resize(size_type count) { + + if (count < _size) { + for (size_type i = count; i < _size; ++i) + std::destroy_at(_data + i); + _size = count; + } + + else if (count > _size) { + expand_capacity_to(count); + for (size_type i = _size; i < count; ++i) + std::construct_at(_data + i); + _size = count; + } + + } + + constexpr void push_back(const T &value) { + expand_capacity_to(_size + 1); + std::construct_at(_data + _size, value); + ++_size; + } + + constexpr void push_back(T &&value) { + expand_capacity_to(_size + 1); + std::construct_at(_data + _size, std::move(value)); + ++_size; + } + + }; + +} diff --git a/euler/include/string b/euler/include/string new file mode 100644 index 0000000..ce42b9e --- /dev/null +++ b/euler/include/string @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace std { + + int stoi(const std::string &str, size_t *pos = 0, int base = 10); + + std::string to_string(int value); + + std::string operator +(std::string &&lhs, std::string &&rhs); + +} diff --git a/euler/include/type_traits b/euler/include/type_traits deleted file mode 100644 index fcea013..0000000 --- a/euler/include/type_traits +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -namespace std { - - template - struct remove_reference { - typedef t type; - }; - - template - struct remove_reference { - typedef t type; - }; - - template - struct remove_reference { - typedef t type; - }; - - template - using remove_reference_t = typename remove_reference::type; - -} diff --git a/euler/include/utility b/euler/include/utility deleted file mode 100644 index 23648c4..0000000 --- a/euler/include/utility +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -namespace std { - - template - constexpr std::remove_reference_t &&move(t &&x) { - return static_cast &&>(x); - } - -} diff --git a/euler/include/vector b/euler/include/vector index f5083ed..2184475 100644 --- a/euler/include/vector +++ b/euler/include/vector @@ -1,62 +1,3 @@ #pragma once -#include -#include - -namespace std { - - template - class vector { - - t *buffer; - size_t buffer_length;//always positive - size_t count; - - public: - vector() : buffer(new t[16]), buffer_length(16), count(0) {} - - ~vector() { - delete[] buffer; - } - - t &operator[](size_t pos) { - return buffer[pos]; - } - - const t &operator[](size_t pos) const { - return buffer[pos]; - } - - t *data() { - return buffer; - } - - const t *data() const { - return buffer; - } - - size_t size() const { - return count; - } - - void reserve(size_t new_length) { - if (new_length <= buffer_length) - return; - t *new_buffer = new t[new_length]; - for (size_t i = 0; i < count; ++i) - new_buffer[i] = std::move(buffer[i]); - delete[] buffer; - buffer = new_buffer; - buffer_length = new_length; - } - - void push_back(t &&value) { - if (count == buffer_length) - reserve(count * 2); - buffer[count++] = std::move(value); - } - - //TODO - }; - -} +#include -- cgit v1.2.3