Browse Source

feat: list container

greatbridf 3 years ago
parent
commit
20c4330c5b
2 changed files with 285 additions and 0 deletions
  1. 4 0
      CMakeLists.txt
  2. 281 0
      include/types/list.hpp

+ 4 - 0
CMakeLists.txt

@@ -24,11 +24,14 @@ add_custom_command(OUTPUT extracted_bootloader
 project(kernel_main)
 
 set(CMAKE_C_FLAGS "-nostdinc -m32 -nostdlib -Wall -Wextra -fverbose-asm -fno-exceptions -fno-pic -fno-stack-protector")
+set(CMAKE_CXX_FLAGS "-nostdinc -m32 -nostdlib -Wall -Wextra -fverbose-asm -fno-exceptions -fno-pic -fno-stack-protector")
 
 if (CMAKE_BUILD_TYPE STREQUAL "Debug")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g")
 elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O")
 endif()
 
 include_directories(${PROJECT_SOURCE_DIR}/include)
@@ -53,6 +56,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/types/types.h
                         include/types/size.h
                         include/types/stdint.h
+                        include/types/list.hpp
                         include/kernel_main.h
                         )
 add_library(kernel_main STATIC ${KERNEL_MAIN_SOURCES})

+ 281 - 0
include/types/list.hpp

