Skip to content

Commit

Permalink
Added preview::endian
Browse files Browse the repository at this point in the history
  • Loading branch information
Chi-Iroh committed Nov 24, 2024
1 parent 82d1195 commit 6e242e7
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmake/RunConfiguration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include(CheckCXXSourceCompiles)
include(CheckCXXCompilerFlag)
include(CheckCXXSymbolExists)

include(config/CheckEndianness)
include(config/HaveBuiltinBitCast)
include(config/HaveBuiltinConstexprAddressof)
include(config/HaveContiguousIteratorTag)
Expand Down
62 changes: 62 additions & 0 deletions cmake/config/CheckEndianness.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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 <cstdint>
#include <fstream>
int main(int argc, char* argv[]) {
const std::uint32_t val{ 0x01'23'45'67 };
const std::uint8_t* ptr{ reinterpret_cast<const std::uint8_t*>(&val) };
std::ofstream out{ argv[1] };
if (ptr[0] == 0x01 && ptr[1] == 0x23 && ptr[2] == 0x45 && ptr[3] == 0x67) {
out << ${PREVIEW_BIG_ENDIAN} << std::endl;
} else if (ptr[0] == 0x67 && ptr[1] == 0x45 && ptr[2] == 0x23 && ptr[3] == 0x01) {
out << ${PREVIEW_LITTLE_ENDIAN} << std::endl;
} else {
out << ${PREVIEW_OTHER_ENDIAN} << std::endl;
}
}")

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(
runres compileres ${CMAKE_BINARY_DIR}
SOURCES ${CMAKE_BINARY_DIR}/CheckEndian.cpp
ARGS ${CMAKE_BINARY_DIR}/endian.txt
)

file(READ ${CMAKE_BINARY_DIR}/endian.txt PREVIEW_ENDIAN)

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()
26 changes: 26 additions & 0 deletions include/preview/__bit/endian.h
Original file line number Diff line number Diff line change
@@ -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 <bit>

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
1 change: 1 addition & 0 deletions include/preview/bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@

#include "preview/__bit/bit_cast.h"
#include "preview/__bit/byteswap.h"
#include "preview/__bit/endian.h"

#endif // PREVIEW_BIT_H_
23 changes: 23 additions & 0 deletions test/bit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::int64_t>(qword_same), qword_same);
}

#if PREVIEW_CXX >= 17
#define IF_CONSTEXPR if constexpr
#else
#define IF_CONSTEXPR if
#endif

TEST(VERSIONED(bit), little_endian) {
const std::uint32_t n{ 0x01'23'45'67 };
const std::uint8_t* const ptr{ reinterpret_cast<const std::uint8_t*>(&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);
}
}

0 comments on commit 6e242e7

Please sign in to comment.