Skip to content

Commit

Permalink
P1272R4 byteswap() (microsoft#2235)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
  • Loading branch information
2 people authored and AZero13 committed Nov 4, 2021
1 parent 556eb1a commit 9480264
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 0 deletions.
45 changes: 45 additions & 0 deletions stl/inc/bit
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,34 @@ _NODISCARD int _Checked_arm_arm64_countl_zero(const _Ty _Val) noexcept {
}
#endif // defined(_M_ARM) || defined(_M_ARM64)

#if _HAS_CXX23
_NODISCARD constexpr unsigned short _Byteswap_ushort(const unsigned short _Val) noexcept {
if (_STD is_constant_evaluated()) {
return static_cast<unsigned short>((_Val << 8) | (_Val >> 8));
} else {
return _byteswap_ushort(_Val);
}
}

_NODISCARD constexpr unsigned long _Byteswap_ulong(const unsigned long _Val) noexcept {
if (_STD is_constant_evaluated()) {
return (_Val << 24) | ((_Val << 8) & 0x00FF'0000) | ((_Val >> 8) & 0x0000'FF00) | (_Val >> 24);
} else {
return _byteswap_ulong(_Val);
}
}

_NODISCARD constexpr unsigned long long _Byteswap_uint64(const unsigned long long _Val) noexcept {
if (_STD is_constant_evaluated()) {
return (_Val << 56) | ((_Val << 40) & 0x00FF'0000'0000'0000) | ((_Val << 24) & 0x0000'FF00'0000'0000)
| ((_Val << 8) & 0x0000'00FF'0000'0000) | ((_Val >> 8) & 0x0000'0000'FF00'0000)
| ((_Val >> 24) & 0x0000'0000'00FF'0000) | ((_Val >> 40) & 0x0000'0000'0000'FF00) | (_Val >> 56);
} else {
return _byteswap_uint64(_Val);
}
}
#endif // _HAS_CXX23

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> _Enabled>
_NODISCARD constexpr int countl_zero(const _Ty _Val) noexcept {
#if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
Expand Down Expand Up @@ -268,6 +296,23 @@ _NODISCARD constexpr int popcount(const _Ty _Val) noexcept {
return _Popcount(_Val);
}

#if _HAS_CXX23
template <class _Ty, enable_if_t<is_integral_v<_Ty>, int> = 0>
_NODISCARD constexpr _Ty byteswap(const _Ty _Val) noexcept {
if constexpr (sizeof(_Ty) == 1) {
return _Val;
} else if constexpr (sizeof(_Ty) == 2) {
return static_cast<_Ty>(_Byteswap_ushort(static_cast<unsigned short>(_Val)));
} else if constexpr (sizeof(_Ty) == 4) {
return static_cast<_Ty>(_Byteswap_ulong(static_cast<unsigned long>(_Val)));
} else if constexpr (sizeof(_Ty) == 8) {
return static_cast<_Ty>(_Byteswap_uint64(static_cast<unsigned long long>(_Val)));
} else {
static_assert(_Always_false<_Ty>, "Unexpected integer size");
}
}
#endif // _HAS_CXX23

enum class endian { little = 0, big = 1, native = little };

_STD_END
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
// P0943R6 Supporting C Atomics In C++
// P1048R1 is_scoped_enum
// P1132R7 out_ptr(), inout_ptr()
// P1272R4 byteswap()
// P1425R4 Iterator Pair Constructors For stack And queue
// P1659R3 ranges::starts_with, ranges::ends_with
// P1679R3 contains() For basic_string/basic_string_view
Expand Down Expand Up @@ -1363,6 +1364,7 @@
#define __cpp_lib_allocate_at_least 202106L
#endif // __cpp_lib_concepts

#define __cpp_lib_byteswap 202110L
#define __cpp_lib_invoke_r 202106L
#define __cpp_lib_is_scoped_enum 202011L

Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ tests\P1135R6_latch
tests\P1135R6_semaphore
tests\P1165R1_consistently_propagating_stateful_allocators
tests\P1208R6_source_location
tests\P1272R4_byteswap
tests\P1423R3_char8_t_remediation
tests\P1425R4_queue_stack_constructors
tests\P1502R1_standard_library_header_units
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P1272R4_byteswap/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
46 changes: 46 additions & 0 deletions tests/std/tests/P1272R4_byteswap/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <bit>
#include <cassert>

using namespace std;

template <typename T>
constexpr bool test_byteswap(const auto src, const auto result) {
static_assert(noexcept(byteswap(T{})));
return byteswap(static_cast<T>(src)) == static_cast<T>(result);
}

constexpr bool test_byteswap_all_types() {
assert(test_byteswap<bool>(true, true));

assert(test_byteswap<char>(0x13, 0x13));
assert(test_byteswap<signed char>(0x13, 0x13));
assert(test_byteswap<unsigned char>(0x13, 0x13));
#ifdef __cpp_char8_t
assert(test_byteswap<char8_t>(0x13, 0x13));
#endif

assert(test_byteswap<short>(0xAC34, 0x34AC));
assert(test_byteswap<unsigned short>(0xAC34, 0x34AC));
assert(test_byteswap<char16_t>(0xAC34, 0x34AC));
assert(test_byteswap<wchar_t>(0xAC34, 0x34AC));

assert(test_byteswap<int>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<unsigned int>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<long>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<unsigned long>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<char32_t>(0x1234ABCD, 0xCDAB3412));

assert(test_byteswap<long long>(0x1234567890ABCDEF, 0xEFCDAB9078563412));
assert(test_byteswap<unsigned long long>(0x1234567890ABCDEF, 0xEFCDAB9078563412));

return true;
}

static_assert(test_byteswap_all_types());

int main() {
test_byteswap_all_types();
}
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,20 @@ STATIC_ASSERT(__cpp_lib_byte == 201603L);
#endif
#endif

#if _HAS_CXX23
#ifndef __cpp_lib_byteswap
#error __cpp_lib_byteswap is not defined
#elif __cpp_lib_byteswap != 202110L
#error __cpp_lib_byteswap is not 202110L
#else
STATIC_ASSERT(__cpp_lib_byteswap == 202110L);
#endif
#else
#ifdef __cpp_lib_byteswap
#error __cpp_lib_byteswap is defined
#endif
#endif

#if _HAS_CXX20 && defined(__cpp_char8_t)
#ifndef __cpp_lib_char8_t
#error __cpp_lib_char8_t is not defined
Expand Down

0 comments on commit 9480264

Please sign in to comment.