22#if defined(__cplusplus) && __cplusplus >= 201703L
24# include <type_traits>
31#define ZTH_STRINGIFY_(x) #x
35#define ZTH_STRINGIFY(x) ZTH_STRINGIFY_(x)
45# define likely(expr) \
46 __builtin_expect(!!(expr) , 1)
48# define likely(expr) (expr)
60# define unlikely(expr) \
61 __builtin_expect(!!(expr) , 0)
63# define unlikely(expr) (expr)
70#define ZTH_GET_MACRO_ARGN( \
71 _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, NAME, ...) \
75# define FOREACH_0(WHAT)
76# define FOREACH_1(WHAT, X) WHAT(X)
77# define FOREACH_2(WHAT, X, ...) \
78 WHAT(X) FOREACH_1(WHAT, __VA_ARGS__)
79# define FOREACH_3(WHAT, X, ...) \
80 WHAT(X) FOREACH_2(WHAT, __VA_ARGS__)
81# define FOREACH_4(WHAT, X, ...) \
82 WHAT(X) FOREACH_3(WHAT, __VA_ARGS__)
83# define FOREACH_5(WHAT, X, ...) \
84 WHAT(X) FOREACH_4(WHAT, __VA_ARGS__)
85# define FOREACH_6(WHAT, X, ...) \
86 WHAT(X) FOREACH_5(WHAT, __VA_ARGS__)
87# define FOREACH_7(WHAT, X, ...) \
88 WHAT(X) FOREACH_6(WHAT, __VA_ARGS__)
89# define FOREACH_8(WHAT, X, ...) \
90 WHAT(X) FOREACH_7(WHAT, __VA_ARGS__)
91# define FOREACH_9(WHAT, X, ...) \
92 WHAT(X) FOREACH_8(WHAT, __VA_ARGS__)
93# define FOREACH_10(WHAT, X, ...) \
94 WHAT(X) FOREACH_9(WHAT, __VA_ARGS__)
95# define FOREACH_11(WHAT, X, ...) \
96 WHAT(X) FOREACH_10(WHAT, __VA_ARGS__)
97# define FOREACH_12(WHAT, X, ...) \
98 WHAT(X) FOREACH_11(WHAT, __VA_ARGS__)
99# define FOREACH_13(WHAT, X, ...) \
100 WHAT(X) FOREACH_12(WHAT, __VA_ARGS__)
101# define FOREACH_14(WHAT, X, ...) \
102 WHAT(X) FOREACH_13(WHAT, __VA_ARGS__)
103# define FOREACH_15(WHAT, X, ...) \
104 WHAT(X) FOREACH_14(WHAT, __VA_ARGS__)
105# define FOREACH_16(WHAT, X, ...) \
106 WHAT(X) FOREACH_15(WHAT, __VA_ARGS__)
112# define FOREACH(action, ...) \
113 ZTH_GET_MACRO_ARGN( \
114 0, ##__VA_ARGS__, FOREACH_16, FOREACH_15, FOREACH_14, FOREACH_13, FOREACH_12, \
115 FOREACH_11, FOREACH_10, FOREACH_9, FOREACH_8, FOREACH_7, FOREACH_6, FOREACH_5, \
116 FOREACH_4, FOREACH_3, FOREACH_2, FOREACH_1, FOREACH_0) \
117 (action, ##__VA_ARGS__)
122# define REVERSE_1(a) a
123# define REVERSE_2(a, ...) REVERSE_1(__VA_ARGS__), a
124# define REVERSE_3(a, ...) REVERSE_2(__VA_ARGS__), a
125# define REVERSE_4(a, ...) REVERSE_3(__VA_ARGS__), a
126# define REVERSE_5(a, ...) REVERSE_4(__VA_ARGS__), a
127# define REVERSE_6(a, ...) REVERSE_5(__VA_ARGS__), a
128# define REVERSE_7(a, ...) REVERSE_6(__VA_ARGS__), a
129# define REVERSE_8(a, ...) REVERSE_7(__VA_ARGS__), a
130# define REVERSE_9(a, ...) REVERSE_8(__VA_ARGS__), a
131# define REVERSE_10(a, ...) REVERSE_9(__VA_ARGS__), a
132# define REVERSE_11(a, ...) REVERSE_10(__VA_ARGS__), a
133# define REVERSE_12(a, ...) REVERSE_11(__VA_ARGS__), a
134# define REVERSE_13(a, ...) REVERSE_12(__VA_ARGS__), a
135# define REVERSE_14(a, ...) REVERSE_13(__VA_ARGS__), a
136# define REVERSE_15(a, ...) REVERSE_14(__VA_ARGS__), a
137# define REVERSE_16(a, ...) REVERSE_15(__VA_ARGS__), a
138# define REVERSE(...) \
139 ZTH_GET_MACRO_ARGN( \
140 0, ##__VA_ARGS__, REVERSE_16, REVERSE_15, REVERSE_14, REVERSE_13, REVERSE_12, \
141 REVERSE_11, REVERSE_10, REVERSE_9, REVERSE_8, REVERSE_7, REVERSE_6, REVERSE_5, \
142 REVERSE_4, REVERSE_3, REVERSE_2, REVERSE_1, REVERSE_0) \
149zth_logv(
char const* fmt, va_list arg);
160# if __cplusplus >= 201103L
163# include <inttypes.h>
166# ifdef ZTH_HAVE_PTHREAD
170# ifdef ZTH_OS_WINDOWS
173# include <sys/types.h>
182# define ZTH_DBG_PREFIX " > "
194# define zth_dbg(group, fmt, a...) \
196 if(::zth::Config::SupportDebugPrint && ::zth::Config::Print_##group > 0 \
197 && zth_config(EnableDebugPrint)) { \
198 if(::zth::Config::EnableColorLog) \
200 ::zth::Config::Print_##group, \
201 ZTH_DBG_PREFIX "zth::" ZTH_STRINGIFY(group) ": " fmt \
206 ZTH_DBG_PREFIX "zth::" ZTH_STRINGIFY(group) ": " fmt \
216# if !defined(NDEBUG) && !defined(CPPCHECK)
217# define zth_assert(expr) \
219 if(unlikely(::zth::Config::EnableAssert && !(expr))) \
220 ::zth::assert_handler( \
221 __FILE__, __LINE__, \
222 ::zth::Config::EnableFullAssert ? ZTH_STRINGIFY(expr) \
226# define zth_assert(...) \
232# ifndef ZTH_CLASS_NOCOPY
233# if __cplusplus >= 201103L
234# define ZTH_CLASS_NOCOPY(Class) \
236 Class(Class const&) = delete; \
240 Class& operator=(Class const&) noexcept = delete; \
241 Class& operator=(Class&&) noexcept = \
246# define ZTH_CLASS_NOCOPY(Class) \
248 Class(Class const&); \
249 Class& operator=(Class const&);
257EXTERN_C ZTH_EXPORT __attribute__((noreturn))
void
261ZTH_EXPORT
ZTH_INLINE __attribute__((noreturn))
void
268ZTH_EXPORT __attribute__((noreturn))
void
275ZTH_EXPORT __attribute__((returns_nonnull))
char const* banner() noexcept;
277ZTH_EXPORT __attribute__((format(
ZTH_ATTR_PRINTF, 1, 2), noreturn))
void
278abort(
char const* fmt, ...) noexcept;
280ZTH_EXPORT __attribute__((format(
ZTH_ATTR_PRINTF, 1, 0), noreturn))
void
281abortv(
char const* fmt, va_list args) noexcept;
283ZTH_EXPORT
bool log_supports_ansi_colors() noexcept;
286log_colorv(
int color,
char const* fmt, va_list args);
294log_color(
int color,
char const* fmt, ...)
298 log_colorv(color, fmt, args);
309logv(
char const* fmt, va_list arg)
332typedef std::basic_string<char, std::char_traits<char>, Config::Allocator<char>::type>
string;
384# if __cplusplus >= 201103L
391 , m_str(
std::move(s))
397 m_str = std::move(s);
404 return std::move(
local());
413 char const*
c_str()
const
415 return m_cstr ? m_cstr : m_str.c_str();
418 operator string const&()
const
423 char const&
at(
size_t pos)
const
425 return str().at(pos);
430 return m_cstr ? m_cstr[pos] :
str()[pos];
438 char const*
data()
const
443 bool empty() const noexcept
445 return m_cstr ? *m_cstr == 0 : m_str.empty();
448 size_t size() const noexcept
453 size_t length() const noexcept
455 return str().length();
458 void clear() noexcept
466 return m_cstr !=
nullptr;
471 return m_cstr ==
nullptr;
475 string const&
local()
const
491 mutable char const* m_cstr;
492 mutable string m_str;
500__attribute__((format(
ZTH_ATTR_PRINTF, 1, 2))) inline
string format(
char const* fmt, ...)
504 string res =
formatv(fmt, args);
514inline cow_string
str(T value)
516 return cow_string(value);
522 return format(
"%c", value);
526inline cow_string str<signed char>(
signed char value)
528 if(Config::UseLimitedFormatSpecifiers)
529 return format(
"%d", (
int)value);
531 return format(
"%hhd", value);
535inline cow_string str<unsigned char>(
unsigned char value)
537 if(Config::UseLimitedFormatSpecifiers)
538 return format(
"%u", (
unsigned int)value);
540 return format(
"%hhu", value);
546 if(Config::UseLimitedFormatSpecifiers)
547 return format(
"%d", (
int)value);
549 return format(
"%hd", value);
553inline cow_string str<unsigned short>(
unsigned short value)
555 if(Config::UseLimitedFormatSpecifiers)
556 return format(
"%u", (
unsigned int)value);
558 return format(
"%hu", value);
564 return format(
"%d", value);
568inline cow_string str<unsigned int>(
unsigned int value)
570 return format(
"%u", value);
574ZTH_EXPORT
ZTH_INLINE cow_string strull(
unsigned long long value)
577 if(value > (
unsigned long long)std::numeric_limits<int>::max())
579 "0x%x%08x", (
unsigned)(value >> 32U),
580 (
unsigned)(value & 0xFFFFFFFFU));
582 return format(
"%d", (
int)value);
584 return format(
"%llu", value);
592 if(Config::UseLimitedFormatSpecifiers) {
593 if(
sizeof(
long) ==
sizeof(
int)
594 || (value <= std::numeric_limits<int>::max()
595 && value >= std::numeric_limits<int>::min()))
596 return format(
"%d", (
int)value);
598 return impl::strull((
unsigned long long)value);
600 return format(
"%ld", value);
605inline cow_string str<unsigned long>(
unsigned long value)
607 if(Config::UseLimitedFormatSpecifiers) {
608 if(
sizeof(
unsigned long) ==
sizeof(
unsigned int)
609 || value <= std::numeric_limits<unsigned int>::max())
610 return format(
"%u", (
unsigned int)value);
612 return impl::strull((
unsigned long long)value);
614 return format(
"%lu", value);
619inline cow_string str<long long>(
long long value)
621 if(Config::UseLimitedFormatSpecifiers) {
622 if(value > std::numeric_limits<int>::max()
623 || value < std::numeric_limits<int>::min())
624 return impl::strull((
unsigned long long)value);
626 return format(
"%d", (
int)value);
628 return format(
"%lld", value);
633inline cow_string str<unsigned long long>(
unsigned long long value)
635 return impl::strull(value);
639ZTH_EXPORT
ZTH_INLINE cow_string strf(
float value)
642 if(!(value < (
float)std::numeric_limits<int>::max()
643 && value > (
float)-std::numeric_limits<int>::max()))
648 if(std::abs(fi - value) < 0.0005F)
651 int f = std::min(std::abs((
int)((value - fi) * 1000.0F + 0.5F)), 999);
652 return format(
"%d.%03d", i, f);
654 return format(
"%g", (
double)value);
662 if(Config::UseLimitedFormatSpecifiers)
663 return impl::strf(value);
665 return format(
"%g", (
double)value);
671 if(Config::UseLimitedFormatSpecifiers)
672 return impl::strf((
float)value);
674 return format(
"%g", value);
678inline cow_string str<long double>(
long double value)
680 if(Config::UseLimitedFormatSpecifiers)
681 return impl::strf((
float)value);
683 return format(
"%Lg", value);
689 return format(
"%p", value);
692# if __cplusplus >= 201103L
694inline cow_string str<string&&>(
string&& value)
703inline string err(
int e)
705# ifdef ZTH_OS_BAREMETAL
707 return format(
"error %d", e);
708# elif defined(ZTH_HAVE_LIBZMQ)
709 return format(
"%s (error %d)", zmq_strerror(e), e);
710# elif ZTH_THREADS && !defined(ZTH_OS_WINDOWS)
712# if !defined(ZTH_OS_LINUX) || (_POSIX_C_SOURCE >= 200112L) && !defined(_GNU_SOURCE)
714 return format(
"%s (error %d)", strerror_r(e, buf,
sizeof(buf)) ?
"Unknown error" : buf, e);
717 return format(
"%s (error %d)", strerror_r(e, buf,
sizeof(buf)), e);
721 return format(
"%s (error %d)", strerror(e), e);
727 virtual char const*
id_str() const noexcept = 0;
739template <
bool Named = Config::NamedObjects>
752# if __cplusplus >= 201103L
754 : m_name(
std::move(name))
758 virtual uint64_t id_() const noexcept = 0;
763 string const& name() const noexcept
768 void setName(
string const& name)
777 changedName(this->name());
780# if __cplusplus >= 201103L
783 m_name = std::move(name);
785 changedName(this->name());
789 virtual char const* id_str() const noexcept
override
794# ifdef ZTH_OS_BAREMETAL
797 format(
"%s #%u", name().empty() ?
"Object" : name().c_str(),
798 (
unsigned int)id_());
801 name().empty() ?
"Object" : name().c_str(),
802# ifdef ZTH_OS_WINDOWS
803 (
unsigned int)_getpid(),
805 (
unsigned int)getpid(),
818 return m_id_str.c_str();
822 virtual void changedName(
string const&
UNUSED_PAR(name)) {}
826 string mutable m_id_str;
836 virtual uint64_t id_() const noexcept = 0;
840 string const& name() const noexcept
842 static string const null;
848 changedName(this->name());
853 changedName(this->name());
856# if __cplusplus >= 201103L
859 changedName(this->name());
863 virtual char const* id_str() const noexcept
override
865 return name().c_str();
869 virtual void changedName(
string const&
UNUSED_PAR(name)) {}
876template <
typename T,
bool ThreadSafe = Config::EnableThreads>
877class UniqueID :
public NamedUniqueID<> {
878# if __cplusplus < 201103L
884# if __cplusplus >= 201103L
891 *
this = std::move(u);
898 base::operator=(std::move(u));
903 static uint64_t getID() noexcept
906# if GCC_VERSION < 40802L
907 __sync_add_and_fetch(&m_nextId, 1)
909 __atomic_add_fetch(&m_nextId, 1, __ATOMIC_RELAXED)
914 explicit UniqueID(
string const& name)
919# if __cplusplus >= 201103L
926 explicit UniqueID(
char const* name =
nullptr)
933 void const* normptr() const noexcept
938 __attribute__((pure)) uint64_t id() const noexcept
944 virtual uint64_t id_() const noexcept final
953 static uint64_t m_nextId;
956template <
typename T,
bool ThreadSafe>
973 zth_assert(m_count < std::numeric_limits<size_t>::max());
977 bool unused() noexcept
987 size_t refs() const noexcept
993 virtual void cleanup() noexcept
1002template <
typename T,
typename WhenTIsVo
id>
1007template <
typename WhenTIsVo
id>
1009 typedef WhenTIsVoid
type;
1012# if __cplusplus >= 201103L
1016template <
size_t N,
size_t... S>
1017struct SequenceGenerator : SequenceGenerator<N - 1, N - 1, S...> {};
1019template <
size_t... S>
1020struct SequenceGenerator<0, S...> {
1021 typedef Sequence<S...> type;
1029template <
typename T>
1040 constexpr operator pointer_type*()
const noexcept
1045 constexpr operator bool() const noexcept
1050 constexpr14 pointer_type* operator->() const noexcept
1056 constexpr14 pointer_type& operator*() const noexcept
1075template <
typename T>
1104template <
typename T>
1130 if(m_instance ==
static_cast<singleton_type*
>(
this))
1131 m_instance =
nullptr;
1139 __attribute__((pure))
constexpr14 static typename safe_ptr<singleton_type>::type
1147 static singleton_type* m_instance;
1150template <
typename T>
1162template <
typename T>
1163class ThreadLocalSingleton {
1189 if(
ZTH_TLS_GET(m_instance) ==
static_cast<singleton_type*
>(
this))
1198 __attribute__((pure))
static typename safe_ptr<singleton_type>::type instance() noexcept
1208template <
typename T>
1229template <typename T, int8_t Prealloc = 1, typename Allocator = typename Config::Allocator<T>::type>
1234 typedef std::vector<value_type, allocator_type>
vector_type;
1237 prealloc_request = Prealloc > 0 ? Prealloc : 0,
1238 prealloc_request_size = prealloc_request *
sizeof(
value_type),
1241 prealloc_request_size > vector_size ? prealloc_request_size : vector_size,
1252 static_assert(prealloc < std::numeric_limits<uint8_t>::max(),
"");
1263 vector().~vector_type();
1269 value_type& operator[](
size_t index)
noexcept
1272 return data()[index];
1278 value_type
const& operator[](
size_t index)
const noexcept
1281 return data()[index];
1289 value_type& front() noexcept
1299 value_type
const& front() const noexcept
1309 value_type& back() noexcept
1312 return (*
this)[size() - 1U];
1320 value_type
const& back() const noexcept
1323 return (*
this)[size() - 1U];
1329 value_type* data() noexcept
1331 return is_small() ? array() : vector().data();
1337 value_type
const* data() const noexcept
1339 return is_small() ? array() : vector().data();
1345 bool empty() const noexcept
1347 return is_small() ? m_size == 0 : vector().empty();
1353 size_t size() const noexcept
1355 return is_small() ? m_size : vector().size();
1363 void reserve(
size_t new_cap)
1365 if(is_small() && new_cap <= prealloc)
1369 make_vector(new_cap);
1371 vector().reserve(new_cap);
1378 size_t capacity() const noexcept
1380 return is_small() ? (size_t)prealloc : vector().capacity();
1388 void clear() noexcept
1399 void clear_and_release() noexcept
1413 void push_back(value_type
const& v)
1415 reserve(size() + 1U);
1417 if(m_size < prealloc) {
1418 new(&array()[m_size]) value_type(v);
1421 vector().push_back(v);
1424# if __cplusplus >= 201103L
1429 template <
class... Args>
1430 void emplace_back(Args&&... args)
1432 reserve(size() + 1U);
1434 if(m_size < prealloc) {
1435 new(&array()[m_size]) value_type(std::forward<Args>(args)...);
1438 vector().emplace_back(std::forward<Args>(args)...);
1447 void pop_back() noexcept
1451 array()[--m_size].~value_type();
1453 vector().pop_back();
1461 void resize(
size_t count, value_type
const& x = value_type())
1464 while(count < m_size)
1465 array()[--m_size].~value_type();
1467 if(count <= prealloc) {
1468 while(count > m_size) {
1469 new(&array()[m_size]) value_type(x);
1474 vector().resize(count, x);
1477 vector().resize(count, x);
1484 bool is_small() const noexcept
1486 return m_size <= prealloc;
1492 value_type* array() noexcept
1495 return reinterpret_cast<value_type*
>(m_buffer);
1501 value_type
const* array() const noexcept
1504 return reinterpret_cast<value_type const*
>(m_buffer);
1510 vector_type& vector() noexcept
1513 void* buffer = m_buffer;
1514 return *
reinterpret_cast<vector_type*
>(buffer);
1520 vector_type
const& vector() const noexcept
1523 void const* buffer = m_buffer;
1524 return *
reinterpret_cast<vector_type const*
>(buffer);
1530 void make_vector(
size_t new_cap)
1536 v.reserve(std::max(new_cap, (
size_t)m_size));
1538 for(
size_t i = 0; i < m_size; i++) {
1539# if __cplusplus >= 201103L
1540 v.emplace_back(std::move(array()[i]));
1542 v.push_back(array()[i]);
1544 array()[i].~value_type();
1547 m_size = prealloc + 1U;
1548 new(m_buffer) vector_type;
1557 alignas(vector_type)
alignas(value_type)
char m_buffer[buffer_size];
1569template <
size_t size>
1574 x >= 0x100000000ULL ? 8U
1575 : x >= 0x10000U ? 4U
1578struct smallest_uint {
1579 typedef uint64_t
type;
1582template <u
int64_t x>
1584 typedef uint8_t
type;
1587template <u
int64_t x>
1589 typedef uint16_t
type;
1592template <u
int64_t x>
1594 typedef uint32_t
type;
1598# if __cplusplus >= 201703L
1601template <
class T,
class... TArgs>
1604template <
class,
class...>
1607template <
class T,
class... TArgs>
1613 constexpr operator T();
1620 using type = std::decay_t<T>;
1626 auto&& [p1, p2, p3, p4] = std::forward<T>(
object);
1627 return std::make_tuple(p1, p2, p3, p4);
1628 }
else if constexpr(
1631 auto&& [p1, p2, p3] = std::forward<T>(
object);
1632 return std::make_tuple(p1, p2, p3);
1634 auto&& [p1, p2] = std::forward<T>(
object);
1635 return std::make_tuple(p1, p2);
1637 auto&& [p1] = std::forward<T>(
object);
1638 return std::make_tuple(p1);
1640 return std::make_tuple();
1644# define ZTH_STRUCTURED_BINDING_FORWARDING(Class) \
1645 template <typename T> \
1646 struct std::tuple_size<Class<T>> : std::tuple_size<T> {}; \
1648 template <size_t N, typename T> \
1649 struct std::tuple_element<N, Class<T>> : std::tuple_element<N, T> {}; \
1651 template <size_t N, typename T> \
1652 decltype(auto) get(Class<T>& f) noexcept \
1654 auto& x = to_tuple(*f); \
1657# define ZTH_STRUCTURED_BINDING_FORWARDING_NS(Class) \
1659 ZTH_STRUCTURED_BINDING_FORWARDING(zth::Class) \
1662# define ZTH_STRUCTURED_BINDING_FORWARDING(Class)
1663# define ZTH_STRUCTURED_BINDING_FORWARDING_NS(Class)
1682ZTH_EXPORT __attribute__((returns_nonnull))
char const*
zth_banner();
1693EXTERN_C ZTH_EXPORT __attribute__((noreturn))
void zth_terminate();
1705 va_start(args, fmt);
1740 va_start(args, fmt);
1748#if !defined(__clang_analyzer__) && GCC_VERSION >= 110000L
1752# define ZTH_ERR_ATTR __attribute__((malloc(free), warn_unused_result))
1754# define ZTH_ERR_ATTR __attribute__((malloc, warn_unused_result))
1769EXTERN_C ZTH_EXPORT __attribute__((warn_unused_result))
ZTH_INLINE char*
zth_err(
int e)
1773 char* p = (
char*)malloc(s.size() + 1);
1776 memcpy(p, s.c_str(), s.size() + 1);
1784#ifdef ZTH_OS_BAREMETAL
1787EXTERN_C __attribute__((
format(gnu_printf, 2, 0))) int asprintf(
char** strp, const
char* fmt, ...);
1788EXTERN_C __attribute__((format(gnu_printf, 2, 0)))
int
1789vasprintf(
char** strp, const
char* fmt, va_list ap);
T singleton_type
Alias of the T template parameter.
Singleton pattern, but only per-thread.
T singleton_type
Alias of the T template parameter.
virtual char const * id_str() const noexcept=0
friend cow_string str(UniqueIDBase const &)
Keeps track of a process-wide unique ID within the type T.
char operator[](size_t pos) const
bool isConst() const noexcept
string const & local() const
char const & at(size_t pos) const
char const * c_str() const
size_t length() const noexcept
cow_string & operator=(cow_string const &s)
size_t size() const noexcept
char const * data() const
bool empty() const noexcept
bool isLocal() const noexcept
Wrapper for a pointer, which checks validity of the pointer upon dereference.
A simple std::vector, which can contain Prealloc without heap allocation.
std::vector< value_type, allocator_type > vector_type
void zth_log(char const *fmt,...)
Logs a given printf()-like formatted string.
void zth_abort(char const *fmt,...)
Aborts the process after printing the given printf() formatted message.
char * zth_err(int e)
Return a string like strerror() does, but as a zth::string.
void zth_log_color(int color, char const *fmt,...)
Logs a given printf()-like formatted string using an ANSI color code.
void zth_logv(char const *fmt, va_list arg)
Prints the given printf()-like formatted string to stdout.
void zth_log_colorv(int color, char const *fmt, va_list args)
Logs a given printf()-like formatted string using an ANSI color code.
char const * zth_banner()
Returns a banner line with version and configuration information.
void log_colorv(int color, char const *fmt, va_list args)
Logs a given printf()-like formatted string using an ANSI color code.
std::basic_string< char, std::char_traits< char >, Config::Allocator< char >::type > string
std::string type using Config::Allocator::type.
char const * banner() noexcept
Returns a banner line with version and configuration information.
void logv(char const *fmt, va_list arg)
Logs a given printf()-like formatted string.
#define ZTH_TLS_DEFINE(type, var, init)
#define ZTH_TLS_MEMBER(type, var)
#define ZTH_TLS_SET(var, value)
decltype(test_is_braces_constructible< T, TArgs... >(0)) is_braces_constructible
decltype(void(T{std::declval< TArgs >()...}), std::true_type{}) test_is_braces_constructible(int)
auto to_tuple(T &&object) noexcept
cow_string str(T value)
Returns an zth::string representation of the given value.
string formatv(char const *fmt, va_list args)
Format like vsprintf(), but save the result in an zth::string.
string err(int e)
Return a string like strerror() does, but as a zth::string.
void assert_handler(char const *file, int line, char const *expr)
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
static bool const UseLimitedFormatSpecifiers
Use limited formatting specifiers.
Change the name of a fiber returned by zth_async.
#define zth_assert(expr)
assert(), but better integrated in Zth.
void zth_assert_handler(char const *file, int line, char const *expr)
#define ZTH_CLASS_NOCOPY(Class)
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
void zth_terminate()
Terminate immediately.