mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
255 lines
4.8 KiB
Plaintext
255 lines
4.8 KiB
Plaintext
/*
|
|
This file is part of Fennix Kernel.
|
|
|
|
Fennix Kernel is free software: you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation, either version 3 of
|
|
the License, or (at your option) any later version.
|
|
|
|
Fennix Kernel is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <types.h>
|
|
#include <algorithm>
|
|
#include <typeinfo>
|
|
|
|
namespace std
|
|
{
|
|
template <typename T = void>
|
|
struct equal_to
|
|
{
|
|
bool operator()(const T &lhs, const T &rhs) const
|
|
{
|
|
return lhs == rhs;
|
|
}
|
|
};
|
|
|
|
template <typename Key>
|
|
struct hash
|
|
{
|
|
size_t operator()(const Key &key) const
|
|
{
|
|
#if defined(a64)
|
|
static_assert(sizeof(uintptr_t) == sizeof(uint64_t));
|
|
const uint64_t FNV_OFFSET_BASIS = 14695981039346656037ull;
|
|
const uint64_t FNV_PRIME = 1099511628211ull;
|
|
#elif defined(a32)
|
|
static_assert(sizeof(uintptr_t) == sizeof(uint32_t));
|
|
const uint32_t FNV_OFFSET_BASIS = 2166136261u;
|
|
const uint32_t FNV_PRIME = 16777619u;
|
|
#else
|
|
#error "Unsupported architecture"
|
|
#endif
|
|
|
|
const uint8_t *data = reinterpret_cast<const uint8_t *>(&key);
|
|
const size_t size = sizeof(Key);
|
|
uintptr_t hash = FNV_OFFSET_BASIS;
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
{
|
|
hash ^= static_cast<uintptr_t>(data[i]);
|
|
hash *= FNV_PRIME;
|
|
}
|
|
|
|
return static_cast<size_t>(hash);
|
|
}
|
|
};
|
|
|
|
template <class T>
|
|
class reference_wrapper;
|
|
|
|
template <class>
|
|
class function; /* undefined */
|
|
|
|
template <class R, class... Args>
|
|
class function<R(Args...)>
|
|
{
|
|
private:
|
|
class impl_base
|
|
{
|
|
public:
|
|
virtual ~impl_base() = default;
|
|
virtual R invoke(Args...) const = 0;
|
|
#ifdef __GXX_RTTI
|
|
virtual const std::type_info &target_type() const noexcept = 0;
|
|
#endif
|
|
virtual impl_base *clone() const = 0;
|
|
};
|
|
|
|
template <class F>
|
|
class impl : public impl_base
|
|
{
|
|
public:
|
|
F _f;
|
|
|
|
template <class G>
|
|
impl(G &&f)
|
|
: _f(std::forward<G>(f))
|
|
{
|
|
}
|
|
|
|
R invoke(Args... args) const override
|
|
{
|
|
return _f(std::forward<Args>(args)...);
|
|
}
|
|
|
|
#ifdef __GXX_RTTI
|
|
const std::type_info &target_type() const noexcept override
|
|
{
|
|
return typeid(F);
|
|
}
|
|
#endif
|
|
|
|
impl_base *clone() const override
|
|
{
|
|
return new impl<F>(_f);
|
|
}
|
|
};
|
|
|
|
impl_base *_ptr;
|
|
|
|
public:
|
|
using result_type = R;
|
|
|
|
function() noexcept
|
|
: _ptr(nullptr)
|
|
{
|
|
}
|
|
|
|
function(std::nullptr_t) noexcept
|
|
: _ptr(nullptr)
|
|
{
|
|
}
|
|
|
|
function(const function &other)
|
|
: _ptr(other._ptr)
|
|
{
|
|
}
|
|
|
|
function(function &&other) noexcept
|
|
: _ptr(other._ptr)
|
|
{
|
|
other._ptr = nullptr;
|
|
}
|
|
|
|
template <class F>
|
|
function(F &&f)
|
|
: _ptr(new impl<F>(std::forward<F>(f)))
|
|
{
|
|
}
|
|
|
|
~function()
|
|
{
|
|
delete _ptr;
|
|
}
|
|
|
|
function &operator=(const function &other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
delete _ptr;
|
|
_ptr = other._ptr ? other._ptr->clone() : nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
function &operator=(function &&other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
delete _ptr;
|
|
_ptr = other._ptr;
|
|
other._ptr = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
function &operator=(std::nullptr_t) noexcept
|
|
{
|
|
delete _ptr;
|
|
_ptr = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
template <class F>
|
|
function &operator=(F &&f)
|
|
{
|
|
delete _ptr;
|
|
_ptr = new impl<F>(std::forward<F>(f));
|
|
return *this;
|
|
}
|
|
|
|
template <class F>
|
|
function &operator=(std::reference_wrapper<F> f) noexcept
|
|
{
|
|
delete _ptr;
|
|
_ptr = new impl<std::reference_wrapper<F>>(f);
|
|
return *this;
|
|
}
|
|
|
|
void swap(function &other) noexcept
|
|
{
|
|
std::swap(_ptr, other._ptr);
|
|
}
|
|
|
|
explicit operator bool() const noexcept
|
|
{
|
|
return _ptr != nullptr;
|
|
}
|
|
|
|
R operator()(Args... args) const
|
|
{
|
|
return _ptr->invoke(std::forward<Args>(args)...);
|
|
}
|
|
|
|
#ifdef __GXX_RTTI
|
|
const std::type_info &target_type() const noexcept
|
|
{
|
|
return _ptr ? _ptr->target_type() : typeid(void);
|
|
}
|
|
|
|
template <class T>
|
|
T *target() noexcept
|
|
{
|
|
return _ptr && _ptr->target_type() == typeid(T) ? &static_cast<impl<T> *>(_ptr)->_f : nullptr;
|
|
}
|
|
|
|
template <class T>
|
|
const T *target() const noexcept
|
|
{
|
|
return _ptr && _ptr->target_type() == typeid(T) ? &static_cast<impl<T> *>(_ptr)->_f : nullptr;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template <class R, class... Args>
|
|
void swap(std::function<R(Args...)> &lhs, std::function<R(Args...)> &rhs) noexcept
|
|
{
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
template <class R, class... ArgTypes>
|
|
|
|
bool operator==(const std::function<R(ArgTypes...)> &f, std::nullptr_t) noexcept
|
|
{
|
|
return !f;
|
|
}
|
|
|
|
template <class T = void>
|
|
struct less
|
|
{
|
|
constexpr bool operator()(const T &lhs, const T &rhs) const
|
|
{
|
|
return lhs < rhs;
|
|
}
|
|
};
|
|
}
|