src: convert all endian checks to constexpr

This is finally possible in C++20 without having to rely on
compiler-defined macros, assuming none of our supported platforms are
mixed-endian.

Refs: https://github.com/nodejs/node/pull/44411
PR-URL: https://github.com/nodejs/node/pull/52974
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Tobias Nießen 2024-05-25 11:04:20 +02:00 committed by GitHub
parent 0cbbab9a4d
commit 177b8b957b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 21 additions and 27 deletions

View File

@ -666,7 +666,7 @@ void Fill(const FunctionCallbackInfo<Value>& args) {
} else if (enc == UCS2) {
str_length = str_obj->Length() * sizeof(uint16_t);
node::TwoByteValue str(env->isolate(), args[1]);
if (IsBigEndian())
if constexpr (IsBigEndian())
SwapBytes16(reinterpret_cast<char*>(&str[0]), str_length);
memcpy(ts_obj_data + start, *str, std::min(str_length, fill_length));
@ -960,7 +960,7 @@ void IndexOfString(const FunctionCallbackInfo<Value>& args) {
return args.GetReturnValue().Set(-1);
}
if (IsBigEndian()) {
if constexpr (IsBigEndian()) {
StringBytes::InlineDecoder decoder;
if (decoder.Decode(env, needle, enc).IsNothing()) return;
const uint16_t* decoded_string =

View File

@ -2262,10 +2262,12 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) {
auto ext = string->GetExternalOneByteStringResource();
buf = const_cast<char*>(ext->data());
len = ext->length();
} else if (enc == UCS2 && IsLittleEndian() && string->IsExternalTwoByte()) {
auto ext = string->GetExternalStringResource();
buf = reinterpret_cast<char*>(const_cast<uint16_t*>(ext->data()));
len = ext->length() * sizeof(*ext->data());
} else if (enc == UCS2 && string->IsExternalTwoByte()) {
if constexpr (IsLittleEndian()) {
auto ext = string->GetExternalStringResource();
buf = reinterpret_cast<char*>(const_cast<uint16_t*>(ext->data()));
len = ext->length() * sizeof(*ext->data());
}
}
}

View File

@ -111,7 +111,7 @@ MaybeLocal<Object> ToBufferEndian(Environment* env, MaybeStackBuffer<T>* buf) {
static_assert(sizeof(T) == 1 || sizeof(T) == 2,
"Currently only one- or two-byte buffers are supported");
if (sizeof(T) > 1 && IsBigEndian()) {
if constexpr (sizeof(T) > 1 && IsBigEndian()) {
SPREAD_BUFFER_ARG(ret.ToLocalChecked(), retbuf);
SwapBytes16(retbuf_data, retbuf_length);
}
@ -128,7 +128,7 @@ void CopySourceBuffer(MaybeStackBuffer<UChar>* dest,
dest->AllocateSufficientStorage(length_in_chars);
char* dst = reinterpret_cast<char*>(**dest);
memcpy(dst, data, length);
if (IsBigEndian()) {
if constexpr (IsBigEndian()) {
SwapBytes16(dst, length);
}
}
@ -527,7 +527,7 @@ void ConverterObject::Decode(const FunctionCallbackInfo<Value>& args) {
char* value = reinterpret_cast<char*>(output) + beginning;
if (IsBigEndian()) {
if constexpr (IsBigEndian()) {
SwapBytes16(value, length);
}

View File

@ -339,8 +339,7 @@ size_t StringBytes::Write(Isolate* isolate,
// the Buffer, so we need to reorder on BE platforms. See
// https://nodejs.org/api/buffer.html regarding Node's "ucs2"
// encoding specification
if (IsBigEndian())
SwapBytes16(buf, nbytes);
if constexpr (IsBigEndian()) SwapBytes16(buf, nbytes);
break;
}
@ -756,7 +755,7 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
case UCS2: {
size_t str_len = buflen / 2;
if (IsBigEndian()) {
if constexpr (IsBigEndian()) {
uint16_t* dst = node::UncheckedMalloc<uint16_t>(str_len);
if (str_len != 0 && dst == nullptr) {
*error = node::ERR_MEMORY_ALLOCATION_FAILED(isolate);
@ -803,7 +802,7 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
// Buffer, so we need to reorder on BE platforms. See
// https://nodejs.org/api/buffer.html regarding Node's "ucs2"
// encoding specification
if (IsBigEndian()) {
if constexpr (IsBigEndian()) {
uint16_t* dst = node::UncheckedMalloc<uint16_t>(buflen);
if (dst == nullptr) {
*error = node::ERR_MEMORY_ALLOCATION_FAILED(isolate);

View File

@ -37,6 +37,7 @@
#include <cstring>
#include <array>
#include <bit>
#include <limits>
#include <memory>
#include <set>
@ -778,24 +779,16 @@ inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
.Check(); \
} while (0)
enum class Endianness { LITTLE, BIG };
inline Endianness GetEndianness() {
// Constant-folded by the compiler.
const union {
uint8_t u8[2];
uint16_t u16;
} u = {{1, 0}};
return u.u16 == 1 ? Endianness::LITTLE : Endianness::BIG;
constexpr inline bool IsLittleEndian() {
return std::endian::native == std::endian::little;
}
inline bool IsLittleEndian() {
return GetEndianness() == Endianness::LITTLE;
constexpr inline bool IsBigEndian() {
return std::endian::native == std::endian::big;
}
inline bool IsBigEndian() {
return GetEndianness() == Endianness::BIG;
}
static_assert(IsLittleEndian() || IsBigEndian(),
"Node.js does not support mixed-endian systems");
// Round up a to the next highest multiple of b.
template <typename T>