/* Copyright (c) 2016, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TORRENT_UNITS_HPP #define TORRENT_UNITS_HPP #include #include #include #include #include #include "libtorrent/config.hpp" namespace libtorrent { namespace aux { template struct difference_tag; template::value>::type> struct strong_typedef { using underlying_type = UnderlyingType; using diff_type = strong_typedef>; constexpr strong_typedef(strong_typedef const& rhs) noexcept = default; constexpr strong_typedef(strong_typedef&& rhs) noexcept = default; strong_typedef() noexcept = default; #if TORRENT_ABI_VERSION == 1 constexpr strong_typedef(UnderlyingType val) : m_val(val) {} constexpr operator UnderlyingType() const { return m_val; } #else constexpr explicit strong_typedef(UnderlyingType val) : m_val(val) {} constexpr explicit operator UnderlyingType() const { return m_val; } constexpr bool operator==(strong_typedef const& rhs) const { return m_val == rhs.m_val; } constexpr bool operator!=(strong_typedef const& rhs) const { return m_val != rhs.m_val; } constexpr bool operator<(strong_typedef const& rhs) const { return m_val < rhs.m_val; } constexpr bool operator>(strong_typedef const& rhs) const { return m_val > rhs.m_val; } constexpr bool operator>=(strong_typedef const& rhs) const { return m_val >= rhs.m_val; } constexpr bool operator<=(strong_typedef const& rhs) const { return m_val <= rhs.m_val; } #endif strong_typedef& operator++() { ++m_val; return *this; } strong_typedef& operator--() { --m_val; return *this; } strong_typedef operator++(int) & { return strong_typedef{m_val++}; } strong_typedef operator--(int) & { return strong_typedef{m_val--}; } friend diff_type operator-(strong_typedef lhs, strong_typedef rhs) { return diff_type{lhs.m_val - rhs.m_val}; } friend strong_typedef operator+(strong_typedef lhs, diff_type rhs) { return strong_typedef{lhs.m_val + static_cast(rhs)}; } friend strong_typedef operator+(diff_type lhs, strong_typedef rhs) { return strong_typedef{static_cast(lhs) + rhs.m_val}; } friend strong_typedef operator-(strong_typedef lhs, diff_type rhs) { return strong_typedef{lhs.m_val - static_cast(rhs)}; } strong_typedef& operator+=(diff_type rhs) & { m_val += static_cast(rhs); return *this; } strong_typedef& operator-=(diff_type rhs) & { m_val -= static_cast(rhs); return *this; } strong_typedef& operator=(strong_typedef const& rhs) & noexcept = default; strong_typedef& operator=(strong_typedef&& rhs) & noexcept = default; private: UnderlyingType m_val; }; // meta function to return the underlying type of a strong_typedef or enumeration // , or the type itself if it isn't a strong_typedef template struct underlying_index_t { using type = T; }; template struct underlying_index_t::value>::type> { using type = typename std::underlying_type::type; }; template struct underlying_index_t> { using type = U; }; struct piece_index_tag; struct file_index_tag; template std::string to_string(strong_typedef const t) { return std::to_string(static_cast(t)); } template strong_typedef next(strong_typedef v) { return ++v;} template strong_typedef prev(strong_typedef v) { return --v;} #if TORRENT_USE_IOSTREAM template std::ostream& operator<<(std::ostream& os, strong_typedef val) { return os << static_cast(val); } #endif } // namespace libtorrent::aux // this type represents a piece index in a torrent. using piece_index_t = aux::strong_typedef; // this type represents an index to a file in a torrent using file_index_t = aux::strong_typedef; } // namespace libtorrent namespace std { template class numeric_limits> : public std::numeric_limits { using type = libtorrent::aux::strong_typedef; public: static constexpr type (min)() { return type((std::numeric_limits::min)()); } static constexpr type (max)() { return type((std::numeric_limits::max)()); } }; template struct hash> : std::hash { using base = std::hash; using argument_type = libtorrent::aux::strong_typedef; #if __cplusplus < 201402 // this was deprecated in C++17 using result_type = typename base::result_type; #else using result_type = std::size_t; #endif result_type operator()(argument_type const& s) const { return this->base::operator()(static_cast(s)); } }; } #endif