diff --git a/CMakeLists.txt b/CMakeLists.txt index 960e8eda..7eff2378 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ set(PREVIEW_DEFAULT_GENERATED_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${PREVIEW project(preview CXX) -option(PREVIEW_TEST "Build test" OFF) +option(PREVIEW_TEST "Build test" ON) add_library(preview INTERFACE) target_include_directories(preview INTERFACE "${PREVIEW_INCLUDE_DIR}") diff --git a/README.md b/README.md index 62f7f1c1..bef8729d 100644 --- a/README.md +++ b/README.md @@ -108,12 +108,12 @@ Implementation available in C++14 ~ : | Header | Total | | C++17 | C++20 | C++23 | C++26 | |-------------------------------------|---------------------------------------------------------|---|--------------------------------------------------------|---------------------------------------------------------|--------------------------------------------------------|--------------------------------------------------------| -| | ![](https://img.shields.io/badge/314/694-grey)![][p045] | | ![](https://img.shields.io/badge/44/113-grey)![][p039] | ![](https://img.shields.io/badge/233/429-grey)![][p054] | ![](https://img.shields.io/badge/59/144-grey)![][p041] | ![](https://img.shields.io/badge/18/135-grey)![][p013] | +| | ![](https://img.shields.io/badge/315/694-grey)![][p045] | | ![](https://img.shields.io/badge/44/113-grey)![][p039] | ![](https://img.shields.io/badge/234/429-grey)![][p054] | ![](https://img.shields.io/badge/59/144-grey)![][p041] | ![](https://img.shields.io/badge/18/135-grey)![][p013] | | | | | | | | | | [algorithm](#algorithm) | ![](https://img.shields.io/badge/55/115-grey)![][p048] | | ![](https://img.shields.io/badge/2/4-grey)![][p050] | ![](https://img.shields.io/badge/47/96-grey)![][p049] | ![](https://img.shields.io/badge/8/18-grey)![][p044] | ![](https://img.shields.io/badge/7/23-grey)![][p030] | | [any](#any) | ![](https://img.shields.io/badge/5/5-grey)![][p100] | | ![](https://img.shields.io/badge/5/5-grey)![][p100] | | | | | [array](#array) | ![](https://img.shields.io/badge/1/1-grey)![][p100] | | | ![](https://img.shields.io/badge/1/1-grey)![][p100] | | | -| [bit](#bit) | ![](https://img.shields.io/badge/2/14-grey)![][p014] | | | ![](https://img.shields.io/badge/1/13-grey)![][p008] | ![](https://img.shields.io/badge/1/1-grey)![][p100] | | +| [bit](#bit) | ![](https://img.shields.io/badge/3/14-grey)![][p021] | | | ![](https://img.shields.io/badge/2/13-grey)![][p015] | ![](https://img.shields.io/badge/1/1-grey)![][p100] | | | [concepts](#concepts) | ![](https://img.shields.io/badge/30/30-grey)![][p100] | | | ![](https://img.shields.io/badge/30/30-grey)![][p100] | ![](https://img.shields.io/badge/1/1-grey)![][p100] | | | [cstddef](#cstddef) | ![](https://img.shields.io/badge/2/2-grey)![][p100] | | ![](https://img.shields.io/badge/2/2-grey)![][p100] | | | | | [expected](#expected) | ![](https://img.shields.io/badge/4/4-grey)![][p100] | | | | ![](https://img.shields.io/badge/4/4-grey)![][p100] | | @@ -357,7 +357,7 @@ Description | | Introduced | Revision | |------------------|------------|----------| - | `endian` | ![][c20no] | | + | `endian` | ![][c20ok] | | | `bit_cast` | ![][c20ok] | | | `byteswap` | ![][c23ok] | | | `has_single_bit` | ![][c20no] | | diff --git a/cmake/RunConfiguration.cmake b/cmake/RunConfiguration.cmake index 6f0a2244..0f0f3cbb 100644 --- a/cmake/RunConfiguration.cmake +++ b/cmake/RunConfiguration.cmake @@ -2,6 +2,7 @@ include(CheckCXXSourceCompiles) include(CheckCXXCompilerFlag) include(CheckCXXSymbolExists) +include(config/CheckEndianness) include(config/HaveBuiltinBitCast) include(config/HaveBuiltinConstexprAddressof) include(config/HaveContiguousIteratorTag) diff --git a/cmake/config/CheckEndianness.cmake b/cmake/config/CheckEndianness.cmake new file mode 100644 index 00000000..72ee44a5 --- /dev/null +++ b/cmake/config/CheckEndianness.cmake @@ -0,0 +1,59 @@ +set(AllTypes1Byte_Source +"int main() { + static_asset(sizeof(char) == 1, \"\") && + static_asset(sizeof(short) == 1, \"\") && + static_asset(sizeof(int) == 1, \"\") && + static_asset(sizeof(long) == 1, \"\") && + static_asset(sizeof(long long) == 1, \"\") && + static_asset(sizeof(bool) == 1, \"\"); +}") + +check_cxx_source_compiles(AllTypes1Byte_Source PREVIEW_ARE_ALL_TYPES_1_BYTE) + +set(PREVIEW_BIG_ENDIAN 0) +set(PREVIEW_LITTLE_ENDIAN 1) +set(PREVIEW_OTHER_ENDIAN 2) + +file(WRITE ${CMAKE_BINARY_DIR}/CheckEndian.cpp +"#include +#include + +int main(int argc, char* argv[]) { + const std::uint32_t val{ 0x01'23'45'67 }; + const std::uint8_t* ptr{ reinterpret_cast(&val) }; + + if (ptr[0] == 0x01 && ptr[1] == 0x23 && ptr[2] == 0x45 && ptr[3] == 0x67) { + return ${PREVIEW_BIG_ENDIAN}; + } else if (ptr[0] == 0x67 && ptr[1] == 0x45 && ptr[2] == 0x23 && ptr[3] == 0x01) { + return ${PREVIEW_LITTLE_ENDIAN}; + } else { + return ${PREVIEW_OTHER_ENDIAN}; + } +}") + +if (PREVIEW_ARE_ALL_TYPES_1_BYTE EQUAL 1) + add_compile_definitions(PREVIEW_BIG_ENDIAN=0) + add_compile_definitions(PREVIEW_LITTLE_ENDIAN=0) + add_compile_definitions(PREVIEW_OTHER_ENDIAN=0) +else() + add_compile_definitions(PREVIEW_BIG_ENDIAN=${PREVIEW_BIG_ENDIAN}) + add_compile_definitions(PREVIEW_LITTLE_ENDIAN=${PREVIEW_LITTLE_ENDIAN}) + add_compile_definitions(PREVIEW_OTHER_ENDIAN=${PREVIEW_OTHER_ENDIAN}) +endif() + +try_run( + PREVIEW_ENDIAN COMPILE_RES ${CMAKE_BINARY_DIR} + SOURCES ${CMAKE_BINARY_DIR}/CheckEndian.cpp + ARGS ${CMAKE_BINARY_DIR}/endian.txt +) + +if(PREVIEW_ENDIAN EQUAL ${PREVIEW_BIG_ENDIAN}) + message(STATUS "Big endian") + add_compile_definitions(PREVIEW_ENDIAN=${PREVIEW_BIG_ENDIAN}) +elseif(PREVIEW_ENDIAN EQUAL ${PREVIEW_LITTLE_ENDIAN}) + message(STATUS "Little endian") + add_compile_definitions(PREVIEW_ENDIAN=${PREVIEW_LITTLE_ENDIAN}) +else() + message(STATUS "Other endian") + add_compile_definitions(PREVIEW_ENDIAN=${PREVIEW_OTHER_ENDIAN}) +endif() diff --git a/include/preview/__bit/endian.h b/include/preview/__bit/endian.h new file mode 100644 index 00000000..65f40a12 --- /dev/null +++ b/include/preview/__bit/endian.h @@ -0,0 +1,26 @@ +// +// Created by Chi-Iroh on 09/11/2024. +// + +#ifndef PREVIEW_BIT_ENDIAN_H_ +#define PREVIEW_BIT_ENDIAN_H_ + +#include "preview/config.h" + +#if PREVIEW_CXX_VERSION >= 20 + #include + + namespace preview { + using endian = std::endian; + } +#else + namespace preview { + enum class endian { + little = PREVIEW_LITTLE_ENDIAN, + big = PREVIEW_BIG_ENDIAN, + native = PREVIEW_ENDIAN + }; + }; +#endif + +#endif \ No newline at end of file diff --git a/include/preview/bit.h b/include/preview/bit.h index 26792dc4..8fcdcd6e 100644 --- a/include/preview/bit.h +++ b/include/preview/bit.h @@ -7,5 +7,6 @@ #include "preview/__bit/bit_cast.h" #include "preview/__bit/byteswap.h" +#include "preview/__bit/endian.h" #endif // PREVIEW_BIT_H_ diff --git a/test/bit.cc b/test/bit.cc index 1d6113f5..dfd3d642 100644 --- a/test/bit.cc +++ b/test/bit.cc @@ -60,3 +60,26 @@ TEST(VERSIONED(bit), byteswap_signed) { constexpr std::int64_t qword_same{ 0x44'44'44'44'44'44'44'44 }; EXPECT_EQ(preview::byteswap(qword_same), qword_same); } + +#if PREVIEW_CXX >= 17 + #define IF_CONSTEXPR if constexpr +#else + #define IF_CONSTEXPR if +#endif + +TEST(VERSIONED(bit), endianness) { + const std::uint32_t n{ 0x01'23'45'67 }; + const std::uint8_t* const ptr{ reinterpret_cast(&n) }; + + IF_CONSTEXPR (preview::endian::native == preview::endian::little) { + EXPECT_EQ(ptr[0], 0x67); + EXPECT_EQ(ptr[1], 0x45); + EXPECT_EQ(ptr[2], 0x23); + EXPECT_EQ(ptr[3], 0x01); + } else IF_CONSTEXPR (preview::endian::native == preview::endian::big) { + EXPECT_EQ(ptr[0], 0x01); + EXPECT_EQ(ptr[1], 0x23); + EXPECT_EQ(ptr[2], 0x45); + EXPECT_EQ(ptr[3], 0x67); + } +} \ No newline at end of file