mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			69 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef _C4_SZCONV_HPP_
 | |
| #define _C4_SZCONV_HPP_
 | |
| 
 | |
| /** @file szconv.hpp utilities to deal safely with narrowing conversions */
 | |
| 
 | |
| #include "c4/config.hpp"
 | |
| #include "c4/error.hpp"
 | |
| 
 | |
| #include <limits>
 | |
| 
 | |
| namespace c4 {
 | |
| 
 | |
| C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
 | |
| 
 | |
| /** @todo this would be so much easier with calls to numeric_limits::max()... */
 | |
| template<class SizeOut, class SizeIn>
 | |
| struct is_narrower_size : std::conditional
 | |
| <
 | |
|    (std::is_signed<SizeOut>::value == std::is_signed<SizeIn>::value)
 | |
|    ?
 | |
|    (sizeof(SizeOut) < sizeof(SizeIn))
 | |
|    :
 | |
|    (
 | |
|        (sizeof(SizeOut) < sizeof(SizeIn))
 | |
|        ||
 | |
|        (
 | |
|            (sizeof(SizeOut) == sizeof(SizeIn))
 | |
|            &&
 | |
|            (std::is_signed<SizeOut>::value && std::is_unsigned<SizeIn>::value)
 | |
|        )
 | |
|    ),
 | |
|    std::true_type,
 | |
|    std::false_type
 | |
| >::type
 | |
| {
 | |
|     static_assert(std::is_integral<SizeIn >::value, "must be integral type");
 | |
|     static_assert(std::is_integral<SizeOut>::value, "must be integral type");
 | |
| };
 | |
| 
 | |
| 
 | |
| /** when SizeOut is wider than SizeIn, assignment can occur without reservations */
 | |
| template<class SizeOut, class SizeIn>
 | |
| C4_ALWAYS_INLINE
 | |
| typename std::enable_if< ! is_narrower_size<SizeOut, SizeIn>::value, SizeOut>::type
 | |
| szconv(SizeIn sz) noexcept
 | |
| {
 | |
|     return static_cast<SizeOut>(sz);
 | |
| }
 | |
| 
 | |
| /** when SizeOut is narrower than SizeIn, narrowing will occur, so we check
 | |
|  * for overflow. Note that this check is done only if C4_XASSERT is enabled.
 | |
|  * @see C4_XASSERT */
 | |
| template<class SizeOut, class SizeIn>
 | |
| C4_ALWAYS_INLINE
 | |
| typename std::enable_if<is_narrower_size<SizeOut, SizeIn>::value, SizeOut>::type
 | |
| szconv(SizeIn sz) C4_NOEXCEPT_X
 | |
| {
 | |
|     C4_XASSERT(sz >= 0);
 | |
|     C4_XASSERT_MSG((SizeIn)sz <= (SizeIn)std::numeric_limits<SizeOut>::max(), "size conversion overflow: in=%zu", (size_t)sz);
 | |
|     SizeOut szo = static_cast<SizeOut>(sz);
 | |
|     return szo;
 | |
| }
 | |
| 
 | |
| C4_SUPPRESS_WARNING_GCC_CLANG_POP
 | |
| 
 | |
| } // namespace c4
 | |
| 
 | |
| #endif /* _C4_SZCONV_HPP_ */
 | 
