Ver código fonte

feat(functional): c++ std::function

greatbridf 1 ano atrás
pai
commit
2ba94b1ce9

+ 0 - 1
CMakeLists.txt

@@ -91,7 +91,6 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         include/types/lock.hpp
                         include/types/string.hpp
                         include/types/vector.hpp
-                        include/types/function.hpp
                         include/kernel/log.hpp
                         )
 

+ 42 - 0
gblibstdc++/include/bits/fwd_functional

@@ -0,0 +1,42 @@
+#ifndef __GBLIBCPP_BITS_FWD_FUNCTIONAL__
+#define __GBLIBCPP_BITS_FWD_FUNCTIONAL__
+
+#include <cstddef>
+
+namespace std {
+
+template <typename T>
+class reference_wrapper;
+
+template <typename>
+class function;
+
+template <typename Ret, typename... Args>
+bool operator==(const std::function<Ret(Args...)>& func, std::nullptr_t) noexcept;
+
+template <typename Ret, typename... Args>
+void swap(std::function<Ret(Args...)>& lhs, std::function<Ret(Args...)>& rhs) noexcept;
+
+template <typename T>
+constexpr std::reference_wrapper<T> ref(T& t) noexcept;
+
+template <typename T>
+constexpr std::reference_wrapper<T>
+    ref(std::reference_wrapper<T> t) noexcept;
+
+template <typename T>
+void ref(const T&&) = delete;
+
+template <typename T>
+constexpr std::reference_wrapper<const T> cref(const T& t) noexcept;
+
+template <typename T>
+constexpr std::reference_wrapper<const T>
+    cref(std::reference_wrapper<T> t) noexcept;
+
+template <typename T>
+void cref(const T&&) = delete;
+
+} // namespace std
+
+#endif

+ 15 - 0
gblibstdc++/include/cstddef

@@ -0,0 +1,15 @@
+#ifndef __GBLIBCPP_CSTDDEF__
+#define __GBLIBCPP_CSTDDEF__
+
+#undef NULL
+#define NULL (nullptr)
+
+namespace std {
+
+using nullptr_t = decltype(nullptr);
+
+using size_t = __SIZE_TYPE__;
+
+}; // namespace std
+
+#endif

+ 292 - 0
gblibstdc++/include/functional

