/* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once #include // we copy some parts of C++11/14/17 std:: library, because on OS X 10.6+ // version we can use C++11/14/17, but we can not use its library :( namespace std_ { using nullptr_t = decltype(nullptr); template struct integral_constant { static constexpr T value = V; using value_type = T; using type = integral_constant; constexpr operator value_type() const noexcept { return (value); } constexpr value_type operator()() const noexcept { return (value); } }; using true_type = integral_constant; using false_type = integral_constant; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template struct is_lvalue_reference : false_type { }; template struct is_lvalue_reference : true_type { }; template struct is_rvalue_reference : false_type { }; template struct is_rvalue_reference : true_type { }; template inline constexpr T &&forward(typename remove_reference::type &value) noexcept { return static_cast(value); } template inline constexpr T &&forward(typename remove_reference::type &&value) noexcept { static_assert(!is_lvalue_reference::value, "bad forward call"); return static_cast(value); } template inline constexpr typename remove_reference::type &&move(T &&value) noexcept { return static_cast::type&&>(value); } template void swap_moveable(T &a, T &b) { T tmp = move(a); a = move(b); b = move(tmp); } template struct remove_const { using type = T; }; template struct remove_const { using type = T; }; template struct remove_volatile { using type = T; }; template struct remove_volatile { using type = T; }; template using decay_simple_t = typename remove_const::type>::type>::type; template struct is_same : false_type { }; template struct is_same : true_type { }; template struct enable_if { }; template struct enable_if { using type = T; }; template using enable_if_t = typename enable_if::type; template struct conditional { using type = Second; }; template struct conditional { using type = First; }; template using conditional_t = typename conditional::type; template struct add_const { using type = const T; }; template using add_const_t = typename add_const::type; template constexpr add_const_t &as_const(T& t) noexcept { return t; } template void as_const(const T&&) = delete; // This is not full unique_ptr, but at least with std interface. template class unique_ptr { public: constexpr unique_ptr() noexcept = default; unique_ptr(const unique_ptr &) = delete; unique_ptr &operator=(const unique_ptr &) = delete; constexpr unique_ptr(std_::nullptr_t) { } unique_ptr &operator=(std_::nullptr_t) noexcept { reset(); return (*this); } explicit unique_ptr(T *p) noexcept : _p(p) { } template unique_ptr(unique_ptr &&other) noexcept : _p(other.release()) { } template unique_ptr &operator=(unique_ptr &&other) noexcept { reset(other.release()); return (*this); } unique_ptr &operator=(unique_ptr &&other) noexcept { if (this != &other) { reset(other.release()); } return (*this); } void swap(unique_ptr &other) noexcept { std::swap(_p, other._p); } ~unique_ptr() noexcept { if (_p) { delete _p; _p = nullptr; } } T &operator*() const { return (*get()); } T *operator->() const noexcept { return get(); } T *get() const noexcept { return _p; } explicit operator bool() const noexcept { return get() != nullptr; } T *release() noexcept { auto old = _p; _p = nullptr; return old; } void reset(T *p = nullptr) noexcept { auto old = _p; _p = p; if (old) { delete old; } } private: T *_p = nullptr; }; template inline unique_ptr make_unique(Args&&... args) { return unique_ptr(new T(forward(args)...)); } template inline bool operator==(const unique_ptr &a, std_::nullptr_t) noexcept { return !a; } template inline bool operator==(std_::nullptr_t, const unique_ptr &b) noexcept { return !b; } template inline bool operator!=(const unique_ptr &a, std_::nullptr_t b) noexcept { return !(a == b); } template inline bool operator!=(std_::nullptr_t a, const unique_ptr &b) noexcept { return !(a == b); } using _yes = char(&)[1]; using _no = char(&)[2]; template struct _host { operator Base*() const; operator Derived*(); }; template struct is_base_of { template static _yes check(Derived*, T); static _no check(Base*, int); static constexpr bool value = sizeof(check(_host(), int())) == sizeof(_yes); }; inline void *align(size_t alignment, size_t size, void*& ptr, size_t& space) noexcept { #ifndef OS_MAC_OLD using std::uintptr_t; #endif // OS_MAC_OLD auto p = reinterpret_cast(ptr); auto a = (p - 1u + alignment) & -alignment; auto d = a - p; if ((size + d) > space) { return nullptr; } space -= d; return ptr = reinterpret_cast(a); } } // namespace std_