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

60
Sources/Tests/CoreTests/test_plFormat.cpp

@ -3,6 +3,7 @@
#include <gtest/gtest.h>
#include <string>
#include <limits>
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", (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