@@ -0,0 +1,292 @@
+#ifndef __GBLIBCPP_FUNCTIONAL__
+#define __GBLIBCPP_FUNCTIONAL__
+
+#include <bits/fwd_functional>
+
+#include <cstddef>
+#include <memory>
+#include <new>
+#include <utility>
+#include <type_traits>
+
+namespace std {
+
+template <typename Func, typename... Args>
+constexpr auto invoke(Func&& func, Args&&... args)
+    noexcept(std::is_nothrow_invocable_v<Func, Args...>)
+    -> std::enable_if_t<std::is_invocable_v<Func, Args...>,
+        std::invoke_result_t<Func, Args...>>
+{
+    return __helpers::INVOKE(std::forward<Func>(func), std::forward<Args>(args)...);
+}
+
+namespace __helpers {
+template <typename T> constexpr void __reference_wrapper_check(T&) noexcept {}
+template <typename T> void __reference_wrapper_check(T&&) = delete;
+} // namespace __helpers
+
+template <typename T>
+class reference_wrapper {
+private:
+    T* _ptr;
+
+    template <typename Ref, typename = 
+        decltype(__helpers::__reference_wrapper_check<T>(std::declval<Ref>()))>
+    struct __check_reference_valid
+        : public bool_constant<!std::is_same_v<reference_wrapper, std::decay_t<Ref>>> {};
+
+public:
+    using type = T;
+
+    constexpr T& get(void) const noexcept { return *_ptr; }
+    constexpr operator T&(void) const noexcept { return *_ptr; }
+
+    template <typename U, std::enable_if_t<__check_reference_valid<U>::value, bool> = true>
+    constexpr reference_wrapper(U&& ref)
+        noexcept(noexcept(__helpers::__reference_wrapper_check<T>(std::declval<U>())))
+        : _ptr(std::addressof(ref)) {}
+
+    constexpr reference_wrapper(const reference_wrapper& val) noexcept
+    {
+        _ptr = val._ptr;
+    }
+    constexpr reference_wrapper& operator=(const reference_wrapper& val) noexcept = default;
+
+    // TODO: std::invoke_result_t
+    template <typename... Args>
+    constexpr invoke_result_t<type&, Args...>
+    operator()(Args&&... args) const noexcept(is_nothrow_invocable_v<type&, Args...>)
+    {
+        return std::invoke(get(), std::forward<Args>(args)...);
+    }
+};
+template <typename T>
+reference_wrapper(T&) -> reference_wrapper<T>;
+
+namespace __inner {
+
+    template <typename Ret, typename... Args>
+    class _function_base {
+    public:
+        virtual constexpr ~_function_base() = default;
+        virtual constexpr Ret operator()(Args... args) const = 0;
+        virtual constexpr void copy_to(_function_base* func) = 0;
+        virtual constexpr void move_to(_function_base* func) = 0;
+        virtual explicit constexpr operator bool(void) const = 0;
+    };
+
+    template <typename FuncLike, typename Ret, typename... Args>
+    class _function : public _function_base<Ret, Args...> {
+    private:
+        using __enable = std::enable_if_t<
+            std::is_same_v<Ret,
+                decltype(std::declval<std::decay_t<FuncLike>>()(std::declval<Args>()...))>
+        >;
+        FuncLike func;
+
+    public:
+        constexpr _function(const FuncLike& _func) : func(_func) {}
+        constexpr _function(FuncLike&& _func) : func(std::move(_func)) {}
+
+        constexpr Ret operator()(Args... args) const override
+        {
+            return std::invoke(func, std::forward<Args>(args)...);
+        }
+
+        constexpr void copy_to(_function_base<Ret, Args...>* dst) override
+        {
+            new (reinterpret_cast<_function*>(dst)) _function(*this);
+        }
+
+        constexpr void move_to(_function_base<Ret, Args...>* dst) override
+        {
+            new (reinterpret_cast<_function*>(dst)) _function(std::move(*this));
+        }
+
+        constexpr explicit operator bool(void) const override
+        {
+            return true;
+        }
+    };
+
+    template <typename Ret, typename... Args>
+    class _function<nullptr_t, Ret, Args...> : public _function_base<Ret, Args...> {
+    public:
+        [[noreturn]] Ret operator()(Args...) const override
+        {
+            // TODO: exception
+            *((int*)(100^100)) = 1; // triggers access to null pointer
+            for (;;);
+        }
+        constexpr void copy_to(_function_base<Ret, Args...>* dst) override
+        {
+            new (reinterpret_cast<_function*>(dst)) _function(*this);
+        }
+        constexpr void move_to(_function_base<Ret, Args...>* dst) override
+        {
+            new (reinterpret_cast<_function*>(dst)) _function(std::move(*this));
+        }
+        constexpr explicit operator bool(void) const override
+        {
+            return false;
+        }
+    };
+
+} // namespace __inner
+
+template <typename Ret, typename... Args>
+class function<Ret(Args...)> {
+public:
+    using result_type = Ret;
+
+private:
+    char _data[sizeof(void*) * 2];
+    using fb_t = __inner::_function_base<Ret, Args...>;
+    constexpr fb_t* _f(void) const
+    {
+        return (fb_t*)_data;
+    }
+
+    constexpr void _clear(void)
+    {
+        _f()->~_function_base();
+    }
+
+public:
+    constexpr function() noexcept
+    {
+        new (_f()) __inner::_function<nullptr_t, Ret, Args...>();
+    }
+    constexpr function(nullptr_t) noexcept : function() {}
+    constexpr function(const function& func)
+    {
+        func._f()->copy_to(_f());
+    }
+    constexpr function(function&& func) noexcept
+    {
+        func._f()->move_to(_f());
+    }
+
+    template <typename FuncLike, std::enable_if_t
+        <
+            std::is_same_v<
+                Ret,
+                decltype(std::declval<std::decay_t<FuncLike>>()(std::declval<Args>()...))
+            >
+            && (sizeof(std::decay_t<FuncLike>) <= sizeof(_data))
+            && !std::is_same_v<std::decay_t<FuncLike>, function>
+        , bool> = true
+    >
+    constexpr function(FuncLike&& func)
+    {
+        new (_f()) __inner::_function<std::decay_t<FuncLike>, Ret, Args...>(std::forward<FuncLike>(func));
+    }
+
+    constexpr ~function()
+    {
+        _clear();
+    }
+
+    constexpr Ret operator()(Args... args) const
+    {
+        return (*_f())(std::forward<Args>(args)...);
+    }
+
+    explicit operator bool(void) const noexcept
+    {
+        return !!*_f();
+    }
+
+    function& operator=(function&& rhs)
+    {
+        _clear();
+        rhs._f()->move_to(_f());
+        return *this;
+    }
+
+    void swap(function& other) noexcept
+    {
+        function tmp(std::move(other));
+        other = std::move(*this);
+        *this = std::move(tmp);
+    }
+
+    function& operator=(const function& rhs)
+    {
+        _clear();
+        rhs._f()->copy_to(_f());
+        return *this;
+    }
+
+    function& operator=(nullptr_t) noexcept
+    {
+        _clear();
+        new (_f()) __inner::_function<nullptr_t, Ret, Args...>();
+        return *this;
+    }
+
+    template <typename FuncLike, std::enable_if_t
+        <
+            std::is_same_v<
+                Ret,
+                decltype(std::declval<std::decay_t<FuncLike>>()(std::declval<Args>()...))
+            >
+            && (sizeof(std::decay_t<FuncLike>) <= sizeof(_data))
+            && !std::is_same_v<std::decay_t<FuncLike>, function>
+        , bool> = true
+    >
+    function& operator=(FuncLike&& func)
+    {
+        function{std::forward<FuncLike>(func)}.swap(*this);
+        return *this;
+    }
+
+    template <typename FuncLike>
+    function& operator=(std::reference_wrapper<FuncLike> func) noexcept
+    {
+        function{func}.swap(*this);
+        return *this;
+    }
+};
+
+template <typename Ret, typename... Args>
+bool operator==(const std::function<Ret(Args...)>& func, std::nullptr_t) noexcept
+{
+    return !func;
+}
+
+template <typename Ret, typename... Args>
+void swap(std::function<Ret(Args...)>& lhs, std::function<Ret(Args...)>& rhs) noexcept
+{
+    return lhs.swap(rhs);
+}
+
+template <typename T>
+constexpr std::reference_wrapper<T> ref(T& t) noexcept
+{
+    return std::reference_wrapper<T>((t));
+}
+
+template <typename T>
+constexpr std::reference_wrapper<T>
+    ref(std::reference_wrapper<T> t) noexcept
+{
+    return t;
+}
+
+template <typename T>
+constexpr std::reference_wrapper<const T> cref(const T& t) noexcept
+{
+    return std::reference_wrapper<const T>((t));
+}
+
+template <typename T>
+constexpr std::reference_wrapper<const T>
+    cref(std::reference_wrapper<T> t) noexcept
+{
+    return t;
+}
+
+} // namespace std
+
+#endif

