From 59d71b242341a0f2bb56c19709d634a995ecd675 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 5 Feb 2023 11:32:14 +0000 Subject: [PATCH] introducing binary safe type cast utility. --- Sources/Core/Math.h | 16 ++++++++++++++++ Sources/Core/OpusAudioStream.cpp | 8 ++++---- Sources/Core/SdlFileStream.cpp | 5 +++-- Sources/Draw/SWImageRenderer.cpp | 4 ++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Sources/Core/Math.h b/Sources/Core/Math.h index da968ebb7..1b1eb7e8a 100644 --- a/Sources/Core/Math.h +++ b/Sources/Core/Math.h @@ -23,10 +23,12 @@ #include // std::max / std::min #include // uint32_t --> msvc #include +#include #include #include #include #include +#include #include namespace spades { @@ -973,6 +975,20 @@ namespace spades { std::string TrimSpaces(const std::string &); float SmoothStep(float); + + /* + * binary safe cast, unlike traditional c++ cast operators, it needs to operate on a matching type size + * + * if the code updates to c++ 20 it can be dropped + */ + template using EnableIf = typename std::enable_if::type; + template + EnableIf::value && std::is_trivially_copyable::value, dest> + SafeCast(const src& s) { + dest d; + std::memcpy(&d, &s, sizeof(dest)); + return d; + } } namespace std { diff --git a/Sources/Core/OpusAudioStream.cpp b/Sources/Core/OpusAudioStream.cpp index 751d1fc37..517660be4 100644 --- a/Sources/Core/OpusAudioStream.cpp +++ b/Sources/Core/OpusAudioStream.cpp @@ -69,19 +69,19 @@ namespace spades { switch (whence) { case SEEK_CUR: self.stream->SetPosition( - static_cast(offset + self.stream->GetPosition())); + SafeCast(offset + self.stream->GetPosition())); break; case SEEK_SET: self.stream->SetPosition(static_cast(offset)); break; case SEEK_END: self.stream->SetPosition( - static_cast(offset + self.stream->GetLength())); + SafeCast(offset + self.stream->GetLength())); break; } return 0; }; opusCallback->tell = [](void *stream) -> opus_int64 { auto &self = *reinterpret_cast(stream); - return static_cast(self.stream->GetPosition()); + return SafeCast(self.stream->GetPosition()); }; opusCallback->close = nullptr; @@ -220,7 +220,7 @@ namespace spades { void OpusAudioStream::SetPosition(uint64_t pos) { pos = std::min(pos, GetLength()); - op_pcm_seek(opusFile, static_cast(pos / (channels * 4))); + op_pcm_seek(opusFile, SafeCast(pos / (channels * 4))); subsamplePosition = static_cast(pos % (channels * 4)); if (subsamplePosition) { diff --git a/Sources/Core/SdlFileStream.cpp b/Sources/Core/SdlFileStream.cpp index 21cab1f6f..26b329034 100644 --- a/Sources/Core/SdlFileStream.cpp +++ b/Sources/Core/SdlFileStream.cpp @@ -21,6 +21,7 @@ #include "SdlFileStream.h" #include "Debug.h" #include "Exception.h" +#include "Math.h" namespace spades { SdlFileStream::SdlFileStream(SDL_RWops *f, bool ac) : ops(f), autoClose(ac) { @@ -76,7 +77,7 @@ namespace spades { if (pos == -1) { SPRaise("This stream doesn't support seeking."); } - return static_cast(pos); + return SafeCast(pos); } void SdlFileStream::SetPosition(uint64_t pos) { @@ -86,7 +87,7 @@ namespace spades { SPRaise("Currently SdlFileStream doesn't support 64-bit offset."); } - if (SDL_RWseek(ops, static_cast(pos), RW_SEEK_SET) == -1) { + if (SDL_RWseek(ops, SafeCast(pos), RW_SEEK_SET) == -1) { SPRaise("This stream doesn't support seeking."); } } diff --git a/Sources/Draw/SWImageRenderer.cpp b/Sources/Draw/SWImageRenderer.cpp index d46e45d0d..702f2290e 100644 --- a/Sources/Draw/SWImageRenderer.cpp +++ b/Sources/Draw/SWImageRenderer.cpp @@ -78,10 +78,10 @@ namespace spades { } if (numSteps == 0) numSteps = 1; - b.divisor = static_cast(numSteps); + b.divisor = SafeCast(numSteps); b.dividend = 0; b.largePos = start; - b.step = static_cast(distance); + b.step = SafeCast(distance); } else { mode = 0; if (numSteps == 0) {