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,
68 if (alarmCondition) [[unlikely]] {
69 qt_assert_x(loc.function_name(),
QUO_CSTR(msg), loc.file_name(), loc.line());
72 return alarmCondition;
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__) ? true : false, "Failing expression: " #__VA_ARGS__)
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));
114#if Quotient_VERSION_MAJOR == 0
&& Quotient_VERSION_MINOR < 10
124template <
typename KeyT,
typename ValT>
130#if Quotient_VERSION_MAJOR == 0
&& Quotient_VERSION_MINOR > 9
131[[
deprecated(
"Use operators from Qt::Literals (aka Quotient::Literals) instead")]]
133constexpr auto operator""_ls(
const char* s, std::size_t size)
135 return operator
""_L1(s, size);
138template <
typename ArrayT>
139class [[deprecated(
"Use std::ranges::subrange instead")]]
Range {
140 using iterator =
typename ArrayT::iterator;
141 using const_iterator =
typename ArrayT::const_iterator;
142 using size_type =
typename ArrayT::size_type;
145 constexpr Range(ArrayT& arr) : from(std::begin(arr)), to(std::end(arr)) {}
146 constexpr Range(iterator from, iterator to) : from(from), to(to) {}
148 constexpr size_type
size()
const
150 Q_ASSERT(std::distance(from, to) >= 0);
151 return size_type(std::distance(from, to));
153 constexpr bool empty()
const {
return from == to; }
154 constexpr const_iterator
begin()
const {
return from; }
155 constexpr const_iterator
end()
const {
return to; }
156 constexpr iterator
begin() {
return from; }
157 constexpr iterator
end() {
return to; }
165 template <
typename T>
166 concept Holds_NonConst_LValue_Ref =
167 std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference<T>>;
185 "Use the member function with the same name of the respective container")]]
asKeyValueRange {
217
218
219
220
249template <
typename ImplType,
typename TypeToDelete = ImplType>
250using ImplPtr = std::unique_ptr<ImplType,
void (*)(TypeToDelete*)>;
270template <
typename ImplType,
typename TypeToDelete = ImplType,
typename... ArgTs>
273 return ImplPtr<ImplType, TypeToDelete> {
274 new ImplType{std::forward<ArgTs>(args)...},
275 [](TypeToDelete* impl) {
delete impl; }
279template <
typename ImplType,
typename TypeToDelete = ImplType>
282 return ImplPtr<ImplType, TypeToDelete> { from, [](TypeToDelete* impl) {
287template <
typename ImplType,
typename TypeToDelete = ImplType>
290 return {
nullptr, [](TypeToDelete*) { } };
295 size_t (*destructor)(T*);
299 destructor(toDelete);
300 delete[]
reinterpret_cast<std::byte*>(toDelete);
322inline auto makeCStruct(T* (*constructor)(
void*), size_t (*sizeFn)(),
325 return CStructPtr<T>{ constructor(
new std::byte[sizeFn()]), { destructor } };
333template <
typename... FunctorTs>
335 using FunctorTs::operator()...;
338template <
typename... FunctorTs>
345
346
347
351
352
353
357
358
359
360
364
365
366
367
368
369
394 return dbg.verbosity(QDebug::MinimumVerbosity);
398#ifdef PROFILER_LOG_USECS
413 return std::invoke(manipFn, dbg);
419 dbg <<
static_cast<
double>(et.nsecsElapsed() / 1000) / 1000
436template <
typename FnT>
437inline auto lift(FnT&& fn,
auto&&... args)
439 if constexpr (std::is_void_v<std::invoke_result_t<FnT,
decltype(*args)...>>) {
440 if ((... &&
bool(args)))
441 std::invoke(std::forward<FnT>(fn), *args...);
443 return (... &&
bool(args))
444 ? std::optional(std::invoke(std::forward<FnT>(fn), *args...))
454template <
typename T1,
typename T2>
455 requires std::is_assignable_v<T1&,
const T2&>
456constexpr inline bool merge(T1& lhs,
const std::optional<T2>& rhs)
458 if (!rhs || lhs == *rhs)
470template <
typename StructT>
471constexpr inline size_t
mergeStruct(StructT& lhs,
const StructT& rhs,
const auto... fields)
473 return ((... +
static_cast<size_t>(merge(lhs.*fields, rhs.*fields))));
constexpr Range(iterator from, iterator to)
constexpr bool empty() const
constexpr const_iterator end() const
constexpr const_iterator begin() const
constexpr Range(ArrayT &arr)
constexpr iterator begin()
constexpr size_type size() const
An adaptor for Qt (hash-)maps to make them iterable in STL style.
QT_IGNORE_DEPRECATIONS(template< typename U > asKeyValueRange(U &) -> asKeyValueRange< U & >;template< typename U > asKeyValueRange(U &&) -> asKeyValueRange< U >;) template< typename InputIt
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.
bool alarmX(bool alarmCondition, const auto &msg, std::source_location loc=std::source_location::current())
Overloads(FunctorTs &&...) -> Overloads< FunctorTs... >
constexpr qint64 ProfilerMinNsecs
constexpr ImplPtr< ImplType, TypeToDelete > ZeroImpl()
QUOTIENT_API void linkifyUrls(QString &htmlEscapedText)
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.
constexpr auto operator""_ls(const char *s, std::size_t size)
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)
This is only to make UnorderedMap alias work until we get rid of it.
size_t operator()(const T &s) const Q_DECL_NOEXCEPT
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