+ 32 - 0
gblibstdc++/include/memory

@@ -0,0 +1,32 @@
+#ifndef __GBLIBCPP_MEMORY__
+#define __GBLIBCPP_MEMORY__
+
+#include <type_traits>
+#include <utility>
+
+namespace std {
+
+template <typename T>
+constexpr enable_if_t<is_function_v<remove_reference_t<T>>, T*>
+addressof(T& arg) noexcept
+{
+    return &arg;
+}
+
+template <typename T>
+constexpr enable_if_t<!is_function_v<remove_reference_t<T>>, T*>
+addressof(T& arg) noexcept
+{
+    return reinterpret_cast<T*>(
+        &const_cast<char&>(
+            reinterpret_cast<const volatile char&>(arg)
+        )
+    );
+}
+
+template <typename T>
+T* addressof(const T&&) = delete;
+
+} // namespace std
+
+#endif

+ 11 - 0
gblibstdc++/include/new

@@ -0,0 +1,11 @@
+#ifndef __GBLIBCPP_NEW__
+#define __GBLIBCPP_NEW__
+
+#include <cstddef>
+
+constexpr void* operator new(std::size_t, void* ptr) noexcept
+{
+    return ptr;
+}
+
+#endif

+ 159 - 0
gblibstdc++/include/type_traits

