mirror of
https://github.com/ZDoom/Raze.git
synced 2024-12-15 07:01:15 +00:00
b0a4b6a1ee
https://kristerw.blogspot.com/2016/02/how-undefined-signed-overflow-enables.html Doing this as cleanly as possible involved demoting several function parameters concerning object sizes and counts from size_t to int--I'm fine with this change as the functions in question are not actually capable of handling input with sizes larger than what can be stored in a signed 32-bit integer, making the use of size_t here misleading at best. git-svn-id: https://svn.eduke32.com/eduke32@7673 1a8010ca-5511-0410-912e-c29ae57300e0 # Conflicts: # source/build/src/polymost.cpp # source/build/src/texcache.cpp # source/build/src/tilepacker.cpp
194 lines
4.1 KiB
C++
194 lines
4.1 KiB
C++
|
|
#pragma once
|
|
|
|
#ifndef print_h_
|
|
#define print_h_
|
|
|
|
#ifdef HAVE_CXX11_HEADERS
|
|
|
|
template <typename T>
|
|
struct binwrap
|
|
{
|
|
T data;
|
|
};
|
|
template <typename T>
|
|
static FORCE_INLINE constexpr binwrap<T> bin(T x)
|
|
{
|
|
return binwrap<T>{x};
|
|
}
|
|
template <typename T>
|
|
struct octwrap
|
|
{
|
|
T data;
|
|
};
|
|
template <typename T>
|
|
static FORCE_INLINE constexpr octwrap<T> oct(T x)
|
|
{
|
|
return octwrap<T>{x};
|
|
}
|
|
template <typename T>
|
|
struct hexwrap
|
|
{
|
|
T data;
|
|
};
|
|
template <typename T>
|
|
static FORCE_INLINE constexpr hexwrap<T> hex(T x)
|
|
{
|
|
return hexwrap<T>{x};
|
|
}
|
|
template <typename T>
|
|
struct HEXwrap
|
|
{
|
|
T data;
|
|
};
|
|
template <typename T>
|
|
static FORCE_INLINE constexpr HEXwrap<T> HEX(T x)
|
|
{
|
|
return HEXwrap<T>{x};
|
|
}
|
|
|
|
FORCE_INLINE constexpr size_t buildprintpiece(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
template<typename T>
|
|
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(T x)
|
|
{
|
|
// log_10(2^x) = x * log(2)/log(10) ~= x * 0.30103
|
|
size_t constexpr numdigits = (sizeof(T) * CHAR_BIT + 1) / 3;
|
|
char str[numdigits + 2]; // +2 for '-', '\0'
|
|
|
|
char * strptr = str;
|
|
|
|
size_t totalChars;
|
|
if (x < 0)
|
|
{
|
|
size_t numChars = logbasenegative<10>(x);
|
|
totalChars = numChars+1;
|
|
*strptr++ = '-';
|
|
strptr[numChars] = '\0';
|
|
do
|
|
{
|
|
DivResult<T> const qr = divrhs<10>(x);
|
|
x = qr.q;
|
|
strptr[numChars-1] = '0' - (char)qr.r;
|
|
}
|
|
while (--numChars);
|
|
}
|
|
else
|
|
{
|
|
size_t numChars = logbase<10>(x);
|
|
totalChars = numChars;
|
|
strptr[numChars] = '\0';
|
|
do
|
|
{
|
|
DivResult<T> const qr = divrhs<10>(x);
|
|
x = qr.q;
|
|
strptr[numChars-1] = '0' + (char)qr.r;
|
|
}
|
|
while (--numChars);
|
|
}
|
|
|
|
initputs(str);
|
|
return totalChars;
|
|
}
|
|
|
|
template<typename T>
|
|
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(binwrap<T> x)
|
|
{
|
|
make_unsigned_t<T> const data = x.data;
|
|
|
|
int constexpr numChars = sizeof(x)*CHAR_BIT;
|
|
char str[numChars+1];
|
|
str[numChars] = '\0';
|
|
|
|
for (int p = 0; p < numChars; ++p)
|
|
str[numChars - 1 - p] = '0' + (char)((data >> p) & 1);
|
|
|
|
initputs(str);
|
|
return numChars;
|
|
}
|
|
|
|
template<typename T>
|
|
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(octwrap<T> x)
|
|
{
|
|
make_unsigned_t<T> const data = x.data;
|
|
|
|
int constexpr numChars = (sizeof(x)*CHAR_BIT + 2) / 3;
|
|
char str[numChars+1];
|
|
str[numChars] = '\0';
|
|
|
|
for (int p = 0; p < numChars; ++p)
|
|
str[numChars - 1 - p] = '0' + (char)((data >> (p*3)) & 7);
|
|
|
|
initputs(str);
|
|
return numChars;
|
|
}
|
|
|
|
template<typename T>
|
|
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(hexwrap<T> x)
|
|
{
|
|
static char const hexletters[] = "0123456789abcdef";
|
|
|
|
make_unsigned_t<T> const data = x.data;
|
|
|
|
int constexpr numChars = (sizeof(x)*CHAR_BIT + 3) >> 2;
|
|
char str[numChars+1];
|
|
str[numChars] = '\0';
|
|
|
|
for (int p = 0; p < numChars; ++p)
|
|
str[numChars - 1 - p] = hexletters[(int)((data >> (p<<2)) & 0xF)];
|
|
|
|
initputs(str);
|
|
return numChars;
|
|
}
|
|
|
|
template<typename T>
|
|
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(HEXwrap<T> x)
|
|
{
|
|
static char const HEXletters[] = "0123456789ABCDEF";
|
|
|
|
make_unsigned_t<T> const data = x.data;
|
|
|
|
int constexpr numChars = (sizeof(x)*CHAR_BIT + 3) >> 2;
|
|
char str[numChars+1];
|
|
str[numChars] = '\0';
|
|
|
|
for (int p = 0; p < numChars; ++p)
|
|
str[numChars - 1 - p] = HEXletters[(int)((data >> (p<<2)) & 0xF)];
|
|
|
|
initputs(str);
|
|
return numChars;
|
|
}
|
|
|
|
template <typename T>
|
|
FORCE_INLINE size_t buildprintpiece(const T * x)
|
|
{
|
|
return buildprintpiece(hex((uintptr_t)x));
|
|
}
|
|
|
|
FORCE_INLINE size_t buildprintpiece(char const *str)
|
|
{
|
|
initputs(str);
|
|
return strlen(str);
|
|
}
|
|
|
|
template<typename T>
|
|
static FORCE_INLINE size_t buildprint(T first)
|
|
{
|
|
return buildprintpiece(first);
|
|
}
|
|
|
|
template<typename T, typename... Args>
|
|
size_t buildprint(T first, Args... args)
|
|
{
|
|
size_t const len = buildprintpiece(first);
|
|
return len + buildprint(args...);
|
|
}
|
|
|
|
// this file is incomplete. a fuller implementation exists but has not been completed and debugged.
|
|
|
|
#endif
|
|
|
|
#endif // print_h_
|