diff options
-rw-r--r-- | include/byte.h | 33 | ||||
-rw-r--r-- | include/multi_span.h | 4 | ||||
-rw-r--r-- | include/span.h | 34 | ||||
-rw-r--r-- | tests/span_tests.cpp | 91 |
4 files changed, 124 insertions, 38 deletions
diff --git a/include/byte.h b/include/byte.h new file mode 100644 index 0000000..c6449aa --- /dev/null +++ b/include/byte.h @@ -0,0 +1,33 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#ifndef GSL_BYTE_H +#define GSL_BYTE_H + +namespace gsl +{ + // This is a simple definition for now that allows + // use of byte within span<> to be standards-compliant + // + // Ultimately a small language change would allow a more + // robust definition (see WG21 proposal P0257 for details). + using byte = unsigned char; + +} // namespace gsl + +#endif // GSL_BYTE_H
\ No newline at end of file diff --git a/include/multi_span.h b/include/multi_span.h index 523f324..3d00c6e 100644 --- a/include/multi_span.h +++ b/include/multi_span.h @@ -21,6 +21,7 @@ #include "gsl_assert.h" #include "gsl_util.h" +#include "byte.h" #include <algorithm> #include <array> #include <cassert> @@ -1053,9 +1054,6 @@ template <typename Span> class contiguous_span_iterator; template <typename Span> class general_span_iterator; -enum class byte : std::uint8_t -{ -}; template <std::ptrdiff_t DimSize = dynamic_range> struct dim diff --git a/include/span.h b/include/span.h index 2760121..7152c2d 100644 --- a/include/span.h +++ b/include/span.h @@ -21,6 +21,7 @@ #include "gsl_assert.h" #include "gsl_util.h" +#include "byte.h" #include <array> #include <limits> #include <iterator> @@ -126,13 +127,13 @@ struct is_allowed_element_type_conversion }; template <class From> -struct is_allowed_element_type_conversion<From, char> +struct is_allowed_element_type_conversion<From, byte> : std::integral_constant<bool, !std::is_const<From>::value> { }; template <class From> -struct is_allowed_element_type_conversion<From, const char> +struct is_allowed_element_type_conversion<From, const byte> : std::integral_constant<bool, true> { }; @@ -507,14 +508,33 @@ constexpr bool operator>=(const span<ElementType, Extent>& l, const span<Element { return !(l < r); } -#if 0 // TODO +namespace details +{ + // if we only supported compilers with good constexpr support then + // this pair of classes could collapse down to a constexpr function + + // we should use a narrow_cast<> to go to size_t, but older compilers may not see it as constexpr + // and so will fail compilation of the template + template <class ElementType, ptrdiff_t Extent> + struct calculate_byte_size : + std::integral_constant<std::ptrdiff_t, static_cast<ptrdiff_t>(sizeof(ElementType) * static_cast<size_t>(Extent))> + {}; + + template <class ElementType> + struct calculate_byte_size<ElementType, dynamic_extent> : + std::integral_constant<std::ptrdiff_t, dynamic_extent> + {}; +} + + // [span.objectrep], views of object representation template <class ElementType, ptrdiff_t Extent> -constexpr span<const char, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept; +constexpr span<const byte, details::calculate_byte_size<ElementType, Extent>::value> as_bytes(span<ElementType, Extent> s) noexcept +{ return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; } -template <class ElementType, ptrdiff_t Extent> -constexpr span<char, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType) * Extent))> as_writeable_bytes(span<ElementType, Extent>) noexcept; -#endif +template <class ElementType, ptrdiff_t Extent, class = std::enable_if_t<!std::is_const<ElementType>::value>> +constexpr span<byte, details::calculate_byte_size<ElementType, Extent>::value> as_writeable_bytes(span<ElementType, Extent> s) noexcept +{ return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; } } // namespace gsl diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 694d9a2..ddae404 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -921,6 +921,69 @@ SUITE(span_tests) } } + TEST(as_bytes) + { + int a[] = {1, 2, 3, 4}; + + { + span<const int> s = a; + CHECK(s.length() == 4); + span<const byte> bs = as_bytes(s); + CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data())); + CHECK(bs.length() == s.length_bytes()); + } + + { + span<int> s; + auto bs = as_bytes(s); + CHECK(bs.length() == s.length()); + CHECK(bs.length() == 0); + CHECK(bs.size_bytes() == 0); + CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data())); + CHECK(bs.data() == nullptr); + } + + { + span<int> s = a; + auto bs = as_bytes(s); + CHECK(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data())); + CHECK(bs.length() == s.length_bytes()); + } + } + + TEST(as_writeable_bytes) + { + int a[] = {1, 2, 3, 4}; + + { +#ifdef CONFIRM_COMPILATION_ERRORS + // you should not be able to get writeable bytes for const objects + span<const int> s = a; + CHECK(s.length() == 4); + span<const byte> bs = as_writeable_bytes(s); + CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data())); + CHECK(bs.length() == s.length_bytes()); +#endif + } + + { + span<int> s; + auto bs = as_writeable_bytes(s); + CHECK(bs.length() == s.length()); + CHECK(bs.length() == 0); + CHECK(bs.size_bytes() == 0); + CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data())); + CHECK(bs.data() == nullptr); + } + + { + span<int> s = a; + auto bs = as_writeable_bytes(s); + CHECK(static_cast<void*>(bs.data()) == static_cast<void*>(s.data())); + CHECK(bs.length() == s.length_bytes()); + } + } + #if 0 TEST(fixed_size_conversions) { @@ -1018,34 +1081,6 @@ SUITE(span_tests) CHECK_THROW(f(), fail_fast); } - TEST(as_writeable_bytes) - { - int a[] = {1, 2, 3, 4}; - - { -#ifdef CONFIRM_COMPILATION_ERRORS - // you should not be able to get writeable bytes for const objects - span<const int, dynamic_range> av = a; - auto wav = av.as_writeable_bytes(); -#endif - } - - { - span<int, dynamic_range> av; - auto wav = as_writeable_bytes(av); - CHECK(wav.length() == av.length()); - CHECK(wav.length() == 0); - CHECK(wav.size_bytes() == 0); - } - - { - span<int, dynamic_range> av = a; - auto wav = as_writeable_bytes(av); - CHECK(wav.data() == (byte*) &a[0]); - CHECK(wav.length() == sizeof(a)); - } - } - #endif } |