瀏覽代碼

Added bx::narrowCast.

Бранимир Караџић 1 年之前
父節點
當前提交
3072cf37df
共有 5 個文件被更改,包括 131 次插入101 次删除
  1. 8 3
      include/bx/bx.h
  2. 2 1
      include/bx/debug.h
  3. 20 4
      include/bx/inline/bx.inl
  4. 0 93
      tests/bitcast_test.cpp
  5. 101 0
      tests/cast_test.cpp

+ 8 - 3
include/bx/bx.h

@@ -8,9 +8,9 @@
 
 
 #include <alloca.h> // alloca
 #include <alloca.h> // alloca
 #include <stdarg.h> // va_list
 #include <stdarg.h> // va_list
+#include <stddef.h> // ptrdiff_t
 #include <stdint.h> // uint32_t
 #include <stdint.h> // uint32_t
 #include <stdlib.h> // size_t
 #include <stdlib.h> // size_t
-#include <stddef.h> // ptrdiff_t
 
 
 #include "platform.h"
 #include "platform.h"
 #include "config.h"
 #include "config.h"
@@ -214,9 +214,14 @@ namespace bx
 	template<typename Ty>
 	template<typename Ty>
 	constexpr bool isPowerOf2(Ty _a);
 	constexpr bool isPowerOf2(Ty _a);
 
 
-	/// Returns a value of type To by reinterpreting the object representation of From.
+	/// Returns a value of type `Ty` by reinterpreting the object representation of `FromT`.
 	template <typename Ty, typename FromT>
 	template <typename Ty, typename FromT>
-	constexpr Ty bit_cast(const FromT& _from);
+	constexpr Ty bitCast(const FromT& _from);
+
+	/// Performs `static_cast` of value `_from`, and in debug build runtime verifies/asserts
+	/// that the value didn't change.
+	template<typename Ty, typename FromT>
+	constexpr Ty narrowCast(const FromT& _from, Location _location = Location::current() );
 
 
 	/// Copy memory block.
 	/// Copy memory block.
 	///
 	///

+ 2 - 1
include/bx/debug.h

@@ -6,7 +6,8 @@
 #ifndef BX_DEBUG_H_HEADER_GUARD
 #ifndef BX_DEBUG_H_HEADER_GUARD
 #define BX_DEBUG_H_HEADER_GUARD
 #define BX_DEBUG_H_HEADER_GUARD
 
 
-#include "bx.h"
+#include <stdint.h> // uint32_t
+#include <stdarg.h> // va_list
 
 
 namespace bx
 namespace bx
 {
 {

+ 20 - 4
include/bx/inline/bx.inl

@@ -148,12 +148,28 @@ namespace bx
 	}
 	}
 
 
 	template <typename Ty, typename FromT>
 	template <typename Ty, typename FromT>
-	inline constexpr Ty bit_cast(const FromT& _from)
+	inline constexpr Ty bitCast(const FromT& _from)
 	{
 	{
-		static_assert(sizeof(Ty) == sizeof(FromT), "Ty and FromT must be the same size.");
-		static_assert(isTriviallyConstructible<Ty>(), "Destination target must be trivially constructible.");
+		static_assert(sizeof(Ty) == sizeof(FromT)
+			, "bx::bitCast failed! Ty and FromT must be the same size."
+			);
+		static_assert(isTriviallyConstructible<Ty>()
+			, "bx::bitCast failed! Destination target must be trivially constructible."
+			);
+
 		Ty to;
 		Ty to;
-		bx::memCopy(&to, &_from, sizeof(Ty) );
+		memCopy(&to, &_from, sizeof(Ty) );
+
+		return to;
+	}
+
+	template<typename Ty, typename FromT>
+	inline constexpr Ty narrowCast(const FromT& _from, Location _location)
+	{
+		Ty to = static_cast<Ty>(_from);
+		BX_ASSERT_LOC(_location, static_cast<FromT>(to) == _from
+			, "bx::narrowCast failed! Value is truncated!"
+			);
 		return to;
 		return to;
 	}
 	}
 
 

+ 0 - 93
tests/bitcast_test.cpp

