Squash commits for public release
This commit is contained in:
14
libs/libcxx/include/__config
Normal file
14
libs/libcxx/include/__config
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX___CONFIG
|
||||
#define _LIBCXX___CONFIG
|
||||
|
||||
#define _LIBCXX_BEGIN_NAMESPACE_STD namespace std {
|
||||
#define _LIBCXX_END_NAMESPACE_STD }
|
||||
|
||||
#define _LIBCXX_BEGIN_XOS_EXTENSION inline namespace xos {
|
||||
#define _LIBCXX_END_XOS_EXTENSION }
|
||||
|
||||
#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(alignof(x))))
|
||||
|
||||
#endif // _LIBCXX___CONFIG
|
||||
509
libs/libcxx/include/__rbtree
Normal file
509
libs/libcxx/include/__rbtree
Normal file
@@ -0,0 +1,509 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX___RBTREE
|
||||
#define _LIBCXX___RBTREE
|
||||
|
||||
#include <__config>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
template <class, class, class>
|
||||
class __rbtree;
|
||||
|
||||
template <typename T>
|
||||
class __rbtree_node {
|
||||
template <class, class, class>
|
||||
friend class __rbtree;
|
||||
|
||||
public:
|
||||
enum class Color {
|
||||
Red = 0,
|
||||
Black,
|
||||
};
|
||||
|
||||
using node_type = __rbtree_node;
|
||||
using node_pointer = node_type*;
|
||||
using value_type = T;
|
||||
using color_type = Color;
|
||||
using const_reference = const value_type&;
|
||||
|
||||
explicit __rbtree_node(const value_type& value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
explicit __rbtree_node(value_type&& value)
|
||||
: m_value(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
~__rbtree_node() = default;
|
||||
|
||||
void set_parent(node_pointer pc) { m_parent = pc; }
|
||||
void set_left_child(node_pointer lc) { m_left_child = lc; }
|
||||
void set_right_child(node_pointer rc) { m_right_child = rc; }
|
||||
void set_color(color_type cl) { m_color = cl; }
|
||||
void set_value(const_reference val) { m_value = val; }
|
||||
void set_value(value_type&& val) { m_value = std::move(val); }
|
||||
|
||||
node_pointer left_child() const { return m_left_child; }
|
||||
node_pointer right_child() const { return m_right_child; }
|
||||
node_pointer parent() const { return m_parent; }
|
||||
color_type color() const { return m_color; }
|
||||
|
||||
bool is_red() const { return color() == color_type::Red; }
|
||||
bool is_black() const { return color() == color_type::Black; }
|
||||
bool is_nil_node() const { return m_is_nil_node; }
|
||||
const_reference value() const { return m_value; }
|
||||
value_type& value() { return m_value; }
|
||||
|
||||
protected:
|
||||
__rbtree_node(bool is_nil_node, color_type color)
|
||||
: m_is_nil_node(is_nil_node)
|
||||
, m_color(color)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
color_type m_color { Color::Red };
|
||||
node_pointer m_parent { nullptr };
|
||||
node_pointer m_left_child { nullptr };
|
||||
node_pointer m_right_child { nullptr };
|
||||
value_type m_value;
|
||||
bool m_is_nil_node { false };
|
||||
};
|
||||
|
||||
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>>
|
||||
class __rbtree {
|
||||
public:
|
||||
using key_type = Key;
|
||||
using value_type = Key;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using key_compare = Compare;
|
||||
using value_compare = Compare;
|
||||
using allocator_type = Allocator;
|
||||
using refernce = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using node_type = __rbtree_node<value_type>;
|
||||
|
||||
private:
|
||||
using node_pointer = node_type*;
|
||||
using node_const_pointer = const node_type*;
|
||||
typedef typename std::__rebind_alloc_helper<allocator_type, node_type>::type node_alloc_type;
|
||||
|
||||
public:
|
||||
__rbtree()
|
||||
: m_nil_node(true, node_type::Color::Black)
|
||||
{
|
||||
m_root = nil_node();
|
||||
}
|
||||
|
||||
__rbtree(const Compare& comp, const Allocator& alloc = Allocator())
|
||||
: m_comp(comp)
|
||||
, m_allocator(alloc)
|
||||
, m_nil_node(true, node_type::Color::Black)
|
||||
{
|
||||
m_root = nil_node();
|
||||
}
|
||||
|
||||
explicit __rbtree(const Allocator& alloc)
|
||||
: m_allocator(alloc)
|
||||
, m_nil_node(true, node_type::Color::Black)
|
||||
{
|
||||
m_root = nil_node();
|
||||
}
|
||||
|
||||
// TODO: Return std::pair<iterator, bool>
|
||||
inline bool insert(const value_type& value) { return insert(value_type(value)); }
|
||||
inline bool insert(value_type&& value)
|
||||
{
|
||||
node_pointer new_node = _btree_insert(std::move(value));
|
||||
if (!new_node) {
|
||||
return false;
|
||||
}
|
||||
m_size++;
|
||||
|
||||
balance_after_insert(new_node);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class EqComp>
|
||||
size_type erase(const_reference value, EqComp comp) { return erase_node(_btree_find(value, comp)); }
|
||||
size_type erase(const_reference value) { return erase_node(_btree_find(value)); }
|
||||
|
||||
pointer find(const_reference value)
|
||||
{
|
||||
node_pointer res = _btree_find(value);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
return &res->m_value;
|
||||
}
|
||||
|
||||
template <class EqComp>
|
||||
pointer find(const_reference value, EqComp comp)
|
||||
{
|
||||
node_pointer res = _btree_find(value, comp);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
return &res->m_value;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const noexcept { return m_allocator; }
|
||||
size_type size() const { return m_size; }
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
private:
|
||||
bool is_root(node_pointer node) const { return node == m_root; }
|
||||
|
||||
inline bool is_left_child(node_pointer of_node) const
|
||||
{
|
||||
if (!of_node->parent()) {
|
||||
return false;
|
||||
}
|
||||
return of_node->parent()->left_child() == of_node;
|
||||
}
|
||||
|
||||
inline bool is_right_child(node_pointer of_node) const
|
||||
{
|
||||
if (!of_node->parent()) {
|
||||
return false;
|
||||
}
|
||||
return of_node->parent()->right_child() == of_node;
|
||||
}
|
||||
|
||||
// Warning: it does NOT check correctness!
|
||||
inline bool has_uncle(node_pointer of_node) const { return !!uncle(of_node); }
|
||||
inline node_pointer uncle(node_pointer of_node) const
|
||||
{
|
||||
if (of_node->parent()->parent()->left_child() == of_node->parent()) {
|
||||
return of_node->parent()->parent()->right_child();
|
||||
} else {
|
||||
return of_node->parent()->parent()->left_child();
|
||||
}
|
||||
}
|
||||
|
||||
void balance_after_insert(node_pointer new_node)
|
||||
{
|
||||
while (!is_root(new_node) && new_node->parent()->is_red()) {
|
||||
if (has_uncle(new_node) && uncle(new_node)->is_red()) {
|
||||
new_node->parent()->set_color(node_type::Color::Black);
|
||||
new_node->parent()->parent()->set_color(node_type::Color::Red);
|
||||
uncle(new_node)->set_color(node_type::Color::Black);
|
||||
new_node = new_node->parent()->parent();
|
||||
} else {
|
||||
if (is_left_child(new_node->parent())) {
|
||||
if (is_right_child(new_node)) {
|
||||
new_node = new_node->parent();
|
||||
rotate<RotateType::Left>(new_node);
|
||||
}
|
||||
new_node->parent()->set_color(node_type::Color::Black);
|
||||
new_node->parent()->parent()->set_color(node_type::Color::Red);
|
||||
rotate<RotateType::Right>(new_node->parent()->parent());
|
||||
} else {
|
||||
if (is_left_child(new_node)) {
|
||||
new_node = new_node->parent();
|
||||
rotate<RotateType::Right>(new_node);
|
||||
}
|
||||
new_node->parent()->set_color(node_type::Color::Black);
|
||||
new_node->parent()->parent()->set_color(node_type::Color::Red);
|
||||
rotate<RotateType::Left>(new_node->parent()->parent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_root->set_color(node_type::Color::Black);
|
||||
}
|
||||
|
||||
void balance_after_delete(node_pointer node)
|
||||
{
|
||||
while (!is_root(node) && node->is_black()) {
|
||||
if (is_left_child(node)) {
|
||||
node_pointer brother = node->parent()->right_child();
|
||||
if (brother && brother->is_red()) {
|
||||
brother->set_color(node_type::Color::Black);
|
||||
node->parent()->set_color(node_type::Color::Red);
|
||||
rotate<RotateType::Left>(node->parent());
|
||||
brother = node->parent()->right_child();
|
||||
}
|
||||
if (brother->left_child()->is_black() && brother->right_child()->is_black()) {
|
||||
brother->set_color(node_type::Color::Red);
|
||||
node = node->parent();
|
||||
} else {
|
||||
if (brother->right_child()->is_black()) {
|
||||
brother->left_child()->set_color(node_type::Color::Black);
|
||||
brother->set_color(node_type::Color::Red);
|
||||
rotate<RotateType::Right>(brother);
|
||||
brother = node->parent()->right_child();
|
||||
}
|
||||
brother->set_color(node->parent()->color());
|
||||
node->parent()->set_color(node_type::Color::Black);
|
||||
brother->right_child()->set_color(node_type::Color::Black);
|
||||
rotate<RotateType::Left>(node->parent());
|
||||
node = m_root;
|
||||
}
|
||||
} else {
|
||||
node_pointer brother = node->parent()->left_child();
|
||||
if (brother && brother->is_red()) {
|
||||
brother->set_color(node_type::Color::Black);
|
||||
node->parent()->set_color(node_type::Color::Red);
|
||||
rotate<RotateType::Right>(node->parent());
|
||||
brother = node->parent()->left_child();
|
||||
}
|
||||
if (brother->left_child()->is_black() && brother->right_child()->is_black()) {
|
||||
brother->set_color(node_type::Color::Red);
|
||||
node = node->parent();
|
||||
} else {
|
||||
if (brother->left_child()->is_black()) {
|
||||
brother->right_child()->set_color(node_type::Color::Black);
|
||||
brother->set_color(node_type::Color::Red);
|
||||
rotate<RotateType::Left>(brother);
|
||||
brother = node->parent()->left_child();
|
||||
}
|
||||
brother->set_color(node->parent()->color());
|
||||
node->parent()->set_color(node_type::Color::Black);
|
||||
brother->left_child()->set_color(node_type::Color::Black);
|
||||
rotate<RotateType::Right>(node->parent());
|
||||
node = m_root;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_root->set_color(node_type::Color::Black);
|
||||
}
|
||||
|
||||
enum class RotateType {
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
template <RotateType rt>
|
||||
constexpr void rotate(node_pointer node)
|
||||
{
|
||||
if constexpr (rt == RotateType::Left) {
|
||||
// p <-(node) b
|
||||
// a b ----> p d
|
||||
// c d c a
|
||||
if (node->right_child()->is_nil_node()) {
|
||||
return;
|
||||
}
|
||||
|
||||
node_pointer node_p = node;
|
||||
node_pointer node_a = node->left_child();
|
||||
node_pointer node_b = node->right_child();
|
||||
node_pointer node_c = node_b->left_child();
|
||||
|
||||
node_b->set_left_child(node_p);
|
||||
node_b->set_parent(node_p->parent());
|
||||
if (node_p->parent()) {
|
||||
if (is_left_child(node_p)) {
|
||||
node_p->parent()->set_left_child(node_b);
|
||||
} else {
|
||||
node_p->parent()->set_right_child(node_b);
|
||||
}
|
||||
}
|
||||
node_p->set_parent(node_b);
|
||||
|
||||
node_p->set_right_child(node_c);
|
||||
node_c->set_parent(node_p);
|
||||
|
||||
if (is_root(node_p)) {
|
||||
m_root = node_b;
|
||||
}
|
||||
} else if constexpr (rt == RotateType::Right) {
|
||||
// p <-(node) a
|
||||
// a b ----> c p
|
||||
// c d d b
|
||||
if (node->left_child()->is_nil_node()) {
|
||||
return;
|
||||
}
|
||||
|
||||
node_pointer node_p = node;
|
||||
node_pointer node_a = node->left_child();
|
||||
node_pointer node_c = node_a->left_child();
|
||||
node_pointer node_d = node_a->right_child();
|
||||
|
||||
node_a->set_right_child(node_p);
|
||||
node_a->set_parent(node_p->parent());
|
||||
if (node_p->parent()) {
|
||||
if (is_left_child(node_p)) {
|
||||
node_p->parent()->set_left_child(node_a);
|
||||
} else {
|
||||
node_p->parent()->set_right_child(node_a);
|
||||
}
|
||||
}
|
||||
node_p->set_parent(node_a);
|
||||
|
||||
node->set_left_child(node_d);
|
||||
node_d->set_parent(node_p);
|
||||
|
||||
if (is_root(node_p)) {
|
||||
m_root = node_a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_type erase_node(node_pointer node_to_delete)
|
||||
{
|
||||
if (!node_to_delete || node_to_delete->is_nil_node()) {
|
||||
return 0;
|
||||
}
|
||||
m_size--;
|
||||
|
||||
auto children_count = [](node_pointer node) -> size_t {
|
||||
return (size_t)(!node->left_child()->is_nil_node()) + (size_t)(!node->right_child()->is_nil_node());
|
||||
};
|
||||
|
||||
auto destroy_node = [this](node_pointer node) {
|
||||
if (node && node->is_nil_node()) {
|
||||
return;
|
||||
}
|
||||
std::destroy_at(node);
|
||||
this->m_node_allocator.deallocate(node, 1);
|
||||
};
|
||||
|
||||
if (children_count(node_to_delete) == 0) {
|
||||
if (is_root(node_to_delete)) {
|
||||
m_root = nil_node();
|
||||
} else {
|
||||
if (is_left_child(node_to_delete)) {
|
||||
node_to_delete->parent()->set_left_child(nil_node());
|
||||
} else {
|
||||
node_to_delete->parent()->set_right_child(nil_node());
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
node_pointer left_most = _btree_left_most(node_to_delete->right_child());
|
||||
node_pointer child = left_most->right_child();
|
||||
if (left_most == nil_node()) {
|
||||
child = nil_node();
|
||||
left_most = node_to_delete->left_child();
|
||||
}
|
||||
|
||||
child->set_parent(left_most->parent());
|
||||
if (is_root(left_most)) {
|
||||
m_root = child;
|
||||
} else {
|
||||
if (is_left_child(left_most)) {
|
||||
left_most->parent()->set_left_child(child);
|
||||
} else {
|
||||
left_most->parent()->set_right_child(child);
|
||||
}
|
||||
}
|
||||
|
||||
if (node_to_delete != left_most) {
|
||||
node_to_delete->set_value(std::move(left_most->value()));
|
||||
}
|
||||
|
||||
if (left_most->is_black()) {
|
||||
balance_after_delete(child);
|
||||
}
|
||||
|
||||
destroy_node(left_most);
|
||||
return 1;
|
||||
}
|
||||
|
||||
node_pointer _btree_insert(value_type&& value)
|
||||
{
|
||||
node_pointer new_node = m_node_allocator.allocate(1);
|
||||
if (!new_node) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::construct_at(new_node, std::move(value));
|
||||
new_node->set_parent(nil_node());
|
||||
new_node->set_left_child(nil_node());
|
||||
new_node->set_right_child(nil_node());
|
||||
|
||||
if (m_root->is_nil_node()) {
|
||||
m_root = new_node;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
node_pointer cur_node = m_root;
|
||||
while (cur_node) {
|
||||
if (m_comp(new_node->value(), cur_node->value())) {
|
||||
if (cur_node->left_child()->is_nil_node()) {
|
||||
new_node->set_parent(cur_node);
|
||||
cur_node->set_left_child(new_node);
|
||||
return new_node;
|
||||
}
|
||||
cur_node = cur_node->left_child();
|
||||
} else {
|
||||
if (cur_node->right_child()->is_nil_node()) {
|
||||
new_node->set_parent(cur_node);
|
||||
cur_node->set_right_child(new_node);
|
||||
return new_node;
|
||||
}
|
||||
cur_node = cur_node->right_child();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node_pointer _btree_find(const_reference value)
|
||||
{
|
||||
node_pointer cur_node = m_root;
|
||||
while (cur_node && !cur_node->is_nil_node()) {
|
||||
if (cur_node->value() == value) {
|
||||
return cur_node;
|
||||
}
|
||||
|
||||
if (m_comp(value, cur_node->value())) {
|
||||
cur_node = cur_node->left_child();
|
||||
} else {
|
||||
cur_node = cur_node->right_child();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class EqComp>
|
||||
node_pointer _btree_find(const_reference value, EqComp eq_comp)
|
||||
{
|
||||
node_pointer cur_node = m_root;
|
||||
while (cur_node && !cur_node->is_nil_node()) {
|
||||
if (eq_comp(cur_node->value(), value)) {
|
||||
return cur_node;
|
||||
}
|
||||
|
||||
if (m_comp(value, cur_node->value())) {
|
||||
cur_node = cur_node->left_child();
|
||||
} else {
|
||||
cur_node = cur_node->right_child();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node_pointer _btree_left_most(node_pointer node)
|
||||
{
|
||||
if (!node) {
|
||||
return nullptr;
|
||||
}
|
||||
if (node->is_nil_node()) {
|
||||
return nil_node();
|
||||
}
|
||||
|
||||
while (!node->left_child()->is_nil_node()) {
|
||||
node = node->left_child();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
node_pointer nil_node() const { return (node_pointer)&m_nil_node; }
|
||||
|
||||
node_pointer m_root { nullptr };
|
||||
size_type m_size { 0 };
|
||||
key_compare m_comp {};
|
||||
allocator_type m_allocator {};
|
||||
node_alloc_type m_node_allocator {};
|
||||
node_type m_nil_node;
|
||||
};
|
||||
|
||||
#endif // _LIBCXX___RBTREE
|
||||
56
libs/libcxx/include/__std_streambuffer
Normal file
56
libs/libcxx/include/__std_streambuffer
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX___STREAMBUFFER
|
||||
#define _LIBCXX___STREAMBUFFER
|
||||
|
||||
#include <__config>
|
||||
#include <cstdio>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class CharT>
|
||||
class __stdoutbuf : public basic_streambuf<CharT> {
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using traits_type = std::char_traits<char_type>;
|
||||
using int_type = typename traits_type::int_type;
|
||||
using pos_type = typename traits_type::pos_type;
|
||||
using off_type = typename traits_type::off_type;
|
||||
|
||||
__stdoutbuf(FILE* file)
|
||||
: basic_streambuf<char_type>()
|
||||
, m_file(file)
|
||||
{
|
||||
}
|
||||
|
||||
~__stdoutbuf() = default;
|
||||
|
||||
virtual int_type overflow(int_type c = traits_type::eof()) override
|
||||
{
|
||||
char_type ch = traits_type::to_char_type(c);
|
||||
if (traits_type::eq_int_type(c, traits_type::eof())) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
if (fwrite(&ch, sizeof(char_type), 1, m_file) != sizeof(char_type)) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
virtual int sync() override
|
||||
{
|
||||
if (fflush(m_file) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
FILE* m_file;
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX___STREAMBUFFER
|
||||
16
libs/libcxx/include/__undef_macros
Normal file
16
libs/libcxx/include/__undef_macros
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX___UNDEF_MACROS
|
||||
#define _LIBCXX___UNDEF_MACROS
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
#endif // _LIBCXX___UNDEF_MACROS
|
||||
45
libs/libcxx/include/algorithm
Normal file
45
libs/libcxx/include/algorithm
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_ALGORITHM
|
||||
#define _LIBCXX_ALGORITHM
|
||||
|
||||
#include <__config>
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <typename T>
|
||||
static inline constexpr T min(const T& a, const T& b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline constexpr T max(const T& a, const T& b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
template <class Iter, class T>
|
||||
static constexpr Iter find(Iter first, Iter last, const T& value)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
if (*first == value) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
template <class InputIter, class OutputIter>
|
||||
static constexpr OutputIter copy(InputIter first, InputIter last, OutputIter dist)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
*dist++ = *first;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_ALGORITHM
|
||||
20
libs/libcxx/include/bit
Normal file
20
libs/libcxx/include/bit
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_BIT
|
||||
#define _LIBCXX_BIT
|
||||
|
||||
#include <__config>
|
||||
#include <__undef_macros>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
enum class endian {
|
||||
little = __ORDER_LITTLE_ENDIAN__,
|
||||
big = __ORDER_BIG_ENDIAN__,
|
||||
native = __BYTE_ORDER__
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_BIT
|
||||
8
libs/libcxx/include/cassert
Normal file
8
libs/libcxx/include/cassert
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CASSERT
|
||||
#define _LIBCXX_CASSERT
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#endif // _LIBCXX_CASSERT
|
||||
27
libs/libcxx/include/cctype
Normal file
27
libs/libcxx/include/cctype
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CCTYPE
|
||||
#define _LIBCXX_CCTYPE
|
||||
|
||||
#include <__config>
|
||||
#include <ctype.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::isalnum;
|
||||
using ::isalpha;
|
||||
using ::iscntrl;
|
||||
using ::isdigit;
|
||||
using ::isgraph;
|
||||
using ::islower;
|
||||
using ::isprint;
|
||||
using ::ispunct;
|
||||
using ::isspace;
|
||||
using ::isupper;
|
||||
using ::isxdigit;
|
||||
using ::tolower;
|
||||
using ::toupper;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CCTYPE
|
||||
16
libs/libcxx/include/csetjmp
Normal file
16
libs/libcxx/include/csetjmp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSETJMP
|
||||
#define _LIBCXX_CSETJMP
|
||||
|
||||
#include <__config>
|
||||
#include <setjmp.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::jmp_buf;
|
||||
using ::longjmp;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSETJMP
|
||||
17
libs/libcxx/include/csignal
Normal file
17
libs/libcxx/include/csignal
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSIGNAL
|
||||
#define _LIBCXX_CSIGNAL
|
||||
|
||||
#include <__config>
|
||||
#include <signal.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::kill;
|
||||
using ::raise;
|
||||
using ::sigaction;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSIGNAL
|
||||
18
libs/libcxx/include/cstddef
Normal file
18
libs/libcxx/include/cstddef
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSTDDEF
|
||||
#define _LIBCXX_CSTDDEF
|
||||
|
||||
#include <__config>
|
||||
#include <stddef.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::ptrdiff_t;
|
||||
using ::size_t;
|
||||
using ::ssize_t;
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSTDDEF
|
||||
40
libs/libcxx/include/cstdint
Normal file
40
libs/libcxx/include/cstdint
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSTDINT
|
||||
#define _LIBCXX_CSTDINT
|
||||
|
||||
#include <__config>
|
||||
#include <stdint.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::int8_t;
|
||||
using ::int16_t;
|
||||
using ::int32_t;
|
||||
using ::int64_t;
|
||||
using ::uint8_t;
|
||||
using ::uint16_t;
|
||||
using ::uint32_t;
|
||||
using ::uint64_t;
|
||||
|
||||
using ::int_least8_t;
|
||||
using ::int_least16_t;
|
||||
using ::int_least32_t;
|
||||
using ::int_least64_t;
|
||||
using ::uint_least8_t;
|
||||
using ::uint_least16_t;
|
||||
using ::uint_least32_t;
|
||||
using ::uint_least64_t;
|
||||
|
||||
using ::int_fast8_t;
|
||||
using ::int_fast16_t;
|
||||
using ::int_fast32_t;
|
||||
using ::int_fast64_t;
|
||||
using ::uint_fast8_t;
|
||||
using ::uint_fast16_t;
|
||||
using ::uint_fast32_t;
|
||||
using ::uint_fast64_t;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSTDINT
|
||||
33
libs/libcxx/include/cstdio
Normal file
33
libs/libcxx/include/cstdio
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSTDIO
|
||||
#define _LIBCXX_CSTDIO
|
||||
|
||||
#include <__config>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::fclose;
|
||||
using ::FILE;
|
||||
using ::fopen;
|
||||
|
||||
using ::setbuf;
|
||||
using ::setlinebuf;
|
||||
using ::setvbuf;
|
||||
|
||||
using ::fprintf;
|
||||
using ::printf;
|
||||
using ::snprintf;
|
||||
using ::sprintf;
|
||||
using ::vsnprintf;
|
||||
using ::vsprintf;
|
||||
|
||||
using ::scanf;
|
||||
using ::sscanf;
|
||||
using ::vsscanf;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSTDIO
|
||||
27
libs/libcxx/include/cstdlib
Normal file
27
libs/libcxx/include/cstdlib
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSTDLIB
|
||||
#define _LIBCXX_CSTDLIB
|
||||
|
||||
#include <__config>
|
||||
#include <stdlib.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::abort;
|
||||
using ::abs;
|
||||
using ::atoi;
|
||||
using ::calloc;
|
||||
using ::exit;
|
||||
using ::free;
|
||||
using ::malloc;
|
||||
using ::posix_openpt;
|
||||
using ::ptsname;
|
||||
using ::ptsname_r;
|
||||
using ::qsort;
|
||||
using ::realloc;
|
||||
using ::strtol;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSTDLIB
|
||||
31
libs/libcxx/include/cstring
Normal file
31
libs/libcxx/include/cstring
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CSTRING
|
||||
#define _LIBCXX_CSTRING
|
||||
|
||||
#include <__config>
|
||||
#include <string.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::memccpy;
|
||||
using ::memchr;
|
||||
using ::memcmp;
|
||||
using ::memcpy;
|
||||
using ::memmove;
|
||||
using ::memset;
|
||||
using ::strcat;
|
||||
using ::strchr;
|
||||
using ::strcmp;
|
||||
using ::strcpy;
|
||||
using ::strlen;
|
||||
using ::strncmp;
|
||||
using ::strncpy;
|
||||
using ::strrchr;
|
||||
using ::strstr;
|
||||
using ::strtok;
|
||||
using ::strtok_r;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CSTRING
|
||||
27
libs/libcxx/include/ctime
Normal file
27
libs/libcxx/include/ctime
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_CTIME
|
||||
#define _LIBCXX_CTIME
|
||||
|
||||
#include <__config>
|
||||
#include <time.h>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::clock_getres;
|
||||
using ::clock_gettime;
|
||||
using ::clock_settime;
|
||||
using ::gmtime;
|
||||
using ::gmtime_r;
|
||||
using ::localtime;
|
||||
using ::localtime_r;
|
||||
using ::mktime;
|
||||
using ::nanosleep;
|
||||
using ::strftime;
|
||||
using ::time;
|
||||
using ::time_t;
|
||||
using ::timespec;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_CTIME
|
||||
154
libs/libcxx/include/functional
Normal file
154
libs/libcxx/include/functional
Normal file
@@ -0,0 +1,154 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_FUNCTIONAL
|
||||
#define _LIBCXX_FUNCTIONAL
|
||||
|
||||
#include <__config>
|
||||
#include <memory>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <typename>
|
||||
class function;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class function<R(Args...)> {
|
||||
public:
|
||||
using result_type = R;
|
||||
|
||||
function() = default;
|
||||
function(std::nullptr_t) { }
|
||||
|
||||
template <typename Functor>
|
||||
function(Functor f)
|
||||
: m_constructor(reinterpret_cast<_constructor>(construct_functor<Functor>))
|
||||
, m_destroyer(reinterpret_cast<_destroyer>(destroy_functor<Functor>))
|
||||
, m_invoker(reinterpret_cast<_invoker>(invoke_functor<Functor>))
|
||||
, m_functor_size(sizeof(Functor))
|
||||
{
|
||||
m_functor.reset(m_allocator.allocate(m_functor_size));
|
||||
m_constructor(m_functor.get(), &f);
|
||||
}
|
||||
|
||||
function(const function& other)
|
||||
: m_constructor(other.m_constructor)
|
||||
, m_destroyer(other.m_destroyer)
|
||||
, m_invoker(other.m_invoker)
|
||||
, m_functor_size(other.m_functor_size)
|
||||
{
|
||||
if (m_invoker && m_functor_size) {
|
||||
m_functor.reset(m_allocator.allocate(m_functor_size));
|
||||
m_constructor(m_functor.get(), other.m_functor.get());
|
||||
}
|
||||
}
|
||||
|
||||
function& operator=(const function& other)
|
||||
{
|
||||
m_constructor = other.m_constructor;
|
||||
m_destroyer = other.m_destroyer;
|
||||
m_invoker = other.m_invoker;
|
||||
m_functor_size = other.m_functor_size;
|
||||
if (m_invoker && m_functor_size) {
|
||||
m_functor.reset(m_allocator.allocate(m_functor_size));
|
||||
m_constructor(m_functor.get(), other.m_functor.get());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~function()
|
||||
{
|
||||
if (m_functor) {
|
||||
m_destroyer(m_functor.get());
|
||||
}
|
||||
}
|
||||
|
||||
result_type operator()(Args&&... args)
|
||||
{
|
||||
return m_invoker(m_functor.get(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
operator bool() { return !!m_functor; }
|
||||
|
||||
private:
|
||||
using _alloc_type = char;
|
||||
using _invoker = R (*)(void*, Args&&...);
|
||||
using _constructor = void (*)(void*, void*);
|
||||
using _destroyer = void (*)(void*);
|
||||
|
||||
template <typename Functor>
|
||||
static void construct_functor(Functor* at, Functor* other)
|
||||
{
|
||||
construct_at(at, *other);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
static void destroy_functor(Functor* p)
|
||||
{
|
||||
destroy_at(p);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
static result_type invoke_functor(Functor* functor, Args&&... args)
|
||||
{
|
||||
return (*functor)(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
_invoker m_invoker { nullptr };
|
||||
_constructor m_constructor { nullptr };
|
||||
_destroyer m_destroyer { nullptr };
|
||||
std::unique_ptr<_alloc_type> m_functor { nullptr };
|
||||
size_t m_functor_size { 0 };
|
||||
std::allocator<_alloc_type> m_allocator {};
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct less {
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct greater {
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs > rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct equal_to {
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct less_equal {
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs <= rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct greater_equal {
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs >= rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T = void>
|
||||
struct not_equal_to {
|
||||
constexpr bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs != rhs;
|
||||
}
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_FUNCTIONAL
|
||||
122
libs/libcxx/include/ios
Normal file
122
libs/libcxx/include/ios
Normal file
@@ -0,0 +1,122 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_IOS
|
||||
#define _LIBCXX_IOS
|
||||
|
||||
#include <__config>
|
||||
#include <iosfwd>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
typedef size_t streamsize;
|
||||
|
||||
class ios_base {
|
||||
public:
|
||||
typedef uint32_t openmode;
|
||||
static constexpr openmode app = 0x1;
|
||||
static constexpr openmode binary = 0x2;
|
||||
static constexpr openmode in = 0x4;
|
||||
static constexpr openmode out = 0x8;
|
||||
static constexpr openmode trunc = 0x10;
|
||||
static constexpr openmode ate = 0x20;
|
||||
|
||||
typedef uint32_t fmtflags;
|
||||
static constexpr fmtflags dec = 0x1;
|
||||
static constexpr fmtflags oct = 0x2;
|
||||
static constexpr fmtflags hex = 0x4;
|
||||
static constexpr fmtflags basefield = dec | oct | hex;
|
||||
static constexpr fmtflags left = 0x8;
|
||||
static constexpr fmtflags right = 0x10;
|
||||
static constexpr fmtflags internal = 0x20;
|
||||
static constexpr fmtflags adjustfield = left | right | internal;
|
||||
static constexpr fmtflags scientific = 0x40;
|
||||
static constexpr fmtflags fixed = 0x80;
|
||||
static constexpr fmtflags floatfield = scientific | fixed;
|
||||
static constexpr fmtflags boolalpha = 0x100;
|
||||
static constexpr fmtflags showbase = 0x200;
|
||||
static constexpr fmtflags showpoint = 0x400;
|
||||
static constexpr fmtflags showpos = 0x800;
|
||||
static constexpr fmtflags skipws = 0x1000;
|
||||
static constexpr fmtflags unitbuf = 0x2000;
|
||||
static constexpr fmtflags uppercase = 0x4000;
|
||||
|
||||
typedef uint32_t iostate;
|
||||
static constexpr iostate goodbit = 0x0;
|
||||
static constexpr iostate badbit = 0x1;
|
||||
static constexpr iostate failbit = 0x2;
|
||||
static constexpr iostate eofbit = 0x4;
|
||||
|
||||
typedef uint32_t seekdir;
|
||||
static constexpr seekdir beg = 0x1;
|
||||
static constexpr seekdir end = 0x2;
|
||||
static constexpr seekdir cur = 0x4;
|
||||
|
||||
ios_base() = default;
|
||||
virtual ~ios_base() = default;
|
||||
|
||||
fmtflags flags() const { return m_fl; }
|
||||
fmtflags flags(fmtflags flags) { return m_fl = flags; }
|
||||
|
||||
fmtflags setf(fmtflags flags) { return m_fl |= flags; }
|
||||
fmtflags setf(fmtflags flags, fmtflags mask) { return m_fl = (m_fl & ~mask) | (flags & mask); }
|
||||
|
||||
void unsetf(fmtflags flags) { m_fl = (m_fl & ~flags); }
|
||||
|
||||
streamsize precision() const { return m_precision; }
|
||||
streamsize precision(streamsize n_p) { return m_precision = n_p; }
|
||||
|
||||
streamsize width() const { return m_width; }
|
||||
streamsize width(streamsize n_w) { return m_width = n_w; }
|
||||
|
||||
bool good() const { return rdstate() == goodbit; }
|
||||
bool eof() const { return (m_rdstate & eofbit) != 0; }
|
||||
bool fail() const { return (m_rdstate & failbit) != 0; }
|
||||
bool bad() const { return (m_rdstate & badbit) != 0; }
|
||||
bool operator!() const { return fail(); }
|
||||
explicit operator bool() const { return !fail(); }
|
||||
|
||||
iostate rdstate() const { return m_rdstate; }
|
||||
void setstate(iostate state) { m_rdstate = state; }
|
||||
void clear(iostate state = goodbit) { m_rdstate = state; }
|
||||
|
||||
// TODO: Support locales
|
||||
|
||||
private:
|
||||
fmtflags m_fl { 0 };
|
||||
iostate m_rdstate { 0 };
|
||||
iostate m_state { 0 };
|
||||
streamsize m_precision { 0 };
|
||||
streamsize m_width { 0 };
|
||||
};
|
||||
|
||||
template <class CharT, class Traits>
|
||||
class basic_ios : public ios_base {
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using traits_type = Traits;
|
||||
using int_type = typename traits_type::int_type;
|
||||
using pos_type = typename traits_type::pos_type;
|
||||
using off_type = typename traits_type::off_type;
|
||||
|
||||
explicit basic_ios(basic_streambuf<char_type, traits_type>* rdbuf)
|
||||
: ios_base()
|
||||
, m_rdbuf(rdbuf)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~basic_ios() = default;
|
||||
|
||||
basic_streambuf<CharT, Traits>* rdbuf() const { return m_rdbuf; }
|
||||
basic_streambuf<CharT, Traits>* rdbuf(basic_streambuf<CharT, Traits>* sb) { return m_rdbuf = sb; }
|
||||
// TODO: Add more API to match C++20 standard.
|
||||
|
||||
protected:
|
||||
basic_ios() = default;
|
||||
|
||||
private:
|
||||
basic_streambuf<char_type, traits_type>* m_rdbuf { nullptr };
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_IOS
|
||||
21
libs/libcxx/include/iosfwd
Normal file
21
libs/libcxx/include/iosfwd
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_IOSFWD
|
||||
#define _LIBCXX_IOSFWD
|
||||
|
||||
#include <__config>
|
||||
#include <string>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
class ios_base;
|
||||
|
||||
template <typename CharT, typename Traits = char_traits<CharT>>
|
||||
class basic_ios;
|
||||
|
||||
template <typename CharT, typename Traits = char_traits<CharT>>
|
||||
class basic_streambuf;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_IOSFWD
|
||||
17
libs/libcxx/include/iostream
Normal file
17
libs/libcxx/include/iostream
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_IOSTREAM
|
||||
#define _LIBCXX_IOSTREAM
|
||||
|
||||
#include <__config>
|
||||
#include <ostream>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
extern ostream cout;
|
||||
extern ostream cerr;
|
||||
// extern ostream clog;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_IOSTREAM
|
||||
230
libs/libcxx/include/iterator
Normal file
230
libs/libcxx/include/iterator
Normal file
@@ -0,0 +1,230 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_ITERATOR
|
||||
#define _LIBCXX_ITERATOR
|
||||
|
||||
#include <__config>
|
||||
#include <stddef.h>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct input_iterator_tag {
|
||||
};
|
||||
struct output_iterator_tag {
|
||||
};
|
||||
struct forward_iterator_tag : public input_iterator_tag {
|
||||
};
|
||||
struct bidirectional_iterator_tag : public forward_iterator_tag {
|
||||
};
|
||||
struct random_access_iterator_tag : public bidirectional_iterator_tag {
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
struct iterator_traits {
|
||||
using value_type = typename Iter::value_type;
|
||||
using difference_type = typename Iter::difference_type;
|
||||
using pointer = typename Iter::pointer;
|
||||
using reference = typename Iter::reference;
|
||||
using iterator_category = typename Iter::iterator_category;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct iterator_traits<T*> {
|
||||
using value_type = T;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class __legacy_iter {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class __legacy_iter<T*> {
|
||||
public:
|
||||
using value_type = T;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
__legacy_iter() = default;
|
||||
__legacy_iter(pointer p)
|
||||
: m_p(p)
|
||||
{
|
||||
}
|
||||
|
||||
~__legacy_iter() = default;
|
||||
|
||||
bool operator!=(const __legacy_iter& other) const { return m_p != other.m_p; }
|
||||
bool operator==(const __legacy_iter& other) const { return m_p == other.m_p; }
|
||||
bool operator<(const __legacy_iter& other) const { return m_p < other.m_p; }
|
||||
bool operator>(const __legacy_iter& other) const { return m_p > other.m_p; }
|
||||
bool operator>=(const __legacy_iter& other) const { return m_p >= other.m_p; }
|
||||
|
||||
__legacy_iter& operator++()
|
||||
{
|
||||
++m_p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__legacy_iter& operator--()
|
||||
{
|
||||
--m_p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__legacy_iter operator++(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
++m_p;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
__legacy_iter operator--(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
--m_p;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
__legacy_iter operator-(difference_type value) { return { m_p - value }; }
|
||||
__legacy_iter operator+(difference_type value) { return { m_p + value }; }
|
||||
|
||||
__legacy_iter& operator+=(difference_type value)
|
||||
{
|
||||
m_p += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__legacy_iter& operator-=(difference_type value)
|
||||
{
|
||||
m_p -= value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__legacy_iter& operator=(const __legacy_iter& other)
|
||||
{
|
||||
m_p = other.m_p;
|
||||
return *this;
|
||||
}
|
||||
reference operator*() { return *m_p; }
|
||||
difference_type operator-(const __legacy_iter& other) { return m_p - other.m_p; }
|
||||
constexpr reference operator[](difference_type n) const { return m_p[n]; }
|
||||
|
||||
private:
|
||||
pointer m_p = nullptr;
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
class reverse_iterator {
|
||||
public:
|
||||
using iterator_type = Iter;
|
||||
using value_type = typename Iter::value_type;
|
||||
using difference_type = typename Iter::difference_type;
|
||||
using pointer = typename Iter::pointer;
|
||||
using reference = typename Iter::reference;
|
||||
using iterator_category = typename Iter::iterator_category;
|
||||
|
||||
constexpr reverse_iterator() = default;
|
||||
~reverse_iterator() = default;
|
||||
|
||||
constexpr explicit reverse_iterator(iterator_type base_iter)
|
||||
: m_base(base_iter)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr iterator_type base() const { return m_base; }
|
||||
|
||||
bool operator!=(const reverse_iterator& other) const { return m_base != other.m_base; }
|
||||
bool operator==(const reverse_iterator& other) const { return m_base == other.m_base; }
|
||||
bool operator<(const reverse_iterator& other) const { return m_base < other.m_base; }
|
||||
bool operator>(const reverse_iterator& other) const { return m_base > other.m_base; }
|
||||
bool operator>=(const reverse_iterator& other) const { return m_base >= other.m_base; }
|
||||
|
||||
reverse_iterator& operator++()
|
||||
{
|
||||
--m_base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator& operator--()
|
||||
{
|
||||
++m_base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator operator++(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
--m_base;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reverse_iterator operator--(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
++m_base;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reverse_iterator operator-(difference_type value) { return { m_base + value }; }
|
||||
reverse_iterator operator+(difference_type value) { return { m_base - value }; }
|
||||
|
||||
reverse_iterator& operator+=(difference_type value)
|
||||
{
|
||||
m_base -= value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator& operator-=(difference_type value)
|
||||
{
|
||||
m_base += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reverse_iterator& operator=(const reverse_iterator& other)
|
||||
{
|
||||
m_base = other.m_base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() { return *m_base; }
|
||||
difference_type operator-(const reverse_iterator& other) { return other.m_base - m_base; }
|
||||
constexpr reference operator[](difference_type n) const { return m_base[-n]; }
|
||||
|
||||
private:
|
||||
iterator_type m_base;
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
constexpr typename iterator_traits<Iter>::difference_type distance(Iter first, Iter last)
|
||||
{
|
||||
typename iterator_traits<Iter>::difference_type res;
|
||||
while (first != last) {
|
||||
first++;
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
template <class Iter, class Distance>
|
||||
constexpr void advance(Iter& it, Distance n)
|
||||
{
|
||||
if (n > 0) {
|
||||
while (n--) {
|
||||
it++;
|
||||
}
|
||||
} else if (n < 0) {
|
||||
while (n++) {
|
||||
it--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_ITERATOR
|
||||
271
libs/libcxx/include/list
Normal file
271
libs/libcxx/include/list
Normal file
@@ -0,0 +1,271 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_LIST
|
||||
#define _LIBCXX_LIST
|
||||
|
||||
#include <__config>
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace details {
|
||||
|
||||
template <class T>
|
||||
class list_node {
|
||||
public:
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
|
||||
private:
|
||||
using __node_type = details::list_node<value_type>;
|
||||
using __node_pointer = __node_type*;
|
||||
|
||||
public:
|
||||
list_node(const_reference elem, __node_pointer next = nullptr, __node_pointer prev = nullptr)
|
||||
: m_elem(elem)
|
||||
, m_next(next)
|
||||
, m_prev(prev)
|
||||
{
|
||||
}
|
||||
|
||||
list_node(value_type&& elem, __node_pointer next = nullptr, __node_pointer prev = nullptr)
|
||||
: m_elem(std::move(elem))
|
||||
, m_next(next)
|
||||
, m_prev(prev)
|
||||
{
|
||||
}
|
||||
|
||||
~list_node() = default;
|
||||
|
||||
inline reference get() { return m_elem; }
|
||||
inline const_reference get() const { return m_elem; }
|
||||
inline reference operator*() { return m_elem; }
|
||||
inline __node_pointer next() const { return m_next; }
|
||||
inline __node_pointer prev() const { return m_prev; }
|
||||
inline void set_prev(__node_pointer prev) { m_prev = prev; };
|
||||
inline void set_next(__node_pointer next) { m_next = next; };
|
||||
|
||||
private:
|
||||
value_type m_elem;
|
||||
__node_pointer m_prev { nullptr };
|
||||
__node_pointer m_next { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Alloc>
|
||||
class list;
|
||||
|
||||
template <class T>
|
||||
class list_iter {
|
||||
template <class U, class Alloctor>
|
||||
friend class list;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
private:
|
||||
using __node_type = details::list_node<value_type>;
|
||||
using __node_pointer = __node_type*;
|
||||
|
||||
public:
|
||||
list_iter() = default;
|
||||
list_iter(nullptr_t) { }
|
||||
list_iter(__node_pointer v)
|
||||
: m_value(v)
|
||||
{
|
||||
}
|
||||
|
||||
~list_iter() = default;
|
||||
|
||||
bool operator!=(const list_iter& other) const { return m_value != other.m_value; }
|
||||
bool operator==(const list_iter& other) const { return m_value == other.m_value; }
|
||||
|
||||
list_iter& operator++()
|
||||
{
|
||||
if (m_value) {
|
||||
m_prev_value = m_value;
|
||||
m_value = m_value->next();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
list_iter& operator--()
|
||||
{
|
||||
if (m_value == end()) {
|
||||
m_value = m_prev_value;
|
||||
} else {
|
||||
m_value = m_value->prev();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
list_iter operator++(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
list_iter operator--(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
operator--();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
list_iter& operator=(const list_iter& other)
|
||||
{
|
||||
m_value = other.m_value;
|
||||
m_prev_value = other.m_prev_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() { return m_value->get(); }
|
||||
|
||||
__node_pointer end() { return nullptr; }
|
||||
|
||||
private:
|
||||
__node_pointer get_value() { return m_value; }
|
||||
|
||||
__node_pointer m_value { nullptr };
|
||||
__node_pointer m_prev_value { nullptr };
|
||||
};
|
||||
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
class list {
|
||||
public:
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using allocator_type = Allocator;
|
||||
using size_type = size_t;
|
||||
using iterator = list_iter<value_type>;
|
||||
using const_iterator = list_iter<const value_type>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
|
||||
private:
|
||||
using __node_type = details::list_node<value_type>;
|
||||
using __node_pointer = __node_type*;
|
||||
typedef typename __rebind_alloc_helper<allocator_type, __node_type>::type __node_alloc_type;
|
||||
|
||||
public:
|
||||
list() = default;
|
||||
~list() = default;
|
||||
|
||||
iterator insert(iterator pos, value_type&& value)
|
||||
{
|
||||
__node_pointer next_elem = pos.get_value();
|
||||
__node_pointer prev_elem = m_tail;
|
||||
if (next_elem) {
|
||||
prev_elem = next_elem->prev();
|
||||
}
|
||||
|
||||
__node_pointer new_elem = m_node_allocator.allocate(1);
|
||||
construct_at(new_elem, std::move(value));
|
||||
|
||||
new_elem->set_prev(prev_elem);
|
||||
if (!prev_elem) {
|
||||
m_head = new_elem;
|
||||
} else {
|
||||
prev_elem->set_next(new_elem);
|
||||
}
|
||||
|
||||
new_elem->set_next(next_elem);
|
||||
if (!next_elem) {
|
||||
m_tail = new_elem;
|
||||
} else {
|
||||
next_elem->set_prev(new_elem);
|
||||
}
|
||||
++m_size;
|
||||
|
||||
return iterator(new_elem);
|
||||
}
|
||||
|
||||
iterator insert(iterator pos, const_reference value)
|
||||
{
|
||||
return insert(pos, value_type(value));
|
||||
}
|
||||
|
||||
void push_back(const_reference value) { insert(end(), value); }
|
||||
void push_back(value_type&& value) { insert(end(), std::move(value)); }
|
||||
|
||||
void push_front(const_reference value) { insert(begin(), value); }
|
||||
void push_front(value_type&& value) { insert(begin(), std::move(value)); }
|
||||
|
||||
iterator erase(iterator pos)
|
||||
{
|
||||
__node_pointer this_elem = pos.get_value();
|
||||
if (!this_elem) {
|
||||
return end();
|
||||
}
|
||||
|
||||
__node_pointer next_elem = this_elem->next();
|
||||
__node_pointer prev_elem = this_elem->prev();
|
||||
|
||||
if (m_head == this_elem) {
|
||||
m_head = next_elem;
|
||||
}
|
||||
|
||||
if (m_tail == this_elem) {
|
||||
m_tail = prev_elem;
|
||||
}
|
||||
|
||||
if (next_elem) {
|
||||
next_elem->set_prev(prev_elem);
|
||||
}
|
||||
|
||||
if (prev_elem) {
|
||||
prev_elem->set_next(next_elem);
|
||||
}
|
||||
|
||||
destroy_at(this_elem);
|
||||
m_node_allocator.deallocate(this_elem, 1);
|
||||
--m_size;
|
||||
|
||||
return iterator(next_elem);
|
||||
}
|
||||
|
||||
void pop_back() { erase(--end()); }
|
||||
void pop_front() { erase(begin()); }
|
||||
|
||||
inline reference front() { return m_head->get(); }
|
||||
inline const_reference front() const { return m_head->get(); }
|
||||
inline reference back() { return m_tail->get(); }
|
||||
inline const_reference back() const { return m_tail->get(); }
|
||||
|
||||
inline size_type size() const { return m_size; }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
|
||||
inline iterator begin() const { return iterator(m_head); }
|
||||
inline iterator end() const { return ++iterator(m_tail); }
|
||||
|
||||
inline reverse_iterator rbegin() const { return reverse_iterator(m_tail); }
|
||||
inline reverse_iterator rend() const { return ++reverse_iterator(m_head); }
|
||||
|
||||
allocator_type allocator() const { return m_allocator; }
|
||||
|
||||
private:
|
||||
__node_alloc_type node_allocator() { return m_node_allocator; }
|
||||
|
||||
__node_pointer m_head { nullptr };
|
||||
__node_pointer m_tail { nullptr };
|
||||
size_type m_size { 0 };
|
||||
__node_alloc_type m_node_allocator {};
|
||||
allocator_type m_allocator {};
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_LIST
|
||||
106
libs/libcxx/include/map
Normal file
106
libs/libcxx/include/map
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_MAP
|
||||
#define _LIBCXX_MAP
|
||||
|
||||
#include <__config>
|
||||
#include <__rbtree>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace details {
|
||||
template <class Key, class T>
|
||||
struct map_key_finder {
|
||||
constexpr bool operator()(const std::pair<Key, T>& lhs, const std::pair<Key, T>& rhs) const
|
||||
{
|
||||
return lhs.first == rhs.first;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <class Key, class T, class Compare = std::less<std::pair<Key, T>>, class Allocator = std::allocator<std::pair<Key, T>>>
|
||||
class map {
|
||||
private:
|
||||
using __value_type = std::pair<Key, T>;
|
||||
using __tree_type = __rbtree<__value_type, Compare, Allocator>;
|
||||
|
||||
public:
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = std::pair<key_type, mapped_type>;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using key_compare = Compare;
|
||||
using value_compare = Compare;
|
||||
using allocator_type = Allocator;
|
||||
using refernce = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using node_type = typename __tree_type::node_type;
|
||||
|
||||
map()
|
||||
: m_tree()
|
||||
{
|
||||
}
|
||||
|
||||
map(const Compare& comp, const Allocator& alloc = Allocator())
|
||||
: m_tree(comp, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit map(const Allocator& alloc)
|
||||
: m_tree(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Return std::pair<iterator, bool>
|
||||
inline bool insert(const_reference value) { return m_tree.insert(value); }
|
||||
inline bool insert(value_type&& value) { return m_tree.insert(std::move(value)); }
|
||||
|
||||
inline size_type erase(const key_type& key) { return m_tree.erase({ key, T() }, details::map_key_finder<Key, T>()); }
|
||||
|
||||
inline allocator_type get_allocator() const noexcept { return m_tree.get_allocator(); }
|
||||
inline size_type size() const { return m_tree.size(); }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
|
||||
T& at(const Key& key)
|
||||
{
|
||||
// TODO: Exceptions are not supported
|
||||
pointer res = m_tree.find({ key, T() }, details::map_key_finder<Key, T>());
|
||||
if (!res) {
|
||||
m_tree.insert({ key, T() });
|
||||
res = m_tree.find({ key, T() }, details::map_key_finder<Key, T>());
|
||||
}
|
||||
|
||||
return res->second;
|
||||
}
|
||||
|
||||
const T& at(const Key& key) const
|
||||
{
|
||||
pointer res = m_tree.find({ key, T() }, details::map_key_finder<Key, T>());
|
||||
|
||||
// TODO: Exceptions are not supported, so we simply add this element for now
|
||||
if (!res) {
|
||||
m_tree.insert({ key, T() });
|
||||
res = m_tree.find({ key, T() }, details::map_key_finder<Key, T>());
|
||||
}
|
||||
|
||||
return res->second;
|
||||
}
|
||||
|
||||
T& operator[](const Key& key)
|
||||
{
|
||||
return at(key);
|
||||
}
|
||||
|
||||
private:
|
||||
__tree_type m_tree;
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_MAP
|
||||
203
libs/libcxx/include/memory
Normal file
203
libs/libcxx/include/memory
Normal file
@@ -0,0 +1,203 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_MEMORY
|
||||
#define _LIBCXX_MEMORY
|
||||
|
||||
#include <__config>
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <typename T>
|
||||
class unique_ptr {
|
||||
public:
|
||||
unique_ptr()
|
||||
: m_data(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
unique_ptr(T* data)
|
||||
: m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
unique_ptr(std::nullptr_t)
|
||||
: m_data(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
unique_ptr& operator=(std::nullptr_t)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr(unique_ptr&& moving) noexcept
|
||||
: m_data(nullptr)
|
||||
{
|
||||
moving.swap(*this);
|
||||
}
|
||||
|
||||
unique_ptr& operator=(unique_ptr&& moving) noexcept
|
||||
{
|
||||
moving.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
unique_ptr(unique_ptr<U>&& moving)
|
||||
{
|
||||
unique_ptr<T> tmp((T*)moving.release());
|
||||
tmp.swap(*this);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
unique_ptr& operator=(unique_ptr<U>&& moving)
|
||||
{
|
||||
unique_ptr<T> tmp((T*)moving.release());
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* release() noexcept
|
||||
{
|
||||
T* result = m_data;
|
||||
m_data = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void swap(unique_ptr& src) noexcept
|
||||
{
|
||||
T* tmp_data = m_data;
|
||||
m_data = src.m_data;
|
||||
src.m_data = tmp_data;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
T* tmp = release();
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
void reset(T* new_ptr)
|
||||
{
|
||||
T* tmp = release();
|
||||
delete tmp;
|
||||
m_data = new_ptr;
|
||||
}
|
||||
|
||||
~unique_ptr()
|
||||
{
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
unique_ptr(unique_ptr const&) = delete;
|
||||
unique_ptr& operator=(unique_ptr const&) = delete;
|
||||
|
||||
T* operator->() const { return m_data; }
|
||||
T& operator*() const { return *m_data; }
|
||||
|
||||
T* get() const { return m_data; }
|
||||
explicit operator bool() const { return m_data; }
|
||||
|
||||
private:
|
||||
T* m_data { nullptr };
|
||||
};
|
||||
|
||||
template <class Alloc>
|
||||
struct allocator_traits {
|
||||
using allocator_type = Alloc;
|
||||
using value_type = typename Alloc::value_type;
|
||||
using pointer = typename Alloc::pointer;
|
||||
using const_pointer = typename Alloc::const_pointer;
|
||||
using void_pointer = typename Alloc::void_pointer;
|
||||
using const_void_pointer = typename Alloc::const_void_pointer;
|
||||
using difference_type = typename Alloc::difference_type;
|
||||
using size_type = typename Alloc::size_type;
|
||||
};
|
||||
|
||||
template <class _Alloc, class S>
|
||||
struct __rebind_alloc_helper;
|
||||
|
||||
template <template <class, class...> class _Alloc, class New, class Old, class... OtherArgs>
|
||||
struct __rebind_alloc_helper<_Alloc<Old, OtherArgs...>, New> {
|
||||
typedef typename std::allocator_traits<_Alloc<New, OtherArgs...>>::allocator_type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct allocator {
|
||||
using value_type = T;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using void_pointer = void*;
|
||||
using const_void_pointer = const void*;
|
||||
using difference_type = ptrdiff_t;
|
||||
using size_type = size_t;
|
||||
|
||||
allocator() = default;
|
||||
~allocator() = default;
|
||||
|
||||
pointer allocate(size_t n)
|
||||
{
|
||||
return reinterpret_cast<pointer>(operator new(n * sizeof(T)));
|
||||
}
|
||||
|
||||
void deallocate(pointer p, size_t n)
|
||||
{
|
||||
return operator delete(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class... Args>
|
||||
static constexpr unique_ptr<T> make_unique(Args&&... args)
|
||||
{
|
||||
return new T(forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
static constexpr T* construct_at(T* p, Args&&... args)
|
||||
{
|
||||
return reinterpret_cast<T*>(new (static_cast<void*>(p)) T(forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static constexpr void destroy_at(T* p)
|
||||
{
|
||||
if constexpr (is_array_v<T>) {
|
||||
static_assert(true, "Not implemented destroy_at for arrays");
|
||||
}
|
||||
return p->~T();
|
||||
}
|
||||
|
||||
#if defined(_LIBCXX_BUILD_XOS_EXTENSIONS)
|
||||
_LIBCXX_BEGIN_XOS_EXTENSION
|
||||
|
||||
template <class T, class... Args>
|
||||
static constexpr T& construct(Args&&... args)
|
||||
{
|
||||
T* newobject = new T(forward<Args>(args)...);
|
||||
return *newobject;
|
||||
}
|
||||
|
||||
_LIBCXX_END_XOS_EXTENSION
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T* to_address(T* p)
|
||||
{
|
||||
static_assert(!is_function_v<T>);
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T* to_address(const T& p)
|
||||
{
|
||||
return to_address(p.operator->());
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_MEMORY
|
||||
106
libs/libcxx/include/new
Normal file
106
libs/libcxx/include/new
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_NEW
|
||||
#define _LIBCXX_NEW
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
enum class nothrow_t {};
|
||||
enum class align_val_t : std::size_t {};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
inline void* operator new(size_t size)
|
||||
{
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t size)
|
||||
{
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
inline void* operator new(size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
inline void* operator new(size_t size, std::align_val_t alignment)
|
||||
{
|
||||
size_t aln = static_cast<size_t>(alignment);
|
||||
void* ptr = std::malloc(size + sizeof(void*) + aln);
|
||||
size_t max_addr = (size_t)ptr + sizeof(void*) + aln;
|
||||
void* aligned_ptr = (void*)(max_addr - (max_addr % aln));
|
||||
((void**)aligned_ptr)[-1] = ptr;
|
||||
return aligned_ptr;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t size, std::align_val_t alignment)
|
||||
{
|
||||
return ::operator new(size, alignment);
|
||||
}
|
||||
|
||||
inline void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
size_t aln = static_cast<size_t>(alignment);
|
||||
void* ptr = std::malloc(size + sizeof(void*) + aln);
|
||||
size_t max_addr = (size_t)ptr + sizeof(void*) + aln;
|
||||
void* aligned_ptr = (void*)(max_addr - (max_addr % aln));
|
||||
((void**)aligned_ptr)[-1] = ptr;
|
||||
return aligned_ptr;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t& nothrow) noexcept
|
||||
{
|
||||
return ::operator new(size, alignment, nothrow);
|
||||
}
|
||||
|
||||
inline void* operator new(size_t, void* ptr) noexcept
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t, void* ptr) noexcept
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void operator delete(void* ptr) noexcept
|
||||
{
|
||||
return std::free(ptr);
|
||||
}
|
||||
|
||||
inline void operator delete(void* ptr, size_t) noexcept
|
||||
{
|
||||
return std::free(ptr);
|
||||
}
|
||||
|
||||
inline void operator delete[](void* ptr) noexcept
|
||||
{
|
||||
return std::free(ptr);
|
||||
}
|
||||
|
||||
inline void operator delete[](void* ptr, size_t) noexcept
|
||||
{
|
||||
return std::free(ptr);
|
||||
}
|
||||
|
||||
inline void operator delete(void* ptr, std::align_val_t alignment) noexcept
|
||||
{
|
||||
std::free(((void**)ptr)[-1]);
|
||||
}
|
||||
|
||||
inline void operator delete[](void* ptr, std::align_val_t alignment) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
#endif // _LIBCXX_NEW
|
||||
70
libs/libcxx/include/numbers
Normal file
70
libs/libcxx/include/numbers
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_NUMBERS
|
||||
#define _LIBCXX_NUMBERS
|
||||
|
||||
#include <__config>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace Math::Numbers {
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T e_v = 2.718281828459045235360287471352662;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T log2e_v = 1.442695040888963407359924681001892;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T log10e_v = 0.434294481903251827651128918916605;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T pi_v = 3.141592653589793238462643383279502;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T inv_pi_v = 0.318309886183790671537767526745028;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T inv_sqrtpi_v = 0.564189583547756286948079451560772;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T ln2_v = 0.693147180559945309417232121458176;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T ln10_v = 2.302585092994045684017991454684364;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T sqrt2_v = 1.414213562373095048801688724209698;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T sqrt3_v = 1.732050807568877293527446341505872;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T inv_sqrt3_v = 0.577350269189625764509148780501957;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T egamma_v = 0.577215664901532860606512090082402;
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_floating_point_v<T>>>
|
||||
inline constexpr T phi_v = 1.618033988749894848204586834365638;
|
||||
|
||||
inline constexpr double e = e_v<double>;
|
||||
inline constexpr double log2e = log2e_v<double>;
|
||||
inline constexpr double log10e = log10e_v<double>;
|
||||
inline constexpr double pi = pi_v<double>;
|
||||
inline constexpr double inv_pi = inv_pi_v<double>;
|
||||
inline constexpr double inv_sqrtpi = inv_sqrtpi_v<double>;
|
||||
inline constexpr double ln2 = ln2_v<double>;
|
||||
inline constexpr double ln10 = ln10_v<double>;
|
||||
inline constexpr double sqrt2 = sqrt2_v<double>;
|
||||
inline constexpr double sqrt3 = sqrt3_v<double>;
|
||||
inline constexpr double inv_sqrt3 = inv_sqrt3_v<double>;
|
||||
inline constexpr double egamma = egamma_v<double>;
|
||||
inline constexpr double phi = phi_v<double>;
|
||||
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_NUMBERS
|
||||
81
libs/libcxx/include/optional
Normal file
81
libs/libcxx/include/optional
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_OPTIONAL
|
||||
#define _LIBCXX_OPTIONAL
|
||||
|
||||
#include <__config>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct nullopt_t {
|
||||
explicit constexpr nullopt_t() { }
|
||||
};
|
||||
inline constexpr nullopt_t nullopt {};
|
||||
|
||||
template <typename T>
|
||||
class optional {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
optional() = default;
|
||||
optional(nullopt_t)
|
||||
: m_has_value(false)
|
||||
, m_value()
|
||||
{
|
||||
}
|
||||
|
||||
template <class U = T>
|
||||
optional(U&& value)
|
||||
: m_value(std::forward<U>(value))
|
||||
, m_has_value(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
optional(in_place_t, Args&&... args)
|
||||
: m_value(std::forward<Args>(args)...)
|
||||
, m_has_value(true)
|
||||
{
|
||||
}
|
||||
|
||||
~optional() = default;
|
||||
|
||||
bool has_value() const { return m_has_value; }
|
||||
operator bool() const { return has_value(); }
|
||||
|
||||
T* operator->() { return &m_value; }
|
||||
const T* operator->() const { return &m_value; }
|
||||
|
||||
T& operator*() { return m_value; }
|
||||
const T& operator*() const { return m_value; }
|
||||
|
||||
T& value() { return m_value; }
|
||||
const T& value() const { return m_value; }
|
||||
|
||||
template <class U>
|
||||
T value_or(U&& def)
|
||||
{
|
||||
if (has_value()) {
|
||||
return m_value;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
T value_or(U&& def) const
|
||||
{
|
||||
if (has_value()) {
|
||||
return m_value;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_has_value { false };
|
||||
T m_value;
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_OPTIONAL
|
||||
161
libs/libcxx/include/ostream
Normal file
161
libs/libcxx/include/ostream
Normal file
@@ -0,0 +1,161 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_OSTREAM
|
||||
#define _LIBCXX_OSTREAM
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ios>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <typename CharT, typename Traits = char_traits<CharT>>
|
||||
class basic_ostream : public basic_ios<CharT, Traits> {
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using traits_type = Traits;
|
||||
using int_type = typename traits_type::int_type;
|
||||
using pos_type = typename traits_type::pos_type;
|
||||
using off_type = typename traits_type::off_type;
|
||||
|
||||
class sentry {
|
||||
public:
|
||||
explicit sentry(basic_ostream<char_type, traits_type>& os)
|
||||
: m_os(os)
|
||||
{
|
||||
}
|
||||
explicit operator bool() const { return true; }
|
||||
~sentry() = default;
|
||||
|
||||
private:
|
||||
basic_ostream<char_type, traits_type>& m_os;
|
||||
};
|
||||
|
||||
explicit basic_ostream(basic_streambuf<char_type, traits_type>* rdbuf)
|
||||
: basic_ios<char_type, traits_type>(rdbuf)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~basic_ostream() = default;
|
||||
|
||||
basic_ostream& put(char_type ch)
|
||||
{
|
||||
sentry sen(*this);
|
||||
if (sen) {
|
||||
if (this->rdbuf()->sputc(ch) == traits_type::eof()) {
|
||||
this->setstate(ios_base::badbit);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_ostream& write(const char_type* s, streamsize count)
|
||||
{
|
||||
sentry sen(*this);
|
||||
if (sen && count) {
|
||||
if (this->rdbuf()->sputn(s, count) != count) {
|
||||
this->setstate(ios_base::badbit);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_ostream& flush()
|
||||
{
|
||||
sentry sen(*this);
|
||||
if (sen) {
|
||||
if (this->rdbuf()->pubsync() == -1) {
|
||||
this->setstate(ios_base::badbit);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline basic_ostream& operator<<(basic_ostream& (*callback)(basic_ostream&)) { return callback(*this); }
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, int value)
|
||||
{
|
||||
char buf[16];
|
||||
std::sprintf(buf, "%d", value);
|
||||
size_t len = std::strlen(buf);
|
||||
os.write(buf, len);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, long value)
|
||||
{
|
||||
char buf[16];
|
||||
std::sprintf(buf, "%d", value);
|
||||
size_t len = std::strlen(buf);
|
||||
os.write(buf, len);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, unsigned int value)
|
||||
{
|
||||
char buf[16];
|
||||
std::sprintf(buf, "%u", value);
|
||||
size_t len = std::strlen(buf);
|
||||
os.write(buf, len);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, unsigned long value)
|
||||
{
|
||||
char buf[16];
|
||||
std::sprintf(buf, "%u", value);
|
||||
size_t len = std::strlen(buf);
|
||||
os.write(buf, len);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, const char* value)
|
||||
{
|
||||
size_t len = std::strlen(value);
|
||||
os.write(value, len);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, char value)
|
||||
{
|
||||
os.put(value);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, std::basic_string<CharT, Traits, Allocator> const& value)
|
||||
{
|
||||
os.write(value.data(), value.size());
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, std::basic_string_view<CharT, Traits> const& value)
|
||||
{
|
||||
os.write(value.data(), value.size());
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
basic_ostream<CharT, Traits>& endl(basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
os.put('\n');
|
||||
os.flush();
|
||||
return os;
|
||||
}
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_OSTREAM
|
||||
64
libs/libcxx/include/set
Normal file
64
libs/libcxx/include/set
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_SET
|
||||
#define _LIBCXX_SET
|
||||
|
||||
#include <__config>
|
||||
#include <__rbtree>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>>
|
||||
class set {
|
||||
private:
|
||||
using __tree_type = __rbtree<Key, Compare, Allocator>;
|
||||
|
||||
public:
|
||||
using key_type = Key;
|
||||
using value_type = Key;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using key_compare = Compare;
|
||||
using value_compare = Compare;
|
||||
using allocator_type = Allocator;
|
||||
using refernce = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using node_type = typename __tree_type::node_type;
|
||||
|
||||
set()
|
||||
: m_tree()
|
||||
{
|
||||
}
|
||||
|
||||
set(const Compare& comp, const Allocator& alloc = Allocator())
|
||||
: m_tree(comp, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit set(const Allocator& alloc)
|
||||
: m_tree(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Return std::pair<iterator, bool>
|
||||
inline bool insert(const_reference value) { return m_tree.insert(value); }
|
||||
inline bool insert(value_type&& value) { return m_tree.insert(std::move(value)); }
|
||||
|
||||
inline size_type erase(const_reference value) { return m_tree.erase(value); }
|
||||
|
||||
inline allocator_type get_allocator() const noexcept { return m_tree.get_allocator(); }
|
||||
inline size_type size() const { return m_tree.size(); }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
|
||||
private:
|
||||
__tree_type m_tree;
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_SET
|
||||
193
libs/libcxx/include/streambuf
Normal file
193
libs/libcxx/include/streambuf
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_STREAMBUF
|
||||
#define _LIBCXX_STREAMBUF
|
||||
|
||||
#include <__config>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <ios>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class CharT, class Traits>
|
||||
class basic_streambuf {
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using traits_type = Traits;
|
||||
using int_type = typename traits_type::int_type;
|
||||
using pos_type = typename traits_type::pos_type;
|
||||
using off_type = typename traits_type::off_type;
|
||||
|
||||
virtual ~basic_streambuf() = default;
|
||||
|
||||
// TODO: Add locales
|
||||
|
||||
basic_streambuf* pubsetbuf(char_type* s, streamsize n) { return setbuf(s, n); }
|
||||
pos_type pubseekoff(off_type off, ios_base::seekdir dir, ios_base::openmode which = ios_base::in | ios_base::out) { return seekoff(off, dir, which); }
|
||||
pos_type pubseekpos(pos_type pos, ios_base::openmode which = ios_base::in | ios_base::out) { return seekpos(pos, which); }
|
||||
int pubsync() { return sync(); }
|
||||
|
||||
streamsize in_avail()
|
||||
{
|
||||
if (egptr() - gptr() > 0) {
|
||||
return egptr() - gptr();
|
||||
}
|
||||
return showmanyc();
|
||||
}
|
||||
|
||||
int_type snextc()
|
||||
{
|
||||
if (sbumpc() == traits_type::eof()) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
return sgetc();
|
||||
}
|
||||
|
||||
int_type sbumpc()
|
||||
{
|
||||
if (gptr() == egptr()) {
|
||||
return uflow();
|
||||
}
|
||||
return Traits::to_int_type(*m_gptr++);
|
||||
}
|
||||
|
||||
int_type sgetc()
|
||||
{
|
||||
if (gptr() == egptr()) {
|
||||
return underflow();
|
||||
}
|
||||
return Traits::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
streamsize sgetn(char_type* s, streamsize n) { return xsgetn(s, n); }
|
||||
|
||||
int_type sputc(char_type c)
|
||||
{
|
||||
if (pptr() == epptr()) {
|
||||
return overflow(c);
|
||||
}
|
||||
*pptr() = c;
|
||||
m_pptr++;
|
||||
return Traits::to_int_type(c);
|
||||
}
|
||||
|
||||
streamsize sputn(const char_type* s, streamsize n) { return xsputn(s, n); }
|
||||
|
||||
int_type sputbackc(char_type c)
|
||||
{
|
||||
if (eback() == egptr() || traits_type::eq(c, egptr()[-1])) {
|
||||
return pbackfail(c);
|
||||
}
|
||||
return traits_type::to_int_type(*(--m_gptr));
|
||||
}
|
||||
|
||||
int_type sungetc()
|
||||
{
|
||||
if (eback() == egptr())
|
||||
return pbackfail();
|
||||
return traits_type::to_int_type(*(--m_gptr));
|
||||
}
|
||||
|
||||
protected:
|
||||
basic_streambuf() = default;
|
||||
|
||||
virtual basic_streambuf* setbuf(char_type* s, streamsize n) { return this; }
|
||||
virtual pos_type seekoff(off_type off, ios_base::seekdir dir, ios_base::openmode which) { return pos_type(off_type(-1)); }
|
||||
virtual pos_type seekpos(pos_type pos, ios_base::openmode which) { return pos_type(off_type(-1)); }
|
||||
virtual int sync() { return 0; }
|
||||
|
||||
virtual streamsize showmanyc() { return 0; }
|
||||
virtual int_type underflow() { return traits_type::eof(); }
|
||||
virtual int_type uflow()
|
||||
{
|
||||
if (underflow() == traits_type::eof()) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
return traits_type::to_int_type(*m_gptr++);
|
||||
}
|
||||
|
||||
virtual streamsize xsgetn(char_type* s, streamsize count)
|
||||
{
|
||||
auto eof = traits_type::eof();
|
||||
int_type tmpcint;
|
||||
for (streamsize i = 0; i < count;) {
|
||||
if (gptr() < egptr()) {
|
||||
streamsize can_get = std::min(static_cast<streamsize>(egptr() - gptr()), count);
|
||||
traits_type::copy(s, gptr(), can_get);
|
||||
this->gbump(can_get);
|
||||
s += can_get;
|
||||
i += can_get;
|
||||
} else if ((tmpcint = uflow()) != eof) {
|
||||
*s = traits_type::to_char_type(tmpcint);
|
||||
s++;
|
||||
i++;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
char_type* eback() const { return m_eback; }
|
||||
char_type* gptr() const { return m_gptr; }
|
||||
char_type* egptr() const { return m_egptr; }
|
||||
|
||||
void gbump(int n) { m_gptr += n; }
|
||||
void setg(char_type* gbeg, char_type* gcurr, char_type* gend)
|
||||
{
|
||||
m_eback = gbeg;
|
||||
m_gptr = gcurr;
|
||||
m_egptr = gend;
|
||||
}
|
||||
|
||||
virtual streamsize xsputn(const char_type* s, streamsize count)
|
||||
{
|
||||
auto eof = traits_type::eof();
|
||||
int_type tmpcint;
|
||||
for (streamsize i = 0; i < count;) {
|
||||
if (pptr() < epptr()) {
|
||||
streamsize can_put = std::min(static_cast<streamsize>(egptr() - gptr()), count);
|
||||
traits_type::copy(pptr(), s, can_put);
|
||||
this->pbump(can_put);
|
||||
s += can_put;
|
||||
i += can_put;
|
||||
} else if ((tmpcint = overflow(*s)) != eof) {
|
||||
s++;
|
||||
i++;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
virtual int_type overflow(int_type ch = traits_type::eof()) { return traits_type::eof(); }
|
||||
|
||||
char_type* pbase() const { return m_pbase; }
|
||||
char_type* pptr() const { return m_pptr; }
|
||||
char_type* epptr() const { return m_epptr; }
|
||||
void pbump(int n) { m_pptr += n; }
|
||||
|
||||
void setg(char_type* pbeg, char_type* pend)
|
||||
{
|
||||
m_pbase = m_pptr = pbeg;
|
||||
m_epptr = pend;
|
||||
}
|
||||
|
||||
virtual int_type pbackfail(int_type c = traits_type::eof()) { return traits_type::eof(); }
|
||||
|
||||
private:
|
||||
char_type* m_eback { nullptr };
|
||||
char_type* m_gptr { nullptr };
|
||||
char_type* m_egptr { nullptr };
|
||||
char_type* m_pbase { nullptr };
|
||||
char_type* m_pptr { nullptr };
|
||||
char_type* m_epptr { nullptr };
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_STREAMBUF
|
||||
362
libs/libcxx/include/string
Normal file
362
libs/libcxx/include/string
Normal file
@@ -0,0 +1,362 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_STRING
|
||||
#define _LIBCXX_STRING
|
||||
|
||||
#include <__config>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
static char __null_char = '\0';
|
||||
|
||||
template <class CharT>
|
||||
class char_traits {
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using int_type = int;
|
||||
using pos_type = int;
|
||||
using off_type = int;
|
||||
using state_type = int;
|
||||
|
||||
static constexpr void assign(char_type& r, const char_type& a) { r = a; }
|
||||
|
||||
static constexpr char_type* assign(char_type* p, size_t count, char_type a)
|
||||
{
|
||||
for (size_t sz = 0; sz < count; sz++) {
|
||||
assign(p[sz], a);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static constexpr char_type* move(char_type* dest, const char_type* src, size_t count)
|
||||
{
|
||||
for (size_t sz = 0; sz < count; sz++) {
|
||||
dest[sz] = std::move(src[sz]);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static constexpr size_t length(const char_type* s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
static constexpr char_type* copy(char_type* dest, const char_type* src, size_t count)
|
||||
{
|
||||
for (size_t sz = 0; sz < count; sz++) {
|
||||
dest[sz] = src[sz];
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
static constexpr int compare(const char_type* a, const char_type* b, size_t count)
|
||||
{
|
||||
return strncmp(a, b, count);
|
||||
}
|
||||
|
||||
static constexpr char_type to_char_type(int_type c) { return static_cast<char_type>(c); }
|
||||
static constexpr int_type to_int_type(char_type c) { return static_cast<int_type>(c); }
|
||||
static constexpr bool eq_int_type(int_type c1, int_type c2) { return c1 == c2; }
|
||||
|
||||
static constexpr int_type eof() { return -1; }
|
||||
static constexpr bool not_eof(int_type a) { return a != eof(); }
|
||||
|
||||
static constexpr bool eq(char_type a, char_type b) { return a == b; }
|
||||
static constexpr bool lt(char_type a, char_type b) { return a < b; }
|
||||
};
|
||||
|
||||
template <class CharT, class Traits>
|
||||
class basic_string_view;
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT>>
|
||||
class basic_string {
|
||||
public:
|
||||
using value_type = CharT;
|
||||
using allocator_type = Allocator;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = CharT*;
|
||||
using const_pointer = const CharT*;
|
||||
using reference = CharT&;
|
||||
using const_reference = const CharT&;
|
||||
using iterator = std::__legacy_iter<pointer>;
|
||||
using const_iterator = std::__legacy_iter<const_pointer>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
basic_string() = default;
|
||||
|
||||
basic_string(const value_type* str)
|
||||
{
|
||||
m_size = Traits::length(str);
|
||||
ensure_capacity(m_size + 1);
|
||||
Traits::copy(m_str, str, m_size);
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
}
|
||||
|
||||
basic_string(const value_type* str, size_t size)
|
||||
{
|
||||
m_size = size;
|
||||
ensure_capacity(m_size + 1);
|
||||
Traits::copy(m_str, str, m_size);
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
constexpr basic_string(Iter first, Iter last)
|
||||
{
|
||||
m_size = std::distance(first, last);
|
||||
ensure_capacity(m_size + 1);
|
||||
for (size_t i = 0; first != last; ++first, ++i) {
|
||||
Traits::assign(at(i), *first);
|
||||
}
|
||||
}
|
||||
|
||||
basic_string(const basic_string& s)
|
||||
{
|
||||
m_size = s.m_size;
|
||||
ensure_capacity(m_size + 1);
|
||||
Traits::copy(m_str, s.m_str, m_size);
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
}
|
||||
|
||||
basic_string(basic_string&& s)
|
||||
{
|
||||
m_size = s.m_size;
|
||||
m_capacity = s.m_capacity;
|
||||
m_str = s.m_str;
|
||||
s.m_size = s.m_capacity = 0;
|
||||
s.m_str = &__null_char;
|
||||
}
|
||||
|
||||
~basic_string()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
basic_string& operator=(const basic_string& s)
|
||||
{
|
||||
m_size = s.m_size;
|
||||
ensure_capacity(m_size + 1);
|
||||
Traits::copy(m_str, s.m_str, m_size);
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_string& operator=(basic_string&& s)
|
||||
{
|
||||
if (this != &s) {
|
||||
clear();
|
||||
m_size = s.m_size;
|
||||
m_capacity = s.m_capacity;
|
||||
m_str = s.m_str;
|
||||
s.m_size = s.m_capacity = 0;
|
||||
s.m_str = &__null_char;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_string& operator+=(const basic_string& s)
|
||||
{
|
||||
ensure_capacity(size() + s.size() + 1);
|
||||
Traits::copy(&m_str[m_size], s.m_str, s.m_size);
|
||||
m_size += s.size();
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_string operator+(const basic_string& s) const
|
||||
{
|
||||
basic_string res(*this);
|
||||
res += s;
|
||||
return res;
|
||||
}
|
||||
|
||||
basic_string operator+(const value_type* s) const
|
||||
{
|
||||
basic_string res(*this);
|
||||
res += basic_string(s);
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr allocator_type get_allocator() const { return m_allocator; }
|
||||
|
||||
inline void push_back(const value_type& c)
|
||||
{
|
||||
ensure_capacity(size() + 2);
|
||||
Traits::assign(m_str[m_size], c);
|
||||
m_size++;
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
}
|
||||
|
||||
inline void pop_back()
|
||||
{
|
||||
--m_size;
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
}
|
||||
|
||||
inline const_reference at(size_t i) const
|
||||
{
|
||||
return m_str[i];
|
||||
}
|
||||
|
||||
inline reference at(size_t i)
|
||||
{
|
||||
return m_str[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (m_capacity && m_str != &__null_char) {
|
||||
free(m_str);
|
||||
m_str = &__null_char;
|
||||
}
|
||||
m_size = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
void resize(size_t count, const value_type& c)
|
||||
{
|
||||
ensure_capacity(count + 1);
|
||||
Traits::assign(&m_str[m_size], count - size(), c);
|
||||
m_size = count;
|
||||
Traits::assign(m_str[m_size], '\0');
|
||||
}
|
||||
void resize(size_t count) { resize(count, '\0'); }
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
inline size_t length() const { return m_size; }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
|
||||
inline const_reference operator[](size_t i) const { return at(i); }
|
||||
inline reference operator[](size_t i) { return at(i); }
|
||||
|
||||
inline const_reference front() const { return at(0); }
|
||||
inline reference front() { return at(0); }
|
||||
|
||||
inline const_reference back() const { return at(size() - 1); }
|
||||
inline reference back() { return at(size() - 1); }
|
||||
|
||||
inline const_pointer c_str() const { return m_str; }
|
||||
inline const_pointer data() const { return m_str; }
|
||||
|
||||
inline iterator begin() { return iterator(&m_str[0]); }
|
||||
inline iterator end() { return iterator(&m_str[m_size]); }
|
||||
|
||||
inline const_iterator cbegin() const { return const_iterator(&m_str[0]); }
|
||||
inline const_iterator cend() const { return const_iterator(&m_str[m_size]); }
|
||||
|
||||
inline reverse_iterator rbegin() { return reverse_iterator(&m_str[m_size - 1]); }
|
||||
inline reverse_iterator rend() { return reverse_iterator(&m_str[-1]); }
|
||||
|
||||
inline const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_str[m_size - 1]); }
|
||||
inline const_reverse_iterator crend() const { return const_reverse_iterator(&m_str[-1]); }
|
||||
|
||||
inline operator std::basic_string_view<CharT, Traits>() const { return std::basic_string_view<CharT, Traits>(data(), size()); }
|
||||
|
||||
bool starts_with(value_type c) const
|
||||
{
|
||||
if (size() == 0) {
|
||||
return false;
|
||||
}
|
||||
return Traits::eq(at(0), c) == 0;
|
||||
}
|
||||
|
||||
bool starts_with(const value_type* s) const
|
||||
{
|
||||
size_t len = Traits::length(s);
|
||||
if (size() < len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Traits::compare(c_str(), s, len) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void ensure_capacity(size_t new_size)
|
||||
{
|
||||
int capacity = 4;
|
||||
while (new_size > capacity) {
|
||||
capacity *= 2;
|
||||
}
|
||||
grow(capacity);
|
||||
}
|
||||
|
||||
void grow(size_t capacity)
|
||||
{
|
||||
if (capacity < m_capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_capacity) {
|
||||
m_str = m_allocator.allocate(capacity);
|
||||
} else {
|
||||
auto new_str = m_allocator.allocate(capacity);
|
||||
Traits::move(new_str, m_str, m_capacity);
|
||||
m_allocator.deallocate(m_str, m_capacity);
|
||||
m_str = new_str;
|
||||
}
|
||||
m_capacity = capacity;
|
||||
}
|
||||
|
||||
size_t m_size { 0 };
|
||||
size_t m_capacity { 0 };
|
||||
value_type* m_str { &__null_char };
|
||||
allocator_type m_allocator;
|
||||
};
|
||||
|
||||
typedef basic_string<char> string;
|
||||
|
||||
static std::string to_string(int a)
|
||||
{
|
||||
char buf[32];
|
||||
std::sprintf(buf, "%d", a);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
static std::string to_string(unsigned a)
|
||||
{
|
||||
char buf[32];
|
||||
std::sprintf(buf, "%u", a);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator==(const std::basic_string<CharT, Traits, Allocator>& a, const std::basic_string<CharT, Traits, Allocator>& b)
|
||||
{
|
||||
if (a.size() != b.size()) {
|
||||
return false;
|
||||
}
|
||||
return Traits::compare(a.c_str(), b.c_str(), a.size()) == 0;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator==(const std::basic_string<CharT, Traits, Allocator>& a, const CharT* cstr)
|
||||
{
|
||||
size_t bsize = Traits::length(cstr);
|
||||
if (a.size() != bsize) {
|
||||
return false;
|
||||
}
|
||||
return Traits::compare(a.c_str(), cstr, a.size()) == 0;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
bool operator<(const std::basic_string<CharT, Traits, Allocator>& a, const std::basic_string<CharT, Traits, Allocator>& b)
|
||||
{
|
||||
int eq = Traits::compare(a.c_str(), b.c_str(), std::min(a.size(), b.size()));
|
||||
if (!eq) {
|
||||
return eq == -1;
|
||||
}
|
||||
return a.size() < b.size();
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_STRING
|
||||
90
libs/libcxx/include/string_view
Normal file
90
libs/libcxx/include/string_view
Normal file
@@ -0,0 +1,90 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_STRING_VIEW
|
||||
#define _LIBCXX_STRING_VIEW
|
||||
|
||||
#include <__config>
|
||||
#include <string>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_string_view {
|
||||
public:
|
||||
using value_type = CharT;
|
||||
using pointer = CharT*;
|
||||
using const_pointer = const CharT*;
|
||||
using reference = CharT&;
|
||||
using const_reference = const CharT&;
|
||||
using iterator = std::__legacy_iter<pointer>;
|
||||
using const_iterator = std::__legacy_iter<const_pointer>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
basic_string_view() = default;
|
||||
|
||||
basic_string_view(const value_type* str)
|
||||
: m_str(str)
|
||||
, m_size(Traits::length(str))
|
||||
{
|
||||
}
|
||||
|
||||
basic_string_view(const value_type* str, size_t size)
|
||||
: m_str(str)
|
||||
, m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
basic_string_view(Iter first, Iter last)
|
||||
: m_str(std::to_address(first))
|
||||
, m_size(std::distance(first, last))
|
||||
{
|
||||
}
|
||||
|
||||
~basic_string_view() = default;
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
inline size_t length() const { return m_size; }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
|
||||
inline const_reference operator[](size_t i) const { return at(i); }
|
||||
inline const_reference at(size_t i) const { return m_str[i]; }
|
||||
inline const_reference front() const { return at(0); }
|
||||
inline const_reference back() const { return at(size() - 1); }
|
||||
|
||||
inline const_pointer data() const { return m_str; }
|
||||
|
||||
inline const_iterator begin() const { return const_iterator(&m_str[0]); }
|
||||
inline const_iterator end() const { return const_iterator(&m_str[m_size]); }
|
||||
|
||||
inline const_iterator cbegin() const { return const_iterator(&m_str[0]); }
|
||||
inline const_iterator cend() const { return const_iterator(&m_str[m_size]); }
|
||||
|
||||
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(&m_str[m_size - 1]); }
|
||||
inline const_reverse_iterator rend() const { return const_reverse_iterator(&m_str[-1]); }
|
||||
|
||||
inline const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_str[m_size - 1]); }
|
||||
inline const_reverse_iterator crend() const { return const_reverse_iterator(&m_str[-1]); }
|
||||
|
||||
private:
|
||||
size_t m_size { 0 };
|
||||
const value_type* m_str { &__null_char };
|
||||
};
|
||||
|
||||
typedef basic_string_view<char> string_view;
|
||||
|
||||
template <class CharT, class Traits>
|
||||
bool operator==(const std::basic_string_view<CharT, Traits>& a, const std::basic_string_view<CharT, Traits>& b)
|
||||
{
|
||||
if (a.size() != b.size()) {
|
||||
return false;
|
||||
}
|
||||
return Traits::compare(a.c_str(), b.c_str(), a.size()) == 0;
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_STRING_VIEW
|
||||
248
libs/libcxx/include/type_traits
Normal file
248
libs/libcxx/include/type_traits
Normal file
@@ -0,0 +1,248 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_TYPE_TRAITS
|
||||
#define _LIBCXX_TYPE_TRAITS
|
||||
|
||||
#include <__config>
|
||||
#include <cstddef>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
// Helper Classes
|
||||
|
||||
template <class T, T v>
|
||||
struct integral_constant {
|
||||
static constexpr T value = v;
|
||||
constexpr operator T() const { return value; }
|
||||
constexpr T operator()() const { return value; }
|
||||
};
|
||||
|
||||
template <bool v>
|
||||
using bool_constant = integral_constant<bool, v>;
|
||||
|
||||
using true_type = integral_constant<bool, true>;
|
||||
using false_type = integral_constant<bool, false>;
|
||||
|
||||
// Type relationships
|
||||
|
||||
template <class T>
|
||||
struct type_identity {
|
||||
using type = T;
|
||||
};
|
||||
template <class T>
|
||||
using type_identity_t = typename type_identity<T>::type;
|
||||
|
||||
template <class T, class U>
|
||||
struct is_same : false_type {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_same<T, T> : true_type {
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
inline constexpr bool is_same_v = is_same<T, U>::value;
|
||||
|
||||
// Const-volatility specifiers
|
||||
|
||||
template <class T>
|
||||
struct remove_const {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_const<const T> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct remove_volatile {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_volatile<volatile T> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
using remove_volatile_t = typename remove_volatile<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct remove_cv {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_cv<const T> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_cv<volatile T> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_cv<const volatile T> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct add_const {
|
||||
typedef const T type;
|
||||
};
|
||||
template <class T>
|
||||
using add_const_t = typename add_const<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct add_volatile {
|
||||
typedef volatile T type;
|
||||
};
|
||||
template <class T>
|
||||
using add_volatile_t = typename add_volatile<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct add_cv {
|
||||
typedef const volatile T type;
|
||||
};
|
||||
template <class T>
|
||||
using add_cv_t = typename add_cv<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct add_pointer {
|
||||
typedef T* type;
|
||||
};
|
||||
template <class T>
|
||||
using add_pointer_t = typename add_pointer<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct remove_reference {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_reference<T&> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_reference<T&&> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
using remove_reference_t = typename remove_reference<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct remove_pointer {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_pointer<T*> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_pointer<T* const> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_pointer<T* volatile> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_pointer<T* const volatile> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
|
||||
template <class T>
|
||||
struct remove_extent {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_extent<T[]> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T, std::size_t N>
|
||||
struct remove_extent<T[N]> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
using remove_extent_t = typename remove_extent<T>::type;
|
||||
|
||||
// Primary type categories
|
||||
|
||||
template <class T>
|
||||
struct is_void : is_same<void, typename remove_cv<T>::type> {
|
||||
};
|
||||
template <class T>
|
||||
inline constexpr bool is_void_v = is_void<T>::value;
|
||||
|
||||
template <class T>
|
||||
struct is_pointer_h : false_type {
|
||||
};
|
||||
template <class T>
|
||||
struct is_pointer_h<T*> : true_type {
|
||||
};
|
||||
template <class T>
|
||||
struct is_pointer : is_pointer_h<typename std::remove_cv<T>::type> {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_array : false_type {
|
||||
};
|
||||
template <class T>
|
||||
struct is_array<T[]> : true_type {
|
||||
};
|
||||
template <class T, size_t N>
|
||||
struct is_array<T[N]> : true_type {
|
||||
};
|
||||
template <class T>
|
||||
inline constexpr bool is_array_v = is_array<T>::value;
|
||||
|
||||
template <class T>
|
||||
struct is_const : false_type {
|
||||
};
|
||||
template <class T>
|
||||
struct is_const<const T> : true_type {
|
||||
};
|
||||
template <class T>
|
||||
inline constexpr bool is_const_v = is_const<T>::value;
|
||||
|
||||
template <class T>
|
||||
struct is_floating_point : integral_constant<bool, is_same_v<float, remove_cv_t<T>> || is_same_v<double, remove_cv_t<T>> || is_same_v<long double, remove_cv_t<T>>> {
|
||||
};
|
||||
template <class T>
|
||||
inline constexpr bool is_floating_point_v = is_floating_point<T>::value;
|
||||
|
||||
template <class T>
|
||||
struct is_function : bool_constant<!is_const_v<const T>> {
|
||||
};
|
||||
template <class T>
|
||||
inline constexpr bool is_function_v = is_function<T>::value;
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct enable_if {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if<true, T> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <bool B, class T = void>
|
||||
using enable_if_t = typename enable_if<B, T>::type;
|
||||
|
||||
template <bool B, class T, class F>
|
||||
struct conditional {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T, class F>
|
||||
struct conditional<false, T, F> {
|
||||
typedef F type;
|
||||
};
|
||||
|
||||
template <bool B, class T, class F>
|
||||
using conditional_t = typename conditional<B, T, F>::type;
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_TYPE_TRAITS
|
||||
28
libs/libcxx/include/typeinfo
Normal file
28
libs/libcxx/include/typeinfo
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_TYPEINFO
|
||||
#define _LIBCXX_TYPEINFO
|
||||
|
||||
#include <__config>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
class type_info {
|
||||
public:
|
||||
virtual ~type_info();
|
||||
bool operator==(const type_info& rhs) const;
|
||||
bool operator!=(const type_info& rhs) const;
|
||||
|
||||
bool before(const type_info& rhs) const;
|
||||
const char* name() const { return m_type_name; }
|
||||
|
||||
private:
|
||||
type_info(const type_info& rhs) = delete;
|
||||
type_info& operator=(const type_info& rhs) = delete;
|
||||
|
||||
const char* m_type_name;
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_TYPEINFO
|
||||
119
libs/libcxx/include/utility
Normal file
119
libs/libcxx/include/utility
Normal file
@@ -0,0 +1,119 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_UTILITY
|
||||
#define _LIBCXX_UTILITY
|
||||
|
||||
#include <__config>
|
||||
#include <type_traits>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <typename T>
|
||||
inline T&& move(T& arg)
|
||||
{
|
||||
return static_cast<T&&>(arg);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline void swap(T& a, U& b)
|
||||
{
|
||||
U tmp = move((U&)a);
|
||||
a = (T &&) move(b);
|
||||
b = move(tmp);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static constexpr T&& forward(std::remove_reference_t<T>& t) { return static_cast<T&&>(t); }
|
||||
|
||||
template <class T>
|
||||
static constexpr T&& forward(std::remove_reference_t<T>&& t) { return static_cast<T&&>(t); }
|
||||
|
||||
struct in_place_t {
|
||||
explicit in_place_t() = default;
|
||||
};
|
||||
inline constexpr in_place_t in_place {};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct pair {
|
||||
using first_type = T1;
|
||||
using second_type = T2;
|
||||
|
||||
constexpr pair() = default;
|
||||
constexpr ~pair() = default;
|
||||
|
||||
constexpr pair(const T1& x, const T2& y)
|
||||
: first(x)
|
||||
, second(y)
|
||||
{
|
||||
}
|
||||
|
||||
template <class U1 = T1, class U2 = T2>
|
||||
constexpr pair(U1&& x, U2&& y)
|
||||
: first(std::forward<U1>(x))
|
||||
, second(std::forward<U2>(y))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(const pair<T1, T2>& p)
|
||||
: first(p.first)
|
||||
, second(p.second)
|
||||
{
|
||||
}
|
||||
|
||||
template <class U1 = T1, class U2 = T2>
|
||||
constexpr pair(pair<U1, U2>&& p)
|
||||
: first(std::move(p.first))
|
||||
, second(std::move(p.second))
|
||||
{
|
||||
}
|
||||
|
||||
T1 first {};
|
||||
T2 second {};
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator==(const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs)
|
||||
{
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator!=(const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<(const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs)
|
||||
{
|
||||
return (lhs.first < rhs.first) || (lhs.first == rhs.first && lhs.second < rhs.second);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<=(const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs)
|
||||
{
|
||||
return (lhs < rhs) || (lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>(const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs)
|
||||
{
|
||||
return (lhs.first > rhs.first) || (lhs.first == rhs.first && lhs.second > rhs.second);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>=(const std::pair<T1, T2>& lhs, const std::pair<T1, T2>& rhs)
|
||||
{
|
||||
return (lhs > rhs) || (lhs == rhs);
|
||||
}
|
||||
|
||||
// TODO: Use decay for return types
|
||||
template <class T1, class T2>
|
||||
std::pair<T1, T2> make_pair(T1&& l, T2&& r)
|
||||
{
|
||||
return std::pair<T1, T2>(std::forward<T1>(l), std::forward<T2>(r));
|
||||
}
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_UTILITY
|
||||
216
libs/libcxx/include/vector
Normal file
216
libs/libcxx/include/vector
Normal file
@@ -0,0 +1,216 @@
|
||||
#pragma GCC system_header
|
||||
|
||||
#ifndef _LIBCXX_VECTOR
|
||||
#define _LIBCXX_VECTOR
|
||||
|
||||
#include <__config>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
_LIBCXX_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class T, class Allocator = std::allocator<T>>
|
||||
class vector {
|
||||
public:
|
||||
using value_type = T;
|
||||
using allocator_type = Allocator;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using iterator = std::__legacy_iter<pointer>;
|
||||
using const_iterator = std::__legacy_iter<const_pointer>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
vector()
|
||||
{
|
||||
grow(16);
|
||||
}
|
||||
|
||||
explicit vector(size_type capacity)
|
||||
{
|
||||
grow(capacity);
|
||||
}
|
||||
|
||||
vector(const vector& v)
|
||||
{
|
||||
grow(v.m_capacity);
|
||||
m_size = v.m_size;
|
||||
copy(m_data, v.m_data, m_size);
|
||||
}
|
||||
|
||||
vector(vector&& v)
|
||||
{
|
||||
m_size = v.m_size;
|
||||
m_capacity = v.m_capacity;
|
||||
m_data = v.m_data;
|
||||
v.m_size = v.m_capacity = 0;
|
||||
v.m_data = nullptr;
|
||||
}
|
||||
|
||||
~vector()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
vector& operator=(const vector& v)
|
||||
{
|
||||
grow(v.m_capacity);
|
||||
m_size = v.m_size;
|
||||
copy(m_data, v.m_data, m_size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector& operator=(vector&& v)
|
||||
{
|
||||
if (this != &v) {
|
||||
clear();
|
||||
m_size = v.m_size;
|
||||
m_capacity = v.m_capacity;
|
||||
m_data = v.m_data;
|
||||
v.m_size = 0;
|
||||
v.m_capacity = 0;
|
||||
v.m_data = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void push_back(value_type&& el)
|
||||
{
|
||||
ensure_capacity(size() + 1);
|
||||
construct_at(&m_data[m_size], std::move(el));
|
||||
m_size++;
|
||||
}
|
||||
|
||||
inline void push_back(const_reference el)
|
||||
{
|
||||
push_back(T(el));
|
||||
}
|
||||
|
||||
inline void pop_back()
|
||||
{
|
||||
back().~T();
|
||||
--m_size;
|
||||
}
|
||||
|
||||
inline const_reference at(size_type i) const
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
inline reference at(size_type i)
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
clear_remain_capacity();
|
||||
if (m_data) {
|
||||
m_allocator.deallocate(m_data, m_capacity);
|
||||
m_data = nullptr;
|
||||
}
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
void clear_remain_capacity()
|
||||
{
|
||||
if (m_data) {
|
||||
for (size_type i = 0; i < m_size; ++i) {
|
||||
destroy_at(&m_data[i]);
|
||||
}
|
||||
}
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
inline void resize(size_type new_size)
|
||||
{
|
||||
ensure_capacity(new_size);
|
||||
m_size = new_size;
|
||||
}
|
||||
|
||||
inline size_t size() const { return m_size; }
|
||||
inline size_t capacity() const { return m_capacity; }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
|
||||
inline reference operator[](size_t i) { return at(i); }
|
||||
inline const_reference operator[](size_t i) const { return at(i); }
|
||||
|
||||
inline reference front() { return at(0); }
|
||||
inline const_reference front() const { return at(0); }
|
||||
|
||||
inline reference back() { return at(size() - 1); }
|
||||
inline const_reference back() const { return at(size() - 1); }
|
||||
|
||||
inline pointer data() { return m_data; }
|
||||
inline const_pointer data() const { return m_data; }
|
||||
|
||||
inline iterator begin() { return iterator(&m_data[0]); }
|
||||
inline iterator end() { return iterator(&m_data[m_size]); }
|
||||
|
||||
inline const_iterator cbegin() const { return const_iterator(&m_data[0]); }
|
||||
inline const_iterator cend() const { return const_iterator(&m_data[m_size]); }
|
||||
|
||||
inline reverse_iterator rbegin() { return reverse_iterator(&m_data[m_size - 1]); }
|
||||
inline reverse_iterator rend() { return reverse_iterator(&m_data[-1]); }
|
||||
|
||||
inline const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_data[m_size - 1]); }
|
||||
inline const_reverse_iterator crend() const { return const_reverse_iterator(&m_data[-1]); }
|
||||
|
||||
private:
|
||||
inline void ensure_capacity(size_type new_size)
|
||||
{
|
||||
size_type capacity = 16;
|
||||
while (new_size > capacity) {
|
||||
capacity *= 2;
|
||||
}
|
||||
grow(capacity);
|
||||
}
|
||||
|
||||
void grow(size_type capacity)
|
||||
{
|
||||
if (capacity <= m_capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_data) {
|
||||
m_data = m_allocator.allocate(capacity);
|
||||
} else {
|
||||
retry:
|
||||
auto new_buf = m_allocator.allocate(capacity);
|
||||
if (!new_buf) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_size; i++) {
|
||||
construct_at(&new_buf[i], std::move(at(i)));
|
||||
destroy_at(&m_data[i]);
|
||||
}
|
||||
m_allocator.deallocate(m_data, m_capacity);
|
||||
m_data = new_buf;
|
||||
}
|
||||
m_capacity = capacity;
|
||||
}
|
||||
|
||||
void copy(pointer to, const_pointer from, size_type len)
|
||||
{
|
||||
for (size_type i = 0; i < len; i++) {
|
||||
construct_at(to, T(*from));
|
||||
to++;
|
||||
from++;
|
||||
}
|
||||
}
|
||||
|
||||
size_type m_size { 0 };
|
||||
size_type m_capacity { 0 };
|
||||
pointer m_data { nullptr };
|
||||
allocator_type m_allocator;
|
||||
};
|
||||
|
||||
_LIBCXX_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCXX_VECTOR
|
||||
Reference in New Issue
Block a user