common: move numeric_cast to dedicated common/numeric_cast.hh
This commit is contained in:
parent
10581327b3
commit
26dedb603f
|
|
@ -24,6 +24,7 @@
|
|||
#include <common/imglib.hh>
|
||||
#include <common/log.hh>
|
||||
#include <common/settings.hh>
|
||||
#include <common/numeric_cast.hh>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits.h>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <common/bspfile.hh>
|
||||
#include <common/cmdlib.hh>
|
||||
#include <common/numeric_cast.hh>
|
||||
|
||||
// dheader_t
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <common/bspfile.hh>
|
||||
#include <common/cmdlib.hh>
|
||||
#include <common/numeric_cast.hh>
|
||||
|
||||
// q2_dheader_t
|
||||
|
||||
|
|
|
|||
|
|
@ -47,48 +47,6 @@ struct lump_t
|
|||
void stream_read(std::istream &s);
|
||||
};
|
||||
|
||||
// helper functions to quickly numerically cast mins/maxs
|
||||
// and floor/ceil them in the case of float -> integral
|
||||
template<typename T, typename F>
|
||||
inline qvec<T, 3> aabb_mins_cast(const qvec<F, 3> &f, const char *overflow_message = "mins")
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<F> && !std::is_floating_point_v<T>)
|
||||
return {numeric_cast<T>(floor(f[0]), overflow_message), numeric_cast<T>(floor(f[1]), overflow_message),
|
||||
numeric_cast<T>(floor(f[2]), overflow_message)};
|
||||
else
|
||||
return {numeric_cast<T>(f[0], overflow_message), numeric_cast<T>(f[1], overflow_message),
|
||||
numeric_cast<T>(f[2], overflow_message)};
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
inline qvec<T, 3> aabb_maxs_cast(const qvec<F, 3> &f, const char *overflow_message = "maxs")
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<F> && !std::is_floating_point_v<T>)
|
||||
return {numeric_cast<T>(ceil(f[0]), overflow_message), numeric_cast<T>(ceil(f[1]), overflow_message),
|
||||
numeric_cast<T>(ceil(f[2]), overflow_message)};
|
||||
else
|
||||
return {numeric_cast<T>(f[0], overflow_message), numeric_cast<T>(f[1], overflow_message),
|
||||
numeric_cast<T>(f[2], overflow_message)};
|
||||
}
|
||||
|
||||
// shortcut template to trim (& convert) std::arrays
|
||||
// between two lengths
|
||||
template<typename ADest, typename ASrc>
|
||||
constexpr ADest array_cast(const ASrc &src, const char *overflow_message = "src")
|
||||
{
|
||||
ADest dest{};
|
||||
|
||||
for (size_t i = 0; i < std::min(dest.size(), src.size()); i++) {
|
||||
if constexpr (std::is_arithmetic_v<typename ADest::value_type> &&
|
||||
std::is_arithmetic_v<typename ASrc::value_type>)
|
||||
dest[i] = numeric_cast<typename ADest::value_type>(src[i], overflow_message);
|
||||
else
|
||||
dest[i] = static_cast<typename ADest::value_type>(src[i]);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
struct gamedef_t;
|
||||
|
||||
struct contentflags_t
|
||||
|
|
|
|||
|
|
@ -490,73 +490,6 @@ inline std::enable_if_t<std::is_enum_v<T>, std::istream &> operator>=(std::istre
|
|||
return s;
|
||||
}
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
constexpr bool numeric_cast_will_overflow(const Src &value)
|
||||
{
|
||||
using DstLim = std::numeric_limits<Dst>;
|
||||
using SrcLim = std::numeric_limits<Src>;
|
||||
|
||||
constexpr bool positive_overflow_possible = DstLim::max() < SrcLim::max();
|
||||
constexpr bool negative_overflow_possible = SrcLim::is_signed || (DstLim::lowest() > SrcLim::lowest());
|
||||
|
||||
// unsigned <-- unsigned
|
||||
if constexpr ((!DstLim::is_signed) && (!SrcLim::is_signed)) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// unsigned <-- signed
|
||||
else if constexpr ((!DstLim::is_signed) && SrcLim::is_signed) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (negative_overflow_possible) {
|
||||
if (value < 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// signed <-- unsigned
|
||||
else if constexpr (DstLim::is_signed && (!SrcLim::is_signed)) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// signed <-- signed
|
||||
else if constexpr (DstLim::is_signed && SrcLim::is_signed) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (negative_overflow_possible) {
|
||||
if (value < DstLim::lowest()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
constexpr Dst numeric_cast(const Src &value, const char *overflow_message = "value")
|
||||
{
|
||||
if (numeric_cast_will_overflow<Dst, Src>(value)) {
|
||||
throw std::overflow_error(overflow_message);
|
||||
}
|
||||
|
||||
return static_cast<Dst>(value);
|
||||
}
|
||||
|
||||
// Memory streams, because C++ doesn't supply these.
|
||||
struct membuf : std::streambuf
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
/* Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
See file, 'COPYING', for details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
constexpr bool numeric_cast_will_overflow(const Src &value)
|
||||
{
|
||||
using DstLim = std::numeric_limits<Dst>;
|
||||
using SrcLim = std::numeric_limits<Src>;
|
||||
|
||||
constexpr bool positive_overflow_possible = DstLim::max() < SrcLim::max();
|
||||
constexpr bool negative_overflow_possible = SrcLim::is_signed || (DstLim::lowest() > SrcLim::lowest());
|
||||
|
||||
// unsigned <-- unsigned
|
||||
if constexpr ((!DstLim::is_signed) && (!SrcLim::is_signed)) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// unsigned <-- signed
|
||||
else if constexpr ((!DstLim::is_signed) && SrcLim::is_signed) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (negative_overflow_possible) {
|
||||
if (value < 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// signed <-- unsigned
|
||||
else if constexpr (DstLim::is_signed && (!SrcLim::is_signed)) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// signed <-- signed
|
||||
else if constexpr (DstLim::is_signed && SrcLim::is_signed) {
|
||||
if constexpr (positive_overflow_possible) {
|
||||
if (value > DstLim::max()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (negative_overflow_possible) {
|
||||
if (value < DstLim::lowest()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
constexpr Dst numeric_cast(const Src &value, const char *overflow_message = "value")
|
||||
{
|
||||
if (numeric_cast_will_overflow<Dst, Src>(value)) {
|
||||
throw std::overflow_error(overflow_message);
|
||||
}
|
||||
|
||||
return static_cast<Dst>(value);
|
||||
}
|
||||
|
||||
// helper functions to quickly numerically cast mins/maxs
|
||||
// and floor/ceil them in the case of float -> integral
|
||||
template<typename T, typename F>
|
||||
inline qvec<T, 3> aabb_mins_cast(const qvec<F, 3> &f, const char *overflow_message = "mins")
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<F> && !std::is_floating_point_v<T>)
|
||||
return {numeric_cast<T>(floor(f[0]), overflow_message), numeric_cast<T>(floor(f[1]), overflow_message),
|
||||
numeric_cast<T>(floor(f[2]), overflow_message)};
|
||||
else
|
||||
return {numeric_cast<T>(f[0], overflow_message), numeric_cast<T>(f[1], overflow_message),
|
||||
numeric_cast<T>(f[2], overflow_message)};
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
inline qvec<T, 3> aabb_maxs_cast(const qvec<F, 3> &f, const char *overflow_message = "maxs")
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<F> && !std::is_floating_point_v<T>)
|
||||
return {numeric_cast<T>(ceil(f[0]), overflow_message), numeric_cast<T>(ceil(f[1]), overflow_message),
|
||||
numeric_cast<T>(ceil(f[2]), overflow_message)};
|
||||
else
|
||||
return {numeric_cast<T>(f[0], overflow_message), numeric_cast<T>(f[1], overflow_message),
|
||||
numeric_cast<T>(f[2], overflow_message)};
|
||||
}
|
||||
|
||||
// shortcut template to trim (& convert) std::arrays
|
||||
// between two lengths
|
||||
template<typename ADest, typename ASrc>
|
||||
constexpr ADest array_cast(const ASrc &src, const char *overflow_message = "src")
|
||||
{
|
||||
ADest dest{};
|
||||
|
||||
for (size_t i = 0; i < std::min(dest.size(), src.size()); i++) {
|
||||
if constexpr (std::is_arithmetic_v<typename ADest::value_type> &&
|
||||
std::is_arithmetic_v<typename ASrc::value_type>)
|
||||
dest[i] = numeric_cast<typename ADest::value_type>(src[i], overflow_message);
|
||||
else
|
||||
dest[i] = static_cast<typename ADest::value_type>(src[i]);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <common/log.hh>
|
||||
#include <common/bsputils.hh>
|
||||
#include <common/numeric_cast.hh>
|
||||
#include <common/fs.hh>
|
||||
#include <common/imglib.hh>
|
||||
#include <common/parallel.hh>
|
||||
|
|
|
|||
Loading…
Reference in New Issue