[llvm] r285483 - Resubmit "Add support for advanced number formatting."
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 28 17:27:22 PDT 2016
Author: zturner
Date: Fri Oct 28 19:27:22 2016
New Revision: 285483
URL: http://llvm.org/viewvc/llvm-project?rev=285483&view=rev
Log:
Resubmit "Add support for advanced number formatting."
This resubmits r284436 and r284437, which were reverted in
r284462 as they were breaking the AArch64 buildbot.
The breakage on AArch64 turned out to be a miscompile which is
still not fixed, but is actively tracked at llvm.org/pr30748.
This resubmission re-writes the code in a way so as to make the
miscompile not happen.
Added:
llvm/trunk/unittests/Support/NativeFormatTests.cpp
Modified:
llvm/trunk/include/llvm/Support/NativeFormatting.h
llvm/trunk/lib/Support/NativeFormatting.cpp
llvm/trunk/lib/Support/raw_ostream.cpp
llvm/trunk/unittests/Support/CMakeLists.txt
Modified: llvm/trunk/include/llvm/Support/NativeFormatting.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/NativeFormatting.h?rev=285483&r1=285482&r2=285483&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/NativeFormatting.h (original)
+++ llvm/trunk/include/llvm/Support/NativeFormatting.h Fri Oct 28 19:27:22 2016
@@ -10,22 +10,32 @@
#ifndef LLVM_SUPPORT_NATIVE_FORMATTING_H
#define LLVM_SUPPORT_NATIVE_FORMATTING_H
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
namespace llvm {
-enum class FloatStyle { Exponent, Decimal };
+enum class FloatStyle { Exponent, ExponentUpper, Fixed, Percent };
+enum class IntegerStyle {
+ Integer,
+ Number,
+};
+enum class HexPrintStyle { Upper, Lower, PrefixUpper, PrefixLower };
-void write_ulong(raw_ostream &S, unsigned long N, std::size_t MinWidth);
-void write_long(raw_ostream &S, long N, std::size_t MinWidth);
-void write_ulonglong(raw_ostream &S, unsigned long long N,
- std::size_t MinWidth);
-void write_longlong(raw_ostream &S, long long N, std::size_t MinWidth);
-void write_hex(raw_ostream &S, unsigned long long N, std::size_t MinWidth,
- bool Upper, bool Prefix);
-void write_double(raw_ostream &S, double D, std::size_t MinWidth,
- std::size_t MinDecimals, FloatStyle Style);
+size_t getDefaultPrecision(FloatStyle Style);
+
+void write_integer(raw_ostream &S, unsigned int N, IntegerStyle Style);
+void write_integer(raw_ostream &S, int N, IntegerStyle Style);
+void write_integer(raw_ostream &S, unsigned long N, IntegerStyle Style);
+void write_integer(raw_ostream &S, long N, IntegerStyle Style);
+void write_integer(raw_ostream &S, unsigned long long N, IntegerStyle Style);
+void write_integer(raw_ostream &S, long long N, IntegerStyle Style);
+
+void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
+ Optional<size_t> Width = None);
+void write_double(raw_ostream &S, double D, FloatStyle Style,
+ Optional<size_t> Precision = None);
}
#endif
\ No newline at end of file
Modified: llvm/trunk/lib/Support/NativeFormatting.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/NativeFormatting.cpp?rev=285483&r1=285482&r2=285483&view=diff
==============================================================================
--- llvm/trunk/lib/Support/NativeFormatting.cpp (original)
+++ llvm/trunk/lib/Support/NativeFormatting.cpp Fri Oct 28 19:27:22 2016
@@ -9,6 +9,7 @@
#include "llvm/Support/NativeFormatting.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Format.h"
@@ -20,96 +21,121 @@ static int format_to_buffer(T Value, cha
char *EndPtr = std::end(Buffer);
char *CurPtr = EndPtr;
- while (Value) {
+ do {
*--CurPtr = '0' + char(Value % 10);
Value /= 10;
- }
+ } while (Value);
return EndPtr - CurPtr;
}
-void llvm::write_ulong(raw_ostream &S, unsigned long N, std::size_t MinWidth) {
- // Zero is a special case.
- if (N == 0) {
- if (MinWidth > 0)
- S.indent(MinWidth - 1);
- S << '0';
- return;
- }
+static void writeWithCommas(raw_ostream &S, ArrayRef<char> Buffer) {
+ assert(!Buffer.empty());
- char NumberBuffer[20];
- int Len = format_to_buffer(N, NumberBuffer);
- int Pad = (MinWidth == 0) ? 0 : MinWidth - Len;
- if (Pad > 0)
- S.indent(Pad);
- S.write(std::end(NumberBuffer) - Len, Len);
-}
+ ArrayRef<char> ThisGroup;
+ int InitialDigits = ((Buffer.size() - 1) % 3) + 1;
+ ThisGroup = Buffer.take_front(InitialDigits);
+ S.write(ThisGroup.data(), ThisGroup.size());
-void llvm::write_long(raw_ostream &S, long N, std::size_t MinWidth) {
- if (N >= 0) {
- write_ulong(S, static_cast<unsigned long>(N), MinWidth);
- return;
+ Buffer = Buffer.drop_front(InitialDigits);
+ assert(Buffer.size() % 3 == 0);
+ while (!Buffer.empty()) {
+ S << ',';
+ ThisGroup = Buffer.take_front(3);
+ S.write(ThisGroup.data(), 3);
+ Buffer = Buffer.drop_front(3);
}
+}
- unsigned long UN = -(unsigned long)N;
- if (MinWidth > 0)
- --MinWidth;
-
- char NumberBuffer[20];
- int Len = format_to_buffer(UN, NumberBuffer);
- int Pad = (MinWidth == 0) ? 0 : MinWidth - Len;
- if (Pad > 0)
- S.indent(Pad);
- S.write('-');
- S.write(std::end(NumberBuffer) - Len, Len);
-}
-
-void llvm::write_ulonglong(raw_ostream &S, unsigned long long N,
- std::size_t MinWidth) {
- // Output using 32-bit div/mod when possible.
- if (N == static_cast<unsigned long>(N)) {
- write_ulong(S, static_cast<unsigned long>(N), MinWidth);
- return;
+template <typename T>
+static void write_unsigned_impl(raw_ostream &S, T N, IntegerStyle Style,
+ bool IsNegative) {
+ static_assert(std::is_unsigned<T>::value, "Value is not unsigned!");
+
+ char NumberBuffer[128];
+ std::memset(NumberBuffer, '0', sizeof(NumberBuffer));
+
+ size_t Len = 0;
+ Len = format_to_buffer(N, NumberBuffer);
+
+ if (IsNegative)
+ S << '-';
+ if (Style == IntegerStyle::Number) {
+ writeWithCommas(S, ArrayRef<char>(std::end(NumberBuffer) - Len, Len));
+ } else {
+ S.write(std::end(NumberBuffer) - Len, Len);
}
+}
- char NumberBuffer[32];
- int Len = format_to_buffer(N, NumberBuffer);
- int Pad = (MinWidth == 0) ? 0 : MinWidth - Len;
- if (Pad > 0)
- S.indent(Pad);
- S.write(std::end(NumberBuffer) - Len, Len);
+template <typename T>
+static void write_unsigned(raw_ostream &S, T N, IntegerStyle Style,
+ bool IsNegative = false) {
+ // Output using 32-bit div/mod if possible.
+ if (N == static_cast<uint32_t>(N))
+ write_unsigned_impl(S, static_cast<uint32_t>(N), Style, IsNegative);
+ else
+ write_unsigned_impl(S, N, Style, IsNegative);
}
-void llvm::write_longlong(raw_ostream &S, long long N, std::size_t MinWidth) {
+template <typename T>
+static void write_signed(raw_ostream &S, T N, IntegerStyle Style) {
+ static_assert(std::is_signed<T>::value, "Value is not signed!");
+
+ using UnsignedT = typename std::make_unsigned<T>::type;
+
if (N >= 0) {
- write_ulonglong(S, static_cast<unsigned long long>(N), MinWidth);
+ write_unsigned(S, static_cast<UnsignedT>(N), Style);
return;
}
- // Avoid undefined behavior on INT64_MIN with a cast.
- unsigned long long UN = -(unsigned long long)N;
- if (MinWidth > 0)
- --MinWidth;
-
- char NumberBuffer[32];
- int Len = format_to_buffer(UN, NumberBuffer);
- int Pad = (MinWidth == 0) ? 0 : MinWidth - Len;
- if (Pad > 0)
- S.indent(Pad);
- S.write('-');
- S.write(std::end(NumberBuffer) - Len, Len);
+ UnsignedT UN = -(UnsignedT)N;
+ write_unsigned(S, UN, Style, true);
+}
+
+void llvm::write_integer(raw_ostream &S, unsigned int N, IntegerStyle Style) {
+ write_unsigned(S, N, Style);
+}
+
+void llvm::write_integer(raw_ostream &S, int N, IntegerStyle Style) {
+ write_signed(S, N, Style);
}
-void llvm::write_hex(raw_ostream &S, unsigned long long N, std::size_t MinWidth,
- bool Upper, bool Prefix) {
+void llvm::write_integer(raw_ostream &S, unsigned long N, IntegerStyle Style) {
+ write_unsigned(S, N, Style);
+}
+
+void llvm::write_integer(raw_ostream &S, long N, IntegerStyle Style) {
+ write_signed(S, N, Style);
+}
+
+void llvm::write_integer(raw_ostream &S, unsigned long long N,
+ IntegerStyle Style) {
+ write_unsigned(S, N, Style);
+}
+
+void llvm::write_integer(raw_ostream &S, long long N, IntegerStyle Style) {
+ write_signed(S, N, Style);
+}
+
+void llvm::write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style,
+ Optional<size_t> Width) {
+ const size_t kMaxWidth = 128u;
+
+ size_t W = std::min(kMaxWidth, Width.getValueOr(0u));
+
unsigned Nibbles = (64 - countLeadingZeros(N) + 3) / 4;
+ bool Prefix = (Style == HexPrintStyle::PrefixLower ||
+ Style == HexPrintStyle::PrefixUpper);
+ bool Upper =
+ (Style == HexPrintStyle::Upper || Style == HexPrintStyle::PrefixUpper);
unsigned PrefixChars = Prefix ? 2 : 0;
- unsigned Width = std::max(static_cast<unsigned>(MinWidth),
- std::max(1u, Nibbles) + PrefixChars);
+ unsigned NumChars =
+ std::max(static_cast<unsigned>(W), std::max(1u, Nibbles) + PrefixChars);
- char NumberBuffer[20] = "0x0000000000000000";
- if (!Prefix)
- NumberBuffer[1] = '0';
- char *EndPtr = NumberBuffer + Width;
+ char NumberBuffer[kMaxWidth];
+ ::memset(NumberBuffer, '0', llvm::array_lengthof(NumberBuffer));
+ if (Prefix)
+ NumberBuffer[1] = 'x';
+ char *EndPtr = NumberBuffer + NumChars;
char *CurPtr = EndPtr;
while (N) {
unsigned char x = static_cast<unsigned char>(N) % 16;
@@ -117,22 +143,34 @@ void llvm::write_hex(raw_ostream &S, uns
N /= 16;
}
- S.write(NumberBuffer, Width);
+ S.write(NumberBuffer, NumChars);
}
-void llvm::write_double(raw_ostream &S, double N, std::size_t MinWidth,
- std::size_t MinDecimals, FloatStyle Style) {
- char Letter = (Style == FloatStyle::Exponent) ? 'e' : 'f';
+void llvm::write_double(raw_ostream &S, double N, FloatStyle Style,
+ Optional<size_t> Precision) {
+ size_t Prec = Precision.getValueOr(getDefaultPrecision(Style));
+
+ if (std::isnan(N)) {
+ S << "nan";
+ return;
+ } else if (std::isinf(N)) {
+ S << "INF";
+ return;
+ }
+
+ char Letter;
+ if (Style == FloatStyle::Exponent)
+ Letter = 'e';
+ else if (Style == FloatStyle::ExponentUpper)
+ Letter = 'E';
+ else
+ Letter = 'f';
+
SmallString<8> Spec;
llvm::raw_svector_ostream Out(Spec);
- Out << '%';
- if (MinWidth > 0)
- Out << MinWidth;
- if (MinDecimals > 0)
- Out << '.' << MinDecimals;
- Out << Letter;
+ Out << "%." << Prec << Letter;
- if (Style == FloatStyle::Exponent) {
+ if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) {
#ifdef _WIN32
// On MSVCRT and compatible, output of %e is incompatible to Posix
// by default. Number of exponent digits should be at least 2. "%+03d"
@@ -140,7 +178,9 @@ void llvm::write_double(raw_ostream &S,
#if defined(__MINGW32__)
// FIXME: It should be generic to C++11.
if (N == 0.0 && std::signbit(N)) {
- S << "-0.000000e+00";
+ const char *NegativeZero = "-0.000000e+00";
+ writePadding(S, Width, strlen(NegativeZero));
+ S << NegativeZero;
return;
}
#else
@@ -148,16 +188,18 @@ void llvm::write_double(raw_ostream &S,
// negative zero
if (fpcl == _FPCLASS_NZ) {
- S << "-0.000000e+00";
+ const char *NegativeZero = "-0.000000e+00";
+ S << NegativeZero;
return;
}
#endif
- char buf[16];
+ char buf[32];
unsigned len;
len = format(Spec.c_str(), N).snprint(buf, sizeof(buf));
if (len <= sizeof(buf) - 2) {
- if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') {
+ if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') &&
+ buf[len - 3] == '0') {
int cs = buf[len - 4];
if (cs == '+' || cs == '-') {
int c1 = buf[len - 2];
@@ -177,5 +219,27 @@ void llvm::write_double(raw_ostream &S,
#endif
}
- S << format(Spec.c_str(), N);
+ if (Style == FloatStyle::Percent)
+ N *= 100.0;
+
+ char Buf[32];
+ unsigned Len;
+ Len = format(Spec.c_str(), N).snprint(Buf, sizeof(Buf));
+ if (Style == FloatStyle::Percent)
+ ++Len;
+ S << Buf;
+ if (Style == FloatStyle::Percent)
+ S << '%';
+}
+
+size_t llvm::getDefaultPrecision(FloatStyle Style) {
+ switch (Style) {
+ case FloatStyle::Exponent:
+ case FloatStyle::ExponentUpper:
+ return 6; // Number of decimal places.
+ case FloatStyle::Fixed:
+ case FloatStyle::Percent:
+ return 2; // Number of decimal places.
+ }
+ LLVM_BUILTIN_UNREACHABLE;
}
Modified: llvm/trunk/lib/Support/raw_ostream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=285483&r1=285482&r2=285483&view=diff
==============================================================================
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)
+++ llvm/trunk/lib/Support/raw_ostream.cpp Fri Oct 28 19:27:22 2016
@@ -114,27 +114,27 @@ void raw_ostream::SetBufferAndMode(char
}
raw_ostream &raw_ostream::operator<<(unsigned long N) {
- write_ulong(*this, N, 0);
+ write_integer(*this, static_cast<uint64_t>(N), IntegerStyle::Integer);
return *this;
}
raw_ostream &raw_ostream::operator<<(long N) {
- write_long(*this, N, 0);
+ write_integer(*this, static_cast<int64_t>(N), IntegerStyle::Integer);
return *this;
}
raw_ostream &raw_ostream::operator<<(unsigned long long N) {
- write_ulonglong(*this, N, 0);
+ write_integer(*this, static_cast<uint64_t>(N), IntegerStyle::Integer);
return *this;
}
raw_ostream &raw_ostream::operator<<(long long N) {
- write_longlong(*this, N, 0);
+ write_integer(*this, static_cast<int64_t>(N), IntegerStyle::Integer);
return *this;
}
raw_ostream &raw_ostream::write_hex(unsigned long long N) {
- llvm::write_hex(*this, N, 0, false, false);
+ llvm::write_hex(*this, N, HexPrintStyle::Lower);
return *this;
}
@@ -179,12 +179,12 @@ raw_ostream &raw_ostream::write_escaped(
}
raw_ostream &raw_ostream::operator<<(const void *P) {
- llvm::write_hex(*this, (uintptr_t)P, 0, false, true);
+ llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower);
return *this;
}
raw_ostream &raw_ostream::operator<<(double N) {
- llvm::write_double(*this, N, 0, 0, FloatStyle::Exponent);
+ llvm::write_double(*this, N, FloatStyle::Exponent);
return *this;
}
@@ -331,9 +331,23 @@ raw_ostream &raw_ostream::operator<<(con
raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
if (FN.Hex) {
- llvm::write_hex(*this, FN.HexValue, FN.Width, FN.Upper, FN.HexPrefix);
+ HexPrintStyle Style;
+ if (FN.Upper && FN.HexPrefix)
+ Style = HexPrintStyle::PrefixUpper;
+ else if (FN.Upper && !FN.HexPrefix)
+ Style = HexPrintStyle::Upper;
+ else if (!FN.Upper && FN.HexPrefix)
+ Style = HexPrintStyle::PrefixLower;
+ else
+ Style = HexPrintStyle::Lower;
+ llvm::write_hex(*this, FN.HexValue, Style, FN.Width);
} else {
- llvm::write_longlong(*this, FN.DecValue, FN.Width);
+ llvm::SmallString<16> Buffer;
+ llvm::raw_svector_ostream Stream(Buffer);
+ llvm::write_integer(Stream, FN.DecValue, IntegerStyle::Integer);
+ if (Buffer.size() < FN.Width)
+ indent(FN.Width - Buffer.size());
+ (*this) << Buffer;
}
return *this;
}
Modified: llvm/trunk/unittests/Support/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=285483&r1=285482&r2=285483&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/CMakeLists.txt (original)
+++ llvm/trunk/unittests/Support/CMakeLists.txt Fri Oct 28 19:27:22 2016
@@ -29,6 +29,7 @@ add_llvm_unittest(SupportTests
MathExtrasTest.cpp
MemoryBufferTest.cpp
MemoryTest.cpp
+ NativeFormatTests.cpp
Path.cpp
ProcessTest.cpp
ProgramTest.cpp
Added: llvm/trunk/unittests/Support/NativeFormatTests.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/NativeFormatTests.cpp?rev=285483&view=auto
==============================================================================
--- llvm/trunk/unittests/Support/NativeFormatTests.cpp (added)
+++ llvm/trunk/unittests/Support/NativeFormatTests.cpp Fri Oct 28 19:27:22 2016
@@ -0,0 +1,176 @@
+//===- llvm/unittest/Support/NativeFormatTests.cpp - formatting tests -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/NativeFormatting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+#include <type_traits>
+
+using namespace llvm;
+
+namespace {
+
+template <typename T> std::string format_number(T N, IntegerStyle Style) {
+ std::string S;
+ llvm::raw_string_ostream Str(S);
+ write_integer(Str, N, Style);
+ Str.flush();
+ return S;
+}
+
+std::string format_number(uint64_t N, HexPrintStyle Style,
+ Optional<size_t> Width = None) {
+ std::string S;
+ llvm::raw_string_ostream Str(S);
+ write_hex(Str, N, Style, Width);
+ Str.flush();
+ return S;
+}
+
+std::string format_number(double D, FloatStyle Style,
+ Optional<size_t> Precision = None) {
+ std::string S;
+ llvm::raw_string_ostream Str(S);
+ write_double(Str, D, Style, Precision);
+ Str.flush();
+ return S;
+}
+
+// Test basic number formatting with various styles and default width and
+// precision.
+TEST(NativeFormatTest, BasicIntegerTests) {
+ // Simple integers with no decimal.
+ EXPECT_EQ("0", format_number(0, IntegerStyle::Integer));
+ EXPECT_EQ("2425", format_number(2425, IntegerStyle::Integer));
+ EXPECT_EQ("-2425", format_number(-2425, IntegerStyle::Integer));
+
+ EXPECT_EQ("0", format_number(0LL, IntegerStyle::Integer));
+ EXPECT_EQ("257257257235709",
+ format_number(257257257235709LL, IntegerStyle::Integer));
+ EXPECT_EQ("-257257257235709",
+ format_number(-257257257235709LL, IntegerStyle::Integer));
+
+ // Number formatting.
+ EXPECT_EQ("0", format_number(0, IntegerStyle::Number));
+ EXPECT_EQ("2,425", format_number(2425, IntegerStyle::Number));
+ EXPECT_EQ("-2,425", format_number(-2425, IntegerStyle::Number));
+ EXPECT_EQ("257,257,257,235,709",
+ format_number(257257257235709LL, IntegerStyle::Number));
+ EXPECT_EQ("-257,257,257,235,709",
+ format_number(-257257257235709LL, IntegerStyle::Number));
+
+ // Hex formatting.
+ // lower case, prefix.
+ EXPECT_EQ("0x0", format_number(0, HexPrintStyle::PrefixLower));
+ EXPECT_EQ("0xbeef", format_number(0xbeefLL, HexPrintStyle::PrefixLower));
+ EXPECT_EQ("0xdeadbeef",
+ format_number(0xdeadbeefLL, HexPrintStyle::PrefixLower));
+
+ // upper-case, prefix.
+ EXPECT_EQ("0x0", format_number(0, HexPrintStyle::PrefixUpper));
+ EXPECT_EQ("0xBEEF", format_number(0xbeefLL, HexPrintStyle::PrefixUpper));
+ EXPECT_EQ("0xDEADBEEF",
+ format_number(0xdeadbeefLL, HexPrintStyle::PrefixUpper));
+
+ // lower-case, no prefix
+ EXPECT_EQ("0", format_number(0, HexPrintStyle::Lower));
+ EXPECT_EQ("beef", format_number(0xbeefLL, HexPrintStyle::Lower));
+ EXPECT_EQ("deadbeef", format_number(0xdeadbeefLL, HexPrintStyle::Lower));
+
+ // upper-case, no prefix.
+ EXPECT_EQ("0", format_number(0, HexPrintStyle::Upper));
+ EXPECT_EQ("BEEF", format_number(0xbeef, HexPrintStyle::Upper));
+ EXPECT_EQ("DEADBEEF", format_number(0xdeadbeef, HexPrintStyle::Upper));
+}
+
+// Test basic floating point formatting with various styles and default width
+// and precision.
+TEST(NativeFormatTest, BasicFloatingPointTests) {
+ // Double
+ EXPECT_EQ("0.000000e+00", format_number(0.0, FloatStyle::Exponent));
+ EXPECT_EQ("-0.000000e+00", format_number(-0.0, FloatStyle::Exponent));
+ EXPECT_EQ("1.100000e+00", format_number(1.1, FloatStyle::Exponent));
+ EXPECT_EQ("1.100000E+00", format_number(1.1, FloatStyle::ExponentUpper));
+
+ // Default precision is 2 for floating points.
+ EXPECT_EQ("1.10", format_number(1.1, FloatStyle::Fixed));
+ EXPECT_EQ("1.34", format_number(1.34, FloatStyle::Fixed));
+ EXPECT_EQ("1.34", format_number(1.344, FloatStyle::Fixed));
+ EXPECT_EQ("1.35", format_number(1.346, FloatStyle::Fixed));
+}
+
+// Test common boundary cases and min/max conditions.
+TEST(NativeFormatTest, BoundaryTests) {
+ // Min and max.
+ EXPECT_EQ("18446744073709551615",
+ format_number(UINT64_MAX, IntegerStyle::Integer));
+
+ EXPECT_EQ("9223372036854775807",
+ format_number(INT64_MAX, IntegerStyle::Integer));
+ EXPECT_EQ("-9223372036854775808",
+ format_number(INT64_MIN, IntegerStyle::Integer));
+
+ EXPECT_EQ("4294967295", format_number(UINT32_MAX, IntegerStyle::Integer));
+ EXPECT_EQ("2147483647", format_number(INT32_MAX, IntegerStyle::Integer));
+ EXPECT_EQ("-2147483648", format_number(INT32_MIN, IntegerStyle::Integer));
+
+ EXPECT_EQ("nan", format_number(std::numeric_limits<double>::quiet_NaN(),
+ FloatStyle::Fixed));
+ EXPECT_EQ("INF", format_number(std::numeric_limits<double>::infinity(),
+ FloatStyle::Fixed));
+}
+
+TEST(NativeFormatTest, HexTests) {
+ // Test hex formatting with different widths and precisions.
+
+ // Width less than the value should print the full value anyway.
+ EXPECT_EQ("0x0", format_number(0, HexPrintStyle::PrefixLower, 0));
+ EXPECT_EQ("0xabcde", format_number(0xABCDE, HexPrintStyle::PrefixLower, 3));
+
+ // Precision greater than the value should pad with 0s.
+ // TODO: The prefix should not be counted in the precision. But unfortunately
+ // it is and we have to live with it unless we fix all existing users of
+ // prefixed hex formatting.
+ EXPECT_EQ("0x000", format_number(0, HexPrintStyle::PrefixLower, 5));
+ EXPECT_EQ("0x0abcde", format_number(0xABCDE, HexPrintStyle::PrefixLower, 8));
+
+ EXPECT_EQ("00000", format_number(0, HexPrintStyle::Lower, 5));
+ EXPECT_EQ("000abcde", format_number(0xABCDE, HexPrintStyle::Lower, 8));
+
+ // Try printing more digits than can fit in a uint64.
+ EXPECT_EQ("0x00000000000000abcde",
+ format_number(0xABCDE, HexPrintStyle::PrefixLower, 21));
+}
+
+TEST(NativeFormatTest, IntegerTests) {
+ EXPECT_EQ("-10", format_number(-10, IntegerStyle::Integer));
+ EXPECT_EQ("-100", format_number(-100, IntegerStyle::Integer));
+ EXPECT_EQ("-1000", format_number(-1000, IntegerStyle::Integer));
+ EXPECT_EQ("-1234567890", format_number(-1234567890, IntegerStyle::Integer));
+ EXPECT_EQ("10", format_number(10, IntegerStyle::Integer));
+ EXPECT_EQ("100", format_number(100, IntegerStyle::Integer));
+ EXPECT_EQ("1000", format_number(1000, IntegerStyle::Integer));
+ EXPECT_EQ("1234567890", format_number(1234567890, IntegerStyle::Integer));
+}
+
+TEST(NativeFormatTest, CommaTests) {
+ EXPECT_EQ("0", format_number(0, IntegerStyle::Number));
+ EXPECT_EQ("10", format_number(10, IntegerStyle::Number));
+ EXPECT_EQ("100", format_number(100, IntegerStyle::Number));
+ EXPECT_EQ("1,000", format_number(1000, IntegerStyle::Number));
+ EXPECT_EQ("1,234,567,890", format_number(1234567890, IntegerStyle::Number));
+
+ EXPECT_EQ("-10", format_number(-10, IntegerStyle::Number));
+ EXPECT_EQ("-100", format_number(-100, IntegerStyle::Number));
+ EXPECT_EQ("-1,000", format_number(-1000, IntegerStyle::Number));
+ EXPECT_EQ("-1,234,567,890", format_number(-1234567890, IntegerStyle::Number));
+}
+}
More information about the llvm-commits
mailing list