diff --git a/Telegram/SourceFiles/base/algorithm.h b/Telegram/SourceFiles/base/algorithm.h deleted file mode 100644 index fbf53e94c..000000000 --- a/Telegram/SourceFiles/base/algorithm.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -inline Type take(Type &value) { - return std::exchange(value, Type {}); -} - -template -inline Type duplicate(const Type &value) { - return value; -} - -template -inline constexpr size_t array_size(const Type(&)[Size]) { - return Size; -} - -template -inline bool contains(const Container &container, const T &value) { - const auto end = std::end(container); - return std::find(std::begin(container), end, value) != end; -} - -template -inline constexpr D up_cast(T object) { - using DV = std::decay_t; - using TV = std::decay_t; - if constexpr (std::is_base_of_v) { - return object; - } else { - return nullptr; - } -} - -// We need a custom comparator for set>::find to work with pointers. -// thanks to http://stackoverflow.com/questions/18939882/raw-pointer-lookup-for-sets-of-unique-ptrs -template -struct pointer_comparator { - using is_transparent = std::true_type; - - // helper does some magic in order to reduce the number of - // pairs of types we need to know how to compare: it turns - // everything into a pointer, and then uses `std::less` - // to do the comparison: - struct helper { - const T *ptr = nullptr; - helper() = default; - helper(const helper &other) = default; - helper(const T *p) : ptr(p) { - } - template - helper(const std::shared_ptr &other) : ptr(other.get()) { - } - template - helper(const std::unique_ptr &other) : ptr(other.get()) { - } - bool operator<(helper other) const { - return std::less()(ptr, other.ptr); - } - }; - - // without helper, we'd need 2^n different overloads, where - // n is the number of types we want to support (so, 8 with - // raw pointers, unique pointers, and shared pointers). That - // seems silly. - // && helps enforce rvalue use only - bool operator()(const helper &&lhs, const helper &&rhs) const { - return lhs < rhs; - } - -}; - -inline QString FromUtf8Safe(const char *string, int size = -1) { - if (!string || !size) { - return QString(); - } else if (size < 0) { - size = strlen(string); - } - const auto result = QString::fromUtf8(string, size); - const auto back = result.toUtf8(); - return (back.size() != size || memcmp(back.constData(), string, size)) - ? QString::fromLocal8Bit(string, size) - : result; -} - -inline QString FromUtf8Safe(const QByteArray &string) { - return FromUtf8Safe(string.constData(), string.size()); -} - -} // namespace base - -template -inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } - -template -inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; } - -template -QLatin1String qstr(const char(&string)[Size]) { - return QLatin1String(string, Size - 1); -} diff --git a/Telegram/SourceFiles/base/algorithm_tests.cpp b/Telegram/SourceFiles/base/algorithm_tests.cpp deleted file mode 100644 index 9e3df829f..000000000 --- a/Telegram/SourceFiles/base/algorithm_tests.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/index_based_iterator.h" - -TEST_CASE("index_based_iterator tests", "[base::algorithm]") { - auto v = std::vector(); - - v.insert(v.end(), { 1, 2, 3, 4, 5, 4, 3, 2, 1 }); - auto push_back_safe_remove_if = [](auto &v, auto predicate) { - auto begin = base::index_based_begin(v); - auto end = base::index_based_end(v); - auto from = std::remove_if(begin, end, predicate); - if (from != end) { - auto newEnd = base::index_based_end(v); - if (newEnd != end) { - REQUIRE(newEnd > end); - while (end != newEnd) { - *from++ = *end++; - } - } - v.erase(from.base(), newEnd.base()); - } - }; - SECTION("allows to push_back from predicate") { - push_back_safe_remove_if(v, [&v](int value) { - v.push_back(value); - return (value % 2) == 1; - }); - auto expected = std::vector { 2, 4, 4, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1 }; - REQUIRE(v == expected); - } - - SECTION("allows to push_back while removing all") { - push_back_safe_remove_if(v, [&v](int value) { - if (value == 5) { - v.push_back(value); - } - return true; - }); - auto expected = std::vector { 5 }; - REQUIRE(v == expected); - } -} \ No newline at end of file diff --git a/Telegram/SourceFiles/base/assertion.h b/Telegram/SourceFiles/base/assertion.h deleted file mode 100644 index d7907a583..000000000 --- a/Telegram/SourceFiles/base/assertion.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// Ensures/Expects. -#include - -namespace base { -namespace assertion { - -// Client must define that method. -void log(const char *message, const char *file, int line); - -// Release build assertions. -inline constexpr void noop() { -} - -[[noreturn]] inline void fail( - const char *message, - const char *file, - int line) { - log(message, file, line); - - // Crash with access violation and generate crash report. - volatile auto nullptr_value = (int*)nullptr; - *nullptr_value = 0; - - // Silent the possible failure to comply noreturn warning. - std::abort(); -} - -constexpr const char* extract_basename(const char* path, size_t size) { - while (size != 0 && path[size - 1] != '/' && path[size - 1] != '\\') { - --size; - } - return path + size; -} - -} // namespace assertion -} // namespace base - -#if defined(__clang__) || defined(__GNUC__) -#define AssertUnlikelyHelper(x) __builtin_expect(!!(x), 0) -#else -#define AssertUnlikelyHelper(x) (!!(x)) -#endif - -#define AssertValidationCondition(condition, message, file, line)\ - ((AssertUnlikelyHelper(!(condition)))\ - ? ::base::assertion::fail(message, file, line)\ - : ::base::assertion::noop()) - -#define SOURCE_FILE_BASENAME (::base::assertion::extract_basename(\ - __FILE__,\ - sizeof(__FILE__))) - -#define AssertCustom(condition, message) (AssertValidationCondition(\ - condition,\ - message,\ - SOURCE_FILE_BASENAME,\ - __LINE__)) -#define Assert(condition) AssertCustom(condition, "\"" #condition "\"") - -// Define our own versions of Expects() and Ensures(). -// Let them crash with reports and logging. -#ifdef Expects -#undef Expects -#endif // Expects -#define Expects(condition) (AssertValidationCondition(\ - condition,\ - "\"" #condition "\"",\ - SOURCE_FILE_BASENAME,\ - __LINE__)) - -#ifdef Ensures -#undef Ensures -#endif // Ensures -#define Ensures(condition) (AssertValidationCondition(\ - condition,\ - "\"" #condition "\"",\ - SOURCE_FILE_BASENAME,\ - __LINE__)) - -#ifdef Unexpected -#undef Unexpected -#endif // Unexpected -#define Unexpected(message) (::base::assertion::fail(\ - "Unexpected: " message,\ - SOURCE_FILE_BASENAME,\ - __LINE__)) - -#ifdef _DEBUG -#define AssertIsDebug(...) -#endif // _DEBUG diff --git a/Telegram/SourceFiles/base/base_integration.h b/Telegram/SourceFiles/base/base_integration.h deleted file mode 100644 index 397e4736c..000000000 --- a/Telegram/SourceFiles/base/base_integration.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/basic_types.h" - -// Methods that must be implemented outside lib_base. - -namespace base { - -void EnterFromEventLoop(FnMut &&method); - -} // namespace diff --git a/Telegram/SourceFiles/base/base_pch.cpp b/Telegram/SourceFiles/base/base_pch.cpp deleted file mode 100644 index 33c7d3279..000000000 --- a/Telegram/SourceFiles/base/base_pch.cpp +++ /dev/null @@ -1,10 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/base_pch.h" - -// Precompiled header helper. diff --git a/Telegram/SourceFiles/base/base_pch.h b/Telegram/SourceFiles/base/base_pch.h deleted file mode 100644 index 933cf5b25..000000000 --- a/Telegram/SourceFiles/base/base_pch.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include "base/flat_map.h" -#include "base/flat_set.h" -#include "base/optional.h" -#include "base/openssl_help.h" diff --git a/Telegram/SourceFiles/base/basic_types.h b/Telegram/SourceFiles/base/basic_types.h deleted file mode 100644 index bd5ec4059..000000000 --- a/Telegram/SourceFiles/base/basic_types.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/build_config.h" -#include "base/ordered_set.h" -#include "base/unique_function.h" -#include "base/functors.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace func = base::functors; - -using gsl::not_null; -using index_type = gsl::index; -using size_type = gsl::index; - -template -using Fn = std::function; - -template -using FnMut = base::unique_function; - -//using uchar = unsigned char; // Qt has uchar -using int8 = qint8; -using uint8 = quint8; -using int16 = qint16; -using uint16 = quint16; -using int32 = qint32; -using uint32 = quint32; -using int64 = qint64; -using uint64 = quint64; -using float32 = float; -using float64 = double; - -using TimeId = int32; - -// Define specializations for QByteArray for Qt 5.3.2, because -// QByteArray in Qt 5.3.2 doesn't declare "pointer" subtype. -#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) -namespace gsl { - -template <> -inline span make_span(QByteArray &cont) { - return span(cont.data(), cont.size()); -} - -template <> -inline span make_span(const QByteArray &cont) { - return span(cont.constData(), cont.size()); -} - -} // namespace gsl -#endif // OS_MAC_OLD diff --git a/Telegram/SourceFiles/base/binary_guard.h b/Telegram/SourceFiles/base/binary_guard.h deleted file mode 100644 index 2f0978999..000000000 --- a/Telegram/SourceFiles/base/binary_guard.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/algorithm.h" - -#include - -namespace base { - -class binary_guard { -public: - binary_guard() = default; - binary_guard(binary_guard &&other); - binary_guard &operator=(binary_guard &&other); - ~binary_guard(); - - binary_guard &operator=(std::nullptr_t); - - bool alive() const; - binary_guard make_guard(); - - explicit operator bool() const; - -private: - void destroy(); - - std::atomic *_bothAlive = nullptr; - -}; - -inline binary_guard::binary_guard(binary_guard &&other) -: _bothAlive(base::take(other._bothAlive)) { -} - -inline binary_guard &binary_guard::operator=(binary_guard &&other) { - if (this != &other) { - destroy(); - _bothAlive = base::take(other._bothAlive); - } - return *this; -} - -inline binary_guard::~binary_guard() { - destroy(); -} - -inline binary_guard &binary_guard::operator=(std::nullptr_t) { - destroy(); - return *this; -} - -inline binary_guard::operator bool() const { - return alive(); -} - -inline bool binary_guard::alive() const { - return _bothAlive && _bothAlive->load(); -} - -inline void binary_guard::destroy() { - if (const auto both = base::take(_bothAlive)) { - auto old = true; - if (!both->compare_exchange_strong(old, false)) { - delete both; - } - } -} - -inline binary_guard binary_guard::make_guard() { - destroy(); - - auto result = binary_guard(); - _bothAlive = result._bothAlive = new std::atomic(true); - return result; -} - -} // namespace base - -namespace crl { - -template -struct guard_traits; - -template <> -struct guard_traits { - static base::binary_guard create(base::binary_guard value) { - return value; - } - static bool check(const base::binary_guard &guard) { - return guard.alive(); - } - -}; - -} // namespace crl diff --git a/Telegram/SourceFiles/base/build_config.h b/Telegram/SourceFiles/base/build_config.h deleted file mode 100644 index 3bcb5952a..000000000 --- a/Telegram/SourceFiles/base/build_config.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// thanks Chromium - -#if defined(__APPLE__) -#define OS_MAC 1 -#elif defined(__linux__) // __APPLE__ -#define OS_LINUX 1 -#elif defined(_WIN32) // __APPLE__ || __linux__ -#define OS_WIN 1 -#else // __APPLE__ || __linux__ || _WIN32 -#error Please add support for your platform in base/build_config.h -#endif // else for __APPLE__ || __linux__ || _WIN32 - -// For access to standard POSIXish features, use OS_POSIX instead of a -// more specific macro. -#if defined(OS_MAC) || defined(OS_LINUX) -#define OS_POSIX 1 -#endif // OS_MAC || OS_LINUX - -// Compiler detection. -#if defined(__clang__) -#define COMPILER_CLANG 1 -#elif defined(__GNUC__) // __clang__ -#define COMPILER_GCC 1 -#elif defined(_MSC_VER) // __clang__ || __GNUC__ -#define COMPILER_MSVC 1 -#else // _MSC_VER || __clang__ || __GNUC__ -#error Please add support for your compiler in base/build_config.h -#endif // else for _MSC_VER || __clang__ || __GNUC__ - -// Processor architecture detection. -#if defined(_M_X64) || defined(__x86_64__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86_64 1 -#define ARCH_CPU_64_BITS 1 -#elif defined(_M_IX86) || defined(__i386__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86 1 -#define ARCH_CPU_32_BITS 1 -#elif defined(__aarch64__) -#define ARCH_CPU_64_BITS 1 -#elif defined(_M_ARM) || defined(__arm__) -#define ARCH_CPU_32_BITS 1 -#else -#error Please add support for your architecture in base/build_config.h -#endif - -#if defined(__GNUC__) -#define TG_FORCE_INLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) -#define TG_FORCE_INLINE __forceinline -#else -#define TG_FORCE_INLINE inline -#endif - -#include -static_assert(CHAR_BIT == 8, "Not supported char size."); diff --git a/Telegram/SourceFiles/base/bytes.h b/Telegram/SourceFiles/base/bytes.h deleted file mode 100644 index 3810e1b4a..000000000 --- a/Telegram/SourceFiles/base/bytes.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/basic_types.h" -#include -#include -#include -#include - -namespace bytes { - -using type = gsl::byte; -using span = gsl::span; -using const_span = gsl::span; -using vector = std::vector; - -template -using array = std::array; - -inline span make_detached_span(QByteArray &container) { - return gsl::as_writeable_bytes(gsl::make_span(container)); -} - -template < - typename Container, - typename = std::enable_if_t< - !std::is_const_v - && !std::is_same_v>> -inline span make_span(Container &container) { - return gsl::as_writeable_bytes(gsl::make_span(container)); -} - -template -inline const_span make_span(const Container &container) { - return gsl::as_bytes(gsl::make_span(container)); -} - -template -inline span make_span(gsl::span container) { - return gsl::as_writeable_bytes(container); -} - -template -inline const_span make_span(gsl::span container) { - return gsl::as_bytes(container); -} - -template -inline span make_span(Type *value, std::size_t count) { - return gsl::as_writeable_bytes(gsl::make_span(value, count)); -} - -template -inline const_span make_span(const Type *value, std::size_t count) { - return gsl::as_bytes(gsl::make_span(value, count)); -} - -template -inline span object_as_span(Type *value) { - return bytes::make_span(value, 1); -} - -template -inline const_span object_as_span(const Type *value) { - return bytes::make_span(value, 1); -} - -template -inline vector make_vector(const Container &container) { - const auto buffer = bytes::make_span(container); - return { buffer.begin(), buffer.end() }; -} - -inline void copy(span destination, const_span source) { - Expects(destination.size() >= source.size()); - - memcpy(destination.data(), source.data(), source.size()); -} - -inline void move(span destination, const_span source) { - Expects(destination.size() >= source.size()); - - memmove(destination.data(), source.data(), source.size()); -} - -inline void set_with_const(span destination, type value) { - memset( - destination.data(), - gsl::to_integer(value), - destination.size()); -} - -inline int compare(const_span a, const_span b) { - const auto aSize = a.size(), bSize = b.size(); - return (aSize > bSize) - ? 1 - : (aSize < bSize) - ? -1 - : memcmp(a.data(), b.data(), aSize); -} - -namespace details { - -template -std::size_t spansLength(Arg &&arg) { - return bytes::make_span(arg).size(); -} - -template -std::size_t spansLength(Arg &&arg, Args &&...args) { - return bytes::make_span(arg).size() + spansLength(args...); -} - -template -void spansAppend(span destination, Arg &&arg) { - bytes::copy(destination, bytes::make_span(arg)); -} - -template -void spansAppend(span destination, Arg &&arg, Args &&...args) { - const auto data = bytes::make_span(arg); - bytes::copy(destination, data); - spansAppend(destination.subspan(data.size()), args...); -} - -} // namespace details - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -vector concatenate(Args &&...args) { - const auto size = details::spansLength(args...); - auto result = vector(size); - details::spansAppend(make_span(result), args...); - return result; -} - -template < - typename SpanRange> -vector concatenate(SpanRange args) { - auto size = std::size_t(0); - for (const auto &arg : args) { - size += bytes::make_span(arg).size(); - } - auto result = vector(size); - auto buffer = make_span(result); - for (const auto &arg : args) { - const auto part = bytes::make_span(arg); - bytes::copy(buffer, part); - buffer = buffer.subspan(part.size()); - } - return result; -} - -// Implemented in base/openssl_help.h -void set_random(span destination); - -} // namespace bytes diff --git a/Telegram/SourceFiles/base/concurrent_timer.cpp b/Telegram/SourceFiles/base/concurrent_timer.cpp deleted file mode 100644 index 7e523a0d1..000000000 --- a/Telegram/SourceFiles/base/concurrent_timer.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/concurrent_timer.h" - -#include -#include - -using namespace base::details; - -namespace base { -namespace details { -namespace { - -constexpr auto kCallDelayedEvent = QEvent::Type(QEvent::User + 1); -constexpr auto kCancelTimerEvent = QEvent::Type(QEvent::User + 2); -static_assert(kCancelTimerEvent < QEvent::MaxUser); - -ConcurrentTimerEnvironment *Environment/* = nullptr*/; -QMutex EnvironmentMutex; - -class CallDelayedEvent : public QEvent { -public: - CallDelayedEvent( - crl::time timeout, - Qt::TimerType type, - FnMut method); - - crl::time timeout() const; - Qt::TimerType type() const; - FnMut takeMethod(); - -private: - crl::time _timeout = 0; - Qt::TimerType _type = Qt::PreciseTimer; - FnMut _method; - -}; - -class CancelTimerEvent : public QEvent { -public: - CancelTimerEvent(); - -}; - -CallDelayedEvent::CallDelayedEvent( - crl::time timeout, - Qt::TimerType type, - FnMut method) -: QEvent(kCallDelayedEvent) -, _timeout(timeout) -, _type(type) -, _method(std::move(method)) { - Expects(_timeout >= 0 && _timeout < std::numeric_limits::max()); -} - -crl::time CallDelayedEvent::timeout() const { - return _timeout; -} - -Qt::TimerType CallDelayedEvent::type() const { - return _type; -} - -FnMut CallDelayedEvent::takeMethod() { - return base::take(_method); -} - -CancelTimerEvent::CancelTimerEvent() : QEvent(kCancelTimerEvent) { -} - -} // namespace - -class TimerObject : public QObject { -public: - TimerObject( - not_null thread, - not_null adjuster, - Fn adjust); - -protected: - bool event(QEvent *e) override; - -private: - void callDelayed(not_null e); - void callNow(); - void cancel(); - void adjust(); - - FnMut _next; - Fn _adjust; - int _timerId = 0; - -}; - -TimerObject::TimerObject( - not_null thread, - not_null adjuster, - Fn adjust) -: _adjust(std::move(adjust)) { - moveToThread(thread); - connect( - adjuster, - &QObject::destroyed, - this, - &TimerObject::adjust, - Qt::DirectConnection); -} - -bool TimerObject::event(QEvent *e) { - const auto type = e->type(); - switch (type) { - case kCallDelayedEvent: - callDelayed(static_cast(e)); - return true; - case kCancelTimerEvent: - cancel(); - return true; - case QEvent::Timer: - callNow(); - return true; - } - return QObject::event(e); -} - -void TimerObject::callDelayed(not_null e) { - cancel(); - - const auto timeout = e->timeout(); - const auto type = e->type(); - _next = e->takeMethod(); - if (timeout > 0) { - _timerId = startTimer(timeout, type); - } else { - base::take(_next)(); - } -} - -void TimerObject::cancel() { - if (const auto id = base::take(_timerId)) { - killTimer(id); - } - _next = nullptr; -} - -void TimerObject::callNow() { - auto next = base::take(_next); - cancel(); - next(); -} - -void TimerObject::adjust() { - if (_adjust) { - _adjust(); - } -} - -TimerObjectWrap::TimerObjectWrap(Fn adjust) { - QMutexLocker lock(&EnvironmentMutex); - - if (Environment) { - _value = Environment->createTimer(std::move(adjust)); - } -} - -TimerObjectWrap::~TimerObjectWrap() { - if (_value) { - QMutexLocker lock(&EnvironmentMutex); - - if (Environment) { - _value.release()->deleteLater(); - } - } -} - -void TimerObjectWrap::call( - crl::time timeout, - Qt::TimerType type, - FnMut method) { - sendEvent(std::make_unique( - timeout, - type, - std::move(method))); -} - -void TimerObjectWrap::cancel() { - sendEvent(std::make_unique()); -} - -void TimerObjectWrap::sendEvent(std::unique_ptr event) { - if (!_value) { - return; - } - QCoreApplication::postEvent( - _value.get(), - event.release(), - Qt::HighEventPriority); -} - -} // namespace details - -ConcurrentTimerEnvironment::ConcurrentTimerEnvironment() { - _thread.start(); - _adjuster.moveToThread(&_thread); - - acquire(); -} - -ConcurrentTimerEnvironment::~ConcurrentTimerEnvironment() { - _thread.quit(); - release(); - _thread.wait(); - QObject::disconnect(&_adjuster, &QObject::destroyed, nullptr, nullptr); -} - -std::unique_ptr ConcurrentTimerEnvironment::createTimer( - Fn adjust) { - return std::make_unique( - &_thread, - &_adjuster, - std::move(adjust)); -} - -void ConcurrentTimerEnvironment::Adjust() { - QMutexLocker lock(&EnvironmentMutex); - if (Environment) { - Environment->adjustTimers(); - } -} - -void ConcurrentTimerEnvironment::adjustTimers() { - QObject emitter; - QObject::connect( - &emitter, - &QObject::destroyed, - &_adjuster, - &QObject::destroyed, - Qt::QueuedConnection); -} - -void ConcurrentTimerEnvironment::acquire() { - Expects(Environment == nullptr); - - QMutexLocker lock(&EnvironmentMutex); - Environment = this; -} - -void ConcurrentTimerEnvironment::release() { - Expects(Environment == this); - - QMutexLocker lock(&EnvironmentMutex); - Environment = nullptr; -} - -ConcurrentTimer::ConcurrentTimer( - Fn)> runner, - Fn callback) -: _runner(std::move(runner)) -, _object(createAdjuster()) -, _callback(std::move(callback)) -, _type(Qt::PreciseTimer) -, _adjusted(false) { - setRepeat(Repeat::Interval); -} - -Fn ConcurrentTimer::createAdjuster() { - _guard = std::make_shared(true); - return [=, runner = _runner, guard = std::weak_ptr(_guard)] { - runner([=] { - if (!guard.lock()) { - return; - } - adjust(); - }); - }; -} - -void ConcurrentTimer::start( - crl::time timeout, - Qt::TimerType type, - Repeat repeat) { - _type = type; - setRepeat(repeat); - _adjusted = false; - setTimeout(timeout); - - cancelAndSchedule(_timeout); - _next = crl::now() + _timeout; -} - -void ConcurrentTimer::cancelAndSchedule(int timeout) { - auto method = [ - =, - runner = _runner, - guard = _running.make_guard() - ]() mutable { - if (!guard) { - return; - } - runner([=, guard = std::move(guard)] { - if (!guard) { - return; - } - timerEvent(); - }); - }; - _object.call(timeout, _type, std::move(method)); -} - -void ConcurrentTimer::timerEvent() { - if (repeat() == Repeat::Interval) { - if (_adjusted) { - start(_timeout, _type, repeat()); - } else { - _next = crl::now() + _timeout; - } - } else { - cancel(); - } - - if (_callback) { - _callback(); - } -} - -void ConcurrentTimer::cancel() { - _running = {}; - if (isActive()) { - _running = base::binary_guard(); - _object.cancel(); - } -} - -crl::time ConcurrentTimer::remainingTime() const { - if (!isActive()) { - return -1; - } - const auto now = crl::now(); - return (_next > now) ? (_next - now) : crl::time(0); -} - -void ConcurrentTimer::adjust() { - auto remaining = remainingTime(); - if (remaining >= 0) { - cancelAndSchedule(remaining); - _adjusted = true; - } -} - -void ConcurrentTimer::setTimeout(crl::time timeout) { - Expects(timeout >= 0 && timeout <= std::numeric_limits::max()); - - _timeout = static_cast(timeout); -} - -int ConcurrentTimer::timeout() const { - return _timeout; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/concurrent_timer.h b/Telegram/SourceFiles/base/concurrent_timer.h deleted file mode 100644 index 4020ee6ae..000000000 --- a/Telegram/SourceFiles/base/concurrent_timer.h +++ /dev/null @@ -1,146 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/binary_guard.h" -#include -#include -#include - -namespace base { -namespace details { - -class TimerObject; - -class TimerObjectWrap { -public: - explicit TimerObjectWrap(Fn adjust); - ~TimerObjectWrap(); - - void call( - crl::time timeout, - Qt::TimerType type, - FnMut method); - void cancel(); - -private: - void sendEvent(std::unique_ptr event); - - std::unique_ptr _value; - -}; - -} // namespace details - -class ConcurrentTimerEnvironment { -public: - ConcurrentTimerEnvironment(); - ~ConcurrentTimerEnvironment(); - - std::unique_ptr createTimer(Fn adjust); - - static void Adjust(); - -private: - void acquire(); - void release(); - void adjustTimers(); - - QThread _thread; - QObject _adjuster; - -}; - -class ConcurrentTimer { -public: - explicit ConcurrentTimer( - Fn)> runner, - Fn callback = nullptr); - - template - explicit ConcurrentTimer( - crl::weak_on_queue weak, - Fn callback = nullptr); - - static Qt::TimerType DefaultType(crl::time timeout) { - constexpr auto kThreshold = crl::time(1000); - return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer; - } - - void setCallback(Fn callback) { - _callback = std::move(callback); - } - - void callOnce(crl::time timeout) { - callOnce(timeout, DefaultType(timeout)); - } - - void callEach(crl::time timeout) { - callEach(timeout, DefaultType(timeout)); - } - - void callOnce(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::SingleShot); - } - - void callEach(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::Interval); - } - - bool isActive() const { - return _running.alive(); - } - - void cancel(); - crl::time remainingTime() const; - -private: - enum class Repeat : unsigned { - Interval = 0, - SingleShot = 1, - }; - Fn createAdjuster(); - void start(crl::time timeout, Qt::TimerType type, Repeat repeat); - void adjust(); - - void cancelAndSchedule(int timeout); - - void setTimeout(crl::time timeout); - int timeout() const; - - void timerEvent(); - - void setRepeat(Repeat repeat) { - _repeat = static_cast(repeat); - } - Repeat repeat() const { - return static_cast(_repeat); - } - - Fn)> _runner; - std::shared_ptr _guard; // Must be before _object. - details::TimerObjectWrap _object; - Fn _callback; - base::binary_guard _running; - crl::time _next = 0; - int _timeout = 0; - - Qt::TimerType _type : 2; - bool _adjusted : 1; - unsigned _repeat : 1; - -}; - -template -ConcurrentTimer::ConcurrentTimer( - crl::weak_on_queue weak, - Fn callback) -: ConcurrentTimer(weak.runner(), std::move(callback)) { -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/crc32hash.cpp b/Telegram/SourceFiles/base/crc32hash.cpp deleted file mode 100644 index 91cbf9920..000000000 --- a/Telegram/SourceFiles/base/crc32hash.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/crc32hash.h" - -namespace base { -namespace { - -class Crc32Table { -public: - Crc32Table() { - auto poly = std::uint32_t(0x04c11db7); - for (auto i = 0; i != 256; ++i) { - _data[i] = reflect(i, 8) << 24; - for (auto j = 0; j != 8; ++j) { - _data[i] = (_data[i] << 1) ^ (_data[i] & (1 << 31) ? poly : 0); - } - _data[i] = reflect(_data[i], 32); - } - } - - std::uint32_t operator[](int index) const { - return _data[index]; - } - -private: - std::uint32_t reflect(std::uint32_t val, char ch) { - auto result = std::uint32_t(0); - for (int i = 1; i < (ch + 1); ++i) { - if (val & 1) { - result |= 1 << (ch - i); - } - val >>= 1; - } - return result; - } - - std::uint32_t _data[256]; - -}; - -} // namespace - -std::int32_t crc32(const void *data, int len) { - static const auto kTable = Crc32Table(); - - const auto buffer = static_cast(data); - - auto crc = std::uint32_t(0xffffffff); - for (auto i = 0; i != len; ++i) { - crc = (crc >> 8) ^ kTable[(crc & 0xFF) ^ buffer[i]]; - } - - return static_cast(crc ^ 0xffffffff); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/crc32hash.h b/Telegram/SourceFiles/base/crc32hash.h deleted file mode 100644 index dac0b5886..000000000 --- a/Telegram/SourceFiles/base/crc32hash.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -std::int32_t crc32(const void *data, int len); - -} // namespace base diff --git a/Telegram/SourceFiles/base/enum_mask.h b/Telegram/SourceFiles/base/enum_mask.h deleted file mode 100644 index f943646c7..000000000 --- a/Telegram/SourceFiles/base/enum_mask.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { - -template -class enum_mask { - using Type = std::uint32_t; - -public: - static_assert(static_cast(Enum::kCount) <= 32, "We have only 32 bit."); - - enum_mask() = default; - enum_mask(Enum value) : _value(ToBit(value)) { - } - - enum_mask added(enum_mask other) const { - auto result = *this; - result.set(other); - return result; - } - void set(enum_mask other) { - _value |= other._value; - } - bool test(Enum value) const { - return _value & ToBit(value); - } - - explicit operator bool() const { - return _value != 0; - } - -private: - inline static Type ToBit(Enum value) { - return 1 << static_cast(value); - } - Type _value = 0; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/flags.h b/Telegram/SourceFiles/base/flags.h deleted file mode 100644 index e3116a334..000000000 --- a/Telegram/SourceFiles/base/flags.h +++ /dev/null @@ -1,351 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -class flags; - -template -struct extended_flags; - -template -using extended_flags_t = typename extended_flags::type; - -namespace details { - -struct flags_zero_helper_struct { -}; - -using flags_zero_helper = void(base::details::flags_zero_helper_struct::*)(); - -template ::type> -inline constexpr auto extended_flag_convert(ExtendedEnum value) { - return static_cast(value); -} - -template ::type> -inline constexpr auto extended_flags_convert(ExtendedEnum value) { - return flags(extended_flag_convert(value)); -} - -} // namespace details - -template -class flags { -public: - using Enum = EnumType; - using Type = std::underlying_type_t; - - constexpr flags() = default; - constexpr flags(details::flags_zero_helper) noexcept { - } - constexpr flags(Enum value) noexcept - : _value(static_cast(value)) { - } - static constexpr flags from_raw(Type value) noexcept { - return flags(static_cast(value)); - } - - constexpr auto value() const noexcept { - return _value; - } - constexpr operator Type() const noexcept { - return value(); - } - - constexpr auto &operator|=(flags b) noexcept { - _value |= b.value(); - return *this; - } - constexpr auto &operator&=(flags b) noexcept { - _value &= b.value(); - return *this; - } - constexpr auto &operator^=(flags b) noexcept { - _value ^= b.value(); - return *this; - } - - constexpr auto operator~() const noexcept { - return from_raw(~value()); - } - - constexpr auto operator|(flags b) const noexcept { - return (flags(*this) |= b); - } - constexpr auto operator&(flags b) const noexcept { - return (flags(*this) &= b); - } - constexpr auto operator^(flags b) const noexcept { - return (flags(*this) ^= b); - } - - constexpr auto operator|(Enum b) const noexcept { - return (flags(*this) |= b); - } - constexpr auto operator&(Enum b) const noexcept { - return (flags(*this) &= b); - } - constexpr auto operator^(Enum b) const noexcept { - return (flags(*this) ^= b); - } - - constexpr auto operator==(Enum b) const noexcept { - return (value() == static_cast(b)); - } - constexpr auto operator!=(Enum b) const noexcept { - return !(*this == b); - } - constexpr auto operator<(Enum b) const noexcept { - return value() < static_cast(b); - } - constexpr auto operator>(Enum b) const noexcept { - return (b < *this); - } - constexpr auto operator<=(Enum b) const noexcept { - return !(b < *this); - } - constexpr auto operator>=(Enum b) const noexcept { - return !(*this < b); - } - -private: - Type _value = 0; - -}; - -template -constexpr auto make_flags(Enum value) noexcept { - return flags(value); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(Enum a, flags b) noexcept { - return b | a; -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator&(Enum a, flags b) noexcept { - return b & a; -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator^(Enum a, flags b) noexcept { - return b ^ a; -} - -template ::type> -inline constexpr auto operator|(flags> a, ExtendedEnum b) { - return a | details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, flags> b) { - return b | a; -} - -template > -inline constexpr auto operator&(flags> a, ExtendedEnum b) { - return a & details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator&(ExtendedEnum a, flags> b) { - return b & a; -} - -template > -inline constexpr auto operator^(flags> a, ExtendedEnum b) { - return a ^ details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator^(ExtendedEnum a, flags> b) { - return b ^ a; -} - -template ::type> -inline constexpr auto &operator&=(flags> &a, ExtendedEnum b) { - return (a &= details::extended_flags_convert(b)); -} - -template ::type> -inline constexpr auto &operator|=(flags> &a, ExtendedEnum b) { - return (a |= details::extended_flags_convert(b)); -} - -template ::type> -inline constexpr auto &operator^=(flags> &a, ExtendedEnum b) { - return (a ^= details::extended_flags_convert(b)); -} - -template ::type> -inline constexpr auto operator==(flags> a, ExtendedEnum b) { - return a == details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator==(ExtendedEnum a, flags> b) { - return (b == a); -} - -template ::type> -inline constexpr auto operator!=(flags> a, ExtendedEnum b) { - return !(a == b); -} - -template ::type> -inline constexpr auto operator!=(ExtendedEnum a, flags> b) { - return !(a == b); -} - -template ::type> -inline constexpr auto operator<(flags> a, ExtendedEnum b) { - return a < details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator<(ExtendedEnum a, flags> b) { - return details::extended_flags_convert(a) < b; -} - -template ::type> -inline constexpr auto operator>(flags> a, ExtendedEnum b) { - return (b < a); -} - -template ::type> -inline constexpr auto operator>(ExtendedEnum a, flags> b) { - return (b < a); -} - -template ::type> -inline constexpr auto operator<=(flags> a, ExtendedEnum b) { - return !(b < a); -} - -template ::type> -inline constexpr auto operator<=(ExtendedEnum a, flags> b) { - return !(b < a); -} - -template ::type> -inline constexpr auto operator>=(flags> a, ExtendedEnum b) { - return !(a < b); -} - -template ::type> -inline constexpr auto operator>=(ExtendedEnum a, flags> b) { - return !(a < b); -} - -} // namespace base - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator!(Enum a) noexcept { - return !base::make_flags(a); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator~(Enum a) noexcept { - return ~base::make_flags(a); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(Enum a, Enum b) noexcept { - return base::make_flags(a) | b; -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(Enum a, base::details::flags_zero_helper) noexcept { - return base::make_flags(a); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(base::details::flags_zero_helper, Enum b) noexcept { - return base::make_flags(b); -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, ExtendedEnum b) { - return base::details::extended_flags_convert(a) | b; -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, typename base::extended_flags::type b) { - return base::details::extended_flags_convert(a) | b; -} - -template ::type> -inline constexpr auto operator|(typename base::extended_flags::type a, ExtendedEnum b) { - return b | a; -} - -template ::type> -inline constexpr auto operator|(base::details::flags_zero_helper, ExtendedEnum b) { - return 0 | base::details::extended_flag_convert(b); -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, base::details::flags_zero_helper) { - return base::details::extended_flag_convert(a) | 0; -} - -template ::type> -inline constexpr auto operator~(ExtendedEnum b) { - return ~base::details::extended_flags_convert(b); -} diff --git a/Telegram/SourceFiles/base/flags_tests.cpp b/Telegram/SourceFiles/base/flags_tests.cpp deleted file mode 100644 index 786dc49c2..000000000 --- a/Telegram/SourceFiles/base/flags_tests.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/flags.h" - -namespace MethodNamespace { - -template -void TestFlags(Enum a, Enum b, Enum c) { - auto abc = a | b; - abc |= c; - auto test = abc != a; - CHECK(abc != a); - CHECK(abc != (a | b)); - CHECK((abc & a) == a); - CHECK((abc & b) == b); - CHECK((abc & c) == c); - CHECK((abc & ~a) == (b | c)); - CHECK((abc & ~(b | c)) == a); - CHECK((abc ^ a) == (abc & ~a)); - - auto another = a | b; - another |= c; - CHECK(abc == another); - another &= ~b; - CHECK(another == (a | c)); - another ^= a; - CHECK(another == c); - another = 0; - another = nullptr; - auto is_zero = ((another & abc) == 0); - CHECK(is_zero); - CHECK(!(another & abc)); - auto more = a | another; - auto just = a | 0; - CHECK(more == just); - CHECK(just); -} - -} // namespace MethodNamespace - -namespace FlagsNamespace { - -enum class Flag : int { - one = (1 << 0), - two = (1 << 1), - three = (1 << 2), -}; -inline constexpr auto is_flag_type(Flag) { return true; } - -class Class { -public: - enum class Public : long { - one = (1 << 2), - two = (1 << 1), - three = (1 << 0), - }; - friend inline constexpr auto is_flag_type(Public) { return true; } - - static void TestPrivate(); - -private: - enum class Private : long { - one = (1 << 0), - two = (1 << 1), - three = (1 << 2), - }; - friend inline constexpr auto is_flag_type(Private) { return true; } - -}; - -void Class::TestPrivate() { - MethodNamespace::TestFlags(Private::one, Private::two, Private::three); -} - -} // namespace FlagsNamespace - -namespace ExtendedNamespace { - -enum class Flag : int { - one = (1 << 3), - two = (1 << 4), - three = (1 << 5), -}; - -} // namespace ExtendedNamespace - -namespace base { - -template<> -struct extended_flags { - using type = FlagsNamespace::Flag; -}; - -} // namespace base - -TEST_CASE("flags operators on scoped enums", "[flags]") { - SECTION("testing non-member flags") { - MethodNamespace::TestFlags( - FlagsNamespace::Flag::one, - FlagsNamespace::Flag::two, - FlagsNamespace::Flag::three); - } - SECTION("testing public member flags") { - MethodNamespace::TestFlags( - FlagsNamespace::Class::Public::one, - FlagsNamespace::Class::Public::two, - FlagsNamespace::Class::Public::three); - } - SECTION("testing private member flags") { - FlagsNamespace::Class::TestPrivate(); - } - SECTION("testing extended flags") { - MethodNamespace::TestFlags( - ExtendedNamespace::Flag::one, - ExtendedNamespace::Flag::two, - ExtendedNamespace::Flag::three); - - auto onetwo = FlagsNamespace::Flag::one | ExtendedNamespace::Flag::two; - auto twoone = ExtendedNamespace::Flag::two | FlagsNamespace::Flag::one; - CHECK(onetwo == twoone); - } -} diff --git a/Telegram/SourceFiles/base/flat_map.h b/Telegram/SourceFiles/base/flat_map.h deleted file mode 100644 index 9c8a9bcd7..000000000 --- a/Telegram/SourceFiles/base/flat_map.h +++ /dev/null @@ -1,917 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "base/optional.h" - -namespace base { - -using std::begin; -using std::end; - -template < - typename Key, - typename Type, - typename Compare = std::less<>> -class flat_map; - -template < - typename Key, - typename Type, - typename Compare = std::less<>> -class flat_multi_map; - -template < - typename Me, - typename Key, - typename Type, - typename iterator_impl, - typename pointer_impl, - typename reference_impl> -class flat_multi_map_iterator_base_impl; - -template -struct flat_multi_map_pair_type { - using first_type = const Key; - using second_type = Value; - - constexpr flat_multi_map_pair_type() - : first() - , second() { - } - - template - constexpr flat_multi_map_pair_type(OtherKey &&key, OtherValue &&value) - : first(std::forward(key)) - , second(std::forward(value)) { - } - - flat_multi_map_pair_type(const flat_multi_map_pair_type &pair) - : first(pair.first) - , second(pair.second) { - } - - flat_multi_map_pair_type(flat_multi_map_pair_type &&pair) - : first(std::move(const_cast(pair.first))) - , second(std::move(pair.second)) { - } - - flat_multi_map_pair_type &operator=(const flat_multi_map_pair_type&) = delete; - flat_multi_map_pair_type &operator=(flat_multi_map_pair_type &&other) { - const_cast(first) = std::move(const_cast(other.first)); - second = std::move(other.second); - return *this; - } - - void swap(flat_multi_map_pair_type &other) { - using std::swap; - - if (this != &other) { - std::swap( - const_cast(first), - const_cast(other.first)); - std::swap(second, other.second); - } - } - - const Key first; - Value second; - -}; - -template < - typename Me, - typename Key, - typename Type, - typename iterator_impl, - typename pointer_impl, - typename reference_impl> -class flat_multi_map_iterator_base_impl { -public: - using iterator_category = typename iterator_impl::iterator_category; - - using pair_type = flat_multi_map_pair_type; - using value_type = pair_type; - using difference_type = typename iterator_impl::difference_type; - using pointer = pointer_impl; - using reference = reference_impl; - - flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl()) - : _impl(impl) { - } - - reference operator*() const { - return *_impl; - } - pointer operator->() const { - return std::addressof(**this); - } - Me &operator++() { - ++_impl; - return static_cast(*this); - } - Me operator++(int) { - return _impl++; - } - Me &operator--() { - --_impl; - return static_cast(*this); - } - Me operator--(int) { - return _impl--; - } - Me &operator+=(difference_type offset) { - _impl += offset; - return static_cast(*this); - } - Me operator+(difference_type offset) const { - return _impl + offset; - } - Me &operator-=(difference_type offset) { - _impl -= offset; - return static_cast(*this); - } - Me operator-(difference_type offset) const { - return _impl - offset; - } - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - difference_type operator-( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl - right._impl; - } - reference operator[](difference_type offset) const { - return _impl[offset]; - } - - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - bool operator==( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl == right._impl; - } - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - bool operator!=( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl != right._impl; - } - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - bool operator<( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl < right._impl; - } - -private: - iterator_impl _impl; - - template < - typename OtherKey, - typename OtherType, - typename OtherCompare> - friend class flat_multi_map; - - template < - typename OtherMe, - typename OtherKey, - typename OtherType, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - friend class flat_multi_map_iterator_base_impl; - -}; - -template -class flat_multi_map { -public: - class iterator; - class const_iterator; - class reverse_iterator; - class const_reverse_iterator; - -private: - using pair_type = flat_multi_map_pair_type; - using impl_t = std::deque; - - using iterator_base = flat_multi_map_iterator_base_impl< - iterator, - Key, - Type, - typename impl_t::iterator, - pair_type*, - pair_type&>; - using const_iterator_base = flat_multi_map_iterator_base_impl< - const_iterator, - Key, - Type, - typename impl_t::const_iterator, - const pair_type*, - const pair_type&>; - using reverse_iterator_base = flat_multi_map_iterator_base_impl< - reverse_iterator, - Key, - Type, - typename impl_t::reverse_iterator, - pair_type*, - pair_type&>; - using const_reverse_iterator_base = flat_multi_map_iterator_base_impl< - const_reverse_iterator, - Key, - Type, - typename impl_t::const_reverse_iterator, - const pair_type*, - const pair_type&>; - -public: - using value_type = pair_type; - using size_type = typename impl_t::size_type; - using difference_type = typename impl_t::difference_type; - using pointer = pair_type*; - using const_pointer = const pair_type*; - using reference = pair_type&; - using const_reference = const pair_type&; - - class iterator : public iterator_base { - public: - using iterator_base::iterator_base; - iterator() = default; - iterator(const iterator_base &other) : iterator_base(other) { - } - friend class const_iterator; - - }; - class const_iterator : public const_iterator_base { - public: - using const_iterator_base::const_iterator_base; - const_iterator() = default; - const_iterator(const_iterator_base other) : const_iterator_base(other) { - } - const_iterator(const iterator &other) : const_iterator_base(other._impl) { - } - - }; - class reverse_iterator : public reverse_iterator_base { - public: - using reverse_iterator_base::reverse_iterator_base; - reverse_iterator() = default; - reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) { - } - friend class const_reverse_iterator; - - }; - class const_reverse_iterator : public const_reverse_iterator_base { - public: - using const_reverse_iterator_base::const_reverse_iterator_base; - const_reverse_iterator() = default; - const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) { - } - const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) { - } - - }; - - flat_multi_map() = default; - flat_multi_map(const flat_multi_map &other) = default; - flat_multi_map(flat_multi_map &&other) = default; - flat_multi_map &operator=(const flat_multi_map &other) { - auto copy = other; - return (*this = std::move(copy)); - } - flat_multi_map &operator=(flat_multi_map &&other) = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - flat_multi_map(Iterator first, Iterator last) - : _data(first, last) { - std::sort(std::begin(impl()), std::end(impl()), compare()); - } - - flat_multi_map(std::initializer_list iter) - : flat_multi_map(iter.begin(), iter.end()) { - } - - size_type size() const { - return impl().size(); - } - bool empty() const { - return impl().empty(); - } - void clear() { - impl().clear(); - } - - iterator begin() { - return impl().begin(); - } - iterator end() { - return impl().end(); - } - const_iterator begin() const { - return impl().begin(); - } - const_iterator end() const { - return impl().end(); - } - const_iterator cbegin() const { - return impl().cbegin(); - } - const_iterator cend() const { - return impl().cend(); - } - reverse_iterator rbegin() { - return impl().rbegin(); - } - reverse_iterator rend() { - return impl().rend(); - } - const_reverse_iterator rbegin() const { - return impl().rbegin(); - } - const_reverse_iterator rend() const { - return impl().rend(); - } - const_reverse_iterator crbegin() const { - return impl().crbegin(); - } - const_reverse_iterator crend() const { - return impl().crend(); - } - - reference front() { - return *begin(); - } - const_reference front() const { - return *begin(); - } - reference back() { - return *(end() - 1); - } - const_reference back() const { - return *(end() - 1); - } - - iterator insert(const value_type &value) { - if (empty() || compare()(value.first, front().first)) { - impl().push_front(value); - return begin(); - } else if (!compare()(value.first, back().first)) { - impl().push_back(value); - return (end() - 1); - } - auto where = getUpperBound(value.first); - return impl().insert(where, value); - } - iterator insert(value_type &&value) { - if (empty() || compare()(value.first, front().first)) { - impl().push_front(std::move(value)); - return begin(); - } else if (!compare()(value.first, back().first)) { - impl().push_back(std::move(value)); - return (end() - 1); - } - auto where = getUpperBound(value.first); - return impl().insert(where, std::move(value)); - } - template - iterator emplace(Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - - bool removeOne(const Key &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return false; - } - auto where = getLowerBound(key); - if (compare()(key, where->first)) { - return false; - } - impl().erase(where); - return true; - } - int removeAll(const Key &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return 0; - } - auto range = getEqualRange(key); - if (range.first == range.second) { - return 0; - } - const auto result = (range.second - range.first); - impl().erase(range.first, range.second); - return result; - } - - iterator erase(const_iterator where) { - return impl().erase(where._impl); - } - iterator erase(const_iterator from, const_iterator till) { - return impl().erase(from._impl, till._impl); - } - int erase(const Key &key) { - return removeAll(key); - } - - iterator findFirst(const Key &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - const_iterator findFirst(const Key &key) const { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - template - iterator findFirst(const OtherKey &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - template - const_iterator findFirst(const OtherKey &key) const { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - bool contains(const Key &key) const { - return findFirst(key) != end(); - } - int count(const Key &key) const { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return 0; - } - auto range = getEqualRange(key); - return (range.second - range.first); - } - -private: - friend class flat_map; - - struct transparent_compare : Compare { - inline constexpr const Compare &initial() const noexcept { - return *this; - } - - template < - typename OtherType1, - typename OtherType2, - typename = std::enable_if_t< - !std::is_same_v, pair_type> && - !std::is_same_v, pair_type>>> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const { - return initial()( - std::forward(a), - std::forward(b)); - } - template < - typename OtherType1, - typename OtherType2> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const -> std::enable_if_t< - std::is_same_v, pair_type> && - std::is_same_v, pair_type>, bool> { - return initial()(a.first, b.first); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, pair_type>>> - inline constexpr auto operator()( - const pair_type &a, - OtherType &&b) const { - return operator()(a.first, std::forward(b)); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, pair_type>>> - inline constexpr auto operator()( - OtherType &&a, - const pair_type &b) const { - return operator()(std::forward(a), b.first); - } - - }; - struct Data : transparent_compare { - template - Data(Args &&...args) - : elements(std::forward(args)...) { - } - - impl_t elements; - }; - - Data _data; - const transparent_compare &compare() const noexcept { - return _data; - } - const impl_t &impl() const noexcept { - return _data.elements; - } - impl_t &impl() noexcept { - return _data.elements; - } - - template - typename impl_t::iterator getLowerBound(const OtherKey &key) { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - typename impl_t::const_iterator getLowerBound(const OtherKey &key) const { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - typename impl_t::iterator getUpperBound(const OtherKey &key) { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - typename impl_t::const_iterator getUpperBound(const OtherKey &key) const { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - std::pair< - typename impl_t::iterator, - typename impl_t::iterator - > getEqualRange(const OtherKey &key) { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - std::pair< - typename impl_t::const_iterator, - typename impl_t::const_iterator - > getEqualRange(const OtherKey &key) const { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - -}; - -template -class flat_map : private flat_multi_map { - using parent = flat_multi_map; - using pair_type = typename parent::pair_type; - -public: - using value_type = typename parent::value_type; - using size_type = typename parent::size_type; - using difference_type = typename parent::difference_type; - using pointer = typename parent::pointer; - using const_pointer = typename parent::const_pointer; - using reference = typename parent::reference; - using const_reference = typename parent::const_reference; - using iterator = typename parent::iterator; - using const_iterator = typename parent::const_iterator; - using reverse_iterator = typename parent::reverse_iterator; - using const_reverse_iterator = typename parent::const_reverse_iterator; - - flat_map() = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category - > - flat_map(Iterator first, Iterator last) : parent(first, last) { - finalize(); - } - - flat_map(std::initializer_list iter) : parent(iter.begin(), iter.end()) { - finalize(); - } - - using parent::parent; - using parent::size; - using parent::empty; - using parent::clear; - using parent::begin; - using parent::end; - using parent::cbegin; - using parent::cend; - using parent::rbegin; - using parent::rend; - using parent::crbegin; - using parent::crend; - using parent::front; - using parent::back; - using parent::erase; - using parent::contains; - - std::pair insert(const value_type &value) { - if (this->empty() || this->compare()(value.first, this->front().first)) { - this->impl().push_front(value); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, value.first)) { - this->impl().push_back(value); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(value.first); - if (this->compare()(value.first, where->first)) { - return { this->impl().insert(where, value), true }; - } - return { where, false }; - } - std::pair insert(value_type &&value) { - if (this->empty() || this->compare()(value.first, this->front().first)) { - this->impl().push_front(std::move(value)); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, value.first)) { - this->impl().push_back(std::move(value)); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(value.first); - if (this->compare()(value.first, where->first)) { - return { this->impl().insert(where, std::move(value)), true }; - } - return { where, false }; - } - std::pair insert_or_assign( - const Key &key, - const Type &value) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().emplace_front(key, value); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, key)) { - this->impl().emplace_back(key, value); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return { this->impl().insert(where, value_type(key, value)), true }; - } - where->second = value; - return { where, false }; - } - std::pair insert_or_assign( - const Key &key, - Type &&value) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().emplace_front(key, std::move(value)); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, key)) { - this->impl().emplace_back(key, std::move(value)); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return { this->impl().insert(where, value_type(key, std::move(value))), true }; - } - where->second = std::move(value); - return { where, false }; - } - template - std::pair emplace( - OtherKey &&key, - Args&&... args) { - return this->insert(value_type( - std::forward(key), - Type(std::forward(args)...))); - } - template - std::pair emplace_or_assign( - const Key &key, - Args&&... args) { - return this->insert_or_assign( - key, - Type(std::forward(args)...)); - } - template - std::pair try_emplace( - const Key &key, - Args&&... args) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().push_front(value_type( - key, - Type(std::forward(args)...))); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, key)) { - this->impl().push_back(value_type( - key, - Type(std::forward(args)...))); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return { - this->impl().insert( - where, - value_type( - key, - Type(std::forward(args)...))), - true - }; - } - return { where, false }; - } - - bool remove(const Key &key) { - return this->removeOne(key); - } - - iterator find(const Key &key) { - return this->findFirst(key); - } - const_iterator find(const Key &key) const { - return this->findFirst(key); - } - template - iterator find(const OtherKey &key) { - return this->template findFirst(key); - } - template - const_iterator find(const OtherKey &key) const { - return this->template findFirst(key); - } - - Type &operator[](const Key &key) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().push_front({ key, Type() }); - return this->front().second; - } else if (this->compare()(this->back().first, key)) { - this->impl().push_back({ key, Type() }); - return this->back().second; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return this->impl().insert(where, { key, Type() })->second; - } - return where->second; - } - - std::optional take(const Key &key) { - auto it = find(key); - if (it == this->end()) { - return std::nullopt; - } - auto result = std::move(it->second); - this->erase(it); - return std::move(result); - } - -private: - void finalize() { - this->impl().erase( - std::unique( - std::begin(this->impl()), - std::end(this->impl()), - [&](auto &&a, auto &&b) { - return !this->compare()(a, b); - } - ), - std::end(this->impl())); - } - -}; - -} // namespace base - -// Structured bindings support. -namespace std { - -template -class tuple_size> -: public integral_constant { -}; - -template -class tuple_element<0, base::flat_multi_map_pair_type> { -public: - using type = const Key; -}; - -template -class tuple_element<1, base::flat_multi_map_pair_type> { -public: - using type = Value; -}; - -} // namespace std - -// Structured bindings support. -namespace base { -namespace details { - -template -using flat_multi_map_pair_element = std::tuple_element_t< - N, - flat_multi_map_pair_type>; - -} // namespace details - -template -auto get(base::flat_multi_map_pair_type &value) --> details::flat_multi_map_pair_element & { - if constexpr (N == 0) { - return value.first; - } else { - return value.second; - } -} - -template -auto get(const base::flat_multi_map_pair_type &value) --> const details::flat_multi_map_pair_element & { - if constexpr (N == 0) { - return value.first; - } else { - return value.second; - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/flat_map_tests.cpp b/Telegram/SourceFiles/base/flat_map_tests.cpp deleted file mode 100644 index e1372c4ac..000000000 --- a/Telegram/SourceFiles/base/flat_map_tests.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/flat_map.h" -#include - -struct int_wrap { - int value; -}; -struct int_wrap_comparator { - inline bool operator()(const int_wrap &a, const int_wrap &b) const { - return a.value < b.value; - } -}; - -using namespace std; - -TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") { - base::flat_map v; - v.emplace(0, "a"); - v.emplace(5, "b"); - v.emplace(4, "d"); - v.emplace(2, "e"); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(prev->first < i->first); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.emplace(3, "c"); - REQUIRE(v.size() == 5); - REQUIRE(v.find(3) != v.end()); - checkSorted(); - } -} - -TEST_CASE("simple flat_maps tests", "[flat_map]") { - SECTION("copy constructor") { - base::flat_map v; - v.emplace(0, "a"); - v.emplace(2, "b"); - auto u = v; - REQUIRE(u.size() == 2); - REQUIRE(u.find(0) == u.begin()); - REQUIRE(u.find(2) == u.end() - 1); - } - SECTION("assignment") { - base::flat_map v, u; - v.emplace(0, "a"); - v.emplace(2, "b"); - u = v; - REQUIRE(u.size() == 2); - REQUIRE(u.find(0) == u.begin()); - REQUIRE(u.find(2) == u.end() - 1); - } -} - -TEST_CASE("flat_maps custom comparator", "[flat_map]") { - base::flat_map v; - v.emplace(int_wrap{ 0 }, "a"); - v.emplace(int_wrap{ 5 }, "b"); - v.emplace(int_wrap{ 4 }, "d"); - v.emplace(int_wrap{ 2 }, "e"); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(int_wrap_comparator()(prev->first, i->first)); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.emplace(int_wrap{ 3 }, "c"); - REQUIRE(v.size() == 5); - REQUIRE(v.find({ 3 }) != v.end()); - checkSorted(); - } -} - -TEST_CASE("flat_maps structured bindings", "[flat_map]") { - base::flat_map> v; - v.emplace(0, std::make_unique(0.)); - v.emplace(1, std::make_unique(1.)); - - SECTION("structred binded range-based for loop") { - for (const auto &[key, value] : v) { - REQUIRE(key == int(std::round(*value))); - } - } - - SECTION("non-const structured binded range-based for loop") { - base::flat_map second = { - { 1, 1 }, - { 2, 2 }, - { 2, 3 }, - { 3, 3 }, - }; - REQUIRE(second.size() == 3); - //for (auto [a, b] : second) { // #MSVC Bug, reported - // REQUIRE(a == b); - //} - for (const auto [a, b] : second) { - REQUIRE(a == b); - } - } -} diff --git a/Telegram/SourceFiles/base/flat_set.h b/Telegram/SourceFiles/base/flat_set.h deleted file mode 100644 index b72814c2e..000000000 --- a/Telegram/SourceFiles/base/flat_set.h +++ /dev/null @@ -1,720 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace base { - -using std::begin; -using std::end; - -template > -class flat_set; - -template > -class flat_multi_set; - -template -class flat_multi_set_iterator_impl; - -template -class flat_multi_set_iterator_impl { -public: - using iterator_category = typename iterator_impl::iterator_category; - - using value_type = Type; - using difference_type = typename iterator_impl::difference_type; - using pointer = const Type*; - using reference = const Type&; - - flat_multi_set_iterator_impl( - iterator_impl impl = iterator_impl()) - : _impl(impl) { - } - template - flat_multi_set_iterator_impl( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &other) - : _impl(other._impl) { - } - - reference operator*() const { - return *_impl; - } - pointer operator->() const { - return std::addressof(**this); - } - flat_multi_set_iterator_impl &operator++() { - ++_impl; - return *this; - } - flat_multi_set_iterator_impl operator++(int) { - return _impl++; - } - flat_multi_set_iterator_impl &operator--() { - --_impl; - return *this; - } - flat_multi_set_iterator_impl operator--(int) { - return _impl--; - } - flat_multi_set_iterator_impl &operator+=(difference_type offset) { - _impl += offset; - return *this; - } - flat_multi_set_iterator_impl operator+(difference_type offset) const { - return _impl + offset; - } - flat_multi_set_iterator_impl &operator-=(difference_type offset) { - _impl -= offset; - return *this; - } - flat_multi_set_iterator_impl operator-(difference_type offset) const { - return _impl - offset; - } - template - difference_type operator-( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl - right._impl; - } - reference operator[](difference_type offset) const { - return _impl[offset]; - } - - template - bool operator==( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl == right._impl; - } - template - bool operator!=( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl != right._impl; - } - template - bool operator<( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl < right._impl; - } - -private: - iterator_impl _impl; - - template - friend class flat_multi_set; - - template - friend class flat_set; - - template < - typename OtherType, - typename other_iterator_impl> - friend class flat_multi_set_iterator_impl; - - Type &wrapped() { - return _impl->wrapped(); - } - -}; - -template -class flat_multi_set_const_wrap { -public: - constexpr flat_multi_set_const_wrap(const Type &value) - : _value(value) { - } - constexpr flat_multi_set_const_wrap(Type &&value) - : _value(std::move(value)) { - } - inline constexpr operator const Type&() const { - return _value; - } - constexpr Type &wrapped() { - return _value; - } - -private: - Type _value; - -}; - -template -class flat_multi_set { - using const_wrap = flat_multi_set_const_wrap; - using impl_t = std::deque; - -public: - using value_type = Type; - using size_type = typename impl_t::size_type; - using difference_type = typename impl_t::difference_type; - using pointer = const Type*; - using reference = const Type&; - - using iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::iterator>; - using const_iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::const_iterator>; - using reverse_iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::reverse_iterator>; - using const_reverse_iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::const_reverse_iterator>; - - flat_multi_set() = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - flat_multi_set(Iterator first, Iterator last) - : _data(first, last) { - std::sort(std::begin(impl()), std::end(impl()), compare()); - } - - flat_multi_set(std::initializer_list iter) - : flat_multi_set(iter.begin(), iter.end()) { - } - - size_type size() const { - return impl().size(); - } - bool empty() const { - return impl().empty(); - } - void clear() { - impl().clear(); - } - - iterator begin() { - return impl().begin(); - } - iterator end() { - return impl().end(); - } - const_iterator begin() const { - return impl().begin(); - } - const_iterator end() const { - return impl().end(); - } - const_iterator cbegin() const { - return impl().cbegin(); - } - const_iterator cend() const { - return impl().cend(); - } - reverse_iterator rbegin() { - return impl().rbegin(); - } - reverse_iterator rend() { - return impl().rend(); - } - const_reverse_iterator rbegin() const { - return impl().rbegin(); - } - const_reverse_iterator rend() const { - return impl().rend(); - } - const_reverse_iterator crbegin() const { - return impl().crbegin(); - } - const_reverse_iterator crend() const { - return impl().crend(); - } - - reference front() const { - return *begin(); - } - reference back() const { - return *(end() - 1); - } - - iterator insert(const Type &value) { - if (empty() || compare()(value, front())) { - impl().push_front(value); - return begin(); - } else if (!compare()(value, back())) { - impl().push_back(value); - return (end() - 1); - } - auto where = getUpperBound(value); - return impl().insert(where, value); - } - iterator insert(Type &&value) { - if (empty() || compare()(value, front())) { - impl().push_front(std::move(value)); - return begin(); - } else if (!compare()(value, back())) { - impl().push_back(std::move(value)); - return (end() - 1); - } - auto where = getUpperBound(value); - return impl().insert(where, std::move(value)); - } - template - iterator emplace(Args&&... args) { - return insert(Type(std::forward(args)...)); - } - - bool removeOne(const Type &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return false; - } - auto where = getLowerBound(value); - if (compare()(value, *where)) { - return false; - } - impl().erase(where); - return true; - } - int removeAll(const Type &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return 0; - } - auto range = getEqualRange(value); - if (range.first == range.second) { - return 0; - } - const auto result = (range.second - range.first); - impl().erase(range.first, range.second); - return result; - } - - iterator erase(const_iterator where) { - return impl().erase(where._impl); - } - iterator erase(const_iterator from, const_iterator till) { - return impl().erase(from._impl, till._impl); - } - int erase(const Type &value) { - return removeAll(value); - } - - iterator findFirst(const Type &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - const_iterator findFirst(const Type &value) const { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - template < - typename OtherType, - typename = typename Compare::is_transparent> - iterator findFirst(const OtherType &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - template < - typename OtherType, - typename = typename Compare::is_transparent> - const_iterator findFirst(const OtherType &value) const { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - bool contains(const Type &value) const { - return findFirst(value) != end(); - } - int count(const Type &value) const { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return 0; - } - auto range = getEqualRange(value); - return (range.second - range.first); - } - - template - auto modify(iterator which, Action action) { - auto result = action(which.wrapped()); - for (auto i = which + 1, e = end(); i != e; ++i) { - if (compare()(*i, *which)) { - std::swap(i.wrapped(), which.wrapped()); - } else { - break; - } - } - for (auto i = which, b = begin(); i != b;) { - --i; - if (compare()(*which, *i)) { - std::swap(i.wrapped(), which.wrapped()); - } else { - break; - } - } - return result; - } - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - void merge(Iterator first, Iterator last) { - impl().insert(impl().end(), first, last); - std::sort(std::begin(impl()), std::end(impl()), compare()); - } - - void merge(const flat_multi_set &other) { - merge(other.begin(), other.end()); - } - - void merge(std::initializer_list list) { - merge(list.begin(), list.end()); - } - -private: - friend class flat_set; - - struct transparent_compare : Compare { - inline constexpr const Compare &initial() const noexcept { - return *this; - } - - template < - typename OtherType1, - typename OtherType2, - typename = std::enable_if_t< - !std::is_same_v, const_wrap> && - !std::is_same_v, const_wrap>>> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const { - return initial()( - std::forward(a), - std::forward(b)); - } - template < - typename OtherType1, - typename OtherType2> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const -> std::enable_if_t< - std::is_same_v, const_wrap> && - std::is_same_v, const_wrap>, bool> { - return initial()( - static_cast(a), - static_cast(b)); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, const_wrap>>> - inline constexpr auto operator()( - const const_wrap &a, - OtherType &&b) const { - return initial()( - static_cast(a), - std::forward(b)); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, const_wrap>>> - inline constexpr auto operator()( - OtherType &&a, - const const_wrap &b) const { - return initial()( - std::forward(a), - static_cast(b)); - } - - }; - struct Data : transparent_compare { - template - Data(Args &&...args) - : elements(std::forward(args)...) { - } - - impl_t elements; - }; - - Data _data; - const transparent_compare &compare() const { - return _data; - } - const impl_t &impl() const { - return _data.elements; - } - impl_t &impl() { - return _data.elements; - } - - typename impl_t::iterator getLowerBound(const Type &value) { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - typename impl_t::const_iterator getLowerBound(const Type &value) const { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - typename impl_t::iterator getLowerBound(const OtherType &value) { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - typename impl_t::const_iterator getLowerBound(const OtherType &value) const { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - typename impl_t::iterator getUpperBound(const Type &value) { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - typename impl_t::const_iterator getUpperBound(const Type &value) const { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - std::pair< - typename impl_t::iterator, - typename impl_t::iterator - > getEqualRange(const Type &value) { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - std::pair< - typename impl_t::const_iterator, - typename impl_t::const_iterator - > getEqualRange(const Type &value) const { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - -}; - -template -class flat_set : private flat_multi_set { - using parent = flat_multi_set; - -public: - using iterator = typename parent::iterator; - using const_iterator = typename parent::const_iterator; - using reverse_iterator = typename parent::reverse_iterator; - using const_reverse_iterator = typename parent::const_reverse_iterator; - using value_type = typename parent::value_type; - using size_type = typename parent::size_type; - using difference_type = typename parent::difference_type; - using pointer = typename parent::pointer; - using reference = typename parent::reference; - - flat_set() = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category - > - flat_set(Iterator first, Iterator last) : parent(first, last) { - finalize(); - } - - flat_set(std::initializer_list iter) : parent(iter.begin(), iter.end()) { - finalize(); - } - - using parent::parent; - using parent::size; - using parent::empty; - using parent::clear; - using parent::begin; - using parent::end; - using parent::cbegin; - using parent::cend; - using parent::rbegin; - using parent::rend; - using parent::crbegin; - using parent::crend; - using parent::front; - using parent::back; - using parent::contains; - using parent::erase; - - std::pair insert(const Type &value) { - if (this->empty() || this->compare()(value, this->front())) { - this->impl().push_front(value); - return std::make_pair(this->begin(), true); - } else if (this->compare()(this->back(), value)) { - this->impl().push_back(value); - return std::make_pair(this->end() - 1, true); - } - auto where = this->getLowerBound(value); - if (this->compare()(value, *where)) { - return std::make_pair(this->impl().insert(where, value), true); - } - return std::make_pair(where, false); - } - std::pair insert(Type &&value) { - if (this->empty() || this->compare()(value, this->front())) { - this->impl().push_front(std::move(value)); - return std::make_pair(this->begin(), true); - } else if (this->compare()(this->back(), value)) { - this->impl().push_back(std::move(value)); - return std::make_pair(this->end() - 1, true); - } - auto where = this->getLowerBound(value); - if (this->compare()(value, *where)) { - return std::make_pair( - this->impl().insert(where, std::move(value)), - true); - } - return std::make_pair(where, false); - } - template - std::pair emplace(Args&&... args) { - return this->insert(Type(std::forward(args)...)); - } - - bool remove(const Type &value) { - return this->removeOne(value); - } - - iterator find(const Type &value) { - return this->findFirst(value); - } - const_iterator find(const Type &value) const { - return this->findFirst(value); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - iterator find(const OtherType &value) { - return this->findFirst(value); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - const_iterator find(const OtherType &value) const { - return this->findFirst(value); - } - - template - void modify(iterator which, Action action) { - action(which.wrapped()); - for (auto i = iterator(which + 1), e = end(); i != e; ++i) { - if (this->compare()(*i, *which)) { - std::swap(i.wrapped(), which.wrapped()); - } else if (!this->compare()(*which, *i)) { - erase(which); - return; - } else{ - break; - } - } - for (auto i = which, b = begin(); i != b;) { - --i; - if (this->compare()(*which, *i)) { - std::swap(i.wrapped(), which.wrapped()); - } else if (!this->compare()(*i, *which)) { - erase(which); - return; - } else { - break; - } - } - } - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - void merge(Iterator first, Iterator last) { - parent::merge(first, last); - finalize(); - } - - void merge(const flat_multi_set &other) { - merge(other.begin(), other.end()); - } - - void merge(std::initializer_list list) { - merge(list.begin(), list.end()); - } - -private: - void finalize() { - this->impl().erase( - std::unique( - std::begin(this->impl()), - std::end(this->impl()), - [&](auto &&a, auto &&b) { - return !this->compare()(a, b); - } - ), - std::end(this->impl())); - } - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/flat_set_tests.cpp b/Telegram/SourceFiles/base/flat_set_tests.cpp deleted file mode 100644 index a73f1d226..000000000 --- a/Telegram/SourceFiles/base/flat_set_tests.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/flat_set.h" - -struct int_wrap { - int value; -}; -struct int_wrap_comparator { - using is_transparent = void; - inline bool operator()(const int &a, const int_wrap &b) const { - return a < b.value; - } - inline bool operator()(const int_wrap &a, const int_wrap &b) const { - return a.value < b.value; - } - inline bool operator()(const int_wrap &a, const int &b) const { - return a.value < b; - } - inline bool operator()(const int &a, const int &b) const { - return a < b; - } -}; - -TEST_CASE("flat_sets should keep items sorted", "[flat_set]") { - - base::flat_set v; - v.insert(0); - v.insert(5); - v.insert(4); - v.insert(2); - - REQUIRE(v.contains(4)); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(*prev < *i); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.insert(3); - REQUIRE(v.size() == 5); - REQUIRE(v.find(3) != v.end()); - checkSorted(); - } -} - -TEST_CASE("flat_sets with custom comparators", "[flat_set]") { - base::flat_set v; - v.insert({ 0 }); - v.insert({ 5 }); - v.insert({ 4 }); - v.insert({ 2 }); - - REQUIRE(v.find(4) != v.end()); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(prev->value < i->value); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.insert({ 3 }); - REQUIRE(v.size() == 5); - REQUIRE(v.find(3) != v.end()); - checkSorted(); - } -} diff --git a/Telegram/SourceFiles/base/functors.h b/Telegram/SourceFiles/base/functors.h deleted file mode 100644 index 2a778a75b..000000000 --- a/Telegram/SourceFiles/base/functors.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { -namespace functors { - -struct abs_helper { - template < - typename Type, - typename = decltype(0 < std::declval()), - typename = decltype(-std::declval())> - constexpr Type operator()(Type value) const { - return (0 < value) ? value : (-value); - } -}; -constexpr auto abs = abs_helper{}; - -constexpr auto add = [](auto value) { - return [value](auto other) { - return value + other; - }; -}; - -struct negate_helper { - template < - typename Type, - typename = decltype(-std::declval())> - constexpr Type operator()(Type value) const { - return -value; - } -}; -constexpr auto negate = negate_helper{}; - -} // namespace functors -} // namespace base diff --git a/Telegram/SourceFiles/base/index_based_iterator.h b/Telegram/SourceFiles/base/index_based_iterator.h deleted file mode 100644 index a4db272d0..000000000 --- a/Telegram/SourceFiles/base/index_based_iterator.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/assertion.h" - -namespace base { - -template -class index_based_iterator { -public: - using iterator_category = std::random_access_iterator_tag; - - using value_type = typename Container::value_type; - using difference_type = typename Container::difference_type; - using pointer = std::conditional_t< - std::is_const_v, - typename Container::const_pointer, - typename Container::pointer>; - using reference = std::conditional_t< - std::is_const_v, - typename Container::const_reference, - typename Container::reference>; - using base_type = std::conditional_t< - std::is_const_v, - typename Container::const_iterator, - typename Container::iterator>; - - index_based_iterator(Container *container, base_type impl) - : _container(container) - , _index(impl - _container->begin()) { - } - - reference operator*() const { - return *(_container->begin() + _index); - } - pointer operator->() const { - return std::addressof(**this); - } - index_based_iterator &operator++() { - ++_index; - return *this; - } - index_based_iterator operator++(int) { - auto copy = *this; - ++*this; - return copy; - } - index_based_iterator &operator--() { - --_index; - return *this; - } - index_based_iterator operator--(int) { - auto copy = *this; - --*this; - return copy; - } - index_based_iterator &operator+=(difference_type offset) { - _index += offset; - return *this; - } - index_based_iterator operator+(difference_type offset) const { - auto copy = *this; - copy += offset; - return copy; - } - index_based_iterator &operator-=(difference_type offset) { - _index -= offset; - return *this; - } - index_based_iterator operator-(difference_type offset) const { - auto copy = *this; - copy -= offset; - return copy; - } - difference_type operator-(const index_based_iterator &other) const { - return _index - other._index; - } - reference operator[](difference_type offset) const { - return *(*this + offset); - } - - bool operator==(const index_based_iterator &other) const { - Expects(_container == other._container); - return _index == other._index; - } - bool operator!=(const index_based_iterator &other) const { - Expects(_container == other._container); - return _index != other._index; - } - bool operator<(const index_based_iterator &other) const { - Expects(_container == other._container); - return _index < other._index; - } - bool operator>(const index_based_iterator &other) const { - return other < *this; - } - bool operator<=(const index_based_iterator &other) const { - return !(other < *this); - } - bool operator>=(const index_based_iterator &other) const { - return !(*this < other); - } - - base_type base() const { - return _container->begin() + _index; - } - -private: - Container *_container = nullptr; - difference_type _index = 0; - -}; - -template -index_based_iterator index_based_begin(Container &container) { - return { &container, std::begin(container) }; -} - -template -index_based_iterator index_based_end(Container &container) { - return { &container, std::end(container) }; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/invoke_queued.h b/Telegram/SourceFiles/base/invoke_queued.h deleted file mode 100644 index a94efe527..000000000 --- a/Telegram/SourceFiles/base/invoke_queued.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -#include "base/basic_types.h" - -namespace base { - -class InvokeQueuedEvent : public QEvent { -public: - static constexpr auto kType = QEvent::Type(60666); - - explicit InvokeQueuedEvent(FnMut &&method) - : QEvent(kType) - , _method(std::move(method)) { - } - - void invoke() { - _method(); - } - -private: - FnMut _method; - -}; - -} // namespace base - -template -inline void InvokeQueued(const QObject *context, Lambda &&lambda) { - QCoreApplication::postEvent( - const_cast(context), - new base::InvokeQueuedEvent(std::forward(lambda))); -} - -class SingleQueuedInvokation : public QObject { -public: - SingleQueuedInvokation(Fn callback) : _callback(callback) { - } - void call() { - if (_pending.testAndSetAcquire(0, 1)) { - InvokeQueued(this, [this] { - if (_pending.testAndSetRelease(1, 0)) { - _callback(); - } - }); - } - } - -private: - Fn _callback; - QAtomicInt _pending = { 0 }; - -}; diff --git a/Telegram/SourceFiles/base/last_used_cache.h b/Telegram/SourceFiles/base/last_used_cache.h deleted file mode 100644 index 65d5fb4a3..000000000 --- a/Telegram/SourceFiles/base/last_used_cache.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace base { - -template -class last_used_cache { -public: - void up(Entry entry); - void remove(Entry entry); - void clear(); - - Entry take_lowest(); - -private: - std::list _queue; - std::unordered_map::iterator> _map; - -}; - -template -void last_used_cache::up(Entry entry) { - if (!_queue.empty() && _queue.back() == entry) { - return; - } - const auto i = _map.find(entry); - if (i != end(_map)) { - _queue.splice(end(_queue), _queue, i->second); - } else { - _map.emplace(entry, _queue.insert(end(_queue), entry)); - } -} - -template -void last_used_cache::remove(Entry entry) { - const auto i = _map.find(entry); - if (i != end(_map)) { - _queue.erase(i->second); - _map.erase(i); - } -} - -template -void last_used_cache::clear() { - _queue.clear(); - _map.clear(); -} - -template -Entry last_used_cache::take_lowest() { - if (_queue.empty()) { - return Entry(); - } - auto result = std::move(_queue.front()); - _queue.erase(begin(_queue)); - _map.erase(result); - return result; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/match_method.h b/Telegram/SourceFiles/base/match_method.h deleted file mode 100644 index 209494939..000000000 --- a/Telegram/SourceFiles/base/match_method.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -inline decltype(auto) match_method( - Data &&data, - Method &&method, - Methods &&...methods) { - using namespace rpl::details; - if constexpr (is_callable_plain_v) { - return std::forward(method)(std::forward(data)); - } else { - return match_method( - std::forward(data), - std::forward(methods)...); - } -} - -template < - typename Data1, - typename Data2, - typename Method, - typename ...Methods> -inline decltype(auto) match_method2( - Data1 &&data1, - Data2 &&data2, - Method &&method, - Methods &&...methods) { - using namespace rpl::details; - if constexpr (is_callable_plain_v) { - return std::forward(method)( - std::forward(data1), - std::forward(data2)); - } else { - return match_method2( - std::forward(data1), - std::forward(data2), - std::forward(methods)...); - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/object_ptr.h b/Telegram/SourceFiles/base/object_ptr.h deleted file mode 100644 index 714ee600a..000000000 --- a/Telegram/SourceFiles/base/object_ptr.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent. -template -class object_ptr { -public: - object_ptr(std::nullptr_t) noexcept { - } - - // No default constructor, but constructors with at least - // one argument are simply make functions. - template - explicit object_ptr(Parent &&parent, Args&&... args) - : _object(new Object(std::forward(parent), std::forward(args)...)) { - } - static object_ptr fromRaw(Object *value) noexcept { - object_ptr result = { nullptr }; - result._object = value; - return result; - } - Object *release() noexcept { - return static_cast(base::take(_object).data()); - } - - object_ptr(const object_ptr &other) = delete; - object_ptr &operator=(const object_ptr &other) = delete; - object_ptr(object_ptr &&other) noexcept : _object(base::take(other._object)) { - } - object_ptr &operator=(object_ptr &&other) noexcept { - auto temp = std::move(other); - destroy(); - std::swap(_object, temp._object); - return *this; - } - - template < - typename OtherObject, - typename = std::enable_if_t< - std::is_base_of_v>> - object_ptr(object_ptr &&other) noexcept - : _object(base::take(other._object)) { - } - - template < - typename OtherObject, - typename = std::enable_if_t< - std::is_base_of_v>> - object_ptr &operator=(object_ptr &&other) noexcept { - _object = base::take(other._object); - return *this; - } - - object_ptr &operator=(std::nullptr_t) noexcept { - _object = nullptr; - return *this; - } - - // So we can pass this pointer to methods like connect(). - Object *data() const noexcept { - return static_cast(_object.data()); - } - operator Object*() const noexcept { - return data(); - } - - explicit operator bool() const noexcept { - return _object != nullptr; - } - - Object *operator->() const noexcept { - return data(); - } - Object &operator*() const noexcept { - return *data(); - } - - // Use that instead "= new Object(parent, ...)" - template - Object *create(Parent &&parent, Args&&... args) { - destroy(); - _object = new Object( - std::forward(parent), - std::forward(args)...); - return data(); - } - void destroy() noexcept { - delete base::take(_object); - } - void destroyDelayed() { - if (_object) { - if (auto widget = base::up_cast(data())) { - widget->hide(); - } - base::take(_object)->deleteLater(); - } - } - - ~object_ptr() noexcept { - if (auto pointer = _object) { - if (!pointer->parent()) { - destroy(); - } - } - } - -private: - template - friend class object_ptr; - - QPointer _object; - -}; diff --git a/Telegram/SourceFiles/base/observer.cpp b/Telegram/SourceFiles/base/observer.cpp deleted file mode 100644 index 1c1245071..000000000 --- a/Telegram/SourceFiles/base/observer.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/observer.h" - -namespace base { -namespace internal { -namespace { - -bool CantUseObservables = false; -void (*HandleDelayedMethod)() = nullptr; - -struct ObservableListWrap { - ~ObservableListWrap() { - CantUseObservables = true; - } - OrderedSet list; -}; - -ObservableListWrap &PendingObservables() { - static ObservableListWrap result; - return result; -} - -ObservableListWrap &ActiveObservables() { - static ObservableListWrap result; - return result; -} - -} // namespace - -void RegisterPendingObservable(ObservableCallHandlers *handlers) { - if (CantUseObservables) return; - PendingObservables().list.insert(handlers); - if (HandleDelayedMethod) { - HandleDelayedMethod(); - } -} - -void UnregisterActiveObservable(ObservableCallHandlers *handlers) { - if (CantUseObservables) return; - ActiveObservables().list.remove(handlers); -} - -void UnregisterObservable(ObservableCallHandlers *handlers) { - if (CantUseObservables) return; - PendingObservables().list.remove(handlers); - ActiveObservables().list.remove(handlers); -} - -} // namespace internal - -void InitObservables(void(*HandleDelayed)()) { - internal::HandleDelayedMethod = HandleDelayed; -} - -void HandleObservables() { - if (internal::CantUseObservables) return; - auto &active = internal::ActiveObservables().list; - qSwap(active, internal::PendingObservables().list); - while (!active.empty()) { - auto first = *active.begin(); - (*first)(); - if (!active.empty() && *active.begin() == first) { - active.erase(active.begin()); - } - } -} - -rpl::producer<> ObservableViewer(base::Observable &observable) { - return [&observable](const auto &consumer) { - auto lifetime = rpl::lifetime(); - lifetime.make_state( - observable.add_subscription([consumer]() { - consumer.put_next({}); - })); - return lifetime; - }; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/observer.h b/Telegram/SourceFiles/base/observer.h deleted file mode 100644 index 75bc0e722..000000000 --- a/Telegram/SourceFiles/base/observer.h +++ /dev/null @@ -1,476 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include "base/type_traits.h" - -namespace base { -namespace internal { - -using ObservableCallHandlers = Fn; -void RegisterPendingObservable(ObservableCallHandlers *handlers); -void UnregisterActiveObservable(ObservableCallHandlers *handlers); -void UnregisterObservable(ObservableCallHandlers *handlers); - -template -struct SubscriptionHandlerHelper { - using type = Fn)>; -}; - -template <> -struct SubscriptionHandlerHelper { - using type = Fn; -}; - -template -using SubscriptionHandler = typename SubscriptionHandlerHelper::type; - -class BaseObservableData { -}; - -template -class CommonObservableData; - -template -class ObservableData; - -} // namespace internal - -class Subscription { -public: - Subscription() = default; - Subscription(const Subscription &) = delete; - Subscription &operator=(const Subscription &) = delete; - Subscription(Subscription &&other) : _node(base::take(other._node)), _removeAndDestroyMethod(other._removeAndDestroyMethod) { - } - Subscription &operator=(Subscription &&other) { - qSwap(_node, other._node); - qSwap(_removeAndDestroyMethod, other._removeAndDestroyMethod); - return *this; - } - explicit operator bool() const { - return (_node != nullptr); - } - void destroy() { - if (_node) { - (*_removeAndDestroyMethod)(base::take(_node)); - } - } - ~Subscription() { - destroy(); - } - -private: - struct Node { - Node(const std::shared_ptr &observable) - : observable(observable) { - } - Node *next = nullptr; - Node *prev = nullptr; - std::weak_ptr observable; - }; - using RemoveAndDestroyMethod = void(*)(Node*); - Subscription(Node *node, RemoveAndDestroyMethod removeAndDestroyMethod) - : _node(node) - , _removeAndDestroyMethod(removeAndDestroyMethod) { - } - - Node *_node = nullptr; - RemoveAndDestroyMethod _removeAndDestroyMethod; - - template - friend class internal::CommonObservableData; - - template - friend class internal::ObservableData; - -}; - -namespace internal { - -template -class BaseObservable; - -template -class CommonObservable { -public: - Subscription add_subscription(Handler &&handler) { - if (!_data) { - _data = std::make_shared>(this); - } - return _data->append(std::move(handler)); - } - -private: - std::shared_ptr> _data; - - friend class CommonObservableData; - friend class BaseObservable::is_fast_copy_type::value>; - -}; - -template -class BaseObservable : public internal::CommonObservable { -public: - void notify(EventType event, bool sync = false) { - if (this->_data) { - this->_data->notify(std::move(event), sync); - } - } - -}; - -template -class BaseObservable : public internal::CommonObservable { -public: - void notify(EventType &&event, bool sync = false) { - if (this->_data) { - this->_data->notify(std::move(event), sync); - } - } - void notify(const EventType &event, bool sync = false) { - if (this->_data) { - auto event_copy = event; - this->_data->notify(std::move(event_copy), sync); - } - } - -}; - -} // namespace internal - -namespace internal { - -template -class CommonObservableData : public BaseObservableData { -public: - CommonObservableData(CommonObservable *observable) : _observable(observable) { - } - - Subscription append(Handler &&handler) { - auto node = new Node(_observable->_data, std::move(handler)); - if (_begin) { - _end->next = node; - node->prev = _end; - _end = node; - } else { - _begin = _end = node; - } - return { _end, &CommonObservableData::removeAndDestroyNode }; - } - - bool empty() const { - return !_begin; - } - -private: - struct Node : public Subscription::Node { - Node( - const std::shared_ptr &observer, - Handler &&handler) - : Subscription::Node(observer) - , handler(std::move(handler)) { - } - Handler handler; - }; - - void remove(Subscription::Node *node) { - if (node->prev) { - node->prev->next = node->next; - } - if (node->next) { - node->next->prev = node->prev; - } - if (_begin == node) { - _begin = static_cast(node->next); - } - if (_end == node) { - _end = static_cast(node->prev); - } - if (_current == node) { - _current = static_cast(node->prev); - } else if (!_begin) { - _observable->_data.reset(); - } - } - - static void removeAndDestroyNode(Subscription::Node *node) { - if (const auto that = node->observable.lock()) { - static_cast(that.get())->remove(node); - } - delete static_cast(node); - } - - template - void notifyEnumerate(CallCurrent callCurrent) { - _current = _begin; - do { - callCurrent(); - if (_current) { - _current = static_cast(_current->next); - } else if (_begin) { - _current = _begin; - } else { - break; - } - } while (_current); - } - - bool destroyMeIfEmpty() const { - if (empty()) { - _observable->_data.reset(); - return true; - } - return false; - } - - CommonObservable *_observable = nullptr; - Node *_begin = nullptr; - Node *_current = nullptr; - Node *_end = nullptr; - ObservableCallHandlers _callHandlers; - - friend class ObservableData; - -}; - -template -class ObservableData : public CommonObservableData { -public: - using CommonObservableData::CommonObservableData; - - void notify(EventType &&event, bool sync) { - if (_handling) { - sync = false; - } - if (sync) { - _events.push_back(std::move(event)); - callHandlers(); - } else { - if (!this->_callHandlers) { - this->_callHandlers = [this]() { - callHandlers(); - }; - } - if (_events.empty()) { - RegisterPendingObservable(&this->_callHandlers); - } - _events.push_back(std::move(event)); - } - } - - ~ObservableData() { - UnregisterObservable(&this->_callHandlers); - } - -private: - void callHandlers() { - _handling = true; - auto events = base::take(_events); - for (auto &event : events) { - this->notifyEnumerate([this, &event]() { - this->_current->handler(event); - }); - if (this->destroyMeIfEmpty()) { - return; - } - } - _handling = false; - UnregisterActiveObservable(&this->_callHandlers); - } - - std::deque _events; - bool _handling = false; - -}; - -template -class ObservableData : public CommonObservableData { -public: - using CommonObservableData::CommonObservableData; - - void notify(bool sync) { - if (_handling) { - sync = false; - } - if (sync) { - ++_eventsCount; - callHandlers(); - } else { - if (!this->_callHandlers) { - this->_callHandlers = [this]() { - callHandlers(); - }; - } - if (!_eventsCount) { - RegisterPendingObservable(&this->_callHandlers); - } - ++_eventsCount; - } - } - - ~ObservableData() { - UnregisterObservable(&this->_callHandlers); - } - -private: - void callHandlers() { - _handling = true; - auto eventsCount = base::take(_eventsCount); - for (int i = 0; i != eventsCount; ++i) { - this->notifyEnumerate([this]() { - this->_current->handler(); - }); - if (this->destroyMeIfEmpty()) { - return; - } - } - _handling = false; - UnregisterActiveObservable(&this->_callHandlers); - } - - int _eventsCount = 0; - bool _handling = false; - -}; - -template -class BaseObservable::is_fast_copy_type::value> : public internal::CommonObservable { -public: - void notify(bool sync = false) { - if (this->_data) { - this->_data->notify(sync); - } - } - -}; - -} // namespace internal - -template > -class Observable : public internal::BaseObservable::is_fast_copy_type::value> { -public: - Observable() = default; - Observable(const Observable &other) = delete; - Observable(Observable &&other) = default; - Observable &operator=(const Observable &other) = delete; - Observable &operator=(Observable &&other) = default; - -}; - -template -class Variable { -public: - Variable(parameter_type startValue = Type()) : _value(startValue) { - } - Variable(Variable &&other) = default; - Variable &operator=(Variable &&other) = default; - - parameter_type value() const { - return _value; - } - - void setForced(parameter_type newValue, bool sync = false) { - _value = newValue; - changed().notify(_value, sync); - } - - void set(parameter_type newValue, bool sync = false) { - if (_value != newValue) { - setForced(newValue, sync); - } - } - - template - void process(Callback callback, bool sync = false) { - callback(_value); - changed().notify(_value, sync); - } - - Observable &changed() const { - return _changed; - } - -private: - Type _value; - mutable Observable _changed; - -}; - -class Subscriber { -protected: - template - int subscribe(base::Observable &observable, Lambda &&handler) { - _subscriptions.push_back(observable.add_subscription(std::forward(handler))); - return _subscriptions.size(); - } - - template - int subscribe(base::Observable *observable, Lambda &&handler) { - return subscribe(*observable, std::forward(handler)); - } - - template - int subscribe(const base::Variable &variable, Lambda &&handler) { - return subscribe(variable.changed(), std::forward(handler)); - } - - template - int subscribe(const base::Variable *variable, Lambda &&handler) { - return subscribe(variable->changed(), std::forward(handler)); - } - - void unsubscribe(int index) { - if (!index) return; - auto count = static_cast(_subscriptions.size()); - Assert(index > 0 && index <= count); - _subscriptions[index - 1].destroy(); - if (index == count) { - while (index > 0 && !_subscriptions[--index]) { - _subscriptions.pop_back(); - } - } - } - - ~Subscriber() { - auto subscriptions = base::take(_subscriptions); - for (auto &subscription : subscriptions) { - subscription.destroy(); - } - } - -private: - std::vector _subscriptions; - -}; - -void InitObservables(void(*HandleDelayed)()); -void HandleObservables(); - -template < - typename Type, - typename = std::enable_if_t>> -inline auto ObservableViewer(base::Observable &observable) { - return rpl::make_producer([&observable]( - const auto &consumer) { - auto lifetime = rpl::lifetime(); - lifetime.make_state( - observable.add_subscription([consumer](auto &&update) { - consumer.put_next_forward( - std::forward(update)); - })); - return lifetime; - }); -} - -rpl::producer<> ObservableViewer(base::Observable &observable); - -} // namespace base diff --git a/Telegram/SourceFiles/base/openssl_help.h b/Telegram/SourceFiles/base/openssl_help.h deleted file mode 100644 index f9ca3ccfb..000000000 --- a/Telegram/SourceFiles/base/openssl_help.h +++ /dev/null @@ -1,577 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/bytes.h" -#include "base/algorithm.h" -#include "base/basic_types.h" - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -} // extern "C" - -#ifdef small -#undef small -#endif // small - -namespace openssl { - -class Context { -public: - Context() : _data(BN_CTX_new()) { - } - Context(const Context &other) = delete; - Context(Context &&other) : _data(base::take(other._data)) { - } - Context &operator=(const Context &other) = delete; - Context &operator=(Context &&other) { - _data = base::take(other._data); - return *this; - } - ~Context() { - if (_data) { - BN_CTX_free(_data); - } - } - - BN_CTX *raw() const { - return _data; - } - -private: - BN_CTX *_data = nullptr; - -}; - -class BigNum { -public: - BigNum() = default; - BigNum(const BigNum &other) - : _data((other.failed() || other.isZero()) - ? nullptr - : BN_dup(other.raw())) - , _failed(other._failed) { - } - BigNum(BigNum &&other) - : _data(std::exchange(other._data, nullptr)) - , _failed(std::exchange(other._failed, false)) { - } - BigNum &operator=(const BigNum &other) { - if (other.failed()) { - _failed = true; - } else if (other.isZero()) { - clear(); - _failed = false; - } else if (!_data) { - _data = BN_dup(other.raw()); - _failed = false; - } else { - _failed = !BN_copy(raw(), other.raw()); - } - return *this; - } - BigNum &operator=(BigNum &&other) { - std::swap(_data, other._data); - std::swap(_failed, other._failed); - return *this; - } - ~BigNum() { - clear(); - } - - explicit BigNum(unsigned int word) : BigNum() { - setWord(word); - } - explicit BigNum(bytes::const_span bytes) : BigNum() { - setBytes(bytes); - } - - BigNum &setWord(unsigned int word) { - if (!word) { - clear(); - _failed = false; - } else { - _failed = !BN_set_word(raw(), word); - } - return *this; - } - BigNum &setBytes(bytes::const_span bytes) { - if (bytes.empty()) { - clear(); - _failed = false; - } else { - _failed = !BN_bin2bn( - reinterpret_cast(bytes.data()), - bytes.size(), - raw()); - } - return *this; - } - - BigNum &setAdd(const BigNum &a, const BigNum &b) { - if (a.failed() || b.failed()) { - _failed = true; - } else { - _failed = !BN_add(raw(), a.raw(), b.raw()); - } - return *this; - } - BigNum &setSub(const BigNum &a, const BigNum &b) { - if (a.failed() || b.failed()) { - _failed = true; - } else { - _failed = !BN_sub(raw(), a.raw(), b.raw()); - } - return *this; - } - BigNum &setMul( - const BigNum &a, - const BigNum &b, - const Context &context = Context()) { - if (a.failed() || b.failed()) { - _failed = true; - } else { - _failed = !BN_mul(raw(), a.raw(), b.raw(), context.raw()); - } - return *this; - } - BigNum &setModAdd( - const BigNum &a, - const BigNum &b, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || b.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || b.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_add(raw(), a.raw(), b.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModSub( - const BigNum &a, - const BigNum &b, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || b.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || b.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_sub(raw(), a.raw(), b.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModMul( - const BigNum &a, - const BigNum &b, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || b.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || b.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_mul(raw(), a.raw(), b.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModInverse( - const BigNum &a, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_inverse(raw(), a.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModExp( - const BigNum &base, - const BigNum &power, - const BigNum &m, - const Context &context = Context()) { - if (base.failed() || power.failed() || m.failed()) { - _failed = true; - } else if (base.isNegative() || power.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_exp(raw(), base.raw(), power.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - - [[nodiscard]] bool isZero() const { - return !failed() && (!_data || BN_is_zero(raw())); - } - - [[nodiscard]] bool isOne() const { - return !failed() && _data && BN_is_one(raw()); - } - - [[nodiscard]] bool isNegative() const { - return !failed() && _data && BN_is_negative(raw()); - } - - [[nodiscard]] bool isPrime(const Context &context = Context()) const { - if (failed() || !_data) { - return false; - } - constexpr auto kMillerRabinIterationCount = 30; - const auto result = BN_is_prime_ex( - raw(), - kMillerRabinIterationCount, - context.raw(), - nullptr); - if (result == 1) { - return true; - } else if (result != 0) { - _failed = true; - } - return false; - } - - BigNum &subWord(unsigned int word) { - if (failed()) { - return *this; - } else if (!BN_sub_word(raw(), word)) { - _failed = true; - } - return *this; - } - BigNum &divWord(BN_ULONG word, BN_ULONG *mod = nullptr) { - Expects(word != 0); - - const auto result = failed() - ? (BN_ULONG)-1 - : BN_div_word(raw(), word); - if (result == (BN_ULONG)-1) { - _failed = true; - } - if (mod) { - *mod = result; - } - return *this; - } - [[nodiscard]] BN_ULONG countModWord(BN_ULONG word) const { - Expects(word != 0); - - return failed() ? (BN_ULONG)-1 : BN_mod_word(raw(), word); - } - - [[nodiscard]] int bitsSize() const { - return failed() ? 0 : BN_num_bits(raw()); - } - [[nodiscard]] int bytesSize() const { - return failed() ? 0 : BN_num_bytes(raw()); - } - - [[nodiscard]] bytes::vector getBytes() const { - if (failed()) { - return {}; - } - auto length = BN_num_bytes(raw()); - auto result = bytes::vector(length); - auto resultSize = BN_bn2bin( - raw(), - reinterpret_cast(result.data())); - Assert(resultSize == length); - return result; - } - - [[nodiscard]] BIGNUM *raw() { - if (!_data) _data = BN_new(); - return _data; - } - [[nodiscard]] const BIGNUM *raw() const { - if (!_data) _data = BN_new(); - return _data; - } - [[nodiscard]] BIGNUM *takeRaw() { - return _failed - ? nullptr - : _data - ? std::exchange(_data, nullptr) - : BN_new(); - } - - [[nodiscard]] bool failed() const { - return _failed; - } - - [[nodiscard]] static BigNum Add(const BigNum &a, const BigNum &b) { - return BigNum().setAdd(a, b); - } - [[nodiscard]] static BigNum Sub(const BigNum &a, const BigNum &b) { - return BigNum().setSub(a, b); - } - [[nodiscard]] static BigNum Mul( - const BigNum &a, - const BigNum &b, - const Context &context = Context()) { - return BigNum().setMul(a, b, context); - } - [[nodiscard]] static BigNum ModAdd( - const BigNum &a, - const BigNum &b, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModAdd(a, b, mod, context); - } - [[nodiscard]] static BigNum ModSub( - const BigNum &a, - const BigNum &b, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModSub(a, b, mod, context); - } - [[nodiscard]] static BigNum ModMul( - const BigNum &a, - const BigNum &b, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModMul(a, b, mod, context); - } - [[nodiscard]] static BigNum ModInverse( - const BigNum &a, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModInverse(a, mod, context); - } - [[nodiscard]] static BigNum ModExp( - const BigNum &base, - const BigNum &power, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModExp(base, power, mod, context); - } - [[nodiscard]] static BigNum Failed() { - auto result = BigNum(); - result._failed = true; - return result; - } - -private: - void clear() { - BN_clear_free(std::exchange(_data, nullptr)); - } - - mutable BIGNUM *_data = nullptr; - mutable bool _failed = false; - -}; - -namespace details { - -template -inline void ShaUpdate(Context context, Method method, Arg &&arg) { - const auto span = bytes::make_span(arg); - method(context, span.data(), span.size()); -} - -template -inline void ShaUpdate(Context context, Method method, Arg &&arg, Args &&...args) { - const auto span = bytes::make_span(arg); - method(context, span.data(), span.size()); - ShaUpdate(context, method, args...); -} - -template -inline bytes::vector Sha(Method method, bytes::const_span data) { - auto result = bytes::vector(Size); - method( - reinterpret_cast(data.data()), - data.size(), - reinterpret_cast(result.data())); - return result; -} - -template < - size_type Size, - typename Context, - typename Init, - typename Update, - typename Finalize, - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -bytes::vector Sha( - Context context, - Init init, - Update update, - Finalize finalize, - Args &&...args) { - auto result = bytes::vector(Size); - - init(&context); - ShaUpdate(&context, update, args...); - finalize(reinterpret_cast(result.data()), &context); - - return result; -} - -template < - size_type Size, - typename Evp> -bytes::vector Pbkdf2( - bytes::const_span password, - bytes::const_span salt, - int iterations, - Evp evp) { - auto result = bytes::vector(Size); - PKCS5_PBKDF2_HMAC( - reinterpret_cast(password.data()), - password.size(), - reinterpret_cast(salt.data()), - salt.size(), - iterations, - evp, - result.size(), - reinterpret_cast(result.data())); - return result; -} - -} // namespace details - -constexpr auto kSha1Size = size_type(SHA_DIGEST_LENGTH); -constexpr auto kSha256Size = size_type(SHA256_DIGEST_LENGTH); -constexpr auto kSha512Size = size_type(SHA512_DIGEST_LENGTH); - -inline bytes::vector Sha1(bytes::const_span data) { - return details::Sha(SHA1, data); -} - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -inline bytes::vector Sha1(Args &&...args) { - return details::Sha( - SHA_CTX(), - SHA1_Init, - SHA1_Update, - SHA1_Final, - args...); -} - -inline bytes::vector Sha256(bytes::const_span data) { - return details::Sha(SHA256, data); -} - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -inline bytes::vector Sha256(Args &&...args) { - return details::Sha( - SHA256_CTX(), - SHA256_Init, - SHA256_Update, - SHA256_Final, - args...); -} - -inline bytes::vector Sha512(bytes::const_span data) { - return details::Sha(SHA512, data); -} - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -inline bytes::vector Sha512(Args &&...args) { - return details::Sha( - SHA512_CTX(), - SHA512_Init, - SHA512_Update, - SHA512_Final, - args...); -} - -inline void AddRandomSeed(bytes::const_span data) { - RAND_seed(data.data(), data.size()); -} - -template >> -[[nodiscard]] inline T RandomValue() { - unsigned char buffer[sizeof(T)]; - if (!RAND_bytes(buffer, sizeof(T))) { - Unexpected("Could not generate random bytes!"); - } - auto result = T(); - memcpy(&result, buffer, sizeof(T)); - return result; -} - -inline bytes::vector Pbkdf2Sha512( - bytes::const_span password, - bytes::const_span salt, - int iterations) { - return details::Pbkdf2( - password, - salt, - iterations, - EVP_sha512()); -} - -inline bytes::vector HmacSha256( - bytes::const_span key, - bytes::const_span data) { - auto result = bytes::vector(kSha256Size); - auto length = (unsigned int)kSha256Size; - - HMAC( - EVP_sha256(), - key.data(), - key.size(), - reinterpret_cast(data.data()), - data.size(), - reinterpret_cast(result.data()), - &length); - - return result; -} - -} // namespace openssl - -namespace bytes { - -inline void set_random(span destination) { - RAND_bytes( - reinterpret_cast(destination.data()), - destination.size()); -} - -} // namespace bytes diff --git a/Telegram/SourceFiles/base/optional.h b/Telegram/SourceFiles/base/optional.h deleted file mode 100644 index 2628ee5bb..000000000 --- a/Telegram/SourceFiles/base/optional.h +++ /dev/null @@ -1,171 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "base/variant.h" - -namespace base { - -template -class optional_variant { -public: - optional_variant() : _impl(std::nullopt) { - } - optional_variant(const optional_variant &other) : _impl(other._impl) { - } - optional_variant(optional_variant &&other) : _impl(std::move(other._impl)) { - } - template >::value>> - optional_variant(T &&value) : _impl(std::forward(value)) { - } - optional_variant &operator=(const optional_variant &other) { - _impl = other._impl; - return *this; - } - optional_variant &operator=(optional_variant &&other) { - _impl = std::move(other._impl); - return *this; - } - template >::value>> - optional_variant &operator=(T &&value) { - _impl = std::forward(value); - return *this; - } - - bool has_value() const { - return !is(); - } - explicit operator bool() const { - return has_value(); - } - bool operator==(const optional_variant &other) const { - return _impl == other._impl; - } - bool operator!=(const optional_variant &other) const { - return _impl != other._impl; - } - bool operator<(const optional_variant &other) const { - return _impl < other._impl; - } - bool operator<=(const optional_variant &other) const { - return _impl <= other._impl; - } - bool operator>(const optional_variant &other) const { - return _impl > other._impl; - } - bool operator>=(const optional_variant &other) const { - return _impl >= other._impl; - } - - template - T &set(Args &&...args) { - _impl.template set(std::forward(args)...); - return get_unchecked(); - } - void clear() { - _impl.template set(); - } - - template - decltype(auto) is() const { - return _impl.template is(); - } - template - decltype(auto) get_unchecked() { - return _impl.template get_unchecked(); - } - template - decltype(auto) get_unchecked() const { - return _impl.template get_unchecked(); - } - - template - decltype(auto) match(Methods &&...methods) { - return base::match(_impl, std::forward(methods)...); - } - template - decltype(auto) match(Methods &&...methods) const { - return base::match(_impl, std::forward(methods)...); - } - -private: - variant _impl; - -}; - -template -inline T *get_if(optional_variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -template -inline const T *get_if(const optional_variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -template -inline decltype(auto) match( - optional_variant &value, - Methods &&...methods) { - return value.match(std::forward(methods)...); -} - -template -inline decltype(auto) match( - const optional_variant &value, - Methods &&...methods) { - return value.match(std::forward(methods)...); -} - -template -struct optional_wrap_once { - using type = std::optional; -}; - -template -struct optional_wrap_once> { - using type = std::optional; -}; - -template -using optional_wrap_once_t = typename optional_wrap_once>::type; - -template -struct optional_chain_result { - using type = optional_wrap_once_t; -}; - -template <> -struct optional_chain_result { - using type = bool; -}; - -template -using optional_chain_result_t = typename optional_chain_result::type; - -template -optional_wrap_once_t make_optional(Type &&value) { - return optional_wrap_once_t { std::forward(value) }; -} - -} // namespace base - -template -inline auto operator|(const std::optional &value, Method method) --> base::optional_chain_result_t { - if constexpr (std::is_same_v) { - return value ? (method(*value), true) : false; - } else { - return value - ? base::optional_chain_result_t( - method(*value)) - : std::nullopt; - } -} diff --git a/Telegram/SourceFiles/base/ordered_set.h b/Telegram/SourceFiles/base/ordered_set.h deleted file mode 100644 index f9ea222d7..000000000 --- a/Telegram/SourceFiles/base/ordered_set.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// ordered set template based on QMap -template -class OrderedSet { - struct NullType { - }; - using Self = OrderedSet; - using Impl = QMap; - using IteratorImpl = typename Impl::iterator; - using ConstIteratorImpl = typename Impl::const_iterator; - Impl impl_; - -public: - OrderedSet() = default; - OrderedSet(const OrderedSet &other) = default; - OrderedSet(OrderedSet &&other) = default; - OrderedSet &operator=(const OrderedSet &other) = default; - OrderedSet &operator=(OrderedSet &&other) = default; - ~OrderedSet() = default; - - inline bool operator==(const Self &other) const { return impl_ == other.impl_; } - inline bool operator!=(const Self &other) const { return impl_ != other.impl_; } - inline int size() const { return impl_.size(); } - inline bool isEmpty() const { return impl_.isEmpty(); } - inline void detach() { return impl_.detach(); } - inline bool isDetached() const { return impl_.isDetached(); } - inline void clear() { return impl_.clear(); } - inline QList values() const { return impl_.keys(); } - inline const T &first() const { return impl_.firstKey(); } - inline const T &last() const { return impl_.lastKey(); } - - class const_iterator; - class iterator { - public: - typedef typename IteratorImpl::iterator_category iterator_category; - typedef typename IteratorImpl::difference_type difference_type; - typedef T value_type; - typedef T *pointer; - typedef T &reference; - - iterator() = default; - iterator(const iterator &other) = default; - iterator &operator=(const iterator &other) = default; - inline const T &operator*() const { return impl_.key(); } - inline const T *operator->() const { return &impl_.key(); } - inline bool operator==(const iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; } - inline iterator &operator++() { ++impl_; return *this; } - inline iterator operator++(int) { return iterator(impl_++); } - inline iterator &operator--() { --impl_; return *this; } - inline iterator operator--(int) { return iterator(impl_--); } - inline iterator operator+(int j) const { return iterator(impl_ + j); } - inline iterator operator-(int j) const { return iterator(impl_ - j); } - inline iterator &operator+=(int j) { impl_ += j; return *this; } - inline iterator &operator-=(int j) { impl_ -= j; return *this; } - - friend class const_iterator; - inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; } - - private: - explicit iterator(const IteratorImpl &impl) : impl_(impl) { - } - IteratorImpl impl_; - friend class OrderedSet; - - }; - friend class iterator; - - class const_iterator { - public: - typedef typename IteratorImpl::iterator_category iterator_category; - typedef typename IteratorImpl::difference_type difference_type; - typedef T value_type; - typedef T *pointer; - typedef T &reference; - - const_iterator() = default; - const_iterator(const const_iterator &other) = default; - const_iterator &operator=(const const_iterator &other) = default; - const_iterator(const iterator &other) : impl_(other.impl_) { - } - const_iterator &operator=(const iterator &other) { - impl_ = other.impl_; - return *this; - } - inline const T &operator*() const { return impl_.key(); } - inline const T *operator->() const { return &impl_.key(); } - inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; } - inline const_iterator &operator++() { ++impl_; return *this; } - inline const_iterator operator++(int) { return const_iterator(impl_++); } - inline const_iterator &operator--() { --impl_; return *this; } - inline const_iterator operator--(int) { return const_iterator(impl_--); } - inline const_iterator operator+(int j) const { return const_iterator(impl_ + j); } - inline const_iterator operator-(int j) const { return const_iterator(impl_ - j); } - inline const_iterator &operator+=(int j) { impl_ += j; return *this; } - inline const_iterator &operator-=(int j) { impl_ -= j; return *this; } - - friend class iterator; - inline bool operator==(const iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; } - - private: - explicit const_iterator(const ConstIteratorImpl &impl) : impl_(impl) { - } - ConstIteratorImpl impl_; - friend class OrderedSet; - - }; - friend class const_iterator; - - // STL style - inline iterator begin() { return iterator(impl_.begin()); } - inline const_iterator begin() const { return const_iterator(impl_.cbegin()); } - inline const_iterator constBegin() const { return const_iterator(impl_.cbegin()); } - inline const_iterator cbegin() const { return const_iterator(impl_.cbegin()); } - inline iterator end() { detach(); return iterator(impl_.end()); } - inline const_iterator end() const { return const_iterator(impl_.cend()); } - inline const_iterator constEnd() const { return const_iterator(impl_.cend()); } - inline const_iterator cend() const { return const_iterator(impl_.cend()); } - inline iterator erase(iterator it) { return iterator(impl_.erase(it.impl_)); } - - inline iterator insert(const T &value) { return iterator(impl_.insert(value, NullType())); } - inline iterator insert(const_iterator pos, const T &value) { return iterator(impl_.insert(pos.impl_, value, NullType())); } - inline int remove(const T &value) { return impl_.remove(value); } - inline bool contains(const T &value) const { return impl_.contains(value); } - - // more Qt - typedef iterator Iterator; - typedef const_iterator ConstIterator; - inline int count() const { return impl_.count(); } - inline iterator find(const T &value) { return iterator(impl_.find(value)); } - inline const_iterator find(const T &value) const { return const_iterator(impl_.constFind(value)); } - inline const_iterator constFind(const T &value) const { return const_iterator(impl_.constFind(value)); } - inline Self &unite(const Self &other) { impl_.unite(other.impl_); return *this; } - - // STL compatibility - typedef typename Impl::difference_type difference_type; - typedef typename Impl::size_type size_type; - inline bool empty() const { return impl_.empty(); } - -}; diff --git a/Telegram/SourceFiles/base/overload.h b/Telegram/SourceFiles/base/overload.h deleted file mode 100644 index 33e3acae3..000000000 --- a/Telegram/SourceFiles/base/overload.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { -namespace details { - -// This implementation was taken from range-v3 library. -// It was modified so that more than one of passed function objects -// could be called with an argument list and the first one that -// matches gets used instead of a compile-time ambiguity error. -// -// This allows to write "default" visitor handlers with [](auto&&) syntax. - -template -constexpr bool is_callable_v = rpl::details::is_callable_plain_v; - -template -struct overloaded; - -template <> -struct overloaded<> { -}; - -template -struct overloaded - : private First - , private overloaded { - -private: - using Others = overloaded; - -public: - overloaded() = default; - - constexpr overloaded(First first, Rest... rest) - : First(std::move(first)) - , Others(std::move(rest)...) { - } - - template - auto operator()(Args&&... args) - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - - template - auto operator()(Args&&... args) const - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - - template < - typename... Args, - typename = std::enable_if_t>> - auto operator()(Args&&... args) - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - - template < - typename... Args, - typename = std::enable_if_t>> - auto operator()(Args&&... args) const - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - -}; - -} // namespace details - -template -Function overload(Function &&function) { - return std::forward(function); -} - -template 1)>> -auto overload(Functions ...functions) { - return details::overloaded(std::move(functions)...); -} - -} // namespace base - diff --git a/Telegram/SourceFiles/base/parse_helper.cpp b/Telegram/SourceFiles/base/parse_helper.cpp deleted file mode 100644 index 52f1b12c0..000000000 --- a/Telegram/SourceFiles/base/parse_helper.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/parse_helper.h" - -namespace base { -namespace parse { - -// inspired by https://github.com/sindresorhus/strip-json-comments -QByteArray stripComments(const QByteArray &content) { - enum class InsideComment { - None, - SingleLine, - MultiLine, - }; - auto insideComment = InsideComment::None; - auto insideString = false; - - QByteArray result; - auto begin = content.cbegin(), end = content.cend(), offset = begin; - auto feedContent = [&result, &offset, end](const char *ch) { - if (ch > offset) { - if (result.isEmpty()) result.reserve(end - offset - 2); - result.append(offset, ch - offset); - offset = ch; - } - }; - auto feedComment = [&result, &offset, end](const char *ch) { - if (ch > offset) { - if (result.isEmpty()) result.reserve(end - offset - 2); - result.append(' '); - offset = ch; - } - }; - for (auto ch = offset; ch != end;) { - auto currentChar = *ch; - auto nextChar = (ch + 1 == end) ? 0 : *(ch + 1); - - if (insideComment == InsideComment::None && currentChar == '"') { - auto escaped = ((ch > begin) && *(ch - 1) == '\\') && ((ch - 1 < begin) || *(ch - 2) != '\\'); - if (!escaped) { - insideString = !insideString; - } - } - if (insideString) { - ++ch; - continue; - } - - if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '/') { - feedContent(ch); - insideComment = InsideComment::SingleLine; - ch += 2; - } else if (insideComment == InsideComment::SingleLine && currentChar == '\r' && nextChar == '\n') { - feedComment(ch); - ch += 2; - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::SingleLine && currentChar == '\n') { - feedComment(ch); - ++ch; - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '*') { - feedContent(ch); - ch += 2; - insideComment = InsideComment::MultiLine; - } else if (insideComment == InsideComment::MultiLine && currentChar == '*' && nextChar == '/') { - ch += 2; - feedComment(ch); - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::MultiLine && currentChar == '\r' && nextChar == '\n') { - feedComment(ch); - ch += 2; - feedContent(ch); - } else if (insideComment == InsideComment::MultiLine && currentChar == '\n') { - feedComment(ch); - ++ch; - feedContent(ch); - } else { - ++ch; - } - } - - if (insideComment == InsideComment::MultiLine) { - // unexpected end of content - } - if (insideComment == InsideComment::None && end > offset) { - if (result.isEmpty()) { - return content; - } else { - result.append(offset, end - offset); - } - } - return result; -} - -} // namespace parse -} // namespace base diff --git a/Telegram/SourceFiles/base/parse_helper.h b/Telegram/SourceFiles/base/parse_helper.h deleted file mode 100644 index ce96690b0..000000000 --- a/Telegram/SourceFiles/base/parse_helper.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { -namespace parse { - -// Strip all C-style comments. -QByteArray stripComments(const QByteArray &content); - -inline bool skipWhitespaces(const char *&from, const char *end) { - Assert(from <= end); - while (from != end && ( - (*from == ' ') || - (*from == '\n') || - (*from == '\t') || - (*from == '\r'))) { - ++from; - } - return (from != end); -} - -inline QLatin1String readName(const char *&from, const char *end) { - Assert(from <= end); - auto start = from; - while (from != end && ( - (*from >= 'a' && *from <= 'z') || - (*from >= 'A' && *from <= 'Z') || - (*from >= '0' && *from <= '9') || - (*from == '_'))) { - ++from; - } - return QLatin1String(start, from - start); -} - -} // namespace parse -} // namespace base diff --git a/Telegram/SourceFiles/base/qt_connection.h b/Telegram/SourceFiles/base/qt_connection.h deleted file mode 100644 index 3fd5610c9..000000000 --- a/Telegram/SourceFiles/base/qt_connection.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/algorithm.h" - -#include - -namespace base { - -class qt_connection final { -public: - qt_connection(QMetaObject::Connection data = {}) : _data(data) { - } - qt_connection(qt_connection &&other) : _data(base::take(other._data)) { - } - qt_connection &operator=(qt_connection &&other) { - reset(base::take(other._data)); - return *this; - } - ~qt_connection() { - disconnect(); - } - - void release() { - _data = QMetaObject::Connection(); - } - void reset(QMetaObject::Connection data = {}) { - disconnect(); - _data = data; - } - -private: - void disconnect() { - if (_data) { - QObject::disconnect(base::take(_data)); - } - } - - QMetaObject::Connection _data; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/qt_signal_producer.h b/Telegram/SourceFiles/base/qt_signal_producer.h deleted file mode 100644 index 29a12a016..000000000 --- a/Telegram/SourceFiles/base/qt_signal_producer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/base_integration.h" - -namespace base { - -// This method allows to create an rpl::producer from a Qt object -// and a signal with none or one reported value. -// -// QtSignalProducer(qtWindow, &QWindow::activeChanged) | rpl::start_ -// -// This producer values construct a custom event loop leave point. -// This means that all postponeCall's will be invoked right after -// the value processing by the current consumer finishes. -template -auto qt_signal_producer(Object *object, Signal signal); - -namespace details { - -template -struct qt_signal_argument; - -template -struct qt_signal_argument { - using type = Value; -}; - -template -struct qt_signal_argument { - using type = void; -}; - -} // namespace details - -template -auto qt_signal_producer(Object *object, Signal signal) { - using Value = typename details::qt_signal_argument::type; - static constexpr auto NoArgument = std::is_same_v; - using Produced = std::conditional_t< - NoArgument, - rpl::empty_value, - std::remove_const_t>>; - const auto guarded = QPointer(object); - return rpl::make_producer([=](auto consumer) { - if (!guarded) { - return rpl::lifetime(); - } - const auto connect = [&](auto &&handler) { - const auto listener = new QObject(guarded.data()); - QObject::connect( - guarded, - signal, - listener, - std::forward(handler)); - const auto weak = QPointer(listener); - return rpl::lifetime([=] { - if (weak) { - delete weak; - } - }); - }; - auto put = [=](const Produced &value) { - EnterFromEventLoop([&] { - consumer.put_next_copy(value); - }); - }; - if constexpr (NoArgument) { - return connect([put = std::move(put)] { put({}); }); - } else { - return connect(std::move(put)); - } - }); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/qthelp_regex.h b/Telegram/SourceFiles/base/qthelp_regex.h deleted file mode 100644 index 09441a74e..000000000 --- a/Telegram/SourceFiles/base/qthelp_regex.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/flags.h" - -namespace qthelp { - -class RegularExpressionMatch { -public: - RegularExpressionMatch(const QRegularExpressionMatch &other) = delete; - RegularExpressionMatch(const RegularExpressionMatch &other) = delete; - RegularExpressionMatch(QRegularExpressionMatch &&match) : data_(std::move(match)) { - } - RegularExpressionMatch(RegularExpressionMatch &&other) : data_(std::move(other.data_)) { - } - RegularExpressionMatch &operator=(const QRegularExpressionMatch &match) = delete; - RegularExpressionMatch &operator=(const RegularExpressionMatch &other) = delete; - RegularExpressionMatch &operator=(QRegularExpressionMatch &&match) { - data_ = std::move(match); - return *this; - } - RegularExpressionMatch &operator=(RegularExpressionMatch &&other) { - data_ = std::move(other.data_); - return *this; - } - QRegularExpressionMatch *operator->() { - return &data_; - } - const QRegularExpressionMatch *operator->() const { - return &data_; - } - bool valid() const { - return data_.hasMatch(); - } - explicit operator bool() const { - return valid(); - } - -private: - QRegularExpressionMatch data_; - -}; - -enum class RegExOption { - None = QRegularExpression::NoPatternOption, - CaseInsensitive = QRegularExpression::CaseInsensitiveOption, - DotMatchesEverything = QRegularExpression::DotMatchesEverythingOption, - Multiline = QRegularExpression::MultilineOption, - ExtendedSyntax = QRegularExpression::ExtendedPatternSyntaxOption, - InvertedGreediness = QRegularExpression::InvertedGreedinessOption, - DontCapture = QRegularExpression::DontCaptureOption, - UseUnicodeProperties = QRegularExpression::UseUnicodePropertiesOption, -#ifndef OS_MAC_OLD - OptimizeOnFirstUsage = QRegularExpression::OptimizeOnFirstUsageOption, - DontAutomaticallyOptimize = QRegularExpression::DontAutomaticallyOptimizeOption, -#endif // OS_MAC_OLD -}; -using RegExOptions = base::flags; -inline constexpr auto is_flag_type(RegExOption) { return true; }; - -inline RegularExpressionMatch regex_match(const QString &string, const QString &subject, RegExOptions options = 0) { - auto qtOptions = QRegularExpression::PatternOptions(static_cast(options)); - return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subject)); -} - -inline RegularExpressionMatch regex_match(const QString &string, const QStringRef &subjectRef, RegExOptions options = 0) { - auto qtOptions = QRegularExpression::PatternOptions(static_cast(options)); -#ifndef OS_MAC_OLD - return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subjectRef)); -#else // OS_MAC_OLD - return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subjectRef.toString())); -#endif // OS_MAC_OLD -} - -} // namespace qthelp diff --git a/Telegram/SourceFiles/base/qthelp_url.cpp b/Telegram/SourceFiles/base/qthelp_url.cpp deleted file mode 100644 index 0cdc486f8..000000000 --- a/Telegram/SourceFiles/base/qthelp_url.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/qthelp_url.h" - -namespace qthelp { -namespace { - -QRegularExpression CreateRegExp(const QString &expression) { - auto result = QRegularExpression( - expression, - QRegularExpression::UseUnicodePropertiesOption); -#ifndef OS_MAC_OLD - result.optimize(); -#endif // OS_MAC_OLD - return result; -} - -QString ExpressionDomain() { - // Matches any domain name, containing at least one '.', including "file.txt". - return QString::fromUtf8("(? url_parse_params( - const QString ¶ms, - UrlParamNameTransform transform) { - auto result = QMap(); - - const auto transformParamName = [transform](const QString &name) { - if (transform == UrlParamNameTransform::ToLower) { - return name.toLower(); - } - return name; - }; - for (const auto ¶m : params.split('&')) { - // Skip params without a name (starting with '='). - if (auto separatorPosition = param.indexOf('=')) { - const auto paramName = transformParamName( - (separatorPosition > 0) - ? param.mid(0, separatorPosition) - : param); - const auto paramValue = (separatorPosition > 0) - ? url_decode(param.mid(separatorPosition + 1)) - : QString(); - if (!result.contains(paramName)) { - result.insert(paramName, paramValue); - } - } - } - return result; -} - -bool is_ipv6(const QString &ip) { - //static const auto regexp = QRegularExpression("^[a-fA-F0-9:]+$"); - //return regexp.match(ip).hasMatch(); - return ip.indexOf('.') < 0 && ip.indexOf(':') >= 0; -} - -QString url_append_query_or_hash(const QString &url, const QString &add) { - const auto query = url.lastIndexOf('?'); - if (query < 0) { - return url + '?' + add; - } - const auto hash = url.lastIndexOf('#'); - return url - + (query >= 0 && query > url.lastIndexOf('#') ? '&' : '?') - + add; -} - -QString validate_url(const QString &value) { - const auto trimmed = value.trimmed(); - if (trimmed.isEmpty()) { - return QString(); - } - const auto match = RegExpDomainExplicit().match(trimmed); - if (!match.hasMatch()) { - const auto domain = RegExpDomain().match(trimmed); - if (!domain.hasMatch() || domain.capturedStart() != 0) { - return QString(); - } - return qstr("http://") + trimmed; - } else if (match.capturedStart() != 0) { - return QString(); - } - const auto protocolMatch = RegExpProtocol().match(trimmed); - Assert(protocolMatch.hasMatch()); - return IsGoodProtocol(protocolMatch.captured(1)) ? trimmed : QString(); -} - -} // namespace qthelp diff --git a/Telegram/SourceFiles/base/qthelp_url.h b/Telegram/SourceFiles/base/qthelp_url.h deleted file mode 100644 index fd8e460be..000000000 --- a/Telegram/SourceFiles/base/qthelp_url.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include - -namespace qthelp { - -const QRegularExpression &RegExpDomain(); -const QRegularExpression &RegExpDomainExplicit(); -QRegularExpression RegExpProtocol(); - -inline QString url_encode(const QString &part) { - return QString::fromLatin1(QUrl::toPercentEncoding(part)); -} - -inline QString url_decode(const QString &encoded) { - return QUrl::fromPercentEncoding(encoded.toUtf8()); -} - -enum class UrlParamNameTransform { - NoTransform, - ToLower, -}; -// Parses a string like "p1=v1&p2=v2&..&pn=vn" to a map. -QMap url_parse_params( - const QString ¶ms, - UrlParamNameTransform transform = UrlParamNameTransform::NoTransform); - -QString url_append_query_or_hash(const QString &url, const QString &add); - -bool is_ipv6(const QString &ip); - -QString validate_url(const QString &value); - -} // namespace qthelp diff --git a/Telegram/SourceFiles/base/runtime_composer.cpp b/Telegram/SourceFiles/base/runtime_composer.cpp deleted file mode 100644 index eec3cdca3..000000000 --- a/Telegram/SourceFiles/base/runtime_composer.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/runtime_composer.h" - -struct RuntimeComposerMetadatasMap { - std::map> data; - QMutex mutex; -}; - -const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask) { - static RuntimeComposerMetadatasMap RuntimeComposerMetadatas; - - QMutexLocker lock(&RuntimeComposerMetadatas.mutex); - auto i = RuntimeComposerMetadatas.data.find(mask); - if (i == end(RuntimeComposerMetadatas.data)) { - i = RuntimeComposerMetadatas.data.emplace( - mask, - std::make_unique(mask)).first; - } - return i->second.get(); -} - -const RuntimeComposerMetadata *RuntimeComposerBase::ZeroRuntimeComposerMetadata = GetRuntimeComposerMetadata(0); - -RuntimeComponentWrapStruct RuntimeComponentWraps[64]; - -QAtomicInt RuntimeComponentIndexLast; diff --git a/Telegram/SourceFiles/base/runtime_composer.h b/Telegram/SourceFiles/base/runtime_composer.h deleted file mode 100644 index 461f3888e..000000000 --- a/Telegram/SourceFiles/base/runtime_composer.h +++ /dev/null @@ -1,279 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -template -class RuntimeComposer; - -class RuntimeComposerBase; -typedef void(*RuntimeComponentConstruct)(void *location, RuntimeComposerBase *composer); -typedef void(*RuntimeComponentDestruct)(void *location); -typedef void(*RuntimeComponentMove)(void *location, void *waslocation); - -struct RuntimeComponentWrapStruct { - // Don't init any fields, because it is only created in - // global scope, so it will be filled by zeros from the start. - RuntimeComponentWrapStruct() = default; - RuntimeComponentWrapStruct(std::size_t size, std::size_t align, RuntimeComponentConstruct construct, RuntimeComponentDestruct destruct, RuntimeComponentMove move) - : Size(size) - , Align(align) - , Construct(construct) - , Destruct(destruct) - , Move(move) { - } - std::size_t Size; - std::size_t Align; - RuntimeComponentConstruct Construct; - RuntimeComponentDestruct Destruct; - RuntimeComponentMove Move; -}; - -template -struct CeilDivideMinimumOne { - static constexpr int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0)); -}; - -extern RuntimeComponentWrapStruct RuntimeComponentWraps[64]; -extern QAtomicInt RuntimeComponentIndexLast; - -template -struct RuntimeComponent { - using RuntimeComponentBase = Base; - - RuntimeComponent() { - // While there is no std::aligned_alloc(). - static_assert(alignof(Type) <= alignof(std::max_align_t), "Components should align to std::max_align_t!"); - } - RuntimeComponent(const RuntimeComponent &other) = delete; - RuntimeComponent &operator=(const RuntimeComponent &other) = delete; - RuntimeComponent(RuntimeComponent &&other) = delete; - RuntimeComponent &operator=(RuntimeComponent &&other) = default; - - static int Index() { - static QAtomicInt MyIndex(0); - if (auto index = MyIndex.loadAcquire()) { - return index - 1; - } - while (true) { - auto last = RuntimeComponentIndexLast.loadAcquire(); - if (RuntimeComponentIndexLast.testAndSetOrdered(last, last + 1)) { - Assert(last < 64); - if (MyIndex.testAndSetOrdered(0, last + 1)) { - RuntimeComponentWraps[last] = RuntimeComponentWrapStruct( - sizeof(Type), - alignof(Type), - Type::RuntimeComponentConstruct, - Type::RuntimeComponentDestruct, - Type::RuntimeComponentMove); - } - break; - } - } - return MyIndex.loadAcquire() - 1; - } - static uint64 Bit() { - return (1ULL << Index()); - } - -protected: - static void RuntimeComponentConstruct(void *location, RuntimeComposerBase *composer) { - new (location) Type(); - } - static void RuntimeComponentDestruct(void *location) { - ((Type*)location)->~Type(); - } - static void RuntimeComponentMove(void *location, void *waslocation) { - *(Type*)location = std::move(*(Type*)waslocation); - } - -}; - -class RuntimeComposerMetadata { -public: - RuntimeComposerMetadata(uint64 mask) : _mask(mask) { - for (int i = 0; i != 64; ++i) { - auto componentBit = (1ULL << i); - if (_mask & componentBit) { - auto componentSize = RuntimeComponentWraps[i].Size; - if (componentSize) { - auto componentAlign = RuntimeComponentWraps[i].Align; - if (auto badAlign = (size % componentAlign)) { - size += (componentAlign - badAlign); - } - offsets[i] = size; - size += componentSize; - accumulate_max(align, componentAlign); - } - } else if (_mask < componentBit) { - last = i; - break; - } - } - } - - // Meta pointer in the start. - std::size_t size = sizeof(const RuntimeComposerMetadata*); - std::size_t align = alignof(const RuntimeComposerMetadata*); - std::size_t offsets[64] = { 0 }; - int last = 64; - - bool equals(uint64 mask) const { - return _mask == mask; - } - uint64 maskadd(uint64 mask) const { - return _mask | mask; - } - uint64 maskremove(uint64 mask) const { - return _mask & (~mask); - } - -private: - uint64 _mask; - -}; - -const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask); - -class RuntimeComposerBase { -public: - RuntimeComposerBase(uint64 mask = 0) : _data(zerodata()) { - if (mask) { - auto meta = GetRuntimeComposerMetadata(mask); - - auto data = operator new(meta->size); - Assert(data != nullptr); - - _data = data; - _meta() = meta; - for (int i = 0; i < meta->last; ++i) { - auto offset = meta->offsets[i]; - if (offset >= sizeof(_meta())) { - try { - auto constructAt = _dataptrunsafe(offset); - auto space = RuntimeComponentWraps[i].Size; - auto alignedAt = constructAt; - std::align(RuntimeComponentWraps[i].Align, space, alignedAt, space); - Assert(alignedAt == constructAt); - RuntimeComponentWraps[i].Construct(constructAt, this); - } catch (...) { - while (i > 0) { - --i; - offset = meta->offsets[--i]; - if (offset >= sizeof(_meta())) { - RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset)); - } - } - throw; - } - } - } - } - } - RuntimeComposerBase(const RuntimeComposerBase &other) = delete; - RuntimeComposerBase &operator=(const RuntimeComposerBase &other) = delete; - ~RuntimeComposerBase() { - if (_data != zerodata()) { - auto meta = _meta(); - for (int i = 0; i < meta->last; ++i) { - auto offset = meta->offsets[i]; - if (offset >= sizeof(_meta())) { - RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset)); - } - } - operator delete(_data); - } - } - -protected: - bool UpdateComponents(uint64 mask = 0) { - if (_meta()->equals(mask)) { - return false; - } - RuntimeComposerBase result(mask); - result.swap(*this); - if (_data != zerodata() && result._data != zerodata()) { - const auto meta = _meta(); - const auto wasmeta = result._meta(); - for (auto i = 0; i != meta->last; ++i) { - const auto offset = meta->offsets[i]; - const auto wasoffset = wasmeta->offsets[i]; - if (offset >= sizeof(_meta()) - && wasoffset >= sizeof(_meta())) { - RuntimeComponentWraps[i].Move( - _dataptrunsafe(offset), - result._dataptrunsafe(wasoffset)); - } - } - } - return true; - } - bool AddComponents(uint64 mask = 0) { - return UpdateComponents(_meta()->maskadd(mask)); - } - bool RemoveComponents(uint64 mask = 0) { - return UpdateComponents(_meta()->maskremove(mask)); - } - -private: - template - friend class RuntimeComposer; - - static const RuntimeComposerMetadata *ZeroRuntimeComposerMetadata; - static void *zerodata() { - return &ZeroRuntimeComposerMetadata; - } - - void *_dataptrunsafe(int skip) const { - return (char*)_data + skip; - } - void *_dataptr(int skip) const { - return (skip >= sizeof(_meta())) ? _dataptrunsafe(skip) : nullptr; - } - const RuntimeComposerMetadata *&_meta() const { - return *static_cast(_data); - } - void *_data = nullptr; - - void swap(RuntimeComposerBase &other) { - std::swap(_data, other._data); - } - -}; - -template -class RuntimeComposer : public RuntimeComposerBase { -public: - using RuntimeComposerBase::RuntimeComposerBase; - - template < - typename Type, - typename = std::enable_if_t>> - bool Has() const { - return (_meta()->offsets[Type::Index()] >= sizeof(_meta())); - } - - template < - typename Type, - typename = std::enable_if_t>> - Type *Get() { - return static_cast(_dataptr(_meta()->offsets[Type::Index()])); - } - template < - typename Type, - typename = std::enable_if_t>> - const Type *Get() const { - return static_cast(_dataptr(_meta()->offsets[Type::Index()])); - } - -}; diff --git a/Telegram/SourceFiles/base/tests_main.cpp b/Telegram/SourceFiles/base/tests_main.cpp deleted file mode 100644 index fbdcb56fe..000000000 --- a/Telegram/SourceFiles/base/tests_main.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#define CATCH_CONFIG_RUNNER -#include "catch.hpp" -#include "reporters/catch_reporter_compact.hpp" -#include - -int (*TestForkedMethod)()/* = nullptr*/; - -namespace base { -namespace assertion { - -// For Assert() / Expects() / Ensures() / Unexpected() to work. -void log(const char *message, const char *file, int line) { - std::cout << message << " (" << file << ":" << line << ")" << std::endl; -} - -} // namespace assertion -} // namespace base - -namespace Catch { - - struct MinimalReporter : CompactReporter { - MinimalReporter( ReporterConfig const& _config ) - : CompactReporter( _config ) - {} - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - } - - private: - // Colour, message variants: - // - white: No tests ran. - // - red: Failed [both/all] N test cases, failed [both/all] M assertions. - // - white: Passed [both/all] N test cases (no assertions). - // - red: Failed N tests cases, failed M assertions. - // - green: Passed [both/all] N tests cases with M assertions. - - std::string bothOrAll( std::size_t count ) const { - return count == 1 ? std::string() : count == 2 ? "both " : "all " ; - } - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - } - else if( totals.testCases.failed == totals.testCases.total() ) { - Colour colour( Colour::ResultError ); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll( totals.assertions.failed ) : std::string(); - stream << - "Failed " << bothOrAll( totals.testCases.failed ) - << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << qualify_assertions_failed << - pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else if( totals.assertions.total() == 0 ) { - stream << - "Passed " << bothOrAll( totals.testCases.total() ) - << pluralise( totals.testCases.total(), "test case" ) - << " (no assertions)."; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - stream << - "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else { - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "minimal", MinimalReporter ) - -} // end namespace Catch - -int main(int argc, const char *argv[]) { - auto touchFile = QString(); - for (auto i = 0; i != argc; ++i) { - if (argv[i] == QString("--touch") && i + 1 != argc) { - touchFile = QFile::decodeName(argv[++i]); - } else if (argv[i] == QString("--forked") && TestForkedMethod) { - return TestForkedMethod(); - } - } - const char *catch_argv[] = { - argv[0], - touchFile.isEmpty() ? "-b" : "-r", - touchFile.isEmpty() ? "-b" : "minimal" }; - constexpr auto catch_argc = sizeof(catch_argv) / sizeof(catch_argv[0]); - auto result = Catch::Session().run(catch_argc, catch_argv); - if (result == 0 && !touchFile.isEmpty()) { - QFile(touchFile).open(QIODevice::WriteOnly); - } - return (result < 0xff ? result : 0xff); -} - diff --git a/Telegram/SourceFiles/base/thread_safe_wrap.h b/Telegram/SourceFiles/base/thread_safe_wrap.h deleted file mode 100644 index 6d97151c7..000000000 --- a/Telegram/SourceFiles/base/thread_safe_wrap.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -class thread_safe_wrap { -public: - template - thread_safe_wrap(Args &&...args) : _value(std::forward(args)...) { - } - - template - auto with(Callback &&callback) { - QMutexLocker lock(&_mutex); - return callback(_value); - } - - template - auto with(Callback &&callback) const { - QMutexLocker lock(&_mutex); - return callback(_value); - } - -private: - T _value; - QMutex _mutex; - -}; - -template typename Container = std::deque> -class thread_safe_queue { -public: - template - void emplace(Args &&...args) { - _wrap.with([&](Container &value) { - value.emplace_back(std::forward(args)...); - }); - } - - Container take() { - return _wrap.with([&](Container &value) { - return std::exchange(value, Container()); - }); - } - -private: - thread_safe_wrap> _wrap; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/timer.cpp b/Telegram/SourceFiles/base/timer.cpp deleted file mode 100644 index 00204ad43..000000000 --- a/Telegram/SourceFiles/base/timer.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/timer.h" - -#include - -namespace base { -namespace { - -QObject *TimersAdjuster() { - static QObject adjuster; - return &adjuster; -} - -} // namespace - -Timer::Timer( - not_null thread, - Fn callback) -: Timer(std::move(callback)) { - moveToThread(thread); -} - -Timer::Timer(Fn callback) -: QObject(nullptr) -, _callback(std::move(callback)) -, _type(Qt::PreciseTimer) -, _adjusted(false) { - setRepeat(Repeat::Interval); - connect( - TimersAdjuster(), - &QObject::destroyed, - this, - [this] { adjust(); }, - Qt::QueuedConnection); -} - -void Timer::start(crl::time timeout, Qt::TimerType type, Repeat repeat) { - cancel(); - - _type = type; - setRepeat(repeat); - _adjusted = false; - setTimeout(timeout); - _timerId = startTimer(_timeout, _type); - if (_timerId) { - _next = crl::now() + _timeout; - } else { - _next = 0; - } -} - -void Timer::cancel() { - if (isActive()) { - killTimer(base::take(_timerId)); - } -} - -crl::time Timer::remainingTime() const { - if (!isActive()) { - return -1; - } - const auto now = crl::now(); - return (_next > now) ? (_next - now) : crl::time(0); -} - -void Timer::Adjust() { - QObject emitter; - connect( - &emitter, - &QObject::destroyed, - TimersAdjuster(), - &QObject::destroyed); -} - -void Timer::adjust() { - auto remaining = remainingTime(); - if (remaining >= 0) { - cancel(); - _timerId = startTimer(remaining, _type); - _adjusted = true; - } -} - -void Timer::setTimeout(crl::time timeout) { - Expects(timeout >= 0 && timeout <= std::numeric_limits::max()); - - _timeout = static_cast(timeout); -} - -int Timer::timeout() const { - return _timeout; -} - -void Timer::timerEvent(QTimerEvent *e) { - if (repeat() == Repeat::Interval) { - if (_adjusted) { - start(_timeout, _type, repeat()); - } else { - _next = crl::now() + _timeout; - } - } else { - cancel(); - } - - if (const auto onstack = _callback) { - onstack(); - } -} - -int DelayedCallTimer::call( - crl::time timeout, - FnMut callback, - Qt::TimerType type) { - Expects(timeout >= 0); - - if (!callback) { - return 0; - } - auto timerId = startTimer(static_cast(timeout), type); - if (timerId) { - _callbacks.emplace(timerId, std::move(callback)); - } - return timerId; -} - -void DelayedCallTimer::cancel(int callId) { - if (callId) { - killTimer(callId); - _callbacks.remove(callId); - } -} - -void DelayedCallTimer::timerEvent(QTimerEvent *e) { - auto timerId = e->timerId(); - killTimer(timerId); - - auto it = _callbacks.find(timerId); - if (it != _callbacks.end()) { - auto callback = std::move(it->second); - _callbacks.erase(it); - - callback(); - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/timer.h b/Telegram/SourceFiles/base/timer.h deleted file mode 100644 index 8ed2b3bb3..000000000 --- a/Telegram/SourceFiles/base/timer.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "base/flat_map.h" - -#include - -namespace base { - -class Timer final : private QObject { -public: - explicit Timer( - not_null thread, - Fn callback = nullptr); - explicit Timer(Fn callback = nullptr); - - static Qt::TimerType DefaultType(crl::time timeout) { - constexpr auto kThreshold = crl::time(1000); - return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer; - } - - void setCallback(Fn callback) { - _callback = std::move(callback); - } - - void callOnce(crl::time timeout) { - callOnce(timeout, DefaultType(timeout)); - } - - void callEach(crl::time timeout) { - callEach(timeout, DefaultType(timeout)); - } - - void callOnce(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::SingleShot); - } - - void callEach(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::Interval); - } - - bool isActive() const { - return (_timerId != 0); - } - - void cancel(); - crl::time remainingTime() const; - - static void Adjust(); - -protected: - void timerEvent(QTimerEvent *e) override; - -private: - enum class Repeat : unsigned { - Interval = 0, - SingleShot = 1, - }; - void start(crl::time timeout, Qt::TimerType type, Repeat repeat); - void adjust(); - - void setTimeout(crl::time timeout); - int timeout() const; - - void setRepeat(Repeat repeat) { - _repeat = static_cast(repeat); - } - Repeat repeat() const { - return static_cast(_repeat); - } - - Fn _callback; - crl::time _next = 0; - int _timeout = 0; - int _timerId = 0; - - Qt::TimerType _type : 2; - bool _adjusted : 1; - unsigned _repeat : 1; - -}; - -class DelayedCallTimer final : private QObject { -public: - int call(crl::time timeout, FnMut callback) { - return call( - timeout, - std::move(callback), - Timer::DefaultType(timeout)); - } - - int call( - crl::time timeout, - FnMut callback, - Qt::TimerType type); - void cancel(int callId); - -protected: - void timerEvent(QTimerEvent *e) override; - -private: - base::flat_map> _callbacks; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/type_traits.h b/Telegram/SourceFiles/base/type_traits.h deleted file mode 100644 index f322d4992..000000000 --- a/Telegram/SourceFiles/base/type_traits.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { - -template -struct custom_is_fast_copy_type : public std::false_type { -}; -// To make your own type a fast copy type just write: -// template <> -// struct base::custom_is_fast_copy_type : public std::true_type { -// }; - -namespace internal { - -template -struct type_list_contains; - -template -struct type_list_contains : public std::false_type { -}; - -template -struct type_list_contains : public std::integral_constant::value || type_list_contains::value> { -}; - -template -using is_std_unsigned_int = type_list_contains; - -template -using is_std_signed_int = type_list_contains; - -template -using is_std_integral = std::integral_constant::value || is_std_signed_int::value || type_list_contains::value>; - -template -using is_std_float = type_list_contains; - -template -using is_std_arith = std::integral_constant::value || is_std_float::value>; - -template -using is_std_fundamental = std::integral_constant::value || std::is_same::value>; - -template -struct is_pointer : public std::false_type { -}; - -template -struct is_pointer : public std::true_type { -}; - -template -struct is_member_pointer : public std::false_type { -}; - -template -struct is_member_pointer : public std::true_type { -}; - -template -using is_fast_copy_type = std::integral_constant::value || is_pointer::value || is_member_pointer::value || custom_is_fast_copy_type::value>; - -template -struct add_const_reference { - using type = const T &; -}; - -template <> -struct add_const_reference { - using type = void; -}; - -template -using add_const_reference_t = typename add_const_reference::type; - -template -struct remove_pointer { - using type = T; -}; - -template -struct remove_pointer { - using type = T; -}; - -template -using remove_pointer_t = typename remove_pointer::type; - -} // namespace internal - -template -struct type_traits { - using is_std_unsigned_int = internal::is_std_unsigned_int; - using is_std_signed_int = internal::is_std_signed_int; - using is_std_integral = internal::is_std_integral; - using is_std_float = internal::is_std_float; - using is_std_arith = internal::is_std_arith; - using is_std_fundamental = internal::is_std_fundamental; - using is_pointer = internal::is_pointer; - using is_member_pointer = internal::is_member_pointer; - using is_fast_copy_type = internal::is_fast_copy_type; - - using parameter_type = std::conditional_t>; - using pointed_type = internal::remove_pointer_t; -}; - -template -using parameter_type = typename type_traits::parameter_type; - -} // namespace base diff --git a/Telegram/SourceFiles/base/unique_any.h b/Telegram/SourceFiles/base/unique_any.h deleted file mode 100644 index c7ff4ea44..000000000 --- a/Telegram/SourceFiles/base/unique_any.h +++ /dev/null @@ -1,230 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { -namespace details { - -template -struct moveable_as_copyable_wrap { - moveable_as_copyable_wrap(Value &&other) - : value(std::move(other)) { - } - moveable_as_copyable_wrap &operator=(Value &&other) { - value = std::move(other); - return *this; - } - moveable_as_copyable_wrap(moveable_as_copyable_wrap &&other) - : value(std::move(other.value)) { - } - moveable_as_copyable_wrap( - const moveable_as_copyable_wrap &other) { - Unexpected("Attempt to copy-construct a move-only type."); - } - moveable_as_copyable_wrap &operator=( - moveable_as_copyable_wrap &&other) { - value = std::move(other.value); - return *this; - } - moveable_as_copyable_wrap &operator=( - const moveable_as_copyable_wrap &other) { - Unexpected("Attempt to copy-assign a move-only type."); - } - - Value value; - -}; - -template < - typename Value, - typename = std::enable_if_t< - std::is_move_constructible_v> - && !std::is_lvalue_reference_v>> -auto wrap_moveable_as_copyable(Value &&value) { - return moveable_as_copyable_wrap(std::move(value)); -} - -} // namespace details - -class unique_any; - -template -Value *any_cast(unique_any *value) noexcept; - -template -const Value *any_cast(const unique_any *value) noexcept; - -class unique_any final { -public: - // Construction and destruction [any.cons] - constexpr unique_any() noexcept { - } - - unique_any(const unique_any &other) = delete; - unique_any &operator=(const unique_any &other) = delete; - - unique_any(unique_any &&other) noexcept - : _impl(std::move(other._impl)) { - } - - unique_any &operator=(unique_any &&other) noexcept { - _impl = std::move(other._impl); - return *this; - } - - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any>>> - unique_any(Value &&other) - : unique_any( - std::forward(other), - std::is_copy_constructible>()) { - } - - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any>>> - unique_any &operator=(Value &&other) { - if constexpr (std::is_copy_constructible_v>) { - _impl = std::forward(other); - } else if constexpr (std::is_move_constructible_v> - && !std::is_lvalue_reference_v) { - _impl = details::wrap_moveable_as_copyable(std::move(other)); - } else { - static_assert( - false_t(Value{}), - "Bad value for base::unique_any."); - } - return *this; - } - - template < - typename Value, - typename ...Args, - typename = std::enable_if_t< - std::is_constructible_v, Args...> - && std::is_copy_constructible_v>>> - std::decay_t &emplace(Args &&...args) { - return _impl.emplace(std::forward(args)...); - } - - void reset() noexcept { - _impl.reset(); - } - - void swap(unique_any &other) noexcept { - _impl.swap(other._impl); - } - - bool has_value() const noexcept { - return _impl.has_value(); - } - - // Should check if it is a moveable_only wrap first. - //const std::type_info &type() const noexcept { - // return _impl.type(); - //} - -private: - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any> - && std::is_copy_constructible_v>>> - unique_any(Value &&other, std::true_type) - : _impl(std::forward(other)) { - } - - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any> - && !std::is_copy_constructible_v> - && std::is_move_constructible_v> - && !std::is_lvalue_reference_v>> - unique_any(Value &&other, std::false_type) - : _impl(details::wrap_moveable_as_copyable(std::move(other))) { - } - - template < - typename Value, - typename ...Args> - friend unique_any make_any(Args &&...args); - - template - friend const Value *any_cast(const unique_any *value) noexcept; - - template - friend Value *any_cast(unique_any *value) noexcept; - - std::any _impl; - -}; - -inline void swap(unique_any &a, unique_any &b) noexcept { - a.swap(b); -} - -template < - typename Value, - typename ...Args> -inline auto make_any(Args &&...args) --> std::enable_if_t< - std::is_copy_constructible_v>, - unique_any> { - return std::make_any(std::forward(args)...); -} - -template < - typename Value, - typename ...Args> -inline auto make_any(Args &&...args) --> std::enable_if_t< - !std::is_copy_constructible_v> - && std::is_move_constructible_v>, - unique_any> { - return Value(std::forward(args)...); -} - -template -inline Value *any_cast(unique_any *value) noexcept { - if constexpr (std::is_copy_constructible_v) { - return std::any_cast(&value->_impl); - } else if constexpr (std::is_move_constructible_v) { - auto wrap = std::any_cast< - details::moveable_as_copyable_wrap - >(&value->_impl); - return wrap ? &wrap->value : nullptr; - } else { - static_assert( - false_t(Value{}), - "Bad type for base::any_cast."); - } -} - -template -inline const Value *any_cast(const unique_any *value) noexcept { - if constexpr (std::is_copy_constructible_v) { - return std::any_cast(&value->_impl); - } else if constexpr (std::is_move_constructible_v) { - auto wrap = std::any_cast< - details::moveable_as_copyable_wrap - >(&value->_impl); - return wrap ? &wrap->value : nullptr; - } else { - static_assert( - false_t(Value{}), - "Bad type for base::any_cast."); - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/unique_function.h b/Telegram/SourceFiles/base/unique_function.h deleted file mode 100644 index f1911be27..000000000 --- a/Telegram/SourceFiles/base/unique_function.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -#ifndef Unexpected -#define Unexpected(message) std::abort() -#define UniqueFunctionUnexpected -#endif // Unexpected - -namespace base { -namespace details { - -template -class moveable_callable_wrap { -public: - static_assert( - std::is_move_constructible_v, - "Should be at least moveable."); - - moveable_callable_wrap(Callable &&other) - : _value(std::move(other)) { - } - moveable_callable_wrap &operator=(Callable &&other) { - _value = std::move(other); - return *this; - } - moveable_callable_wrap(moveable_callable_wrap &&other) - : _value(std::move(other._value)) { - } - moveable_callable_wrap( - const moveable_callable_wrap &other) - : _value(fail_construct()) { - } - moveable_callable_wrap &operator=( - moveable_callable_wrap &&other) { - _value = std::move(other._value); - return *this; - } - moveable_callable_wrap &operator=( - const moveable_callable_wrap &other) { - return fail_assign(); - } - - template - decltype(auto) operator()(Args &&...args) { - return _value(std::forward(args)...); - } - -private: - [[noreturn]] Callable fail_construct() { - Unexpected("Attempt to copy-construct a move-only type."); - } - [[noreturn]] moveable_callable_wrap &fail_assign() { - Unexpected("Attempt to copy-assign a move-only type."); - } - - Callable _value; - -}; - -} // namespace details - -template -class unique_function; - -template -class unique_function final { -public: - unique_function(std::nullptr_t = nullptr) noexcept { - } - unique_function(const unique_function &other) = delete; - unique_function &operator=(const unique_function &other) = delete; - - // Move construct / assign from the same type. - unique_function(unique_function &&other) - : _impl(std::move(other._impl)) { - } - unique_function &operator=(unique_function &&other) { - _impl = std::move(other._impl); - return *this; - } - - template < - typename Callable, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - std::declval()...)), - Return>>> - unique_function(Callable &&other) - : unique_function( - std::forward(other), - std::is_copy_constructible>{}) { - } - - template < - typename Callable, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - std::declval()...)), - Return>>> - unique_function &operator=(Callable &&other) { - using Decayed = std::decay_t; - if constexpr (std::is_copy_constructible_v) { - _impl = std::forward(other); - } else if constexpr (std::is_move_constructible_v) { - _impl = details::moveable_callable_wrap( - std::forward(other)); - } else { - static_assert(false_t(other), "Should be moveable."); - } - return *this; - } - - void swap(unique_function &other) { - _impl.swap(other._impl); - } - - Return operator()(Args ...args) { - return _impl(std::forward(args)...); - } - - explicit operator bool() const { - return _impl.operator bool(); - } - - friend inline bool operator==( - const unique_function &value, - std::nullptr_t) noexcept { - return value._impl == nullptr; - } - friend inline bool operator==( - std::nullptr_t, - const unique_function &value) noexcept { - return value._impl == nullptr; - } - friend inline bool operator!=( - const unique_function &value, - std::nullptr_t) noexcept { - return value._impl != nullptr; - } - friend inline bool operator!=( - std::nullptr_t, - const unique_function &value) noexcept { - return value._impl != nullptr; - } - -private: - template - unique_function(Callable &&other, std::true_type) - : _impl(std::forward(other)) { - } - - template - unique_function(Callable &&other, std::false_type) - : _impl(details::moveable_callable_wrap>( - std::forward(other))) { - } - - std::function _impl; - -}; - -} // namespace base - -#ifdef UniqueFunctionUnexpected -#undef UniqueFunctionUnexpected -#undef Unexpected -#endif // UniqueFunctionUnexpectedb - diff --git a/Telegram/SourceFiles/base/unique_qptr.h b/Telegram/SourceFiles/base/unique_qptr.h deleted file mode 100644 index 89bd2dc58..000000000 --- a/Telegram/SourceFiles/base/unique_qptr.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -class unique_qptr { -public: - unique_qptr() = default; - unique_qptr(std::nullptr_t) noexcept { - } - explicit unique_qptr(T *pointer) noexcept - : _object(pointer) { - } - - unique_qptr(const unique_qptr &other) = delete; - unique_qptr &operator=(const unique_qptr &other) = delete; - unique_qptr(unique_qptr &&other) noexcept - : _object(base::take(other._object)) { - } - unique_qptr &operator=(unique_qptr &&other) noexcept { - if (_object != other._object) { - destroy(); - _object = base::take(other._object); - } - return *this; - } - - template < - typename U, - typename = std::enable_if_t>> - unique_qptr(unique_qptr &&other) noexcept - : _object(base::take(other._object)) { - } - - template < - typename U, - typename = std::enable_if_t>> - unique_qptr &operator=(unique_qptr &&other) noexcept { - if (_object != other._object) { - destroy(); - _object = base::take(other._object); - } - return *this; - } - - unique_qptr &operator=(std::nullptr_t) noexcept { - destroy(); - return *this; - } - - template - explicit unique_qptr(std::in_place_t, Args &&...args) - : _object(new T(std::forward(args)...)) { - } - - template - T *emplace(Args &&...args) { - reset(new T(std::forward(args)...)); - return get(); - } - - void reset(T *value = nullptr) noexcept { - if (_object != value) { - destroy(); - _object = value; - } - } - - T *get() const noexcept { - return static_cast(_object.data()); - } - operator T*() const noexcept { - return get(); - } - - T *release() noexcept { - return static_cast(base::take(_object).data()); - } - - explicit operator bool() const noexcept { - return _object != nullptr; - } - - T *operator->() const noexcept { - return get(); - } - T &operator*() const noexcept { - return *get(); - } - - ~unique_qptr() noexcept { - destroy(); - } - -private: - void destroy() noexcept { - delete base::take(_object).data(); - } - - template - friend class unique_qptr; - - QPointer _object; - -}; - -template -inline unique_qptr make_unique_q(Args &&...args) { - return unique_qptr(std::in_place, std::forward(args)...); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/unixtime.cpp b/Telegram/SourceFiles/base/unixtime.cpp deleted file mode 100644 index d3185e190..000000000 --- a/Telegram/SourceFiles/base/unixtime.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/unixtime.h" - -#include -#include - -#ifdef Q_OS_WIN -#include -#elif defined Q_OS_MAC -#include -#else -#include -#endif - -namespace base { -namespace unixtime { -namespace { - -std::atomic ValueUpdated/* = false*/; -std::atomic ValueShift/* = 0*/; -std::atomic HttpValueValid/* = false*/; -std::atomic HttpValueShift/* = 0*/; - -class MsgIdManager { -public: - MsgIdManager(); - - void update(); - [[nodiscard]] uint64 next(); - -private: - void initialize(); - - QReadWriteLock _lock; - uint64 _startId = 0; - std::atomic _incrementedPart = 0; - uint64 _startCounter = 0; - uint64 _randomPart = 0; - float64 _multiplier = 0.; - -}; - -MsgIdManager GlobalMsgIdManager; - -[[nodiscard]] float64 GetMultiplier() { - // 0xFFFF0000 instead of 0x100000000 to make msgId grow slightly slower, - // than unixtime and we had time to reconfigure. - -#ifdef Q_OS_WIN - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - return float64(0xFFFF0000L) / float64(li.QuadPart); -#elif defined Q_OS_MAC // Q_OS_WIN - mach_timebase_info_data_t tb = { 0, 0 }; - mach_timebase_info(&tb); - const auto frequency = (float64(tb.numer) / tb.denom) / 1000000.; - return frequency * (float64(0xFFFF0000L) / 1000.); -#else // Q_OS_MAC || Q_OS_WIN - return float64(0xFFFF0000L) / 1000000000.; -#endif // Q_OS_MAC || Q_OS_WIN -} - -[[nodiscard]] uint64 GetCounter() { -#ifdef Q_OS_WIN - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - return li.QuadPart; -#elif defined Q_OS_MAC // Q_OS_WIN - return mach_absolute_time(); -#else // Q_OS_MAC || Q_OS_WIN - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return 1000000000 * uint64(ts.tv_sec) + uint64(ts.tv_nsec); -#endif // Q_OS_MAC || Q_OS_WIN -} - -MsgIdManager::MsgIdManager() { - auto generator = std::mt19937(std::random_device()()); - auto distribution = std::uniform_int_distribution(); - _randomPart = distribution(generator); - _multiplier = GetMultiplier(); - initialize(); - - srand(uint32(_startCounter & 0xFFFFFFFFUL)); -} - -void MsgIdManager::update() { - QWriteLocker lock(&_lock); - initialize(); -} - -void MsgIdManager::initialize() { - _startCounter = GetCounter(); - _startId = ((uint64(uint32(now()))) << 32) | _randomPart; -} - -uint64 MsgIdManager::next() { - const auto counter = GetCounter(); - - QReadLocker lock(&_lock); - const auto delta = (counter - _startCounter); - const auto result = _startId + (uint64)floor(delta * _multiplier); - lock.unlock(); - - return (result & ~0x03L) + (_incrementedPart += 4); -} - -TimeId local() { - return (TimeId)time(nullptr); -} - -} // namespace - -TimeId now() { - return local() + ValueShift.load(); -} - -void update(TimeId now, bool force) { - if (force) { - ValueUpdated = true; - } else { - auto expected = false; - if (!ValueUpdated.compare_exchange_strong(expected, true)) { - return; - } - } - const auto shift = now + 1 - local(); - ValueShift = shift; - - HttpValueShift = 0; - HttpValueValid = false; - - GlobalMsgIdManager.update(); -} - -QDateTime parse(TimeId value) { - return (value > 0) - ? QDateTime::fromTime_t(value - ValueShift) - : QDateTime(); -} - -TimeId serialize(const QDateTime &date) { - return date.isNull() ? TimeId(0) : date.toTime_t() + ValueShift; -} - -bool http_valid() { - return HttpValueValid; -} - -TimeId http_now() { - return now() + HttpValueShift; -} - -void http_update(TimeId now) { - HttpValueShift = now - base::unixtime::now(); - HttpValueValid = true; -} - -void http_invalidate() { - HttpValueValid = false; -} - -uint64 mtproto_msg_id() { - return GlobalMsgIdManager.next(); -} - -} // namespace unixtime -} // namespace base diff --git a/Telegram/SourceFiles/base/unixtime.h b/Telegram/SourceFiles/base/unixtime.h deleted file mode 100644 index 9db64ed2a..000000000 --- a/Telegram/SourceFiles/base/unixtime.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/basic_types.h" - -class QDateTime; - -namespace base { -namespace unixtime { - -// All functions are thread-safe. - -[[nodiscard]] TimeId now(); -void update(TimeId now, bool force = false); - -[[nodiscard]] QDateTime parse(TimeId value); -[[nodiscard]] TimeId serialize(const QDateTime &date); - -[[nodiscard]] bool http_valid(); -[[nodiscard]] TimeId http_now(); -void http_update(TimeId now); -void http_invalidate(); - -[[nodiscard]] uint64 mtproto_msg_id(); - -} // namespace unixtime -} // namespace base diff --git a/Telegram/SourceFiles/base/value_ordering.h b/Telegram/SourceFiles/base/value_ordering.h deleted file mode 100644 index 941421bfa..000000000 --- a/Telegram/SourceFiles/base/value_ordering.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { -namespace details { - -template < - typename Type, - typename Operator, - typename = decltype(Operator{}( - std::declval(), - std::declval()))> -char test_operator(const Type &, const Operator &); -int test_operator(...); - -template typename Operator> -struct has_operator - : std::bool_constant< - sizeof(test_operator( - std::declval(), - std::declval>() - )) == sizeof(char)> { -}; - -template < - typename Type, - template typename Operator> -constexpr bool has_operator_v - = has_operator::value; - -template -constexpr bool has_less_v = has_operator_v; - -template -constexpr bool has_greater_v = has_operator_v; - -template -constexpr bool has_less_equal_v = has_operator_v; - -template -constexpr bool has_greater_equal_v = has_operator_v; - -template -constexpr bool has_equal_to_v = has_operator_v; - -template -constexpr bool has_not_equal_to_v = has_operator_v; - -} // namespace details -} // namespace base - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator<(const ValueType &a, const ValueType &b) --> std::enable_if_t, bool> { - return value_ordering_helper(a) < value_ordering_helper(b); -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator>(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_greater_v - || base::details::has_less_v, - bool -> { - if constexpr (base::details::has_greater_v) { - return value_ordering_helper(a) > value_ordering_helper(b); - } else { - return value_ordering_helper(b) < value_ordering_helper(a); - } -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator<=(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_less_equal_v - || base::details::has_less_v, - bool -> { - if constexpr (base::details::has_less_equal_v) { - return value_ordering_helper(a) <= value_ordering_helper(b); - } else { - return !(value_ordering_helper(b) < value_ordering_helper(a)); - } -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator>=(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_greater_equal_v - || base::details::has_less_v, - bool -> { - if constexpr (base::details::has_greater_equal_v) { - return value_ordering_helper(a) >= value_ordering_helper(b); - } else { - return !(value_ordering_helper(a) < value_ordering_helper(b)); - } -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator==(const ValueType &a, const ValueType &b) --> std::enable_if_t, bool> { - return value_ordering_helper(a) == value_ordering_helper(b); -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator!=(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_not_equal_to_v - || base::details::has_equal_to_v, - bool -> { - if constexpr (base::details::has_not_equal_to_v) { - return value_ordering_helper(a) != value_ordering_helper(b); - } else { - return !(value_ordering_helper(a) == value_ordering_helper(b)); - } -} diff --git a/Telegram/SourceFiles/base/variant.h b/Telegram/SourceFiles/base/variant.h deleted file mode 100644 index e8539d4d2..000000000 --- a/Telegram/SourceFiles/base/variant.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -inline bool operator<(std::nullopt_t, std::nullopt_t) { - return false; -} -inline bool operator>(std::nullopt_t, std::nullopt_t) { - return false; -} -inline bool operator<=(std::nullopt_t, std::nullopt_t) { - return true; -} -inline bool operator>=(std::nullopt_t, std::nullopt_t) { - return true; -} -inline bool operator==(std::nullopt_t, std::nullopt_t) { - return true; -} -inline bool operator!=(std::nullopt_t, std::nullopt_t) { - return false; -} - -#include -#include -#include "base/match_method.h" -#include "base/assertion.h" - -// We use base::variant<> alias and base::get_if() helper while we don't have std::variant<>. -namespace base { - -template -using variant = mapbox::util::variant; - -template -inline T *get_if(variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -template -inline const T *get_if(const variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -namespace type_list = rpl::details::type_list; - -template -struct normalized_variant { - using list = type_list::list; - using distinct = type_list::distinct_t; - using type = std::conditional_t< - type_list::size_v == 1, - type_list::get_t<0, distinct>, - type_list::extract_to_t>; -}; - -template -using normalized_variant_t - = typename normalized_variant::type; - -template -struct match_helper; - -template < - typename Type, - typename ...Types, - typename Variant, - typename ...Methods> -struct match_helper, Variant, Methods...> { - static decltype(auto) call(Variant &value, Methods &&...methods) { - if (const auto v = get_if(&value)) { - return match_method( - *v, - std::forward(methods)...); - } - return match_helper< - type_list::list, - Variant, - Methods...>::call( - value, - std::forward(methods)...); - } -}; - -template < - typename Type, - typename Variant, - typename ...Methods> -struct match_helper, Variant, Methods...> { - static decltype(auto) call(Variant &value, Methods &&...methods) { - if (const auto v = get_if(&value)) { - return match_method( - *v, - std::forward(methods)...); - } - Unexpected("Valueless variant in base::match()."); - } -}; - -template -inline decltype(auto) match( - variant &value, - Methods &&...methods) { - return match_helper< - type_list::list, - variant, - Methods...>::call(value, std::forward(methods)...); -} - -template -inline decltype(auto) match( - const variant &value, - Methods &&...methods) { - return match_helper< - type_list::list, - const variant, - Methods...>::call(value, std::forward(methods)...); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/virtual_method.h b/Telegram/SourceFiles/base/virtual_method.h deleted file mode 100644 index 9feda79c6..000000000 --- a/Telegram/SourceFiles/base/virtual_method.h +++ /dev/null @@ -1,704 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { - -template -class virtual_object; - -template -class virtual_method; - -template -class virtual_override; - -namespace virtual_methods { - -struct child_entry; -using is_parent_check = bool(*)(const child_entry &possible_parent); -struct child_entry { - is_parent_check check_is_parent; - int *table_index; -}; -using child_entries = std::vector; - -// Recursive method to find if some class is a child of some other class. -template -struct is_parent { - static inline bool check(const child_entry &possible_parent) { - // Generate a good error message if ConcreteObject is not a child of virtual_object<>. - using all_objects_must_derive_virtual_object = typename ConcreteObject::virtual_object_parent; - using ConcreteObjectParent = all_objects_must_derive_virtual_object; - return (possible_parent.check_is_parent == &is_parent::check) - || is_parent::check(possible_parent); - } -}; - -template <> -struct is_parent { - static inline bool check(const child_entry &possible_parent) { - return (possible_parent.check_is_parent == &is_parent::check); - } -}; - -// Just force the compiler not to optimize away the object that "enforce" points at. -inline void dont_optimize_away(void *enforce) { - static volatile void *result = nullptr; - if (result) { - result = enforce; - } -} - -template -struct dont_optimize_away_struct { -}; - -inline bool first_dispatch_fired(bool did_fire = false) { - static bool fired = false; - if (did_fire) { - fired = true; - } - return fired; -} - -template -class object_registrator { -public: - inline object_registrator() { - Assert(!first_dispatch_fired()); - Creator(child_entry { - &is_parent::check, - &_index, - }); - } - static inline int &Index() { - return _index; - } - -private: - static int _index; - -}; - -template -int object_registrator::_index = -1; - -class object_base { -protected: - virtual ~object_base() = default; - -}; - -template -struct multi_index_collector; -template -struct override_key_collector_helper; -template -struct table_fill_entry_helper; -template -struct table_count_size; - -} // namespace virtual_methods - -// This should be a base class for every child object in your hierarchy. -// It registers this child in the root virtual_objects classes list. -// Also it holds its own index in the classes list that is used for fast -// invoking of methods from the virtual tables in different virtual_methods. -template -class virtual_object : public ParentObject { -protected: - virtual ~virtual_object() { - virtual_methods::dont_optimize_away(&_virtual_object_registrator); - } - -private: - using virtual_object_parent = ParentObject; - - friend struct virtual_methods::is_parent; - template - friend struct virtual_methods::multi_index_collector; - template - friend struct virtual_methods::override_key_collector_helper; - template - friend class virtual_object; - template - friend class virtual_method; - - static inline void virtual_object_register_child(const virtual_methods::child_entry &entry) { - return ParentObject::virtual_object_register_child(entry); - } - - using virtual_object_registrator = virtual_methods::object_registrator; - static virtual_object_registrator _virtual_object_registrator; - using virtual_object_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct; - - static inline int &virtual_object_child_index_static() { - return virtual_object_registrator::Index(); - } - int &virtual_object_child_index() override { - return virtual_object_child_index_static(); - } - -}; - -template -typename virtual_object::virtual_object_registrator virtual_object::_virtual_object_registrator = {}; - -// This should be a base class for the root of the whole hierarchy. -// It holds the table of all child classes in a list. -// This list is used by virtual_methods to generate virtual table. -template -class virtual_object : public virtual_methods::object_base { -protected: - virtual ~virtual_object() { - virtual_methods::dont_optimize_away(&_virtual_object_registrator); - } - -private: - using virtual_object_parent = void; - - friend struct virtual_methods::is_parent; - template - friend struct virtual_methods::table_count_size; - template - friend struct virtual_methods::multi_index_collector; - template - friend struct virtual_methods::override_key_collector_helper; - template - friend struct virtual_methods::table_fill_entry_helper; - template - friend class virtual_object; - template - friend class virtual_method; - - static inline virtual_methods::child_entries &virtual_object_get_child_entries() { - static virtual_methods::child_entries entries; - return entries; - } - - // Registers a new child class. - // After that on the next call to virtual_method::virtual_method_prepare_table() will - // generate a new virtual table for that virtual method. - static inline void virtual_object_register_child(const virtual_methods::child_entry &entry) { - auto &entries = virtual_object_get_child_entries(); - for (auto i = entries.begin(), e = entries.end(); i != e; ++i) { - if (entry.check_is_parent(*i)) { - *entry.table_index = (i - entries.begin()); - i = entries.insert(i, entry); - for (++i, e = entries.end(); i != e; ++i) { - ++*(i->table_index); - } - return; - } - } - *entry.table_index = entries.size(); - entries.push_back(entry); - } - - using virtual_object_registrator = virtual_methods::object_registrator; - static virtual_object_registrator _virtual_object_registrator; - using virtual_object_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct; - - static inline int &virtual_object_child_index_static() { - return virtual_object_registrator::Index(); - } - virtual int &virtual_object_child_index() { - return virtual_object_child_index_static(); - } - -}; - -template -typename virtual_object::virtual_object_registrator virtual_object::_virtual_object_registrator = {}; - -namespace virtual_methods { - -template -struct is_virtual_argument : public std::integral_constant::is_pointer::value - ? std::is_base_of::pointed_type>::value - : false> { -}; - -template -class multi_int_wrap { -public: - inline multi_int_wrap(int *indices) : _indices(indices) { - } - inline multi_int_wrap subindex() const { - static_assert(N > 0, "Wrong multi_int_wrap created!"); - return multi_int_wrap(_indices + 1); - } - inline int ¤t() const { - return *_indices; - } - -private: - int *_indices; - -}; - -template -class multi_int_wrap<0, Instance> { -public: - inline multi_int_wrap(int *indices) { - } - inline int current() const { - return 1; - } - -}; - -template -using multi_index_wrap = multi_int_wrap; -template -using multi_size_wrap = multi_int_wrap; - -template -struct multi_index_collector { - static constexpr int N = sizeof...(ConcreteArgs) + 1; - static inline void call(multi_index_wrap indices, ConcreteArg arg, ConcreteArgs... args) { - indices.current() = computeIndex(is_virtual_argument(), arg); - multi_index_collector::call(indices.subindex(), args...); - } - - static inline int computeIndex(std::integral_constant, ConcreteArg arg) { - return 0; - } - static inline int computeIndex(std::integral_constant, ConcreteArg arg) { - return arg->virtual_object_child_index(); - } - -}; - -template <> -struct multi_index_collector<> { - static inline void call(multi_index_wrap<0> indices) { - } -}; - -template -class override_key; - -template -class multi_int { -public: - inline multi_int_wrap data_wrap() { - return multi_int_wrap(_indices); - } - - template - static inline multi_int collect(ConcreteArgs... args) { - multi_int result; - multi_index_collector::call(result.data_wrap(), args...); - return result; - } - - inline void reset() { - memset(_indices, 0, sizeof(_indices)); - } - - inline int value(int index) const { - return _indices[index]; - } - - inline void copy(multi_int_wrap other) { - memcpy(_indices, &other.current(), sizeof(_indices)); - } - -private: - int _indices[N] = { 0 }; - friend class override_key; - -}; - -template -using multi_index = multi_int; -template -using multi_size = multi_int; - -template -class table_data_wrap { -public: - inline table_data_wrap(Call *data, multi_size_wrap size) : _data(data), _size(size) { - } - inline table_data_wrap operator[](int index) const { - return table_data_wrap(_data + index * _size.subindex().current(), _size.subindex()); - } - inline Call &operator[](multi_index_wrap index) const { - return (*this)[index.current()][index.subindex()]; - } - inline int size() const { - return count_size(std::integral_constant()); - } - -private: - template - inline int count_size(std::integral_constant) const { - return _size.current() / _size.subindex().current(); - } - inline int count_size(std::integral_constant) const { - return _size.current(); - } - - Call *_data; - multi_size_wrap _size; - -}; - -template -class table_data_wrap { -public: - inline table_data_wrap(Call *data, multi_size_wrap<0> size) : _data(data) { - } - inline Call &operator[](multi_index_wrap<0> index) const { - return *_data; - } - -private: - Call *_data; - -}; - -template -class table_data_wrap; - -template -struct table_count_size { - static constexpr int N = sizeof...(Args) + 1; - static inline void call(multi_size_wrap index) { - auto subindex = index.subindex(); - table_count_size::call(subindex); - index.current() = count(is_virtual_argument()) * subindex.current(); - } - - static inline int count(std::integral_constant) { - return 1; - } - static inline int count(std::integral_constant) { - return base::type_traits::pointed_type::virtual_object_get_child_entries().size(); - } - -}; - -template <> -struct table_count_size<> { - static inline void call(multi_size_wrap<0> index) { - } -}; - -template -class table_data { -public: - inline table_data_wrap data_wrap() { - return table_data_wrap(_data.data(), _size.data_wrap()); - } - - inline Call &operator[](multi_index index) { - int flat_index = 0; - for (int i = 0; i != N - 1; ++i) { - flat_index += _size.value(i + 1) * index.value(i); - } - flat_index += index.value(N - 1); - return _data[flat_index]; - } - - template - inline bool changed() { - if (!_data.empty()) { - return false; - } - - multi_size size; - table_count_size::call(size.data_wrap()); - _size = size; - _data.resize(_size.value(0), nullptr); - return true; - } - -private: - std::vector _data; - multi_size _size; - -}; - -template -class table_data { -public: - inline table_data_wrap data_wrap() { - return table_data_wrap(&_call, multi_size_wrap<0>(nullptr)); - } - - inline Call &operator[](multi_index<0> index) { - return _call; - } - - inline bool changed() const { - return false; - } - -private: - Call _call = nullptr; - -}; - -template -struct table_fill_entry_helper; - -template -struct table_fill_entry_helper { - static constexpr int N = sizeof...(Args) + 1; - - static inline bool call(table_data_wrap table, multi_index_wrap index, Call &fill) { - auto start = index.current(); - for (auto i = start, count = table.size(); i != count; ++i) { - auto foundGoodType = good(is_virtual_argument(), start, index.current()); - if (foundGoodType) { - index.current() = i; - if (table_fill_entry_helper::call(table[i], index.subindex(), fill)) { - return true; - } - } - } - index.current() = start; - return false; - } - - static inline bool good(std::integral_constant, int start, int current) { - return (start == current); - } - static inline bool good(std::integral_constant, int start, int current) { - using BaseObject = typename base::type_traits::pointed_type; - auto &entries = BaseObject::virtual_object_get_child_entries(); - return (start == current) || entries[start].check_is_parent(entries[current]); - } - -}; - -template -struct table_fill_entry_helper { - static inline bool call(table_data_wrap table, multi_index_wrap<0> index, Call &fill) { - if (auto overrideMethod = table[index]) { - fill = overrideMethod; - return true; - } - return false; - } -}; - -template -struct table_fill_entry; - -template -struct table_fill_entry { - using Call = ReturnType(*)(BaseMethod*, Args...); - static inline void call(table_data_wrap table, multi_index_wrap index, Call &fill) { - table_fill_entry_helper::call(table, index, fill); - } -}; - -template -inline void fill_entry(table_data_wrap table, multi_index_wrap index, Call &fill) { - return virtual_methods::table_fill_entry::call(table, index, fill); -} - -template -struct override_key_collector_helper; - -template -struct override_key_collector_helper { - static inline void call(int **indices) { - setValue(is_virtual_argument(), indices); - override_key_collector_helper::call(indices); - } - - static inline void setValue(std::integral_constant, int **indices) { - indices[M] = nullptr; - } - static inline void setValue(std::integral_constant, int **indices) { - using ConcreteObject = typename base::type_traits::pointed_type; - using IsParentCheckStruct = is_parent; - using IsParentCheckPointer = decltype(&IsParentCheckStruct::check); - using override_key_collector_dont_optimize_away = dont_optimize_away_struct; - override_key_collector_dont_optimize_away dont_optimize_away_object; - (void)dont_optimize_away_object; - - // Check that is_parent<> can be instantiated. - // So every ConcreteObject is a valid child of virtual_object<>. - dont_optimize_away(reinterpret_cast(&IsParentCheckStruct::check)); - indices[M] = &ConcreteObject::virtual_object_child_index_static(); - } - -}; - -template -struct override_key_collector_helper { - static inline void call(int **indices) { - } -}; - -template -struct override_key_collector; - -template -struct override_key_collector { - static inline void call(int **indices) { - override_key_collector_helper<0, ConcreteArgs...>::call(indices); - } -}; - -template -class override_key { -public: - inline multi_index value() const { - multi_index result; - for (int i = 0; i != N; ++i) { - auto pointer = _indices[i]; - result._indices[i] = (pointer ? *pointer : 0); - } - return result; - } - - friend inline bool operator<(const override_key &k1, const override_key &k2) { - for (int i = 0; i != N; ++i) { - auto pointer1 = k1._indices[i], pointer2 = k2._indices[i]; - if (pointer1 < pointer2) { - return true; - } else if (pointer1 > pointer2) { - return false; - } - } - return false; - } - - template - inline void collect() { - override_key_collector::call(_indices); - } - -private: - int *_indices[N]; - -}; - -template -struct static_cast_helper; - -template -struct static_cast_helper { - static inline ReturnType call(BaseMethod *context, Args ...args) { - return ConcreteMethod::call(context, static_cast(args)...); - } -}; - -} // namespace virtual_methods - -// This is a base class for all your virtual methods. -// It dispatches a call to one of the registered virtual_overrides -// or calls the fallback method of the BaseMethod class. -template -class virtual_method { - static constexpr int N = sizeof...(Args); - using virtual_method_call = ReturnType(*)(BaseMethod *context, Args... args); - -public: - inline ReturnType call(Args... args) { - auto context = static_cast(this); - auto index = virtual_methods::multi_index::collect(args...); - auto &table = virtual_method_prepare_table(); - auto &entry = table[index]; - if (!entry) { - virtual_methods::fill_entry(table.data_wrap(), index.data_wrap(), entry); - if (!entry) { - entry = &virtual_method::virtual_method_base_instance; - } - } - return (*entry)(context, args...); - } - -private: - // This map of methods contains only the original registered overrides. - using virtual_method_override_key = virtual_methods::override_key; - using virtual_method_override_map = std::map; - static inline virtual_method_override_map &virtual_method_get_override_map() { - static virtual_method_override_map override_map; - return override_map; - } - - // This method generates and returns a virtual table which holds a method - // for any child in the hierarchy or nullptr if none of the virtual_overrides fit. - using virtual_method_table_data = virtual_methods::table_data; - static inline virtual_method_table_data &virtual_method_get_table_data() { - static virtual_method_table_data virtual_table; - return virtual_table; - } - - static inline virtual_method_table_data &virtual_method_prepare_table() { - auto &virtual_table = virtual_method_get_table_data(); - if (virtual_table.template changed()) { - virtual_methods::first_dispatch_fired(true); - - // The class hierarchy has changed - we need to generate the virtual table once again. - // All other handlers will be placed if they're called. - for (auto &i : virtual_method_get_override_map()) { - virtual_table[i.first.value()] = i.second; - } - } - return virtual_table; - } - - static ReturnType virtual_method_base_instance(BaseMethod *context, Args... args) { - return BaseMethod::default_call(context, args...); - } - - template - static ReturnType virtual_method_override_instance(BaseMethod *context, Args... args) { - return virtual_methods::static_cast_helper::call(context, args...); - } - - template - static inline void virtual_method_register_override() { - auto call = &virtual_method_override_instance; - - virtual_methods::override_key key; - key.template collect(); - - virtual_method_get_override_map()[key] = call; - } - - template - friend class virtual_override; - -}; - -template -class virtual_override { -protected: - virtual ~virtual_override() { - virtual_methods::dont_optimize_away(&_virtual_override_registrator); - } - -private: - class virtual_override_registrator { - public: - inline virtual_override_registrator() { - Assert(!virtual_methods::first_dispatch_fired()); - BaseMethod::template virtual_method_register_override(); - } - - }; - static virtual_override_registrator _virtual_override_registrator; - using virtual_override_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct; - -}; - -template -typename virtual_override::virtual_override_registrator virtual_override::_virtual_override_registrator = {}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/weak_ptr.h b/Telegram/SourceFiles/base/weak_ptr.h deleted file mode 100644 index d396501c7..000000000 --- a/Telegram/SourceFiles/base/weak_ptr.h +++ /dev/null @@ -1,325 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace base { - -class has_weak_ptr; - -namespace details { - -struct alive_tracker { - explicit alive_tracker(const has_weak_ptr *value) : value(value) { - } - - std::atomic counter = 1; - std::atomic value; -}; - -inline alive_tracker *check_and_increment(alive_tracker *tracker) noexcept { - if (tracker) { - ++tracker->counter; - } - return tracker; -} - -inline void decrement(alive_tracker *tracker) noexcept { - if (tracker->counter.fetch_sub(1) == 0) { - delete tracker; - } -} - -} // namespace details - -template -class weak_ptr; - -class has_weak_ptr { -public: - has_weak_ptr() = default; - has_weak_ptr(const has_weak_ptr &other) noexcept { - } - has_weak_ptr(has_weak_ptr &&other) noexcept { - } - has_weak_ptr &operator=(const has_weak_ptr &other) noexcept { - return *this; - } - has_weak_ptr &operator=(has_weak_ptr &&other) noexcept { - return *this; - } - - ~has_weak_ptr() { - if (const auto alive = _alive.load()) { - alive->value.store(nullptr); - details::decrement(alive); - } - } - - friend inline void invalidate_weak_ptrs(has_weak_ptr *object) { - if (auto alive = object->_alive.load()) { - if (object->_alive.compare_exchange_strong(alive, nullptr)) { - alive->value.store(nullptr); - details::decrement(alive); - } - } - } - -private: - template - friend class weak_ptr; - - details::alive_tracker *incrementAliveTracker() const { - auto current = _alive.load(); - if (!current) { - auto alive = std::make_unique(this); - if (_alive.compare_exchange_strong(current, alive.get())) { - return alive.release(); - } - } - ++current->counter; - return current; - } - - mutable std::atomic _alive = nullptr; - -}; - -template -class weak_ptr { -public: - weak_ptr() = default; - weak_ptr(T *value) - : _alive(value ? value->incrementAliveTracker() : nullptr) { - } - weak_ptr(const std::unique_ptr &value) - : weak_ptr(value.get()) { - } - weak_ptr(const std::shared_ptr &value) - : weak_ptr(value.get()) { - } - weak_ptr(const std::weak_ptr &value) - : weak_ptr(value.lock().get()) { - } - weak_ptr(const weak_ptr &other) noexcept - : _alive(details::check_and_increment(other._alive)) { - } - weak_ptr(weak_ptr &&other) noexcept - : _alive(std::exchange(other._alive, nullptr)) { - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr(const weak_ptr &other) noexcept - : _alive(details::check_and_increment(other._alive)) { - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr(weak_ptr &&other) noexcept - : _alive(std::exchange(other._alive, nullptr)) { - } - - weak_ptr &operator=(T *value) { - reset(value); - return *this; - } - weak_ptr &operator=(const std::unique_ptr &value) { - reset(value.get()); - return *this; - } - weak_ptr &operator=(const std::shared_ptr &value) { - reset(value.get()); - return *this; - } - weak_ptr &operator=(const std::weak_ptr &value) { - reset(value.lock().get()); - return *this; - } - weak_ptr &operator=(const weak_ptr &other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = details::check_and_increment(other._alive); - } - return *this; - } - weak_ptr &operator=(weak_ptr &&other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = std::exchange(other._alive, nullptr); - } - return *this; - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr &operator=(const weak_ptr &other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = details::check_and_increment(other._alive); - } - return *this; - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr &operator=(weak_ptr &&other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = std::exchange(other._alive, nullptr); - } - return *this; - } - - ~weak_ptr() { - destroy(); - } - - T *get() const noexcept { - const auto strong = _alive ? _alive->value.load() : nullptr; - if constexpr (std::is_const_v) { - return static_cast(strong); - } else { - return const_cast(static_cast(strong)); - } - } - explicit operator bool() const noexcept { - return (_alive && _alive->value); - } - T &operator*() const noexcept { - return *get(); - } - T *operator->() const noexcept { - return get(); - } - - void reset(T *value = nullptr) { - if (get() != value) { - destroy(); - _alive = value ? value->incrementAliveTracker() : nullptr; - } - } - -private: - void destroy() noexcept { - if (_alive) { - details::decrement(_alive); - } - } - - details::alive_tracker *_alive = nullptr; - - template - friend class weak_ptr; - -}; - -template -inline bool operator==(const weak_ptr &pointer, std::nullptr_t) noexcept { - return (pointer.get() == nullptr); -} - -template -inline bool operator==(std::nullptr_t, const weak_ptr &pointer) noexcept { - return (pointer == nullptr); -} - -template -inline bool operator!=(const weak_ptr &pointer, std::nullptr_t) noexcept { - return !(pointer == nullptr); -} - -template -inline bool operator!=(std::nullptr_t, const weak_ptr &pointer) noexcept { - return !(pointer == nullptr); -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(T *value) { - return value; -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(const std::unique_ptr &value) { - return value; -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(const std::shared_ptr &value) { - return value; -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(const std::weak_ptr &value) { - return value; -} - -} // namespace base - -namespace crl { - -template -struct guard_traits; - -template -struct guard_traits, void> { - static base::weak_ptr create(const base::weak_ptr &value) { - return value; - } - static base::weak_ptr create(base::weak_ptr &&value) { - return std::move(value); - } - static bool check(const base::weak_ptr &guard) { - return guard.get() != nullptr; - } - -}; - -template -struct guard_traits< - T*, - std::enable_if_t< - std::is_base_of_v>>> { - static base::weak_ptr create(T *value) { - return value; - } - static bool check(const base::weak_ptr &guard) { - return guard.get() != nullptr; - } - -}; - -template -struct guard_traits< - gsl::not_null, - std::enable_if_t< - std::is_base_of_v>>> { - static base::weak_ptr create(gsl::not_null value) { - return value.get(); - } - static bool check(const base::weak_ptr &guard) { - return guard.get() != nullptr; - } - -}; - -} // namespace crl diff --git a/Telegram/SourceFiles/base/zlib_help.h b/Telegram/SourceFiles/base/zlib_help.h deleted file mode 100644 index 8c0147cdc..000000000 --- a/Telegram/SourceFiles/base/zlib_help.h +++ /dev/null @@ -1,410 +0,0 @@ -/* -WARNING! All changes made in this file will be lost! -Created from 'colors.palette' by 'codegen_style' - -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "zip.h" -#include "unzip.h" -#include "logs.h" - -#ifdef small -#undef small -#endif // small - -namespace zlib { -namespace internal { - -class InMemoryFile { -public: - InMemoryFile(const QByteArray &data = QByteArray()) : _data(data) { - } - - zlib_filefunc_def funcs() { - zlib_filefunc_def result; - result.opaque = this; - result.zopen_file = &InMemoryFile::Open; - result.zerror_file = &InMemoryFile::Error; - result.zread_file = &InMemoryFile::Read; - result.zwrite_file = &InMemoryFile::Write; - result.zclose_file = &InMemoryFile::Close; - result.zseek_file = &InMemoryFile::Seek; - result.ztell_file = &InMemoryFile::Tell; - return result; - } - - int error() const { - return _error; - } - - QByteArray result() const { - return _data; - } - -private: - voidpf open(const char *filename, int mode) { - if (mode & ZLIB_FILEFUNC_MODE_WRITE) { - if (mode & ZLIB_FILEFUNC_MODE_CREATE) { - _data.clear(); - } - _position = _data.size(); - _data.reserve(2 * 1024 * 1024); - } else if (mode & ZLIB_FILEFUNC_MODE_READ) { - _position = 0; - } - _error = 0; - return this; - } - - uLong read(voidpf stream, void* buf, uLong size) { - uLong toRead = 0; - if (!_error) { - if (_data.size() > int(_position)) { - toRead = qMin(size, uLong(_data.size() - _position)); - memcpy(buf, _data.constData() + _position, toRead); - _position += toRead; - } - if (toRead < size) { - _error = -1; - } - } - return toRead; - } - - uLong write(voidpf stream, const void* buf, uLong size) { - if (_data.size() < int(_position + size)) { - _data.resize(_position + size); - } - memcpy(_data.data() + _position, buf, size); - _position += size; - return size; - } - - int close(voidpf stream) { - auto result = _error; - _position = 0; - _error = 0; - return result; - } - - int error(voidpf stream) const { - return _error; - } - - long tell(voidpf stream) const { - return _position; - } - - long seek(voidpf stream, uLong offset, int origin) { - if (!_error) { - switch (origin) { - case ZLIB_FILEFUNC_SEEK_SET: _position = offset; break; - case ZLIB_FILEFUNC_SEEK_CUR: _position += offset; break; - case ZLIB_FILEFUNC_SEEK_END: _position = _data.size() + offset; break; - } - if (int(_position) > _data.size()) { - _error = -1; - } - } - return _error; - } - - static voidpf Open(voidpf opaque, const char* filename, int mode) { - return static_cast(opaque)->open(filename, mode); - } - - static uLong Read(voidpf opaque, voidpf stream, void* buf, uLong size) { - return static_cast(opaque)->read(stream, buf, size); - } - - static uLong Write(voidpf opaque, voidpf stream, const void* buf, uLong size) { - return static_cast(opaque)->write(stream, buf, size); - } - - static int Close(voidpf opaque, voidpf stream) { - return static_cast(opaque)->close(stream); - } - - static int Error(voidpf opaque, voidpf stream) { - return static_cast(opaque)->error(stream); - } - - static long Tell(voidpf opaque, voidpf stream) { - return static_cast(opaque)->tell(stream); - } - - static long Seek(voidpf opaque, voidpf stream, uLong offset, int origin) { - return static_cast(opaque)->seek(stream, offset, origin); - } - - uLong _position = 0; - int _error = 0; - QByteArray _data; - -}; - -} // namespace internal - -constexpr int kCaseSensitive = 1; -constexpr int kCaseInsensitive = 2; - -class FileToRead { -public: - FileToRead(const QByteArray &content) : _data(content) { - auto funcs = _data.funcs(); - if (!(_handle = unzOpen2(nullptr, &funcs))) { - _error = -1; - } - } - - int getGlobalInfo(unz_global_info *pglobal_info) { - if (error() == UNZ_OK) { - _error = _handle ? unzGetGlobalInfo(_handle, pglobal_info) : -1; - } - return _error; - } - - int locateFile(const char *szFileName, int iCaseSensitivity) { - if (error() == UNZ_OK) { - _error = _handle ? unzLocateFile(_handle, szFileName, iCaseSensitivity) : -1; - } - return error(); - } - - int goToFirstFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzGoToFirstFile(_handle) : -1; - } - return error(); - } - - int goToNextFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzGoToNextFile(_handle) : -1; - } - return error(); - } - - int getCurrentFileInfo( - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) { - if (error() == UNZ_OK) { - _error = _handle ? unzGetCurrentFileInfo( - _handle, - pfile_info, - szFileName, - fileNameBufferSize, - extraField, - extraFieldBufferSize, - szComment, - commentBufferSize - ) : -1; - } - return error(); - } - - QString getCurrentFileName() { - unz_file_info info = { 0 }; - constexpr auto kMaxName = 128; - char name[kMaxName + 1] = { 0 }; - const auto result = getCurrentFileInfo( - &info, - name, - kMaxName, - nullptr, - 0, - nullptr, - 0); - return (result == UNZ_OK) ? QString::fromUtf8(name) : QString(); - } - - int openCurrentFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzOpenCurrentFile(_handle) : -1; - } - return error(); - } - - int readCurrentFile(voidp buf, unsigned len) { - if (error() == UNZ_OK) { - auto result = _handle ? unzReadCurrentFile(_handle, buf, len) : -1; - if (result >= 0) { - return result; - } else { - _error = result; - } - } - return error(); - } - - int closeCurrentFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzCloseCurrentFile(_handle) : -1; - } - return error(); - } - - QByteArray readCurrentFileContent(int fileSizeLimit) { - unz_file_info fileInfo = { 0 }; - if (getCurrentFileInfo(&fileInfo, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK) { - LOG(("Error: could not get current file info in a zip file.")); - return QByteArray(); - } - - auto size = fileInfo.uncompressed_size; - if (size > static_cast(fileSizeLimit)) { - if (_error == UNZ_OK) _error = -1; - LOG(("Error: current file is too large (should be less than %1, got %2) in a zip file.").arg(fileSizeLimit).arg(size)); - return QByteArray(); - } - if (openCurrentFile() != UNZ_OK) { - LOG(("Error: could not open current file in a zip file.")); - return QByteArray(); - } - - QByteArray result; - result.resize(size); - - auto couldRead = readCurrentFile(result.data(), size); - if (couldRead != static_cast(size)) { - LOG(("Error: could not read current file in a zip file, got %1.").arg(couldRead)); - return QByteArray(); - } - - if (closeCurrentFile() != UNZ_OK) { - LOG(("Error: could not close current file in a zip file.")); - return QByteArray(); - } - - return result; - } - - QByteArray readFileContent(const char *szFileName, int iCaseSensitivity, int fileSizeLimit) { - if (locateFile(szFileName, iCaseSensitivity) != UNZ_OK) { - LOG(("Error: could not locate '%1' in a zip file.").arg(szFileName)); - return QByteArray(); - } - return readCurrentFileContent(fileSizeLimit); - } - - void close() { - if (_handle && unzClose(_handle) != UNZ_OK && _error == UNZ_OK) { - _error = -1; - } - _handle = nullptr; - } - - int error() const { - if (auto dataError = _data.error()) { - return dataError; - } - return _error; - } - - void clearError() { - _error = UNZ_OK; - } - - ~FileToRead() { - close(); - } - -private: - internal::InMemoryFile _data; - unzFile _handle = nullptr; - int _error = 0; - -}; - -class FileToWrite { -public: - FileToWrite() { - auto funcs = _data.funcs(); - if (!(_handle = zipOpen2(nullptr, APPEND_STATUS_CREATE, nullptr, &funcs))) { - _error = -1; - } - } - - int openNewFile( - const char *filename, - const zip_fileinfo *zipfi, - const void *extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level - ) { - if (error() == ZIP_OK) { - _error = _handle ? zipOpenNewFileInZip( - _handle, - filename, - zipfi, - extrafield_local, - size_extrafield_local, - extrafield_global, - size_extrafield_global, - comment, - method, - level - ) : -1; - } - return error(); - } - - int writeInFile(const void* buf, unsigned len) { - if (error() == ZIP_OK) { - _error = _handle ? zipWriteInFileInZip(_handle, buf, len) : -1; - } - return error(); - } - - int closeFile() { - if (error() == ZIP_OK) { - _error = _handle ? zipCloseFileInZip(_handle) : -1; - } - return error(); - } - - void close() { - if (_handle && zipClose(_handle, nullptr) != ZIP_OK && _error == ZIP_OK) { - _error = -1; - } - _handle = nullptr; - } - - int error() const { - if (auto dataError = _data.error()) { - return dataError; - } - return _error; - } - - QByteArray result() const { - return _data.result(); - } - - ~FileToWrite() { - close(); - } - -private: - internal::InMemoryFile _data; - zipFile _handle = nullptr; - int _error = 0; - -}; - -} // namespace zlib diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index a2f474fd0..9bf5bbad0 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include #include "base/basic_types.h" #include "base/match_method.h" #include "base/flags.h" diff --git a/Telegram/SourceFiles/rpl/after_next.h b/Telegram/SourceFiles/rpl/after_next.h deleted file mode 100644 index 12d20ed90..000000000 --- a/Telegram/SourceFiles/rpl/after_next.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { - -template -class after_next_helper { -public: - template - after_next_helper(OtherSideEffect &&method) - : _method(std::forward(method)) { - } - - template - auto operator()(producer &&initial) { - return make_producer([ - initial = std::move(initial), - method = std::move(_method) - ](const auto &consumer) mutable { - return std::move(initial).start( - [method = std::move(method), consumer](auto &&value) { - auto copy = method; - consumer.put_next_copy(value); - details::callable_invoke( - std::move(copy), - std::forward(value)); - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -private: - SideEffect _method; - -}; - -} // namespace details - -template -inline auto after_next(SideEffect &&method) --> details::after_next_helper> { - return details::after_next_helper>( - std::forward(method)); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/before_next.h b/Telegram/SourceFiles/rpl/before_next.h deleted file mode 100644 index 01261f1ee..000000000 --- a/Telegram/SourceFiles/rpl/before_next.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace rpl { - -template -inline auto before_next(SideEffect &&method) { - return filter([method = std::forward(method)]( - const auto &value) { - method(value); - return true; - }); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/combine.h b/Telegram/SourceFiles/rpl/combine.h deleted file mode 100644 index f7a1b018d..000000000 --- a/Telegram/SourceFiles/rpl/combine.h +++ /dev/null @@ -1,349 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/optional.h" -#include "base/variant.h" -#include -#include -#include -#include -#include -#include - -namespace rpl { -namespace details { - -template -struct combine_state { - combine_state() : accumulated(std::tuple...>()) { - } - std::optional...>> accumulated; - std::optional> latest; - int invalid = sizeof...(Values); - int working = sizeof...(Values); -}; - -template -inline std::tuple combine_make_first( - std::tuple...> &&accumulated, - std::index_sequence) { - return std::make_tuple(std::move(*std::get(accumulated))...); -} - -template -class combine_subscribe_one { -public: - combine_subscribe_one( - const consumer_type &consumer, - combine_state *state) - : _consumer(consumer) - , _state(state) { - } - - template - void subscribe(producer &&producer) { - _consumer.add_lifetime(std::move(producer).start( - [consumer = _consumer, state = _state](Value &&value) { - if (!state->accumulated) { - std::get(*state->latest) = std::move(value); - consumer.put_next_copy(*state->latest); - } else { - auto &accumulated = std::get( - *state->accumulated); - if (accumulated) { - accumulated = std::move(value); - } else { - accumulated = std::move(value); - if (!--state->invalid) { - constexpr auto kArity = sizeof...(Values); - state->latest = combine_make_first( - std::move(*state->accumulated), - std::make_index_sequence()); - state->accumulated = std::nullopt; - consumer.put_next_copy(*state->latest); - } - } - } - }, [consumer = _consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer = _consumer, state = _state] { - if (!--state->working) { - consumer.put_done(); - } - })); - } - -private: - const consumer_type &_consumer; - combine_state *_state = nullptr; - -}; - -template < - typename consumer_type, - typename ...Values, - typename ...Errors, - typename ...Generators, - std::size_t ...I> -inline void combine_subscribe( - const consumer_type &consumer, - combine_state *state, - std::index_sequence, - std::tuple...> &&saved) { - auto consume = { ( - combine_subscribe_one( - consumer, - state - ).subscribe(std::get(std::move(saved))), 0)... }; - (void)consume; -} - -template -class combine_implementation_helper; - -template -combine_implementation_helper...> -make_combine_implementation_helper(Producers &&...producers) { - return combine_implementation_helper...>( - std::forward(producers)...); -} - -template < - typename ...Values, - typename ...Errors, - typename ...Generators> -class combine_implementation_helper...> { -public: - using CombinedValue = std::tuple; - using CombinedError = base::normalized_variant_t; - - combine_implementation_helper( - producer &&...producers) - : _saved(std::make_tuple(std::move(producers)...)) { - } - - template - lifetime operator()(const consumer &consumer) { - auto state = consumer.template make_state< - combine_state>(); - constexpr auto kArity = sizeof...(Values); - combine_subscribe( - consumer, - state, - std::make_index_sequence(), - std::move(_saved)); - - return lifetime(); - } - -private: - std::tuple...> _saved; - -}; - -template < - typename ...Values, - typename ...Errors, - typename ...Generators> -inline auto combine_implementation( - producer &&...producers) { - using CombinedValue = std::tuple; - using CombinedError = base::normalized_variant_t; - - return make_producer( - make_combine_implementation_helper(std::move(producers)...)); -} - -template -struct combine_just_producers : std::false_type { -}; - -template -constexpr bool combine_just_producers_v - = combine_just_producers::value; - -template < - typename ...Values, - typename ...Errors, - typename ...Generators> -struct combine_just_producers< - producer...> - : std::true_type { -}; - -template -struct combine_just_producers_list - : type_list::extract_to_t { -}; - -template -struct combine_result_type; - -template -using combine_result_type_t - = typename combine_result_type::type; - -template < - typename ...Values, - typename ...Errors, - typename ...Generators> -struct combine_result_type...> { - using type = std::tuple; -}; - -template -struct combine_result_type_list - : type_list::extract_to_t { -}; - -template -using combine_result_type_list_t - = typename combine_result_type_list::type; - -template -using combine_producers_no_mapper_t - = type_list::chop_last_t; - -template -constexpr bool combine_is_good_mapper(std::true_type) { - return is_callable_v< - type_list::last_t, - combine_result_type_list_t< - combine_producers_no_mapper_t - >>; -} - -template -constexpr bool combine_is_good_mapper(std::false_type) { - return false; -} - -template -struct combine_producers_with_mapper_list : std::bool_constant< - combine_is_good_mapper( - combine_just_producers_list< - combine_producers_no_mapper_t - >())> { -}; - -template -struct combine_producers_with_mapper - : combine_producers_with_mapper_list> { -}; - -template -constexpr bool combine_producers_with_mapper_v - = combine_producers_with_mapper::value; - -template -inline decltype(auto) combine_call( - std::index_sequence, - Producers &&...producers) { - return combine_implementation( - argument_mapper::call(std::move(producers)...)...); -} - -} // namespace details - -template < - typename ...Args, - typename = std::enable_if_t< - details::combine_just_producers_v - || details::combine_producers_with_mapper_v>> -inline decltype(auto) combine(Args &&...args) { - if constexpr (details::combine_just_producers_v) { - return details::combine_implementation(std::move(args)...); - } else if constexpr (details::combine_producers_with_mapper_v) { - constexpr auto kProducersCount = sizeof...(Args) - 1; - return details::combine_call( - std::make_index_sequence(), - std::forward(args)...) - | map(details::argument_mapper::call( - std::forward(args)...)); - } else { - static_assert(false_(args...), "Bad combine() call."); - } -} - -namespace details { - -template -struct combine_vector_state { - std::vector> accumulated; - std::vector latest; - int invalid = 0; - int working = 0; -}; - -} // namespace details - -template -inline auto combine( - std::vector> &&producers) { - using state_type = details::combine_vector_state; - return make_producer, Error>([ - producers = std::move(producers) - ](const auto &consumer) mutable { - auto count = producers.size(); - auto state = consumer.template make_state(); - state->accumulated.resize(count); - state->invalid = count; - state->working = count; - for (auto index = 0; index != count; ++index) { - auto &producer = producers[index]; - consumer.add_lifetime(std::move(producer).start( - [consumer, state, index](Value &&value) { - if (state->accumulated.empty()) { - state->latest[index] = std::move(value); - consumer.put_next_copy(state->latest); - } else if (state->accumulated[index]) { - state->accumulated[index] = std::move(value); - } else { - state->accumulated[index] = std::move(value); - if (!--state->invalid) { - state->latest.reserve( - state->accumulated.size()); - for (auto &&value : state->accumulated) { - state->latest.push_back( - std::move(*value)); - } - details::take(state->accumulated); - consumer.put_next_copy(state->latest); - } - } - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer, state] { - if (!--state->working) { - consumer.put_done(); - } - })); - } - if (!count) { - consumer.put_done(); - } - return lifetime(); - }); -} - -template < - typename Value, - typename Error, - typename Generator, - typename Mapper> -inline auto combine( - std::vector> &&producers, - Mapper &&mapper) { - return combine(std::move(producers)) - | map(std::forward(mapper)); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/combine_previous.h b/Telegram/SourceFiles/rpl/combine_previous.h deleted file mode 100644 index d4c448a14..000000000 --- a/Telegram/SourceFiles/rpl/combine_previous.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include "base/optional.h" - -namespace rpl { -namespace details { - -class combine_previous_helper { -public: - template - auto operator()( - producer &&initial) const { - return make_producer, Error>([ - initial = std::move(initial) - ](const auto &consumer) mutable { - auto previous = consumer.template make_state< - std::optional - >(); - return std::move(initial).start( - [consumer, previous](auto &&value) { - if (auto &exists = *previous) { - auto &existing = *exists; - auto next = std::make_tuple( - std::move(existing), - value); - consumer.put_next(std::move(next)); - existing = std::forward( - value); - } else { - *previous = std::forward( - value); - } - }, [consumer](auto &&error) { - consumer.put_error_forward(std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -}; - -template -class combine_previous_with_default_helper { -public: - template - combine_previous_with_default_helper(OtherValue &&value) - : _value(std::forward(value)) { - } - - template - auto operator()(producer &&initial) { - return make_producer, Error>([ - initial = std::move(initial), - value = Value(std::move(_value)) - ](const auto &consumer) mutable { - auto previous = consumer.template make_state( - std::move(value)); - return std::move(initial).start( - [consumer, previous](auto &&value) { - auto &existing = *previous; - auto next = std::make_tuple( - std::move(existing), - value); - consumer.put_next(std::move(next)); - existing = std::forward(value); - }, [consumer](auto &&error) { - consumer.put_error_forward(std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -private: - DefaultValue _value; - -}; - -template -combine_previous_with_default_helper> -combine_previous_with_default(DefaultValue &&value) { - return { std::forward(value) }; -} - -} // namespace details - -inline auto combine_previous() --> details::combine_previous_helper { - return details::combine_previous_helper(); -} - -template -inline auto combine_previous(DefaultValue &&value) { - return details::combine_previous_with_default( - std::forward(value)); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/complete.h b/Telegram/SourceFiles/rpl/complete.h deleted file mode 100644 index 703b4a175..000000000 --- a/Telegram/SourceFiles/rpl/complete.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { - -template -inline auto complete() { - return make_producer([](const auto &consumer) { - consumer.put_done(); - return lifetime(); - }); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/conditional.h b/Telegram/SourceFiles/rpl/conditional.h deleted file mode 100644 index 15380a14f..000000000 --- a/Telegram/SourceFiles/rpl/conditional.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/optional.h" -#include "base/variant.h" -#include -#include - -namespace rpl { - -template < - typename Value, - typename Error, - typename GeneratorTest, - typename GeneratorA, - typename GeneratorB> -inline auto conditional( - rpl::producer &&test, - rpl::producer &&a, - rpl::producer &&b) { - return rpl::combine( - std::move(test), - std::move(a), - std::move(b) - ) | rpl::map([](bool test, Value &&a, Value &&b) { - return test ? std::move(a) : std::move(b); - }); - //struct conditional_state { - // std::optional a; - // std::optional b; - // char state = -1; - // int working = 3; - //}; - //return rpl::make_producer([ - // test = std::move(test), - // a = std::move(a), - // b = std::move(b) - //](const auto &consumer) mutable { - // auto result = lifetime(); - // const auto state = result.make_state(); - // result.add(std::move(test).start()) - // return result; - //}); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/consumer.h b/Telegram/SourceFiles/rpl/consumer.h deleted file mode 100644 index 09603116e..000000000 --- a/Telegram/SourceFiles/rpl/consumer.h +++ /dev/null @@ -1,636 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include - -// GCC 7.2 can't handle not type-erased consumers. -// It eats up 4GB RAM + 16GB swap on the unittest and dies. -// Clang and Visual C++ both handle it without such problems. -#if defined _DEBUG || defined COMPILER_GCC -#define RPL_CONSUMER_TYPE_ERASED_ALWAYS -#endif // _DEBUG || COMPILER_GCC - -namespace rpl { -namespace details { - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone> -class consumer_handlers; - -template -class type_erased_handlers { -public: - virtual bool put_next(Value &&value) = 0; - virtual bool put_next_copy(const Value &value) = 0; - virtual void put_error(Error &&error) = 0; - virtual void put_error_copy(const Error &error) = 0; - virtual void put_done() = 0; - - bool add_lifetime(lifetime &&lifetime); - - template - Type *make_state(Args&& ...args); - - void terminate(); - - virtual ~type_erased_handlers() = default; - -protected: - lifetime _lifetime; - bool _terminated = false; - -}; - -template -struct is_type_erased_handlers - : std::false_type { -}; - -template -struct is_type_erased_handlers> - : std::true_type { -}; - -template -constexpr bool is_type_erased_handlers_v - = is_type_erased_handlers::value; - -template -class consumer_handlers final - : public type_erased_handlers { -public: - template < - typename OnNextOther, - typename OnErrorOther, - typename OnDoneOther> - consumer_handlers( - OnNextOther &&next, - OnErrorOther &&error, - OnDoneOther &&done) - : _next(std::forward(next)) - , _error(std::forward(error)) - , _done(std::forward(done)) { - } - - bool put_next(Value &&value) final override; - bool put_next_copy(const Value &value) final override; - void put_error(Error &&error) final override; - void put_error_copy(const Error &error) final override; - void put_done() final override; - -private: - OnNext _next; - OnError _error; - OnDone _done; - -}; - -template -inline bool type_erased_handlers::add_lifetime( - lifetime &&lifetime) { - if (_terminated) { - lifetime.destroy(); - return false; - } - _lifetime.add(std::move(lifetime)); - return true; -} - -template -template -inline Type *type_erased_handlers::make_state( - Args&& ...args) { - if (_terminated) { - return nullptr; - } - return _lifetime.make_state(std::forward(args)...); -} - -template -inline void type_erased_handlers::terminate() { - if (!_terminated) { - _terminated = true; - _lifetime.destroy(); - } -} - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone> -bool consumer_handlers< - Value, - Error, - OnNext, - OnError, - OnDone ->::put_next(Value &&value) { - if (this->_terminated) { - return false; - } - auto handler = this->_next; - details::callable_invoke(std::move(handler), std::move(value)); - return true; -} - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone> -bool consumer_handlers< - Value, - Error, - OnNext, - OnError, - OnDone ->::put_next_copy(const Value &value) { - if (this->_terminated) { - return false; - } - auto handler = this->_next; - details::const_ref_call_invoke(std::move(handler), value); - return true; -} - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone> -void consumer_handlers< - Value, - Error, - OnNext, - OnError, - OnDone ->::put_error(Error &&error) { - if (!this->_terminated) { - details::callable_invoke( - std::move(this->_error), - std::move(error)); - this->terminate(); - } -} - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone> -void consumer_handlers< - Value, - Error, - OnNext, - OnError, - OnDone ->::put_error_copy(const Error &error) { - if (!this->_terminated) { - details::const_ref_call_invoke( - std::move(this->_error), - error); - this->terminate(); - } -} - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone> -void consumer_handlers< - Value, - Error, - OnNext, - OnError, - OnDone ->::put_done() { - if (!this->_terminated) { - std::move(this->_done)(); - this->terminate(); - } -} - -} // namespace details - -struct no_value { - no_value() = delete; -}; - -struct no_error { - no_error() = delete; -}; - -struct empty_value { -}; - -struct empty_error { -}; - -template < - typename Value = empty_value, - typename Error = no_error, - typename Handlers = details::type_erased_handlers> -class consumer; - -namespace details { - -template -class consumer_base { - static constexpr bool is_type_erased - = is_type_erased_handlers_v; - -public: - template < - typename OnNext, - typename OnError, - typename OnDone> - consumer_base( - OnNext &&next, - OnError &&error, - OnDone &&done); - - bool put_next(Value &&value) const; - bool put_next_copy(const Value &value) const; - bool put_next_forward(Value &&value) const { - return put_next(std::move(value)); - } - bool put_next_forward(const Value &value) const { - return put_next_copy(value); - } - void put_error(Error &&error) const; - void put_error_copy(const Error &error) const; - void put_error_forward(Error &&error) const { - return put_error(std::move(error)); - } - void put_error_forward(const Error &error) const { - return put_error_copy(error); - } - void put_done() const; - - bool add_lifetime(lifetime &&lifetime) const; - - template - Type *make_state(Args&& ...args) const; - - void terminate() const; - auto terminator() const { - return [self = *this] { - self.terminate(); - }; - } - - const details::type_erased_handlers *comparable() const { - return _handlers.get(); - } - -private: - template < - typename OtherHandlers, - typename = std::enable_if_t< - std::is_base_of_v>> - consumer_base(const std::shared_ptr &handlers) - : _handlers(handlers) { - } - - template < - typename OtherHandlers, - typename = std::enable_if_t< - std::is_base_of_v>> - consumer_base(std::shared_ptr &&handlers) - : _handlers(std::move(handlers)) { - } - - mutable std::shared_ptr _handlers; - - bool handlers_put_next(Value &&value) const { - if constexpr (is_type_erased) { - return _handlers->put_next(std::move(value)); - } else { - return _handlers->Handlers::put_next(std::move(value)); - } - } - bool handlers_put_next_copy(const Value &value) const { - if constexpr (is_type_erased) { - return _handlers->put_next_copy(value); - } else { - return _handlers->Handlers::put_next_copy(value); - } - } - std::shared_ptr take_handlers() const { - return std::exchange(_handlers, nullptr); - } - - template < - typename OtherValue, - typename OtherError, - typename OtherHandlers> - friend class ::rpl::consumer; - -}; - -template -template -inline consumer_base::consumer_base( - OnNext &&next, - OnError &&error, - OnDone &&done) -: _handlers(std::make_shared, - std::decay_t, - std::decay_t>>( - std::forward(next), - std::forward(error), - std::forward(done))) { -} - -template -inline bool consumer_base::put_next( - Value &&value) const { - if (_handlers) { - if (handlers_put_next(std::move(value))) { - return true; - } - _handlers = nullptr; - } - return false; -} - -template -inline bool consumer_base::put_next_copy( - const Value &value) const { - if (_handlers) { - if (handlers_put_next_copy(value)) { - return true; - } - _handlers = nullptr; - } - return false; -} - -template -inline void consumer_base::put_error( - Error &&error) const { - if (_handlers) { - if constexpr (is_type_erased) { - take_handlers()->put_error(std::move(error)); - } else { - take_handlers()->Handlers::put_error(std::move(error)); - } - } -} - -template -inline void consumer_base::put_error_copy( - const Error &error) const { - if (_handlers) { - if constexpr (is_type_erased) { - take_handlers()->put_error_copy(error); - } else { - take_handlers()->Handlers::put_error_copy(error); - } - } -} - -template -inline void consumer_base::put_done() const { - if (_handlers) { - if constexpr (is_type_erased) { - take_handlers()->put_done(); - } else { - take_handlers()->Handlers::put_done(); - } - } -} - -template -inline bool consumer_base::add_lifetime( - lifetime &&lifetime) const { - if (!_handlers) { - lifetime.destroy(); - return false; - } - if (_handlers->add_lifetime(std::move(lifetime))) { - return true; - } - _handlers = nullptr; - return false; -} - -template -template -inline Type *consumer_base::make_state( - Args&& ...args) const { - if (!_handlers) { - return nullptr; - } - if (auto result = _handlers->template make_state( - std::forward(args)...)) { - return result; - } - _handlers = nullptr; - return nullptr; -} - -template -inline void consumer_base::terminate() const { - if (_handlers) { - std::exchange(_handlers, nullptr)->terminate(); - } -} - -template -using consumer_base_type_erased = consumer_base< - Value, - Error, - details::type_erased_handlers>; - -template -constexpr bool is_specific_handlers_v = !std::is_same_v< - details::type_erased_handlers, - Handlers -> && std::is_base_of_v< - details::type_erased_handlers, - Handlers ->; - -} // namespace details - -template -class consumer final -: public details::consumer_base { - using parent_type = details::consumer_base< - Value, - Error, - Handlers>; - -public: - using parent_type::parent_type; - -}; - -template -class consumer> final -: public details::consumer_base_type_erased { - using parent_type = details::consumer_base_type_erased< - Value, - Error>; - -public: - using parent_type::parent_type; - - template < - typename Handlers, - typename = std::enable_if_t< - details::is_specific_handlers_v>> - consumer(const details::consumer_base &other) - : parent_type(other._handlers) { - } - - template < - typename Handlers, - typename = std::enable_if_t< - details::is_specific_handlers_v>> - consumer(details::consumer_base &&other) - : parent_type(std::move(other._handlers)) { - } - - template < - typename Handlers, - typename = std::enable_if_t< - details::is_specific_handlers_v>> - consumer &operator=( - const details::consumer_base &other) { - this->_handlers = other._handlers; - return *this; - } - - template < - typename Handlers, - typename = std::enable_if_t< - details::is_specific_handlers_v>> - consumer &operator=( - details::consumer_base &&other) { - this->_handlers = std::move(other._handlers); - return *this; - } - -}; - -template < - typename Value, - typename Error, - typename Handlers1, - typename Handlers2> -inline bool operator==( - const consumer &a, - const consumer &b) { - return a.comparable() == b.comparable(); -} - -template < - typename Value, - typename Error, - typename Handlers1, - typename Handlers2> -inline bool operator<( - const consumer &a, - const consumer &b) { - return a.comparable() < b.comparable(); -} - -template < - typename Value, - typename Error, - typename Handlers1, - typename Handlers2> -inline bool operator!=( - const consumer &a, - const consumer &b) { - return !(a == b); -} - -template < - typename Value, - typename Error, - typename Handlers1, - typename Handlers2> -inline bool operator>( - const consumer &a, - const consumer &b) { - return b < a; -} - -template < - typename Value, - typename Error, - typename Handlers1, - typename Handlers2> -inline bool operator<=( - const consumer &a, - const consumer &b) { - return !(b < a); -} - -template < - typename Value, - typename Error, - typename Handlers1, - typename Handlers2> -inline bool operator>=( - const consumer &a, - const consumer &b) { - return !(a < b); -} - -template < - typename Value, - typename Error, - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - details::is_callable_v && - details::is_callable_v && - details::is_callable_v>> -#ifdef RPL_CONSUMER_TYPE_ERASED_ALWAYS -inline consumer make_consumer( -#else // RPL_CONSUMER_TYPE_ERASED_ALWAYS -inline auto make_consumer( -#endif // !RPL_CONSUMER_TYPE_ERASED_ALWAYS - OnNext &&next, - OnError &&error, - OnDone &&done) { - return consumer, - std::decay_t, - std::decay_t>>( - std::forward(next), - std::forward(error), - std::forward(done)); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/deferred.h b/Telegram/SourceFiles/rpl/deferred.h deleted file mode 100644 index a8848e749..000000000 --- a/Telegram/SourceFiles/rpl/deferred.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { - -template < - typename Creator, - typename Value = typename decltype(std::declval()())::value_type, - typename Error = typename decltype(std::declval()())::error_type> -inline auto deferred(Creator &&creator) { - return make_producer([ - creator = std::forward(creator) - ](const auto &consumer) mutable { - return std::move(creator)().start_existing(consumer); - }); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/details/callable.h b/Telegram/SourceFiles/rpl/details/callable.h deleted file mode 100644 index 3598e0318..000000000 --- a/Telegram/SourceFiles/rpl/details/callable.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/build_config.h" -#include - -namespace rpl { -namespace details { - -template -const Arg &const_ref_val() noexcept; - -template -Arg &lvalue_ref_val() noexcept; - -using false_t = char; -struct true_t { - false_t data[2]; -}; -static_assert(sizeof(false_t) != sizeof(true_t), "I can't work :("); - -template < - typename Method, - typename ...Args, - typename = decltype(std::declval()( - std::declval()...))> -true_t test_callable_plain(Method &&, Args &&...) noexcept; -false_t test_callable_plain(...) noexcept; - -template -struct is_callable_plain - : std::bool_constant<( - sizeof(test_callable_plain( - std::declval(), - std::declval()... - )) == sizeof(true_t))> { -}; - -template -constexpr bool is_callable_plain_v = is_callable_plain::value; - -template < - typename Method, - typename ...Types, - typename = decltype(std::declval()( - std::declval()...))> -true_t test_callable_tuple( - Method &&, - std::tuple &&) noexcept; -template < - typename Method, - typename ...Types, - typename = decltype(std::declval()( - const_ref_val()...))> -true_t test_callable_tuple( - Method &&, - const std::tuple &) noexcept; -false_t test_callable_tuple(...) noexcept; - -template -constexpr bool is_callable_tuple_v = (sizeof(test_callable_tuple( - std::declval(), - std::declval())) == sizeof(true_t)); - -template -struct is_callable_tuple - : std::bool_constant< - is_callable_tuple_v> { -}; - -template -struct is_callable; - -template -struct is_callable - : std::bool_constant< - is_callable_plain_v> { -}; - -template -struct is_callable - : std::bool_constant< - is_callable_plain_v || - is_callable_tuple_v || - is_callable_plain_v> { -}; - -template -constexpr bool is_callable_v = is_callable::value; - -template -inline decltype(auto) callable_invoke(Method &&method, Arg &&arg) { - if constexpr (is_callable_plain_v) { - return std::forward(method)(std::forward(arg)); - } else if constexpr (is_callable_tuple_v) { - return std::apply( - std::forward(method), - std::forward(arg)); - } else if constexpr (is_callable_v) { - return std::forward(method)(); - } else { - static_assert(false_(method, arg), "Bad callable_invoke() call."); - } -} - -template -using callable_result = decltype(callable_invoke( - std::declval(), - std::declval())); - -template < - typename Method, - typename Arg, - typename = decltype(std::declval()( - const_ref_val>()))> -true_t test_allows_const_ref(Method &&, Arg &&) noexcept; -false_t test_allows_const_ref(...) noexcept; - -template -constexpr bool allows_const_ref_v = (sizeof(test_allows_const_ref( - std::declval(), - std::declval())) == sizeof(true_t)); - -template -inline decltype(auto) const_ref_call_invoke( - Method &&method, - const Arg &arg) { - if constexpr (allows_const_ref_v) { - return callable_invoke(std::forward(method), arg); - } else { - auto copy = arg; - return callable_invoke( - std::forward(method), - std::move(copy)); - } -} - -} // namespace details -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/details/superset_type.h b/Telegram/SourceFiles/rpl/details/superset_type.h deleted file mode 100644 index dc70d78b9..000000000 --- a/Telegram/SourceFiles/rpl/details/superset_type.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace rpl { - -template -struct superset_type; - -template -using superset_type_t = typename superset_type::type; - -template -struct superset_type { - using type = Value; -}; - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/details/type_list.h b/Telegram/SourceFiles/rpl/details/type_list.h deleted file mode 100644 index 31a381de5..000000000 --- a/Telegram/SourceFiles/rpl/details/type_list.h +++ /dev/null @@ -1,180 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { -namespace type_list { - -template -struct list { -}; - -template -struct list { - using head = Type; - using tail = list; -}; - -using empty_list = list<>; - -template -using head_t = typename TypeList::head; - -template -using tail_t = typename TypeList::tail; - -template -struct construct; - -template -using construct_t = typename construct::type; - -template -struct construct> { - using type = list; -}; - -template -struct size; - -template -constexpr std::size_t size_v = size::value; - -template -struct size> - : std::integral_constant< - std::size_t, - sizeof...(Types)> { -}; - -template -constexpr bool empty_v = (size_v == 0); - -template -struct empty : std::bool_constant> { -}; - -template -struct get; - -template -using get_t = typename get::type; - -template -struct get { - using type = get_t>; -}; - -template -struct get<0, TypeList> { - using type = head_t; -}; - -template -struct concat; - -template -using concat_t = typename concat::type; - -template -struct concat, list> { - using type = list; -}; - -template -struct remove_all; - -template -using remove_all_t = typename remove_all::type; - -template -struct remove_all { - using head = head_t; - using tail = tail_t; - using clean_tail = remove_all_t; - using type = std::conditional_t< - std::is_same_v, - clean_tail, - construct_t>; -}; - -template -struct remove_all { - using type = empty_list; -}; - -template -struct last; - -template -using last_t = typename last::type; - -template -struct last { - using type = last_t>; -}; - -template -struct last> { - using type = Type; -}; - -template -struct chop_last; - -template -using chop_last_t = typename chop_last::type; - -template -struct chop_last { - using type = construct_t< - head_t, - chop_last_t>>; -}; - -template -struct chop_last> { - using type = empty_list; -}; - -template -struct distinct; - -template -using distinct_t = typename distinct::type; - -template -struct distinct { - using type = construct_t< - head_t, - distinct_t< - remove_all_t, head_t>>>; -}; - -template <> -struct distinct { - using type = empty_list; -}; - -template typename To> -struct extract_to; - -template typename To> -using extract_to_t = typename extract_to::type; - -template typename To> -struct extract_to, To> { - using type = To; -}; - -} // namespace type_list -} // namespace details -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/distinct_until_changed.h b/Telegram/SourceFiles/rpl/distinct_until_changed.h deleted file mode 100644 index a81d00ce7..000000000 --- a/Telegram/SourceFiles/rpl/distinct_until_changed.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include "base/optional.h" - -namespace rpl { -namespace details { - -class distinct_until_changed_helper { -public: - template - auto operator()( - producer &&initial) const { - return make_producer([ - initial = std::move(initial) - ](const auto &consumer) mutable { - auto previous = consumer.template make_state< - std::optional - >(); - return std::move(initial).start( - [consumer, previous](auto &&value) { - if (!(*previous) || (**previous) != value) { - *previous = value; - consumer.put_next_forward(std::forward(value)); - } - }, [consumer](auto &&error) { - consumer.put_error_forward(std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -}; - -} // namespace details - -inline auto distinct_until_changed() --> details::distinct_until_changed_helper { - return details::distinct_until_changed_helper(); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/event_stream.h b/Telegram/SourceFiles/rpl/event_stream.h deleted file mode 100644 index f98be33d6..000000000 --- a/Telegram/SourceFiles/rpl/event_stream.h +++ /dev/null @@ -1,293 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "base/assertion.h" -#include "base/index_based_iterator.h" - -namespace rpl { - -// Currently not thread-safe :( - -template -class event_stream { -public: - event_stream(); - event_stream(event_stream &&other); - event_stream &operator=(event_stream &&other); - - template - void fire_forward(OtherValue &&value) const; - void fire(Value &&value) const { - return fire_forward(std::move(value)); - } - void fire_copy(const Value &value) const { - return fire_forward(value); - } - - template - void fire_error_forward(OtherError &&error) const; - void fire_error(Error &&error) const { - return fire_error_forward(std::move(error)); - } - void fire_error_copy(const Error &error) const { - return fire_error_forward(error); - } - - void fire_done() const; - -#if defined _MSC_VER && _MSC_VER >= 1914 && _MSC_VER < 1916 - producer events() const { -#else // _MSC_VER >= 1914 && _MSC_VER < 1916 - auto events() const { -#endif // _MSC_VER >= 1914 && _MSC_VER < 1916 - return make_producer([weak = make_weak()]( - const auto &consumer) { - if (const auto strong = weak.lock()) { - auto result = [weak, consumer] { - if (const auto strong = weak.lock()) { - const auto it = std::find( - strong->consumers.begin(), - strong->consumers.end(), - consumer); - if (it != strong->consumers.end()) { - it->terminate(); - } - } - }; - strong->consumers.push_back(std::move(consumer)); - return lifetime(std::move(result)); - } - return lifetime(); - }); - } - auto events_starting_with(Value &&value) const { - return single(std::move(value)) | then(events()); - } - auto events_starting_with_copy(const Value &value) const { - return single(value) | then(events()); - } - bool has_consumers() const { - return (_data != nullptr) && !_data->consumers.empty(); - } - - ~event_stream(); - -private: - struct Data { - std::vector> consumers; - int depth = 0; - }; - std::weak_ptr make_weak() const; - - mutable std::shared_ptr _data; - -}; - -template -inline event_stream::event_stream() { -} - -template -inline event_stream::event_stream(event_stream &&other) -: _data(details::take(other._data)) { -} - -template -inline event_stream &event_stream::operator=( - event_stream &&other) { - if (this != &other) { - std::swap(_data, other._data); - other.fire_done(); - } - return *this; -} - -template -template -inline void event_stream::fire_forward( - OtherValue &&value) const { - if (!_data) { - return; - } - const auto copy = _data; - auto &consumers = copy->consumers; - if (consumers.empty()) { - return; - } - - ++copy->depth; - const auto begin = base::index_based_begin(consumers); - const auto end = base::index_based_end(consumers); - - // Copy value for every consumer except the last. - const auto prev = end - 1; - auto staleFrom = std::remove_if(begin, prev, [&](const auto &consumer) { - return !consumer.put_next_copy(value); - }); - - // Perhaps move value for the last consumer. - if (prev->put_next_forward(std::forward(value))) { - if (staleFrom != prev) { - *staleFrom++ = std::move(*prev); - } else { - ++staleFrom; - } - } - - if (staleFrom != end) { - // Move new consumers. - const auto newEnd = base::index_based_end(consumers); - if (newEnd != end) { - Assert(newEnd > end); - for (auto i = end; i != newEnd;) { - *staleFrom++ = *i++; - } - } - - // Erase stale consumers. - if (copy->depth == 1) { - consumers.erase(staleFrom.base(), consumers.end()); - } - } - --copy->depth; -} - -template -template -inline void event_stream::fire_error_forward( - OtherError &&error) const { - if (!_data) { - return; - } - const auto data = std::move(_data); - const auto &consumers = data->consumers; - if (consumers.empty()) { - return; - } - const auto begin = base::index_based_begin(consumers); - const auto end = base::index_based_end(consumers); - - // Copy error for every consumer except the last. - const auto prev = end - 1; - std::for_each(begin, prev, [&](const auto &consumer) { - consumer.put_error_copy(error); - }); - - // Perhaps move error for the last consumer. - prev->put_error_forward(std::forward(error)); - - // Just drop any new consumers. -} - -template -void event_stream::fire_done() const { - if (const auto data = details::take(_data)) { - for (const auto &consumer : data->consumers) { - consumer.put_done(); - } - } -} - -template -inline auto event_stream::make_weak() const --> std::weak_ptr { - if (!_data) { - _data = std::make_shared(); - } - return _data; -} - -template -inline event_stream::~event_stream() { - fire_done(); -} - -template -inline auto start_to_stream( - event_stream &stream, - lifetime &alive_while) { - if constexpr (std::is_same_v) { - return start_with_next_done([&](auto &&value) { - stream.fire_forward(std::forward(value)); - }, [&] { - stream.fire_done(); - }, alive_while); - } else { - return start_with_next_error_done([&](auto &&value) { - stream.fire_forward(std::forward(value)); - }, [&](auto &&error) { - stream.fire_error_forward(std::forward(error)); - }, [&] { - stream.fire_done(); - }, alive_while); - } -} - -namespace details { - -class start_spawning_helper { -public: - start_spawning_helper(lifetime &alive_while) - : _lifetime(alive_while) { - } - - template - auto operator()(producer &&initial) { - auto stream = _lifetime.make_state>(); - auto values = std::vector(); - if constexpr (std::is_same_v) { - auto collecting = stream->events().start( - [&](Value &&value) { values.push_back(std::move(value)); }, - [](const Error &error) {}, - [] {}); - std::move(initial) | start_to_stream(*stream, _lifetime); - collecting.destroy(); - - return vector(std::move(values)) | then(stream->events()); - } else { - auto maybeError = std::optional(); - auto collecting = stream->events().start( - [&](Value && value) { values.push_back(std::move(value)); }, - [&](Error &&error) { maybeError = std::move(error); }, - [] {}); - std::move(initial) | start_to_stream(*stream, _lifetime); - collecting.destroy(); - - if (maybeError.has_value()) { - return rpl::producer([ - error = std::move(*maybeError) - ](const auto &consumer) mutable { - consumer.put_error(std::move(error)); - }); - } - return rpl::producer(vector( - std::move(values) - ) | then(stream->events())); - } - } - -private: - lifetime &_lifetime; - -}; - -} // namespace details - -inline auto start_spawning(lifetime &alive_while) --> details::start_spawning_helper { - return details::start_spawning_helper(alive_while); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/fail.h b/Telegram/SourceFiles/rpl/fail.h deleted file mode 100644 index 7db387cf2..000000000 --- a/Telegram/SourceFiles/rpl/fail.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { - -template -inline auto fail(Error &&error) { - return make_producer>([ - error = std::forward(error) - ](const auto &consumer) mutable { - consumer.put_error(std::move(error)); - return lifetime(); - }); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/filter.h b/Telegram/SourceFiles/rpl/filter.h deleted file mode 100644 index 08d11ba74..000000000 --- a/Telegram/SourceFiles/rpl/filter.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include "base/optional.h" - -namespace rpl { -namespace details { - -template -class filter_helper { -public: - template - filter_helper(OtherPredicate &&predicate) - : _predicate(std::forward(predicate)) { - } - - template < - typename Value, - typename Error, - typename Generator, - typename = std::enable_if_t< - details::is_callable_v>> - auto operator()(producer &&initial) { - return make_producer([ - initial = std::move(initial), - predicate = std::move(_predicate) - ](const auto &consumer) mutable { - return std::move(initial).start( - [ - consumer, - predicate = std::move(predicate) - ](auto &&value) { - const auto &immutable = value; - if (details::callable_invoke( - predicate, - immutable) - ) { - consumer.put_next_forward( - std::forward(value)); - } - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -private: - Predicate _predicate; - -}; - -} // namespace details - -template -inline auto filter(Predicate &&predicate) --> details::filter_helper> { - return details::filter_helper>( - std::forward(predicate)); -} - -namespace details { - -template -class filter_helper> { -public: - filter_helper( - producer &&filterer) - : _filterer(std::move(filterer)) { - } - - template - auto operator()(producer &&initial) { - using namespace mappers; - return combine(std::move(initial), std::move(_filterer)) - | filter(_2) - | map(_1_of_two); - } - -private: - producer _filterer; - -}; - -template -inline const Value &deref_optional_helper( - const std::optional &value) { - return *value; -} - -template -inline Value &&deref_optional_helper( - std::optional &&value) { - return std::move(*value); -} - -class filter_optional_helper { -public: - template - auto operator()(producer< - std::optional, - Error, - Generator> &&initial) const { - return make_producer([ - initial = std::move(initial) - ](const auto &consumer) mutable { - return std::move(initial).start( - [consumer](auto &&value) { - if (value) { - consumer.put_next_forward( - deref_optional_helper( - std::forward( - value))); - } - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -}; - -} // namespace details - -inline auto filter_optional() --> details::filter_optional_helper { - return details::filter_optional_helper(); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/flatten_latest.h b/Telegram/SourceFiles/rpl/flatten_latest.h deleted file mode 100644 index 33cdbd88a..000000000 --- a/Telegram/SourceFiles/rpl/flatten_latest.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { - -class flatten_latest_helper { -public: - template < - typename Value, - typename Error, - typename Generator, - typename MetaGenerator> - auto operator()(producer< - producer, - Error, - MetaGenerator> &&initial) const { - return make_producer([ - initial = std::move(initial) - ](const auto &consumer) mutable { - auto state = consumer.template make_state(); - return std::move(initial).start( - [consumer, state](producer &&inner) { - state->finished = false; - state->alive = lifetime(); - std::move(inner).start( - [consumer](auto &&value) { - consumer.put_next_forward(std::forward(value)); - }, [consumer](auto &&error) { - consumer.put_error_forward(std::forward(error)); - }, [consumer, state] { - if (state->finished) { - consumer.put_done(); - } else { - state->finished = true; - } - }, state->alive); - }, [consumer](auto &&error) { - consumer.put_error_forward(std::forward(error)); - }, [consumer, state] { - if (state->finished) { - consumer.put_done(); - } else { - state->finished = true; - } - }); - }); - } - -private: - struct State { - lifetime alive; - bool finished = false; - }; - -}; - -} // namespace details - -inline auto flatten_latest() --> details::flatten_latest_helper { - return details::flatten_latest_helper(); -} - -} // namespace rpl - diff --git a/Telegram/SourceFiles/rpl/lifetime.h b/Telegram/SourceFiles/rpl/lifetime.h deleted file mode 100644 index a8a2b77f7..000000000 --- a/Telegram/SourceFiles/rpl/lifetime.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/unique_function.h" -#include - -namespace rpl { -namespace details { - -template -inline Type take(Type &value) { - return std::exchange(value, Type{}); -} - -} // namespace details - -class lifetime { -public: - lifetime() = default; - lifetime(lifetime &&other); - lifetime &operator=(lifetime &&other); - ~lifetime() { destroy(); } - - template ()())> - lifetime(Destroy &&destroy); - - explicit operator bool() const { return !_callbacks.empty(); } - - template ()())> - void add(Destroy &&destroy); - void add(lifetime &&other); - void destroy(); - - template - Type *make_state(Args&& ...args) { - const auto result = new Type(std::forward(args)...); - add([=] { - static_assert(sizeof(Type) > 0, "Can't delete unknown type."); - delete result; - }); - return result; - } - -private: - std::vector> _callbacks; - -}; - -inline lifetime::lifetime(lifetime &&other) -: _callbacks(details::take(other._callbacks)) { -} - -inline lifetime &lifetime::operator=(lifetime &&other) { - std::swap(_callbacks, other._callbacks); - other.destroy(); - return *this; -} - -template -inline lifetime::lifetime(Destroy &&destroy) { - _callbacks.emplace_back(std::forward(destroy)); -} - -template -inline void lifetime::add(Destroy &&destroy) { - _callbacks.emplace_back(std::forward(destroy)); -} - -inline void lifetime::add(lifetime &&other) { - auto callbacks = details::take(other._callbacks); - _callbacks.insert( - _callbacks.end(), - std::make_move_iterator(callbacks.begin()), - std::make_move_iterator(callbacks.end())); -} - -inline void lifetime::destroy() { - auto callbacks = details::take(_callbacks); - for (auto i = callbacks.rbegin(), e = callbacks.rend(); i != e; ++i) { - (*i)(); - } -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/map.h b/Telegram/SourceFiles/rpl/map.h deleted file mode 100644 index 4003141a4..000000000 --- a/Telegram/SourceFiles/rpl/map.h +++ /dev/null @@ -1,211 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { - -template < - typename Transform, - typename NewValue, - typename Error, - typename Handlers> -class map_transform_helper { -public: - map_transform_helper( - Transform &&transform, - const consumer &consumer) - : _consumer(consumer) - , _transform(std::move(transform)) { - } - template < - typename OtherValue, - typename = std::enable_if_t< - std::is_rvalue_reference_v>> - void operator()(OtherValue &&value) const { - _consumer.put_next_forward( - details::callable_invoke(_transform, std::move(value))); - } - template < - typename OtherValue, - typename = decltype( - std::declval()(const_ref_val()))> - void operator()(const OtherValue &value) const { - _consumer.put_next_forward( - details::callable_invoke(_transform, value)); - } - -private: - consumer _consumer; - Transform _transform; - -}; - -template < - typename Transform, - typename NewValue, - typename Error, - typename Handlers, - typename = std::enable_if_t< - std::is_rvalue_reference_v>> -inline map_transform_helper -map_transform( - Transform &&transform, - const consumer &consumer) { - return { std::move(transform), consumer }; -} - -template -class map_helper { -public: - template - map_helper(OtherTransform &&transform) - : _transform(std::forward(transform)) { - } - - template < - typename Value, - typename Error, - typename Generator, - typename NewValue = details::callable_result< - Transform, - Value>> - auto operator()(producer &&initial) { - return make_producer([ - initial = std::move(initial), - transform = std::move(_transform) - ](const auto &consumer) mutable { - return std::move(initial).start( - map_transform( - std::move(transform), - consumer - ), [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - }); - } - -private: - Transform _transform; - -}; - -} // namespace details - -template -inline auto map(Transform &&transform) --> details::map_helper> { - return details::map_helper>( - std::forward(transform)); -} - -namespace details { - -template < - typename Transform, - typename Value, - typename NewError, - typename Handlers> -class map_error_transform_helper { -public: - map_error_transform_helper( - Transform &&transform, - const consumer &consumer) - : _transform(std::move(transform)) - , _consumer(consumer) { - } - template < - typename OtherError, - typename = std::enable_if_t< - std::is_rvalue_reference_v>> - void operator()(OtherError &&error) const { - _consumer.put_error_forward( - details::callable_invoke(_transform, std::move(error))); - } - template < - typename OtherError, - typename = decltype( - std::declval()(const_ref_val()))> - void operator()(const OtherError &error) const { - _consumer.put_error_forward( - details::callable_invoke(_transform, error)); - } - -private: - consumer _consumer; - Transform _transform; - -}; - -template < - typename Transform, - typename Value, - typename NewError, - typename Handlers, - typename = std::enable_if_t< - std::is_rvalue_reference_v>> -inline map_error_transform_helper -map_error_transform( - Transform &&transform, - const consumer &consumer) { - return { std::move(transform), consumer }; -} - -template -class map_error_helper { -public: - template - map_error_helper(OtherTransform &&transform) - : _transform(std::forward(transform)) { - } - - template < - typename Value, - typename Error, - typename Generator, - typename NewError = details::callable_result< - Transform, - Error>> - auto operator()(producer &&initial) { - return make_producer([ - initial = std::move(initial), - transform = std::move(_transform) - ](const auto &consumer) mutable { - return std::move(initial).start( - [consumer](auto &&value) { - consumer.put_next_forward( - std::forward(value)); - }, map_error_transform( - std::move(transform), - consumer - ), [consumer] { - consumer.put_done(); - }); - }); - } - -private: - Transform _transform; - -}; - -} // namespace details - -template -inline auto map_error(Transform &&transform) --> details::map_error_helper> { - return details::map_error_helper>( - std::forward(transform)); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/mappers.h b/Telegram/SourceFiles/rpl/mappers.h deleted file mode 100644 index 0e69da142..000000000 --- a/Telegram/SourceFiles/rpl/mappers.h +++ /dev/null @@ -1,474 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace rpl { -namespace details { - -struct base_mapper { -}; - -template -constexpr bool is_mapper_v = std::is_base_of_v< - base_mapper, - std::decay_t>; - -template -struct argument_mapper : base_mapper { - template < - typename Arg, - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) >= Index)>> - static constexpr decltype(auto) call(Arg &&arg, Args &&...args) { - return argument_mapper::call( - std::forward(args)...); - } - - template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > Index)>> - constexpr auto operator()(Args &&...args) const { - return call(std::forward(args)...); - } - -}; - -template <> -struct argument_mapper<0> : base_mapper { - template < - typename Arg, - typename ...Args> - static constexpr decltype(auto) call(Arg &&arg, Args &&...args) { - return std::forward(arg); - } - - template < - typename Arg, - typename ...Args> - constexpr auto operator()(Arg &&arg, Args &&...args) const { - return std::forward(arg); - } - -}; - -template -class value_mapper : public base_mapper { -public: - template - constexpr value_mapper(OtherType &&value) - : _value(std::forward(value)) { - } - - template - constexpr auto operator()(Args &&...args) const { - return _value; - } - -private: - Type _value; - -}; - -template -struct wrap_mapper { - using type = std::conditional_t< - is_mapper_v, - Type, - value_mapper>; -}; - -template -using wrap_mapper_t = typename wrap_mapper::type; - -template -class unary_operator_mapper : public base_mapper { - using TypeWrapper = wrap_mapper_t>; - -public: - template - constexpr unary_operator_mapper(OtherType &&value) - : _value(std::forward(value)) { - } - - template < - typename ...Args, - typename Result = decltype((Operator{})( - std::declval()(std::declval()...)))> - constexpr std::decay_t operator()(Args &&...args) const { - return (Operator{})( - _value(std::forward(args)...)); - } - -private: - TypeWrapper _value; - -}; - -template -class binary_operator_mapper : public base_mapper { - using LeftWrapper = wrap_mapper_t>; - using RightWrapper = wrap_mapper_t>; - -public: - template - constexpr binary_operator_mapper(OtherLeft &&left, OtherRight &&right) - : _left(std::forward(left)) - , _right(std::forward(right)) { - } - - template < - typename ...Args, - typename Result = decltype((Operator{})( - std::declval()(std::declval()...), - std::declval()(std::declval()...)))> - constexpr std::decay_t operator()(Args &&...args) const { - return (Operator{})( - _left(std::forward(args)...), - _right(std::forward(args)...)); - } - -private: - LeftWrapper _left; - RightWrapper _right; - -}; - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator+(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::plus<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator-(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::minus<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator*(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::multiplies<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator/(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::divides<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator%(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::modulus<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Type, - typename = std::enable_if_t< - is_mapper_v - >> -inline auto operator-(Type &&value) { - return unary_operator_mapper< - Type, - std::negate<>>( - std::forward(value)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator<(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::less<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator<=(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::less_equal<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator>(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::greater<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator>=(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::greater_equal<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator==(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::equal_to<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator!=(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::not_equal_to<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator&&(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::logical_and<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator||(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::logical_or<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Type, - typename = std::enable_if_t< - is_mapper_v - >> -inline auto operator!(Type &&value) { - return unary_operator_mapper< - Type, - std::logical_not<>>( - std::forward(value)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator&(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::bit_and<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator|(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::bit_or<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Left, - typename Right, - typename = std::enable_if_t< - is_mapper_v || is_mapper_v - >> -inline auto operator^(Left &&left, Right &&right) { - return binary_operator_mapper< - Left, - Right, - std::bit_xor<>>( - std::forward(left), - std::forward(right)); -} - -template < - typename Type, - typename = std::enable_if_t< - is_mapper_v - >> -inline auto operator~(Type &&value) { - return unary_operator_mapper< - Type, - std::bit_not<>>( - std::forward(value)); -} - -template -class tuple_mapper { - template - using tuple_result = std::tuple>>()( - std::declval()...))...>; -public: - template - tuple_mapper(OtherMappers &&...mappers) : _mappers( - std::forward(mappers)...) { - } - - template - constexpr tuple_result operator()( - Args &&...args) const { - constexpr auto kArity = sizeof...(Mappers); - return call_helper( - std::make_index_sequence(), - std::forward(args)...); - } - -private: - template - inline tuple_result call_helper( - std::index_sequence, - Args &&...args) const { - return std::make_tuple( - std::get(_mappers)(std::forward(args)...)...); - } - - std::tuple>...> _mappers; - -}; - -template -tuple_mapper tuple(Args &&...args) { - return tuple_mapper(std::forward(args)...); -} - -} // namespace details - -namespace mappers { - -constexpr const details::argument_mapper<0> _1; -constexpr const details::argument_mapper<1> _2; -constexpr const details::argument_mapper<2> _3; -constexpr const details::argument_mapper<3> _4; -constexpr const details::argument_mapper<4> _5; -constexpr const details::argument_mapper<5> _6; -constexpr const details::argument_mapper<6> _7; -constexpr const details::argument_mapper<7> _8; -constexpr const details::argument_mapper<8> _9; -constexpr const details::argument_mapper<9> _10; - -constexpr const auto _1_of_two = ((void)_2, _1); - -} // namespace mappers -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/merge.h b/Telegram/SourceFiles/rpl/merge.h deleted file mode 100644 index 84287ef87..000000000 --- a/Telegram/SourceFiles/rpl/merge.h +++ /dev/null @@ -1,149 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { - -struct merge_state { - merge_state(int working) : working(working) { - } - int working = 0; -}; - -template -class merge_subscribe_one { -public: - merge_subscribe_one( - const consumer_type &consumer, - merge_state *state) - : _consumer(consumer) - , _state(state) { - } - - template - void subscribe(producer &&producer) { - _consumer.add_lifetime(std::move(producer).start( - [consumer = _consumer](auto &&value) { - consumer.put_next_forward( - std::forward(value)); - }, [consumer = _consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer = _consumer, state = _state] { - if (!--state->working) { - consumer.put_done(); - } - })); - } - -private: - const consumer_type &_consumer; - merge_state *_state = nullptr; - -}; - -template < - typename consumer_type, - typename Value, - typename Error, - typename ...Generators, - std::size_t ...I> -inline void merge_subscribe( - const consumer_type &consumer, - merge_state *state, - std::index_sequence, - std::tuple...> &&saved) { - auto consume = { ( - details::merge_subscribe_one( - consumer, - state - ).subscribe(std::get(std::move(saved))), 0)... }; - (void)consume; -} - -template -class merge_implementation_helper; - -template -merge_implementation_helper...> -make_merge_implementation_helper(Producers &&...producers) { - return merge_implementation_helper...>( - std::forward(producers)...); -} - -template < - typename Value, - typename Error, - typename ...Generators> -class merge_implementation_helper...> { -public: - merge_implementation_helper( - producer &&...producers) - : _saved(std::make_tuple(std::move(producers)...)) { - } - - template - lifetime operator()(const consumer &consumer) { - auto state = consumer.template make_state< - details::merge_state>(sizeof...(Generators)); - constexpr auto kArity = sizeof...(Generators); - details::merge_subscribe( - consumer, - state, - std::make_index_sequence(), - std::move(_saved)); - - return lifetime(); - } - -private: - std::tuple...> _saved; - -}; - -template < - typename Value, - typename Error, - typename ...Generators> -inline auto merge_implementation( - producer &&...producers) { - return make_producer( - make_merge_implementation_helper(std::move(producers)...)); -} - -template -struct merge_producers : std::false_type { -}; - -template -constexpr bool merge_producers_v - = merge_producers::value; - -template < - typename Value, - typename Error, - typename ...Generators> -struct merge_producers< - producer...> - : std::true_type { -}; - -} // namespace details - -template < - typename ...Args, - typename = std::enable_if_t< - details::merge_producers_v>> -inline decltype(auto) merge(Args &&...args) { - return details::merge_implementation(std::move(args)...); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/never.h b/Telegram/SourceFiles/rpl/never.h deleted file mode 100644 index e6218b98e..000000000 --- a/Telegram/SourceFiles/rpl/never.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { - -template -inline auto never() { - return make_producer([](const auto &consumer) { - return lifetime(); - }); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/operators_tests.cpp b/Telegram/SourceFiles/rpl/operators_tests.cpp deleted file mode 100644 index 548057f44..000000000 --- a/Telegram/SourceFiles/rpl/operators_tests.cpp +++ /dev/null @@ -1,508 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include -#include - -using namespace rpl; - -class OnDestructor { -public: - OnDestructor(std::function callback) - : _callback(std::move(callback)) { - } - ~OnDestructor() { - if (_callback) { - _callback(); - } - } - -private: - std::function _callback; - -}; - -class InvokeCounter { -public: - InvokeCounter( - const std::shared_ptr ©Counter, - const std::shared_ptr &moveCounter) - : _copyCounter(copyCounter) - , _moveCounter(moveCounter) { - } - InvokeCounter(const InvokeCounter &other) - : _copyCounter(other._copyCounter) - , _moveCounter(other._moveCounter) { - if (_copyCounter) { - ++*_copyCounter; - } - } - InvokeCounter(InvokeCounter &&other) - : _copyCounter(details::take(other._copyCounter)) - , _moveCounter(details::take(other._moveCounter)) { - if (_moveCounter) { - ++*_moveCounter; - } - } - InvokeCounter &operator=(const InvokeCounter &other) { - _copyCounter = other._copyCounter; - _moveCounter = other._moveCounter; - if (_copyCounter) { - ++*_copyCounter; - } - return *this; - } - InvokeCounter &operator=(InvokeCounter &&other) { - _copyCounter = details::take(other._copyCounter); - _moveCounter = details::take(other._moveCounter); - if (_moveCounter) { - ++*_moveCounter; - } - return *this; - } - -private: - std::shared_ptr _copyCounter; - std::shared_ptr _moveCounter; - -}; - -TEST_CASE("basic operators tests", "[rpl::operators]") { - SECTION("single test") { - auto sum = std::make_shared(0); - auto doneGenerated = std::make_shared(false); - auto destroyed = std::make_shared(false); - auto copyCount = std::make_shared(0); - auto moveCount = std::make_shared(0); - { - InvokeCounter counter(copyCount, moveCount); - auto destroyCalled = std::make_shared([=] { - *destroyed = true; - }); - rpl::lifetime lifetime; - single(std::move(counter)) - | start_with_next_error_done([=](InvokeCounter&&) { - (void)destroyCalled; - ++*sum; - }, [=](no_error) { - (void)destroyCalled; - }, [=] { - (void)destroyCalled; - *doneGenerated = true; - }, lifetime); - } - REQUIRE(*sum == 1); - REQUIRE(*doneGenerated); - REQUIRE(*destroyed); - REQUIRE(*copyCount == 0); - } - - SECTION("then test") { - auto sum = std::make_shared(0); - auto doneGenerated = std::make_shared(false); - auto destroyed = std::make_shared(false); - auto copyCount = std::make_shared(0); - auto moveCount = std::make_shared(0); - { - auto testing = complete() | type_erased(); - for (auto i = 0; i != 5; ++i) { - InvokeCounter counter(copyCount, moveCount); - testing = std::move(testing) - | then(single(std::move(counter))); - } - auto destroyCalled = std::make_shared([=] { - *destroyed = true; - }); - - rpl::lifetime lifetime; - std::move(testing) - | then(complete()) - | start_with_next_error_done([=](InvokeCounter&&) { - (void)destroyCalled; - ++*sum; - }, [=](no_error) { - (void)destroyCalled; - }, [=] { - (void)destroyCalled; - *doneGenerated = true; - }, lifetime); - } - REQUIRE(*sum == 5); - REQUIRE(*doneGenerated); - REQUIRE(*destroyed); - REQUIRE(*copyCount == 0); - } - - SECTION("map test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - single(1) - | then(single(2)) - | then(single(3)) - | then(single(4)) - | then(single(5)) - | map([](int value) { - return std::to_string(value); - }) - | start_with_next([=](std::string &&value) { - *sum += std::move(value) + ' '; - }, lifetime); - } - REQUIRE(*sum == "1 2 3 4 5 "); - } - - SECTION("deferred test") { - auto launched = std::make_shared(0); - auto checked = std::make_shared(0); - { - rpl::lifetime lifetime; - auto make_next = [=] { - return deferred([=] { - return single(++*launched); - }); - }; - make_next() - | then(make_next()) - | then(make_next()) - | then(make_next()) - | then(make_next()) - | start_with_next([=](int value) { - REQUIRE(++*checked == *launched); - REQUIRE(*checked == value); - }, lifetime); - REQUIRE(*launched == 5); - } - } - - SECTION("filter test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - single(1) - | then(single(1)) - | then(single(2)) - | then(single(2)) - | then(single(3)) - | filter([](int value) { return value != 2; }) - | map([](int value) { - return std::to_string(value); - }) - | start_with_next([=](std::string &&value) { - *sum += std::move(value) + ' '; - }, lifetime); - } - REQUIRE(*sum == "1 1 3 "); - } - - SECTION("filter tuple test") { - auto sum = std::make_shared(""); - { - auto lifetime = single(std::make_tuple(1, 2)) - | then(single(std::make_tuple(1, 2))) - | then(single(std::make_tuple(2, 3))) - | then(single(std::make_tuple(2, 3))) - | then(single(std::make_tuple(3, 4))) - | filter([](auto first, auto second) { return first != 2; }) - | map([](auto first, auto second) { - return std::to_string(second); - }) - | start_with_next([=](std::string &&value) { - *sum += std::move(value) + ' '; - }); - } - REQUIRE(*sum == "2 2 4 "); - } - - SECTION("distinct_until_changed test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - single(1) - | then(single(1)) - | then(single(2)) - | then(single(2)) - | then(single(3)) - | distinct_until_changed() - | map([](int value) { - return std::to_string(value); - }) - | start_with_next([=](std::string &&value) { - *sum += std::move(value) + ' '; - }, lifetime); - } - REQUIRE(*sum == "1 2 3 "); - } - - SECTION("flatten_latest test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - { - event_stream stream; - single(single(1) | then(single(2))) - | then(single(single(3) | then(single(4)))) - | then(single(single(5) | then(stream.events()))) - | flatten_latest() - | map([](int value) { - return std::to_string(value); - }) - | start_with_next_done([=](std::string &&value) { - *sum += std::move(value) + ' '; - }, [=] { - *sum += "done "; - }, lifetime); - stream.fire(6); - } - single(single(1)) - | then(single(single(2) | then(single(3)))) - | then(single(single(4) | then(single(5)) | then(single(6)))) - | flatten_latest() - | map([](int value) { - return std::to_string(value); - }) - | start_with_next([=](std::string &&value) { - *sum += std::move(value) + ' '; - }, lifetime); - } - REQUIRE(*sum == "1 2 3 4 5 6 done 1 2 3 4 5 6 "); - } - - SECTION("combine vector test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - event_stream a; - event_stream b; - event_stream c; - - std::vector> v; - v.push_back(a.events()); - v.push_back(b.events()); - v.push_back(c.events()); - - combine(std::move(v), [](const auto &values) { - return values[0] && values[1] && !values[2]; - }) - | start_with_next([=](bool value) { - *sum += std::to_string(value ? 1 : 0); - }, lifetime); - - a.fire(true); - b.fire(true); - c.fire(false); - a.fire(false); - b.fire(true); - a.fire(true); - c.fire(true); - } - REQUIRE(*sum == "10010"); - } - - SECTION("combine test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - event_stream a; - event_stream b; - event_stream c; - - combine( - a.events(), - b.events(), - c.events(), - [](long a, long b, long c) { - return a; - }) - | start_with_next([=](int value) { - *sum += std::to_string(value); - }, lifetime); - - combine( - a.events(), - b.events(), - c.events(), - [](auto &&value) { - return std::get<1>(value); - }) - | start_with_next([=](int value) { - *sum += std::to_string(value); - }, lifetime); - - combine(a.events(), b.events(), c.events()) - | map([](auto &&value) { - return std::make_tuple( - std::to_string(std::get<0>(value)), - std::to_string(std::get<1>(value)), - std::to_string(std::get<2>(value))); - }) - | start_with_next([=](auto &&value) { - *sum += std::get<0>(value) + ' ' - + std::get<1>(value) + ' ' - + std::get<2>(value) + ' '; - }, lifetime); - a.fire(1); - b.fire(2); - c.fire(3); - a.fire(4); - b.fire(5); - c.fire(6); - } - REQUIRE(*sum == "121 2 3 424 2 3 454 5 3 454 5 6 "); - } - - SECTION("mappers test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - event_stream a; - event_stream b; - event_stream c; - - using namespace mappers; - - // MSVC BUG + REGRESSION rpl::mappers::tuple :( - //combine( - // a.events(), - // b.events(), - // tuple(_1, _1 + _2) - //) | rpl::start_with_next([=](int a, int a_plus_b) { - // *sum += std::to_string(a * a_plus_b); - //}, lifetime); - - combine( - a.events(), - b.events(), - c.events(), - _1 + _2 + _3 + 10) - | start_with_next([=](int value) { - *sum += std::to_string(value); - }, lifetime); - - a.fire(1); - b.fire(2); - c.fire(3); - a.fire(4); - b.fire(5); - c.fire(6); - } - REQUIRE(*sum == "16192225"); - - // MSVC BUG + REGRESSION rpl::mappers::tuple :( - //REQUIRE(*sum == "3162419362225"); - } - - SECTION("after_next test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - ints(3) - | after_next([=](int value) { - *sum += std::to_string(-value-1); - }) - | start_with_next([=](int value) { - *sum += std::to_string(value); - }, lifetime); - } - REQUIRE(*sum == "0-11-22-3"); - } - - SECTION("combine_previous test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - event_stream a; - - a.events( - ) | combine_previous( - ) | start_with_next([=](int previous, int next) { - *sum += std::to_string(previous) + ' '; - *sum += std::to_string(next) + ' '; - }, lifetime); - - a.events( - ) | combine_previous( - 5 - ) | start_with_next([=](int previous, int next) { - *sum += std::to_string(10 + previous) + ' '; - *sum += std::to_string(next) + ' '; - }, lifetime); - - a.fire(1); - a.fire(2); - a.fire(3); - a.fire(4); - } - REQUIRE(*sum == "15 1 1 2 11 2 2 3 12 3 3 4 13 4 "); - } - - SECTION("take test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - ints(10) | take(3) - | start_with_next_done([=](int value) { - *sum += std::to_string(value); - }, [=] { - *sum += "done"; - }, lifetime); - } - { - rpl::lifetime lifetime; - ints(3) | take(3) - | start_with_next_done([=](int value) { - *sum += std::to_string(value); - }, [=] { - *sum += "done"; - }, lifetime); - } - { - rpl::lifetime lifetime; - ints(3) | take(10) - | start_with_next_done([=](int value) { - *sum += std::to_string(value); - }, [=] { - *sum += "done"; - }, lifetime); - } - REQUIRE(*sum == "012done012done012done"); - } - - SECTION("skip test") { - auto sum = std::make_shared(""); - { - rpl::lifetime lifetime; - ints(10) | skip(5) - | start_with_next_done([=](int value) { - *sum += std::to_string(value); - }, [=] { - *sum += "done"; - }, lifetime); - } - { - rpl::lifetime lifetime; - ints(3) | skip(3) - | start_with_next_done([=](int value) { - *sum += std::to_string(value); - }, [=] { - *sum += "done"; - }, lifetime); - } - { - rpl::lifetime lifetime; - ints(3) | skip(10) - | start_with_next_done([=](int value) { - *sum += std::to_string(value); - }, [=] { - *sum += "done"; - }, lifetime); - } - REQUIRE(*sum == "56789donedonedone"); - } -} diff --git a/Telegram/SourceFiles/rpl/producer.h b/Telegram/SourceFiles/rpl/producer.h deleted file mode 100644 index b00e677bf..000000000 --- a/Telegram/SourceFiles/rpl/producer.h +++ /dev/null @@ -1,1025 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include - -#if defined _DEBUG || defined COMPILER_MSVC -#define RPL_PRODUCER_TYPE_ERASED_ALWAYS -#endif // _DEBUG - -namespace rpl { -namespace details { - -template -const consumer &const_ref_consumer(); - -template -class mutable_lambda_wrap { -public: - mutable_lambda_wrap(Lambda &&lambda) - : _lambda(std::move(lambda)) { - } - mutable_lambda_wrap(const mutable_lambda_wrap &other) = default; - mutable_lambda_wrap(mutable_lambda_wrap &&other) = default; - mutable_lambda_wrap &operator=( - const mutable_lambda_wrap &other) = default; - mutable_lambda_wrap &operator=( - mutable_lambda_wrap &&other) = default; - - template - auto operator()(Args&&... args) const { - return (const_cast(this)->_lambda)( - std::forward(args)...); - } - -private: - Lambda _lambda; - -}; - -// Type-erased copyable mutable function using std::function. -template -class type_erased_generator final { -public: - template - using consumer_type = consumer; - using value_type = Value; - using error_type = Error; - - type_erased_generator( - const type_erased_generator &other) = default; - type_erased_generator( - type_erased_generator &&other) = default; - type_erased_generator &operator=( - const type_erased_generator &other) = default; - type_erased_generator &operator=( - type_erased_generator &&other) = default; - - type_erased_generator(std::nullptr_t = nullptr) { - } - type_erased_generator &operator=(std::nullptr_t) { - _implementation = nullptr; - return *this; - } - - template < - typename Generator, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - const_ref_consumer())), - lifetime> && - !std::is_same_v< - std::decay_t, - type_erased_generator>>> - type_erased_generator(Generator other) : _implementation( - mutable_lambda_wrap(std::move(other))) { - } - template < - typename Generator, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - const_ref_consumer())), - lifetime> && - !std::is_same_v< - std::decay_t, - type_erased_generator>>> - type_erased_generator &operator=(Generator other) { - _implementation = mutable_lambda_wrap( - std::move(other)); - return *this; - } - - template - lifetime operator()(const consumer_type &consumer) { - return _implementation ? _implementation(consumer) : lifetime(); - } - - bool empty() const { - return !_implementation; - } - -private: - std::function> &)> _implementation; - -}; - -} // namespace details - -template < - typename Value = empty_value, - typename Error = no_error, - typename Generator = details::type_erased_generator< - Value, - Error>> -class producer; - -template < - typename Value1, - typename Value2, - typename Error1, - typename Error2, - typename Generator> -struct superset_type< - producer, - producer> { - using type = producer< - superset_type_t, - superset_type_t, - Generator>; -}; - -template < - typename Value, - typename Error, - typename Generator1, - typename Generator2> -struct superset_type< - producer, - producer> { - using type = producer; -}; - -template < - typename Value, - typename Error, - typename Generator> -struct superset_type< - producer, - producer> { - using type = producer; -}; - -namespace details { - -template -class producer_base { -public: - template - using consumer_type = consumer; - using value_type = Value; - using error_type = Error; - - template < - typename OtherGenerator, - typename = std::enable_if_t< - std::is_constructible_v>> - producer_base(OtherGenerator &&generator); - - producer_base() = default; - producer_base(const producer_base &other) = default; - producer_base(producer_base &&other) = default; - producer_base &operator=(const producer_base &other) = default; - producer_base &operator=(producer_base &&other) = default; - - template < - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v - && is_callable_v - && is_callable_v>> - void start( - OnNext &&next, - OnError &&error, - OnDone &&done, - lifetime &alive_while) &&; - - template < - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v - && is_callable_v - && is_callable_v>> - [[nodiscard]] lifetime start( - OnNext &&next, - OnError &&error, - OnDone &&done) &&; - - template < - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v - && is_callable_v - && is_callable_v>> - void start_copy( - OnNext &&next, - OnError &&error, - OnDone &&done, - lifetime &alive_while) const &; - - template < - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v - && is_callable_v - && is_callable_v>> - [[nodiscard]] lifetime start_copy( - OnNext &&next, - OnError &&error, - OnDone &&done) const &; - - template - void start_existing( - const consumer_type &consumer, - lifetime &alive_while) &&; - - template - [[nodiscard]] lifetime start_existing( - const consumer_type &consumer) &&; - -private: - Generator _generator; - - template < - typename OtherValue, - typename OtherError, - typename OtherGenerator> - friend class ::rpl::producer; - -}; - -template -template -inline producer_base::producer_base( - OtherGenerator &&generator) -: _generator(std::forward(generator)) { -} - -template -template < - typename OnNext, - typename OnError, - typename OnDone, - typename> -inline void producer_base::start( - OnNext &&next, - OnError &&error, - OnDone &&done, - lifetime &alive_while) && { - return std::move(*this).start_existing( - make_consumer( - std::forward(next), - std::forward(error), - std::forward(done)), - alive_while); -} - -template -template < - typename OnNext, - typename OnError, - typename OnDone, - typename> -[[nodiscard]] inline lifetime producer_base::start( - OnNext &&next, - OnError &&error, - OnDone &&done) && { - auto result = lifetime(); - std::move(*this).start_existing( - make_consumer( - std::forward(next), - std::forward(error), - std::forward(done)), - result); - return result; -} - -template -template < - typename OnNext, - typename OnError, - typename OnDone, - typename> -inline void producer_base::start_copy( - OnNext &&next, - OnError &&error, - OnDone &&done, - lifetime &alive_while) const & { - auto copy = *this; - return std::move(copy).start_existing( - make_consumer( - std::forward(next), - std::forward(error), - std::forward(done)), - alive_while); -} - -template -template < - typename OnNext, - typename OnError, - typename OnDone, - typename> -[[nodiscard]] inline lifetime producer_base::start_copy( - OnNext &&next, - OnError &&error, - OnDone &&done) const & { - auto result = lifetime(); - auto copy = *this; - std::move(copy).start_existing( - make_consumer( - std::forward(next), - std::forward(error), - std::forward(done)), - result); - return result; -} - -template -template -inline void producer_base::start_existing( - const consumer_type &consumer, - lifetime &alive_while) && { - alive_while.add(consumer.terminator()); - consumer.add_lifetime(std::move(_generator)(consumer)); -} - -template -template -[[nodiscard]] inline lifetime producer_base::start_existing( - const consumer_type &consumer) && { - auto result = lifetime(); - std::move(*this).start_existing(consumer, result); - return result; -} - -template -using producer_base_type_erased = producer_base< - Value, - Error, - type_erased_generator>; - -} // namespace details - -template -class producer final -: public details::producer_base { - using parent_type = details::producer_base< - Value, - Error, - Generator>; - -public: - using parent_type::parent_type; - -}; - -template -class producer< - Value, - Error, - details::type_erased_generator> final -: public details::producer_base_type_erased { - using parent_type = details::producer_base_type_erased< - Value, - Error>; - -public: - using parent_type::parent_type; - - producer() = default; - producer(const producer &other) = default; - producer(producer &&other) = default; - producer &operator=(const producer &other) = default; - producer &operator=(producer &&other) = default; - - template < - typename Generic, - typename = std::enable_if_t>>> - producer(const details::producer_base &other) - : parent_type(other._generator) { - } - - template < - typename Generic, - typename = std::enable_if_t>>> - producer(details::producer_base &&other) - : parent_type(std::move(other._generator)) { - } - - template < - typename Generic, - typename = std::enable_if_t>>> - producer &operator=( - const details::producer_base &other) { - this->_generator = other._generator; - return *this; - } - - template < - typename Generic, - typename = std::enable_if_t>>> - producer &operator=( - details::producer_base &&other) { - this->_generator = std::move(other._generator); - return *this; - } - - explicit operator bool() const { - return !this->_generator.empty(); - } - -}; - -template < - typename Value = empty_value, - typename Error = no_error, - typename Generator, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - details::const_ref_consumer())), - lifetime>>> -inline auto make_producer(Generator &&generator) -#ifdef RPL_PRODUCER_TYPE_ERASED_ALWAYS --> producer { -#else // RPL_PRODUCER_TYPE_ERASED_ALWAYS --> producer> { -#endif // !RPL_PRODUCER_TYPE_ERASED_ALWAYS - return std::forward(generator); -} - -template -inline producer duplicate( - const producer &value) { - return value; -} - -template < - typename Value, - typename Error, - typename Generator, - typename Method, - typename = decltype(std::declval()( - std::declval>()))> -inline auto operator|( - producer &&value, - Method &&method) { - return std::forward(method)(std::move(value)); -} - -namespace details { - -struct with_none { -}; - -struct lifetime_with_none { - lifetime &alive_while; -}; - -template -struct with_next { - OnNext next; -}; - -template -struct lifetime_with_next { - lifetime &alive_while; - OnNext next; -}; - -template -struct with_error { - OnError error; -}; - -template -struct lifetime_with_error { - lifetime &alive_while; - OnError error; -}; - -template -struct with_done { - OnDone done; -}; - -template -struct lifetime_with_done { - lifetime &alive_while; - OnDone done; -}; - -template -struct with_next_error { - OnNext next; - OnError error; -}; - -template -struct lifetime_with_next_error { - lifetime &alive_while; - OnNext next; - OnError error; -}; - -template -struct with_error_done { - OnError error; - OnDone done; -}; - -template -struct lifetime_with_error_done { - lifetime &alive_while; - OnError error; - OnDone done; -}; - -template -struct with_next_done { - OnNext next; - OnDone done; -}; - -template -struct lifetime_with_next_done { - lifetime &alive_while; - OnNext next; - OnDone done; -}; - -template -struct with_next_error_done { - OnNext next; - OnError error; - OnDone done; -}; - -template -struct lifetime_with_next_error_done { - lifetime &alive_while; - OnNext next; - OnError error; - OnDone done; -}; - -} // namespace details - -inline auto start() --> details::with_none { - return {}; -} - -inline auto start(lifetime &alive_while) --> details::lifetime_with_none { - return { alive_while }; -} - -template -inline auto start_with_next(OnNext &&next) --> details::with_next> { - return { std::forward(next) }; -} - -template -inline auto start_with_next(OnNext &&next, lifetime &alive_while) --> details::lifetime_with_next> { - return { alive_while, std::forward(next) }; -} - -template -inline auto start_with_error(OnError &&error) --> details::with_error> { - return { std::forward(error) }; -} - -template -inline auto start_with_error(OnError &&error, lifetime &alive_while) --> details::lifetime_with_error> { - return { alive_while, std::forward(error) }; -} - -template -inline auto start_with_done(OnDone &&done) --> details::with_done> { - return { std::forward(done) }; -} - -template -inline auto start_with_done(OnDone &&done, lifetime &alive_while) --> details::lifetime_with_done> { - return { alive_while, std::forward(done) }; -} - -template -inline auto start_with_next_error( - OnNext &&next, - OnError &&error) --> details::with_next_error< - std::decay_t, - std::decay_t> { - return { - std::forward(next), - std::forward(error) - }; -} - -template -inline auto start_with_next_error( - OnNext &&next, - OnError &&error, - lifetime &alive_while) --> details::lifetime_with_next_error< - std::decay_t, - std::decay_t> { - return { - alive_while, - std::forward(next), - std::forward(error) - }; -} - -template -inline auto start_with_error_done( - OnError &&error, - OnDone &&done) --> details::with_error_done< - std::decay_t, - std::decay_t> { - return { - std::forward(error), - std::forward(done) - }; -} - -template -inline auto start_with_error_done( - OnError &&error, - OnDone &&done, - lifetime &alive_while) --> details::lifetime_with_error_done< - std::decay_t, - std::decay_t> { - return { - alive_while, - std::forward(error), - std::forward(done) - }; -} - -template -inline auto start_with_next_done( - OnNext &&next, - OnDone &&done) --> details::with_next_done< - std::decay_t, - std::decay_t> { - return { - std::forward(next), - std::forward(done) - }; -} - -template -inline auto start_with_next_done( - OnNext &&next, - OnDone &&done, - lifetime &alive_while) --> details::lifetime_with_next_done< - std::decay_t, - std::decay_t> { - return { - alive_while, - std::forward(next), - std::forward(done) - }; -} - -template -inline auto start_with_next_error_done( - OnNext &&next, - OnError &&error, - OnDone &&done) --> details::with_next_error_done< - std::decay_t, - std::decay_t, - std::decay_t> { - return { - std::forward(next), - std::forward(error), - std::forward(done) - }; -} - -template -inline auto start_with_next_error_done( - OnNext &&next, - OnError &&error, - OnDone &&done, - lifetime &alive_while) --> details::lifetime_with_next_error_done< - std::decay_t, - std::decay_t, - std::decay_t> { - return { - alive_while, - std::forward(next), - std::forward(error), - std::forward(done) - }; -} - -namespace details { - -template -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_none &&handlers) { - return std::move(value).start( - [] {}, - [] {}, - [] {}); -} - -template -inline void operator|( - producer &&value, - lifetime_with_none &&handlers) { - std::move(value).start( - [] {}, - [] {}, - [] {}, - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename = std::enable_if_t>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_next &&handlers) { - return std::move(value).start( - std::move(handlers.next), - [] {}, - [] {}); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename = std::enable_if_t>> -inline void operator|( - producer &&value, - lifetime_with_next &&handlers) { - std::move(value).start( - std::move(handlers.next), - [] {}, - [] {}, - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnError, - typename = std::enable_if_t>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_error &&handlers) { - return std::move(value).start( - [] {}, - std::move(handlers.error), - [] {}); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnError, - typename = std::enable_if_t>> -inline void operator|( - producer &&value, - lifetime_with_error &&handlers) { - std::move(value).start( - [] {}, - std::move(handlers.error), - [] {}, - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnDone, - typename = std::enable_if_t>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_done &&handlers) { - return std::move(value).start( - [] {}, - [] {}, - std::move(handlers.done)); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnDone, - typename = std::enable_if_t>> -inline void operator|( - producer &&value, - lifetime_with_done &&handlers) { - std::move(value).start( - [] {}, - [] {}, - std::move(handlers.done), - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename OnError, - typename = std::enable_if_t< - is_callable_v && - is_callable_v>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_next_error &&handlers) { - return std::move(value).start( - std::move(handlers.next), - std::move(handlers.error), - [] {}); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename OnError, - typename = std::enable_if_t< - is_callable_v && - is_callable_v>> -inline void operator|( - producer &&value, - lifetime_with_next_error &&handlers) { - std::move(value).start( - std::move(handlers.next), - std::move(handlers.error), - [] {}, - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v && - is_callable_v>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_error_done &&handlers) { - return std::move(value).start( - [] {}, - std::move(handlers.error), - std::move(handlers.done)); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v && - is_callable_v>> -inline void operator|( - producer &&value, - lifetime_with_error_done &&handlers) { - std::move(value).start( - [] {}, - std::move(handlers.error), - std::move(handlers.done), - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename OnDone, - typename = std::enable_if_t< - is_callable_v && - is_callable_v>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_next_done &&handlers) { - return std::move(value).start( - std::move(handlers.next), - [] {}, - std::move(handlers.done)); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename OnDone, - typename = std::enable_if_t< - is_callable_v && - is_callable_v>> -inline void operator|( - producer &&value, - lifetime_with_next_done &&handlers) { - std::move(value).start( - std::move(handlers.next), - [] {}, - std::move(handlers.done), - handlers.alive_while); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v && - is_callable_v && - is_callable_v>> -[[nodiscard]] inline lifetime operator|( - producer &&value, - with_next_error_done< - OnNext, - OnError, - OnDone> &&handlers) { - return std::move(value).start( - std::move(handlers.next), - std::move(handlers.error), - std::move(handlers.done)); -} - -template < - typename Value, - typename Error, - typename Generator, - typename OnNext, - typename OnError, - typename OnDone, - typename = std::enable_if_t< - is_callable_v && - is_callable_v && - is_callable_v>> -inline void operator|( - producer &&value, - lifetime_with_next_error_done< - OnNext, - OnError, - OnDone> &&handlers) { - std::move(value).start( - std::move(handlers.next), - std::move(handlers.error), - std::move(handlers.done), - handlers.alive_while); -} - -} // namespace details -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/producer_tests.cpp b/Telegram/SourceFiles/rpl/producer_tests.cpp deleted file mode 100644 index 0267f92aa..000000000 --- a/Telegram/SourceFiles/rpl/producer_tests.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include -#include - -using namespace rpl; - -class OnDestructor { -public: - OnDestructor(std::function callback) - : _callback(std::move(callback)) { - } - ~OnDestructor() { - if (_callback) { - _callback(); - } - } - -private: - std::function _callback; - -}; - -TEST_CASE("basic producer tests", "[rpl::producer]") { - SECTION("producer next, done and lifetime end test") { - auto lifetimeEnded = std::make_shared(false); - auto sum = std::make_shared(0); - auto doneGenerated = std::make_shared(false); - auto destroyed = std::make_shared(false); - { - auto destroyCaller = std::make_shared([=] { - *destroyed = true; - }); - { - auto alive = make_producer([=](auto &&consumer) { - (void)destroyCaller; - consumer.put_next(1); - consumer.put_next(2); - consumer.put_next(3); - consumer.put_done(); - return [=] { - (void)destroyCaller; - *lifetimeEnded = true; - }; - }).start([=](int value) { - (void)destroyCaller; - *sum += value; - }, [=](no_error) { - (void)destroyCaller; - }, [=]() { - (void)destroyCaller; - *doneGenerated = true; - }); - } - } - REQUIRE(*sum == 1 + 2 + 3); - REQUIRE(*doneGenerated); - REQUIRE(*lifetimeEnded); - REQUIRE(*destroyed); - } - - SECTION("producer error test") { - auto errorGenerated = std::make_shared(false); - { - auto alive = make_producer([=](auto &&consumer) { - consumer.put_error(true); - return lifetime(); - }).start([=](no_value) { - }, [=](bool error) { - *errorGenerated = error; - }, [=]() { - }); - } - REQUIRE(*errorGenerated); - } - - SECTION("nested lifetimes test") { - auto lifetimeEndCount = std::make_shared(0); - { - auto lifetimes = lifetime(); - { - auto testProducer = make_producer([=](auto &&consumer) { - return [=] { - ++*lifetimeEndCount; - }; - }); - testProducer.start_copy([=](no_value) { - }, [=](no_error) { - }, [=] { - }, lifetimes); - std::move(testProducer).start([=](no_value) { - }, [=](no_error) { - }, [=] { - }, lifetimes); - } - REQUIRE(*lifetimeEndCount == 0); - } - REQUIRE(*lifetimeEndCount == 2); - } - - SECTION("nested producers test") { - auto sum = std::make_shared(0); - auto lifetimeEndCount = std::make_shared(0); - auto saved = lifetime(); - { - make_producer([=](auto &&consumer) { - auto inner = make_producer([=](auto &&consumer) { - consumer.put_next(1); - consumer.put_next(2); - consumer.put_next(3); - return [=] { - ++*lifetimeEndCount; - }; - }); - auto result = lifetime([=] { - ++*lifetimeEndCount; - }); - inner.start_copy([=](int value) { - consumer.put_next_copy(value); - }, [=](no_error) { - }, [=] { - }, result); - std::move(inner).start([=](int value) { - consumer.put_next_copy(value); - }, [=](no_error) { - }, [=] { - }, result); - return result; - }).start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, saved); - } - REQUIRE(*sum == 1 + 2 + 3 + 1 + 2 + 3); - REQUIRE(*lifetimeEndCount == 0); - saved.destroy(); - REQUIRE(*lifetimeEndCount == 3); - } - - SECTION("tuple producer test") { - auto result = std::make_shared(0); - { - auto alive = make_producer>([=]( - auto &&consumer) { - consumer.put_next(std::make_tuple(1, 2.)); - return lifetime(); - }).start([=](int a, double b) { - *result = a + int(b); - }, [=](no_error error) { - }, [=]() { - }); - } - REQUIRE(*result == 3); - } -} - -TEST_CASE("basic event_streams tests", "[rpl::event_stream]") { - SECTION("event_stream basic test") { - auto sum = std::make_shared(0); - event_stream stream; - stream.fire(1); - stream.fire(2); - stream.fire(3); - { - auto saved = lifetime(); - stream.events().start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, saved); - stream.fire(11); - stream.fire(12); - stream.fire(13); - } - stream.fire(21); - stream.fire(22); - stream.fire(23); - - REQUIRE(11 + 12 + 13); - } - - SECTION("event_stream add in handler test") { - auto sum = std::make_shared(0); - event_stream stream; - - { - auto composite = lifetime(); - stream.events().start([=, &stream, &composite](int value) { - *sum += value; - stream.events().start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, composite); - }, [=](no_error) { - }, [=] { - }, composite); - - { - auto inner = lifetime(); - stream.events().start([=, &stream, &inner](int value) { - *sum += value; - stream.events().start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, inner); - }, [=](no_error) { - }, [=] { - }, inner); - - stream.fire(1); - stream.fire(2); - stream.fire(3); - } - stream.fire(11); - stream.fire(12); - stream.fire(13); - } - stream.fire(21); - stream.fire(22); - stream.fire(23); - - REQUIRE(*sum == - (1 + 1) + - ((2 + 2) + (2 + 2)) + - ((3 + 3 + 3) + (3 + 3 + 3)) + - (11 + 11 + 11 + 11) + - (12 + 12 + 12 + 12 + 12) + - (13 + 13 + 13 + 13 + 13 + 13)); - } - - SECTION("event_stream add and remove in handler test") { - auto sum = std::make_shared(0); - event_stream stream; - - { - auto composite = lifetime(); - stream.events().start([=, &stream, &composite](int value) { - *sum += value; - composite.destroy(); - stream.events().start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, composite); - }, [=](no_error) { - }, [=] { - }, composite); - - { - auto inner = lifetime(); - stream.events().start([=, &stream, &inner](int value) { - *sum += value; - inner.destroy(); - stream.events().start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, inner); - }, [=](no_error) { - }, [=] { - }, inner); - - stream.fire(1); - stream.fire(2); - stream.fire(3); - } - stream.fire(11); - stream.fire(12); - stream.fire(13); - } - stream.fire(21); - stream.fire(22); - stream.fire(23); - - REQUIRE(*sum == - (1 + 1) + - (2 + 2) + - (3 + 3) + - (11) + - (12) + - (13)); - } - - SECTION("event_stream ends before handler lifetime") { - auto sum = std::make_shared(0); - lifetime extended; - { - event_stream stream; - stream.events().start([=](int value) { - *sum += value; - }, [=](no_error) { - }, [=] { - }, extended); - stream.fire(1); - stream.fire(2); - stream.fire(3); - } - REQUIRE(*sum == 1 + 2 + 3); - } - - SECTION("event_stream move test") { - auto sum = std::make_shared(0); - lifetime extended; - { - event_stream stream; - stream.events() - | start_with_next([=](int value) { - *sum += value; - }, extended); - - stream.fire(1); - stream.fire(2); - - auto movedStream = std::move(stream); - movedStream.fire(3); - movedStream.fire(4); - } - REQUIRE(*sum == 1 + 2 + 3 + 4); - } -} - -TEST_CASE("basic piping tests", "[rpl::producer]") { - - SECTION("start_with_*") { - auto sum = std::make_shared(0); - auto dones = std::make_shared(0); - { - auto alive = lifetime(); - make_producer([=](auto &&consumer) { - consumer.put_next(1); - consumer.put_done(); - return lifetime(); - }) | start_with_next([=](int value) { - *sum += value; - }, alive); - - make_producer([=](auto &&consumer) { - consumer.put_next(11); - consumer.put_error(111); - return lifetime(); - }) | start_with_error([=](int value) { - *sum += value; - }, alive); - - make_producer([=](auto &&consumer) { - consumer.put_next(1111); - consumer.put_done(); - return lifetime(); - }) | start_with_done([=]() { - *dones += 1; - }, alive); - - make_producer([=](auto &&consumer) { - consumer.put_next(11111); - consumer.put_next(11112); - consumer.put_next(11113); - consumer.put_error(11114); - return lifetime(); - }) | start_with_next_error([=](int value) { - *sum += value; - }, [=](int value) { - *sum += value; - }, alive); - } - - auto alive = lifetime(); - make_producer([=](auto &&consumer) { - consumer.put_next(111111); - consumer.put_next(111112); - consumer.put_next(111113); - consumer.put_done(); - return lifetime(); - }) | start_with_next_done([=](int value) { - *sum += value; - }, [=]() { - *dones += 11; - }, alive); - - make_producer([=](auto &&consumer) { - consumer.put_error(1111111); - return lifetime(); - }) | start_with_error_done([=](int value) { - *sum += value; - }, [=]() { - *dones = 0; - }, alive); - - make_producer([=](auto &&consumer) { - consumer.put_next(11111111); - consumer.put_next(11111112); - consumer.put_next(11111113); - consumer.put_error(11111114); - return lifetime(); - }) | start_with_next_error_done([=](int value) { - *sum += value; - }, [=](int value) { - *sum += value; - }, [=]() { - *dones = 0; - }, alive); - - REQUIRE(*sum == - 1 + - 111 + - 11111 + 11112 + 11113 + 11114 + - 111111 + 111112 + 111113 + - 1111111 + - 11111111 + 11111112 + 11111113 + 11111114); - REQUIRE(*dones == 1 + 11); - } - - SECTION("start_with_next should copy its callback") { - auto sum = std::make_shared(0); - { - auto next = [=](int value) { - REQUIRE(sum != nullptr); - *sum += value; - }; - - for (int i = 0; i != 3; ++i) { - auto alive = lifetime(); - make_producer([=](auto &&consumer) { - consumer.put_next(1); - consumer.put_done(); - return lifetime(); - }) | start_with_next(next, alive); - } - } - REQUIRE(*sum == 3); - } -} diff --git a/Telegram/SourceFiles/rpl/range.h b/Telegram/SourceFiles/rpl/range.h deleted file mode 100644 index 790e168b0..000000000 --- a/Telegram/SourceFiles/rpl/range.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace rpl { - -template -inline auto single(Value &&value) { - return make_producer, Error>([ - value = std::forward(value) - ](const auto &consumer) mutable { - consumer.put_next(std::move(value)); - consumer.put_done(); - return lifetime(); - }); -} - -template -inline auto single() { - return make_producer([](const auto &consumer) { - consumer.put_next({}); - consumer.put_done(); - return lifetime(); - }); -} - -template -inline auto vector(std::vector &&values) { - return make_producer([ - values = std::move(values) - ](const auto &consumer) mutable { - for (auto &value : values) { - consumer.put_next(std::move(value)); - } - consumer.put_done(); - return lifetime(); - }); -} - -template -inline auto vector(std::vector &&values) { - return make_producer([ - values = std::move(values) - ](const auto &consumer) { - for (auto value : values) { - consumer.put_next_copy(value); - } - consumer.put_done(); - return lifetime(); - }); -} - -template < - typename Range, - typename Value = std::decay_t< - decltype(*std::begin(std::declval()))>> -inline auto range(Range &&range) { - return vector(std::vector( - std::begin(range), - std::end(range))); -} - -inline auto ints(int from, int till) { - Expects(from <= till); - return make_producer([from, till](const auto &consumer) { - for (auto i = from; i != till; ++i) { - consumer.put_next_copy(i); - } - consumer.put_done(); - return lifetime(); - }); -} - -inline auto ints(int count) { - return ints(0, count); -} - -} // namespace rpl - diff --git a/Telegram/SourceFiles/rpl/rpl.h b/Telegram/SourceFiles/rpl/rpl.h deleted file mode 100644 index b2b0ebc53..000000000 --- a/Telegram/SourceFiles/rpl/rpl.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -// rpl - reactive programming library - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include diff --git a/Telegram/SourceFiles/rpl/skip.h b/Telegram/SourceFiles/rpl/skip.h deleted file mode 100644 index 8cfe5774b..000000000 --- a/Telegram/SourceFiles/rpl/skip.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace rpl { -namespace details { - -class skip_helper { -public: - skip_helper(int count) : _count(count) { - } - - template < - typename Value, - typename Error, - typename Generator> - auto operator()(producer &&initial) { - return make_producer([ - initial = std::move(initial), - skipping = _count - ](const auto &consumer) mutable { - auto count = consumer.template make_state(skipping); - auto initial_consumer = make_consumer( - [consumer, count](auto &&value) { - if (*count) { - --*count; - } else { - consumer.put_next_forward( - std::forward(value)); - } - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - consumer.add_lifetime(initial_consumer.terminator()); - return std::move(initial).start_existing(initial_consumer); - }); - } - -private: - int _count = 0; - -}; - -} // namespace details - -inline auto skip(int count) --> details::skip_helper { - Expects(count >= 0); - - return details::skip_helper(count); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/take.h b/Telegram/SourceFiles/rpl/take.h deleted file mode 100644 index 6164de4ad..000000000 --- a/Telegram/SourceFiles/rpl/take.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace rpl { -namespace details { - -class take_helper { -public: - take_helper(int count) : _count(count) { - } - - template < - typename Value, - typename Error, - typename Generator> - auto operator()(producer &&initial) { - return make_producer([ - initial = std::move(initial), - limit = _count - ](const auto &consumer) mutable { - auto count = consumer.template make_state(limit); - auto initial_consumer = make_consumer( - [consumer, count](auto &&value) { - auto left = (*count)--; - if (left) { - consumer.put_next_forward( - std::forward(value)); - --left; - } - if (!left) { - consumer.put_done(); - } - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - }); - consumer.add_lifetime(initial_consumer.terminator()); - return std::move(initial).start_existing(initial_consumer); - }); - } - -private: - int _count = 0; - -}; - -} // namespace details - -inline auto take(int count) --> details::take_helper { - Expects(count >= 0); - - return details::take_helper(count); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/then.h b/Telegram/SourceFiles/rpl/then.h deleted file mode 100644 index 0d24fa38d..000000000 --- a/Telegram/SourceFiles/rpl/then.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { - -template -class then_helper { -public: - then_helper(producer &&following) - : _following(std::move(following)) { - } - - template < - typename OtherValue, - typename OtherError, - typename OtherGenerator, - typename NewValue = superset_type_t, - typename NewError = superset_type_t> - auto operator()( - producer &&initial - ) { - return make_producer([ - initial = std::move(initial), - following = std::move(_following) - ](const auto &consumer) mutable { - return std::move(initial).start( - [consumer](auto &&value) { - consumer.put_next_forward( - std::forward(value)); - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [ - consumer, - following = std::move(following) - ]() mutable { - consumer.add_lifetime(std::move(following).start( - [consumer](auto &&value) { - consumer.put_next_forward( - std::forward(value)); - }, [consumer](auto &&error) { - consumer.put_error_forward( - std::forward(error)); - }, [consumer] { - consumer.put_done(); - })); - }); - }); - } - -private: - producer _following; - -}; - -} // namespace details -template -inline auto then(producer &&following) --> details::then_helper { - return { std::move(following) }; -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/type_erased.h b/Telegram/SourceFiles/rpl/type_erased.h deleted file mode 100644 index 7a871ff29..000000000 --- a/Telegram/SourceFiles/rpl/type_erased.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace rpl { -namespace details { - -class type_erased_helper { -public: - template - producer operator()( - producer &&initial) const { - return std::move(initial); - } - -}; - -} // namespace details - -inline auto type_erased() --> details::type_erased_helper { - return details::type_erased_helper(); -} - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/variable.h b/Telegram/SourceFiles/rpl/variable.h deleted file mode 100644 index 06f9e0e74..000000000 --- a/Telegram/SourceFiles/rpl/variable.h +++ /dev/null @@ -1,181 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace mapbox { -namespace util { - -template -class variant; - -} // namespace util -} // namespace mapbox - -namespace rpl { -namespace details { - -template -struct supports_equality_compare { - template - static auto test(const U *u, const V *v) - -> decltype(*u == *v, true_t()); - static false_t test(...); - static constexpr bool value - = (sizeof(test((const A*)nullptr, (const B*)nullptr)) - == sizeof(true_t)); -}; - -// Fix for MSVC expression SFINAE. -// It still doesn't work! :( -// -//template -//struct supports_equality_compare< -// mapbox::util::variant, -// mapbox::util::variant> { -// static constexpr bool value -// = (supports_equality_compare::value -// && supports_equality_compare< -// mapbox::util::variant, -// mapbox::util::variant>::value); -// -//}; -//template -//struct supports_equality_compare< -// mapbox::util::variant, -// mapbox::util::variant> { -// static constexpr bool value = supports_equality_compare::value; -// -//}; - -template -constexpr bool supports_equality_compare_v - = supports_equality_compare, std::decay_t>::value; - -} // namespace details - -template -class variable final { -public: - variable() : _data{} { - } - variable(variable &&other) : _data(std::move(other._data)) { - } - variable &operator=(variable &&other) { - return (*this = std::move(other._data)); - } - - template < - typename OtherType, - typename = std::enable_if_t< - std::is_constructible_v>> - variable(OtherType &&data) : _data(std::forward(data)) { - } - - template < - typename OtherType, - typename = std::enable_if_t< - std::is_assignable_v>> - variable &operator=(OtherType &&data) { - _lifetime.destroy(); - return assign(std::forward(data)); - } - - template < - typename OtherType, - typename OtherError, - typename Generator, - typename = std::enable_if_t< - std::is_assignable_v>> - variable(producer &&stream) { - std::move(stream) - | start_with_next([=](auto &&data) { - assign(std::forward(data)); - }, _lifetime); - } - - template < - typename OtherType, - typename OtherError, - typename Generator, - typename = std::enable_if_t< - std::is_assignable_v>> - variable &operator=( - producer &&stream) { - _lifetime.destroy(); - std::move(stream) - | start_with_next([=](auto &&data) { - assign(std::forward(data)); - }, _lifetime); - return *this; - } - - Type current() const { - return _data; - } - auto value() const { - return _changes.events_starting_with_copy(_data); - } - auto changes() const { - return _changes.events(); - } - - // Send 'done' to all subscribers and unsubscribe them. - template < - typename OtherType, - typename = std::enable_if_t< - std::is_assignable_v>> - void reset(OtherType &&data) { - _data = std::forward(data); - _changes = event_stream(); - } - void reset() { - reset(Type()); - } - - template < - typename OtherError, - typename = std::enable_if_t< - std::is_constructible_v>> - void reset_with_error(OtherError &&error) { - _changes.fire_error(std::forward(error)); - } - void reset_with_error() { - reset_with_error(Error()); - } - -private: - template - variable &assign(OtherType &&data) { - if constexpr (details::supports_equality_compare_v) { - if (!(_data == data)) { - _data = std::forward(data); - _changes.fire_copy(_data); - } - } else if constexpr (details::supports_equality_compare_v) { - auto old = std::move(_data); - _data = std::forward(data); - if (!(_data == old)) { - _changes.fire_copy(_data); - } - } else { - _data = std::forward(data); - _changes.fire_copy(_data); - } - return *this; - } - - Type _data; - event_stream _changes; - lifetime _lifetime; - -}; - -} // namespace rpl diff --git a/Telegram/SourceFiles/rpl/variable_tests.cpp b/Telegram/SourceFiles/rpl/variable_tests.cpp deleted file mode 100644 index 9c697fcd7..000000000 --- a/Telegram/SourceFiles/rpl/variable_tests.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include -#include - -using namespace rpl; - -TEST_CASE("basic variable tests", "[rpl::variable]") { - SECTION("simple test") { - auto sum = std::make_shared(0); - { - auto var = variable(1); - auto lifeftime = var.value() - | start_with_next([=](int value) { - *sum += value; - }); - var = 1; - var = 11; - var = 111; - var = 111; - } - REQUIRE(*sum == 1 + 11 + 111); - } -} - diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index 145fd678f..40723b255 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -6,7 +6,7 @@ { 'includes': [ - 'common/common.gypi', + '../ThirdParty/gyp_helpers/common/common.gypi', 'telegram/telegram.gypi', ], } diff --git a/Telegram/gyp/codegen.gyp b/Telegram/gyp/codegen.gyp index 79061051a..244ff15a5 100644 --- a/Telegram/gyp/codegen.gyp +++ b/Telegram/gyp/codegen.gyp @@ -6,7 +6,7 @@ { 'includes': [ - 'common/common.gypi', + '../ThirdParty/gyp_helpers/common/common.gypi', ], 'targets': [{ 'target_name': 'codegen_lang', @@ -15,8 +15,8 @@ 'mac_target': '10.10', }, 'includes': [ - 'common/executable.gypi', - 'modules/qt.gypi', + '../ThirdParty/gyp_helpers/common/executable.gypi', + '../ThirdParty/gyp_helpers/modules/qt.gypi', ], 'include_dirs': [ @@ -52,11 +52,11 @@ 'mac_target': '10.10', }, 'includes': [ - 'common/executable.gypi', - 'modules/qt.gypi', + '../ThirdParty/gyp_helpers/common/executable.gypi', + '../ThirdParty/gyp_helpers/modules/qt.gypi', ], 'dependencies': [ - 'lib_base.gyp:lib_base', + '../ThirdParty/lib_base/lib_base.gyp:lib_base', ], 'include_dirs': [ '<(src_loc)', @@ -95,8 +95,8 @@ 'mac_target': '10.10', }, 'includes': [ - 'common/executable.gypi', - 'modules/qt.gypi', + '../ThirdParty/gyp_helpers/common/executable.gypi', + '../ThirdParty/gyp_helpers/modules/qt.gypi', ], 'include_dirs': [ @@ -132,8 +132,8 @@ 'mac_target': '10.10', }, 'includes': [ - 'common/executable.gypi', - 'modules/qt.gypi', + '../ThirdParty/gyp_helpers/common/executable.gypi', + '../ThirdParty/gyp_helpers/modules/qt.gypi', ], 'include_dirs': [ diff --git a/Telegram/gyp/common/common.gypi b/Telegram/gyp/common/common.gypi deleted file mode 100644 index 6531a7a75..000000000 --- a/Telegram/gyp/common/common.gypi +++ /dev/null @@ -1,115 +0,0 @@ -# This file is part of Telegram Desktop, -# the official desktop application for the Telegram messaging service. -# -# For license and copyright information please follow this link: -# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL - -{ - 'includes': [ - 'win.gypi', - 'mac.gypi', - 'linux.gypi', - ], - 'variables': { - 'variables': { - 'variables': { - 'variables': { - 'variables': { - 'build_os%': '<(OS)', - }, - 'build_os%': '<(build_os)', - 'conditions': [ - [ 'build_os == "win"', { - 'build_win': 1, - }, { - 'build_win': 0, - }], - [ 'build_os == "mac"', { - 'build_mac': 1, - }, { - 'build_mac': 0, - }], - [ 'build_os == "linux"', { - 'build_linux': 1, - }, { - 'build_linux': 0, - }], - ], - }, - 'build_os%': '<(build_os)', - 'build_win%': '<(build_win)', - 'build_mac%': '<(build_mac)', - 'build_linux%': '<(build_linux)', - }, - 'build_os%': '<(build_os)', - 'build_win%': '<(build_win)', - 'build_mac%': '<(build_mac)', - 'build_linux%': '<(build_linux)', - - 'official_build_target%': '', - 'build_standard_win%': 'c++17', - 'libs_loc%': '<(DEPTH)/../../../Libraries', - }, - 'build_os%': '<(build_os)', - 'build_win%': '<(build_win)', - 'build_mac%': '<(build_mac)', - 'build_linux%': '<(build_linux)', - 'official_build_target%': '<(official_build_target)', - 'build_standard_win%': '<(build_standard_win)', - 'libs_loc%': '<(libs_loc)', - - # GYP does not support per-configuration libraries :( - # So they will be emulated through additional link flags, - # which will contain <(ld_lib_prefix)LibraryName<(ld_lib_postfix) - 'conditions': [ - [ 'build_win', { - 'ld_lib_prefix': '', - 'ld_lib_postfix': '.lib', - 'exe_ext': '.exe', - }, { - 'ld_lib_prefix': '-l', - 'ld_lib_postfix': '', - 'exe_ext': '', - }], - [ '"<(official_build_target)" == "mac32"', { - 'mac_target%': '10.6', - 'build_macold': 1, - }, { - 'mac_target%': '10.8', - 'build_macold': 0, - }], - [ '"<(official_build_target)" == "macstore"', { - 'build_macstore': 1, - }, { - 'build_macstore': 0, - }], - [ '"<(official_build_target)" == "uwp"', { - 'build_uwp': 1, - }, { - 'build_uwp': 0, - }], - ], - 'ld_lib_prefix': '<(ld_lib_prefix)', - 'ld_lib_postfix': '<(ld_lib_postfix)', - 'exe_ext': '<(exe_ext)', - - 'library%': 'static_library', - - }, - - 'defines': [ - 'NOMINMAX' - ], - 'configurations': { - 'Debug': { - 'defines': [ - '_DEBUG', - ], - }, - 'Release': { - 'defines': [ - 'NDEBUG', - ], - }, - }, -} diff --git a/Telegram/gyp/common/executable.gypi b/Telegram/gyp/common/executable.gypi deleted file mode 100644 index df9671afc..000000000 --- a/Telegram/gyp/common/executable.gypi +++ /dev/null @@ -1,21 +0,0 @@ -# This file is part of Telegram Desktop, -# the official desktop application for the Telegram messaging service. -# -# For license and copyright information please follow this link: -# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL - -{ - 'type': 'executable', - 'variables': { - 'win_subsystem': '2', # Windows application - }, - 'includes': [ - 'common.gypi', - ], - 'msvs_settings': { - 'VCLinkerTool': { - 'SubSystem': '<(win_subsystem)', - 'ImportLibrary': '<(PRODUCT_DIR)/<(_target_name).lib', - }, - }, -} diff --git a/Telegram/gyp/common/library.gypi b/Telegram/gyp/common/library.gypi deleted file mode 100644 index bf06013ef..000000000 --- a/Telegram/gyp/common/library.gypi +++ /dev/null @@ -1,12 +0,0 @@ -# This file is part of Telegram Desktop, -# the official desktop application for the Telegram messaging service. -# -# For license and copyright information please follow this link: -# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL - -{ - 'type': 'static_library', - 'includes': [ - 'common.gypi', - ], -} diff --git a/Telegram/gyp/common/linux.gypi b/Telegram/gyp/common/linux.gypi deleted file mode 100644 index cdcdef1dc..000000000 --- a/Telegram/gyp/common/linux.gypi +++ /dev/null @@ -1,112 +0,0 @@ -# This file is part of Telegram Desktop, -# the official desktop application for the Telegram messaging service. -# -# For license and copyright information please follow this link: -# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL - -{ - 'conditions': [ - [ 'build_linux', { - 'variables': { - 'linux_common_flags': [ - '-pipe', - '-Wall', - '-Werror', - '-W', - '-fPIC', - '-Wno-unused-variable', - '-Wno-unused-parameter', - '-Wno-unused-function', - '-Wno-switch', - '-Wno-comment', - '-Wno-unused-but-set-variable', - '-Wno-missing-field-initializers', - '-Wno-sign-compare', - '-Wno-attributes', - '-Wno-error=class-memaccess', - '-Wno-error=parentheses', - ], - 'linux_path_ffmpeg%': '/usr/local', - 'linux_path_openal%': '/usr/local', - 'linux_path_va%': '/usr/local', - 'linux_path_vdpau%': '/usr/local', - 'linux_path_breakpad%': '/usr/local', - 'linux_path_opus_include%': '<(libs_loc)/opus/include', - 'linux_path_range%': '/usr/local', - }, - 'include_dirs': [ - '/usr/local/include', - '<(linux_path_ffmpeg)/include', - '<(linux_path_openal)/include', - '<(linux_path_breakpad)/include/breakpad', - '<(linux_path_opus_include)', - '<(linux_path_range)/include', - ], - 'library_dirs': [ - '/usr/local/lib', - '<(linux_path_ffmpeg)/lib', - '<(linux_path_openal)/lib', - '<(linux_path_va)/lib', - '<(linux_path_vdpau)/lib', - '<(linux_path_breakpad)/lib', - ], - 'conditions': [ - [ '"