Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 176cb76

Browse files
committed
Add constexpr endianness utilities
1 parent 599a6d4 commit 176cb76

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

fml/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ if (enable_unittests) {
268268
"backtrace_unittests.cc",
269269
"base32_unittest.cc",
270270
"command_line_unittest.cc",
271+
"endianness_unittests.cc",
271272
"file_unittest.cc",
272273
"hash_combine_unittests.cc",
273274
"hex_codec_unittest.cc",

fml/endianness.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_FML_ENDIANNESS_H_
6+
#define FLUTTER_FML_ENDIANNESS_H_
7+
8+
#include <cstdint>
9+
#include <type_traits>
10+
#if defined(_MSC_VER)
11+
#include "intrin.h"
12+
#endif
13+
14+
#include "flutter/fml/build_config.h"
15+
16+
// Compiler intrinsics for flipping endianness.
17+
#define BYTESWAP16(n) __builtin_bswap16(n)
18+
#define BYTESWAP32(n) __builtin_bswap32(n)
19+
#define BYTESWAP64(n) __builtin_bswap64(n)
20+
21+
#if defined(_MSC_VER)
22+
#define BYTESWAP16(n) _byteswap_ushort(n)
23+
#define BYTESWAP32(n) _byteswap_ulong(n)
24+
#define BYTESWAP64(n) _byteswap_uint64(n)
25+
#endif
26+
27+
namespace fml {
28+
29+
/// @brief Flips the endianness of the given value.
30+
template <typename T>
31+
constexpr T ByteSwap(T n) {
32+
if constexpr (sizeof(T) == 1) {
33+
return n;
34+
} else if constexpr (sizeof(T) == 2) {
35+
return (T)BYTESWAP16((uint16_t)n);
36+
} else if constexpr (sizeof(T) == 4) {
37+
return (T)BYTESWAP32((uint32_t)n);
38+
} else if constexpr (sizeof(T) == 8) {
39+
return (T)BYTESWAP64((uint64_t)n);
40+
} else {
41+
static_assert(!sizeof(T), "Unsupported size");
42+
}
43+
}
44+
45+
/// @brief Convert a known big endian value to match the endianness of the
46+
/// current architecture. This is effectively a cross platform
47+
/// ntohl/ntohs (as network byte order is always Big Endian).
48+
template <typename T>
49+
constexpr T BigEndianToArch(T n) {
50+
#if ARCH_CPU_LITTLE_ENDIAN
51+
return ByteSwap<T>(n);
52+
#else
53+
return n;
54+
#endif
55+
}
56+
57+
/// @brief Convert a known little endian value to match the endianness of the
58+
/// current architecture.
59+
template <typename T>
60+
constexpr T LittleEndianToArch(T n) {
61+
#if !ARCH_CPU_LITTLE_ENDIAN
62+
return ByteSwap<T>(n);
63+
#else
64+
return n;
65+
#endif
66+
}
67+
68+
} // namespace fml
69+
70+
#endif // FLUTTER_FML_ENDIANNESS_H_

fml/endianness_unittests.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/fml/endianness.h"
6+
7+
#include "flutter/testing/testing.h"
8+
9+
namespace fml {
10+
namespace testing {
11+
12+
TEST(EndiannessTest, ByteSwap) {
13+
ASSERT_EQ(ByteSwap<int16_t>(0x1122), 0x2211);
14+
ASSERT_EQ(ByteSwap<int32_t>(0x11223344), 0x44332211);
15+
ASSERT_EQ(ByteSwap<uint64_t>(0x1122334455667788), 0x8877665544332211);
16+
}
17+
18+
TEST(EndiannessTest, BigEndianToArch) {
19+
#if ARCH_CPU_LITTLE_ENDIAN
20+
uint32_t expected = 0x44332211;
21+
#else
22+
uint32_t expected = 0x11223344;
23+
#endif
24+
ASSERT_EQ(BigEndianToArch(0x11223344u), expected);
25+
}
26+
27+
TEST(EndiannessTest, LittleEndianToArch) {
28+
#if ARCH_CPU_LITTLE_ENDIAN
29+
uint32_t expected = 0x11223344;
30+
#else
31+
uint32_t expected = 0x44332211;
32+
#endif
33+
ASSERT_EQ(LittleEndianToArch(0x11223344u), expected);
34+
}
35+
36+
} // namespace testing
37+
} // namespace fml

0 commit comments

Comments
 (0)