mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Add more CTL content
This commit is contained in:
parent
38921dc46b
commit
021c53ba32
56 changed files with 1747 additions and 298 deletions
55
ctl/add_lvalue_reference.h
Normal file
55
ctl/add_lvalue_reference.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// -*-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_ADD_LVALUE_REFERENCE_H_
|
||||||
|
#define CTL_ADD_LVALUE_REFERENCE_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct add_lvalue_reference
|
||||||
|
{
|
||||||
|
typedef T& type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct add_lvalue_reference<T&>
|
||||||
|
{
|
||||||
|
typedef T& type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct add_lvalue_reference<T&&>
|
||||||
|
{
|
||||||
|
typedef T& type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct add_lvalue_reference<void>
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct add_lvalue_reference<const void>
|
||||||
|
{
|
||||||
|
typedef const void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct add_lvalue_reference<volatile void>
|
||||||
|
{
|
||||||
|
typedef volatile void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct add_lvalue_reference<const volatile void>
|
||||||
|
{
|
||||||
|
typedef const volatile void type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_ADD_LVALUE_REFERENCE_H_
|
43
ctl/add_pointer.h
Normal file
43
ctl/add_pointer.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_ADD_POINTER_H_
|
||||||
|
#define CTL_ADD_POINTER_H_
|
||||||
|
#include "remove_reference.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
// Primary template
|
||||||
|
template<typename T>
|
||||||
|
struct add_pointer
|
||||||
|
{
|
||||||
|
typedef typename remove_reference<T>::type* type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for functions
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct add_pointer<R(Args...)>
|
||||||
|
{
|
||||||
|
typedef R (*type)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for function references
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct add_pointer<R (&)(Args...)>
|
||||||
|
{
|
||||||
|
typedef R (*type)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for rvalue references to functions
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
struct add_pointer<R (&&)(Args...)>
|
||||||
|
{
|
||||||
|
typedef R (*type)(Args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper alias template (C++14 and later)
|
||||||
|
template<typename T>
|
||||||
|
using add_pointer_t = typename add_pointer<T>::type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_ADD_POINTER_H_
|
|
@ -9,11 +9,9 @@ template<class InputIt, class UnaryPredicate>
|
||||||
constexpr bool
|
constexpr bool
|
||||||
all_of(InputIt first, InputIt last, UnaryPredicate p)
|
all_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||||
{
|
{
|
||||||
for (; first != last; ++first) {
|
for (; first != last; ++first)
|
||||||
if (!p(*first)) {
|
if (!p(*first))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#ifndef CTL_ALLOCATOR_H_
|
#ifndef CTL_ALLOCATOR_H_
|
||||||
#define CTL_ALLOCATOR_H_
|
#define CTL_ALLOCATOR_H_
|
||||||
#include "bad_alloc.h"
|
#include "bad_alloc.h"
|
||||||
|
#include "integral_constant.h"
|
||||||
#include "new.h"
|
#include "new.h"
|
||||||
#include "type_traits.h"
|
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
// -*-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_TRAITS_H_
|
#ifndef CTL_ALLOCATOR_TRAITS_H_
|
||||||
#define CTL_ALLOCATOR_TRAITS_H_
|
#define CTL_ALLOCATOR_TRAITS_H_
|
||||||
#include "type_traits.h"
|
#include "integral_constant.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,9 @@ template<class InputIt, class UnaryPredicate>
|
||||||
constexpr bool
|
constexpr bool
|
||||||
any_of(InputIt first, InputIt last, UnaryPredicate p)
|
any_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||||
{
|
{
|
||||||
for (; first != last; ++first) {
|
for (; first != last; ++first)
|
||||||
if (p(*first)) {
|
if (p(*first))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#ifndef CTL_ARRAY_H_
|
#ifndef CTL_ARRAY_H_
|
||||||
#define CTL_ARRAY_H_
|
#define CTL_ARRAY_H_
|
||||||
#include "initializer_list.h"
|
#include "initializer_list.h"
|
||||||
|
#include "out_of_range.h"
|
||||||
#include "reverse_iterator.h"
|
#include "reverse_iterator.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
@ -25,25 +26,25 @@ struct array
|
||||||
T elems[N];
|
T elems[N];
|
||||||
|
|
||||||
constexpr array() = default;
|
constexpr array() = default;
|
||||||
|
|
||||||
constexpr array(std::initializer_list<T> init)
|
constexpr array(std::initializer_list<T> init)
|
||||||
{
|
{
|
||||||
auto it = init.begin();
|
auto it = init.begin();
|
||||||
for (size_t i = 0; i < N && it != init.end(); ++i, ++it) {
|
for (size_t i = 0; i < N && it != init.end(); ++i, ++it)
|
||||||
elems[i] = *it;
|
elems[i] = *it;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr reference at(size_type pos)
|
constexpr reference at(size_type pos)
|
||||||
{
|
{
|
||||||
if (pos >= N)
|
if (pos >= N)
|
||||||
__builtin_trap();
|
throw ctl::out_of_range("out of range");
|
||||||
return elems[pos];
|
return elems[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_reference at(size_type pos) const
|
constexpr const_reference at(size_type pos) const
|
||||||
{
|
{
|
||||||
if (pos >= N)
|
if (pos >= N)
|
||||||
__builtin_trap();
|
throw ctl::out_of_range("out of range");
|
||||||
return elems[pos];
|
return elems[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
ctl/conditional.h
Normal file
22
ctl/conditional.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_CONDITIONAL_H_
|
||||||
|
#define CTL_CONDITIONAL_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<bool B, class T, class F>
|
||||||
|
struct conditional
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class F>
|
||||||
|
struct conditional<false, T, F>
|
||||||
|
{
|
||||||
|
typedef F type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_CONDITIONAL_H_
|
35
ctl/decay.h
Normal file
35
ctl/decay.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// -*-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_DECAY_H_
|
||||||
|
#define CTL_DECAY_H_
|
||||||
|
#include "add_pointer.h"
|
||||||
|
#include "conditional.h"
|
||||||
|
#include "is_array.h"
|
||||||
|
#include "is_function.h"
|
||||||
|
#include "remove_cv.h"
|
||||||
|
#include "remove_extent.h"
|
||||||
|
#include "remove_reference.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct decay
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename remove_reference<T>::type U;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename conditional<
|
||||||
|
is_array<U>::value,
|
||||||
|
typename remove_extent<U>::type*,
|
||||||
|
typename conditional<is_function<U>::value,
|
||||||
|
typename add_pointer<U>::type,
|
||||||
|
typename remove_cv<U>::type>::type>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using decay_t = typename decay<T>::type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_DECAY_H_
|
44
ctl/default_delete.h
Normal file
44
ctl/default_delete.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// -*-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_DEFAULT_DELETE_H_
|
||||||
|
#define CTL_DEFAULT_DELETE_H_
|
||||||
|
#include "enable_if.h"
|
||||||
|
#include "is_convertible.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct default_delete
|
||||||
|
{
|
||||||
|
constexpr default_delete() noexcept = default;
|
||||||
|
template<typename U,
|
||||||
|
typename = typename ctl::enable_if<
|
||||||
|
ctl::is_convertible<U*, T*>::value>::type>
|
||||||
|
constexpr default_delete(const default_delete<U>&) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr void operator()(T* const p) const noexcept
|
||||||
|
{
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct default_delete<T[]>
|
||||||
|
{
|
||||||
|
constexpr default_delete() noexcept = default;
|
||||||
|
template<typename U,
|
||||||
|
typename = typename ctl::enable_if<
|
||||||
|
ctl::is_convertible<U (*)[], T (*)[]>::value>::type>
|
||||||
|
constexpr default_delete(const default_delete<U[]>&) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr void operator()(T* const p) const noexcept
|
||||||
|
{
|
||||||
|
delete[] p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_DEFAULT_DELETE_H_
|
|
@ -1,3 +1,5 @@
|
||||||
|
// -*-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_ENABLE_IF_H_
|
#ifndef CTL_ENABLE_IF_H_
|
||||||
#define CTL_ENABLE_IF_H_
|
#define CTL_ENABLE_IF_H_
|
||||||
|
|
||||||
|
|
29
ctl/integral_constant.h
Normal file
29
ctl/integral_constant.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_INTEGRAL_CONSTANT_H_
|
||||||
|
#define CTL_INTEGRAL_CONSTANT_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<class T, T v>
|
||||||
|
struct integral_constant
|
||||||
|
{
|
||||||
|
static constexpr T value = v;
|
||||||
|
typedef T value_type;
|
||||||
|
typedef integral_constant type;
|
||||||
|
constexpr operator value_type() const noexcept
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
constexpr value_type operator()() const noexcept
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef integral_constant<bool, true> true_type;
|
||||||
|
typedef integral_constant<bool, false> false_type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_INTEGRAL_CONSTANT_H_
|
26
ctl/is_array.h
Normal file
26
ctl/is_array.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// -*-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_IS_ARRAY_H_
|
||||||
|
#define CTL_IS_ARRAY_H_
|
||||||
|
#include "integral_constant.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_array : false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T, size_t N>
|
||||||
|
struct is_array<T[N]> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_array<T[]> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_array_v = is_array<T>::value;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_ARRAY_H_
|
54
ctl/is_convertible.h
Normal file
54
ctl/is_convertible.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
// -*-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_IS_CONVERTIBLE_H_
|
||||||
|
#define CTL_IS_CONVERTIBLE_H_
|
||||||
|
|
||||||
|
#include "ctl/integral_constant.h"
|
||||||
|
#include "ctl/void_t.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
// Declaration of declval
|
||||||
|
template<typename T>
|
||||||
|
T&&
|
||||||
|
declval() noexcept;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename From, typename To, typename = void>
|
||||||
|
struct is_convertible_impl : false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename From, typename To>
|
||||||
|
struct is_convertible_impl<From,
|
||||||
|
To,
|
||||||
|
void_t<decltype(static_cast<To>(declval<From>()))>>
|
||||||
|
: true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Handle void types separately
|
||||||
|
template<>
|
||||||
|
struct is_convertible_impl<void, void> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename To>
|
||||||
|
struct is_convertible_impl<void, To> : false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename From>
|
||||||
|
struct is_convertible_impl<From, void> : false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename From, typename To>
|
||||||
|
struct is_convertible : detail::is_convertible_impl<From, To>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Helper variable template (C++17 and later)
|
||||||
|
template<typename From, typename To>
|
||||||
|
inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_CONVERTIBLE_H_
|
120
ctl/is_function.h
Normal file
120
ctl/is_function.h
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
// -*-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_IS_FUNCTION_H_
|
||||||
|
#define CTL_IS_FUNCTION_H_
|
||||||
|
#include "integral_constant.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
// Primary template
|
||||||
|
template<class>
|
||||||
|
struct is_function : false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Specializations for various function types
|
||||||
|
|
||||||
|
// Regular functions
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...)> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Functions with cv-qualifiers
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) const> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) volatile> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) const volatile> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Functions with ref-qualifiers
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...)&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) const&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) volatile&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) const volatile&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) &&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) const&&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) volatile&&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args...) const volatile&&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Variadic functions
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...)> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Variadic functions with cv-qualifiers
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) const> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) volatile> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) const volatile> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Variadic functions with ref-qualifiers
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...)&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) const&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) volatile&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) const volatile&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) &&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) const&&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) volatile&&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class Ret, class... Args>
|
||||||
|
struct is_function<Ret(Args..., ...) const volatile&&> : true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_FUNCTION_H_
|
|
@ -1,29 +1,11 @@
|
||||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
// -*-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
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
#ifndef CTL_TYPE_TRAITS_H_
|
#ifndef CTL_IS_INTEGRAL_H_
|
||||||
#define CTL_TYPE_TRAITS_H_
|
#define CTL_IS_INTEGRAL_H_
|
||||||
|
#include "integral_constant.h"
|
||||||
|
|
||||||
namespace ctl {
|
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>
|
template<typename T>
|
||||||
struct is_integral : false_type
|
struct is_integral : false_type
|
||||||
{};
|
{};
|
||||||
|
@ -91,33 +73,6 @@ struct is_integral<wchar_t> : true_type
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr bool is_integral_v = is_integral<T>::value;
|
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
|
} // namespace ctl
|
||||||
|
|
||||||
#endif // CTL_TYPE_TRAITS_H_
|
#endif // CTL_IS_INTEGRAL_H_
|
35
ctl/is_reference.h
Normal file
35
ctl/is_reference.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// -*-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_IS_REFERENCE_H_
|
||||||
|
#define CTL_IS_REFERENCE_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
// Primary template
|
||||||
|
template<class T>
|
||||||
|
struct is_reference
|
||||||
|
{
|
||||||
|
static constexpr bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for lvalue reference
|
||||||
|
template<class T>
|
||||||
|
struct is_reference<T&>
|
||||||
|
{
|
||||||
|
static constexpr bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for rvalue reference
|
||||||
|
template<class T>
|
||||||
|
struct is_reference<T&&>
|
||||||
|
{
|
||||||
|
static constexpr bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper variable template (C++14 and later)
|
||||||
|
template<class T>
|
||||||
|
inline constexpr bool is_reference_v = is_reference<T>::value;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_REFERENCE_H_
|
25
ctl/is_same.h
Normal file
25
ctl/is_same.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// -*-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_IS_SAME_H_
|
||||||
|
#define CTL_IS_SAME_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
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_IS_SAME_H_
|
16
ctl/is_signed.h
Normal file
16
ctl/is_signed.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// -*-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_IS_SIGNED_H_
|
||||||
|
#define CTL_IS_SIGNED_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_signed
|
||||||
|
{
|
||||||
|
static constexpr bool value = T(0) > T(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_SIGNED_H_
|
25
ctl/is_sorted.h
Normal file
25
ctl/is_sorted.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// -*-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_IS_SORTED_H_
|
||||||
|
#define CTL_IS_SORTED_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename It, typename Compare>
|
||||||
|
bool
|
||||||
|
is_sorted(It first, It last, Compare comp)
|
||||||
|
{
|
||||||
|
if (first == last)
|
||||||
|
return true;
|
||||||
|
It next = first;
|
||||||
|
while (++next != last) {
|
||||||
|
if (comp(*next, *first))
|
||||||
|
return false;
|
||||||
|
first = next;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_SORTED_H_
|
16
ctl/is_unsigned.h
Normal file
16
ctl/is_unsigned.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// -*-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_IS_UNSIGNED_H_
|
||||||
|
#define CTL_IS_UNSIGNED_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_unsigned
|
||||||
|
{
|
||||||
|
static constexpr bool value = T(0) < T(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_IS_UNSIGNED_H_
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef CTL_MOVE_ITERATOR_H_
|
#ifndef CTL_MOVE_ITERATOR_H_
|
||||||
#define CTL_MOVE_ITERATOR_H_
|
#define CTL_MOVE_ITERATOR_H_
|
||||||
#include "iterator_traits.h"
|
#include "iterator_traits.h"
|
||||||
#include "type_traits.h"
|
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
|
|
47
ctl/mutex.h
Normal file
47
ctl/mutex.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// -*-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_MUTEX_H_
|
||||||
|
#define CTL_MUTEX_H_
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
class mutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mutex()
|
||||||
|
{
|
||||||
|
pthread_mutex_init(&m_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
~mutex()
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
return pthread_mutex_trylock(&m_) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&m_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete copy constructor and assignment operator
|
||||||
|
mutex(const mutex&) = delete;
|
||||||
|
mutex& operator=(const mutex&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pthread_mutex_t m_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_MUTEX_H_
|
|
@ -2,7 +2,8 @@
|
||||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
#ifndef CTL_NUMERIC_LIMITS_H_
|
#ifndef CTL_NUMERIC_LIMITS_H_
|
||||||
#define CTL_NUMERIC_LIMITS_H_
|
#define CTL_NUMERIC_LIMITS_H_
|
||||||
#include "type_traits.h"
|
#include "is_integral.h"
|
||||||
|
#include "is_unsigned.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
|
|
29
ctl/partition.h
Normal file
29
ctl/partition.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_PARTITION_H_
|
||||||
|
#define CTL_PARTITION_H_
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename RandomIt, typename Compare>
|
||||||
|
RandomIt
|
||||||
|
partition(RandomIt first, RandomIt last, Compare comp)
|
||||||
|
{
|
||||||
|
auto pivot = *ctl::move(last - 1);
|
||||||
|
auto i = first - 1;
|
||||||
|
|
||||||
|
for (auto j = first; j < last - 1; ++j) {
|
||||||
|
if (comp(*j, pivot)) {
|
||||||
|
++i;
|
||||||
|
ctl::swap(*i, *j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl::swap(*(i + 1), *(last - 1));
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_PARTITION_H_
|
49
ctl/remove_cv.h
Normal file
49
ctl/remove_cv.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// -*-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_REMOVE_CV_H_
|
||||||
|
#define CTL_REMOVE_CV_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_const
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_const<const T>
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_volatile
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_volatile<volatile T>
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_cv
|
||||||
|
{
|
||||||
|
typedef typename remove_volatile<typename remove_const<T>::type>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using remove_const_t = typename remove_const<T>::type;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using remove_volatile_t = typename remove_volatile<T>::type;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using remove_cv_t = typename remove_cv<T>::type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_REMOVE_CV_H_
|
31
ctl/remove_extent.h
Normal file
31
ctl/remove_extent.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_REMOVE_EXTENT_H_
|
||||||
|
#define CTL_REMOVE_EXTENT_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct remove_extent
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, size_t N>
|
||||||
|
struct remove_extent<T[N]>
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct remove_extent<T[]>
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using remove_extent_t = typename remove_extent<T>::type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_REMOVE_EXTENT_H_
|
31
ctl/remove_reference.h
Normal file
31
ctl/remove_reference.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_REMOVE_REFERENCE_H_
|
||||||
|
#define CTL_REMOVE_REFERENCE_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_reference
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_reference<T&>
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct remove_reference<T&&>
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using remove_reference_t = typename remove_reference<T>::type;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_REMOVE_REFERENCE_H_
|
33
ctl/runtime_error.h
Normal file
33
ctl/runtime_error.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// -*-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_RUNTIME_ERROR_H_
|
||||||
|
#define CTL_RUNTIME_ERROR_H_
|
||||||
|
#include "ctl/string.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
class runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit runtime_error(const string& what_arg) : msg_(what_arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit runtime_error(const char* what_arg) : msg_(what_arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~runtime_error() noexcept = default;
|
||||||
|
|
||||||
|
virtual const char* what() const noexcept
|
||||||
|
{
|
||||||
|
return msg_.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_RUNTIME_ERROR_H_
|
44
ctl/sort.h
Normal file
44
ctl/sort.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// -*-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_SORT_H_
|
||||||
|
#define CTL_SORT_H_
|
||||||
|
#include "iterator_traits.h"
|
||||||
|
#include "less.h"
|
||||||
|
#include "partition.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename RandomIt, typename Compare>
|
||||||
|
void
|
||||||
|
quicksort(RandomIt first, RandomIt last, Compare comp)
|
||||||
|
{
|
||||||
|
if (first < last) {
|
||||||
|
auto pivot = ctl::partition(first, last, comp);
|
||||||
|
quicksort(first, pivot, comp);
|
||||||
|
quicksort(pivot + 1, last, comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<typename RandomIt, typename Compare>
|
||||||
|
void
|
||||||
|
sort(RandomIt first, RandomIt last, Compare comp)
|
||||||
|
{
|
||||||
|
detail::quicksort(first, last, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename RandomIt>
|
||||||
|
void
|
||||||
|
sort(RandomIt first, RandomIt last)
|
||||||
|
{
|
||||||
|
sort(first,
|
||||||
|
last,
|
||||||
|
ctl::less<typename ctl::iterator_traits<RandomIt>::value_type>());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_SORT_H_
|
|
@ -38,9 +38,9 @@ strcat(const string_view lhs, const string_view rhs) noexcept
|
||||||
if (rhs.n)
|
if (rhs.n)
|
||||||
memcpy(res.data() + lhs.n, rhs.p, rhs.n);
|
memcpy(res.data() + lhs.n, rhs.p, rhs.n);
|
||||||
if (res.isbig()) {
|
if (res.isbig()) {
|
||||||
res.big()->n = lhs.n + rhs.n;
|
res.__b.n = lhs.n + rhs.n;
|
||||||
} else {
|
} else {
|
||||||
res.small()->rem = __::sso_max - lhs.n - rhs.n;
|
res.__s.rem = __::sso_max - lhs.n - rhs.n;
|
||||||
}
|
}
|
||||||
res.data()[res.size()] = 0;
|
res.data()[res.size()] = 0;
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace ctl {
|
||||||
void
|
void
|
||||||
string::destroy_big() noexcept
|
string::destroy_big() noexcept
|
||||||
{
|
{
|
||||||
auto* b = big();
|
auto* b = &__b;
|
||||||
if (b->n) {
|
if (b->n) {
|
||||||
if (b->n >= b->c)
|
if (b->n >= b->c)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
|
@ -41,7 +41,14 @@ string::destroy_big() noexcept
|
||||||
void
|
void
|
||||||
string::init_big(const string& s) noexcept
|
string::init_big(const string& s) noexcept
|
||||||
{
|
{
|
||||||
init_big(string_view(s));
|
char* p2;
|
||||||
|
size_t size = s.size();
|
||||||
|
size_t need = size + 1;
|
||||||
|
size_t capacity = need;
|
||||||
|
if (!(p2 = (char*)malloc(capacity)))
|
||||||
|
__builtin_trap();
|
||||||
|
memcpy(p2, s.data(), need);
|
||||||
|
set_big_string(p2, size, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -103,7 +110,7 @@ string::reserve(size_t c2) noexcept
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
memcpy(p2, data(), __::string_size);
|
memcpy(p2, data(), __::string_size);
|
||||||
} else {
|
} else {
|
||||||
if (!(p2 = (char*)realloc(big()->p, c2)))
|
if (!(p2 = (char*)realloc(__b.p, c2)))
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
}
|
}
|
||||||
std::atomic_signal_fence(std::memory_order_seq_cst);
|
std::atomic_signal_fence(std::memory_order_seq_cst);
|
||||||
|
@ -120,7 +127,7 @@ string::resize(const size_t n2, const char ch) noexcept
|
||||||
if (n2 > size())
|
if (n2 > size())
|
||||||
memset(data() + size(), ch, n2 - size());
|
memset(data() + size(), ch, n2 - size());
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->p[big()->n = n2] = 0;
|
__b.p[__b.n = n2] = 0;
|
||||||
} else {
|
} else {
|
||||||
set_small_size(n2);
|
set_small_size(n2);
|
||||||
data()[size()] = 0;
|
data()[size()] = 0;
|
||||||
|
@ -141,9 +148,9 @@ string::append(const char ch) noexcept
|
||||||
}
|
}
|
||||||
data()[size()] = ch;
|
data()[size()] = ch;
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
++big()->n;
|
++__b.n;
|
||||||
} else {
|
} else {
|
||||||
--small()->rem;
|
--__s.rem;
|
||||||
}
|
}
|
||||||
data()[size()] = 0;
|
data()[size()] = 0;
|
||||||
}
|
}
|
||||||
|
@ -174,9 +181,9 @@ string::append(const char ch, const size_t size) noexcept
|
||||||
if (size)
|
if (size)
|
||||||
memset(data() + this->size(), ch, size);
|
memset(data() + this->size(), ch, size);
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->n += size;
|
__b.n += size;
|
||||||
} else {
|
} else {
|
||||||
small()->rem -= size;
|
__s.rem -= size;
|
||||||
}
|
}
|
||||||
data()[this->size()] = 0;
|
data()[this->size()] = 0;
|
||||||
}
|
}
|
||||||
|
@ -188,9 +195,9 @@ string::append(const void* data, const size_t size) noexcept
|
||||||
if (size)
|
if (size)
|
||||||
memcpy(this->data() + this->size(), data, size);
|
memcpy(this->data() + this->size(), data, size);
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->n += size;
|
__b.n += size;
|
||||||
} else {
|
} else {
|
||||||
small()->rem -= size;
|
__s.rem -= size;
|
||||||
}
|
}
|
||||||
this->data()[this->size()] = 0;
|
this->data()[this->size()] = 0;
|
||||||
}
|
}
|
||||||
|
@ -201,9 +208,9 @@ string::pop_back() noexcept
|
||||||
if (!size())
|
if (!size())
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
--big()->n;
|
--__b.n;
|
||||||
} else {
|
} else {
|
||||||
++small()->rem;
|
++__s.rem;
|
||||||
}
|
}
|
||||||
data()[size()] = 0;
|
data()[size()] = 0;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +329,7 @@ string::replace(const size_t pos,
|
||||||
memmove(data() + pos + s.n, data() + last, extra);
|
memmove(data() + pos + s.n, data() + last, extra);
|
||||||
memcpy(data() + pos, s.p, s.n);
|
memcpy(data() + pos, s.p, s.n);
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->p[big()->n = need] = 0;
|
__b.p[__b.n = need] = 0;
|
||||||
} else {
|
} else {
|
||||||
set_small_size(need);
|
set_small_size(need);
|
||||||
data()[size()] = 0;
|
data()[size()] = 0;
|
||||||
|
@ -346,9 +353,9 @@ string::insert(const size_t i, const string_view s) noexcept
|
||||||
memmove(data() + i + s.n, data() + i, extra);
|
memmove(data() + i + s.n, data() + i, extra);
|
||||||
memcpy(data() + i, s.p, s.n);
|
memcpy(data() + i, s.p, s.n);
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->n += s.n;
|
__b.n += s.n;
|
||||||
} else {
|
} else {
|
||||||
small()->rem -= s.n;
|
__s.rem -= s.n;
|
||||||
}
|
}
|
||||||
data()[size()] = 0;
|
data()[size()] = 0;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -365,7 +372,7 @@ string::erase(const size_t pos, size_t count) noexcept
|
||||||
if (extra)
|
if (extra)
|
||||||
memmove(data() + pos, data() + pos + count, extra);
|
memmove(data() + pos, data() + pos + count, extra);
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->n = pos + extra;
|
__b.n = pos + extra;
|
||||||
} else {
|
} else {
|
||||||
set_small_size(pos + extra);
|
set_small_size(pos + extra);
|
||||||
}
|
}
|
||||||
|
|
52
ctl/string.h
52
ctl/string.h
|
@ -151,7 +151,7 @@ class string
|
||||||
void clear() noexcept
|
void clear() noexcept
|
||||||
{
|
{
|
||||||
if (isbig()) {
|
if (isbig()) {
|
||||||
big()->n = 0;
|
__b.n = 0;
|
||||||
} else {
|
} else {
|
||||||
set_small_size(0);
|
set_small_size(0);
|
||||||
}
|
}
|
||||||
|
@ -159,26 +159,26 @@ class string
|
||||||
|
|
||||||
bool empty() const noexcept
|
bool empty() const noexcept
|
||||||
{
|
{
|
||||||
return isbig() ? !big()->n : small()->rem >= __::sso_max;
|
return isbig() ? !__b.n : __s.rem >= __::sso_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* data() noexcept
|
__attribute__((__always_inline__)) char* data() noexcept
|
||||||
{
|
{
|
||||||
return isbig() ? big()->p : small()->buf;
|
return isbig() ? __b.p : __s.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* data() const noexcept
|
__attribute__((__always_inline__)) const char* data() const noexcept
|
||||||
{
|
{
|
||||||
return isbig() ? big()->p : small()->buf;
|
return isbig() ? __b.p : __s.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const noexcept
|
__attribute__((__always_inline__)) size_t size() const noexcept
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
if (!isbig() && small()->rem > __::sso_max)
|
if (!isbig() && __s.rem > __::sso_max)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
#endif
|
#endif
|
||||||
return isbig() ? big()->n : __::sso_max - small()->rem;
|
return isbig() ? __b.n : __::sso_max - __s.rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t length() const noexcept
|
size_t length() const noexcept
|
||||||
|
@ -189,10 +189,10 @@ class string
|
||||||
size_t capacity() const noexcept
|
size_t capacity() const noexcept
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
if (isbig() && big()->c <= __::sso_max)
|
if (isbig() && __b.c <= __::sso_max)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
#endif
|
#endif
|
||||||
return isbig() ? __::big_mask & big()->c : __::string_size;
|
return isbig() ? __::big_mask & __b.c : __::string_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin() noexcept
|
iterator begin() noexcept
|
||||||
|
@ -374,7 +374,7 @@ class string
|
||||||
void init_big(string_view) noexcept;
|
void init_big(string_view) noexcept;
|
||||||
void init_big(size_t, char) noexcept;
|
void init_big(size_t, char) noexcept;
|
||||||
|
|
||||||
bool isbig() const noexcept
|
__attribute__((__always_inline__)) bool isbig() const noexcept
|
||||||
{
|
{
|
||||||
return *(blob + __::sso_max) & 0x80;
|
return *(blob + __::sso_max) & 0x80;
|
||||||
}
|
}
|
||||||
|
@ -395,34 +395,6 @@ class string
|
||||||
__b.c = c2 | ~__::big_mask;
|
__b.c = c2 | ~__::big_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
__::small_string* small() noexcept
|
|
||||||
{
|
|
||||||
if (isbig())
|
|
||||||
__builtin_trap();
|
|
||||||
return &__s;
|
|
||||||
}
|
|
||||||
|
|
||||||
const __::small_string* small() const noexcept
|
|
||||||
{
|
|
||||||
if (isbig())
|
|
||||||
__builtin_trap();
|
|
||||||
return &__s;
|
|
||||||
}
|
|
||||||
|
|
||||||
__::big_string* big() noexcept
|
|
||||||
{
|
|
||||||
if (!isbig())
|
|
||||||
__builtin_trap();
|
|
||||||
return &__b;
|
|
||||||
}
|
|
||||||
|
|
||||||
const __::big_string* big() const noexcept
|
|
||||||
{
|
|
||||||
if (!isbig())
|
|
||||||
__builtin_trap();
|
|
||||||
return &__b;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend string strcat(string_view, string_view) noexcept;
|
friend string strcat(string_view, string_view) noexcept;
|
||||||
|
|
||||||
union
|
union
|
||||||
|
|
138
ctl/tuple.h
Normal file
138
ctl/tuple.h
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// -*-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_TUPLE_H_
|
||||||
|
#define CTL_TUPLE_H_
|
||||||
|
#include "decay.h"
|
||||||
|
#include "enable_if.h"
|
||||||
|
#include "is_same.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
template<typename... Types>
|
||||||
|
class tuple;
|
||||||
|
|
||||||
|
// Base case for tuple
|
||||||
|
template<>
|
||||||
|
class tuple<>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// Recursive case for tuple
|
||||||
|
template<typename Head, typename... Tail>
|
||||||
|
class tuple<Head, Tail...> : public tuple<Tail...>
|
||||||
|
{
|
||||||
|
using Base = tuple<Tail...>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Head head;
|
||||||
|
|
||||||
|
constexpr tuple() : Base(), head()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename H,
|
||||||
|
typename... T,
|
||||||
|
typename = typename ctl::enable_if<
|
||||||
|
!ctl::is_same<typename ctl::decay<H>::type, tuple>::value>::type>
|
||||||
|
constexpr tuple(H&& h, T&&... t)
|
||||||
|
: Base(ctl::forward<T>(t)...), head(ctl::forward<H>(h))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... UTypes>
|
||||||
|
constexpr tuple(const tuple<UTypes...>& other)
|
||||||
|
: Base(static_cast<const tuple<UTypes...>&>(other)), head(other.head)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... UTypes>
|
||||||
|
constexpr tuple(tuple<UTypes...>&& other)
|
||||||
|
: Base(static_cast<tuple<UTypes...>&&>(other))
|
||||||
|
, head(ctl::forward<Head>(other.head))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple(const tuple&) = default;
|
||||||
|
tuple(tuple&&) = default;
|
||||||
|
tuple& operator=(const tuple&) = default;
|
||||||
|
tuple& operator=(tuple&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper struct for getting element type
|
||||||
|
template<size_t I, typename T>
|
||||||
|
struct tuple_element;
|
||||||
|
|
||||||
|
template<size_t I, typename Head, typename... Tail>
|
||||||
|
struct tuple_element<I, tuple<Head, Tail...>>
|
||||||
|
: tuple_element<I - 1, tuple<Tail...>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<typename Head, typename... Tail>
|
||||||
|
struct tuple_element<0, tuple<Head, Tail...>>
|
||||||
|
{
|
||||||
|
using type = Head;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to get element
|
||||||
|
template<size_t I, typename Head, typename... Tail>
|
||||||
|
constexpr typename tuple_element<I, tuple<Head, Tail...>>::type&
|
||||||
|
get(tuple<Head, Tail...>& t)
|
||||||
|
{
|
||||||
|
if constexpr (I == 0) {
|
||||||
|
return t.head;
|
||||||
|
} else {
|
||||||
|
return get<I - 1>(static_cast<tuple<Tail...>&>(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t I, typename Head, typename... Tail>
|
||||||
|
constexpr const typename tuple_element<I, tuple<Head, Tail...>>::type&
|
||||||
|
get(const tuple<Head, Tail...>& t)
|
||||||
|
{
|
||||||
|
if constexpr (I == 0) {
|
||||||
|
return t.head;
|
||||||
|
} else {
|
||||||
|
return get<I - 1>(static_cast<const tuple<Tail...>&>(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to create a tuple
|
||||||
|
template<typename... Types>
|
||||||
|
constexpr tuple<typename ctl::decay<Types>::type...>
|
||||||
|
make_tuple(Types&&... args)
|
||||||
|
{
|
||||||
|
return tuple<typename ctl::decay<Types>::type...>(
|
||||||
|
ctl::forward<Types>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for tuple comparison
|
||||||
|
template<size_t I = 0, typename... TTypes, typename... UTypes>
|
||||||
|
constexpr bool
|
||||||
|
tuple_equals(const tuple<TTypes...>& t, const tuple<UTypes...>& u)
|
||||||
|
{
|
||||||
|
if constexpr (I == sizeof...(TTypes)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return get<I>(t) == get<I>(u) && tuple_equals<I + 1>(t, u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equality comparison
|
||||||
|
template<typename... TTypes, typename... UTypes>
|
||||||
|
constexpr bool
|
||||||
|
operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u)
|
||||||
|
{
|
||||||
|
return tuple_equals(t, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... TTypes, typename... UTypes>
|
||||||
|
constexpr bool
|
||||||
|
operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u)
|
||||||
|
{
|
||||||
|
return !(t == u);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_TUPLE_H_
|
147
ctl/unique_lock.h
Normal file
147
ctl/unique_lock.h
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
// -*-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_UNIQUE_LOCK_H_
|
||||||
|
#define CTL_UNIQUE_LOCK_H_
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
struct defer_lock_t
|
||||||
|
{
|
||||||
|
explicit defer_lock_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct try_to_lock_t
|
||||||
|
{
|
||||||
|
explicit try_to_lock_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct adopt_lock_t
|
||||||
|
{
|
||||||
|
explicit adopt_lock_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr defer_lock_t defer_lock{};
|
||||||
|
inline constexpr try_to_lock_t try_to_lock{};
|
||||||
|
inline constexpr adopt_lock_t adopt_lock{};
|
||||||
|
|
||||||
|
class unique_lock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unique_lock() noexcept : mutex_(nullptr), owns_lock_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit unique_lock(ctl::mutex& m) : mutex_(&m), owns_lock_(false)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_lock(ctl::mutex& m, defer_lock_t) noexcept
|
||||||
|
: mutex_(&m), owns_lock_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_lock(ctl::mutex& m, try_to_lock_t)
|
||||||
|
: mutex_(&m), owns_lock_(mutex_->try_lock())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_lock(ctl::mutex& m, adopt_lock_t) : mutex_(&m), owns_lock_(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~unique_lock()
|
||||||
|
{
|
||||||
|
if (owns_lock_)
|
||||||
|
mutex_->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_lock(const unique_lock&) = delete;
|
||||||
|
unique_lock& operator=(const unique_lock&) = delete;
|
||||||
|
|
||||||
|
unique_lock(unique_lock&& other) noexcept
|
||||||
|
: mutex_(other.mutex_), owns_lock_(other.owns_lock_)
|
||||||
|
{
|
||||||
|
other.mutex_ = nullptr;
|
||||||
|
other.owns_lock_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_lock& operator=(unique_lock&& other) noexcept
|
||||||
|
{
|
||||||
|
if (owns_lock_)
|
||||||
|
mutex_->unlock();
|
||||||
|
mutex_ = other.mutex_;
|
||||||
|
owns_lock_ = other.owns_lock_;
|
||||||
|
other.mutex_ = nullptr;
|
||||||
|
other.owns_lock_ = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock()
|
||||||
|
{
|
||||||
|
if (!mutex_)
|
||||||
|
__builtin_trap();
|
||||||
|
if (owns_lock_)
|
||||||
|
__builtin_trap();
|
||||||
|
mutex_->lock();
|
||||||
|
owns_lock_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_lock()
|
||||||
|
{
|
||||||
|
if (!mutex_)
|
||||||
|
__builtin_trap();
|
||||||
|
if (owns_lock_)
|
||||||
|
__builtin_trap();
|
||||||
|
owns_lock_ = mutex_->try_lock();
|
||||||
|
return owns_lock_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock()
|
||||||
|
{
|
||||||
|
if (!owns_lock_)
|
||||||
|
__builtin_trap();
|
||||||
|
mutex_->unlock();
|
||||||
|
owns_lock_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(unique_lock& other) noexcept
|
||||||
|
{
|
||||||
|
using ctl::swap;
|
||||||
|
swap(mutex_, other.mutex_);
|
||||||
|
swap(owns_lock_, other.owns_lock_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl::mutex* release() noexcept
|
||||||
|
{
|
||||||
|
ctl::mutex* result = mutex_;
|
||||||
|
mutex_ = nullptr;
|
||||||
|
owns_lock_ = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool owns_lock() const noexcept
|
||||||
|
{
|
||||||
|
return owns_lock_;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const noexcept
|
||||||
|
{
|
||||||
|
return owns_lock_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl::mutex* mutex() const noexcept
|
||||||
|
{
|
||||||
|
return mutex_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ctl::mutex* mutex_;
|
||||||
|
bool owns_lock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_UNIQUE_LOCK_H_
|
|
@ -1,19 +0,0 @@
|
||||||
// -*- 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 "unique_ptr.h"
|
|
105
ctl/unique_ptr.h
105
ctl/unique_ptr.h
|
@ -1,41 +1,17 @@
|
||||||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
// -*-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
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
#ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
#ifndef CTL_UNIQUE_PTR_H_
|
||||||
#define COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
#define CTL_UNIQUE_PTR_H_
|
||||||
|
#include "add_lvalue_reference.h"
|
||||||
|
#include "default_delete.h"
|
||||||
|
#include "is_convertible.h"
|
||||||
|
#include "is_reference.h"
|
||||||
|
#include "is_same.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include <__type_traits/is_convertible.h>
|
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T, typename D = ctl::default_delete<T>>
|
||||||
struct default_delete
|
|
||||||
{
|
|
||||||
constexpr default_delete() noexcept = default;
|
|
||||||
template<typename U>
|
|
||||||
constexpr default_delete(default_delete<U>&&) noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
constexpr void operator()(T* const p) const noexcept
|
|
||||||
{
|
|
||||||
delete p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct default_delete<T[]>
|
|
||||||
{
|
|
||||||
constexpr default_delete() noexcept = default;
|
|
||||||
template<typename U>
|
|
||||||
constexpr default_delete(default_delete<U>&&) noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
constexpr void operator()(T* const p) const noexcept
|
|
||||||
{
|
|
||||||
delete[] p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename D = default_delete<T>>
|
|
||||||
struct unique_ptr
|
struct unique_ptr
|
||||||
{
|
{
|
||||||
using pointer = T*;
|
using pointer = T*;
|
||||||
|
@ -49,26 +25,34 @@ struct unique_ptr
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr unique_ptr(const pointer p) noexcept : p(p), d()
|
constexpr explicit unique_ptr(pointer p) noexcept : p(p), d()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr unique_ptr(const pointer p, auto&& d) noexcept
|
constexpr unique_ptr(pointer p, const D& d) noexcept : p(p), d(d)
|
||||||
: p(p), d(ctl::forward<decltype(d)>(d))
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr unique_ptr(pointer p, D&& d) noexcept : p(p), d(ctl::move(d))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U, typename E>
|
template<typename U, typename E>
|
||||||
requires std::is_convertible_v<U, T> && std::is_convertible_v<E, D>
|
|
||||||
constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept
|
constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept
|
||||||
: p(u.p), d(ctl::move(u.d))
|
: p(u.release()), d(ctl::forward<E>(u.get_deleter()))
|
||||||
{
|
{
|
||||||
u.p = nullptr;
|
static_assert(ctl::is_convertible<typename unique_ptr<U, E>::pointer,
|
||||||
|
pointer>::value,
|
||||||
|
"U* must be implicitly convertible to T*");
|
||||||
|
static_assert(
|
||||||
|
(ctl::is_reference<D>::value && ctl::is_same<D, E>::value) ||
|
||||||
|
(!ctl::is_reference<D>::value && ctl::is_convertible<E, D>::value),
|
||||||
|
"The deleter must be convertible to the target deleter type");
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr(const unique_ptr&) = delete;
|
unique_ptr(const unique_ptr&) = delete;
|
||||||
|
|
||||||
constexpr ~unique_ptr() /* noexcept */
|
constexpr ~unique_ptr() noexcept
|
||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
d(p);
|
d(p);
|
||||||
|
@ -80,6 +64,20 @@ struct unique_ptr
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename U, typename E>
|
||||||
|
constexpr unique_ptr& operator=(unique_ptr<U, E>&& r) noexcept
|
||||||
|
{
|
||||||
|
reset(r.release());
|
||||||
|
d = ctl::forward<E>(r.get_deleter());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr unique_ptr& operator=(nullptr_t) noexcept
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr pointer release() noexcept
|
constexpr pointer release() noexcept
|
||||||
{
|
{
|
||||||
pointer r = p;
|
pointer r = p;
|
||||||
|
@ -87,12 +85,12 @@ struct unique_ptr
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void reset(const pointer p2 = pointer()) noexcept
|
constexpr void reset(pointer p2 = pointer()) noexcept
|
||||||
{
|
{
|
||||||
const pointer r = p;
|
pointer old = p;
|
||||||
p = p2;
|
p = p2;
|
||||||
if (r)
|
if (old)
|
||||||
d(r);
|
d(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void swap(unique_ptr& r) noexcept
|
constexpr void swap(unique_ptr& r) noexcept
|
||||||
|
@ -119,20 +117,16 @@ struct unique_ptr
|
||||||
|
|
||||||
constexpr explicit operator bool() const noexcept
|
constexpr explicit operator bool() const noexcept
|
||||||
{
|
{
|
||||||
return p;
|
return p != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
element_type& operator*() const noexcept(noexcept(*ctl::declval<pointer>()))
|
constexpr typename ctl::add_lvalue_reference<T>::type operator*() const
|
||||||
{
|
{
|
||||||
if (!p)
|
|
||||||
__builtin_trap();
|
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer operator->() const noexcept
|
constexpr pointer operator->() const noexcept
|
||||||
{
|
{
|
||||||
if (!p)
|
|
||||||
__builtin_trap();
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -148,16 +142,9 @@ template<typename T>
|
||||||
constexpr unique_ptr<T>
|
constexpr unique_ptr<T>
|
||||||
make_unique_for_overwrite()
|
make_unique_for_overwrite()
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
// You'd think that it'd work like this, but std::unique_ptr does not.
|
|
||||||
return unique_ptr<T>(
|
|
||||||
static_cast<T*>(::operator new(sizeof(T), align_val_t(alignof(T)))));
|
|
||||||
#else
|
|
||||||
return unique_ptr<T>(new T);
|
return unique_ptr<T>(new T);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mrdomino): specializations for T[]
|
|
||||||
|
|
||||||
} // namespace ctl
|
} // namespace ctl
|
||||||
#endif // COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
|
||||||
|
#endif // CTL_UNIQUE_PTR_H_
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
// -*- 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 "utility.h"
|
|
|
@ -2,6 +2,7 @@
|
||||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
#ifndef COSMOPOLITAN_CTL_UTILITY_H_
|
#ifndef COSMOPOLITAN_CTL_UTILITY_H_
|
||||||
#define COSMOPOLITAN_CTL_UTILITY_H_
|
#define COSMOPOLITAN_CTL_UTILITY_H_
|
||||||
|
#include "remove_reference.h"
|
||||||
|
|
||||||
namespace ctl {
|
namespace ctl {
|
||||||
|
|
||||||
|
@ -18,6 +19,14 @@ using no_infer = typename no_infer_<T>::type;
|
||||||
|
|
||||||
} // namespace __
|
} // namespace __
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T&&
|
||||||
|
move(T&& t) noexcept
|
||||||
|
{
|
||||||
|
typedef remove_reference_t<T> U;
|
||||||
|
return static_cast<U&&>(t);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T&&
|
constexpr T&&
|
||||||
move(T& t) noexcept
|
move(T& t) noexcept
|
||||||
|
@ -47,9 +56,8 @@ template<typename T, size_t N>
|
||||||
constexpr void
|
constexpr void
|
||||||
swap(T (&a)[N], T (&b)[N]) noexcept
|
swap(T (&a)[N], T (&b)[N]) noexcept
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i)
|
||||||
swap(a[i], b[i]);
|
swap(a[i], b[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
13
ctl/void_t.h
Normal file
13
ctl/void_t.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// -*-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_VOID_T_H_
|
||||||
|
#define CTL_VOID_T_H_
|
||||||
|
|
||||||
|
namespace ctl {
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
using void_t = void;
|
||||||
|
|
||||||
|
} // namespace ctl
|
||||||
|
|
||||||
|
#endif // CTL_VOID_T_H_
|
|
@ -18,6 +18,7 @@ TEST_CTL_DIRECTDEPS = \
|
||||||
LIBC_INTRIN \
|
LIBC_INTRIN \
|
||||||
LIBC_MEM \
|
LIBC_MEM \
|
||||||
LIBC_STDIO \
|
LIBC_STDIO \
|
||||||
|
LIBC_THREAD \
|
||||||
THIRD_PARTY_LIBCXX \
|
THIRD_PARTY_LIBCXX \
|
||||||
THIRD_PARTY_LIBCXXABI \
|
THIRD_PARTY_LIBCXXABI \
|
||||||
THIRD_PARTY_LIBUNWIND \
|
THIRD_PARTY_LIBUNWIND \
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "ctl/accumulate.h"
|
#include "ctl/accumulate.h"
|
||||||
#include "ctl/array.h"
|
#include "ctl/array.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
// #include <array>
|
// #include <array>
|
||||||
// #include <numeric>
|
// #include <numeric>
|
||||||
|
@ -48,4 +49,6 @@ main()
|
||||||
// Test accumulation with single element
|
// Test accumulation with single element
|
||||||
if (ctl::accumulate(arr.begin(), arr.begin() + 1, 0) != 1)
|
if (ctl::accumulate(arr.begin(), arr.begin() + 1, 0) != 1)
|
||||||
return 5;
|
return 5;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "ctl/advance.h"
|
#include "ctl/advance.h"
|
||||||
#include "ctl/array.h"
|
#include "ctl/array.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
// #include <array>
|
// #include <array>
|
||||||
// #include <iterator>
|
// #include <iterator>
|
||||||
|
@ -53,4 +54,6 @@ main()
|
||||||
ctl::advance(it, -2);
|
ctl::advance(it, -2);
|
||||||
if (it != arr.begin())
|
if (it != arr.begin())
|
||||||
return 5;
|
return 5;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "ctl/all_of.h"
|
#include "ctl/all_of.h"
|
||||||
#include "ctl/array.h"
|
#include "ctl/array.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -49,4 +50,6 @@ main()
|
||||||
// Test with no elements satisfying the condition
|
// Test with no elements satisfying the condition
|
||||||
if (ctl::all_of(arr1.begin(), arr1.end(), [](int n) { return n > 10; }))
|
if (ctl::all_of(arr1.begin(), arr1.end(), [](int n) { return n > 10; }))
|
||||||
return 5;
|
return 5;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "ctl/any_of.h"
|
#include "ctl/any_of.h"
|
||||||
#include "ctl/array.h"
|
#include "ctl/array.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
// #include <algorithm>
|
// #include <algorithm>
|
||||||
// #include <array>
|
// #include <array>
|
||||||
|
@ -48,4 +49,6 @@ main()
|
||||||
// Test with a different condition
|
// Test with a different condition
|
||||||
if (!ctl::any_of(arr1.begin(), arr1.end(), [](int n) { return n > 5; }))
|
if (!ctl::any_of(arr1.begin(), arr1.end(), [](int n) { return n > 5; }))
|
||||||
return 5;
|
return 5;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,11 @@
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "ctl/array.h"
|
#include "ctl/array.h"
|
||||||
|
#include "ctl/string.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
// #include <array>
|
// #include <array>
|
||||||
|
// #include <string>
|
||||||
// #define ctl std
|
// #define ctl std
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -264,4 +267,21 @@ main()
|
||||||
if (rit != arr.rend())
|
if (rit != arr.rend())
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ctl::array<ctl::string, 2> 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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "ctl/back_inserter.h"
|
#include "ctl/back_inserter.h"
|
||||||
#include "ctl/copy.h"
|
#include "ctl/copy.h"
|
||||||
#include "ctl/vector.h"
|
#include "ctl/vector.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
// #include <array>
|
// #include <array>
|
||||||
// #include <iterator>
|
// #include <iterator>
|
||||||
|
@ -29,33 +30,38 @@
|
||||||
int
|
int
|
||||||
main()
|
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));
|
ctl::vector<int> vec = { 1, 2, 3 };
|
||||||
|
ctl::array<int, 3> arr = { 4, 5, 6 };
|
||||||
|
|
||||||
// Check if vec now contains all elements
|
// Use back_inserter to append elements from arr to vec
|
||||||
if (vec.size() != 6)
|
ctl::copy(arr.begin(), arr.end(), ctl::back_inserter(vec));
|
||||||
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
|
// Check if vec now contains all elements
|
||||||
ctl::back_inserter(vec) = 7;
|
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;
|
||||||
|
|
||||||
// Check if the new element was added
|
// Use back_inserter with a single element
|
||||||
if (vec.size() != 7)
|
ctl::back_inserter(vec) = 7;
|
||||||
return 3;
|
|
||||||
if (vec[6] != 7)
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
// Test with an empty source range
|
// Check if the new element was added
|
||||||
ctl::array<int, 0> empty_arr;
|
if (vec.size() != 7)
|
||||||
ctl::copy(empty_arr.begin(), empty_arr.end(), ctl::back_inserter(vec));
|
return 3;
|
||||||
|
if (vec[6] != 7)
|
||||||
|
return 4;
|
||||||
|
|
||||||
// Check that no elements were added
|
// Test with an empty source range
|
||||||
if (vec.size() != 7)
|
ctl::array<int, 0> empty_arr;
|
||||||
return 5;
|
ctl::copy(empty_arr.begin(), empty_arr.end(), ctl::back_inserter(vec));
|
||||||
|
|
||||||
|
// Check that no elements were added
|
||||||
|
if (vec.size() != 7)
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,49 +18,56 @@
|
||||||
|
|
||||||
#include "ctl/array.h"
|
#include "ctl/array.h"
|
||||||
#include "ctl/copy.h"
|
#include "ctl/copy.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
// #include <iterator>
|
// #include <algorithm>
|
||||||
// #include <array>
|
// #include <array>
|
||||||
|
// #include <iterator>
|
||||||
// #define ctl std
|
// #define ctl std
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
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());
|
ctl::array<int, 5> src = { 1, 2, 3, 4, 5 };
|
||||||
for (size_t i = 0; i < 5; ++i) {
|
ctl::array<int, 5> dest = { 0, 0, 0, 0, 0 };
|
||||||
if (dest[i] != src[i])
|
|
||||||
return 1;
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test partial copy
|
CheckForMemoryLeaks();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
114
test/ctl/mutex_test.cc
Normal file
114
test/ctl/mutex_test.cc
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// -*- 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/mutex.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
|
// #include <mutex>
|
||||||
|
// #define ctl std
|
||||||
|
|
||||||
|
ctl::mutex mtx;
|
||||||
|
int shared_resource = 0;
|
||||||
|
const int NUM_THREADS = 5;
|
||||||
|
const int ITERATIONS = 100000;
|
||||||
|
|
||||||
|
void*
|
||||||
|
increment_resource(void* arg)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ITERATIONS; ++i) {
|
||||||
|
mtx.lock();
|
||||||
|
++shared_resource;
|
||||||
|
mtx.unlock();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
decrement_resource(void* arg)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ITERATIONS; ++i) {
|
||||||
|
mtx.lock();
|
||||||
|
--shared_resource;
|
||||||
|
mtx.unlock();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_basic_locking()
|
||||||
|
{
|
||||||
|
shared_resource = 0;
|
||||||
|
pthread_t threads[NUM_THREADS];
|
||||||
|
for (int i = 0; i < NUM_THREADS; ++i)
|
||||||
|
if (pthread_create(&threads[i], 0, increment_resource, 0) != 0)
|
||||||
|
return 1;
|
||||||
|
for (int i = 0; i < NUM_THREADS; ++i)
|
||||||
|
if (pthread_join(threads[i], 0) != 0)
|
||||||
|
return 2;
|
||||||
|
return (shared_resource == NUM_THREADS * ITERATIONS) ? 0 : 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_lock_contention()
|
||||||
|
{
|
||||||
|
shared_resource = 0;
|
||||||
|
pthread_t threads[NUM_THREADS * 2];
|
||||||
|
for (int i = 0; i < NUM_THREADS; ++i)
|
||||||
|
if (pthread_create(&threads[i], 0, increment_resource, 0) != 0 ||
|
||||||
|
pthread_create(&threads[i + NUM_THREADS],
|
||||||
|
nullptr,
|
||||||
|
decrement_resource,
|
||||||
|
nullptr) != 0)
|
||||||
|
return 4;
|
||||||
|
for (int i = 0; i < NUM_THREADS * 2; ++i)
|
||||||
|
if (pthread_join(threads[i], 0) != 0)
|
||||||
|
return 5;
|
||||||
|
return (shared_resource == 0) ? 0 : 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_try_lock()
|
||||||
|
{
|
||||||
|
ctl::mutex try_mtx;
|
||||||
|
if (!try_mtx.try_lock())
|
||||||
|
return 7;
|
||||||
|
if (try_mtx.try_lock())
|
||||||
|
return 8;
|
||||||
|
try_mtx.unlock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = test_basic_locking();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_lock_contention();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_try_lock();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
|
}
|
130
test/ctl/sort_test.cc
Normal file
130
test/ctl/sort_test.cc
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// -*- 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/is_sorted.h"
|
||||||
|
#include "ctl/sort.h"
|
||||||
|
#include "ctl/string.h"
|
||||||
|
#include "ctl/vector.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
#include "libc/stdio/rand.h"
|
||||||
|
|
||||||
|
// #include <algorithm>
|
||||||
|
// #include <string>
|
||||||
|
// #include <vector>
|
||||||
|
// #define ctl std
|
||||||
|
|
||||||
|
// Test sorting integers
|
||||||
|
int
|
||||||
|
test_sort_integers()
|
||||||
|
{
|
||||||
|
ctl::vector<int> v = { 5, 2, 8, 1, 9, 3, 7, 6, 4 };
|
||||||
|
ctl::sort(v.begin(), v.end());
|
||||||
|
if (!ctl::is_sorted(v.begin(), v.end(), ctl::less<int>()))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sorting with custom comparator
|
||||||
|
int
|
||||||
|
test_sort_custom_compare()
|
||||||
|
{
|
||||||
|
ctl::vector<int> v = { 5, 2, 8, 1, 9, 3, 7, 6, 4 };
|
||||||
|
ctl::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
|
||||||
|
if (!ctl::is_sorted(v.begin(), v.end(), [](int a, int b) { return a > b; }))
|
||||||
|
return 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sorting strings
|
||||||
|
int
|
||||||
|
test_sort_strings()
|
||||||
|
{
|
||||||
|
ctl::vector<ctl::string> v = { "banana", "apple", "cherry", "date" };
|
||||||
|
ctl::sort(v.begin(), v.end());
|
||||||
|
if (!ctl::is_sorted(v.begin(), v.end(), ctl::less<ctl::string>()))
|
||||||
|
return 3;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sorting with large number of elements
|
||||||
|
int
|
||||||
|
test_sort_large()
|
||||||
|
{
|
||||||
|
const int SIZE = 10000;
|
||||||
|
ctl::vector<int> v(SIZE);
|
||||||
|
for (int i = 0; i < SIZE; ++i)
|
||||||
|
v[i] = rand() % SIZE;
|
||||||
|
ctl::sort(v.begin(), v.end());
|
||||||
|
if (!is_sorted(v.begin(), v.end(), ctl::less<int>()))
|
||||||
|
return 4;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sorting already sorted vector
|
||||||
|
int
|
||||||
|
test_sort_sorted()
|
||||||
|
{
|
||||||
|
ctl::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||||
|
ctl::sort(v.begin(), v.end());
|
||||||
|
if (!is_sorted(v.begin(), v.end(), ctl::less<int>()))
|
||||||
|
return 5;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sorting reverse sorted vector
|
||||||
|
int
|
||||||
|
test_sort_reverse()
|
||||||
|
{
|
||||||
|
ctl::vector<int> v = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
|
ctl::sort(v.begin(), v.end());
|
||||||
|
if (!is_sorted(v.begin(), v.end(), ctl::less<int>()))
|
||||||
|
return 6;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = test_sort_integers();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_sort_custom_compare();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_sort_strings();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_sort_large();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_sort_sorted();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_sort_reverse();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
|
}
|
|
@ -17,8 +17,8 @@
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "ctl/string.h"
|
#include "ctl/string.h"
|
||||||
|
#include "ctl/utility.h"
|
||||||
#include <__utility/move.h>
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -100,7 +100,7 @@ main()
|
||||||
|
|
||||||
BENCH(1000000, 1, {
|
BENCH(1000000, 1, {
|
||||||
ctl::string s(small);
|
ctl::string s(small);
|
||||||
ctl::string s2(std::move(s));
|
ctl::string s2(ctl::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
BENCH(1000000, 1, {
|
BENCH(1000000, 1, {
|
||||||
|
@ -119,7 +119,7 @@ main()
|
||||||
|
|
||||||
BENCH(1000000, 1, {
|
BENCH(1000000, 1, {
|
||||||
ctl::string s(big);
|
ctl::string s(big);
|
||||||
ctl::string s2(std::move(s));
|
ctl::string s2(ctl::move(s));
|
||||||
});
|
});
|
||||||
|
|
||||||
BENCH(1000000, 1, {
|
BENCH(1000000, 1, {
|
||||||
|
@ -142,5 +142,5 @@ main()
|
||||||
BENCH(1000000, 1, { ctl::string s(big_trunc); });
|
BENCH(1000000, 1, { ctl::string s(big_trunc); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
CheckForMemoryLeaks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,14 @@
|
||||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
#include "ctl/is_same.h"
|
||||||
#include "ctl/string.h"
|
#include "ctl/string.h"
|
||||||
#include "ctl/type_traits.h"
|
|
||||||
#include "libc/mem/leaks.h"
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
// #include <string>
|
// #include <string>
|
||||||
|
// #include <utility>
|
||||||
// #define ctl std
|
// #define ctl std
|
||||||
|
|
||||||
using String = ctl::string;
|
using String = ctl::string;
|
||||||
|
|
|
@ -173,5 +173,4 @@ main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckForMemoryLeaks();
|
CheckForMemoryLeaks();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
161
test/ctl/tuple_test.cc
Normal file
161
test/ctl/tuple_test.cc
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
// -*- 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/string.h"
|
||||||
|
#include "ctl/tuple.h"
|
||||||
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
|
// #include <string>
|
||||||
|
// #include <tuple>
|
||||||
|
// #define ctl std
|
||||||
|
|
||||||
|
int
|
||||||
|
test_tuple_creation()
|
||||||
|
{
|
||||||
|
ctl::tuple<int, double, ctl::string> t(1, 2.5, "hello");
|
||||||
|
if (ctl::get<0>(t) != 1 || ctl::get<1>(t) != 2.5 ||
|
||||||
|
ctl::get<2>(t) != "hello") {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_make_tuple()
|
||||||
|
{
|
||||||
|
auto t = ctl::make_tuple(1, 2.5, ctl::string("hello"));
|
||||||
|
if (ctl::get<0>(t) != 1 || ctl::get<1>(t) != 2.5 ||
|
||||||
|
ctl::get<2>(t) != "hello") {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_tuple_get()
|
||||||
|
{
|
||||||
|
ctl::tuple<int, double, ctl::string> t(1, 2.5, "hello");
|
||||||
|
if (ctl::get<0>(t) != 1)
|
||||||
|
return 3;
|
||||||
|
if (ctl::get<1>(t) != 2.5)
|
||||||
|
return 4;
|
||||||
|
if (ctl::get<2>(t) != "hello")
|
||||||
|
return 5;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_tuple_comparison()
|
||||||
|
{
|
||||||
|
auto t1 = ctl::make_tuple(1, 2.5, "hello");
|
||||||
|
auto t2 = ctl::make_tuple(1, 2.5, "hello");
|
||||||
|
auto t3 = ctl::make_tuple(2, 3.5, "world");
|
||||||
|
|
||||||
|
if (!(t1 == t2))
|
||||||
|
return 6;
|
||||||
|
if (t1 != t2)
|
||||||
|
return 7;
|
||||||
|
if (t1 == t3)
|
||||||
|
return 8;
|
||||||
|
if (!(t1 != t3))
|
||||||
|
return 9;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_tuple_assignment()
|
||||||
|
{
|
||||||
|
ctl::tuple<int, double, ctl::string> t1(1, 2.5, "hello");
|
||||||
|
ctl::tuple<int, double, ctl::string> t2;
|
||||||
|
t2 = t1;
|
||||||
|
if (!(t1 == t2))
|
||||||
|
return 10;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_tuple_move()
|
||||||
|
{
|
||||||
|
ctl::tuple<int, double, ctl::string> t1(1, 2.5, "hello");
|
||||||
|
ctl::tuple<int, double, ctl::string> t2(ctl::move(t1));
|
||||||
|
if (ctl::get<0>(t2) != 1 || ctl::get<1>(t2) != 2.5 ||
|
||||||
|
ctl::get<2>(t2) != "hello") {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_empty_tuple()
|
||||||
|
{
|
||||||
|
ctl::tuple<> t;
|
||||||
|
ctl::tuple<> t2;
|
||||||
|
if (!(t == t2))
|
||||||
|
return 12;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test_single_element_tuple()
|
||||||
|
{
|
||||||
|
ctl::tuple<int> t(42);
|
||||||
|
if (ctl::get<0>(t) != 42)
|
||||||
|
return 13;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = test_tuple_creation();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_make_tuple();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_tuple_get();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_tuple_comparison();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_tuple_assignment();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_tuple_move();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_empty_tuple();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = test_single_element_tuple();
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "ctl/type_traits.h"
|
#include "ctl/is_same.h"
|
||||||
#include "ctl/unique_ptr.h"
|
#include "ctl/unique_ptr.h"
|
||||||
#include "libc/mem/leaks.h"
|
#include "libc/mem/leaks.h"
|
||||||
|
|
||||||
|
@ -41,29 +41,30 @@ MkRaw()
|
||||||
return ctl::make_unique_for_overwrite<T>();
|
return ctl::make_unique_for_overwrite<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ctl
|
// #undef ctl
|
||||||
|
|
||||||
static int g = 0;
|
static int g = 0;
|
||||||
|
|
||||||
struct SetsGDeleter
|
struct SetsGDeleter
|
||||||
{
|
{
|
||||||
void operator()(auto*) const noexcept
|
void operator()(auto* x) const noexcept
|
||||||
{
|
{
|
||||||
++g;
|
++g;
|
||||||
|
delete x;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StatefulDeleter
|
struct StatefulDeleter
|
||||||
{
|
{
|
||||||
char state;
|
char state;
|
||||||
void operator()(auto*) const noexcept
|
void operator()(auto* x) const noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FinalDeleter final
|
struct FinalDeleter final
|
||||||
{
|
{
|
||||||
void operator()(auto*) const noexcept
|
void operator()(auto* x) const noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -99,6 +100,7 @@ struct Derived : Base
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
|
||||||
{
|
{
|
||||||
Ptr<int> x(new int(5));
|
Ptr<int> x(new int(5));
|
||||||
}
|
}
|
||||||
|
@ -186,9 +188,9 @@ main()
|
||||||
g = 0;
|
g = 0;
|
||||||
{
|
{
|
||||||
auto x = Mk<SetsGDtor>();
|
auto x = Mk<SetsGDtor>();
|
||||||
x.release();
|
delete x.release();
|
||||||
}
|
}
|
||||||
if (g)
|
if (g != 1)
|
||||||
return 13;
|
return 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +226,5 @@ main()
|
||||||
Ptr<Base> z(ctl::move(y));
|
Ptr<Base> z(ctl::move(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
// next is 18
|
CheckForMemoryLeaks();
|
||||||
|
|
||||||
// TODO(mrdomino): Fix memory leaks reported by MODE=dbg
|
|
||||||
// CheckForMemoryLeaks();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue