From: Tsuda Kageyu Date: Fri, 31 Jul 2015 03:46:43 +0000 (+0900) Subject: Run-time check for floating point byte order rather than CMake check. X-Git-Tag: v1.10beta~17^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=44d9f2bf2583d0c692ab946afd9b4ea5dfb1cebf;p=taglib Run-time check for floating point byte order rather than CMake check. It's safer not to use an unofficial CMake script. --- diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 04f39548..fad3ad34 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -2,7 +2,6 @@ include(CheckLibraryExists) include(CheckTypeSize) include(CheckCXXSourceCompiles) include(TestBigEndian) -include(TestFloatFormat) # Check if the size of numeric types are suitable. @@ -46,17 +45,6 @@ else() set(SYSTEM_BYTEORDER 2) endif() -# Check if the format of floating point types are suitable. - -test_float_format(FP_IEEE754) -if(${FP_IEEE754} EQUAL 1) - set(FLOAT_BYTEORDER 1) -elseif(${FP_IEEE754} EQUAL 2) - set(FLOAT_BYTEORDER 2) -else() - message(FATAL_ERROR "TagLib requires that floating point types are IEEE754 compliant.") -endif() - # Determine which kind of atomic operations your compiler supports. check_cxx_source_compiles(" diff --git a/cmake/TestFloatFormat.c b/cmake/TestFloatFormat.c deleted file mode 100644 index 4a7b32e4..00000000 --- a/cmake/TestFloatFormat.c +++ /dev/null @@ -1,17 +0,0 @@ -int main(int argc, char **argv) -{ - int ret = 0; - - double bin1[] = { - // "*TAGLIB*" encoded as a little-endian floating-point number - (double)3.9865557444897601e-105, (double)0.0 - }; - float bin2[] = { - // "*TL*" encoded as a little-endian floating-point number - (float)1.81480400e-013, (float)0.0 - }; - ret += ((int*)bin1)[argc]; - ret += ((int*)bin2)[argc]; - - return ret; -} diff --git a/cmake/modules/TestFloatFormat.cmake b/cmake/modules/TestFloatFormat.cmake deleted file mode 100644 index ef9b1860..00000000 --- a/cmake/modules/TestFloatFormat.cmake +++ /dev/null @@ -1,61 +0,0 @@ -# Returns 1 if IEEE754 little-endian, 2 if IEEE754 big-endian, otherwise 0. - -MACRO(TEST_FLOAT_FORMAT FP_IEEE754) - IF(NOT FP_IEEE754) - TRY_COMPILE(HAVE_FLOAT_FORMAT_BIN - "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestFloatFormat.c" - COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin") - - SET(FP_IEEE754 0) - - IF(HAVE_FLOAT_FORMAT_BIN) - - # dont match first/last letter because of string rounding errors :-) - FILE(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin" - DOUBLE_IEEE754_LE LIMIT_COUNT 1 REGEX "TAGLIB") - FILE(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin" - DOUBLE_IEEE754_BE LIMIT_COUNT 1 REGEX "BILGAT") - FILE(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin" - FLOAT_IEEE754_LE LIMIT_COUNT 1 REGEX "TL") - FILE(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestFloatFormat.bin" - FLOAT_IEEE754_BE LIMIT_COUNT 1 REGEX "LT") - - IF(DOUBLE_IEEE754_LE AND FLOAT_IEEE754_LE) - SET(FP_IEEE754_LE 1) - ENDIF() - - IF(DOUBLE_IEEE754_BE AND FLOAT_IEEE754_BE) - SET(FP_IEEE754_BE 1) - ENDIF() - - # OS X Universal binaries will contain both strings, set it to the host - IF(FP_IEEE754_LE AND FP_IEEE754_BE) - IF(CMAKE_SYSTEM_PROCESSOR MATCHES powerpc) - SET(FP_IEEE754_LE FALSE) - SET(FP_IEEE754_BE TRUE) - ELSE() - SET(FP_IEEE754_LE TRUE) - SET(FP_IEEE754_BE FALSE) - ENDIF() - ENDIF() - - IF(FP_IEEE754_LE) - SET(FP_IEEE754 1) - ELSEIF(FP_IEEE754_BE) - SET(FP_IEEE754 2) - ENDIF() - ENDIF() - - # just some informational output for the user - IF(FP_IEEE754_LE) - MESSAGE(STATUS "Checking the floating point format - IEEE754 (LittleEndian)") - ELSEIF(FP_IEEE754_BE) - MESSAGE(STATUS "Checking the floating point format - IEEE754 (BigEndian)") - ELSE() - MESSAGE(STATUS "Checking the floating point format - Not IEEE754 or failed to detect.") - ENDIF() - - SET(FP_IEEE754 "${${FP_IEEE754}}" CACHE INTERNAL "Result of TEST_FLOAT_FORMAT" FORCE) - ENDIF() -ENDMACRO(TEST_FLOAT_FORMAT FP_IEEE754) - diff --git a/config.h.cmake b/config.h.cmake index 8fd8391d..2feded0f 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -4,10 +4,6 @@ /* 1 if little-endian, 2 if big-endian. */ #cmakedefine SYSTEM_BYTEORDER ${SYSTEM_BYTEORDER} -/* IEEE754 byte order of your target system. */ -/* 1 if little-endian, 2 if big-endian. */ -#cmakedefine FLOAT_BYTEORDER ${FLOAT_BYTEORDER} - /* Defined if your compiler supports some byte swap functions */ #cmakedefine HAVE_GCC_BYTESWAP_16 1 #cmakedefine HAVE_GCC_BYTESWAP_32 1 diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 45ad0317..ca1c30bc 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -251,7 +251,7 @@ TFloat toFloat(const ByteVector &v, size_t offset) } tmp; ::memcpy(&tmp, v.data() + offset, sizeof(TInt)); - if(ENDIAN != Utils::FloatByteOrder) + if(ENDIAN != Utils::floatByteOrder()) tmp.i = Utils::byteSwap(tmp.i); return tmp.f; @@ -266,7 +266,7 @@ ByteVector fromFloat(TFloat value) } tmp; tmp.f = value; - if(ENDIAN != Utils::FloatByteOrder) + if(ENDIAN != Utils::floatByteOrder()) tmp.i = Utils::byteSwap(tmp.i); return ByteVector(reinterpret_cast(&tmp), sizeof(TInt)); diff --git a/taglib/toolkit/tutils.h b/taglib/toolkit/tutils.h index a7ed6fde..a1ca76fb 100644 --- a/taglib/toolkit/tutils.h +++ b/taglib/toolkit/tutils.h @@ -248,37 +248,26 @@ namespace TagLib #endif -#ifdef FLOAT_BYTEORDER - -# if FLOAT_BYTEORDER == 1 - - const ByteOrder FloatByteOrder = LittleEndian; - -# else - - const ByteOrder FloatByteOrder = BigEndian; - -# endif - -#else - + /*! + * Returns the IEEE754 byte order of the system. + */ inline ByteOrder floatByteOrder() { - double bin[] = { - // "*TAGLIB*" encoded as a little-endian floating-point number - (double) 3.9865557444897601e-105, (double) 0.0 - }; - - char *str = (char*)&bin[0]; - if(strncmp(&str[1], "TAGLIB", 6) == 0) - return LittleEndian; - else - return BigEndian; - } + union { + double d; + char c; + } u; - const ByteOrder FloatByteOrder = floatByteOrder(); + // 1.0 is stored in memory like 0x3FF0000000000000 in canonical form. + // So the first byte is zero if little endian. + + u.d = 1.0; + if(u.c == 0) + return LittleEndian; + else + return BigEndian; + } -#endif } }