9#include <QtCore/QDebug>
10#include <QtCore/QElapsedTimer>
11#include <QtCore/QFuture>
12#include <QtCore/QHashFunctions>
13#include <QtCore/QLatin1String>
14#include <QtCore/QScopedPointer>
19#include <source_location>
20#include <unordered_map>
22#define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended)
23 Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended
39#define SLICE(Object, ToType) ToType{static_cast<const ToType&>(Object)}
45 constexpr inline auto toUtf8(S&& s)
47 if constexpr (std::convertible_to<S, std::string_view>)
48 return std::string_view(std::forward<S>(s));
49 else if constexpr (std::convertible_to<S, QByteArray>)
50 return QByteArray(std::forward<S>(s));
52 return QString(std::forward<S>(s)).toUtf8();
63#define QUO_CSTR(StringConvertible_) std::data(::Quotient::_impl::toUtf8(StringConvertible_))
65inline bool alarmX(
bool alarmCondition,
const auto& msg,
bool invertReturnValue =
false,
68 if (alarmCondition) [[unlikely]] {
69 qt_assert_x(loc.function_name(),
QUO_CSTR(msg), loc.file_name(), loc.line());
72 return alarmCondition != invertReturnValue;
85#define QUO_ALARM_X(...) ::Quotient::alarmX(__VA_ARGS__)
87#define QUO_ALARM(...) ::Quotient::alarmX((__VA_ARGS__) ? true : false, "Alarm: " #__VA_ARGS__)
91 ::Quotient::alarmX((__VA_ARGS__) ? false : true, "Failing expression: " #__VA_ARGS__, true)
96#if QT_VERSION >= QT_VERSION_CHECK(6
, 6
, 0
)
97 return QtFuture::makeReadyVoidFuture();
99 return QtFuture::makeReadyFuture<
void>();
107#if QT_VERSION >= QT_VERSION_CHECK(6
, 6
, 0
)
108 return QtFuture::makeReadyValueFuture(std::forward<T>(value));
110 return QtFuture::makeReadyFuture(std::forward<T>(value));
117
118
119
120
121template <
typename InputIt,
typename ForwardIt>
122inline std::pair<InputIt, ForwardIt>
findFirstOf(InputIt first, InputIt last,
124 ForwardIt sLast,
auto pred)
126 for (; first != last; ++first)
127 for (
auto it = sFirst; it != sLast; ++it)
128 if (pred(*first, *it))
129 return { first, it };
131 return { last, sLast };
149template <
typename ImplType,
typename TypeToDelete = ImplType>
150using ImplPtr = std::unique_ptr<ImplType,
void (*)(TypeToDelete*)>;
170template <
typename ImplType,
typename TypeToDelete = ImplType,
typename... ArgTs>
173 return ImplPtr<ImplType, TypeToDelete> {
174 new ImplType{std::forward<ArgTs>(args)...},
175 [](TypeToDelete* impl) {
delete impl; }
179template <
typename ImplType,
typename TypeToDelete = ImplType>
182 return ImplPtr<ImplType, TypeToDelete> { from, [](TypeToDelete* impl) {
187template <
typename ImplType,
typename TypeToDelete = ImplType>
190 return {
nullptr, [](TypeToDelete*) { } };
195 size_t (*destructor)(T*);
199 destructor(toDelete);
200 delete[]
reinterpret_cast<std::byte*>(toDelete);
222inline auto makeCStruct(T* (*constructor)(
void*), size_t (*sizeFn)(),
225 return CStructPtr<T>{ constructor(
new std::byte[sizeFn()]), { destructor } };
233template <
typename... FunctorTs>
235 using FunctorTs::operator()...;
238template <
typename... FunctorTs>
245
246
247
251
252
253
257
258
259
260
264
265
266
267
268
269
294 return dbg.verbosity(QDebug::MinimumVerbosity);
298#ifdef PROFILER_LOG_USECS
313 return std::invoke(manipFn, dbg);
319 dbg <<
static_cast<
double>(et.nsecsElapsed() / 1000) / 1000
336template <
typename FnT>
337inline auto lift(FnT&& fn,
auto&&... args)
339 if constexpr (std::is_void_v<std::invoke_result_t<FnT,
decltype(*args)...>>) {
340 if ((... &&
bool(args)))
341 std::invoke(std::forward<FnT>(fn), *args...);
343 return (... &&
bool(args))
344 ? std::optional(std::invoke(std::forward<FnT>(fn), *args...))
354template <
typename T1,
typename T2>
355 requires std::is_assignable_v<T1&,
const T2&>
356constexpr inline bool merge(T1& lhs,
const std::optional<T2>& rhs)
358 if (!rhs || lhs == *rhs)
370template <
typename StructT>
371constexpr inline size_t
mergeStruct(StructT& lhs,
const StructT& rhs,
const auto... fields)
373 return ((... +
static_cast<size_t>(merge(lhs.*fields, rhs.*fields))));
QUOTIENT_API bool isGuestUserId(const UserId &uId)
auto lift(FnT &&fn, auto &&... args)
Lift an operation into dereferenceable types (std::optional or pointers)
auto makeReadyValueFuture(T &&value)
A substitute for QtFuture::makeReadyValueFuture() for compatibility with Qt pre-6....
QUOTIENT_API int patchVersion()
QUOTIENT_API int minorVersion()
QDebug formatJson(QDebug dbg)
QDebug manipulator to setup the stream for JSON output.
std::pair< InputIt, ForwardIt > findFirstOf(InputIt first, InputIt last, ForwardIt sFirst, ForwardIt sLast, auto pred)
Overloads(FunctorTs &&...) -> Overloads< FunctorTs... >
constexpr qint64 ProfilerMinNsecs
constexpr ImplPtr< ImplType, TypeToDelete > ZeroImpl()
QUOTIENT_API void linkifyUrls(QString &htmlEscapedText)
bool alarmX(bool alarmCondition, const auto &msg, bool invertReturnValue=false, std::source_location loc=std::source_location::current())
constexpr bool merge(T1 &lhs, const std::optional< T2 > &rhs)
Merge the value from an optional.
constexpr size_t mergeStruct(StructT &lhs, const StructT &rhs, const auto... fields)
Merge structure-like types.
ImplPtr< ImplType, TypeToDelete > makeImpl(ArgTs &&... args)
make_unique for ImplPtr
QDebug terse(QDebug dbg)
Suppress full qualification of enums/QFlags when logging.
auto makeReadyVoidFuture()
A substitute for QtFuture::makeReadyVoidFuture() for compatibility with Qt pre-6.6.
auto makeCStruct(T *(*constructor)(void *), size_t(*sizeFn)(), auto destructor)
Create a C structure with pre-programmed deletion logic.
QUOTIENT_API int majorVersion()
ImplPtr< ImplType, TypeToDelete > acquireImpl(ImplType *from)
void operator()(T *toDelete)
Multiplex several functors in one.
QDebug operator<<(QDebug dbg, std::invocable< QDebug > auto manipFn)
A helper operator for QDebug manipulators, e.g. formatJson.
#define QUO_CSTR(StringConvertible_)
q(Utf8)Printable that can handle more than just QStrings