@@ -1,6 +1,9 @@
 #ifndef __GBLIBCPP_TYPE_TRAITS__
 #define __GBLIBCPP_TYPE_TRAITS__
 
+#include <bits/fwd_functional>
+#include <utility>
+
 namespace std {
 
 template <typename... Ts>
@@ -170,6 +173,16 @@ struct is_const<T const> : public true_type {};
 template <typename T>
 inline constexpr bool is_const_v = is_const<T>::value;
 
+template <typename T>
+struct is_function : public bool_constant<!is_const_v<const T>> {};
+template <typename T>
+struct is_function<T&> : public false_type {};
+template <typename T>
+struct is_function<T&&> : public false_type {};
+
+template <typename T>
+inline constexpr bool is_function_v = is_function<T>::value;
+
 template <bool B, typename T = void>
 struct enable_if {};
 template <typename T>
@@ -197,6 +210,31 @@ struct is_convertible<Void1, Void2,
     enable_if_t<is_void_v<Void1> && is_void_v<Void2> >
 > : public true_type {};
 
+// TODO: check T is union
+template <typename T>
+true_type __test_is_class(int T::*);
+template <typename T>
+false_type __test_is_class(...);
+
+template <typename Base, typename Derived>
+auto _try_is_base_of(...) -> true_type;
+
+template <typename Base, typename Derived>
+auto _try_is_base_of() ->
+    decltype(void());
+
+template <typename Base>
+true_type __conv_base_pointer(const volatile Base*);
+template <typename>
+false_type __conv_base_pointer(const volatile void*);
+
+template <typename Base, typename Derived>
+decltype(__conv_base_pointer<Base>(declval<Derived*>()))
+try_is_base_of(int);
+
+template <typename, typename>
+true_type try_is_base_of(...);
+
 } // namespace __helpers
 
 template <typename From, typename To>
@@ -205,6 +243,127 @@ struct is_convertible : public __helpers::is_convertible<From, To> {};
 template <typename From, typename To>
 inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
 
