From 176cb76aabea7f0da71a3236a728026e7f86159d Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 27 Jan 2022 13:12:46 -0800 Subject: [PATCH 1/3] Add constexpr endianness utilities --- fml/BUILD.gn | 1 + fml/endianness.h | 70 +++++++++++++++++++++++++++++++++++++ fml/endianness_unittests.cc | 37 ++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 fml/endianness.h create mode 100644 fml/endianness_unittests.cc diff --git a/fml/BUILD.gn b/fml/BUILD.gn index 1f764cea4b6f7..ea9a437ef6688 100644 --- a/fml/BUILD.gn +++ b/fml/BUILD.gn @@ -268,6 +268,7 @@ if (enable_unittests) { "backtrace_unittests.cc", "base32_unittest.cc", "command_line_unittest.cc", + "endianness_unittests.cc", "file_unittest.cc", "hash_combine_unittests.cc", "hex_codec_unittest.cc", diff --git a/fml/endianness.h b/fml/endianness.h new file mode 100644 index 0000000000000..fe24ef59e41b5 --- /dev/null +++ b/fml/endianness.h @@ -0,0 +1,70 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_FML_ENDIANNESS_H_ +#define FLUTTER_FML_ENDIANNESS_H_ + +#include +#include +#if defined(_MSC_VER) +#include "intrin.h" +#endif + +#include "flutter/fml/build_config.h" + +// Compiler intrinsics for flipping endianness. +#define BYTESWAP16(n) __builtin_bswap16(n) +#define BYTESWAP32(n) __builtin_bswap32(n) +#define BYTESWAP64(n) __builtin_bswap64(n) + +#if defined(_MSC_VER) +#define BYTESWAP16(n) _byteswap_ushort(n) +#define BYTESWAP32(n) _byteswap_ulong(n) +#define BYTESWAP64(n) _byteswap_uint64(n) +#endif + +namespace fml { + +/// @brief Flips the endianness of the given value. +template +constexpr T ByteSwap(T n) { + if constexpr (sizeof(T) == 1) { + return n; + } else if constexpr (sizeof(T) == 2) { + return (T)BYTESWAP16((uint16_t)n); + } else if constexpr (sizeof(T) == 4) { + return (T)BYTESWAP32((uint32_t)n); + } else if constexpr (sizeof(T) == 8) { + return (T)BYTESWAP64((uint64_t)n); + } else { + static_assert(!sizeof(T), "Unsupported size"); + } +} + +/// @brief Convert a known big endian value to match the endianness of the +/// current architecture. This is effectively a cross platform +/// ntohl/ntohs (as network byte order is always Big Endian). +template +constexpr T BigEndianToArch(T n) { +#if ARCH_CPU_LITTLE_ENDIAN + return ByteSwap(n); +#else + return n; +#endif +} + +/// @brief Convert a known little endian value to match the endianness of the +/// current architecture. +template +constexpr T LittleEndianToArch(T n) { +#if !ARCH_CPU_LITTLE_ENDIAN + return ByteSwap(n); +#else + return n; +#endif +} + +} // namespace fml + +#endif // FLUTTER_FML_ENDIANNESS_H_ diff --git a/fml/endianness_unittests.cc b/fml/endianness_unittests.cc new file mode 100644 index 0000000000000..24b35464e82bd --- /dev/null +++ b/fml/endianness_unittests.cc @@ -0,0 +1,37 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/fml/endianness.h" + +#include "flutter/testing/testing.h" + +namespace fml { +namespace testing { + +TEST(EndiannessTest, ByteSwap) { + ASSERT_EQ(ByteSwap(0x1122), 0x2211); + ASSERT_EQ(ByteSwap(0x11223344), 0x44332211); + ASSERT_EQ(ByteSwap(0x1122334455667788), 0x8877665544332211); +} + +TEST(EndiannessTest, BigEndianToArch) { +#if ARCH_CPU_LITTLE_ENDIAN + uint32_t expected = 0x44332211; +#else + uint32_t expected = 0x11223344; +#endif + ASSERT_EQ(BigEndianToArch(0x11223344u), expected); +} + +TEST(EndiannessTest, LittleEndianToArch) { +#if ARCH_CPU_LITTLE_ENDIAN + uint32_t expected = 0x11223344; +#else + uint32_t expected = 0x44332211; +#endif + ASSERT_EQ(LittleEndianToArch(0x11223344u), expected); +} + +} // namespace testing +} // namespace fml From 35d4b612df77136cad926a17da4193fa221b7f8c Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 27 Jan 2022 13:32:36 -0800 Subject: [PATCH 2/3] Licenses --- ci/licenses_golden/licenses_flutter | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 536c859585413..594268f6325d8 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -176,6 +176,8 @@ FILE: ../../../flutter/fml/dart/dart_converter.h FILE: ../../../flutter/fml/delayed_task.cc FILE: ../../../flutter/fml/delayed_task.h FILE: ../../../flutter/fml/eintr_wrapper.h +FILE: ../../../flutter/fml/endianness.h +FILE: ../../../flutter/fml/endianness_unittests.cc FILE: ../../../flutter/fml/file.cc FILE: ../../../flutter/fml/file.h FILE: ../../../flutter/fml/file_unittest.cc From e85b19d4d61ac2237a1001d7da5010860c135da4 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 28 Jan 2022 10:22:50 -0800 Subject: [PATCH 3/3] Address comments --- ci/licenses_golden/licenses_flutter | 1 + fml/BUILD.gn | 2 ++ fml/endianness.cc | 5 +++++ fml/endianness.h | 27 +++++++++++++++------------ 4 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 fml/endianness.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 594268f6325d8..a43d07e1c31fc 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -176,6 +176,7 @@ FILE: ../../../flutter/fml/dart/dart_converter.h FILE: ../../../flutter/fml/delayed_task.cc FILE: ../../../flutter/fml/delayed_task.h FILE: ../../../flutter/fml/eintr_wrapper.h +FILE: ../../../flutter/fml/endianness.cc FILE: ../../../flutter/fml/endianness.h FILE: ../../../flutter/fml/endianness_unittests.cc FILE: ../../../flutter/fml/file.cc diff --git a/fml/BUILD.gn b/fml/BUILD.gn index ea9a437ef6688..39610f6aa5613 100644 --- a/fml/BUILD.gn +++ b/fml/BUILD.gn @@ -21,6 +21,8 @@ source_set("fml") { "delayed_task.cc", "delayed_task.h", "eintr_wrapper.h", + "endianness.cc", + "endianness.h", "file.cc", "file.h", "hash_combine.h", diff --git a/fml/endianness.cc b/fml/endianness.cc new file mode 100644 index 0000000000000..c7de7861f7ef6 --- /dev/null +++ b/fml/endianness.cc @@ -0,0 +1,5 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/fml/endianness.h" diff --git a/fml/endianness.h b/fml/endianness.h index fe24ef59e41b5..4951f7c2edeaf 100644 --- a/fml/endianness.h +++ b/fml/endianness.h @@ -14,29 +14,30 @@ #include "flutter/fml/build_config.h" // Compiler intrinsics for flipping endianness. -#define BYTESWAP16(n) __builtin_bswap16(n) -#define BYTESWAP32(n) __builtin_bswap32(n) -#define BYTESWAP64(n) __builtin_bswap64(n) +#define FML_BYTESWAP_16(n) __builtin_bswap16(n) +#define FML_BYTESWAP_32(n) __builtin_bswap32(n) +#define FML_BYTESWAP_64(n) __builtin_bswap64(n) #if defined(_MSC_VER) -#define BYTESWAP16(n) _byteswap_ushort(n) -#define BYTESWAP32(n) _byteswap_ulong(n) -#define BYTESWAP64(n) _byteswap_uint64(n) +#define FML_BYTESWAP_16(n) _byteswap_ushort(n) +#define FML_BYTESWAP_32(n) _byteswap_ulong(n) +#define FML_BYTESWAP_64(n) _byteswap_uint64(n) #endif namespace fml { /// @brief Flips the endianness of the given value. -template +/// The given value must be an integral type of size 1, 2, 4, or 8. +template >> constexpr T ByteSwap(T n) { if constexpr (sizeof(T) == 1) { return n; } else if constexpr (sizeof(T) == 2) { - return (T)BYTESWAP16((uint16_t)n); + return (T)FML_BYTESWAP_16((uint16_t)n); } else if constexpr (sizeof(T) == 4) { - return (T)BYTESWAP32((uint32_t)n); + return (T)FML_BYTESWAP_32((uint32_t)n); } else if constexpr (sizeof(T) == 8) { - return (T)BYTESWAP64((uint64_t)n); + return (T)FML_BYTESWAP_64((uint64_t)n); } else { static_assert(!sizeof(T), "Unsupported size"); } @@ -45,7 +46,8 @@ constexpr T ByteSwap(T n) { /// @brief Convert a known big endian value to match the endianness of the /// current architecture. This is effectively a cross platform /// ntohl/ntohs (as network byte order is always Big Endian). -template +/// The given value must be an integral type of size 1, 2, 4, or 8. +template >> constexpr T BigEndianToArch(T n) { #if ARCH_CPU_LITTLE_ENDIAN return ByteSwap(n); @@ -56,7 +58,8 @@ constexpr T BigEndianToArch(T n) { /// @brief Convert a known little endian value to match the endianness of the /// current architecture. -template +/// The given value must be an integral type of size 1, 2, 4, or 8. +template >> constexpr T LittleEndianToArch(T n) { #if !ARCH_CPU_LITTLE_ENDIAN return ByteSwap(n);