Browse Source

Test plFormat's decimal conversions, and fix several issues with signed

decimal formatting (especially with negative values)
Michael Hansen 10 years ago
parent
commit
76372424cd
  1. 31
      Sources/Plasma/CoreLib/plFormat.cpp
  2. 60
      Sources/Tests/CoreTests/test_plFormat.cpp

31
Sources/Plasma/CoreLib/plFormat.cpp

@ -45,6 +45,7 @@ Mead, WA 99021
#include "HeadSpin.h" #include "HeadSpin.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <type_traits>
#define BADCHAR_REPLACEMENT (0xFFFDul) #define BADCHAR_REPLACEMENT (0xFFFDul)
@ -226,7 +227,8 @@ static void _formatNumeric(const plFormat_Private::FormatSpec &format,
plStringStream &output, _IType value, plStringStream &output, _IType value,
int radix, bool upperCase = false) int radix, bool upperCase = false)
{ {
char pad = format.fPadChar ? format.fPadChar : ' '; static_assert(std::is_unsigned<_IType>::value,
"Signed numerics are currently only supported in Decimal formatting");
size_t format_size = 0; size_t format_size = 0;
_IType temp = value; _IType temp = value;
@ -250,8 +252,8 @@ template <typename _IType>
static void _formatDecimal(const plFormat_Private::FormatSpec &format, static void _formatDecimal(const plFormat_Private::FormatSpec &format,
plStringStream &output, _IType value) plStringStream &output, _IType value)
{ {
char pad = format.fPadChar ? format.fPadChar : ' '; typedef typename std::make_unsigned<_IType>::type _UType;
_IType abs = (value < 0) ? -value : value; _UType abs = (value < 0) ? -(_UType)value : value;
size_t format_size = 0; size_t format_size = 0;
_IType temp = abs; _IType temp = abs;
@ -266,18 +268,15 @@ static void _formatDecimal(const plFormat_Private::FormatSpec &format,
if (value < 0 || format.fDigitClass == plFormat_Private::kDigitDecAlwaysSigned) if (value < 0 || format.fDigitClass == plFormat_Private::kDigitDecAlwaysSigned)
++format_size; ++format_size;
hsAssert(format_size < 21, "Format length too long"); hsAssert(format_size < 24, "Format length too long");
char buffer[21];
_IFormatNumeric_Impl<_IType>(buffer + format_size, abs, 10);
int signPos = arrsize(buffer) - static_cast<int>(format_size); char buffer[24];
hsAssert(signPos >= 0, "Format buffer not large enough for sign"); _IFormatNumeric_Impl<_UType>(buffer + format_size, abs, 10);
if (value < 0) if (value < 0)
buffer[signPos] = '-'; buffer[0] = '-';
else if (format.fDigitClass == plFormat_Private::kDigitDecAlwaysSigned) else if (format.fDigitClass == plFormat_Private::kDigitDecAlwaysSigned)
buffer[signPos] = '+'; buffer[0] = '+';
_formatString(format, output, buffer, format_size, plFormat_Private::kAlignRight); _formatString(format, output, buffer, format_size, plFormat_Private::kAlignRight);
} }
@ -477,20 +476,20 @@ PL_FORMAT_IMPL(wchar_t)
{ {
switch (format.fDigitClass) { switch (format.fDigitClass) {
case plFormat_Private::kDigitBin: case plFormat_Private::kDigitBin:
_formatNumeric<wchar_t>(format, output, value, 2); _formatNumeric<uint32_t>(format, output, value, 2);
break; break;
case plFormat_Private::kDigitOct: case plFormat_Private::kDigitOct:
_formatNumeric<wchar_t>(format, output, value, 8); _formatNumeric<uint32_t>(format, output, value, 8);
break; break;
case plFormat_Private::kDigitHex: case plFormat_Private::kDigitHex:
_formatNumeric<wchar_t>(format, output, value, 16, false); _formatNumeric<uint32_t>(format, output, value, 16, false);
break; break;
case plFormat_Private::kDigitHexUpper: case plFormat_Private::kDigitHexUpper:
_formatNumeric<wchar_t>(format, output,value, 16, true); _formatNumeric<uint32_t>(format, output, value, 16, true);
break; break;
case plFormat_Private::kDigitDec: case plFormat_Private::kDigitDec:
case plFormat_Private::kDigitDecAlwaysSigned: case plFormat_Private::kDigitDecAlwaysSigned:
_formatDecimal<wchar_t>(format, output, value); _formatDecimal<uint32_t>(format, output, value);
break; break;
case plFormat_Private::kDigitChar: case plFormat_Private::kDigitChar:
case plFormat_Private::kDigitDefault: case plFormat_Private::kDigitDefault:

60
Sources/Tests/CoreTests/test_plFormat.cpp

@ -3,6 +3,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <string> #include <string>
#include <limits>
TEST(plFormat, Escapes) TEST(plFormat, Escapes)
{ {
@ -83,3 +84,62 @@ TEST(plFormat, Char)
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (int64_t)0x10ffff)); EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (int64_t)0x10ffff));
EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (uint64_t)0x10ffff)); EXPECT_EQ(plString("xx\xf4\x8f\xbf\xbfxx"), plFormat("xx{c}xx", (uint64_t)0x10ffff));
} }
TEST(plFormat, Decimal)
{
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{d}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{2}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{>2}xx", 1234));
EXPECT_EQ(plString("xx1234xx"), plFormat("xx{<2}xx", 1234));
EXPECT_EQ(plString("xx 1234xx"), plFormat("xx{6}xx", 1234));
EXPECT_EQ(plString("xx 1234xx"), plFormat("xx{>6}xx", 1234));
EXPECT_EQ(plString("xx1234 xx"), plFormat("xx{<6}xx", 1234));
// Character types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{d}xx", '\0'));
EXPECT_EQ(plString("xx65xx"), plFormat("xx{d}xx", 'A'));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{d}xx", L'\0'));
EXPECT_EQ(plString("xx65xx"), plFormat("xx{d}xx", L'A'));
EXPECT_EQ(plString("xx32767xx"), plFormat("xx{d}xx", L'\u7fff'));
// Numeric char types
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (signed char)0));
EXPECT_EQ(plString("xx127xx"), plFormat("xx{}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx+127xx"), plFormat("xx{+}xx", std::numeric_limits<signed char>::max()));
EXPECT_EQ(plString("xx-128xx"), plFormat("xx{}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx-128xx"), plFormat("xx{+}xx", std::numeric_limits<signed char>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (unsigned char)0));
EXPECT_EQ(plString("xx255xx"), plFormat("xx{}xx", std::numeric_limits<unsigned char>::max()));
EXPECT_EQ(plString("xx+255xx"), plFormat("xx{+}xx", std::numeric_limits<unsigned char>::max()));
// 16-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (short)0));
EXPECT_EQ(plString("xx32767xx"), plFormat("xx{}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx+32767xx"), plFormat("xx{+}xx", std::numeric_limits<short>::max()));
EXPECT_EQ(plString("xx-32768xx"), plFormat("xx{}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx-32768xx"), plFormat("xx{+}xx", std::numeric_limits<short>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (unsigned short)0));
EXPECT_EQ(plString("xx65535xx"), plFormat("xx{}xx", std::numeric_limits<unsigned short>::max()));
EXPECT_EQ(plString("xx+65535xx"), plFormat("xx{+}xx", std::numeric_limits<unsigned short>::max()));
// 32-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (int)0));
EXPECT_EQ(plString("xx2147483647xx"), plFormat("xx{}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx+2147483647xx"), plFormat("xx{+}xx", std::numeric_limits<int>::max()));
EXPECT_EQ(plString("xx-2147483648xx"), plFormat("xx{}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx-2147483648xx"), plFormat("xx{+}xx", std::numeric_limits<int>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (unsigned int)0));
EXPECT_EQ(plString("xx4294967295xx"), plFormat("xx{}xx", std::numeric_limits<unsigned int>::max()));
EXPECT_EQ(plString("xx+4294967295xx"), plFormat("xx{+}xx", std::numeric_limits<unsigned int>::max()));
// 64-bit ints
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (int64_t)0));
EXPECT_EQ(plString("xx9223372036854775807xx"), plFormat("xx{}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx+9223372036854775807xx"), plFormat("xx{+}xx", std::numeric_limits<int64_t>::max()));
EXPECT_EQ(plString("xx-9223372036854775808xx"), plFormat("xx{}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx-9223372036854775808xx"), plFormat("xx{+}xx", std::numeric_limits<int64_t>::min()));
EXPECT_EQ(plString("xx0xx"), plFormat("xx{}xx", (uint64_t)0));
EXPECT_EQ(plString("xx18446744073709551615xx"), plFormat("xx{}xx", std::numeric_limits<uint64_t>::max()));
EXPECT_EQ(plString("xx+18446744073709551615xx"), plFormat("xx{+}xx", std::numeric_limits<uint64_t>::max()));
}

Loading…
Cancel
Save