@@ -0,0 +1,281 @@
+#pragma once
+
+#include <kernel/mem.h>
+#include <types/types.h>
+
+inline void* operator new(size_t, void* ptr)
+{
+    return ptr;
+}
+
+namespace types {
+
+template <typename T>
+class kernel_allocator {
+public:
+    using value_type = T;
+
+    static value_type* allocate_memory(size_t count)
+    {
+        return static_cast<value_type*>(::k_malloc(sizeof(value_type) * count));
+    }
+
+    static void deallocate_memory(value_type* ptr)
+    {
+        ::k_free(ptr);
+    }
+};
+
+template <typename Allocator>
+class allocator_traits {
+public:
+    using value_type = typename Allocator::value_type;
+
+    static value_type* allocate_memory(size_t count)
+    {
+        return Allocator::allocate_memory(count);
+    }
+
+    template <typename... Args>
+    static value_type* allocate(Args... args)
+    {
+        value_type* ptr = allocate_memory(sizeof(value_type));
+        new (ptr) value_type(args...);
+        return ptr;
+    }
+
+    static void deallocate(value_type* ptr)
+    {
+        ptr->~value_type();
+        Allocator::deallocate_memory(ptr);
+    }
+};
+
+template <typename T, template <typename _value_type> class Allocator = kernel_allocator>
+class list {
+private:
+    class node_base;
+    template <typename NodeValue>
+    class node;
+
+public:
+    class iterator;
+
+    using value_type = T;
+    using pointer_type = value_type*;
+    using reference_type = value_type&;
+    using iterator_type = iterator;
+    using size_type = size_t;
+    using difference_type = ssize_t;
+    using node_base_type = node_base;
+    using node_type = node<value_type>;
+    using allocator_type = Allocator<node_type>;
+    using sentry_node_type = node<size_t>;
+    using sentry_allocator_type = Allocator<sentry_node_type>;
+
+private:
+    class node_base {
+    public:
+        node_base* prev = 0;
+        node_base* next = 0;
+
+        void connect(node_base* _next) noexcept
+        {
+            this->next = _next;
+            _next->prev = this;
+        }
+    };
+
+    template <typename NodeValue>
+    class node : public node_base {
+    public:
+        explicit node(const NodeValue& v) noexcept
+            : value(v)
+        {
+        }
+
+        explicit node(NodeValue&& v) noexcept
+            : value(v)
+        {
+        }
+
+        NodeValue value;
+    };
+
+public:
+    class iterator {
+    public:
+        explicit iterator(const iterator& iter) noexcept
+            : n(iter.n)
+        {
+        }
+
+        explicit iterator(iterator&& iter) noexcept
+            : n(iter.n)
+        {
+        }
+
+        explicit iterator(node_base* _n) noexcept
+            : n(_n)
+        {
+        }
+
+        bool operator==(const iterator& iter) noexcept
+        {
+            return this->_node() == iter._node();
+        }
+
+        bool operator!=(const iterator& iter) noexcept
+        {
+            return !(*this == iter);
+        }
+
+        iterator& operator++() noexcept
+        {
+            n = n->next;
+            return *this;
+        }
+
+        iterator operator++(int) noexcept
+        {
+            iterator iter(*this);
+            n = n->next;
+            return iter;
+        }
+
+        iterator& operator--() noexcept
+        {
+            n = n->prev;
+            return *this;
+        }
+
+        iterator operator--(int) noexcept
+        {
+            iterator iter(*this);
+            n = n->prev;
+            return iter;
+        }
+
+        reference_type operator*() const noexcept
+        {
+            return (static_cast<node_type*>(n))->value;
+        }
+
+        pointer_type operator->() const noexcept
+        {
+            return (static_cast<node_type*>(n))->value;
+        }
+
+        node_base_type* _node(void) const noexcept
+        {
+            return n;
+        }
+
+    protected:
+        node_base_type* n;
+    };
+
+private:
+    node_base_type* head;
+    node_base_type* tail;
+
+    size_t& _size(void) noexcept
+    {
+        return (static_cast<sentry_node_type*>(head))->value;
+    }
+
+public:
+    list() noexcept
+        // size is stored in the 'head' node
+        : head(allocator_traits<sentry_allocator_type>::allocate(0))
+        , tail(allocator_traits<sentry_allocator_type>::allocate(0))
+    {
+        head->connect(tail);
+        tail->connect(head);
+    }
+
+    ~list() noexcept
+    {
+        for (auto iter = begin(); iter != end(); ++iter) {
+            erase(iter);
+        }
+        allocator_traits<sentry_allocator_type>::deallocate(static_cast<sentry_node_type*>(head));
+        allocator_traits<sentry_allocator_type>::deallocate(static_cast<sentry_node_type*>(tail));
+    }
+
+    // TODO: find
+
+    // erase the node which iter points to
+    void erase(const iterator_type& iter) noexcept
+    {
+        node_base_type* current_node = iter._node();
+        current_node->prev->connect(current_node->next);
+        allocator_traits<allocator_type>::deallocate(static_cast<node_type*>(current_node));
+    }
+
+    // insert the value v in front of the given iterator
+    void insert(const iterator_type& iter, const value_type& v) noexcept
+    {
+        node_base_type* new_node = allocator_traits<allocator_type>::allocate(v);
+        iter._node()->prev->connect(new_node);
+        new_node->connect(iter._node());
+
+        ++_size();
+    }
+
+    // insert the value v in front of the given iterator
+    void insert(const iterator_type& iter, value_type&& v) noexcept
+    {
+        node_base_type* new_node = allocator_traits<allocator_type>::allocate(v);
+        iter._node().prev->connect(new_node);
+        new_node->connect(iter._node());
+
+        ++_size();
+    }
+
+    void push_back(const value_type& v) noexcept
+    {
+        insert(end(), v);
+    }
+
+    void push_back(value_type&& v) noexcept
+    {
+        insert(end(), v);
+    }
+
+    void push_front(const value_type& v) noexcept
+    {
+        insert(begin(), v);
+    }
+
+    void push_front(value_type&& v) noexcept
+    {
+        insert(begin(), v);
+    }
+
+    size_t size(void) const noexcept
+    {
+        return _size();
+    }
+
+    iterator_type begin() noexcept
+    {
+        return iterator_type(head->next);
+    }
+    iterator_type end() noexcept
+    {
+        return iterator_type(tail);
+    }
+
+    // TODO
+    // iterator_type cstart() noexcept;
+    // iterator_type cend() noexcept;
+
+    // iterator_type r_start() noexcept;
+    // iterator_type r_end() noexcept;
+
+    // iterator_type cr_start() noexcept;
+    // iterator_type cr_end() noexcept;
+};
+
+} // namespace types