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