BUUUUUNCH of shit, but added logger, more stl nonsense, improved code quaklity, squashed bugs.

This commit is contained in:
Gvidas Juknevičius 2025-05-31 16:12:31 +03:00
parent 3b1b2bfb06
commit 2a31d770ed
Signed by: MCorange
GPG Key ID: 5BE6B533CB76FE86
31 changed files with 1543 additions and 21 deletions

2
.vscode/launch.json vendored
View File

@ -6,7 +6,7 @@
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"type": "by-gdb",
"request": "launch",
"program": "${workspaceFolder}/test/test",
"args": [],

View File

@ -2,11 +2,11 @@ LIB=libc+
COM_FLAGS = -fPIC -Isrc/include
CC_FLAGS = -std=c23 -ggdb
CXX_FLAGS = -std=c++23 -nostdinc++ -ggdb
LD_FLAGS = -nostdlib++ -lsupc++ -ggdb
CC=gcc
CXX=g++
LD=gcc
CXX_FLAGS = -std=c++23 -nostdinc++ -ggdb -fexceptions
LD_FLAGS = -nostdlib++ -lsupc++ -ggdb -fexceptions
CC=clang
CXX=clang
LD=clang
AR=ar
cxx_sources=$(wildcard src/*.cpp)

View File

@ -0,0 +1,35 @@
#ifndef _H_LIBCP_COLLECTIONS_HASHMAP
#define _H_LIBCP_COLLECTIONS_HASHMAP
#include "option.hpp"
#include <collections/vec.hpp>
#include <stdint.h>
namespace __internal {
template <typename K, typename V>
struct HashMapPart {
private:
// uint8_t hash[4];
K key;
V val;
public:
};
} // namespace __internal
template <typename K, typename V>
class HashMap {
private:
Vec<__internal::HashMapPart<K, V>> items;
public:
HashMap() = default;
~HashMap() = default;
Option<V> insert(K& key, V& value) {}
Option<V> get(K& key) {}
};
#endif // !_H_LIBCP_COLLECTIONS_HASHMAP

View File

@ -1,10 +1,10 @@
#ifndef _H_LIBCP_COLLECTIONS_VEC
#define _H_LIBCP_COLLECTIONS_VEC
#include "result.hpp"
#include <result.hpp>
#include <option.hpp>
#include <stdint.h>
#include <stddef.h>
#include <stddef.hpp>
template <typename T>
class Vec {

View File

@ -0,0 +1,23 @@
#ifndef _H_LIBCP_CONFIG_PLATFORM
#if defined(__linux__)
#define PLATFORM_LINUX
#elif defined(__APPLE__) && defined(__MACH__)
#define PLATFORM_MACOS
#elif defined(__FreeBSD__)
#define PLATFORM_FREEBSD
#elif defined(__NetBSD__)
#define PLATFORM_NETBSD
#elif defined(__OpenBSD__)
#define PLATFORM_OPENBSD
#elif defined(_WIN32)
#define PLATFORM_WINDOWS
#else
#define PLATFORM_UNKNOWN
#endif
#ifdef PLATFORM_UNKNOWN
#error This platform is not supported by this library yet
#endif // PLATFORM_UNKNOWN
#endif // !_H_LIBCP_CONFIG_PLATFORM

View File

@ -18,7 +18,7 @@ concept Format = requires(T t) {
#ifndef __CONCEPT_ONLY
namespace __internal {
namespace {
String format(Vec<String>& args, String& _fmt) {
const char* fmt = _fmt.as_cstr();
String str = String();
@ -33,7 +33,9 @@ namespace __internal {
}
if (fmt[i + 1] == '}') {
i += 1;
String* arg = args.nth(args_idx).unwrap();
if (args.len() <= args_idx) {
}
String* arg = args.nth(args_idx).expect("Amount of arguments dont match amount of placeholders in format string");
str.push_str(*arg);
args_idx += 1;
}
@ -54,17 +56,18 @@ namespace __internal {
args.push(Formatter<ActualType>::fmt_to_str(var1));
}
return __internal::format(args, fmt, var2...);
return format(args, fmt, var2...);
}
} // namespace __internal
} // namespace
template <typename... Types>
String format(const char* fmt, Types... vars) {
Vec<String> args = Vec<String>();
String fmt_ = String(fmt);
return __internal::format(args, fmt_, vars...);
return format(args, fmt_, vars...);
}
// Has to be here, cause c++
template <Format T>
struct Formatter<Vec<T>> {
static String fmt_to_str(Vec<T>& val) {

View File

@ -0,0 +1,43 @@
#ifndef _H_LIBCP_FORMAT_OBJ_FMT_HELPER
#define _H_LIBCP_FORMAT_OBJ_FMT_HELPER
#include <stddef.h>
#include <format/fmt.hpp>
#include <string.hpp>
#include <collections/vec.hpp>
class ObjFmtHelper {
private:
String buffer = String();
size_t nest_level = 0;
public:
ObjFmtHelper(const char* name) {
buffer.push_str(name);
buffer.push_str(" {\n");
};
ObjFmtHelper(int level, const char* name) {
this->nest_level = level;
buffer.push_str(name);
buffer.push_str(" {\n");
};
~ObjFmtHelper() = default;
template <Format T>
void add_field(const char* name, T val) {
for (size_t i = 0; i < nest_level + 1; i++) {
this->buffer.push_str(" ");
}
auto s = format("{}: {}\n", name, val);
this->buffer.push_str(s);
}
String finish() {
this->buffer.push_str("}\n");
return this->buffer;
}
};
#endif // !_H_LIBCP_FORMAT_OBJ_FMT_HELPER

17
src/include/hash/hash.hpp Normal file
View File

@ -0,0 +1,17 @@
#include <stdint.h>
#include <stl.hpp>
#include <sys/types.h>
#define HASH_SIZE 4
template <typename T>
struct Hasher;
template <typename T>
concept Hash = requires(T t) {
{ t.hash() } -> stl::same_as<uint8_t[HASH_SIZE]>;
} || requires(T t) {
{ Hasher<T>::hash(t) } -> stl::same_as<u_int8_t[HASH_SIZE]>;
};

View File

@ -4,14 +4,16 @@
#include <format/fmt.hpp>
extern "C" {
int puts(const char* s);
int putchar(int c);
}
template <typename... Types>
void print(const char* fmt, Types... args) {
String s = format(fmt, args...);
puts(s.as_cstr());
char* cs = s.as_cstr();
for (int i = 0; i < s.len(); i++) {
putchar(cs[i]);
}
}
template <typename... Types>

60
src/include/logger.hpp Normal file
View File

@ -0,0 +1,60 @@
#include "format/fmt.hpp"
#ifndef _H_LIBCP_LOGGER
#include <io/print.hpp>
#include <string.hpp>
#include <sync/spinlock.hpp>
namespace log {
#define LOG_LEVEL_COUNT 4
enum LogLevel { LOG_OFF = -1, LOG_ERROR = 0, LOG_WARN, LOG_INFO, LOG_DEBUG };
class Logger {
private:
LogLevel filter_level = LOG_INFO;
const char* prefixes[LOG_LEVEL_COUNT];
public:
void log(LogLevel level, const char* file, const int line, const char* func, const char* str);
void log(LogLevel level, const char* file, const int line, const char* func, String str);
void set_log_level(LogLevel level);
const char* get_prefix(LogLevel level);
void load_default_prefixes_with_color();
void load_default_prefixes();
void load_custom_prefixes(const char* pfx[LOG_LEVEL_COUNT]);
Logger();
~Logger() = default;
private:
bool should_display(LogLevel level);
};
namespace {
SpinLock<log::Logger*> LOGGER = SpinLock<log::Logger*>(new log::Logger());
}
template <typename... Args>
void debug(const char* fmt, Args... args, const char* file = __builtin_FILE(), int line = __builtin_LINE(), const char* function = __builtin_FUNCTION()) {
LOGGER.lock().get()->log(LOG_DEBUG, file, line, function, format(fmt, args...));
}
template <typename... Args>
void info(const char* fmt, Args... args, const char* file = __builtin_FILE(), int line = __builtin_LINE(), const char* function = __builtin_FUNCTION()) {
LOGGER.lock().get()->log(LOG_INFO, file, line, function, format(fmt, args...));
}
template <typename... Args>
void warn(const char* fmt, Args... args, const char* file = __builtin_FILE(), int line = __builtin_LINE(), const char* function = __builtin_FUNCTION()) {
LOGGER.lock().get()->log(LOG_WARN, file, line, function, format(fmt, args...));
}
template <typename... Args>
void error(const char* fmt, Args... args, const char* file = __builtin_FILE(), int line = __builtin_LINE(), const char* function = __builtin_FUNCTION()) {
LOGGER.lock().get()->log(LOG_ERROR, file, line, function, format(fmt, args...));
}
} // namespace log
#endif // !_H_LIBCP_LOGGER

View File

@ -3,6 +3,10 @@
#define _H_LIBCP_OPTION
#include <stl.hpp>
extern "C" {
int puts(const char* s);
}
template <typename T>
class Option {
bool has_value = false;
@ -35,8 +39,19 @@ public:
return !has_value;
}
T& expect(const char* str) {
if (!has_value) {
puts("PANIC: Unwrapped a None Option: ");
puts(str);
puts("\n");
__builtin_trap();
}
return this->storage;
}
T& unwrap() {
if (!has_value) {
puts("PANIC: Unwrapped a None Option\n");
__builtin_trap();
}
return this->storage;

View File

@ -3,6 +3,10 @@
#include <stl.hpp>
extern "C" {
int puts(const char* s);
};
template <typename E>
struct ResultErrBase {
bool is_okay = true;
@ -80,9 +84,20 @@ public:
}
}
T& expect(const char* str) {
if (!this->is_ok()) {
puts("PANIC: Unwrapped result with error: ");
puts(str);
puts("\n");
__builtin_trap();
}
return &this->ok_data;
}
T& unwrap() {
if (!this->is_ok()) {
throw "Unwrapped result with error";
puts("PANIC: Unwrapped result with error\n");
__builtin_trap();
}
return &this->ok_data;
}

View File

@ -2,8 +2,8 @@
#ifndef _H_LIBCP
#define _H_LIBCP
#include <stddef.hpp>
#include <stdint.h>
#include <string.hpp>
#include <collections/vec.hpp>
#include <format/fmt.hpp>

7
src/include/stddef.hpp Normal file
View File

@ -0,0 +1,7 @@
#ifndef _H_LIBCP_STDDEF
using size_t = decltype(sizeof(int));
using ptrdiff_t = decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr));
using nullptr_t = decltype(nullptr);
#endif // !_H_LIBCP_STDDEF

View File

@ -9,6 +9,13 @@ namespace stl {
#include <stl/move.hpp>
#include <stl/remove_cvref.hpp>
#include <stl/remove_reference.hpp>
#include <stl/add_lvalue_reference.hpp>
#include <stl/add_rvalue_reference.hpp>
#include <stl/integer_sequence.hpp>
#include <stl/is_constructable.hpp>
#include <stl/void_t.hpp>
#include <stl/is_referenceable.hpp>
#include <stl/is_integral.hpp>
} // namespace stl
#endif // _H_LIBCP_STL

View File

@ -0,0 +1,35 @@
#ifndef _H_LIBCP_STL_ADD_LVALUE_REF
#define _H_LIBCP_STL_ADD_LVALUE_REF
#include <stl/is_referenceable.hpp>
#if __has_builtin(__add_lvalue_reference)
template <class _Tp>
using __add_lvalue_reference_t = __add_lvalue_reference(_Tp);
#else
template <class _Tp, bool = __is_referenceable_v<_Tp>>
struct __add_lvalue_reference_impl {
using type = _Tp;
};
template <class _Tp>
struct __add_lvalue_reference_impl<_Tp, true> {
using type = _Tp&;
};
template <class _Tp>
using __add_lvalue_reference_t = typename __add_lvalue_reference_impl<_Tp>::type;
#endif // __has_builtin(__add_lvalue_reference)
template <class _Tp>
struct add_lvalue_reference {
using type = __add_lvalue_reference_t<_Tp>;
};
template <class _Tp>
using add_lvalue_reference_t = __add_lvalue_reference_t<_Tp>;
#endif // _H_LIBCP_STL_ADD_LVALUE_REF

View File

@ -0,0 +1,36 @@
#ifndef _H_LIBCP_STL_ADD_RVALUE_REF
#define _H_LIBCP_STL_ADD_RVALUE_REF
#include <stl/is_referenceable.hpp>
#if __has_builtin(__add_rvalue_reference)
template <class _Tp>
using __add_rvalue_reference_t = __add_rvalue_reference(_Tp);
#else
template <class _Tp, bool = __is_referenceable_v<_Tp>>
struct __add_rvalue_reference_impl {
using type = _Tp;
};
template <class _Tp>
struct __add_rvalue_reference_impl<_Tp, true> {
using type = _Tp&&;
};
template <class _Tp>
using __add_rvalue_reference_t = typename __add_rvalue_reference_impl<_Tp>::type;
#endif // __has_builtin(__add_rvalue_reference)
template <class _Tp>
struct add_rvalue_reference {
using type = __add_rvalue_reference_t<_Tp>;
};
template <class _Tp>
using add_rvalue_reference_t = __add_rvalue_reference_t<_Tp>;
#endif // _H_LIBCP_STL_ADD_RVALUE_REF

View File

@ -0,0 +1,67 @@
#ifndef _H_LIBCP_STL_INTEGER_SEQUENCE
#define _H_LIBCP_STL_INTEGER_SEQUENCE
#include <stddef.h>
#include <stl/is_integral.hpp>
template <size_t...>
struct __tuple_indices;
template <class _IdxType, _IdxType... _Values>
struct __integer_sequence {
template <template <class _OIdxType, _OIdxType...> class _ToIndexSeq, class _ToIndexType>
using __convert = _ToIndexSeq<_ToIndexType, _Values...>;
template <size_t _Sp>
using __to_tuple_indices = __tuple_indices<(_Values + _Sp)...>;
};
#if __has_builtin(__make_integer_seq)
template <size_t _Ep, size_t _Sp>
using __make_indices_imp = typename __make_integer_seq<__integer_sequence, size_t, _Ep - _Sp>::template __to_tuple_indices<_Sp>;
#elif __has_builtin(__integer_pack)
template <size_t _Ep, size_t _Sp>
using __make_indices_imp = typename __integer_sequence<size_t, __integer_pack(_Ep - _Sp)...>::template __to_tuple_indices<_Sp>;
#else
#error "No known way to get an integer pack from the compiler"
#endif
template <class _Tp, _Tp... _Ip>
struct integer_sequence {
typedef _Tp value_type;
static_assert(is_integral<_Tp>::value, "std::integer_sequence can only be instantiated with an integral type");
static constexpr size_t size() noexcept {
return sizeof...(_Ip);
}
};
template <size_t... _Ip>
using index_sequence = integer_sequence<size_t, _Ip...>;
#if __has_builtin(__make_integer_seq)
template <class _Tp, _Tp _Ep>
using make_integer_sequence = __make_integer_seq<integer_sequence, _Tp, _Ep>;
#elif __has_builtin(__integer_pack)
template <class _Tp, _Tp _SequenceSize>
using make_integer_sequence = integer_sequence<_Tp, __integer_pack(_SequenceSize)...>;
#else
#error "No known way to get an integer pack from the compiler"
#endif
template <size_t _Np>
using make_index_sequence = make_integer_sequence<size_t, _Np>;
template <class... _Tp>
using index_sequence_for = make_index_sequence<sizeof...(_Tp)>;
// Executes __func for every element in an index_sequence.
template <size_t... _Index, class _Function>
constexpr void __for_each_index_sequence(index_sequence<_Index...>, _Function __func) {
(__func.template operator()<_Index>(), ...);
}
#endif // _H_LIBCP_STL_INTEGER_SEQUENCE

View File

@ -0,0 +1,32 @@
#ifndef _H_LIBCP_STL_IS_COPY_CONSTRUCTABLE
#define _H_LIBCP_STL_IS_COPY_CONSTRUCTABLE
#include <stl/integral_constant.hpp>
#include <stl/add_lvalue_reference.hpp>
#include <stl/add_rvalue_reference.hpp>
template <class _Tp, class... _Args>
struct is_constructible : integral_constant<bool, __is_constructible(_Tp, _Args...)> {};
template <class _Tp, class... _Args>
inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
template <class _Tp>
struct is_copy_constructible : integral_constant<bool, __is_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> {};
template <class _Tp>
inline constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value;
template <class _Tp>
struct is_move_constructible : integral_constant<bool, __is_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {};
template <class _Tp>
inline constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value;
template <class _Tp>
struct is_default_constructible : integral_constant<bool, __is_constructible(_Tp)> {};
template <class _Tp>
inline constexpr bool is_default_constructible_v = __is_constructible(_Tp);
#endif // _H_LIBCP_STL_IS_COPY_CONSTRUCTABLE

View File

@ -0,0 +1,53 @@
#ifndef _H_LIBCP_STL_IS_INTEGRAL
#define _H_LIBCP_STL_IS_INTEGRAL
#include <stl/integral_constant.hpp>
#include <stl/remove_cvref.hpp>
// clang-format off
template <class _Tp> struct __libcpp_is_integral { enum { value = 0 }; };
template <> struct __libcpp_is_integral<bool> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<char> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<signed char> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<unsigned char> { enum { value = 1 }; };
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <> struct __libcpp_is_integral<wchar_t> { enum { value = 1 }; };
#endif
#if _LIBCPP_HAS_CHAR8_T
template <> struct __libcpp_is_integral<char8_t> { enum { value = 1 }; };
#endif
template <> struct __libcpp_is_integral<char16_t> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<char32_t> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<short> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<unsigned short> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<int> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<unsigned int> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<long> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<unsigned long> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<long long> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<unsigned long long> { enum { value = 1 }; };
#if _LIBCPP_HAS_INT128
template <> struct __libcpp_is_integral<__int128_t> { enum { value = 1 }; };
template <> struct __libcpp_is_integral<__uint128_t> { enum { value = 1 }; };
#endif
// clang-format on
#if __has_builtin(__is_integral)
template <class _Tp>
struct is_integral : _BoolConstant<__is_integral(_Tp)> {};
template <class _Tp>
inline constexpr bool is_integral_v = __is_integral(_Tp);
#else
template <class _Tp>
struct is_integral : public _BoolConstant<__libcpp_is_integral<__remove_cvref_t<_Tp>>::value> {};
template <class _Tp>
inline constexpr bool is_integral_v = is_integral<_Tp>::value;
#endif // __has_builtin(__is_integral)
#endif // !_H_LIBCP_STL_IS_INTEGRAL

View File

@ -0,0 +1,15 @@
#ifndef _H_LIBCP_STL_IS_REFERENCEABLE
#define _H_LIBCP_STL_IS_REFERENCEABLE
#include <stl/void_t.hpp>
template <class _Tp, class = void>
inline const bool __is_referenceable_v = false;
template <class _Tp>
inline const bool __is_referenceable_v<_Tp, __void_t<_Tp&>> = true;
template <class _Tp>
concept __referenceable = __is_referenceable_v<_Tp>;
#endif // !_H_LIBCP_STL_IS_REFERENCEABLE

View File

@ -0,0 +1,10 @@
#ifndef _H_LIBCP_STL_VOID_T
#define _H_LIBCP_STL_VOID_T
template <class...>
using void_t = void;
template <class...>
using __void_t = void;
#endif // !_H_LIBCP_STL_VOID_T

View File

@ -0,0 +1,77 @@
#ifndef _H_LIBCP_SYNC_MUTEX
#define _H_LIBCP_SYNC_MUTEX
#include <config/platform.hpp>
#ifdef PLATFORM_LINUX
#include <linux/futex.h>
#include <sys/syscall.h>
#endif
#include <unistd.h>
template <typename T>
struct Mutex {
private:
int locked = 0;
T value;
Mutex() = default;
void acquire() {
#ifdef PLATFORM_LINUX
int expected = 0;
if (!__atomic_compare_exchange_n(&this->locked, &expected, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
// someone else already locked it, wait
while (__atomic_exchange_n(&this->locked, 2, __ATOMIC_ACQUIRE) != 0) {
syscall(SYS_futex, &this->locked, FUTEX_WAIT, 2, nullptr, nullptr, 0);
}
}
#endif
}
void release() {
#ifdef PLATFORM_LINUX
if (__atomic_exchange_n(&this->locked, 0, __ATOMIC_RELEASE) == 2) {
syscall(SYS_futex, &this->locked, FUTEX_WAKE, 1, nullptr, nullptr, 0);
}
#endif
}
struct MutexGuard {
private:
Mutex<T>* parent;
public:
MutexGuard(Mutex<T>* p) : parent(p) {
parent->acquire();
}
~MutexGuard() {
parent->release();
}
T& get() {
return parent->value;
}
T* operator->() {
return &parent->value;
}
T& operator*() {
return parent->value;
}
MutexGuard(const MutexGuard&) = delete;
MutexGuard& operator=(const MutexGuard&) = delete;
};
public:
template <typename... Args>
explicit Mutex(Args&&... args) : value((Args&&)args...) {}
MutexGuard lock() {
return MutexGuard(this);
}
};
#endif // !_H_LIBCP_SYNC_MUTEX

View File

@ -0,0 +1,64 @@
#ifndef _H_LIBCP_SYNC_SPINLOCK
#define _H_LIBCP_SYNC_SPINLOCK
#include <io/print.hpp>
#include <stdatomic.h>
template <typename T>
struct SpinLock {
private:
volatile atomic_bool locked = ATOMIC_BOOL_LOCK_FREE;
T value;
SpinLock() = default;
void acquire() {
while (atomic_load_explicit(&locked, memory_order_acquire) == true) {
// println("Locked");
}
}
void release() {
atomic_store_explicit(&locked, false, memory_order_release);
}
struct SpinGuard {
private:
SpinLock<T>* parent;
public:
SpinGuard(SpinLock<T>* p) : parent(p) {
parent->acquire();
}
~SpinGuard() {
parent->release();
}
T& get() {
return parent->value;
}
T* operator->() {
return &parent->value;
}
T& operator*() {
return parent->value;
}
SpinGuard(const SpinGuard&) = delete;
SpinGuard& operator=(const SpinGuard&) = delete;
};
public:
template <typename... Args>
explicit SpinLock(Args&&... args) : value((Args&&)args...) {
atomic_store_explicit(&locked, false, memory_order_release);
}
SpinGuard lock() {
return SpinGuard(this);
}
};
#endif // !_H_LIBCP_SYNC_SPINLOCK

View File

View File

@ -0,0 +1,701 @@
/*===================================================*
| field-reflection version v0.2.1 |
| https://github.com/yosh-matsuda/field-reflection |
| |
| Copyright (c) 2024 Yoshiki Matsuda @yosh-matsuda |
| |
| This software is released under the MIT License. |
| https://opensource.org/license/mit/ |
====================================================*/
// Heavily modified by MCorange <mcorange@mcorangehq.xyz>
#pragma once
#include <stl.hpp>
#include <stddef.h>
namespace field_reflection {
namespace detail {
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundefined-inline"
#endif
template <typename T, size_t = 0>
struct any_lref {
template <typename U>
requires(!stl::same_as<U, T>)
constexpr operator U&() const&& noexcept; // NOLINT
template <typename U>
requires(!stl::same_as<U, T>)
constexpr operator U&() const& noexcept; // NOLINT
};
template <typename T, size_t = 0>
struct any_rref {
template <typename U>
requires(!stl::same_as<U, T>)
constexpr operator U() const&& noexcept; // NOLINT
};
template <typename T, size_t = 0>
struct any_lref_no_base {
template <typename U>
requires(!stl::is_base_of_v<U, T> && !stl::same_as<U, T>)
constexpr operator U&() const&& noexcept; // NOLINT
template <typename U>
requires(!stl::is_base_of_v<U, T> && !stl::same_as<U, T>)
constexpr operator U&() const& noexcept; // NOLINT
};
template <typename T, size_t = 0>
struct any_rref_no_base {
template <typename U>
requires(!stl::is_base_of_v<U, T> && !stl::same_as<U, T>)
constexpr operator U() const&& noexcept; // NOLINT
};
template <typename T, size_t = 0>
struct any_lref_base {
template <typename U>
requires stl::is_base_of_v<U, T>
constexpr operator U&() const&& noexcept; // NOLINT
template <typename U>
requires stl::is_base_of_v<U, T>
constexpr operator U&() const& noexcept; // NOLINT
};
template <typename T, size_t = 0>
struct any_rref_base {
template <typename U>
requires stl::is_base_of_v<U, T>
constexpr operator U() const&& noexcept; // NOLINT
};
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
template <typename T, size_t ArgNum>
concept constructible = (ArgNum == 0 && requires { T{}; }) || []<size_t I0, size_t... Is>(stl::index_sequence<I0, Is...>) {
if constexpr (stl::is_copy_constructible_v<T>) {
return requires { T{any_lref_no_base<T, I0>(), any_lref<T, Is>()...}; };
} else {
return requires { T{any_rref_no_base<T, I0>(), any_rref<T, Is>()...}; };
}
}(stl::make_index_sequence<ArgNum>());
template <typename T>
concept has_base = []() {
if constexpr (stl::is_copy_constructible_v<T>) {
return requires { T{stl::declval<any_lref_base<T>>()}; };
} else {
return requires { T{stl::declval<any_rref_base<T>>()}; };
}
}();
constexpr size_t macro_max_fields_count = 100;
template <typename T>
constexpr auto max_field_count = stl::min(size_t{macro_max_fields_count}, sizeof(T) * CHAR_BIT); // in consideration of bit field
template <typename T, size_t N>
requires stl::is_aggregate_v<T>
constexpr size_t field_count_impl = []() {
if constexpr (N >= max_field_count<T>) {
return stl::numeric_limits<size_t>::max();
} else if constexpr (constructible<T, N> && !constructible<T, N + 1>) {
return N;
} else {
return field_count_impl<T, N + 1>;
}
}();
template <typename T>
requires stl::is_aggregate_v<T>
constexpr size_t field_count_value = field_count_impl<T, 0>;
template <typename T>
concept field_countable = stl::is_aggregate_v<T> && requires { requires field_count_value<T> <= max_field_count<T>; };
template <field_countable T>
constexpr size_t field_count = field_count_value<T>;
template <typename T>
concept field_referenceable = field_countable<T> && (!has_base<T>);
template <typename T, field_referenceable U = stl::remove_cvref_t<T>>
constexpr auto to_ptr_tuple(T&&) {
static_assert([] { return false; }(), "The supported maximum number of fields in struct must be <= 100.");
}
template <typename T, field_referenceable U = stl::remove_cvref_t<T>>
requires(field_count<U> == 0)
constexpr auto to_ptr_tuple(T&&) {
return stl::tie();
}
template <typename T, field_referenceable U = stl::remove_cvref_t<T>>
requires(field_count<U> == 0)
constexpr auto to_tuple(T&&) {
return stl::tie();
}
#pragma region TO_TUPLE_TEMPLATE_MACRO
// map macro: https://github.com/swansontec/map-macro
#define FIELD_RFL_EVAL0(...) __VA_ARGS__
#define FIELD_RFL_EVAL1(...) FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(__VA_ARGS__)))
#define FIELD_RFL_EVAL2(...) FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(__VA_ARGS__)))
#define FIELD_RFL_EVAL3(...) FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(__VA_ARGS__)))
#define FIELD_RFL_EVAL4(...) FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(__VA_ARGS__)))
#define FIELD_RFL_EVAL(...) FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(__VA_ARGS__)))
#define FIELD_RFL_MAP_END(...)
#define FIELD_RFL_MAP_OUT
#define FIELD_RFL_MAP_COMMA ,
#define FIELD_RFL_MAP_GET_END2() 0, FIELD_RFL_MAP_END
#define FIELD_RFL_MAP_GET_END1(...) FIELD_RFL_MAP_GET_END2
#define FIELD_RFL_MAP_GET_END(...) FIELD_RFL_MAP_GET_END1
#define FIELD_RFL_MAP_NEXT0(test, next, ...) next FIELD_RFL_MAP_OUT
#define FIELD_RFL_MAP_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, next, 0)
#define FIELD_RFL_MAP_NEXT(test, next) FIELD_RFL_MAP_NEXT1(FIELD_RFL_MAP_GET_END test, next)
#define FIELD_RFL_MAP0(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP1)(f, peek, __VA_ARGS__)
#define FIELD_RFL_MAP1(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP0)(f, peek, __VA_ARGS__)
#define FIELD_RFL_MAP_LIST_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, FIELD_RFL_MAP_COMMA next, 0)
#define FIELD_RFL_MAP_LIST_NEXT(test, next) FIELD_RFL_MAP_LIST_NEXT1(FIELD_RFL_MAP_GET_END test, next)
#define FIELD_RFL_MAP_LIST0(f, x, peek, ...) f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST1)(f, peek, __VA_ARGS__)
#define FIELD_RFL_MAP_LIST1(f, x, peek, ...) f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST0)(f, peek, __VA_ARGS__)
#define FIELD_RFL_MAP(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
#define FIELD_RFL_MAP_LIST(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
#define FIELD_RFL_ADDR(x) &x
#define FIELD_RFL_DECLTYPE(x) decltype(x)
#define FIELD_RFL_FORWARD(x) stl::forward<decltype(x)>(x)
#define TO_TUPLE_TEMPLATE(NUM, ...) \
template <typename T, field_referenceable U = stl::remove_cvref_t<T>> \
requires(field_count<U> == NUM) \
constexpr auto to_ptr_tuple(T&& t) { \
auto& [__VA_ARGS__] = t; \
return stl::tuple(FIELD_RFL_MAP_LIST(FIELD_RFL_ADDR, __VA_ARGS__)); \
} \
template <typename T, field_referenceable U = stl::remove_cvref_t<T>> \
requires(field_count<U> == NUM) \
constexpr auto to_tuple(T&& t) { \
auto [__VA_ARGS__] = stl::forward<T>(t); \
return stl::tuple<FIELD_RFL_MAP_LIST(FIELD_RFL_DECLTYPE, __VA_ARGS__)>(FIELD_RFL_MAP_LIST(FIELD_RFL_FORWARD, __VA_ARGS__)); \
}
TO_TUPLE_TEMPLATE(1, p0)
TO_TUPLE_TEMPLATE(2, p0, p1)
TO_TUPLE_TEMPLATE(3, p0, p1, p2)
TO_TUPLE_TEMPLATE(4, p0, p1, p2, p3)
TO_TUPLE_TEMPLATE(5, p0, p1, p2, p3, p4)
TO_TUPLE_TEMPLATE(6, p0, p1, p2, p3, p4, p5)
TO_TUPLE_TEMPLATE(7, p0, p1, p2, p3, p4, p5, p6)
TO_TUPLE_TEMPLATE(8, p0, p1, p2, p3, p4, p5, p6, p7)
TO_TUPLE_TEMPLATE(9, p0, p1, p2, p3, p4, p5, p6, p7, p8)
TO_TUPLE_TEMPLATE(10, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)
TO_TUPLE_TEMPLATE(11, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
TO_TUPLE_TEMPLATE(12, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)
TO_TUPLE_TEMPLATE(13, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)
TO_TUPLE_TEMPLATE(14, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)
TO_TUPLE_TEMPLATE(15, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)
TO_TUPLE_TEMPLATE(16, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)
TO_TUPLE_TEMPLATE(17, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)
TO_TUPLE_TEMPLATE(18, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)
TO_TUPLE_TEMPLATE(19, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)
TO_TUPLE_TEMPLATE(20, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)
TO_TUPLE_TEMPLATE(21, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)
TO_TUPLE_TEMPLATE(22, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21)
TO_TUPLE_TEMPLATE(23, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22)
TO_TUPLE_TEMPLATE(24, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23)
TO_TUPLE_TEMPLATE(25, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24)
TO_TUPLE_TEMPLATE(26, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25)
TO_TUPLE_TEMPLATE(27, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26)
TO_TUPLE_TEMPLATE(28, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27)
TO_TUPLE_TEMPLATE(29, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28)
TO_TUPLE_TEMPLATE(30, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29)
TO_TUPLE_TEMPLATE(31, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30)
TO_TUPLE_TEMPLATE(32, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31)
TO_TUPLE_TEMPLATE(33, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32)
TO_TUPLE_TEMPLATE(34, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33)
TO_TUPLE_TEMPLATE(35, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34)
TO_TUPLE_TEMPLATE(36, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35)
TO_TUPLE_TEMPLATE(37, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36)
TO_TUPLE_TEMPLATE(38, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37)
TO_TUPLE_TEMPLATE(39, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38)
TO_TUPLE_TEMPLATE(40, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39)
TO_TUPLE_TEMPLATE(41, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40)
TO_TUPLE_TEMPLATE(42, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41)
TO_TUPLE_TEMPLATE(43, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42)
TO_TUPLE_TEMPLATE(44, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43)
TO_TUPLE_TEMPLATE(45, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44)
TO_TUPLE_TEMPLATE(46, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45)
TO_TUPLE_TEMPLATE(47, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46)
TO_TUPLE_TEMPLATE(48, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47)
TO_TUPLE_TEMPLATE(49, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48)
TO_TUPLE_TEMPLATE(50, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49)
TO_TUPLE_TEMPLATE(51, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50)
TO_TUPLE_TEMPLATE(52, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51)
TO_TUPLE_TEMPLATE(53, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52)
TO_TUPLE_TEMPLATE(54, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53)
TO_TUPLE_TEMPLATE(55, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54)
TO_TUPLE_TEMPLATE(56, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55)
TO_TUPLE_TEMPLATE(57, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56)
TO_TUPLE_TEMPLATE(58, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57)
TO_TUPLE_TEMPLATE(59, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58)
TO_TUPLE_TEMPLATE(60, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59)
TO_TUPLE_TEMPLATE(61, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60)
TO_TUPLE_TEMPLATE(62, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61)
TO_TUPLE_TEMPLATE(63, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62)
TO_TUPLE_TEMPLATE(64, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63)
TO_TUPLE_TEMPLATE(65, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64)
TO_TUPLE_TEMPLATE(66, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65)
TO_TUPLE_TEMPLATE(67, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66)
TO_TUPLE_TEMPLATE(68, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67)
TO_TUPLE_TEMPLATE(69, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68)
TO_TUPLE_TEMPLATE(70, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69)
TO_TUPLE_TEMPLATE(71, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70)
TO_TUPLE_TEMPLATE(72, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71)
TO_TUPLE_TEMPLATE(73, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72)
TO_TUPLE_TEMPLATE(74, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73)
TO_TUPLE_TEMPLATE(75, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74)
TO_TUPLE_TEMPLATE(76, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75)
TO_TUPLE_TEMPLATE(77, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76)
TO_TUPLE_TEMPLATE(78, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77)
TO_TUPLE_TEMPLATE(79, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78)
TO_TUPLE_TEMPLATE(80, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79)
TO_TUPLE_TEMPLATE(81, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80)
TO_TUPLE_TEMPLATE(82, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81)
TO_TUPLE_TEMPLATE(83, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82)
TO_TUPLE_TEMPLATE(84, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83)
TO_TUPLE_TEMPLATE(85, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84)
TO_TUPLE_TEMPLATE(86, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85)
TO_TUPLE_TEMPLATE(87, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86)
TO_TUPLE_TEMPLATE(88, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87)
TO_TUPLE_TEMPLATE(89, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88)
TO_TUPLE_TEMPLATE(90, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89)
TO_TUPLE_TEMPLATE(91, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90)
TO_TUPLE_TEMPLATE(92, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91)
TO_TUPLE_TEMPLATE(93, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92)
TO_TUPLE_TEMPLATE(94, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93)
TO_TUPLE_TEMPLATE(95, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94)
TO_TUPLE_TEMPLATE(96, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95)
TO_TUPLE_TEMPLATE(97, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96)
TO_TUPLE_TEMPLATE(98, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97)
TO_TUPLE_TEMPLATE(99, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98)
TO_TUPLE_TEMPLATE(100, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27,
p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54,
p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81,
p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99)
#undef FIELD_RFL_EVAL0
#undef FIELD_RFL_EVAL1
#undef FIELD_RFL_EVAL2
#undef FIELD_RFL_EVAL3
#undef FIELD_RFL_EVAL4
#undef FIELD_RFL_EVAL
#undef FIELD_RFL_MAP_END
#undef FIELD_RFL_MAP_OUT
#undef FIELD_RFL_MAP_COMMA
#undef FIELD_RFL_MAP_GET_END2
#undef FIELD_RFL_MAP_GET_END1
#undef FIELD_RFL_MAP_GET_END
#undef FIELD_RFL_MAP_NEXT0
#undef FIELD_RFL_MAP_NEXT1
#undef FIELD_RFL_MAP_NEXT
#undef FIELD_RFL_MAP0
#undef FIELD_RFL_MAP1
#undef FIELD_RFL_MAP_LIST_NEXT1
#undef FIELD_RFL_MAP_LIST_NEXT
#undef FIELD_RFL_MAP_LIST0
#undef FIELD_RFL_MAP_LIST1
#undef FIELD_RFL_MAP
#undef FIELD_RFL_MAP_LIST
#undef FIELD_RFL_DECLTYPE
#undef FIELD_RFL_MOVE
#undef FIELD_RFL_TO_TUPLE_TEMPLATE
#pragma endregion TO_TUPLE_TEMPLATE_MACRO
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundefined-internal"
#pragma clang diagnostic ignored "-Wundefined-var-template"
#elif defined(__GNUC__)
#elif defined(_MSC_VER)
#else
#endif
template <typename T>
struct wrapper {
explicit constexpr wrapper(const T& v) : value(v) {}
T value;
static wrapper<T> fake; // NOLINT
};
template <typename T, size_t N> // NOLINT
consteval auto get_ptr() noexcept {
#if defined(__clang__)
return wrapper(stl::get<N>(to_ptr_tuple(wrapper<T>::fake.value)));
#else
return stl::get<N>(to_ptr_tuple(wrapper<T>::fake.value));
#endif
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif __GNUC__
#elif defined(_MSC_VER)
#else
#endif
template <auto Ptr>
using nontype_template_parameter_helper = void;
template <typename T> // clang-format off
concept field_namable = field_referenceable<T> && (field_count<T> > 0) && requires {
typename nontype_template_parameter_helper<get_ptr<T, 0>()>;
}; // clang-format on
template <typename T, auto Ptr>
consteval stl::string_view get_function_name() {
#if defined(__clang__) && defined(_WIN32)
// clang-cl returns function_name() as __FUNCTION__ instead of __PRETTY_FUNCTION__
return stl::string_view{__PRETTY_FUNCTION__};
#else
return stl::string_view{stl::source_location::current().function_name()};
#endif
}
template <typename T>
consteval stl::string_view get_function_name() {
#if defined(__clang__) && defined(_WIN32)
// clang-cl returns function_name() as __FUNCTION__ instead of __PRETTY_FUNCTION__
return stl::string_view{__PRETTY_FUNCTION__};
#else
return stl::string_view{stl::source_location::current().function_name()};
#endif
}
template <typename T, auto Ptr>
consteval stl::string_view get_field_name() {
struct field_name_detector {
void* dummy;
};
constexpr auto detector_name = get_function_name<field_name_detector, get_ptr<field_name_detector, 0>()>();
constexpr auto dummy_begin = detector_name.rfind(stl::string_view("dummy"));
constexpr auto suffix = detector_name.substr(dummy_begin + stl::string_view("dummy").size());
constexpr auto begin_sentinel = detector_name[dummy_begin - 1];
const auto field_name_raw = get_function_name<T, Ptr>();
const auto last = field_name_raw.rfind(suffix);
const auto begin = field_name_raw.rfind(begin_sentinel, last - 1) + 1;
assert(begin < field_name_raw.size());
assert(last <= field_name_raw.size());
assert(begin < last);
return field_name_raw.substr(begin, last - begin);
}
template <typename T>
using remove_rvalue_reference_t = stl::conditional_t<stl::is_rvalue_reference_v<T>, stl::remove_reference_t<T>, T>;
template <field_namable T, size_t N>
constexpr stl::string_view field_name = get_field_name<T, get_ptr<T, N>()>();
template <field_referenceable T, size_t N>
using field_type = remove_rvalue_reference_t<decltype(stl::get<N>(to_tuple(stl::declval<T&>())))>;
struct type_name_detector {};
template <typename T>
consteval stl::string_view get_type_name() {
#if defined(__GNUC__) || defined(__clang__)
constexpr auto detector_name = get_function_name<type_name_detector>();
constexpr auto dummy = stl::string_view("T = ");
constexpr auto dummy_begin = detector_name.find(dummy) + dummy.size();
constexpr auto dummy2 = stl::string_view("type_name_detector");
constexpr auto dummy_suffix_length = detector_name.size() - detector_name.find(dummy2) - dummy2.size();
constexpr auto type_name_raw = get_function_name<T>();
return type_name_raw.substr(dummy_begin, type_name_raw.size() - dummy_begin - dummy_suffix_length);
#else
constexpr auto detector_name = get_function_name<type_name_detector>();
constexpr auto dummy = stl::string_view("struct field_reflection::detail::type_name_detector");
constexpr auto dummy_begin = detector_name.find(dummy);
constexpr auto dummy_suffix_length = detector_name.size() - dummy_begin - dummy.size();
auto type_name_raw = get_function_name<T>();
auto type_name = type_name_raw.substr(dummy_begin, type_name_raw.size() - dummy_begin - dummy_suffix_length);
if (auto s = stl::string_view("struct "); type_name.starts_with(s)) {
type_name.remove_prefix(s.size());
}
if (auto s = stl::string_view("class "); type_name.starts_with(s)) {
type_name.remove_prefix(s.size());
}
return type_name;
#endif
}
template <class T>
constexpr stl::string_view type_name = get_type_name<T>();
template <size_t N, typename T, field_referenceable U = stl::remove_cvref_t<T>>
constexpr decltype(auto) get_field(T& t) noexcept {
return *stl::get<N>(to_ptr_tuple(t));
}
template <size_t N, typename T, field_referenceable U = stl::remove_cvref_t<T>>
requires stl::is_rvalue_reference_v<T&&>
constexpr auto get_field(T&& t) noexcept {
return stl::get<N>(to_tuple(stl::forward<T>(t)));
}
template <typename T, typename Func, size_t... Is, field_referenceable U = stl::remove_cvref_t<T>>
void for_each_field_impl(T&& t, Func&& func, stl::index_sequence<Is...>) {
if constexpr (requires { (func(get_field<Is>(t)), ...); }) {
(func(get_field<Is>(t)), ...);
} else if constexpr (requires { (func(field_name<U, Is>, get_field<Is>(t)), ...); }) {
(func(field_name<U, Is>, get_field<Is>(t)), ...);
} else {
static_assert([] { return false; }(), "invalid function object for call to for_each_field");
}
}
template <typename T1, typename T2, typename Func, size_t... Is, field_referenceable U = stl::remove_cvref_t<T1>>
void for_each_field_impl(T1&& t1, T2&& t2, Func&& func, stl::index_sequence<Is...>) {
if constexpr (requires { (func(get_field<Is>(t1), get_field<Is>(t2)), ...); }) {
(func(get_field<Is>(t1), get_field<Is>(t2)), ...);
} else if constexpr (requires { (func(field_name<U, Is>, get_field<Is>(t1), get_field<Is>(t2)), ...); }) {
(func(field_name<U, Is>, get_field<Is>(t1), get_field<Is>(t2)), ...);
} else {
static_assert([] { return false; }(), "invalid function object for call to for_each_field");
}
}
template <typename T, typename Func, size_t... Is, field_referenceable U = stl::remove_cvref_t<T>>
bool all_of_field_impl(T&& t, Func&& func, stl::index_sequence<Is...>) {
if constexpr (requires { (func(get_field<Is>(t)) && ...); }) {
return (func(get_field<Is>(t)) && ...);
} else if constexpr (requires { (func(field_name<U, Is>, get_field<Is>(t)) && ...); }) {
return (func(field_name<U, Is>, get_field<Is>(t)) && ...);
} else {
static_assert([] { return false; }(), "invalid function object for call to all_of_field");
}
}
template <typename T1, typename T2, typename Func, size_t... Is, field_referenceable U = stl::remove_cvref_t<T1>>
bool all_of_field_impl(T1&& t1, T2&& t2, Func&& func, stl::index_sequence<Is...>) {
if constexpr (requires { (func(get_field<Is>(t1), get_field<Is>(t2)) && ...); }) {
return (func(get_field<Is>(t1), get_field<Is>(t2)) && ...);
} else if constexpr (requires { (func(field_name<U, Is>, get_field<Is>(t1), get_field<Is>(t2)) && ...); }) {
return (func(field_name<U, Is>, get_field<Is>(t1), get_field<Is>(t2)) && ...);
} else {
static_assert([] { return false; }(), "invalid function object for call to all_of_field");
}
}
template <typename T, typename Func, size_t... Is, field_referenceable U = stl::remove_cvref_t<T>>
bool any_of_field_impl(T&& t, Func&& func, stl::index_sequence<Is...>) {
if constexpr (requires { (func(get_field<Is>(t)) || ...); }) {
return (func(get_field<Is>(t)) || ...);
} else if constexpr (requires { (func(field_name<U, Is>, get_field<Is>(t)) || ...); }) {
return (func(field_name<U, Is>, get_field<Is>(t)) || ...);
} else {
static_assert([] { return false; }(), "invalid function object for call to any_of_field");
}
}
template <typename T1, typename T2, typename Func, size_t... Is, field_referenceable U = stl::remove_cvref_t<T1>>
bool any_of_field_impl(T1&& t1, T2&& t2, Func&& func, stl::index_sequence<Is...>) {
if constexpr (requires { (func(get_field<Is>(t1), get_field<Is>(t2)) || ...); }) {
return (func(get_field<Is>(t1), get_field<Is>(t2)) || ...);
} else if constexpr (requires { (func(field_name<U, Is>, get_field<Is>(t1), get_field<Is>(t2)) || ...); }) {
return (func(field_name<U, Is>, get_field<Is>(t1), get_field<Is>(t2)) || ...);
} else {
static_assert([] { return false; }(), "invalid function object for call to any_of_field");
}
}
} // namespace detail
using detail::field_count;
using detail::field_countable;
using detail::field_namable;
using detail::field_name;
using detail::field_referenceable;
using detail::field_type;
using detail::get_field;
using detail::to_tuple;
using detail::type_name;
template <typename T1, typename T2, typename Func, field_referenceable U1 = stl::remove_cvref_t<T1>, field_referenceable U2 = stl::remove_cvref_t<T2>>
requires stl::is_same_v<U1, U2>
void for_each_field(T1&& t1, T2&& t2, Func&& func) {
detail::for_each_field_impl(stl::forward<T1>(t1), stl::forward<T2>(t2), stl::forward<Func>(func), stl::make_index_sequence<field_count<U1>>());
}
template <typename T, typename Func, field_referenceable U = stl::remove_cvref_t<T>>
void for_each_field(T&& t, Func&& func) {
detail::for_each_field_impl(stl::forward<T>(t), stl::forward<Func>(func), stl::make_index_sequence<field_count<U>>());
}
template <typename T1, typename T2, typename Func, field_referenceable U1 = stl::remove_cvref_t<T1>, field_referenceable U2 = stl::remove_cvref_t<T2>>
requires stl::is_same_v<U1, U2>
bool all_of_field(T1&& t1, T2&& t2, Func&& func) {
return detail::all_of_field_impl(stl::forward<T1>(t1), stl::forward<T2>(t2), stl::forward<Func>(func), stl::make_index_sequence<field_count<U1>>());
}
template <typename T, typename Func, field_referenceable U = stl::remove_cvref_t<T>>
bool all_of_field(T&& t, Func&& func) {
return detail::all_of_field_impl(stl::forward<T>(t), stl::forward<Func>(func), stl::make_index_sequence<field_count<U>>());
}
template <typename T1, typename T2, typename Func, field_referenceable U1 = stl::remove_cvref_t<T1>, field_referenceable U2 = stl::remove_cvref_t<T2>>
requires stl::is_same_v<U1, U2>
bool any_of_field(T1&& t1, T2&& t2, Func&& func) {
return detail::any_of_field_impl(stl::forward<T1>(t1), stl::forward<T2>(t2), stl::forward<Func>(func), stl::make_index_sequence<field_count<U1>>());
}
template <typename T, typename Func, field_referenceable U = stl::remove_cvref_t<T>>
bool any_of_field(T&& t, Func&& func) {
return detail::any_of_field_impl(stl::forward<T>(t), stl::forward<Func>(func), stl::make_index_sequence<field_count<U>>());
}
} // namespace field_reflection

15
src/internals.cpp Normal file
View File

@ -0,0 +1,15 @@
#include <stdlib.h>
#include <std.hpp>
namespace std {
void __glibcxx_assert_fail(char const* file, int line, char const* func, char const* info) {
println("{}:{}:{}: {}", file, line, func, info);
}
void terminate() {
exit(1);
}
} // namespace std
extern "C" void __cxa_begin_catch() {}

106
src/logger.cpp Normal file
View File

@ -0,0 +1,106 @@
#include "io/print.hpp"
#include <string.h>
#include <logger.hpp>
using namespace log;
#define C_RS "\x1b[0m"
#define C_BLACK "\x1b[30m"
#define C_RED "\x1b[31m"
#define C_GREEN "\x1b[32m"
#define C_YELLOW "\x1b[33m"
#define C_BLUE "\x1b[34m"
#define C_MAGENTA "\x1b[35m"
#define C_CYAN "\x1b[36m"
#define C_WHITE "\x1b[37m"
#define C_BOLD "\x1b[1m"
#define C_DIM "\x1b[2m"
#define C_ITALIC "\x1b[3m"
#define C_UL "\x1b[4m"
#define C_BLINK "\x1b[5m"
extern "C" char* getenv(const char* name);
Logger::Logger() {
char* val = getenv("CPLUS_LOG");
if (val != NULL) {
if (strcmp(val, "OFF") == 0) {
this->set_log_level(LOG_OFF);
} else if (strcmp(val, "ERROR") == 0) {
this->set_log_level(LOG_ERROR);
} else if (strcmp(val, "WARN") == 0) {
this->set_log_level(LOG_WARN);
} else if (strcmp(val, "INFO") == 0) {
this->set_log_level(LOG_INFO);
} else if (strcmp(val, "DEBUG") == 0) {
this->set_log_level(LOG_DEBUG);
}
}
val = getenv("CPLUS_LOG_COLOR");
// clang-format off
if (val != NULL) {
if (
strcmp(val, "false") == 0 ||
strcmp(val, "FALSE") == 0 ||
strcmp(val, "off") == 0 ||
strcmp(val, "OFF") == 0 ||
strcmp(val, "no") == 0 ||
strcmp(val, "NO") == 0
) {
this->load_default_prefixes();
} else {
this->load_default_prefixes_with_color();
}
} else {
this->load_default_prefixes_with_color();
}
}
void Logger::log(LogLevel level, const char* file, const int line, const char* func, const char* str) {
String s = String(str);
Logger::log(level, file, line, func, s);
}
void Logger::log(LogLevel level, const char* file, const int line, const char* func, String str) {
if (!this->should_display(level)) {
return;
}
println(this->get_prefix(level), file, line, func, str);
}
void Logger::set_log_level(LogLevel level) {
this->filter_level = level;
}
// Fucking c++ and its implicit member variable access, god forbid C++ code looks clean.
const char* Logger::get_prefix(LogLevel level) {
return this->prefixes[level];
}
void Logger::load_default_prefixes_with_color() {
// clang-format off
this->prefixes[LOG_ERROR] = C_UL "{}" C_RS ":" C_UL "{}" C_RS ":" C_CYAN " [" C_RS C_RED "ERROR" C_RS C_CYAN "] (" C_RS "{}" C_CYAN ")" C_RS ": {}";
this->prefixes[LOG_WARN] = C_UL "{}" C_RS ":" C_UL "{}" C_RS ":" C_CYAN " [" C_RS C_YELLOW "WARN" C_RS C_CYAN "] (" C_RS "{}" C_CYAN ")" C_RS ": {}";
this->prefixes[LOG_INFO] = C_UL "{}" C_RS ":" C_UL "{}" C_RS ":" C_CYAN " [" C_RS C_GREEN "INFO" C_RS C_CYAN "] (" C_RS "{}" C_CYAN ")" C_RS ": {}";
this->prefixes[LOG_DEBUG] = C_UL "{}" C_RS ":" C_UL "{}" C_RS ":" C_CYAN " [" C_RS C_MAGENTA "DEBUG" C_RS C_CYAN "] (" C_RS "{}" C_CYAN ")" C_RS ": {}";
// clang-format on
}
void Logger::load_default_prefixes() {
this->prefixes[LOG_ERROR] = "{}:{}: [ERROR] ({}): {}";
this->prefixes[LOG_WARN] = "{}:{}: [WARN] ({}): {}";
this->prefixes[LOG_INFO] = "{}:{}: [INFO] ({}): {}";
this->prefixes[LOG_DEBUG] = "{}:{}: [DEBUG] ({}): {}";
}
void Logger::load_custom_prefixes(const char* pfx[LOG_LEVEL_COUNT]) {
for (int i = 0; i < LOG_LEVEL_COUNT; i++) {
this->prefixes[i] = pfx[i];
}
}
bool Logger::should_display(LogLevel level) {
return this->filter_level >= level;
}

View File

@ -1,4 +1,4 @@
CC = clang
all: ../build/libc+ test compile_commands.json
@ -6,10 +6,10 @@ clean:
rm -rf test *.o compile_commands.json
test: test.o
cc -o $@ $^ -L../build -l:libc+.a -ggdb # -nostdlib++ -lsupc++
$(CC) -o $@ $^ -L../build -l:libc+.a -ggdb # -nostdlib++ -lsupc++
%.o: %.cpp
cc -c -o $@ $< -std=c++23 -I../src/include -ggdb # -nostdinc++
$(CC) -c -o $@ $< -std=c++23 -I../src/include -ggdb # -nostdinc++
../build/libc+:
$(MAKE) -C ../

BIN
test/test

Binary file not shown.

View File

@ -1,11 +1,95 @@
#include "io/print.hpp"
#include <std.hpp>
#include <format/obj_fmt_helper.hpp>
#include <sync/mutex.hpp>
#include <sync/spinlock.hpp>
#include <stddef.h>
#include <pthread.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
#include <logger.hpp>
struct Foo {
int bar = 1;
float baz = 2.0;
// IMPL: Format
String fmt_to_str() {
auto h = ObjFmtHelper("Foo");
h.add_field("bar", this->bar);
h.add_field("baz", this->baz);
return h.finish();
}
};
Vec<int> test_vec() {
Vec<int> v = Vec<int>();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
return v;
}
void test_fmt(Vec<int> v) {
Foo f = Foo();
println("Hello!!!! {}, {}, {}, {}", "meow", 420.0, 49, v);
println("> {}", f);
}
extern "C" void* test_mutex_thread(void* arg) {
Mutex<int>* m = (Mutex<int>*)arg;
auto val = m->lock();
println("mutex: changing {} to 69", *val);
*val = 69;
println("mutex: 5 second eep!! (eepy boyo)");
sleep(5);
return NULL;
}
void test_mutex() {
Mutex<int>* m = new Mutex<int>(0);
pthread_t thread;
println("mutex: Creating thread for mutex");
if (pthread_create(&thread, NULL, test_mutex_thread, (void*)m) != 0) {
println("Uh oh (mutex)");
}
pthread_join(thread, NULL);
auto val = m->lock();
println("mutex: Value was {}", *val);
}
extern "C" void* test_spinlock_thread(void* arg) {
SpinLock<int>* sl = (SpinLock<int>*)arg;
println("spinlock: changing {} to 5", *sl->lock());
*sl->lock() = 5;
println("spinlock: 5 second eep!! (eepy girlie)");
sleep(5);
return NULL;
}
void test_spinlock() {
SpinLock<int>* sl = new SpinLock<int>(0);
pthread_t thread;
println("spinlock: Creating thread for spinlock");
if (pthread_create(&thread, NULL, test_spinlock_thread, (void*)sl) != 0) {
println("Uh oh (spinlock)");
}
pthread_join(thread, NULL);
println("spinlock: Value was {}", *sl->lock());
}
/// https://github.com/yosh-matsuda/field-reflection
int main(int argc, char* argv[]) {
// Vec<int> v = test_vec();
// test_fmt(v);
// test_spinlock();
// test_mutex();
log::debug("hemlo!!");
log::info("hemlo!!");
log::warn("hemlo!!");
log::error("hemlo!!");
return 0;
}