mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-16 01:40:46 +08:00
140 lines
2.7 KiB
C++
140 lines
2.7 KiB
C++
// IWYU pragma: private, include <meojson/json.hpp>
|
|
|
|
#pragma once
|
|
|
|
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
|
#include <bit>
|
|
|
|
namespace json::_bitops
|
|
{
|
|
using std::countl_one;
|
|
using std::countl_zero;
|
|
using std::countr_one;
|
|
using std::countr_zero;
|
|
|
|
inline constexpr bool is_little_endian()
|
|
{
|
|
return std::endian::native == std::endian::little;
|
|
}
|
|
}
|
|
#else
|
|
#include <cstdint>
|
|
|
|
namespace json::_bitops
|
|
{
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
inline constexpr int countl_zero(uint32_t x)
|
|
{
|
|
if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) {
|
|
return x == 0 ? 32 : __builtin_clz(x);
|
|
}
|
|
if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) {
|
|
return x == 0 ? 32 : __builtin_clzl(x);
|
|
}
|
|
return x == 0 ? 32 : __builtin_clzll(x);
|
|
}
|
|
|
|
inline constexpr int countr_zero(uint32_t x)
|
|
{
|
|
if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) {
|
|
return x == 0 ? 32 : __builtin_ctz(x);
|
|
}
|
|
if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) {
|
|
return x == 0 ? 32 : __builtin_ctzl(x);
|
|
}
|
|
return x == 0 ? 32 : __builtin_ctzll(x);
|
|
}
|
|
|
|
inline constexpr int countl_zero(uint64_t x)
|
|
{
|
|
return x == 0 ? 64 : __builtin_clzll(x);
|
|
}
|
|
|
|
inline constexpr int countr_zero(uint64_t x)
|
|
{
|
|
return x == 0 ? 64 : __builtin_ctzll(x);
|
|
}
|
|
#elif defined(_MSC_VER)
|
|
#ifdef __AVX2__
|
|
// lzcnt intrinsics is not constexpr
|
|
inline int countl_zero(uint32_t x)
|
|
{
|
|
return __lzcnt(x);
|
|
}
|
|
|
|
inline int countr_zero(uint32_t x)
|
|
{
|
|
return _tzcnt_u32(x);
|
|
}
|
|
|
|
inline int countl_zero(uint64_t x)
|
|
{
|
|
return (int)__lzcnt64(x);
|
|
}
|
|
|
|
inline int countr_zero(uint64_t x)
|
|
{
|
|
return (int)_tzcnt_u64(x);
|
|
}
|
|
#else
|
|
inline constexpr int countl_zero(uint32_t x)
|
|
{
|
|
unsigned long index = 0;
|
|
return _BitScanReverse(&index, x) ? 31 - index : 32;
|
|
}
|
|
|
|
inline constexpr int countr_zero(uint32_t x)
|
|
{
|
|
unsigned long index = 0;
|
|
return _BitScanForward(&index, x) ? index : 32;
|
|
}
|
|
|
|
inline constexpr int countl_zero(uint64_t x)
|
|
{
|
|
unsigned long index = 0;
|
|
return _BitScanReverse64(&index, x) ? 63 - index : 64;
|
|
}
|
|
|
|
inline constexpr int countr_zero(uint64_t x)
|
|
{
|
|
unsigned long index = 0;
|
|
return _BitScanForward64(&index, x) ? index : 64;
|
|
}
|
|
#endif // __AVX2__
|
|
#else // compiler
|
|
#error "bring your own bit counting implementation"
|
|
#endif
|
|
inline int countl_one(uint32_t x)
|
|
{
|
|
return countl_zero(~x);
|
|
}
|
|
|
|
inline int countr_one(uint32_t x)
|
|
{
|
|
return countr_zero(~x);
|
|
}
|
|
|
|
inline int countl_one(uint64_t x)
|
|
{
|
|
return countl_zero(~x);
|
|
}
|
|
|
|
inline int countr_one(uint64_t x)
|
|
{
|
|
return countr_zero(~x);
|
|
}
|
|
|
|
// no constexpr endian awareness before C++20
|
|
inline bool is_little_endian()
|
|
{
|
|
union
|
|
{
|
|
uint32_t u32;
|
|
uint8_t u8;
|
|
} u = { 0x01020304 };
|
|
|
|
return u.u8 == 4;
|
|
}
|
|
} // namespace json::_bitops
|
|
#endif // C++20
|