@@ -1,93 +0,0 @@
-/*
- * Copyright 2010-2024 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
- */
-
-#include "test.h"
-#include <bx/bx.h>
-#include <string.h>
-
-namespace bx
-{
-	extern void memCopyRef(void* _dst, const void* _src, size_t _numBytes);
-}
-
-TEST_CASE("Bit cast round trip test using double to uint64_t")
-{
-	constexpr double d64v = 19880124.0;
-	REQUIRE(sizeof(double) == sizeof(uint64_t));
-
-	SECTION("bx::bit_cast")
-	{
-		const uint64_t u64v = bx::bit_cast<uint64_t>(d64v);
-		const double result = bx::bit_cast<double>(u64v);
-		REQUIRE(result == d64v);
-	}
-
-	SECTION("bx::memCopy")
-	{
-		uint64_t u64v = 0;
-		double result = 0;
-		bx::memCopy(&u64v, &d64v, sizeof(uint64_t));
-		bx::memCopy(&result, &u64v, sizeof(double));
-		REQUIRE(result == d64v);
-	}
-
-	SECTION("bx::memCopyRef")
-	{
-		uint64_t u64v = 0;
-		double result = 0;
-		bx::memCopyRef(&u64v, &d64v, sizeof(uint64_t));
-		bx::memCopyRef(&result, &u64v, sizeof(double));
-		REQUIRE(result == d64v);
-	}
-
-	SECTION("::memcpy")
-	{
-		uint64_t u64v = 0;
-		double result = 0;
-		::memcpy(&u64v, &d64v, sizeof(uint64_t));
-		::memcpy(&result, &u64v, sizeof(double));
-		REQUIRE(result == d64v);
-	}
-}
-
-TEST_CASE("Bit cast round trip test using uint64_t to double")
-{
-	constexpr uint64_t u64v = 0x3fe9000000000000ull;
-	REQUIRE(sizeof(uint64_t) == sizeof(double));
-
-	SECTION("bx::bit_cast")
-	{
-		const double d64v = bx::bit_cast<double>(u64v);
-		const uint64_t result = bx::bit_cast<uint64_t>(d64v);
-		REQUIRE(result == u64v);
-	}
-
-	SECTION("bx::memCopy")
-	{
-		double d64v = 0;
-		uint64_t result = 0;
-		bx::memCopy(&d64v, &u64v, sizeof(double));
-		bx::memCopy(&result, &d64v, sizeof(uint64_t));
-		REQUIRE(result == u64v);
-	}
-
-	SECTION("bx::memCopyRef")
-	{
-		double d64v = 0;
-		uint64_t result = 0;
-		bx::memCopyRef(&d64v, &u64v, sizeof(double));
-		bx::memCopyRef(&result, &d64v, sizeof(uint64_t));
-		REQUIRE(result == u64v);
-	}
-
-	SECTION("::memcpy")
-	{
-		double d64v = 0;
-		uint64_t result = 0;
-		::memcpy(&d64v, &u64v, sizeof(double));
-		::memcpy(&result, &d64v, sizeof(uint64_t));
-		REQUIRE(result == u64v);
-	}
-}

+ 101 - 0
tests/cast_test.cpp

@@ -0,0 +1,101 @@
+/*
+ * Copyright 2010-2024 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
+ */
+
+#include "test.h"
+#include <bx/bx.h>
+#include <string.h>
+
+namespace bx
+{
+	extern void memCopyRef(void* _dst, const void* _src, size_t _numBytes);
+}
+
+TEST_CASE("Bit cast round trip test using double to uint64_t", "[cast]")
+{
+	constexpr double d64v = 19880124.0;
+	REQUIRE(sizeof(double) == sizeof(uint64_t) );
+
+	SECTION("bx::bitCast")
+	{
+		const uint64_t u64v = bx::bitCast<uint64_t>(d64v);
+		const double result = bx::bitCast<double>(u64v);
+		REQUIRE(result == d64v);
+	}
+
+	SECTION("bx::memCopy")
+	{
+		uint64_t u64v = 0;
+		double result = 0;
+		bx::memCopy(&u64v, &d64v, sizeof(uint64_t) );
+		bx::memCopy(&result, &u64v, sizeof(double) );
+		REQUIRE(result == d64v);
+	}
+
+	SECTION("bx::memCopyRef")
+	{
+		uint64_t u64v = 0;
+		double result = 0;
+		bx::memCopyRef(&u64v, &d64v, sizeof(uint64_t) );
+		bx::memCopyRef(&result, &u64v, sizeof(double) );
+		REQUIRE(result == d64v);
+	}
+
+	SECTION("::memcpy")
+	{
+		uint64_t u64v = 0;
+		double result = 0;
+		::memcpy(&u64v, &d64v, sizeof(uint64_t) );
+		::memcpy(&result, &u64v, sizeof(double) );
+		REQUIRE(result == d64v);
+	}
+}
+
+TEST_CASE("Bit cast round trip test using uint64_t to double", "[cast]")
+{
+	constexpr uint64_t u64v = 0x3fe9000000000000ull;
+	REQUIRE(sizeof(uint64_t) == sizeof(double) );
+
+	SECTION("bx::bitCast")
+	{
+		const double d64v = bx::bitCast<double>(u64v);
+		const uint64_t result = bx::bitCast<uint64_t>(d64v);
+		REQUIRE(result == u64v);
+	}
+
+	SECTION("bx::memCopy")
+	{
+		double d64v = 0;
+		uint64_t result = 0;
+		bx::memCopy(&d64v, &u64v, sizeof(double) );
+		bx::memCopy(&result, &d64v, sizeof(uint64_t) );
+		REQUIRE(result == u64v);
+	}
+
+	SECTION("bx::memCopyRef")
+	{
+		double d64v = 0;
+		uint64_t result = 0;
+		bx::memCopyRef(&d64v, &u64v, sizeof(double) );
+		bx::memCopyRef(&result, &d64v, sizeof(uint64_t) );
+		REQUIRE(result == u64v);
+	}
+
+	SECTION("::memcpy")
+	{
+		double d64v = 0;
+		uint64_t result = 0;
+		::memcpy(&d64v, &u64v, sizeof(double) );
+		::memcpy(&result, &d64v, sizeof(uint64_t) );
+		REQUIRE(result == u64v);
+	}
+}
+
+TEST_CASE("Narrow cast", "[cast]")
+{
+	REQUIRE(127 == bx::narrowCast<int8_t>(int32_t(127) ) );
+	REQUIRE_ASSERTS(bx::narrowCast<int8_t>(int32_t(128) ) );
+	REQUIRE_ASSERTS(bx::narrowCast<int8_t>(uint32_t(128) ) );
+	REQUIRE(128 == bx::narrowCast<uint8_t>(int32_t(128) ) );
+}