tdesktop/Telegram/SourceFiles/core/stl_subset.h

299 lines
6.7 KiB
C
Raw Normal View History

/*
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>
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>
2016-09-29 14:04:43 +00:00
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_