From b72d7abfb05aab6e3be88d414811473cb9394465 Mon Sep 17 00:00:00 2001 From: Neil MacIntosh Date: Fri, 24 Jun 2016 04:54:09 -0700 Subject: [PATCH] Added definition of gsl::byte to match proposed std::byte. --- include/byte.h | 46 ++++++++++++++++++++-- tests/CMakeLists.txt | 1 + tests/byte_tests.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 tests/byte_tests.cpp diff --git a/include/byte.h b/include/byte.h index c6449aa..6e32fef 100644 --- a/include/byte.h +++ b/include/byte.h @@ -23,10 +23,48 @@ 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; + enum class byte : unsigned char {}; + + template ::value>> + constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept + { return b = byte(static_cast(b) << shift); } + + template ::value>> + constexpr byte operator<<(byte b, IntegerType shift) noexcept + { return byte(static_cast(b) << shift); } + + template ::value>> + constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept + { return b = byte(static_cast(b) >> shift); } + + template ::value>> + constexpr byte operator>> (byte b, IntegerType shift) noexcept + { return byte(static_cast(b) >> shift); } + + constexpr byte& operator|=(byte& l, byte r) noexcept + { return l = byte(static_cast(l) | static_cast(r)); } + + constexpr byte operator|(byte l, byte r) noexcept + { return byte(static_cast(l) + static_cast(r)); } + + constexpr byte& operator&=(byte& l, byte r) noexcept + { return l = byte(static_cast(l) & static_cast(r)); } + + constexpr byte operator&(byte l, byte r) noexcept + { return byte(static_cast(l) & static_cast(r)); } + + constexpr byte& operator^=(byte& l, byte r) noexcept + { return l = byte(static_cast(l) ^ static_cast(r)); } + + constexpr byte operator^(byte l, byte r) noexcept + { return byte(static_cast(l) ^ static_cast(r)); } + + constexpr byte operator~(byte b) noexcept + { return byte(~static_cast(b)); } + + template ::value>> + constexpr IntegerType to_integer(byte b) noexcept { return {b}; } + } // namespace gsl diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9723309..009b52d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,3 +54,4 @@ add_gsl_test(notnull_tests) add_gsl_test(assertion_tests) add_gsl_test(utils_tests) add_gsl_test(owner_tests) +add_gsl_test(byte_tests) \ No newline at end of file diff --git a/tests/byte_tests.cpp b/tests/byte_tests.cpp new file mode 100644 index 0000000..ff91e50 --- /dev/null +++ b/tests/byte_tests.cpp @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace gsl; + +namespace +{ + +SUITE(byte_tests) +{ + TEST(construction) + { + { + byte b = static_cast(4); + CHECK(static_cast(b) == 4); + } + + { + byte b = byte(12); + CHECK(static_cast(b) == 12); + } + + // waiting for C++17 enum class direct initializer support + //{ + // byte b { 14 }; + // CHECK(static_cast(b) == 14); + //} + } + + TEST(bitwise_operations) + { + byte b = byte(0xFF); + + byte a = byte(0x00); + CHECK((b | a) == byte(0xFF)); + CHECK(a == byte(0x00)); + + a |= b; + CHECK(a == byte(0xFF)); + + a = byte(0x01); + CHECK((b & a) == byte(0x01)); + + a &= b; + CHECK(a == byte(0x01)); + + CHECK((b ^ a) == byte(0xFE)); + + CHECK(a == byte(0x01)); + a ^= b; + CHECK(a == byte(0xFE)); + + a = byte(0x01); + CHECK(~a == byte(0xFE)); + + a = byte(0xFF); + CHECK((a << 4) == byte(0xF0)); + CHECK((a >> 4) == byte(0x0F)); + + a <<= 4; + CHECK(a == byte(0xF0)); + a >>= 4; + CHECK(a == byte(0x0F)); + } +} +} + +int main(int, const char* []) { return UnitTest::RunAllTests(); }