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#ifndef GSL_BYTE_H 18#define GSL_BYTE_H 19 20// 21// make suppress attributes work for some compilers 22// Hopefully temporary until suppression standardization occurs 23// 24#if defined(__clang__) 25#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] 26#else 27#if defined(_MSC_VER) 28#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] 29#else 30#define GSL_SUPPRESS(x) 31#endif // _MSC_VER 32#endif // __clang__ 33 34#include <type_traits> 35 36// VS2017 15.8 added support for the __cpp_lib_byte definition 37// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires 38#ifdef _MSC_VER 39 40#pragma warning(push) 41 42// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. 43#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates does not always work 44 45#ifndef GSL_USE_STD_BYTE 46// this tests if we are under MSVC and the standard lib has std::byte and it is enabled 47#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) 48 49#define GSL_USE_STD_BYTE 1 50 51#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) 52 53#define GSL_USE_STD_BYTE 0 54 55#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) 56#endif // GSL_USE_STD_BYTE 57 58#else // _MSC_VER 59 60#ifndef GSL_USE_STD_BYTE 61#include <cstddef> /* __cpp_lib_byte */ 62// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte 63// also check if libc++ version is sufficient (> 5.0) or libstc++ actually contains std::byte 64#if defined(__cplusplus) && (__cplusplus >= 201703L) && \ 65 (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ 66 defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) 67 68#define GSL_USE_STD_BYTE 1 69 70#else // defined(__cplusplus) && (__cplusplus >= 201703L) && 71 // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || 72 // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) 73 74#define GSL_USE_STD_BYTE 0 75 76#endif //defined(__cplusplus) && (__cplusplus >= 201703L) && 77 // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || 78 // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) 79#endif // GSL_USE_STD_BYTE 80 81#endif // _MSC_VER 82 83// Use __may_alias__ attribute on gcc and clang 84#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5) 85#define byte_may_alias __attribute__((__may_alias__)) 86#else // defined __clang__ || defined __GNUC__ 87#define byte_may_alias 88#endif // defined __clang__ || defined __GNUC__ 89 90#if GSL_USE_STD_BYTE 91#include <cstddef> 92#endif 93 94namespace gsl 95{ 96#if GSL_USE_STD_BYTE 97 98using std::byte; 99using std::to_integer; 100 101#else // GSL_USE_STD_BYTE 102 103// This is a simple definition for now that allows 104// use of byte within span<> to be standards-compliant 105enum class byte_may_alias byte : unsigned char 106{ 107}; 108 109template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> 110constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept 111{ 112 return b = byte(static_cast<unsigned char>(b) << shift); 113} 114 115template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> 116constexpr byte operator<<(byte b, IntegerType shift) noexcept 117{ 118 return byte(static_cast<unsigned char>(b) << shift); 119} 120 121template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> 122constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept 123{ 124 return b = byte(static_cast<unsigned char>(b) >> shift); 125} 126 127template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> 128constexpr byte operator>>(byte b, IntegerType shift) noexcept 129{ 130 return byte(static_cast<unsigned char>(b) >> shift); 131} 132 133constexpr byte& operator|=(byte& l, byte r) noexcept 134{ 135 return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r)); 136} 137 138constexpr byte operator|(byte l, byte r) noexcept 139{ 140 return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r)); 141} 142 143constexpr byte& operator&=(byte& l, byte r) noexcept 144{ 145 return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); 146} 147 148constexpr byte operator&(byte l, byte r) noexcept 149{ 150 return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); 151} 152 153constexpr byte& operator^=(byte& l, byte r) noexcept 154{ 155 return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); 156} 157 158constexpr byte operator^(byte l, byte r) noexcept 159{ 160 return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); 161} 162 163constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); } 164 165template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> 166constexpr IntegerType to_integer(byte b) noexcept 167{ 168 return static_cast<IntegerType>(b); 169} 170 171#endif // GSL_USE_STD_BYTE 172 173template <bool E, typename T> 174constexpr byte to_byte_impl(T t) noexcept 175{ 176 static_assert( 177 E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " 178 "If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version."); 179 return static_cast<byte>(t); 180} 181template <> 182// NOTE: need suppression since c++14 does not allow "return {t}" 183// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work 184constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept 185{ 186 return byte(t); 187} 188 189template <typename T> 190constexpr byte to_byte(T t) noexcept 191{ 192 return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t); 193} 194 195template <int I> 196constexpr byte to_byte() noexcept 197{ 198 static_assert(I >= 0 && I <= 255, 199 "gsl::byte only has 8 bits of storage, values must be in range 0-255"); 200 return static_cast<byte>(I); 201} 202 203} // namespace gsl 204 205#ifdef _MSC_VER 206#pragma warning(pop) 207#endif // _MSC_VER 208 209#endif // GSL_BYTE_H 210