/* 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 <stdint.h> // 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 <typename T, T V> struct integral_constant { static constexpr T value = V; using value_type = T; using type = integral_constant<T, V>; constexpr operator value_type() const noexcept { return (value); } constexpr value_type operator()() const noexcept { return (value); } }; using true_type = integral_constant<bool, true>; using false_type = integral_constant<bool, false>; template <typename T> struct remove_reference { using type = T; }; template <typename T> struct remove_reference<T&> { using type = T; }; template <typename T> struct remove_reference<T&&> { using type = T; }; template <typename T> using remove_reference_t = typename remove_reference<T>::type; template <typename T> struct is_lvalue_reference : false_type { }; template <typename T> struct is_lvalue_reference<T&> : true_type { }; template <typename T> struct is_rvalue_reference : false_type { }; template <typename T> struct is_rvalue_reference<T&&> : true_type { }; template <typename T> inline constexpr T &&forward(typename remove_reference<T>::type &value) noexcept { return static_cast<T&&>(value); } template <typename T> inline constexpr T &&forward(typename remove_reference<T>::type &&value) noexcept { static_assert(!is_lvalue_reference<T>::value, "bad forward call"); return static_cast<T&&>(value); } template <typename T> inline constexpr typename remove_reference<T>::type &&move(T &&value) noexcept { return static_cast<typename remove_reference<T>::type&&>(value); } template <typename T> void swap_moveable(T &a, T &b) { T tmp = move(a); a = move(b); b = move(tmp); } template <typename T> struct remove_const { using type = T; }; template <typename T> struct remove_const<const T> { using type = T; }; template <typename T> struct remove_volatile { using type = T; }; template <typename T> struct remove_volatile<volatile T> { using type = T; }; template <typename T> using decay_simple_t = typename remove_const<typename remove_volatile<typename remove_reference<T>::type>::type>::type; template <typename T1, typename T2> struct is_same : false_type { }; template <typename T> struct is_same<T, T> : true_type { }; template <bool, typename T = void> struct enable_if { }; template <typename T> struct enable_if<true, T> { using type = T; }; template <bool Test, typename T = void> using enable_if_t = typename enable_if<Test, T>::type; template <bool, typename First, typename Second> struct conditional { using type = Second; }; template <typename First, typename Second> struct conditional<true, First, Second> { using type = First; }; template <bool Test, typename First, typename Second> using conditional_t = typename conditional<Test, First, Second>::type; template <typename T> struct add_const { using type = const T; }; template <typename T> using add_const_t = typename add_const<T>::type; template <typename T> constexpr add_const_t<T> &as_const(T& t) noexcept { return t; } template <typename T> void as_const(const T&&) = delete; // This is not full unique_ptr, but at least with std interface. template <typename T> class unique_ptr { public: constexpr unique_ptr() noexcept = default; unique_ptr(const unique_ptr<T> &) = delete; unique_ptr<T> &operator=(const unique_ptr<T> &) = delete; constexpr unique_ptr(std_::nullptr_t) { } unique_ptr<T> &operator=(std_::nullptr_t) noexcept { reset(); return (*this); } explicit unique_ptr(T *p) noexcept : _p(p) { } template <typename U> unique_ptr(unique_ptr<U> &&other) noexcept : _p(other.release()) { } template <typename U> unique_ptr<T> &operator=(unique_ptr<U> &&other) noexcept { reset(other.release()); return (*this); } unique_ptr<T> &operator=(unique_ptr<T> &&other) noexcept { if (this != &other) { reset(other.release()); } return (*this); } void swap(unique_ptr<T> &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 <typename T, typename... Args> inline unique_ptr<T> make_unique(Args&&... args) { return unique_ptr<T>(new T(forward<Args>(args)...)); } template <typename T> inline bool operator==(const unique_ptr<T> &a, std_::nullptr_t) noexcept { return !a; } template <typename T> inline bool operator==(std_::nullptr_t, const unique_ptr<T> &b) noexcept { return !b; } template <typename T> inline bool operator!=(const unique_ptr<T> &a, std_::nullptr_t b) noexcept { return !(a == b); } template <typename T> inline bool operator!=(std_::nullptr_t a, const unique_ptr<T> &b) noexcept { return !(a == b); } using _yes = char(&)[1]; using _no = char(&)[2]; template <typename Base, typename Derived> struct _host { operator Base*() const; operator Derived*(); }; template <typename Base, typename Derived> struct is_base_of { template <typename T> static _yes check(Derived*, T); static _no check(Base*, int); static constexpr bool value = sizeof(check(_host<Base, Derived>(), 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<uintptr_t>(ptr); auto a = (p - 1u + alignment) & -alignment; auto d = a - p; if ((size + d) > space) { return nullptr; } space -= d; return ptr = reinterpret_cast<void*>(a); } } // namespace std_