Home | History | Annotate | Download | only in gsl
      1 ///////////////////////////////////////////////////////////////////////////////
      2 //
      3 // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
      4 //
      5 // This code is licensed under the MIT License (MIT).
      6 //
      7 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      8 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      9 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     10 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     11 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     12 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     13 // THE SOFTWARE.
     14 //
     15 ///////////////////////////////////////////////////////////////////////////////
     16 
     17 #pragma once
     18 
     19 #ifndef GSL_BYTE_H
     20 #define GSL_BYTE_H
     21 
     22 #include <type_traits>
     23 
     24 #ifdef _MSC_VER
     25 
     26 #pragma warning(push)
     27 
     28 // don't warn about function style casts in byte related operators
     29 #pragma warning(disable : 26493)
     30 
     31 #ifndef GSL_USE_STD_BYTE
     32 // this tests if we are under MSVC and the standard lib has std::byte and it is enabled
     33 #if _MSC_VER >= 1911 && (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE)
     34 
     35 #define GSL_USE_STD_BYTE 1
     36 
     37 #else // _MSC_VER >= 1911 && (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE)
     38 
     39 #define GSL_USE_STD_BYTE 0
     40 
     41 #endif // _MSC_VER >= 1911 && (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE)
     42 #endif // GSL_USE_STD_BYTE
     43 
     44 #else // _MSC_VER
     45 
     46 #ifndef GSL_USE_STD_BYTE
     47 // this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte
     48 #if defined(__cplusplus) && (__cplusplus >= 201703L)
     49 
     50 #define GSL_USE_STD_BYTE 1
     51 #include <cstddef>
     52 
     53 #else // defined(__cplusplus) && (__cplusplus >= 201703L)
     54 
     55 #define GSL_USE_STD_BYTE 0
     56 
     57 #endif //defined(__cplusplus) && (__cplusplus >= 201703L)
     58 #endif // GSL_USE_STD_BYTE
     59 
     60 #endif           // _MSC_VER
     61 
     62 namespace gsl
     63 {
     64 #if GSL_USE_STD_BYTE
     65 
     66 
     67 using std::byte;
     68 using std::to_integer;
     69 
     70 #else // GSL_USE_STD_BYTE
     71 
     72 // This is a simple definition for now that allows
     73 // use of byte within span<> to be standards-compliant
     74 enum class byte : unsigned char
     75 {
     76 };
     77 
     78 template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
     79 inline constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
     80 {
     81     return b = byte(static_cast<unsigned char>(b) << shift);
     82 }
     83 
     84 template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
     85 inline constexpr byte operator<<(byte b, IntegerType shift) noexcept
     86 {
     87     return byte(static_cast<unsigned char>(b) << shift);
     88 }
     89 
     90 template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
     91 inline constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
     92 {
     93     return b = byte(static_cast<unsigned char>(b) >> shift);
     94 }
     95 
     96 template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
     97 inline constexpr byte operator>>(byte b, IntegerType shift) noexcept
     98 {
     99     return byte(static_cast<unsigned char>(b) >> shift);
    100 }
    101 
    102 inline constexpr byte& operator|=(byte& l, byte r) noexcept
    103 {
    104     return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
    105 }
    106 
    107 inline constexpr byte operator|(byte l, byte r) noexcept
    108 {
    109     return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
    110 }
    111 
    112 inline constexpr byte& operator&=(byte& l, byte r) noexcept
    113 {
    114     return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
    115 }
    116 
    117 inline constexpr byte operator&(byte l, byte r) noexcept
    118 {
    119     return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
    120 }
    121 
    122 inline constexpr byte& operator^=(byte& l, byte r) noexcept
    123 {
    124     return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
    125 }
    126 
    127 inline constexpr byte operator^(byte l, byte r) noexcept
    128 {
    129     return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
    130 }
    131 
    132 inline constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
    133 
    134 template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
    135 inline constexpr IntegerType to_integer(byte b) noexcept
    136 {
    137     return static_cast<IntegerType>(b);
    138 }
    139 
    140 #endif // GSL_USE_STD_BYTE
    141 
    142 template <bool E, typename T>
    143 inline constexpr byte to_byte_impl(T t) noexcept
    144 {
    145     static_assert(
    146         E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
    147            "If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
    148     return static_cast<byte>(t);
    149 }
    150 template <>
    151 inline constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
    152 {
    153     return byte(t);
    154 }
    155 
    156 template <typename T>
    157 inline constexpr byte to_byte(T t) noexcept
    158 {
    159     return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
    160 }
    161 
    162 template <int I>
    163 inline constexpr byte to_byte() noexcept
    164 {
    165     static_assert(I >= 0 && I <= 255,
    166                   "gsl::byte only has 8 bits of storage, values must be in range 0-255");
    167     return static_cast<byte>(I);
    168 }
    169 
    170 } // namespace gsl
    171 
    172 #ifdef _MSC_VER
    173 #pragma warning(pop)
    174 #endif // _MSC_VER
    175 
    176 #endif // GSL_BYTE_H
    177