@auto_js/utility 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +45 -0
- package/LICENSE +13 -0
- package/_module.cc +14 -0
- package/assertions.cc +32 -0
- package/container/mutable_priority_queue.cc +35 -0
- package/container/sealed_map.cc +121 -0
- package/container/segmented_priority_queue.cc +105 -0
- package/container/tinker_queue.cc +73 -0
- package/functional/bind.cc +151 -0
- package/functional/elide.cc +52 -0
- package/functional/flat_tuple.cc +90 -0
- package/functional/function_constant.cc +58 -0
- package/functional/function_ref.cc +68 -0
- package/functional/functional.cc +107 -0
- package/functional/regular_return.cc +55 -0
- package/include/auto_js/chunk_view.h +363 -0
- package/include/auto_js/no_unique_address.h +8 -0
- package/memory/autorelease_pool.cc +281 -0
- package/memory/comparator.cc +53 -0
- package/memory/memory.cc +64 -0
- package/memory/noinit_allocator.cc +64 -0
- package/meta/algorithm.cc +74 -0
- package/package.json +11 -0
- package/platform/lockable.cc +261 -0
- package/platform/shim/darwin.cc +8 -0
- package/platform/stop_token.cc +107 -0
- package/platform/timer.cc +175 -0
- package/platform/timer.h.cc +36 -0
- package/type_traits/function_traits.cc +173 -0
- package/type_traits/transform.cc +60 -0
- package/type_traits/type_of.cc +72 -0
- package/type_traits/type_pack.cc +116 -0
- package/type_traits/type_traits.cc +5 -0
- package/utility/constant_wrapper.cc +57 -0
- package/utility/covariant_value.cc +33 -0
- package/utility/facade.cc +126 -0
- package/utility/hash.cc +37 -0
- package/utility/ranges.cc +55 -0
- package/utility/string.cc +328 -0
- package/utility/utility.cc +150 -0
- package/utility/variant.cc +26 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module;
|
|
2
|
+
#include "auto_js/no_unique_address.h"
|
|
3
|
+
#include <type_traits>
|
|
4
|
+
#include <utility>
|
|
5
|
+
export module util:functional.flat_tuple;
|
|
6
|
+
|
|
7
|
+
namespace util {
|
|
8
|
+
|
|
9
|
+
// Internal `flat_tuple` element storage
|
|
10
|
+
template <std::size_t Index, class Type>
|
|
11
|
+
class flat_tuple_element {
|
|
12
|
+
public:
|
|
13
|
+
flat_tuple_element() = default;
|
|
14
|
+
constexpr explicit flat_tuple_element(Type&& value) : value_{std::move(value)} {}
|
|
15
|
+
constexpr explicit flat_tuple_element(const Type& value) : value_{value} {}
|
|
16
|
+
|
|
17
|
+
using index_type = std::integral_constant<std::size_t, Index>;
|
|
18
|
+
constexpr auto get(index_type /*index*/) & -> Type& { return value_; }
|
|
19
|
+
constexpr auto get(index_type /*index*/) && -> Type&& { return std::move(value_); }
|
|
20
|
+
[[nodiscard]] constexpr auto get(index_type /*index*/) const& -> const Type& { return value_; }
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
NO_UNIQUE_ADDRESS Type value_;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Specialization for reference types
|
|
27
|
+
template <std::size_t Index, class Type>
|
|
28
|
+
class flat_tuple_element<Index, Type&> {
|
|
29
|
+
public:
|
|
30
|
+
flat_tuple_element() = delete;
|
|
31
|
+
constexpr explicit flat_tuple_element(Type& value) : value_{&value} {}
|
|
32
|
+
|
|
33
|
+
using index_type = std::integral_constant<std::size_t, Index>;
|
|
34
|
+
constexpr auto get(index_type /*index*/) & -> Type& { return *value_; }
|
|
35
|
+
constexpr auto get(index_type /*index*/) && -> Type& { return *value_; }
|
|
36
|
+
[[nodiscard]] constexpr auto get(index_type /*index*/) const& -> const Type& { return *value_; }
|
|
37
|
+
|
|
38
|
+
private:
|
|
39
|
+
NO_UNIQUE_ADDRESS Type* value_;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Internal `flat_tuple` helper providing access into private `flat_tuple_element` via friend
|
|
43
|
+
// visibility
|
|
44
|
+
constexpr auto flat_tuple_get(auto index, auto&& tuple) -> auto&& {
|
|
45
|
+
return std::forward<decltype(tuple)>(tuple).get(index);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Internal `flat_tuple_storage` element collection storage
|
|
49
|
+
template <class Indices, class... Types>
|
|
50
|
+
class flat_tuple_storage;
|
|
51
|
+
|
|
52
|
+
template <class... Types>
|
|
53
|
+
using flat_tuple_storage_t = flat_tuple_storage<std::make_index_sequence<sizeof...(Types)>, Types...>;
|
|
54
|
+
|
|
55
|
+
template <std::size_t... Index, class... Type>
|
|
56
|
+
class flat_tuple_storage<std::index_sequence<Index...>, Type...> : private flat_tuple_element<Index, Type>... {
|
|
57
|
+
public:
|
|
58
|
+
flat_tuple_storage() = default;
|
|
59
|
+
constexpr explicit flat_tuple_storage(auto&&... values) :
|
|
60
|
+
flat_tuple_element<Index, Type>{std::forward<decltype(values)>(values)}... {}
|
|
61
|
+
|
|
62
|
+
private:
|
|
63
|
+
constexpr friend auto flat_tuple_get(auto, auto&&) -> auto&&;
|
|
64
|
+
using flat_tuple_element<Index, Type>::get...;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Simple replacement for `std::tuple` which is trivially copyable in the case its members are.
|
|
68
|
+
// See: `static_assert(!std::is_trivially_copyable_v<std::tuple<int>>);`
|
|
69
|
+
export template <class... Types>
|
|
70
|
+
struct flat_tuple : flat_tuple_storage_t<Types...> {
|
|
71
|
+
using flat_tuple_storage_t<Types...>::flat_tuple_storage_t;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// `std::get` replacement for `flat_tuple`
|
|
75
|
+
export template <std::size_t Index, class... Types>
|
|
76
|
+
constexpr auto get(flat_tuple<Types...>& tuple) -> auto& {
|
|
77
|
+
return flat_tuple_get(std::integral_constant<std::size_t, Index>{}, tuple);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export template <std::size_t Index, class... Types>
|
|
81
|
+
constexpr auto get(flat_tuple<Types...>&& tuple) -> auto&& {
|
|
82
|
+
return flat_tuple_get(std::integral_constant<std::size_t, Index>{}, std::move(tuple));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export template <std::size_t Index, class... Types>
|
|
86
|
+
constexpr auto get(const flat_tuple<Types...>& tuple) -> const auto& {
|
|
87
|
+
return flat_tuple_get(std::integral_constant<std::size_t, Index>{}, tuple);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
} // namespace util
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module;
|
|
2
|
+
#include <concepts>
|
|
3
|
+
#include <utility>
|
|
4
|
+
export module util:functional.function_constant;
|
|
5
|
+
import :type_traits;
|
|
6
|
+
|
|
7
|
+
namespace util {
|
|
8
|
+
|
|
9
|
+
// Kind of related to P3774 [https://isocpp.org/files/papers/P3774R0.html] but returns an invocable
|
|
10
|
+
// which can be inferred with `function_signature_t`.
|
|
11
|
+
export template <auto Invocable>
|
|
12
|
+
struct function_constant;
|
|
13
|
+
|
|
14
|
+
export template <auto Invocable>
|
|
15
|
+
constexpr auto fn = function_constant<Invocable>{};
|
|
16
|
+
|
|
17
|
+
template <auto Invocable, class Function, class Signature>
|
|
18
|
+
struct function_constant_of;
|
|
19
|
+
|
|
20
|
+
template <auto Invocable, class Function>
|
|
21
|
+
struct function_constant_with;
|
|
22
|
+
|
|
23
|
+
// Specialization for inferrable signatures
|
|
24
|
+
template <auto Invocable>
|
|
25
|
+
requires requires { typename function_signature_t<decltype(Invocable)>; }
|
|
26
|
+
struct function_constant<Invocable> : function_constant_of<Invocable, decltype(Invocable), function_signature_t<decltype(Invocable)>> {};
|
|
27
|
+
|
|
28
|
+
// Overloaded invocable
|
|
29
|
+
template <auto Invocable>
|
|
30
|
+
struct function_constant : function_constant_with<Invocable, decltype(Invocable)> {};
|
|
31
|
+
|
|
32
|
+
// Free function or invocable object
|
|
33
|
+
template <auto Invocable, class Function, class... Args, bool Nx, class Result>
|
|
34
|
+
struct function_constant_of<Invocable, Function, auto(Args...) noexcept(Nx)->Result> {
|
|
35
|
+
constexpr auto operator()(Args... args) const noexcept(Nx) -> Result {
|
|
36
|
+
return Invocable(std::forward<Args>(args)...);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Member function pointer
|
|
41
|
+
template <auto Invocable, class Type, class Function, class That, class... Args, bool Nx, class Result>
|
|
42
|
+
struct function_constant_of<Invocable, Function Type::*, auto(That, Args...) noexcept(Nx)->Result> {
|
|
43
|
+
constexpr auto operator()(That that, Args... args) const noexcept(Nx) -> Result {
|
|
44
|
+
return (std::forward<That>(that).*Invocable)(std::forward<Args>(args)...);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Overloaded function
|
|
49
|
+
template <auto Invocable, class Function>
|
|
50
|
+
struct function_constant_with {
|
|
51
|
+
template <class... Args>
|
|
52
|
+
constexpr auto operator()(Args&&... args) const noexcept(std::is_nothrow_invocable_v<Function, Args...>) -> decltype(auto)
|
|
53
|
+
requires std::invocable<Function, Args...> {
|
|
54
|
+
return Invocable(std::forward<Args>(args)...);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
} // namespace util
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module;
|
|
2
|
+
#include <concepts>
|
|
3
|
+
#include <type_traits>
|
|
4
|
+
#include <utility>
|
|
5
|
+
export module util:functional.function_ref;
|
|
6
|
+
import :functional.elide;
|
|
7
|
+
import :type_traits;
|
|
8
|
+
|
|
9
|
+
namespace util {
|
|
10
|
+
|
|
11
|
+
export template <class Signature>
|
|
12
|
+
class function_ref;
|
|
13
|
+
|
|
14
|
+
template <class Result, bool Nx, class... Args>
|
|
15
|
+
class function_ref<auto(Args...) noexcept(Nx)->Result> {
|
|
16
|
+
private:
|
|
17
|
+
template <class Type>
|
|
18
|
+
constexpr explicit function_ref(std::type_identity<Type> /*tag*/, void* ptr) :
|
|
19
|
+
invoke_{[](void* ptr, Args... args) noexcept(Nx) -> Result {
|
|
20
|
+
auto& object = *static_cast<Type*>(ptr);
|
|
21
|
+
return object(std::forward<Args>(args)...);
|
|
22
|
+
}},
|
|
23
|
+
ptr_{ptr} {}
|
|
24
|
+
|
|
25
|
+
public:
|
|
26
|
+
using signature_type = auto(Args...) noexcept(Nx) -> Result;
|
|
27
|
+
|
|
28
|
+
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
29
|
+
constexpr function_ref(signature_type* function) :
|
|
30
|
+
function_ref{std::type_identity<signature_type>{}, static_cast<void*>(function)} {}
|
|
31
|
+
|
|
32
|
+
template <std::invocable<Args...> Object>
|
|
33
|
+
requires(type<Object> != type<function_ref>)
|
|
34
|
+
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
35
|
+
constexpr function_ref(Object& object) :
|
|
36
|
+
function_ref{std::type_identity<Object>{}, static_cast<void*>(&object)} {}
|
|
37
|
+
|
|
38
|
+
// Explicit to avoid automatic binding to temporary objects
|
|
39
|
+
template <std::invocable<Args...> Object>
|
|
40
|
+
requires(type<Object> != type<function_ref>)
|
|
41
|
+
constexpr explicit function_ref(const Object& object) :
|
|
42
|
+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
|
43
|
+
function_ref{std::type_identity<const Object>{}, const_cast<void*>(static_cast<const void*>(&object))} {}
|
|
44
|
+
|
|
45
|
+
// Bound function constant
|
|
46
|
+
template <class Object, std::invocable<Object&, Args...> Function>
|
|
47
|
+
requires std::is_empty_v<Function>
|
|
48
|
+
constexpr explicit function_ref(Function /*function*/, Object& bound) :
|
|
49
|
+
invoke_{[](void* ptr, Args... args) noexcept(Nx) -> Result {
|
|
50
|
+
auto& object = *static_cast<Object*>(ptr);
|
|
51
|
+
constexpr auto function = Function{};
|
|
52
|
+
return function(object, std::forward<Args>(args)...);
|
|
53
|
+
}},
|
|
54
|
+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
|
55
|
+
ptr_{const_cast<void*>(static_cast<const void*>(&bound))} {}
|
|
56
|
+
|
|
57
|
+
constexpr auto operator()(Args... args) const noexcept(Nx) -> Result {
|
|
58
|
+
return invoke_(ptr_, std::forward<Args>(args)...);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private:
|
|
62
|
+
using invoke_type = auto(void*, Args...) noexcept(Nx) -> Result;
|
|
63
|
+
|
|
64
|
+
invoke_type* invoke_;
|
|
65
|
+
void* ptr_;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
} // namespace util
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module;
|
|
2
|
+
#include <functional>
|
|
3
|
+
#include <utility>
|
|
4
|
+
export module util:functional;
|
|
5
|
+
export import :functional.bind;
|
|
6
|
+
export import :functional.elide;
|
|
7
|
+
export import :functional.function_constant;
|
|
8
|
+
export import :functional.function_ref;
|
|
9
|
+
export import :functional.regular_return;
|
|
10
|
+
import :type_traits;
|
|
11
|
+
|
|
12
|
+
namespace util {
|
|
13
|
+
|
|
14
|
+
// https://en.cppreference.com/w/cpp/utility/variant/visit
|
|
15
|
+
export template <class... Visitors>
|
|
16
|
+
struct overloaded : Visitors... {
|
|
17
|
+
using Visitors::operator()...;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Holder for functions in libc++ which doesn't support std::move_only_function
|
|
21
|
+
#if defined(__cpp_lib_move_only_function) && !defined(DEBUG)
|
|
22
|
+
|
|
23
|
+
export template <class Signature>
|
|
24
|
+
using maybe_move_only_function = std::move_only_function<Signature>;
|
|
25
|
+
|
|
26
|
+
export template <class Fn>
|
|
27
|
+
auto make_indirect_moveable_function(Fn fn) {
|
|
28
|
+
return fn;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#else
|
|
32
|
+
|
|
33
|
+
export template <class Signature>
|
|
34
|
+
using maybe_move_only_function = std::function<remove_function_cvref_t<Signature>>;
|
|
35
|
+
|
|
36
|
+
export template <class Fn>
|
|
37
|
+
auto make_indirect_moveable_function(Fn&& fn) {
|
|
38
|
+
auto fn_ptr = std::make_shared<std::remove_cvref_t<Fn>>(std::forward<Fn>(fn));
|
|
39
|
+
return [ = ](auto&&... args) -> decltype(auto) {
|
|
40
|
+
return (*fn_ptr)(std::forward<decltype(args)>(args)...);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
// Hide `-Wunused-value` warnings
|
|
47
|
+
export constexpr auto unused = [](auto&& /*nothing*/) -> void {};
|
|
48
|
+
|
|
49
|
+
// Invoke the given callable as a base class of itself. cvref qualifiers are forwarded, so `Type` is
|
|
50
|
+
// expected to be unqualified.
|
|
51
|
+
export template <class Type, class From>
|
|
52
|
+
constexpr auto invoke_as(From&& func, auto&&... args)
|
|
53
|
+
-> decltype(std::declval<apply_cvref_t<From, Type>>()(std::declval<decltype(args)>()...)) {
|
|
54
|
+
return static_cast<apply_cvref_t<From, Type>>(std::forward<decltype(func)>(func))(std::forward<decltype(args)>(args)...);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Invoke the given callable using an explicit and possibly shadowed `operator()()` on a base class,
|
|
58
|
+
// but without erasing the pointer type for deduced `this`. The syntax here is messy, and
|
|
59
|
+
// `InvokeAsType_` can be shadowed by the base class. Also, clang has some really spooky behavior
|
|
60
|
+
// which is resolved by breaking out invocations to deduced-this instances.
|
|
61
|
+
export template <class InvokeAsType_>
|
|
62
|
+
constexpr auto invoke_this_as(auto&& func, auto&&... args)
|
|
63
|
+
// This is functionally the same as ` -> decltype(auto)` but works around the error:
|
|
64
|
+
// 'invoke_as<...>' with deduced return type cannot be used before it is defined
|
|
65
|
+
-> decltype(std::declval<decltype(func)>().InvokeAsType_::operator()(std::declval<decltype(args)>()...)) {
|
|
66
|
+
return std::forward<decltype(func)>(func).InvokeAsType_::operator()(std::forward<decltype(args)>(args)...);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Invoke the given function with the constant expression matching a runtime value.
|
|
70
|
+
export constexpr auto template_switch(const auto& value, auto case_pack, auto invoke) -> decltype(auto) {
|
|
71
|
+
auto dispatch = [ & ](this const auto& self, auto case_, auto... cases) -> decltype(auto) {
|
|
72
|
+
if (value == case_) {
|
|
73
|
+
return invoke(case_);
|
|
74
|
+
} else {
|
|
75
|
+
if constexpr (sizeof...(cases) == 0) {
|
|
76
|
+
// default
|
|
77
|
+
return invoke();
|
|
78
|
+
} else {
|
|
79
|
+
return self(cases...);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const auto [... cases ] = case_pack;
|
|
84
|
+
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
|
|
85
|
+
return dispatch(cases...);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// libc++'s `std::reference_wrapper` causes a template instantiation while looking for
|
|
89
|
+
// `result_type`. That breaks our transfer machinery.
|
|
90
|
+
export template <class Type>
|
|
91
|
+
class reference_wrapper {
|
|
92
|
+
public:
|
|
93
|
+
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
94
|
+
constexpr reference_wrapper(Type& value) : value_{&value} {}
|
|
95
|
+
|
|
96
|
+
constexpr auto operator()(auto&&... args) const
|
|
97
|
+
-> decltype(std::declval<Type&>()(std::declval<decltype(args)>()...)) {
|
|
98
|
+
return (*value_)(std::forward<decltype(args)>(args)...);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
constexpr auto get() const -> Type& { return *value_; }
|
|
102
|
+
|
|
103
|
+
private:
|
|
104
|
+
Type* value_;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
} // namespace util
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module;
|
|
2
|
+
#include <utility>
|
|
3
|
+
export module util:functional.regular_return;
|
|
4
|
+
import :type_traits;
|
|
5
|
+
import :utility;
|
|
6
|
+
|
|
7
|
+
namespace util {
|
|
8
|
+
|
|
9
|
+
// Value wrapper which can accept void values. `operator*` will return the underlying value.
|
|
10
|
+
template <class Type>
|
|
11
|
+
class regular_value {
|
|
12
|
+
public:
|
|
13
|
+
constexpr explicit regular_value(Type value) :
|
|
14
|
+
value_{std::move(value)} {}
|
|
15
|
+
|
|
16
|
+
constexpr auto operator*() && -> Type { return std::move(value_); }
|
|
17
|
+
constexpr auto value_or(const auto& /*nothing*/) && -> Type { return *std::move(*this); };
|
|
18
|
+
|
|
19
|
+
private:
|
|
20
|
+
Type value_;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
template <>
|
|
24
|
+
class regular_value<void> {
|
|
25
|
+
public:
|
|
26
|
+
constexpr auto operator*() const -> void {}
|
|
27
|
+
|
|
28
|
+
template <class Type>
|
|
29
|
+
constexpr auto value_or(Type value) -> Type { return value; };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Wraps the given invocable. When invoked it returns `regular_value<T>` of the function return
|
|
33
|
+
// value.
|
|
34
|
+
export template <class Type>
|
|
35
|
+
class regular_return {
|
|
36
|
+
public:
|
|
37
|
+
constexpr explicit regular_return(Type invoke) :
|
|
38
|
+
invoke_{std::move(invoke)} {}
|
|
39
|
+
|
|
40
|
+
constexpr auto operator()(this auto&& self, auto&&... args)
|
|
41
|
+
-> regular_value<std::invoke_result_t<util::apply_cvref_t<decltype(self), Type>, decltype(args)...>> {
|
|
42
|
+
using result_type = std::invoke_result_t<util::apply_cvref_t<decltype(self), Type>, decltype(args)...>;
|
|
43
|
+
if constexpr (std::is_void_v<result_type>) {
|
|
44
|
+
std::forward<decltype(self)>(self).invoke_(std::forward<decltype(args)>(args)...);
|
|
45
|
+
return regular_value<void>{};
|
|
46
|
+
} else {
|
|
47
|
+
return regular_value<result_type>{std::forward<decltype(self)>(self).invoke_(std::forward<decltype(args)>(args)...)};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private:
|
|
52
|
+
Type invoke_;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
} // namespace util
|