mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-08-04 19:11:42 +00:00
Compare commits
13 Commits
f5c8ae9323
...
nightly
Author | SHA1 | Date | |
---|---|---|---|
2c1d6c2608
|
|||
97a892d114
|
|||
3be150da53
|
|||
455224ceb4
|
|||
e01f1dc97c
|
|||
76113df5a9
|
|||
1addd310ad
|
|||
3d92a87bef
|
|||
f7177f92cf
|
|||
6a6c3bfc67
|
|||
8dbeee4d9a
|
|||
5d5b674aed
|
|||
31bbc29c9f
|
@@ -25,7 +25,7 @@
|
||||
}
|
||||
},
|
||||
// From this line below are for qemu, so not that important.
|
||||
"initializeCommand": "xhost +local:docker", // "xhost -local:docker" to disable
|
||||
"initializeCommand": "[ -x \"$(command -v xhost)\" ] && xhost +local:docker || true", // "xhost -local:docker" to disable
|
||||
"mounts": [
|
||||
{
|
||||
"source": "/tmp/.X11-unix",
|
||||
|
26
.github/workflows/makefile.yml
vendored
26
.github/workflows/makefile.yml
vendored
@@ -26,9 +26,7 @@ jobs:
|
||||
run: |
|
||||
sudo mkdir -p /tmp/.X11-unix
|
||||
sudo mkdir -p /run/user/1000/pulse
|
||||
sudo touch /tmp/.Xauthority
|
||||
sudo touch /run/user/1000/pulse/native
|
||||
echo "XAUTHORITY=/tmp/.Xauthority" >> $GITHUB_ENV
|
||||
|
||||
- name: Run make ci-setup in dev container
|
||||
if: steps.cache-cross.outputs.cache-hit != 'true'
|
||||
@@ -134,9 +132,7 @@ jobs:
|
||||
run: |
|
||||
sudo mkdir -p /tmp/.X11-unix
|
||||
sudo mkdir -p /run/user/1000/pulse
|
||||
sudo touch /tmp/.Xauthority
|
||||
sudo touch /run/user/1000/pulse/native
|
||||
echo "XAUTHORITY=/tmp/.Xauthority" >> $GITHUB_ENV
|
||||
|
||||
- name: Build AMD64 Debug
|
||||
if: always()
|
||||
@@ -205,5 +201,25 @@ jobs:
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Fennix
|
||||
name: artifacts
|
||||
path: artifacts/
|
||||
|
||||
nightly:
|
||||
if: always()
|
||||
name: Upload Nightly Build to GitHub Releases
|
||||
runs-on: ubuntu-latest
|
||||
needs: [compile]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download All Builds
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Update Nightly
|
||||
run: gh release upload nightly artifacts/* -R ${{github.repository}} --clobber
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
@@ -409,4 +409,84 @@ namespace std
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
constexpr auto lexicographical_compare_three_way(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T = void>
|
||||
struct __algo_less
|
||||
{
|
||||
constexpr bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct __algo_less<T *>
|
||||
{
|
||||
constexpr bool operator()(const T *lhs, const T *rhs) const
|
||||
{
|
||||
if (__builtin_is_constant_evaluated())
|
||||
return lhs < rhs;
|
||||
return (__UINTPTR_TYPE__)lhs < (__UINTPTR_TYPE__)rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class __algo_less<void>
|
||||
{
|
||||
public:
|
||||
template <class T, class U>
|
||||
constexpr auto operator()(T &&lhs, U &&rhs) const -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs))
|
||||
{
|
||||
return std::forward<T>(lhs) < std::forward<U>(rhs);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class ForwardIt, class Compare>
|
||||
ForwardIt is_sorted_until(ForwardIt first, ForwardIt last, Compare comp)
|
||||
{
|
||||
if (first == last)
|
||||
return last;
|
||||
|
||||
ForwardIt next = first;
|
||||
while (++next != last)
|
||||
{
|
||||
if (comp(*next, *first))
|
||||
return next;
|
||||
first = next;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
template <class ForwardIt>
|
||||
ForwardIt is_sorted_until(ForwardIt first, ForwardIt last)
|
||||
{
|
||||
return is_sorted_until(first, last, detail::__algo_less<>());
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt>
|
||||
ForwardIt is_sorted_until(ExecutionPolicy &&policy, ForwardIt first, ForwardIt last);
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt, class Compare>
|
||||
ForwardIt is_sorted_until(ExecutionPolicy &&policy, ForwardIt first, ForwardIt last, Compare comp);
|
||||
|
||||
template <class ForwardIt>
|
||||
constexpr bool is_sorted(ForwardIt first, ForwardIt last)
|
||||
{
|
||||
return std::is_sorted_until(first, last) == last;
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt>
|
||||
bool is_sorted(ExecutionPolicy &&policy, ForwardIt first, ForwardIt last);
|
||||
|
||||
template <class ForwardIt, class Compare>
|
||||
constexpr bool is_sorted(ForwardIt first, ForwardIt last, Compare comp)
|
||||
{
|
||||
return std::is_sorted_until(first, last, comp) == last;
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt, class Compare>
|
||||
bool is_sorted(ExecutionPolicy &&policy, ForwardIt first, ForwardIt last, Compare comp);
|
||||
}
|
||||
|
789
Kernel/include_std/foward_list
Normal file
789
Kernel/include_std/foward_list
Normal file
@@ -0,0 +1,789 @@
|
||||
/*
|
||||
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 <memory>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <compare>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
class forward_list
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using allocator_type = Allocator;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = value_type &;
|
||||
using const_reference = const value_type &;
|
||||
using pointer = std::allocator_traits<Allocator>::pointer;
|
||||
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
// using iterator = value_type;
|
||||
// using const_iterator = const value_type;
|
||||
|
||||
private:
|
||||
struct node
|
||||
{
|
||||
node *Next;
|
||||
value_type Value;
|
||||
|
||||
template <class... Args>
|
||||
node(node *next, Args &&...args)
|
||||
: Next(next), Value(std::forward<Args>(args)...) {}
|
||||
};
|
||||
|
||||
using node_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<node>;
|
||||
node_allocator_type NodeAlloc;
|
||||
node *Head; /* Points to dummy node (before first element) */
|
||||
|
||||
node *__CreateNode(const T &value)
|
||||
{
|
||||
node *n = std::allocator_traits<node_allocator_type>::allocate(NodeAlloc, 1);
|
||||
try
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::construct(NodeAlloc, n, nullptr, value);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::deallocate(NodeAlloc, n, 1);
|
||||
throw;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
node *__CreateNode(T &&value)
|
||||
{
|
||||
node *n = std::allocator_traits<node_allocator_type>::allocate(NodeAlloc, 1);
|
||||
try
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::construct(NodeAlloc, n, nullptr, std::move(value));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::deallocate(NodeAlloc, n, 1);
|
||||
throw;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
node *__CreateNodeEmplace(Args &&...args)
|
||||
{
|
||||
node *n = std::allocator_traits<node_allocator_type>::allocate(NodeAlloc, 1);
|
||||
try
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::construct(NodeAlloc, n, nullptr, std::forward<Args>(args)...);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::deallocate(NodeAlloc, n, 1);
|
||||
throw;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void __DestroyNode(node *n)
|
||||
{
|
||||
std::allocator_traits<node_allocator_type>::destroy(NodeAlloc, n);
|
||||
std::allocator_traits<node_allocator_type>::deallocate(NodeAlloc, n, 1);
|
||||
}
|
||||
|
||||
void __ClearNodes(node *start)
|
||||
{
|
||||
while (start)
|
||||
{
|
||||
node *next = start->Next;
|
||||
__DestroyNode(start);
|
||||
start = next;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
friend class forward_list;
|
||||
node *ptr;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T *pointer;
|
||||
typedef T &reference;
|
||||
using self_type = iterator;
|
||||
|
||||
iterator() : ptr(nullptr) {}
|
||||
iterator(node *p) : ptr(p) {}
|
||||
iterator(const iterator &other) = default;
|
||||
iterator &operator=(const iterator &other) = default;
|
||||
~iterator() = default;
|
||||
|
||||
reference operator*() { return ptr->Value; }
|
||||
pointer operator->() { return &(ptr->Value); }
|
||||
const_reference operator*() const { return ptr->Value; }
|
||||
const_pointer operator->() const { return &(ptr->Value); }
|
||||
|
||||
self_type &operator++()
|
||||
{
|
||||
ptr = ptr->Next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_type operator++(int)
|
||||
{
|
||||
self_type tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const self_type &other) const { return ptr == other.ptr; }
|
||||
bool operator!=(const self_type &other) const { return ptr != other.ptr; }
|
||||
};
|
||||
|
||||
class const_iterator
|
||||
{
|
||||
friend class forward_list;
|
||||
const node *ptr;
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef const T *pointer;
|
||||
typedef const T &reference;
|
||||
using self_type = const_iterator;
|
||||
|
||||
const_iterator() : ptr(nullptr) {}
|
||||
const_iterator(const node *p) : ptr(p) {}
|
||||
const_iterator(const iterator &it) : ptr(it.ptr) {}
|
||||
const_iterator(const const_iterator &other) = default;
|
||||
const_iterator &operator=(const const_iterator &other) = default;
|
||||
~const_iterator() = default;
|
||||
|
||||
reference operator*() const { return ptr->Value; }
|
||||
pointer operator->() const { return &(ptr->Value); }
|
||||
|
||||
self_type &operator++()
|
||||
{
|
||||
ptr = ptr->Next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_type operator++(int)
|
||||
{
|
||||
self_type tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const self_type &other) const { return ptr == other.ptr; }
|
||||
bool operator!=(const self_type &other) const { return ptr != other.ptr; }
|
||||
};
|
||||
|
||||
#pragma region Constructors
|
||||
|
||||
forward_list() : NodeAlloc(), Head(__CreateNodeEmplace()) {}
|
||||
|
||||
explicit forward_list(const Allocator &alloc) : NodeAlloc(alloc), Head(__CreateNodeEmplace()) {}
|
||||
|
||||
explicit forward_list(size_type count, const Allocator &alloc = Allocator())
|
||||
: NodeAlloc(alloc), Head(__CreateNodeEmplace())
|
||||
{
|
||||
node *cur = Head;
|
||||
for (size_type i = 0; i < count; ++i)
|
||||
{
|
||||
cur->Next = __CreateNode(T());
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
forward_list(size_type count, const T &value, const Allocator &alloc = Allocator())
|
||||
: NodeAlloc(alloc), Head(__CreateNodeEmplace())
|
||||
{
|
||||
node *cur = Head;
|
||||
for (size_type i = 0; i < count; ++i)
|
||||
{
|
||||
cur->Next = __CreateNode(value);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIt, typename = std::enable_if_t<!std::is_integral<InputIt>::value>>
|
||||
forward_list(InputIt first, InputIt last, const Allocator &alloc = Allocator())
|
||||
: NodeAlloc(alloc), Head(__CreateNodeEmplace())
|
||||
{
|
||||
node *cur = Head;
|
||||
for (; first != last; ++first)
|
||||
{
|
||||
cur->Next = __CreateNode(*first);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
forward_list(const forward_list &other)
|
||||
: NodeAlloc(std::allocator_traits<Allocator>::select_on_container_copy_construction(other.NodeAlloc)), Head(__CreateNodeEmplace())
|
||||
{
|
||||
node *cur = Head;
|
||||
for (node *n = other.Head->Next; n; n = n->Next)
|
||||
{
|
||||
cur->Next = __CreateNode(n->Value);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
forward_list(forward_list &&other)
|
||||
: NodeAlloc(std::move(other.NodeAlloc)), Head(other.Head)
|
||||
{
|
||||
other.Head = nullptr;
|
||||
}
|
||||
|
||||
forward_list(const forward_list &other, const std::type_identity_t<Allocator> &alloc)
|
||||
: NodeAlloc(alloc), Head(__CreateNodeEmplace())
|
||||
{
|
||||
node *cur = Head;
|
||||
for (node *n = other.Head->Next; n; n = n->Next)
|
||||
{
|
||||
cur->Next = __CreateNode(n->Value);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
forward_list(forward_list &&other, const std::type_identity_t<Allocator> &alloc)
|
||||
: NodeAlloc(alloc), Head(__CreateNodeEmplace())
|
||||
{
|
||||
if (other.empty())
|
||||
return;
|
||||
|
||||
node *cur = Head;
|
||||
for (node *n = other.Head->Next; n; n = n->Next)
|
||||
{
|
||||
cur->Next = __CreateNode(std::move(n->Value));
|
||||
cur = cur->Next;
|
||||
}
|
||||
other.clear();
|
||||
}
|
||||
|
||||
forward_list(std::initializer_list<T> init, const Allocator &alloc = Allocator())
|
||||
: NodeAlloc(alloc), Head(__CreateNodeEmplace())
|
||||
{
|
||||
node *cur = Head;
|
||||
for (const auto &v : init)
|
||||
{
|
||||
cur->Next = __CreateNode(v);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
~forward_list()
|
||||
{
|
||||
if (Head == nullptr)
|
||||
return;
|
||||
|
||||
clear();
|
||||
__DestroyNode(Head);
|
||||
Head = nullptr;
|
||||
}
|
||||
|
||||
#pragma endregion Constructors
|
||||
|
||||
forward_list &operator=(const forward_list &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
clear();
|
||||
node *cur = Head;
|
||||
for (node *n = other.Head->Next; n; n = n->Next)
|
||||
{
|
||||
cur->Next = __CreateNode(n->Value);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
forward_list &operator=(forward_list &&other) noexcept(std::allocator_traits<Allocator>::is_always_equal::value)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
clear();
|
||||
__DestroyNode(Head);
|
||||
Head = other.Head;
|
||||
NodeAlloc = std::move(other.NodeAlloc);
|
||||
other.Head = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
forward_list &operator=(std::initializer_list<value_type> ilist)
|
||||
{
|
||||
clear();
|
||||
node *cur = Head;
|
||||
for (const auto &v : ilist)
|
||||
{
|
||||
cur->Next = __CreateNode(v);
|
||||
cur = cur->Next;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void assign(size_type count, const T &value)
|
||||
{
|
||||
clear();
|
||||
node *cur = Head;
|
||||
for (size_type i = 0; i < count; ++i)
|
||||
{
|
||||
cur->Next = __CreateNode(value);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void assign(InputIt first, InputIt last)
|
||||
{
|
||||
clear();
|
||||
node *cur = Head;
|
||||
for (; first != last; ++first)
|
||||
{
|
||||
cur->Next = __CreateNode(*first);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
void assign(std::initializer_list<T> ilist)
|
||||
{
|
||||
clear();
|
||||
node *cur = Head;
|
||||
for (const auto &v : ilist)
|
||||
{
|
||||
cur->Next = __CreateNode(v);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const noexcept { return allocator_type(NodeAlloc); }
|
||||
|
||||
#pragma region Element Access
|
||||
|
||||
reference front() { return Head->Next->Value; }
|
||||
const_reference front() const { return Head->Next->Value; }
|
||||
|
||||
#pragma endregion Element Access
|
||||
|
||||
#pragma region Iterators
|
||||
|
||||
iterator before_begin() noexcept { return iterator(Head); }
|
||||
const_iterator before_begin() const noexcept { return const_iterator(Head); }
|
||||
const_iterator cbefore_begin() const noexcept { return const_iterator(Head); }
|
||||
|
||||
iterator begin() noexcept { return iterator(Head->Next); }
|
||||
const_iterator begin() const noexcept { return const_iterator(Head->Next); }
|
||||
const_iterator cbegin() const noexcept { return const_iterator(Head->Next); }
|
||||
|
||||
iterator end() noexcept { return iterator(nullptr); }
|
||||
const_iterator end() const noexcept { return const_iterator(nullptr); }
|
||||
const_iterator cend() const noexcept { return const_iterator(nullptr); }
|
||||
|
||||
#pragma endregion Iterators
|
||||
|
||||
#pragma region Capacity
|
||||
|
||||
bool empty() const noexcept { return Head->Next == nullptr; }
|
||||
size_type max_size() const noexcept { return std::numeric_limits<size_type>::max(); }
|
||||
|
||||
#pragma endregion Capacity
|
||||
|
||||
#pragma region Modifiers
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
node *cur = Head->Next;
|
||||
Head->Next = nullptr;
|
||||
__ClearNodes(cur);
|
||||
}
|
||||
|
||||
iterator insert_after(const_iterator pos, const T &value)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *n = __CreateNode(value);
|
||||
n->Next = p->Next;
|
||||
p->Next = n;
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
iterator insert_after(const_iterator pos, T &&value)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *n = __CreateNode(std::move(value));
|
||||
n->Next = p->Next;
|
||||
p->Next = n;
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
iterator insert_after(const_iterator pos, size_type count, const T &value)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *last = p;
|
||||
|
||||
for (size_type i = 0; i < count; ++i)
|
||||
{
|
||||
node *n = __CreateNode(value);
|
||||
n->Next = last->Next;
|
||||
last->Next = n;
|
||||
last = n;
|
||||
}
|
||||
|
||||
return iterator(last);
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
iterator insert_after(const_iterator pos, InputIt first, InputIt last)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *cur = p;
|
||||
|
||||
for (; first != last; ++first)
|
||||
{
|
||||
node *n = __CreateNode(*first);
|
||||
n->Next = cur->Next;
|
||||
cur->Next = n;
|
||||
cur = n;
|
||||
}
|
||||
|
||||
return iterator(cur);
|
||||
}
|
||||
|
||||
iterator insert_after(const_iterator pos, std::initializer_list<T> ilist)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *cur = p;
|
||||
|
||||
for (const auto &v : ilist)
|
||||
{
|
||||
node *n = __CreateNode(v);
|
||||
n->Next = cur->Next;
|
||||
cur->Next = n;
|
||||
cur = n;
|
||||
}
|
||||
|
||||
return iterator(cur);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
iterator emplace_after(const_iterator pos, Args &&...args)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *n = __CreateNodeEmplace(std::forward<Args>(args)...);
|
||||
n->Next = p->Next;
|
||||
p->Next = n;
|
||||
return iterator(n);
|
||||
}
|
||||
|
||||
iterator erase_after(const_iterator pos)
|
||||
{
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *to_delete = p->Next;
|
||||
|
||||
if (to_delete)
|
||||
{
|
||||
p->Next = to_delete->Next;
|
||||
__DestroyNode(to_delete);
|
||||
}
|
||||
|
||||
return iterator(p->Next);
|
||||
}
|
||||
|
||||
iterator erase_after(const_iterator first, const_iterator last)
|
||||
{
|
||||
node *p = const_cast<node *>(first.ptr);
|
||||
node *end = const_cast<node *>(last.ptr);
|
||||
node *cur = p->Next;
|
||||
|
||||
while (cur != end)
|
||||
{
|
||||
node *next = cur->Next;
|
||||
__DestroyNode(cur);
|
||||
cur = next;
|
||||
}
|
||||
|
||||
p->Next = end;
|
||||
return iterator(end);
|
||||
}
|
||||
|
||||
void push_front(const T &value) { insert_after(before_begin(), value); }
|
||||
void push_front(T &&value) { insert_after(before_begin(), std::move(value)); }
|
||||
|
||||
template <class... Args>
|
||||
reference emplace_front(Args &&...args)
|
||||
{
|
||||
iterator it = emplace_after(before_begin(), std::forward<Args>(args)...);
|
||||
return *it;
|
||||
}
|
||||
|
||||
void pop_front() { erase_after(before_begin()); }
|
||||
|
||||
void resize(size_type count) { resize(count, T()); }
|
||||
|
||||
void resize(size_type count, const value_type &value)
|
||||
{
|
||||
node *cur = Head;
|
||||
size_type n = 0;
|
||||
|
||||
while (cur->Next && n < count)
|
||||
{
|
||||
cur = cur->Next;
|
||||
++n;
|
||||
}
|
||||
|
||||
if (n == count)
|
||||
{
|
||||
/* Remove remaining */
|
||||
__ClearNodes(cur->Next);
|
||||
cur->Next = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add more */
|
||||
for (; n < count; ++n)
|
||||
{
|
||||
cur->Next = __CreateNode(value);
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void swap(forward_list &other) noexcept(std::allocator_traits<Allocator>::is_always_equal::value)
|
||||
{
|
||||
std::swap(Head, other.Head);
|
||||
/* FIXME FIXME FIXME FIXME */
|
||||
// std::swap(NodeAlloc, other.NodeAlloc);
|
||||
}
|
||||
|
||||
#pragma endregion Modifiers
|
||||
|
||||
#pragma region Operations
|
||||
|
||||
void merge(forward_list &other) { merge(other, std::less<T>()); }
|
||||
void merge(forward_list &&other) { merge(other, std::less<T>()); }
|
||||
|
||||
template <class Compare>
|
||||
void merge(forward_list &other, Compare comp)
|
||||
{
|
||||
if (this == &other)
|
||||
return;
|
||||
|
||||
node *this_prev = Head;
|
||||
node *this_cur = Head->Next;
|
||||
node *other_cur = other.Head->Next;
|
||||
|
||||
while (this_cur && other_cur)
|
||||
{
|
||||
if (comp(other_cur->Value, this_cur->Value))
|
||||
{
|
||||
node *next = other_cur->Next;
|
||||
this_prev->Next = other_cur;
|
||||
other_cur->Next = this_cur;
|
||||
this_prev = other_cur;
|
||||
other_cur = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_prev = this_cur;
|
||||
this_cur = this_cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
if (other_cur)
|
||||
this_prev->Next = other_cur;
|
||||
|
||||
other.Head->Next = nullptr;
|
||||
}
|
||||
|
||||
template <class Compare>
|
||||
void merge(forward_list &&other, Compare comp) { merge(other, comp); }
|
||||
|
||||
void splice_after(const_iterator pos, forward_list &other)
|
||||
{
|
||||
if (&other == this || other.empty())
|
||||
return;
|
||||
splice_after(pos, other, other.before_begin(), other.end());
|
||||
}
|
||||
|
||||
void splice_after(const_iterator pos, forward_list &&other) { splice_after(pos, other); }
|
||||
void splice_after(const_iterator pos, forward_list &other, const_iterator it) { splice_after(pos, other, it, std::next(it)); }
|
||||
void splice_after(const_iterator pos, forward_list &&other, const_iterator it) { splice_after(pos, other, it); }
|
||||
|
||||
void splice_after(const_iterator pos, forward_list &other, const_iterator first, const_iterator last)
|
||||
{
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
node *p = const_cast<node *>(pos.ptr);
|
||||
node *f = const_cast<node *>(first.ptr);
|
||||
node *l = const_cast<node *>(last.ptr);
|
||||
|
||||
node *start = f->Next;
|
||||
node *end = start;
|
||||
|
||||
if (!start)
|
||||
return;
|
||||
|
||||
while (end->Next && end->Next != l)
|
||||
end = end->Next;
|
||||
|
||||
f->Next = l;
|
||||
node *after = p->Next;
|
||||
p->Next = start;
|
||||
end->Next = after;
|
||||
}
|
||||
|
||||
void splice_after(const_iterator pos, forward_list &&other, const_iterator first, const_iterator last)
|
||||
{
|
||||
splice_after(pos, other, first, last);
|
||||
}
|
||||
|
||||
size_type remove(const T &value)
|
||||
{
|
||||
size_type count = 0;
|
||||
node *prev = Head;
|
||||
node *cur = Head->Next;
|
||||
while (cur)
|
||||
{
|
||||
if (cur->Value == value)
|
||||
{
|
||||
node *to_delete = cur;
|
||||
prev->Next = cur->Next;
|
||||
cur = cur->Next;
|
||||
__DestroyNode(to_delete);
|
||||
++count;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = cur;
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class UnaryPred>
|
||||
size_type remove_if(UnaryPred p)
|
||||
{
|
||||
size_type count = 0;
|
||||
node *prev = Head;
|
||||
node *cur = Head->Next;
|
||||
while (cur)
|
||||
{
|
||||
if (p(cur->Value))
|
||||
{
|
||||
node *to_delete = cur;
|
||||
prev->Next = cur->Next;
|
||||
cur = cur->Next;
|
||||
__DestroyNode(to_delete);
|
||||
++count;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = cur;
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void reverse() noexcept
|
||||
{
|
||||
node *prev = nullptr;
|
||||
node *cur = Head->Next;
|
||||
while (cur)
|
||||
{
|
||||
node *next = cur->Next;
|
||||
cur->Next = prev;
|
||||
prev = cur;
|
||||
cur = next;
|
||||
}
|
||||
Head->Next = prev;
|
||||
}
|
||||
|
||||
size_type unique() { return unique(std::equal_to<T>()); }
|
||||
|
||||
template <class BinaryPred>
|
||||
size_type unique(BinaryPred p)
|
||||
{
|
||||
size_type count = 0;
|
||||
node *cur = Head->Next;
|
||||
while (cur && cur->Next)
|
||||
{
|
||||
if (p(cur->Value, cur->Next->Value))
|
||||
{
|
||||
node *to_delete = cur->Next;
|
||||
cur->Next = to_delete->Next;
|
||||
__DestroyNode(to_delete);
|
||||
++count;
|
||||
}
|
||||
else
|
||||
cur = cur->Next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void sort() { sort(std::less<T>()); }
|
||||
|
||||
template <class Compare>
|
||||
void sort(Compare comp)
|
||||
{
|
||||
if (!Head->Next || !Head->Next->Next)
|
||||
return;
|
||||
|
||||
std::vector<T> vec;
|
||||
for (node *cur = Head->Next; cur; cur = cur->Next)
|
||||
vec.push_back(cur->Value);
|
||||
|
||||
std::sort(vec.begin(), vec.end(), comp);
|
||||
node *cur = Head->Next;
|
||||
for (auto &v : vec)
|
||||
{
|
||||
cur->Value = v;
|
||||
cur = cur->Next;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion Operations
|
||||
};
|
||||
|
||||
template <class T, class Alloc>
|
||||
bool operator==(const std::forward_list<T, Alloc> &lhs, const std::forward_list<T, Alloc> &rhs)
|
||||
{
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
template <class T, class Alloc>
|
||||
auto operator<=>(const std::forward_list<T, Alloc> &lhs, const std::forward_list<T, Alloc> &rhs)
|
||||
{
|
||||
return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), __synth_three_way);
|
||||
}
|
||||
}
|
@@ -18,7 +18,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
namespace std
|
||||
@@ -249,4 +248,4 @@ namespace std
|
||||
typedef pair<first_type, second_type> pair_type;
|
||||
return pair_type(std::forward<T1>(t), std::forward<T2>(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
92
Kernel/tests/stl/foward_list.cpp
Normal file
92
Kernel/tests/stl/foward_list.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <foward_list>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
void test_stl_forward_list()
|
||||
{
|
||||
debug("Running forward_list tests...");
|
||||
|
||||
std::forward_list<int> fl1(3, 7);
|
||||
assert(std::distance(fl1.begin(), fl1.end()) == 3);
|
||||
for (int v : fl1)
|
||||
assert(v == 7);
|
||||
|
||||
fl1.assign({1, 2, 3});
|
||||
assert(std::distance(fl1.begin(), fl1.end()) == 3);
|
||||
assert(*fl1.begin() == 1);
|
||||
|
||||
auto alloc = fl1.get_allocator();
|
||||
int *test = alloc.allocate(1);
|
||||
alloc.deallocate(test, 1);
|
||||
|
||||
assert(fl1.front() == 9 || fl1.front() == 1);
|
||||
|
||||
auto before = fl1.before_begin();
|
||||
auto begin = fl1.begin();
|
||||
auto end = fl1.end();
|
||||
assert(std::distance(begin, end) >= 0);
|
||||
|
||||
assert(!fl1.empty());
|
||||
assert(fl1.max_size() > 0);
|
||||
|
||||
fl1.insert_after(before, 42);
|
||||
fl1.emplace_after(fl1.begin(), 99);
|
||||
|
||||
fl1.erase_after(fl1.begin());
|
||||
|
||||
fl1.emplace_front(88);
|
||||
fl1.pop_front();
|
||||
|
||||
fl1.resize(5, -1);
|
||||
fl1.resize(2);
|
||||
|
||||
std::forward_list<int> fl2 = {100, 200};
|
||||
fl1.swap(fl2);
|
||||
assert(*fl1.begin() == 100);
|
||||
|
||||
std::forward_list<int> a = {1, 3, 5};
|
||||
std::forward_list<int> b = {2, 4, 6};
|
||||
a.merge(b);
|
||||
assert(std::is_sorted(a.begin(), a.end()));
|
||||
|
||||
std::forward_list<int> src = {9, 8};
|
||||
a.splice_after(a.before_begin(), src);
|
||||
assert(*a.begin() == 9);
|
||||
|
||||
a.remove(3);
|
||||
a.remove_if([](int x)
|
||||
{ return x == 5; });
|
||||
|
||||
a.reverse();
|
||||
|
||||
a.push_front(2);
|
||||
a.push_front(2);
|
||||
a.unique();
|
||||
|
||||
a.sort();
|
||||
assert(std::is_sorted(a.begin(), a.end()));
|
||||
|
||||
debug("All forward_list tests passed.");
|
||||
}
|
||||
|
||||
#endif
|
32
Kernel/tests/stl/is_sorted.cpp
Normal file
32
Kernel/tests/stl/is_sorted.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
void test_stl_is_sorted()
|
||||
{
|
||||
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
assert(std::is_sorted(a, a + (sizeof(a) / sizeof(int))));
|
||||
|
||||
int b[] = {1, 2, 3, 4, 5, 6, 7, 8, 10, 9};
|
||||
assert(!std::is_sorted(b, b + (sizeof(b) / sizeof(int))));
|
||||
}
|
||||
|
||||
#endif
|
@@ -26,6 +26,8 @@ void test_stl_bitset();
|
||||
void test_stl_string();
|
||||
void test_stl_unordered_map() {}
|
||||
void test_stl_future();
|
||||
void test_stl_forward_list();
|
||||
void test_stl_is_sorted();
|
||||
void test_stl_array();
|
||||
void test_stl_shared_ptr();
|
||||
void test_stl_set();
|
||||
@@ -42,6 +44,8 @@ void Test_stl()
|
||||
test_stl_string();
|
||||
test_stl_unordered_map();
|
||||
test_stl_future();
|
||||
test_stl_forward_list();
|
||||
test_stl_is_sorted();
|
||||
test_stl_array();
|
||||
test_stl_shared_ptr();
|
||||
test_stl_set();
|
||||
|
Reference in New Issue
Block a user