From 914762513d9e70f4fe8a569dfb4316b29cd567b6 Mon Sep 17 00:00:00 2001 From: hendricks266 Date: Mon, 5 Jun 2017 10:05:07 +0000 Subject: [PATCH] Introducing buildprint, a type-safe and more performant replacement for printf using C++11 variadic templates. At least, an incomplete version that is enough to implement the next commit. git-svn-id: https://svn.eduke32.com/eduke32@6139 1a8010ca-5511-0410-912e-c29ae57300e0 --- source/build/include/baselayer.h | 2 + source/build/include/print.h | 194 +++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 source/build/include/print.h diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index e14cd7b25..1429fb9ad 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -249,5 +249,7 @@ void maybe_redirect_outputs(void); } #endif +#include "print.h" + #endif // baselayer_h_ diff --git a/source/build/include/print.h b/source/build/include/print.h new file mode 100644 index 000000000..089ea887b --- /dev/null +++ b/source/build/include/print.h @@ -0,0 +1,194 @@ + +#pragma once + +#ifndef print_h_ +#define print_h_ + +#if CXXSTD >= 2011 + +template +struct binwrap +{ + T data; +}; +template +static FORCE_INLINE constexpr binwrap bin(T x) +{ + return binwrap{x}; +} +template +struct octwrap +{ + T data; +}; +template +static FORCE_INLINE constexpr octwrap oct(T x) +{ + return octwrap{x}; +} +template +struct hexwrap +{ + T data; +}; +template +static FORCE_INLINE constexpr hexwrap hex(T x) +{ + return hexwrap{x}; +} +template +struct HEXwrap +{ + T data; +}; +template +static FORCE_INLINE constexpr HEXwrap HEX(T x) +{ + return HEXwrap{x}; +} + +FORCE_INLINE constexpr size_t buildprintpiece(void) +{ + return 0; +} + +template +enable_if_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 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 const qr = divrhs<10>(x); + x = qr.q; + strptr[numChars-1] = '0' + (char)qr.r; + } + while (--numChars); + } + + initputs(str); + return totalChars; +} + +template +enable_if_t::value, size_t> buildprintpiece(binwrap x) +{ + make_unsigned_t const data = x.data; + + size_t constexpr numChars = sizeof(x)*CHAR_BIT; + char str[numChars+1]; + str[numChars] = '\0'; + + for (size_t p = 0; p < numChars; ++p) + str[numChars - 1 - p] = '0' + (char)((data >> p) & 1); + + initputs(str); + return numChars; +} + +template +enable_if_t::value, size_t> buildprintpiece(octwrap x) +{ + make_unsigned_t const data = x.data; + + size_t constexpr numChars = (sizeof(x)*CHAR_BIT + 2) / 3; + char str[numChars+1]; + str[numChars] = '\0'; + + for (size_t p = 0; p < numChars; ++p) + str[numChars - 1 - p] = '0' + (char)((data >> (p*3)) & 7); + + initputs(str); + return numChars; +} + +template +enable_if_t::value, size_t> buildprintpiece(hexwrap x) +{ + static char const hexletters[] = "0123456789abcdef"; + + make_unsigned_t const data = x.data; + + size_t constexpr numChars = (sizeof(x)*CHAR_BIT + 3) / 4; + char str[numChars+1]; + str[numChars] = '\0'; + + for (size_t p = 0; p < numChars; ++p) + str[numChars - 1 - p] = hexletters[(size_t)((data >> (p*4)) & 0xF)]; + + initputs(str); + return numChars; +} + +template +enable_if_t::value, size_t> buildprintpiece(HEXwrap x) +{ + static char const HEXletters[] = "0123456789ABCDEF"; + + make_unsigned_t const data = x.data; + + size_t constexpr numChars = (sizeof(x)*CHAR_BIT + 3) / 4; + char str[numChars+1]; + str[numChars] = '\0'; + + for (size_t p = 0; p < numChars; ++p) + str[numChars - 1 - p] = HEXletters[(size_t)((data >> (p*4)) & 0xF)]; + + initputs(str); + return numChars; +} + +template +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 +static FORCE_INLINE size_t buildprint(T first) +{ + return buildprintpiece(first); +} + +template +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_