mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Introduce more CTL content
This change introduces accumulate, addressof, advance, all_of, distance, array, enable_if, allocator_traits, back_inserter, bad_alloc, is_signed, any_of, copy, exception, fill, fill_n, is_same, is_same_v, out_of_range, lexicographical_compare, is_integral, uninitialized_fill_n, is_unsigned, numeric_limits, uninitialized_fill, iterator_traits, move_backward, min, max, iterator_tag, move_iterator, reverse_iterator, uninitialized_move_n This change experiments with rewriting the ctl::vector class to make the CTL design more similar to the STL. So far it has not slowed things down to have 42 #include lines rather than 2, since it's still almost nothing compared to LLVM's code. In fact the closer we can flirt with being just like libcxx, the better chance we might have of discovering exactly what makes it so slow to compile. It would be an enormous discovery if we can find one simple trick to solving the issue there instead. This also fixes a bug in `ctl::string(const string &s)` when `s` is big.
This commit is contained in:
parent
054da021d0
commit
38921dc46b
52 changed files with 2980 additions and 193 deletions
|
@ -36,6 +36,7 @@ $(CTL_A_OBJS): private \
|
|||
-Walloca-larger-than=4096 \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fexceptions \
|
||||
|
||||
CTL_LIBS = $(foreach x,$(CTL_ARTIFACTS),$($(x)))
|
||||
CTL_SRCS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_SRCS))
|
||||
|
|
28
ctl/accumulate.h
Normal file
28
ctl/accumulate.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ACCUMULATE_H_
|
||||
#define CTL_ACCUMULATE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class T>
|
||||
constexpr T
|
||||
accumulate(InputIt first, InputIt last, T init)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = init + *first;
|
||||
return init;
|
||||
}
|
||||
|
||||
template<class InputIt, class T, class BinaryOperation>
|
||||
constexpr T
|
||||
accumulate(InputIt first, InputIt last, T init, BinaryOperation op)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = op(init, *first);
|
||||
return init;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ACCUMULATE_H_
|
29
ctl/addressof.h
Normal file
29
ctl/addressof.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADDRESSOF_H_
|
||||
#define CTL_ADDRESSOF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
addressof(T& arg) noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char&>(arg)));
|
||||
}
|
||||
|
||||
template<typename R, typename... Args>
|
||||
R (*addressof(R (*&arg)(Args...)) noexcept)
|
||||
(Args...)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
addressof(T&&) = delete;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADDRESSOF_H_
|
24
ctl/advance.h
Normal file
24
ctl/advance.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADVANCE_H_
|
||||
#define CTL_ADVANCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
constexpr void
|
||||
advance(InputIt& it, Distance n)
|
||||
{
|
||||
while (n > 0) {
|
||||
--n;
|
||||
++it;
|
||||
}
|
||||
while (n < 0) {
|
||||
++n;
|
||||
--it;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADVANCE_H_
|
22
ctl/all_of.h
Normal file
22
ctl/all_of.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALL_OF_H_
|
||||
#define CTL_ALL_OF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
constexpr bool
|
||||
all_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
if (!p(*first)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALL_OF_H_
|
94
ctl/allocator.h
Normal file
94
ctl/allocator.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALLOCATOR_H_
|
||||
#define CTL_ALLOCATOR_H_
|
||||
#include "bad_alloc.h"
|
||||
#include "new.h"
|
||||
#include "type_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
class allocator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using propagate_on_container_move_assignment = ctl::true_type;
|
||||
using is_always_equal = ctl::true_type;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
|
||||
constexpr allocator() noexcept = default;
|
||||
|
||||
constexpr allocator(const allocator&) noexcept = default;
|
||||
|
||||
template<class U>
|
||||
constexpr allocator(const allocator<U>&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ~allocator() = default;
|
||||
|
||||
[[nodiscard]] T* allocate(size_type n)
|
||||
{
|
||||
if (n > __SIZE_MAX__ / sizeof(T))
|
||||
throw ctl::bad_alloc();
|
||||
if (auto p = static_cast<T*>(::operator new(
|
||||
n * sizeof(T), ctl::align_val_t(alignof(T)), ctl::nothrow)))
|
||||
return p;
|
||||
throw ctl::bad_alloc();
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_type n) noexcept
|
||||
{
|
||||
::operator delete(p, n * sizeof(T), ctl::align_val_t(alignof(T)));
|
||||
}
|
||||
|
||||
template<typename U, typename... Args>
|
||||
void construct(U* p, Args&&... args)
|
||||
{
|
||||
::new (static_cast<void*>(p)) U(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void destroy(U* p)
|
||||
{
|
||||
p->~U();
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return __SIZE_MAX__ / sizeof(T);
|
||||
}
|
||||
|
||||
allocator& operator=(const allocator&) = default;
|
||||
|
||||
template<typename U>
|
||||
struct rebind
|
||||
{
|
||||
using other = allocator<U>;
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool
|
||||
operator==(const allocator<T>&, const allocator<U>&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool
|
||||
operator!=(const allocator<T>&, const allocator<U>&) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALLOCATOR_H_
|
72
ctl/allocator_traits.h
Normal file
72
ctl/allocator_traits.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
#ifndef CTL_ALLOCATOR_TRAITS_H_
|
||||
#define CTL_ALLOCATOR_TRAITS_H_
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename 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 = void*;
|
||||
using const_void_pointer = const void*;
|
||||
using difference_type = typename Alloc::difference_type;
|
||||
using size_type = typename Alloc::size_type;
|
||||
|
||||
using propagate_on_container_copy_assignment = false_type;
|
||||
using propagate_on_container_move_assignment = true_type;
|
||||
using propagate_on_container_swap = false_type;
|
||||
using is_always_equal = true_type;
|
||||
|
||||
template<typename T>
|
||||
using rebind_alloc = typename Alloc::template rebind<T>::other;
|
||||
|
||||
template<typename T>
|
||||
using rebind_traits = allocator_traits<rebind_alloc<T>>;
|
||||
|
||||
__attribute__((__always_inline__)) static pointer allocate(Alloc& a,
|
||||
size_type n)
|
||||
{
|
||||
return a.allocate(n);
|
||||
}
|
||||
|
||||
__attribute__((__always_inline__)) static void deallocate(Alloc& a,
|
||||
pointer p,
|
||||
size_type n)
|
||||
{
|
||||
a.deallocate(p, n);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
__attribute__((__always_inline__)) static void construct(Alloc& a,
|
||||
T* p,
|
||||
Args&&... args)
|
||||
{
|
||||
::new ((void*)p) T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__attribute__((__always_inline__)) static void destroy(Alloc& a, T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
__attribute__((__always_inline__)) static size_type max_size(
|
||||
const Alloc& a) noexcept
|
||||
{
|
||||
return __PTRDIFF_MAX__ / sizeof(value_type);
|
||||
}
|
||||
|
||||
__attribute__((__always_inline__)) static Alloc
|
||||
select_on_container_copy_construction(const Alloc& a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALLOCATOR_TRAITS_H_
|
22
ctl/any_of.h
Normal file
22
ctl/any_of.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ANY_OF_H_
|
||||
#define CTL_ANY_OF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
constexpr bool
|
||||
any_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
if (p(*first)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ANY_OF_H_
|
243
ctl/array.h
Normal file
243
ctl/array.h
Normal file
|
@ -0,0 +1,243 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ARRAY_H_
|
||||
#define CTL_ARRAY_H_
|
||||
#include "initializer_list.h"
|
||||
#include "reverse_iterator.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T, size_t N>
|
||||
struct array
|
||||
{
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using iterator = value_type*;
|
||||
using const_iterator = const value_type*;
|
||||
using reverse_iterator = ctl::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = ctl::reverse_iterator<const_iterator>;
|
||||
|
||||
T elems[N];
|
||||
|
||||
constexpr array() = default;
|
||||
constexpr array(std::initializer_list<T> init)
|
||||
{
|
||||
auto it = init.begin();
|
||||
for (size_t i = 0; i < N && it != init.end(); ++i, ++it) {
|
||||
elems[i] = *it;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr reference at(size_type pos)
|
||||
{
|
||||
if (pos >= N)
|
||||
__builtin_trap();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr const_reference at(size_type pos) const
|
||||
{
|
||||
if (pos >= N)
|
||||
__builtin_trap();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr reference operator[](size_type pos)
|
||||
{
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr const_reference operator[](size_type pos) const
|
||||
{
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr reference front()
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
constexpr const_reference front() const
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
constexpr reference back()
|
||||
{
|
||||
return elems[N - 1];
|
||||
}
|
||||
|
||||
constexpr const_reference back() const
|
||||
{
|
||||
return elems[N - 1];
|
||||
}
|
||||
|
||||
constexpr T* data() noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr const T* data() const noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr iterator begin() noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr const_iterator begin() const noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr iterator end() noexcept
|
||||
{
|
||||
return elems + N;
|
||||
}
|
||||
|
||||
constexpr const_iterator end() const noexcept
|
||||
{
|
||||
return elems + N;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rend() noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return N == 0;
|
||||
}
|
||||
|
||||
constexpr size_type size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
constexpr size_type max_size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
void fill(const T& value)
|
||||
{
|
||||
for (size_type i = 0; i < N; ++i) {
|
||||
elems[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(array& other) noexcept
|
||||
{
|
||||
for (size_type i = 0; i < N; ++i) {
|
||||
T temp = elems[i];
|
||||
elems[i] = other.elems[i];
|
||||
other.elems[i] = temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator==(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (!(lhs[i] == rhs[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator!=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator<(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (lhs[i] < rhs[i])
|
||||
return true;
|
||||
if (rhs[i] < lhs[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator<=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator>(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator>=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void
|
||||
swap(array<T, N>& lhs, array<T, N>& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ARRAY_H_
|
64
ctl/back_inserter.h
Normal file
64
ctl/back_inserter.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_BACK_INSERTER_H_
|
||||
#define CTL_BACK_INSERTER_H_
|
||||
#include "iterator.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class Container>
|
||||
class back_insert_iterator
|
||||
{
|
||||
protected:
|
||||
Container* container;
|
||||
|
||||
public:
|
||||
using iterator_category = ctl::output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = void;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
|
||||
explicit back_insert_iterator(Container& c) : container(&c)
|
||||
{
|
||||
}
|
||||
|
||||
back_insert_iterator& operator=(const typename Container::value_type& value)
|
||||
{
|
||||
container->push_back(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator=(typename Container::value_type&& value)
|
||||
{
|
||||
container->push_back(ctl::move(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator*()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator++()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator operator++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
back_insert_iterator<Container>
|
||||
back_inserter(Container& c)
|
||||
{
|
||||
return back_insert_iterator<Container>(c);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_BACK_INSERTER_H_
|
23
ctl/bad_alloc.h
Normal file
23
ctl/bad_alloc.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_BAD_ALLOC_H_
|
||||
#define CTL_BAD_ALLOC_H_
|
||||
#include "exception.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class bad_alloc : public exception
|
||||
{
|
||||
public:
|
||||
bad_alloc() noexcept = default;
|
||||
~bad_alloc() override = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "ctl::bad_alloc";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_BAD_ALLOC_H_
|
22
ctl/copy.h
Normal file
22
ctl/copy.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_COPY_H_
|
||||
#define CTL_COPY_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class OutputIt>
|
||||
OutputIt
|
||||
copy(InputIt first, InputIt last, OutputIt d_first)
|
||||
{
|
||||
while (first != last) {
|
||||
*d_first = *first;
|
||||
++d_first;
|
||||
++first;
|
||||
}
|
||||
return d_first;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_COPY_H_
|
37
ctl/distance.h
Normal file
37
ctl/distance.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_DISTANCE_H_
|
||||
#define CTL_DISTANCE_H_
|
||||
#include "iterator.h"
|
||||
#include "iterator_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIter>
|
||||
constexpr typename iterator_traits<InputIter>::difference_type
|
||||
distance_impl(InputIter first, InputIter last, input_iterator_tag)
|
||||
{
|
||||
typename iterator_traits<InputIter>::difference_type res(0);
|
||||
for (; first != last; ++first)
|
||||
++res;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<class RandIter>
|
||||
constexpr typename iterator_traits<RandIter>::difference_type
|
||||
distance_impl(RandIter first, RandIter last, random_access_iterator_tag)
|
||||
{
|
||||
return last - first;
|
||||
}
|
||||
|
||||
template<class InputIter>
|
||||
constexpr typename iterator_traits<InputIter>::difference_type
|
||||
distance(InputIter first, InputIter last)
|
||||
{
|
||||
return distance_impl(
|
||||
first, last, typename iterator_traits<InputIter>::iterator_category());
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_DISTANCE_H_
|
21
ctl/enable_if.h
Normal file
21
ctl/enable_if.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef CTL_ENABLE_IF_H_
|
||||
#define CTL_ENABLE_IF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
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;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ENABLE_IF_H_
|
22
ctl/exception.h
Normal file
22
ctl/exception.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_EXCEPTION_H_
|
||||
#define CTL_EXCEPTION_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class exception
|
||||
{
|
||||
public:
|
||||
exception() noexcept = default;
|
||||
virtual ~exception() = default;
|
||||
|
||||
virtual const char* what() const noexcept
|
||||
{
|
||||
return "ctl::exception";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_EXCEPTION_H_
|
18
ctl/fill.h
Normal file
18
ctl/fill.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_FILL_H_
|
||||
#define CTL_FILL_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename ForwardIt, typename T>
|
||||
void
|
||||
fill(ForwardIt first, ForwardIt last, const T& value)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
*first = value;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_FILL_H_
|
19
ctl/fill_n.h
Normal file
19
ctl/fill_n.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_FILL_N_H_
|
||||
#define CTL_FILL_N_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename OutputIt, typename Size, typename T>
|
||||
OutputIt
|
||||
fill_n(OutputIt first, Size count, const T& value)
|
||||
{
|
||||
for (; count > 0; --count, ++first)
|
||||
*first = value;
|
||||
return first;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_FILL_N_H_
|
28
ctl/iterator.h
Normal file
28
ctl/iterator.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_OUTPUT_ITERATOR_TAG_H_
|
||||
#define CTL_OUTPUT_ITERATOR_TAG_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
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
|
||||
{};
|
||||
|
||||
struct contiguous_iterator_tag : public random_access_iterator_tag
|
||||
{};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OUTPUT_ITERATOR_TAG_H_
|
31
ctl/iterator_traits.h
Normal file
31
ctl/iterator_traits.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ITERATOR_TRAITS_H_
|
||||
#define CTL_ITERATOR_TRAITS_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class Iterator>
|
||||
struct iterator_traits
|
||||
{
|
||||
using iterator_category = typename Iterator::iterator_category;
|
||||
using value_type = typename Iterator::value_type;
|
||||
using difference_type = typename Iterator::difference_type;
|
||||
using pointer = typename Iterator::pointer;
|
||||
using reference = typename Iterator::reference;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct iterator_traits<T*>
|
||||
{
|
||||
using iterator_category = void*; // We don't actually use this
|
||||
using value_type = T;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ITERATOR_TRAITS_H_
|
43
ctl/lexicographical_compare.h
Normal file
43
ctl/lexicographical_compare.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_LEXICOGRAPHICAL_COMPARE_H_
|
||||
#define CTL_LEXICOGRAPHICAL_COMPARE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt1, class InputIt2>
|
||||
bool
|
||||
lexicographical_compare(InputIt1 first1,
|
||||
InputIt1 last1,
|
||||
InputIt2 first2,
|
||||
InputIt2 last2)
|
||||
{
|
||||
for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
|
||||
if (*first1 < *first2)
|
||||
return true;
|
||||
if (*first2 < *first1)
|
||||
return false;
|
||||
}
|
||||
return (first1 == last1) && (first2 != last2);
|
||||
}
|
||||
|
||||
template<class InputIt1, class InputIt2, class Compare>
|
||||
bool
|
||||
lexicographical_compare(InputIt1 first1,
|
||||
InputIt1 last1,
|
||||
InputIt2 first2,
|
||||
InputIt2 last2,
|
||||
Compare comp)
|
||||
{
|
||||
for (; (first1 != last1) && (first2 != last2); ++first1, ++first2) {
|
||||
if (comp(*first1, *first2))
|
||||
return true;
|
||||
if (comp(*first2, *first1))
|
||||
return false;
|
||||
}
|
||||
return (first1 == last1) && (first2 != last2);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_LEXICOGRAPHICAL_COMPARE_H_ */
|
|
@ -2,6 +2,7 @@
|
|||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MAP_H_
|
||||
#define CTL_MAP_H_
|
||||
#include "out_of_range.h"
|
||||
#include "set.h"
|
||||
|
||||
namespace ctl {
|
||||
|
@ -164,7 +165,7 @@ class map
|
|||
{
|
||||
auto it = find(key);
|
||||
if (it == end())
|
||||
__builtin_trap();
|
||||
throw ctl::out_of_range("out of range");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
@ -172,7 +173,7 @@ class map
|
|||
{
|
||||
auto it = find(key);
|
||||
if (it == end())
|
||||
__builtin_trap();
|
||||
throw ctl::out_of_range("out of range");
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
|
17
ctl/max.h
Normal file
17
ctl/max.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MAX_H_
|
||||
#define CTL_MAX_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T&
|
||||
max(const T& a, const T& b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_MAX_H_ */
|
17
ctl/min.h
Normal file
17
ctl/min.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MIN_H_
|
||||
#define CTL_MIN_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T>
|
||||
inline constexpr const T&
|
||||
min(const T& a, const T& b)
|
||||
{
|
||||
return b < a ? b : a;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif /* CTL_MIN_H_ */
|
20
ctl/move_backward.h
Normal file
20
ctl/move_backward.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_MOVE_BACKWARD_H_
|
||||
#define CTL_MOVE_BACKWARD_H_
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename BidirIt1, typename BidirIt2>
|
||||
BidirIt2
|
||||
move_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last)
|
||||
{
|
||||
while (first != last)
|
||||
*(--d_last) = ctl::move(*(--last));
|
||||
return d_last;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MOVE_BACKWARD_H_
|
173
ctl/move_iterator.h
Normal file
173
ctl/move_iterator.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
#ifndef CTL_MOVE_ITERATOR_H_
|
||||
#define CTL_MOVE_ITERATOR_H_
|
||||
#include "iterator_traits.h"
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Iterator>
|
||||
class move_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_type = Iterator;
|
||||
using iterator_category =
|
||||
typename ctl::iterator_traits<Iterator>::iterator_category;
|
||||
using value_type = typename ctl::iterator_traits<Iterator>::value_type;
|
||||
using difference_type =
|
||||
typename ctl::iterator_traits<Iterator>::difference_type;
|
||||
using pointer = Iterator;
|
||||
using reference = value_type&&;
|
||||
|
||||
constexpr move_iterator() : current()
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr move_iterator(Iterator i) : current(i)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
constexpr move_iterator(const move_iterator<U>& u) : current(u.base())
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Iterator base() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
constexpr reference operator*() const
|
||||
{
|
||||
return static_cast<reference>(*current);
|
||||
}
|
||||
|
||||
constexpr pointer operator->() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator++()
|
||||
{
|
||||
++current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator++(int)
|
||||
{
|
||||
move_iterator tmp = *this;
|
||||
++current;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator--()
|
||||
{
|
||||
--current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator--(int)
|
||||
{
|
||||
move_iterator tmp = *this;
|
||||
--current;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator+(difference_type n) const
|
||||
{
|
||||
return move_iterator(current + n);
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator+=(difference_type n)
|
||||
{
|
||||
current += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr move_iterator operator-(difference_type n) const
|
||||
{
|
||||
return move_iterator(current - n);
|
||||
}
|
||||
|
||||
constexpr move_iterator& operator-=(difference_type n)
|
||||
{
|
||||
current -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr reference operator[](difference_type n) const
|
||||
{
|
||||
return ctl::move(current[n]);
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator current;
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
__attribute__((__always_inline__)) constexpr move_iterator<Iterator>
|
||||
make_move_iterator(Iterator i)
|
||||
{
|
||||
return move_iterator<Iterator>(i);
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator==(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return x.base() == y.base();
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator!=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return x.base() < y.base();
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr bool
|
||||
operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
constexpr move_iterator<Iterator>
|
||||
operator+(typename move_iterator<Iterator>::difference_type n,
|
||||
const move_iterator<Iterator>& x)
|
||||
{
|
||||
return x + n;
|
||||
}
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
constexpr auto
|
||||
operator-(const move_iterator<Iterator1>& x,
|
||||
const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base())
|
||||
{
|
||||
return x.base() - y.base();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_MOVE_ITERATOR_H_
|
52
ctl/new.cc
52
ctl/new.cc
|
@ -23,7 +23,7 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
static void*
|
||||
_ctl_alloc(size_t n, size_t a)
|
||||
_ctl_alloc(size_t n, size_t a) noexcept
|
||||
{
|
||||
void* p;
|
||||
if (!(p = memalign(a, n)))
|
||||
|
@ -32,7 +32,16 @@ _ctl_alloc(size_t n, size_t a)
|
|||
}
|
||||
|
||||
static void*
|
||||
_ctl_alloc1(size_t n)
|
||||
_ctl_alloc_nothrow(size_t n, size_t a, const ctl::nothrow_t&)
|
||||
{
|
||||
void* p;
|
||||
if (!(p = memalign(a, n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_alloc1(size_t n) noexcept
|
||||
{
|
||||
void* p;
|
||||
if (!(p = malloc(n)))
|
||||
|
@ -41,19 +50,28 @@ _ctl_alloc1(size_t n)
|
|||
}
|
||||
|
||||
static void*
|
||||
_ctl_ret(size_t, void* p)
|
||||
_ctl_alloc1_nothrow(size_t n, const ctl::nothrow_t&) noexcept
|
||||
{
|
||||
void* p;
|
||||
if (!(p = malloc(n)))
|
||||
__builtin_trap();
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
_ctl_ret(size_t, void* p) noexcept
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
_ctl_free(void* p)
|
||||
_ctl_free(void* p) noexcept
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
_ctl_nop(void*, void*)
|
||||
_ctl_nop(void*, void*) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -75,23 +93,43 @@ __weak_reference(void*
|
|||
operator new(size_t, ctl::align_val_t),
|
||||
_ctl_alloc);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t,
|
||||
ctl::align_val_t,
|
||||
const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc_nothrow);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t, ctl::align_val_t),
|
||||
_ctl_alloc);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t,
|
||||
ctl::align_val_t,
|
||||
const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc_nothrow);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t),
|
||||
_ctl_alloc1);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new(size_t, const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc1_nothrow);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t),
|
||||
_ctl_alloc1);
|
||||
|
||||
__weak_reference(void*
|
||||
operator new[](size_t, const ctl::nothrow_t&) noexcept,
|
||||
_ctl_alloc1_nothrow);
|
||||
|
||||
// XXX clang-format currently mutilates these for some reason.
|
||||
// clang-format off
|
||||
|
||||
__weak_reference(void* operator new(size_t, void*), _ctl_ret);
|
||||
__weak_reference(void* operator new[](size_t, void*), _ctl_ret);
|
||||
__weak_reference(void* operator new(size_t, void*) noexcept, _ctl_ret);
|
||||
__weak_reference(void* operator new[](size_t, void*) noexcept, _ctl_ret);
|
||||
|
||||
__weak_reference(void operator delete(void*) noexcept, _ctl_free);
|
||||
__weak_reference(void operator delete[](void*) noexcept, _ctl_free);
|
||||
|
|
26
ctl/new.h
26
ctl/new.h
|
@ -13,18 +13,30 @@ enum class align_val_t : size_t
|
|||
{
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
struct nothrow_t
|
||||
{
|
||||
explicit nothrow_t() = default;
|
||||
};
|
||||
|
||||
void* operator new(size_t);
|
||||
void* operator new[](size_t);
|
||||
void* operator new(size_t, ctl::align_val_t);
|
||||
void* operator new[](size_t, ctl::align_val_t);
|
||||
inline constexpr nothrow_t nothrow{};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
// XXX clang-format currently mutilates these for some reason.
|
||||
// clang-format off
|
||||
|
||||
void* operator new(size_t, void*);
|
||||
void* operator new[](size_t, void*);
|
||||
void* operator new(size_t);
|
||||
void* operator new(size_t, const ctl::nothrow_t&) noexcept;
|
||||
void* operator new(size_t, ctl::align_val_t);
|
||||
void* operator new(size_t, ctl::align_val_t, const ctl::nothrow_t&) noexcept;
|
||||
|
||||
void* operator new[](size_t);
|
||||
void* operator new[](size_t, const ctl::nothrow_t&) noexcept;
|
||||
void* operator new[](size_t, ctl::align_val_t);
|
||||
void* operator new[](size_t, ctl::align_val_t, const ctl::nothrow_t&) noexcept;
|
||||
|
||||
void* operator new(size_t, void*) noexcept;
|
||||
void* operator new[](size_t, void*) noexcept;
|
||||
|
||||
void operator delete(void*) noexcept;
|
||||
void operator delete[](void*) noexcept;
|
||||
|
|
122
ctl/numeric_limits.h
Normal file
122
ctl/numeric_limits.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_NUMERIC_LIMITS_H_
|
||||
#define CTL_NUMERIC_LIMITS_H_
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
class numeric_limits
|
||||
{
|
||||
static constexpr T max_signed()
|
||||
{
|
||||
return T(((uintmax_t)1 << (sizeof(T) * 8 - 1)) - 1);
|
||||
}
|
||||
|
||||
static constexpr T max_unsigned()
|
||||
{
|
||||
return T(~T(0));
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr bool is_specialized = ctl::is_integral<T>::value;
|
||||
static constexpr bool is_signed = !ctl::is_unsigned<T>::value;
|
||||
static constexpr bool is_integer = ctl::is_integral<T>::value;
|
||||
static constexpr bool is_exact = ctl::is_integral<T>::value;
|
||||
static constexpr int digits = sizeof(T) * 8 - (is_signed ? 1 : 0);
|
||||
|
||||
static constexpr T min() noexcept
|
||||
{
|
||||
return is_signed ? T(-max_signed() - 1) : T(0);
|
||||
}
|
||||
|
||||
static constexpr T max() noexcept
|
||||
{
|
||||
return is_signed ? max_signed() : max_unsigned();
|
||||
}
|
||||
|
||||
static constexpr T lowest() noexcept
|
||||
{
|
||||
return min();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct numeric_limits<bool>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr int digits = 1;
|
||||
|
||||
static constexpr bool min() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static constexpr bool max() noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr bool lowest() noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct numeric_limits<float>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr int digits = 24;
|
||||
|
||||
static constexpr float min() noexcept
|
||||
{
|
||||
return __FLT_MIN__;
|
||||
}
|
||||
|
||||
static constexpr float max() noexcept
|
||||
{
|
||||
return __FLT_MAX__;
|
||||
}
|
||||
|
||||
static constexpr float lowest() noexcept
|
||||
{
|
||||
return -max();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct numeric_limits<double>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr int digits = 53;
|
||||
|
||||
static constexpr double min() noexcept
|
||||
{
|
||||
return __DBL_MIN__;
|
||||
}
|
||||
|
||||
static constexpr double max() noexcept
|
||||
{
|
||||
return __DBL_MAX__;
|
||||
}
|
||||
|
||||
static constexpr double lowest() noexcept
|
||||
{
|
||||
return -max();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_NUMERIC_LIMITS_H_
|
23
ctl/out_of_range.h
Normal file
23
ctl/out_of_range.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_OUT_OF_RANGE_H_
|
||||
#define CTL_OUT_OF_RANGE_H_
|
||||
#include "exception.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class out_of_range : public exception
|
||||
{
|
||||
public:
|
||||
out_of_range() noexcept = default;
|
||||
~out_of_range() override = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "ctl::out_of_range";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_OUT_OF_RANGE_H_
|
183
ctl/reverse_iterator.h
Normal file
183
ctl/reverse_iterator.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_REVERSE_ITERATOR_H_
|
||||
#define CTL_REVERSE_ITERATOR_H_
|
||||
#include "iterator_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class Iterator>
|
||||
class reverse_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_type = Iterator;
|
||||
using iterator_category =
|
||||
typename iterator_traits<Iterator>::iterator_category;
|
||||
using value_type = typename iterator_traits<Iterator>::value_type;
|
||||
using difference_type = typename iterator_traits<Iterator>::difference_type;
|
||||
using pointer = typename iterator_traits<Iterator>::pointer;
|
||||
using reference = typename iterator_traits<Iterator>::reference;
|
||||
|
||||
constexpr reverse_iterator() : current()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr explicit reverse_iterator(Iterator x) : current(x)
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
constexpr reverse_iterator(const reverse_iterator<U>& other)
|
||||
: current(other.base())
|
||||
{
|
||||
}
|
||||
|
||||
template<class U>
|
||||
constexpr reverse_iterator& operator=(const reverse_iterator<U>& other)
|
||||
{
|
||||
current = other.base();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Iterator base() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
constexpr reference operator*() const
|
||||
{
|
||||
Iterator tmp = current;
|
||||
return *--tmp;
|
||||
}
|
||||
|
||||
constexpr pointer operator->() const
|
||||
{
|
||||
return &(operator*());
|
||||
}
|
||||
|
||||
constexpr reverse_iterator& operator++()
|
||||
{
|
||||
--current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator operator++(int)
|
||||
{
|
||||
reverse_iterator tmp = *this;
|
||||
--current;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator& operator--()
|
||||
{
|
||||
++current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator operator--(int)
|
||||
{
|
||||
reverse_iterator tmp = *this;
|
||||
++current;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator operator+(difference_type n) const
|
||||
{
|
||||
return reverse_iterator(current - n);
|
||||
}
|
||||
|
||||
constexpr reverse_iterator& operator+=(difference_type n)
|
||||
{
|
||||
current -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator operator-(difference_type n) const
|
||||
{
|
||||
return reverse_iterator(current + n);
|
||||
}
|
||||
|
||||
constexpr reverse_iterator& operator-=(difference_type n)
|
||||
{
|
||||
current += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr reference operator[](difference_type n) const
|
||||
{
|
||||
return *(*this + n);
|
||||
}
|
||||
|
||||
protected:
|
||||
Iterator current;
|
||||
};
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr bool
|
||||
operator==(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs)
|
||||
{
|
||||
return lhs.base() == rhs.base();
|
||||
}
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr bool
|
||||
operator!=(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs)
|
||||
{
|
||||
return lhs.base() != rhs.base();
|
||||
}
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr bool
|
||||
operator<(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs)
|
||||
{
|
||||
return rhs.base() < lhs.base();
|
||||
}
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr bool
|
||||
operator<=(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr bool
|
||||
operator>(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr bool
|
||||
operator>=(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
constexpr reverse_iterator<Iterator>
|
||||
operator+(typename reverse_iterator<Iterator>::difference_type n,
|
||||
const reverse_iterator<Iterator>& it)
|
||||
{
|
||||
return reverse_iterator<Iterator>(it.base() - n);
|
||||
}
|
||||
|
||||
template<class Iterator1, class Iterator2>
|
||||
constexpr auto
|
||||
operator-(const reverse_iterator<Iterator1>& lhs,
|
||||
const reverse_iterator<Iterator2>& rhs) -> decltype(rhs.base() -
|
||||
lhs.base())
|
||||
{
|
||||
return rhs.base() - lhs.base();
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_REVERSE_ITERATOR_H_
|
|
@ -41,25 +41,14 @@ string::destroy_big() noexcept
|
|||
void
|
||||
string::init_big(const string& s) noexcept
|
||||
{
|
||||
char* p2;
|
||||
#ifndef NDEBUG
|
||||
if (!s.isbig())
|
||||
__builtin_trap();
|
||||
#endif
|
||||
if (s.size() >= s.capacity() >> 1) {
|
||||
if (!(p2 = (char*)malloc(s.capacity())))
|
||||
__builtin_trap();
|
||||
set_big_string(p2, s.size(), s.capacity());
|
||||
} else {
|
||||
init_big(string_view(s));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
string::init_big(const string_view s) noexcept
|
||||
{
|
||||
size_t need;
|
||||
char* p2;
|
||||
size_t need;
|
||||
if (ckd_add(&need, s.n, 1 /* nul */ + 15))
|
||||
__builtin_trap();
|
||||
need &= -16;
|
||||
|
|
59
ctl/string.h
59
ctl/string.h
|
@ -2,6 +2,7 @@
|
|||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_STRING_H_
|
||||
#define CTL_STRING_H_
|
||||
#include "reverse_iterator.h"
|
||||
#include "string_view.h"
|
||||
|
||||
namespace ctl {
|
||||
|
@ -44,8 +45,18 @@ struct big_string
|
|||
class string
|
||||
{
|
||||
public:
|
||||
using iterator = char*;
|
||||
using const_iterator = const char*;
|
||||
using value_type = char;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = ctl::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = ctl::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
string() noexcept
|
||||
|
@ -189,9 +200,9 @@ class string
|
|||
return data();
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return data() + size();
|
||||
return data();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept
|
||||
|
@ -199,11 +210,51 @@ class string
|
|||
return data();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(cbegin());
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(cbegin());
|
||||
}
|
||||
|
||||
char& front()
|
||||
{
|
||||
if (!size())
|
||||
|
|
123
ctl/type_traits.h
Normal file
123
ctl/type_traits.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_TYPE_TRAITS_H_
|
||||
#define CTL_TYPE_TRAITS_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant
|
||||
{
|
||||
static constexpr T value = v;
|
||||
using value_type = T;
|
||||
using type = integral_constant;
|
||||
constexpr operator value_type() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
constexpr value_type operator()() const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
using true_type = integral_constant<bool, true>;
|
||||
using false_type = integral_constant<bool, false>;
|
||||
|
||||
template<typename T>
|
||||
struct is_integral : false_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<bool> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<char> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<signed char> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned char> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<short> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned short> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<int> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned int> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<long> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned long> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<long long> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<unsigned long long> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<char16_t> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<char32_t> : true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_integral<wchar_t> : true_type
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_integral_v = is_integral<T>::value;
|
||||
|
||||
template<typename T>
|
||||
struct is_signed
|
||||
{
|
||||
static constexpr bool value = T(0) > T(-1);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_unsigned
|
||||
{
|
||||
static constexpr bool value = T(0) < T(-1);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct is_same
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_same<T, T>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
inline constexpr bool is_same_v = is_same<T, U>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_TYPE_TRAITS_H_
|
29
ctl/uninitialized_fill.h
Normal file
29
ctl/uninitialized_fill.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_UNINITIALIZED_FILL_H_
|
||||
#define CTL_UNINITIALIZED_FILL_H_
|
||||
#include "addressof.h"
|
||||
#include "iterator_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename ForwardIt, typename T>
|
||||
void
|
||||
uninitialized_fill(ForwardIt first, ForwardIt last, const T& value)
|
||||
{
|
||||
using ValueType = typename ctl::iterator_traits<ForwardIt>::value_type;
|
||||
ForwardIt current = first;
|
||||
try {
|
||||
for (; current != last; ++current)
|
||||
::new (static_cast<void*>(ctl::addressof(*current)))
|
||||
ValueType(value);
|
||||
} catch (...) {
|
||||
for (; first != current; ++first)
|
||||
first->~ValueType();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_UNINITIALIZED_FILL_H_
|
52
ctl/uninitialized_fill_n.h
Normal file
52
ctl/uninitialized_fill_n.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_UNINITIALIZED_FILL_N_H_
|
||||
#define CTL_UNINITIALIZED_FILL_N_H_
|
||||
#include "addressof.h"
|
||||
#include "allocator_traits.h"
|
||||
#include "iterator_traits.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename ForwardIt, typename Size, typename T>
|
||||
ForwardIt
|
||||
uninitialized_fill_n(ForwardIt first, Size n, const T& value)
|
||||
{
|
||||
using ValueType = typename ctl::iterator_traits<ForwardIt>::value_type;
|
||||
ForwardIt current = first;
|
||||
try {
|
||||
for (; n > 0; ++current, --n) {
|
||||
::new (static_cast<void*>(ctl::addressof(*current)))
|
||||
ValueType(value);
|
||||
}
|
||||
return current;
|
||||
} catch (...) {
|
||||
for (; first != current; ++first) {
|
||||
first->~ValueType();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ForwardIt, typename Size, typename T, typename Alloc>
|
||||
ForwardIt
|
||||
uninitialized_fill_n(ForwardIt first, Size n, const T& value, Alloc& alloc)
|
||||
{
|
||||
using AllocTraits = ctl::allocator_traits<Alloc>;
|
||||
ForwardIt current = first;
|
||||
try {
|
||||
for (; n > 0; ++current, --n) {
|
||||
AllocTraits::construct(alloc, ctl::addressof(*current), value);
|
||||
}
|
||||
return current;
|
||||
} catch (...) {
|
||||
for (; first != current; ++first) {
|
||||
AllocTraits::destroy(alloc, ctl::addressof(*first));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_UNINITIALIZED_FILL_N_H_
|
52
ctl/uninitialized_move_n.h
Normal file
52
ctl/uninitialized_move_n.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_UNINITIALIZED_MOVE_N_H_
|
||||
#define CTL_UNINITIALIZED_MOVE_N_H_
|
||||
#include "addressof.h"
|
||||
#include "allocator_traits.h"
|
||||
#include "iterator_traits.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename InputIt, typename Size, typename ForwardIt>
|
||||
ForwardIt
|
||||
uninitialized_move_n(InputIt first, Size n, ForwardIt d_first)
|
||||
{
|
||||
using T = typename ctl::iterator_traits<ForwardIt>::value_type;
|
||||
ForwardIt current = d_first;
|
||||
try {
|
||||
for (; n > 0; ++first, (void)++current, --n) {
|
||||
::new (static_cast<void*>(ctl::addressof(*current)))
|
||||
T(ctl::move(*first));
|
||||
}
|
||||
} catch (...) {
|
||||
for (; d_first != current; ++d_first) {
|
||||
d_first->~T();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
template<typename InputIt, typename Size, typename ForwardIt, typename Alloc>
|
||||
ForwardIt
|
||||
uninitialized_move_n(InputIt first, Size n, ForwardIt d_first, Alloc& alloc)
|
||||
{
|
||||
using AllocTraits = ctl::allocator_traits<Alloc>;
|
||||
ForwardIt current = d_first;
|
||||
try {
|
||||
for (; n > 0; ++first, (void)++current, --n)
|
||||
AllocTraits::construct(
|
||||
alloc, ctl::addressof(*current), ctl::move(*first));
|
||||
} catch (...) {
|
||||
for (; d_first != current; ++d_first)
|
||||
AllocTraits::destroy(alloc, ctl::addressof(*d_first));
|
||||
throw;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_UNINITIALIZED_MOVE_N_H_
|
633
ctl/vector.h
633
ctl/vector.h
|
@ -1,245 +1,594 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#define COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#include "new.h"
|
||||
#include "utility.h"
|
||||
#ifndef CTL_VECTOR_H_
|
||||
#define CTL_VECTOR_H_
|
||||
#include "allocator.h"
|
||||
#include "allocator_traits.h"
|
||||
#include "copy.h"
|
||||
#include "distance.h"
|
||||
#include "equal.h"
|
||||
#include "fill_n.h"
|
||||
#include "initializer_list.h"
|
||||
#include "iterator_traits.h"
|
||||
#include "lexicographical_compare.h"
|
||||
#include "max.h"
|
||||
#include "move_backward.h"
|
||||
#include "move_iterator.h"
|
||||
#include "out_of_range.h"
|
||||
#include "reverse_iterator.h"
|
||||
#include "uninitialized_fill.h"
|
||||
#include "uninitialized_fill_n.h"
|
||||
#include "uninitialized_move_n.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct vector
|
||||
template<typename T, typename Allocator = ctl::allocator<T>>
|
||||
class vector
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t c = 0;
|
||||
T* p = nullptr;
|
||||
public:
|
||||
using value_type = T;
|
||||
using allocator_type = Allocator;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = typename ctl::allocator_traits<Allocator>::pointer;
|
||||
using const_pointer =
|
||||
typename ctl::allocator_traits<Allocator>::const_pointer;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = ctl::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = ctl::reverse_iterator<const_iterator>;
|
||||
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
|
||||
vector() = default;
|
||||
|
||||
~vector()
|
||||
public:
|
||||
vector() noexcept(noexcept(Allocator()))
|
||||
: alloc_(), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
delete[] p;
|
||||
}
|
||||
|
||||
explicit vector(const Allocator& alloc) noexcept
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
}
|
||||
|
||||
vector(size_type count,
|
||||
const T& value,
|
||||
const Allocator& alloc = Allocator())
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
assign(count, value);
|
||||
}
|
||||
|
||||
explicit vector(size_type count, const Allocator& alloc = Allocator())
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
resize(count);
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator())
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
assign(first, last);
|
||||
}
|
||||
|
||||
vector(const vector& other)
|
||||
: alloc_(ctl::allocator_traits<
|
||||
Allocator>::select_on_container_copy_construction(other.alloc_))
|
||||
, data_(nullptr)
|
||||
, size_(0)
|
||||
, capacity_(0)
|
||||
{
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
p = new T[c];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
new (&p[i]) T(other.p[i]);
|
||||
assign(other.begin(), other.end());
|
||||
}
|
||||
|
||||
vector(const vector& other, const Allocator& alloc)
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
assign(other.begin(), other.end());
|
||||
}
|
||||
|
||||
vector(vector&& other) noexcept
|
||||
: alloc_(ctl::move(other.alloc_))
|
||||
, data_(other.data_)
|
||||
, size_(other.size_)
|
||||
, capacity_(other.capacity_)
|
||||
{
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
p = other.p;
|
||||
other.n = 0;
|
||||
other.c = 0;
|
||||
other.p = nullptr;
|
||||
other.data_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
}
|
||||
|
||||
explicit vector(size_t count, const T& value = T())
|
||||
vector(vector&& other, const Allocator& alloc)
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
n = count;
|
||||
c = count;
|
||||
p = new T[c];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
new (&p[i]) T(value);
|
||||
if (alloc_ == other.alloc_) {
|
||||
data_ = other.data_;
|
||||
size_ = other.size_;
|
||||
capacity_ = other.capacity_;
|
||||
other.data_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
} else {
|
||||
assign(ctl::make_move_iterator(other.begin()),
|
||||
ctl::make_move_iterator(other.end()));
|
||||
}
|
||||
}
|
||||
|
||||
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator())
|
||||
: alloc_(alloc), data_(nullptr), size_(0), capacity_(0)
|
||||
{
|
||||
assign(init.begin(), init.end());
|
||||
}
|
||||
|
||||
~vector()
|
||||
{
|
||||
clear();
|
||||
ctl::allocator_traits<Allocator>::deallocate(alloc_, data_, capacity_);
|
||||
}
|
||||
|
||||
vector& operator=(const vector& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
T* newData = new T[other.c];
|
||||
for (size_t i = 0; i < other.n; ++i) {
|
||||
newData[i] = other.p[i];
|
||||
}
|
||||
delete[] p;
|
||||
p = newData;
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
if (ctl::allocator_traits<
|
||||
Allocator>::propagate_on_container_copy_assignment::value)
|
||||
alloc_ = other.alloc_;
|
||||
assign(other.begin(), other.end());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector& operator=(vector&& other) noexcept
|
||||
vector& operator=(vector&& other) noexcept(
|
||||
ctl::allocator_traits<Allocator>::is_always_equal::value)
|
||||
{
|
||||
if (this != &other) {
|
||||
delete[] p;
|
||||
p = other.p;
|
||||
n = other.n;
|
||||
c = other.c;
|
||||
other.p = nullptr;
|
||||
other.n = 0;
|
||||
other.c = 0;
|
||||
clear();
|
||||
ctl::allocator_traits<Allocator>::deallocate(
|
||||
alloc_, data_, capacity_);
|
||||
if (ctl::allocator_traits<
|
||||
Allocator>::propagate_on_container_move_assignment::value)
|
||||
alloc_ = ctl::move(other.alloc_);
|
||||
data_ = other.data_;
|
||||
size_ = other.size_;
|
||||
capacity_ = other.capacity_;
|
||||
other.data_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
vector& operator=(std::initializer_list<T> ilist)
|
||||
{
|
||||
return !n;
|
||||
assign(ilist.begin(), ilist.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
void assign(size_type count, const T& value)
|
||||
{
|
||||
return n;
|
||||
clear();
|
||||
if (count > capacity_)
|
||||
reallocate(count);
|
||||
ctl::uninitialized_fill_n(data_, count, value);
|
||||
size_ = count;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
template<class InputIt>
|
||||
void assign(InputIt first, InputIt last)
|
||||
{
|
||||
return c;
|
||||
clear();
|
||||
for (; first != last; ++first)
|
||||
push_back(*first);
|
||||
}
|
||||
|
||||
T& operator[](size_t i)
|
||||
void assign(std::initializer_list<T> ilist)
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
assign(ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
const T& operator[](size_t i) const
|
||||
reference at(size_type pos)
|
||||
{
|
||||
if (i >= n)
|
||||
__builtin_trap();
|
||||
return p[i];
|
||||
if (pos >= size_)
|
||||
throw ctl::out_of_range("out of range");
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
const_reference at(size_type pos) const
|
||||
{
|
||||
return p;
|
||||
if (pos >= size_)
|
||||
throw ctl::out_of_range("out of range");
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
iterator end()
|
||||
reference operator[](size_type pos)
|
||||
{
|
||||
return p + n;
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
const_reference operator[](size_type pos) const
|
||||
{
|
||||
return p;
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
reference front()
|
||||
{
|
||||
return p + n;
|
||||
return data_[0];
|
||||
}
|
||||
|
||||
T& front()
|
||||
const_reference front() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
return data_[0];
|
||||
}
|
||||
|
||||
const T& front() const
|
||||
reference back()
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[0];
|
||||
return data_[size_ - 1];
|
||||
}
|
||||
|
||||
T& back()
|
||||
const_reference back() const
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
return data_[size_ - 1];
|
||||
}
|
||||
|
||||
const T& back() const
|
||||
T* data() noexcept
|
||||
{
|
||||
if (!n)
|
||||
__builtin_trap();
|
||||
return p[n - 1];
|
||||
return data_;
|
||||
}
|
||||
|
||||
void clear()
|
||||
const T* data() const noexcept
|
||||
{
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
p[i].~T();
|
||||
n = 0;
|
||||
return data_;
|
||||
}
|
||||
|
||||
void reserve(size_t c2)
|
||||
iterator begin() noexcept
|
||||
{
|
||||
if (c2 <= c)
|
||||
return;
|
||||
T* newP = new T[c2];
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
newP[i] = ctl::move(p[i]);
|
||||
delete[] p;
|
||||
p = newP;
|
||||
c = c2;
|
||||
return data_;
|
||||
}
|
||||
|
||||
void push_back(const T& e)
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
if (n == c) {
|
||||
size_t c2 = c + 1;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(e);
|
||||
++n;
|
||||
return data_;
|
||||
}
|
||||
|
||||
void push_back(T&& e)
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
if (n == c) {
|
||||
size_t c2 = c + 1;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
}
|
||||
new (&p[n]) T(ctl::forward<T>(e));
|
||||
++n;
|
||||
return data_;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void emplace_back(Args&&... args)
|
||||
iterator end() noexcept
|
||||
{
|
||||
if (n == c) {
|
||||
size_t c2 = c + 1;
|
||||
c2 += c2 >> 1;
|
||||
reserve(c2);
|
||||
return data_ + size_;
|
||||
}
|
||||
new (&p[n]) T(ctl::forward<Args>(args)...);
|
||||
++n;
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
|
||||
reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return __PTRDIFF_MAX__;
|
||||
}
|
||||
|
||||
size_type capacity() const noexcept
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
void reserve(size_type new_cap)
|
||||
{
|
||||
if (new_cap > capacity_)
|
||||
reallocate(new_cap);
|
||||
}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
if (size_ < capacity_)
|
||||
reallocate(size_);
|
||||
}
|
||||
|
||||
void clear() noexcept
|
||||
{
|
||||
for (size_type i = 0; i < size_; ++i)
|
||||
ctl::allocator_traits<Allocator>::destroy(alloc_, data_ + i);
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, const T& value)
|
||||
{
|
||||
return insert(pos, 1, value);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, T&& value)
|
||||
{
|
||||
difference_type index = pos - begin();
|
||||
if (size_ == capacity_)
|
||||
grow();
|
||||
iterator it = begin() + index;
|
||||
ctl::move_backward(it, end(), end() + 1);
|
||||
*it = ctl::move(value);
|
||||
++size_;
|
||||
return it;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, size_type count, const T& value)
|
||||
{
|
||||
difference_type index = pos - begin();
|
||||
if (size_ + count > capacity_)
|
||||
reallocate(ctl::max(size_ + count, capacity_ * 2));
|
||||
iterator it = begin() + index;
|
||||
ctl::move_backward(it, end(), end() + count);
|
||||
ctl::fill_n(it, count, value);
|
||||
size_ += count;
|
||||
return it;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
iterator insert(const_iterator pos, InputIt first, InputIt last)
|
||||
{
|
||||
difference_type count = ctl::distance(first, last);
|
||||
difference_type index = pos - begin();
|
||||
if (size_ + count > capacity_)
|
||||
reallocate(ctl::max(size_ + count, capacity_ * 2));
|
||||
iterator it = begin() + index;
|
||||
ctl::move_backward(it, end(), end() + count);
|
||||
ctl::copy(first, last, it);
|
||||
size_ += count;
|
||||
return it;
|
||||
}
|
||||
|
||||
iterator insert(const_iterator pos, std::initializer_list<T> ilist)
|
||||
{
|
||||
return insert(pos, ilist.begin(), ilist.end());
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
iterator emplace(const_iterator pos, Args&&... args)
|
||||
{
|
||||
difference_type index = pos - begin();
|
||||
if (size_ == capacity_)
|
||||
grow();
|
||||
iterator it = begin() + index;
|
||||
ctl::move_backward(it, end(), end() + 1);
|
||||
ctl::allocator_traits<Allocator>::construct(
|
||||
alloc_, it, ctl::forward<Args>(args)...);
|
||||
++size_;
|
||||
return it;
|
||||
}
|
||||
|
||||
iterator erase(const_iterator pos)
|
||||
{
|
||||
return erase(pos, pos + 1);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
difference_type index = first - begin();
|
||||
difference_type count = last - first;
|
||||
iterator it = begin() + index;
|
||||
ctl::move(it + count, end(), it);
|
||||
for (difference_type i = 0; i < count; ++i)
|
||||
ctl::allocator_traits<Allocator>::destroy(alloc_, end() - i - 1);
|
||||
size_ -= count;
|
||||
return it;
|
||||
}
|
||||
|
||||
void push_back(const T& value)
|
||||
{
|
||||
if (size_ == capacity_)
|
||||
grow();
|
||||
ctl::allocator_traits<Allocator>::construct(
|
||||
alloc_, data_ + size_, value);
|
||||
++size_;
|
||||
}
|
||||
|
||||
void push_back(T&& value)
|
||||
{
|
||||
if (size_ == capacity_)
|
||||
grow();
|
||||
ctl::allocator_traits<Allocator>::construct(
|
||||
alloc_, data_ + size_, ctl::move(value));
|
||||
++size_;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
reference emplace_back(Args&&... args)
|
||||
{
|
||||
if (size_ == capacity_)
|
||||
grow();
|
||||
ctl::allocator_traits<Allocator>::construct(
|
||||
alloc_, data_ + size_, ctl::forward<Args>(args)...);
|
||||
return data_[size_++];
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
if (n > 0) {
|
||||
--n;
|
||||
p[n].~T();
|
||||
if (!empty()) {
|
||||
ctl::allocator_traits<Allocator>::destroy(alloc_,
|
||||
data_ + size_ - 1);
|
||||
--size_;
|
||||
}
|
||||
}
|
||||
|
||||
void resize(size_t n2)
|
||||
void resize(size_type count)
|
||||
{
|
||||
if (n2 > n) {
|
||||
reserve(n2);
|
||||
for (size_t i = n; i < n2; ++i)
|
||||
new (&p[i]) T();
|
||||
} else if (n2 < n) {
|
||||
for (size_t i = n2; i < n; ++i)
|
||||
p[i].~T();
|
||||
}
|
||||
n = n2;
|
||||
resize(count, T());
|
||||
}
|
||||
|
||||
void swap(vector& other) noexcept
|
||||
void resize(size_type count, const value_type& value)
|
||||
{
|
||||
ctl::swap(n, other.n);
|
||||
ctl::swap(c, other.c);
|
||||
ctl::swap(p, other.p);
|
||||
if (count > size_) {
|
||||
if (count > capacity_)
|
||||
reallocate(count);
|
||||
ctl::uninitialized_fill(data_ + size_, data_ + count, value);
|
||||
} else if (count < size_) {
|
||||
for (size_type i = count; i < size_; ++i)
|
||||
ctl::allocator_traits<Allocator>::destroy(alloc_, data_ + i);
|
||||
}
|
||||
size_ = count;
|
||||
}
|
||||
|
||||
void swap(vector& other) noexcept(
|
||||
ctl::allocator_traits<Allocator>::is_always_equal::value)
|
||||
{
|
||||
using ctl::swap;
|
||||
swap(alloc_, other.alloc_);
|
||||
swap(data_, other.data_);
|
||||
swap(size_, other.size_);
|
||||
swap(capacity_, other.capacity_);
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const noexcept
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
private:
|
||||
void grow()
|
||||
{
|
||||
size_type c2;
|
||||
c2 = capacity_;
|
||||
if (c2 < 4)
|
||||
c2 = 4;
|
||||
c2 += c2 >> 1;
|
||||
reallocate(c2);
|
||||
}
|
||||
|
||||
void reallocate(size_type new_capacity)
|
||||
{
|
||||
pointer new_data =
|
||||
ctl::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
|
||||
size_type new_size = size_ < new_capacity ? size_ : new_capacity;
|
||||
try {
|
||||
ctl::uninitialized_move_n(data_, new_size, new_data);
|
||||
} catch (...) {
|
||||
ctl::allocator_traits<Allocator>::deallocate(
|
||||
alloc_, new_data, new_capacity);
|
||||
throw;
|
||||
}
|
||||
for (size_type i = 0; i < size_; ++i)
|
||||
ctl::allocator_traits<Allocator>::destroy(alloc_, data_ + i);
|
||||
ctl::allocator_traits<Allocator>::deallocate(alloc_, data_, capacity_);
|
||||
data_ = new_data;
|
||||
size_ = new_size;
|
||||
capacity_ = new_capacity;
|
||||
}
|
||||
|
||||
Allocator alloc_;
|
||||
pointer data_;
|
||||
size_type size_;
|
||||
size_type capacity_;
|
||||
};
|
||||
|
||||
template<class T, class Alloc>
|
||||
bool
|
||||
operator==(const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs)
|
||||
{
|
||||
return lhs.size() == rhs.size() &&
|
||||
ctl::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
template<class T, class Alloc>
|
||||
bool
|
||||
operator!=(const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<class T, class Alloc>
|
||||
bool
|
||||
operator<(const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs)
|
||||
{
|
||||
return ctl::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
template<class T, class Alloc>
|
||||
bool
|
||||
operator<=(const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<class T, class Alloc>
|
||||
bool
|
||||
operator>(const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<class T, class Alloc>
|
||||
bool
|
||||
operator>=(const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<class T, class Alloc>
|
||||
void
|
||||
swap(vector<T, Alloc>& lhs,
|
||||
vector<T, Alloc>& rhs) noexcept(noexcept(lhs.swap(rhs)))
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template<class InputIt,
|
||||
class Alloc =
|
||||
ctl::allocator<typename ctl::iterator_traits<InputIt>::value_type>>
|
||||
vector(InputIt, InputIt, Alloc = Alloc())
|
||||
-> vector<typename ctl::iterator_traits<InputIt>::value_type, Alloc>;
|
||||
|
||||
template<class Alloc>
|
||||
vector(size_t,
|
||||
const typename ctl::allocator_traits<Alloc>::value_type&,
|
||||
Alloc = Alloc())
|
||||
-> vector<typename ctl::allocator_traits<Alloc>::value_type, Alloc>;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_OPTIONAL_H_
|
||||
#endif // CTL_VECTOR_H_
|
||||
|
|
|
@ -17,6 +17,10 @@ TEST_CTL_DIRECTDEPS = \
|
|||
LIBC_STDIO \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_LIBCXX \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
THIRD_PARTY_LIBUNWIND \
|
||||
|
||||
TEST_CTL_DEPS := \
|
||||
$(call uniq,$(foreach x,$(TEST_CTL_DIRECTDEPS),$($(x))))
|
||||
|
@ -33,6 +37,10 @@ o/$(MODE)/test/ctl/%.dbg: \
|
|||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
$(TEST_CTL_OBJS): private \
|
||||
OVERRIDE_CXXFLAGS += \
|
||||
-fexceptions \
|
||||
|
||||
.PHONY: o/$(MODE)/test/ctl
|
||||
o/$(MODE)/test/ctl: \
|
||||
$(TEST_CTL_BINS) \
|
||||
|
|
51
test/ctl/accumulate_test.cc
Normal file
51
test/ctl/accumulate_test.cc
Normal file
|
@ -0,0 +1,51 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/accumulate.h"
|
||||
#include "ctl/array.h"
|
||||
|
||||
// #include <array>
|
||||
// #include <numeric>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
|
||||
// Test basic accumulation with addition
|
||||
if (ctl::accumulate(arr.begin(), arr.end(), 0) != 15)
|
||||
return 1;
|
||||
|
||||
// Test accumulation with initial value
|
||||
if (ctl::accumulate(arr.begin(), arr.end(), 10) != 25)
|
||||
return 2;
|
||||
|
||||
// Test accumulation with custom operation (multiplication)
|
||||
if (ctl::accumulate(
|
||||
arr.begin(), arr.end(), 1, [](int a, int b) { return a * b; }) != 120)
|
||||
return 3;
|
||||
|
||||
// Test accumulation with empty range
|
||||
if (ctl::accumulate(arr.end(), arr.end(), 0) != 0)
|
||||
return 4;
|
||||
|
||||
// Test accumulation with single element
|
||||
if (ctl::accumulate(arr.begin(), arr.begin() + 1, 0) != 1)
|
||||
return 5;
|
||||
}
|
56
test/ctl/advance_test.cc
Normal file
56
test/ctl/advance_test.cc
Normal file
|
@ -0,0 +1,56 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/advance.h"
|
||||
#include "ctl/array.h"
|
||||
|
||||
// #include <array>
|
||||
// #include <iterator>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
|
||||
// Test advancing forward
|
||||
auto it = arr.begin();
|
||||
ctl::advance(it, 2);
|
||||
if (*it != 3)
|
||||
return 1;
|
||||
|
||||
// Test advancing to the end
|
||||
ctl::advance(it, 2);
|
||||
if (it != arr.end() - 1)
|
||||
return 2;
|
||||
|
||||
// Test advancing backward
|
||||
ctl::advance(it, -2);
|
||||
if (*it != 3)
|
||||
return 3;
|
||||
|
||||
// Test advancing by zero
|
||||
ctl::advance(it, 0);
|
||||
if (*it != 3)
|
||||
return 4;
|
||||
|
||||
// Test advancing to the beginning
|
||||
ctl::advance(it, -2);
|
||||
if (it != arr.begin())
|
||||
return 5;
|
||||
}
|
52
test/ctl/all_of_test.cc
Normal file
52
test/ctl/all_of_test.cc
Normal file
|
@ -0,0 +1,52 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/all_of.h"
|
||||
#include "ctl/array.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
ctl::array<int, 5> arr1 = { 2, 4, 6, 8, 10 };
|
||||
ctl::array<int, 5> arr2 = { 2, 4, 5, 8, 10 };
|
||||
|
||||
// Test when all elements satisfy the condition
|
||||
if (!ctl::all_of(
|
||||
arr1.begin(), arr1.end(), [](int n) { return n % 2 == 0; }))
|
||||
return 1;
|
||||
|
||||
// Test when not all elements satisfy the condition
|
||||
if (ctl::all_of(arr2.begin(), arr2.end(), [](int n) { return n % 2 == 0; }))
|
||||
return 2;
|
||||
|
||||
// Test with empty range
|
||||
if (!ctl::all_of(arr1.end(), arr1.end(), [](int n) { return false; }))
|
||||
return 3;
|
||||
|
||||
// Test with all elements satisfying a different condition
|
||||
if (!ctl::all_of(arr1.begin(), arr1.end(), [](int n) { return n > 0; }))
|
||||
return 4;
|
||||
|
||||
// Test with no elements satisfying the condition
|
||||
if (ctl::all_of(arr1.begin(), arr1.end(), [](int n) { return n > 10; }))
|
||||
return 5;
|
||||
}
|
51
test/ctl/any_of_test.cc
Normal file
51
test/ctl/any_of_test.cc
Normal file
|
@ -0,0 +1,51 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/any_of.h"
|
||||
#include "ctl/array.h"
|
||||
|
||||
// #include <algorithm>
|
||||
// #include <array>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
ctl::array<int, 5> arr1 = { 1, 3, 5, 7, 9 };
|
||||
ctl::array<int, 5> arr2 = { 2, 4, 6, 8, 10 };
|
||||
|
||||
// Test when at least one element satisfies the condition
|
||||
if (!ctl::any_of(arr1.begin(), arr1.end(), [](int n) { return n == 7; }))
|
||||
return 1;
|
||||
|
||||
// Test when no elements satisfy the condition
|
||||
if (ctl::any_of(arr1.begin(), arr1.end(), [](int n) { return n == 11; }))
|
||||
return 2;
|
||||
|
||||
// Test with empty range
|
||||
if (ctl::any_of(arr1.end(), arr1.end(), [](int n) { return true; }))
|
||||
return 3;
|
||||
|
||||
// Test when all elements satisfy the condition
|
||||
if (!ctl::any_of(arr2.begin(), arr2.end(), [](int n) { return true; }))
|
||||
return 4;
|
||||
|
||||
// Test with a different condition
|
||||
if (!ctl::any_of(arr1.begin(), arr1.end(), [](int n) { return n > 5; }))
|
||||
return 5;
|
||||
}
|
267
test/ctl/array_test.cc
Normal file
267
test/ctl/array_test.cc
Normal file
|
@ -0,0 +1,267 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/array.h"
|
||||
|
||||
// #include <array>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
// Test construction and basic properties
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
if (arr.size() != 5)
|
||||
return 2;
|
||||
if (arr.max_size() != 5)
|
||||
return 3;
|
||||
if (arr.empty())
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Test element access
|
||||
{
|
||||
ctl::array<int, 3> arr = { 10, 20, 30 };
|
||||
if (arr[0] != 10 || arr[1] != 20 || arr[2] != 30)
|
||||
return 5;
|
||||
if (arr.front() != 10)
|
||||
return 6;
|
||||
if (arr.back() != 30)
|
||||
return 7;
|
||||
}
|
||||
|
||||
// Test data() method
|
||||
{
|
||||
ctl::array<int, 3> arr = { 1, 2, 3 };
|
||||
int* data = arr.data();
|
||||
if (data[0] != 1 || data[1] != 2 || data[2] != 3)
|
||||
return 9;
|
||||
}
|
||||
|
||||
// Test iterators
|
||||
{
|
||||
ctl::array<int, 3> arr = { 1, 2, 3 };
|
||||
int sum = 0;
|
||||
for (auto it = arr.begin(); it != arr.end(); ++it) {
|
||||
sum += *it;
|
||||
}
|
||||
if (sum != 6)
|
||||
return 10;
|
||||
|
||||
sum = 0;
|
||||
for (auto it = arr.rbegin(); it != arr.rend(); ++it) {
|
||||
sum += *it;
|
||||
}
|
||||
if (sum != 6)
|
||||
return 11;
|
||||
}
|
||||
|
||||
// Test const iterators
|
||||
{
|
||||
const ctl::array<int, 3> arr = { 1, 2, 3 };
|
||||
int sum = 0;
|
||||
for (auto it = arr.cbegin(); it != arr.cend(); ++it) {
|
||||
sum += *it;
|
||||
}
|
||||
if (sum != 6)
|
||||
return 12;
|
||||
|
||||
sum = 0;
|
||||
for (auto it = arr.crbegin(); it != arr.crend(); ++it) {
|
||||
sum += *it;
|
||||
}
|
||||
if (sum != 6)
|
||||
return 13;
|
||||
}
|
||||
|
||||
// Test fill method
|
||||
{
|
||||
ctl::array<int, 5> arr;
|
||||
arr.fill(42);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (arr[i] != 42)
|
||||
return 14;
|
||||
}
|
||||
}
|
||||
|
||||
// Test swap method
|
||||
{
|
||||
ctl::array<int, 3> arr1 = { 1, 2, 3 };
|
||||
ctl::array<int, 3> arr2 = { 4, 5, 6 };
|
||||
arr1.swap(arr2);
|
||||
if (arr1[0] != 4 || arr1[1] != 5 || arr1[2] != 6)
|
||||
return 15;
|
||||
if (arr2[0] != 1 || arr2[1] != 2 || arr2[2] != 3)
|
||||
return 16;
|
||||
}
|
||||
|
||||
// Test comparison operators
|
||||
{
|
||||
ctl::array<int, 3> arr1 = { 1, 2, 3 };
|
||||
ctl::array<int, 3> arr2 = { 1, 2, 3 };
|
||||
ctl::array<int, 3> arr3 = { 1, 2, 4 };
|
||||
|
||||
if (!(arr1 == arr2))
|
||||
return 17;
|
||||
if (arr1 != arr2)
|
||||
return 18;
|
||||
if (!(arr1 < arr3))
|
||||
return 19;
|
||||
if (arr3 <= arr1)
|
||||
return 20;
|
||||
if (!(arr3 > arr1))
|
||||
return 21;
|
||||
if (arr1 >= arr3)
|
||||
return 22;
|
||||
}
|
||||
|
||||
// Test non-member swap function
|
||||
{
|
||||
ctl::array<int, 3> arr1 = { 1, 2, 3 };
|
||||
ctl::array<int, 3> arr2 = { 4, 5, 6 };
|
||||
swap(arr1, arr2);
|
||||
if (arr1[0] != 4 || arr1[1] != 5 || arr1[2] != 6)
|
||||
return 23;
|
||||
if (arr2[0] != 1 || arr2[1] != 2 || arr2[2] != 3)
|
||||
return 24;
|
||||
}
|
||||
|
||||
// Test with non-trivial type
|
||||
{
|
||||
struct NonTrivial
|
||||
{
|
||||
int value;
|
||||
|
||||
NonTrivial(int v = 0) : value(v)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const NonTrivial& other) const
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
ctl::array<NonTrivial, 3> arr = { 1, 2, 3 };
|
||||
if (arr[0].value != 1 || arr[1].value != 2 || arr[2].value != 3)
|
||||
return 25;
|
||||
}
|
||||
|
||||
// Test empty array
|
||||
{
|
||||
ctl::array<int, 0> arr;
|
||||
if (!arr.empty())
|
||||
return 26;
|
||||
if (arr.size() != 0)
|
||||
return 27;
|
||||
if (arr.begin() != arr.end())
|
||||
return 28;
|
||||
}
|
||||
|
||||
// Test basic array functionality
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
if (arr.size() != 5)
|
||||
return 2;
|
||||
if (arr[0] != 1 || arr[4] != 5)
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Test reverse iterator basics
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
auto rit = arr.rbegin();
|
||||
if (*rit != 5)
|
||||
return 4;
|
||||
++rit;
|
||||
if (*rit != 4)
|
||||
return 5;
|
||||
if (*(arr.rbegin() + 2) != 3)
|
||||
return 6;
|
||||
}
|
||||
|
||||
// Test reverse iterator traversal
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
int expected = 5;
|
||||
for (auto rit = arr.rbegin(); rit != arr.rend(); ++rit) {
|
||||
if (*rit != expected)
|
||||
return 7;
|
||||
--expected;
|
||||
}
|
||||
}
|
||||
|
||||
// Test const reverse iterator
|
||||
{
|
||||
const ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
auto crit = arr.crbegin();
|
||||
if (*crit != 5)
|
||||
return 8;
|
||||
++crit;
|
||||
if (*crit != 4)
|
||||
return 9;
|
||||
}
|
||||
|
||||
// Test reverse iterator arithmetic
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
auto rit = arr.rbegin();
|
||||
rit += 2;
|
||||
if (*rit != 3)
|
||||
return 10;
|
||||
rit -= 1;
|
||||
if (*rit != 4)
|
||||
return 11;
|
||||
if (*(rit + 2) != 2)
|
||||
return 12;
|
||||
if (*(rit - 1) != 5)
|
||||
return 13;
|
||||
}
|
||||
|
||||
// Test reverse iterator comparison
|
||||
{
|
||||
ctl::array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
auto rit1 = arr.rbegin();
|
||||
auto rit2 = arr.rbegin() + 2;
|
||||
if (rit1 >= rit2)
|
||||
return 14;
|
||||
if (!(rit1 < rit2))
|
||||
return 15;
|
||||
if (rit1 == rit2)
|
||||
return 16;
|
||||
}
|
||||
|
||||
// Test it seems legit
|
||||
{
|
||||
ctl::array<int, 3> arr = { 1, 2, 3 };
|
||||
auto rit = arr.rbegin();
|
||||
if (*rit != 3)
|
||||
return 1;
|
||||
++rit;
|
||||
if (*rit != 2)
|
||||
return 2;
|
||||
++rit;
|
||||
if (*rit != 1)
|
||||
return 3;
|
||||
++rit;
|
||||
if (rit != arr.rend())
|
||||
return 4;
|
||||
}
|
||||
}
|
61
test/ctl/back_inserter_test.cc
Normal file
61
test/ctl/back_inserter_test.cc
Normal file
|
@ -0,0 +1,61 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/array.h"
|
||||
#include "ctl/back_inserter.h"
|
||||
#include "ctl/copy.h"
|
||||
#include "ctl/vector.h"
|
||||
|
||||
// #include <array>
|
||||
// #include <iterator>
|
||||
// #include <vector>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
ctl::vector<int> vec = { 1, 2, 3 };
|
||||
ctl::array<int, 3> arr = { 4, 5, 6 };
|
||||
|
||||
// Use back_inserter to append elements from arr to vec
|
||||
ctl::copy(arr.begin(), arr.end(), ctl::back_inserter(vec));
|
||||
|
||||
// Check if vec now contains all elements
|
||||
if (vec.size() != 6)
|
||||
return 1;
|
||||
if (vec[0] != 1 || vec[1] != 2 || vec[2] != 3 || vec[3] != 4 ||
|
||||
vec[4] != 5 || vec[5] != 6)
|
||||
return 2;
|
||||
|
||||
// Use back_inserter with a single element
|
||||
ctl::back_inserter(vec) = 7;
|
||||
|
||||
// Check if the new element was added
|
||||
if (vec.size() != 7)
|
||||
return 3;
|
||||
if (vec[6] != 7)
|
||||
return 4;
|
||||
|
||||
// Test with an empty source range
|
||||
ctl::array<int, 0> empty_arr;
|
||||
ctl::copy(empty_arr.begin(), empty_arr.end(), ctl::back_inserter(vec));
|
||||
|
||||
// Check that no elements were added
|
||||
if (vec.size() != 7)
|
||||
return 5;
|
||||
}
|
66
test/ctl/copy_test.cc
Normal file
66
test/ctl/copy_test.cc
Normal file
|
@ -0,0 +1,66 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/array.h"
|
||||
#include "ctl/copy.h"
|
||||
|
||||
// #include <iterator>
|
||||
// #include <array>
|
||||
// #define ctl std
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
ctl::array<int, 5> src = { 1, 2, 3, 4, 5 };
|
||||
ctl::array<int, 5> dest = { 0, 0, 0, 0, 0 };
|
||||
|
||||
// Test basic copy
|
||||
ctl::copy(src.begin(), src.end(), dest.begin());
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
if (dest[i] != src[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test partial copy
|
||||
ctl::array<int, 5> dest2 = { 0, 0, 0, 0, 0 };
|
||||
ctl::copy(src.begin(), src.begin() + 3, dest2.begin());
|
||||
if (dest2[0] != 1 || dest2[1] != 2 || dest2[2] != 3 || dest2[3] != 0 ||
|
||||
dest2[4] != 0)
|
||||
return 2;
|
||||
|
||||
// Test copy to middle of destination
|
||||
ctl::array<int, 7> dest3 = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
ctl::copy(src.begin(), src.end(), dest3.begin() + 1);
|
||||
if (dest3[0] != 0 || dest3[1] != 1 || dest3[2] != 2 || dest3[3] != 3 ||
|
||||
dest3[4] != 4 || dest3[5] != 5 || dest3[6] != 0)
|
||||
return 3;
|
||||
|
||||
// Test copy with empty range
|
||||
ctl::array<int, 5> dest4 = { 0, 0, 0, 0, 0 };
|
||||
ctl::copy(src.begin(), src.begin(), dest4.begin());
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
if (dest4[i] != 0)
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Test copy return value
|
||||
ctl::array<int, 5> dest5 = { 0, 0, 0, 0, 0 };
|
||||
auto result = ctl::copy(src.begin(), src.end(), dest5.begin());
|
||||
if (result != dest5.end())
|
||||
return 5;
|
||||
}
|
|
@ -17,10 +17,9 @@
|
|||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/string.h"
|
||||
#include "ctl/type_traits.h"
|
||||
#include "libc/mem/leaks.h"
|
||||
|
||||
#include <__type_traits/is_same.h>
|
||||
|
||||
#include "libc/str/str.h"
|
||||
|
||||
// #include <string>
|
||||
|
@ -366,7 +365,7 @@ main()
|
|||
|
||||
{
|
||||
String s;
|
||||
if constexpr (std::is_same_v<ctl::string, decltype(s)>) {
|
||||
if constexpr (ctl::is_same_v<ctl::string, decltype(s)>) {
|
||||
// tests the small-string optimization on ctl::string
|
||||
for (int i = 0; i < 23; ++i) {
|
||||
s.append("a");
|
||||
|
@ -397,7 +396,7 @@ main()
|
|||
s.resize(4);
|
||||
if (s != "arst")
|
||||
return 105;
|
||||
if constexpr (std::is_same_v<ctl::string, decltype(s)>) {
|
||||
if constexpr (ctl::is_same_v<ctl::string, decltype(s)>) {
|
||||
String r(s);
|
||||
if (issmall(s) || !issmall(r))
|
||||
return 106;
|
||||
|
@ -405,5 +404,4 @@ main()
|
|||
}
|
||||
|
||||
CheckForMemoryLeaks();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/type_traits.h"
|
||||
#include "ctl/unique_ptr.h"
|
||||
|
||||
#include <__type_traits/is_same.h>
|
||||
#include "libc/mem/leaks.h"
|
||||
|
||||
// #include <memory>
|
||||
// #include <type_traits>
|
||||
// #define ctl std
|
||||
|
||||
template<typename T, typename D = ctl::default_delete<T>>
|
||||
|
@ -70,7 +71,7 @@ struct FinalDeleter final
|
|||
static_assert(sizeof(Ptr<int, SetsGDeleter>) == sizeof(int*));
|
||||
|
||||
// not everyone uses [[no_unique_address]]...
|
||||
static_assert(!std::is_same_v<Ptr<int>, ctl::unique_ptr<int>> ||
|
||||
static_assert(!ctl::is_same_v<Ptr<int>, ctl::unique_ptr<int>> ||
|
||||
sizeof(Ptr<int, FinalDeleter>) == sizeof(int*));
|
||||
|
||||
struct SetsGCtor
|
||||
|
@ -227,6 +228,4 @@ main()
|
|||
|
||||
// TODO(mrdomino): Fix memory leaks reported by MODE=dbg
|
||||
// CheckForMemoryLeaks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,13 +16,10 @@
|
|||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "ctl/string.h"
|
||||
#include "ctl/vector.h"
|
||||
#include "libc/mem/leaks.h"
|
||||
|
||||
#include <cosmo.h>
|
||||
|
||||
#include "ctl/string.h"
|
||||
|
||||
// #include <string>
|
||||
// #include <vector>
|
||||
// #define ctl std
|
||||
|
@ -315,6 +312,45 @@ main()
|
|||
return 69;
|
||||
}
|
||||
|
||||
{
|
||||
ctl::vector<int> A = { 1, 2, 3 };
|
||||
if (A[1] != 2)
|
||||
return 70;
|
||||
A = { 4, 5, 6 };
|
||||
if (A[1] != 5)
|
||||
return 71;
|
||||
}
|
||||
|
||||
{
|
||||
ctl::vector<int> arr = { 1, 2, 3 };
|
||||
auto rit = arr.rbegin();
|
||||
if (*rit != 3)
|
||||
return 72;
|
||||
++rit;
|
||||
if (*rit != 2)
|
||||
return 73;
|
||||
++rit;
|
||||
if (*rit != 1)
|
||||
return 74;
|
||||
++rit;
|
||||
if (rit != arr.rend())
|
||||
return 75;
|
||||
}
|
||||
|
||||
{
|
||||
ctl::vector<ctl::string> A = { "hi", "theretheretheretherethere" };
|
||||
if (A.size() != 2)
|
||||
return 76;
|
||||
if (A[0] != "hi")
|
||||
return 77;
|
||||
if (A[1] != "theretheretheretherethere")
|
||||
return 78;
|
||||
A = { "theretheretheretherethere", "hi" };
|
||||
if (A[0] != "theretheretheretherethere")
|
||||
return 79;
|
||||
if (A[1] != "hi")
|
||||
return 80;
|
||||
}
|
||||
|
||||
CheckForMemoryLeaks();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,6 @@ static void *pthread_main(void *ptr) {
|
|||
struct State *s = ptr;
|
||||
struct State children[2];
|
||||
int fd, rc;
|
||||
|
||||
fd = s->fd;
|
||||
if (s->id < 8) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
|
25
test/libc/stdio/lemur64_test.c
Normal file
25
test/libc/stdio/lemur64_test.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/rand.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(lemur64, test) {
|
||||
EXPECT_EQ(1819718037028923529, lemur64());
|
||||
EXPECT_EQ(-3120132252617434764, lemur64());
|
||||
}
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
(gcc-builtin-functions
|
||||
'("__builtin_strlen"
|
||||
"__builtin_memcpy"
|
||||
"__builtin_memmove"
|
||||
"__builtin_setjmp"
|
||||
"__builtin_longjmp"
|
||||
"__builtin_va_start"
|
||||
|
|
|
@ -771,7 +771,9 @@
|
|||
dots (cosmo-file-name-sans-extensions name))))
|
||||
(if (file-exists-p cc-version)
|
||||
cc-version
|
||||
c-version))
|
||||
(if (eq major-mode 'c++-mode)
|
||||
cc-version
|
||||
c-version)))
|
||||
))))
|
||||
(when buddy
|
||||
(find-file buddy))))))
|
||||
|
|
Loading…
Reference in a new issue