+template <typename T>
+struct is_class : public decltype(__helpers::__test_is_class<T>(nullptr)) {};
+
+template <typename T>
+inline constexpr bool is_class_v = is_class<T>::value;
+
+template <typename Base, typename Derived>
+struct is_base_of : public bool_constant<
+    is_class_v<Base> && is_class_v<Derived>
+    && decltype(__helpers::try_is_base_of<Base, Derived>(0))::value
+> {};
+
+template <typename Base, typename Derived>
+inline constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;
+
+namespace __helpers {
+
+template <typename>
+struct is_reference_wrapper : public false_type {};
+template <typename T>
+struct is_reference_wrapper<reference_wrapper<T>> : public true_type {};
+
+template <typename FuncType>
+struct __invoke_impl {
+    template <typename Func, typename... Args>
+    static auto __invoke(Func&& func, Args&&... args)
+        noexcept(noexcept(forward<Func>(func)(forward<Args>(args)...)))
+        -> decltype(forward<Func>(func)(forward<Args>(args)...)) {
+        return forward<Func>(func)(forward<Args>(args)...);
+    }
+};
+
+template <typename T, typename Ret>
+struct __invoke_impl<Ret T::*> {
+    template <typename _T1, typename T1 = decay_t<_T1>, typename = enable_if_t<
+        is_same_v<T, T1> || is_base_of_v<T, T1>
+        >>
+    static auto get(_T1&& val) -> _T1&& {
+        return forward<_T1>(val);
+    }
+
+    template <typename _T1, typename T1 = decay_t<_T1>, typename = enable_if_t<
+        is_reference_wrapper<T1>::value
+        >>
+    static auto get(_T1&& val) -> decltype(val.get()) {
+        return val.get();
+    }
+
+    template <typename _T1, typename T1 = decay_t<_T1>, typename = enable_if_t<
+        !is_same_v<T, T1> && !is_base_of_v<T, T1>
+        && !is_reference_wrapper<T1>::value
+        >>
+    static auto get(_T1&& val) -> decltype(*forward<_T1>(val)) {
+        return *forward<_T1>(val);
+    }
+
+    template <typename T1, typename... Args>
+    static auto __invoke(Ret T::*pmf, T1&& t1, Args&&... args)
+        noexcept(noexcept((forward<T1>(t1).*pmf)(forward<Args>(args)...)))
+        -> decltype((get(forward<T1>(t1)).*pmf)(forward<Args>(args)...)) {
+        return (get(forward<T1>(t1)).*pmf)(forward<Args>(args)...);
+    }
+
+    template <typename T1>
+    static auto __invoke(Ret T::*pdm, T1&& t1) noexcept
+        -> decltype(get(forward<T1>(t1)).*pdm) {
+        return get(forward<T1>(t1)).*pdm;
+    }
+};
+
+template <typename Func, typename... Args, typename FuncBase = decay_t<Func>>
+auto INVOKE(Func&& func, Args&&... args)
+    noexcept(noexcept(__invoke_impl<FuncBase>::__invoke(
+        forward<Func>(func), forward<Args>(args)...)))
+    -> decltype(__invoke_impl<FuncBase>::__invoke(
+        forward<Func>(func), forward<Args>(args)...))
+{
+    return __invoke_impl<FuncBase>::__invoke(
+    forward<Func>(func), forward<Args>(args)...);
+}
+
+template <typename Func, typename = void, typename... Args>
+struct __is_invocable : public false_type {};
+
+template <typename Func, typename... Args>
+struct __is_invocable<Func, void_t<
+    decltype(INVOKE(declval<Func>(), declval<Args>()...))>,
+    Args...> : public true_type {};
+
+template <typename Func, typename = void, typename... Args>
+struct __invoke_result {};
+
+template <typename Func, typename... Args>
+struct __invoke_result<Func, enable_if_t<
+    __is_invocable<Func, void, Args...>::value
+>, Args...> {
+    using type = decltype(INVOKE(declval<Func>(), declval<Args>()...));
+};
+
+} // namespace __helpers
+
+template <typename Func, typename... Args>
+struct is_invocable : __helpers::__is_invocable<Func, void, Args...> {};
+
+template <typename Func, typename... Args>
+struct is_nothrow_invocable : bool_constant<
+    is_invocable<Func, Args...>::value
+    && noexcept(__helpers::INVOKE(declval<Func>(), declval<Args>()...))
+> {};
+
+template <typename Func, typename... Args>
+inline constexpr bool is_invocable_v = is_invocable<Func, Args...>::value;
+template <typename Func, typename... Args>
+inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Func, Args...>::value;
+
+template <typename Func, typename... Args>
+struct invoke_result : __helpers::__invoke_result<Func, void, Args...> {};
+
+template <class Func, class... Args>
+using invoke_result_t = typename invoke_result<Func, Args...>::type;
+
 #define __CPP_GREATBRIDF
 #ifdef __CPP_GREATBRIDF
 

+ 18 - 6
gblibstdc++/include/utility

@@ -1,23 +1,35 @@
 #ifndef __GBLIBCPP_UTILITY__
 #define __GBLIBCPP_UTILITY__
 
-#include <type_traits>
-
 namespace std {
 
+namespace __helpers {
+template <typename T>
+struct __utility_remove_reference { using type = T; };
+template <typename T>
+struct __utility_remove_reference<T&> { using type = T; };
+template <typename T>
+struct __utility_remove_reference<T&&> { using type = T; };
+};
+
 template <typename T>
-constexpr remove_reference_t<T>&& move(T&& val)
+constexpr typename __helpers::__utility_remove_reference<T>::type&&
+move(T&& val) noexcept
 {
-    return static_cast<remove_reference_t<T>&&>(val);
+    return static_cast<
+        typename __helpers::__utility_remove_reference<T>::type&&
+        >(val);
 }
 
 template <typename T>
-constexpr T&& forward(remove_reference_t<T>& val)
+constexpr T&& forward(
+    typename __helpers::__utility_remove_reference<T>::type& val) noexcept
 {
     return static_cast<T&&>(val);
 }
 template <typename T>
-constexpr T&& forward(remove_reference_t<T>&& val)
+constexpr T&& forward(
+    typename __helpers::__utility_remove_reference<T>::type&& val) noexcept
 {
     return static_cast<T&&>(val);
 }

+ 2 - 1
include/kernel/vfs.hpp

@@ -1,12 +1,13 @@
 #pragma once
 
+#include <functional>
+
 #include <assert.h>
 #include <kernel/event/evtqueue.hpp>
 #include <stdint.h>
 #include <types/allocator.hpp>
 #include <types/buffer.hpp>
 #include <types/cplusplus.hpp>
-#include <types/function.hpp>
 #include <types/hash_map.hpp>
 #include <types/list.hpp>
 #include <types/lock.hpp>

+ 1 - 5
include/types/allocator.hpp

@@ -1,4 +1,5 @@
 #pragma once
+#include <new>
 #include <utility>
 #include <type_traits>
 #include <assert.h>
@@ -6,11 +7,6 @@
 #include <types/cplusplus.hpp>
 #include <types/types.h>
 
-constexpr void* operator new(size_t, void* ptr)
-{
-    return ptr;
-}
-
 namespace types {
 
 namespace __allocator {

+ 0 - 76
include/types/function.hpp

@@ -1,76 +0,0 @@
-#pragma once
-#include <utility>
-#include <type_traits>
-
-namespace std {
-
-namespace __inner {
-
-    template <typename Ret, typename... Args>
-    class _function_base {
-    public:
-        constexpr _function_base() = default;
-        virtual constexpr ~_function_base() = default;
-        virtual constexpr Ret operator()(Args&&... args) const = 0;
-    };
-
-    template <typename FuncLike, typename Ret, typename... Args>
-    class _function : public _function_base<Ret, Args...> {
-    private:
-        FuncLike func;
-
-    public:
-        constexpr _function(FuncLike&& _func)
-            : func(std::forward<FuncLike>(_func))
-        {
-        }
-        constexpr ~_function() = default;
-
-        constexpr Ret operator()(Args&&... args) const override
-        {
-            return func(std::forward<Args>(args)...);
-        }
-    };
-
-} // namespace __inner
-
-template <typename>
-class function;
-
-template <typename Ret, typename... Args>
-class function<Ret(Args...)> {
-private:
-    char _data[sizeof(void*) * 2];
-    using fb_t = __inner::_function_base<Ret, Args...>;
-    constexpr fb_t* _f(void) const
-    {
-        return (fb_t*)_data;
-    }
-
-public:
-    template <typename FuncLike>
-    constexpr function(FuncLike&& func)
-    {
-        static_assert(sizeof(FuncLike) <= sizeof(_data));
-        new (_f()) __inner::_function<FuncLike, Ret, Args...>(std::forward<FuncLike>(func));
-    }
-
-    template <typename FuncPtr>
-    constexpr function(FuncPtr* funcPtr)
-    {
-        new (_f()) __inner::_function<std::decay_t<FuncPtr>, Ret, Args...>(
-            std::forward<std::decay_t<FuncPtr>>(funcPtr));
-    }
-
-    constexpr ~function()
-    {
-        _f()->~_function_base();
-    }
-
-    constexpr Ret operator()(Args... args) const
-    {
-        return (*_f())(std::forward<Args>(args)...);
-    }
-};
-
-} // namespace std