add support for binary type and test long longs more

This commit is contained in:
Gregory Czajkowski 2013-10-23 20:04:32 -07:00
parent eded10cf31
commit e4ffc06875
3 changed files with 70 additions and 12 deletions

View File

@ -115,7 +115,7 @@ The general form of a *standard format specifier* is:
sign: "+" | "-" | " " sign: "+" | "-" | " "
width: `integer` width: `integer`
precision: `integer` | "{" `arg_index` "}" precision: `integer` | "{" `arg_index` "}"
type: "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "o" | "p" | s" | "x" | "X" type: "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "o" | "p" | s" | "x" | "X" | "b" | "B"
The *fill* character can be any character other than '{' or '}'. The presence The *fill* character can be any character other than '{' or '}'. The presence
of a fill character is signaled by the character following it, which must be of a fill character is signaled by the character following it, which must be
@ -167,9 +167,9 @@ following:
The ``'#'`` option causes the "alternate form" to be used for the The ``'#'`` option causes the "alternate form" to be used for the
conversion. The alternate form is defined differently for different conversion. The alternate form is defined differently for different
types. This option is only valid for integer and floating-point types. types. This option is only valid for integer and floating-point types.
For integers, when octal, or hexadecimal output For integers, when octal, or hexadecimal, or binary output
is used, this option adds the prefix respective ``'0'``, or is used, this option adds the prefix respective ``'0'``, or
``'0x'`` to the output value. For floating-point numbers the ``'0x'``, or ``'0b'`` to the output value. For floating-point numbers the
alternate form causes the result of the conversion to always contain a alternate form causes the result of the conversion to always contain a
decimal-point character, even if no digits follow it. Normally, a decimal-point character, even if no digits follow it. Normally, a
decimal-point character appears in the result of these conversions decimal-point character appears in the result of these conversions
@ -235,6 +235,12 @@ The available integer presentation types are:
| ``'X'`` | Hex format. Outputs the number in base 16, using | | ``'X'`` | Hex format. Outputs the number in base 16, using |
| | upper-case letters for the digits above 9. | | | upper-case letters for the digits above 9. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
| ``'b'`` | Binary format. Outputs the number in base 2, using |
| | a upper-case 0B if a prefix is requested. |
+---------+----------------------------------------------------------+
| ``'B'`` | Binary format. Outputs the number in base 2, using |
| | a lower-case 0b if a prefix is requested. |
+---------+----------------------------------------------------------+
| none | The same as ``'d'``. | | none | The same as ``'d'``. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
@ -349,13 +355,13 @@ Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign::
Format("{:-f}; {:-f}") << 3.14 << -3.14; // show only the minus -- same as '{:f}; {:f}' Format("{:-f}; {:-f}") << 3.14 << -3.14; // show only the minus -- same as '{:f}; {:f}'
// Result: "3.140000; -3.140000" // Result: "3.140000; -3.140000"
Replacing ``%x`` and ``%o`` and converting the value to different bases:: Replacing ``%x`` and ``%o`` and ``%b`` and converting the value to different bases::
Format("int: {0:d}; hex: {0:x}; oct: {0:o}") << 42; Format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}") << 42;
// Result: "int: 42; hex: 2a; oct: 52" // Result: "int: 42; hex: 2a; oct: 52; bin: 101010"
// with 0x or 0 as prefix: // with 0x or 0 or 0b as prefix:
Format("int: {0:d}; hex: {0:#x}; oct: {0:#o}") << 42; Format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}") << 42;
// Result: "int: 42; hex: 0x2a; oct: 052" // Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010"
.. ifconfig:: False .. ifconfig:: False

View File

@ -369,6 +369,16 @@ class IntFormatter : public SpecT {
T value() const { return value_; } T value() const { return value_; }
}; };
/**
Returns an integer formatter that formats the value in base 2.
*/
IntFormatter<int, TypeSpec<'b'> > bin(int value);
/**
Returns an integer formatter that formats the value in base 2.
*/
IntFormatter<int, TypeSpec<'B'> > binu(int value);
/** /**
Returns an integer formatter that formats the value in base 8. Returns an integer formatter that formats the value in base 8.
*/ */
@ -403,6 +413,12 @@ IntFormatter<int, AlignTypeSpec<TYPE_CODE> > pad(
int value, unsigned width, wchar_t fill = ' '); int value, unsigned width, wchar_t fill = ' ');
#define DEFINE_INT_FORMATTERS(TYPE) \ #define DEFINE_INT_FORMATTERS(TYPE) \
inline IntFormatter<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
} \
inline IntFormatter<TYPE, TypeSpec<'B'> > binu(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'B'> >(value, TypeSpec<'B'>()); \
} \
inline IntFormatter<TYPE, TypeSpec<'o'> > oct(TYPE value) { \ inline IntFormatter<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \ return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
} \ } \
@ -433,6 +449,7 @@ DEFINE_INT_FORMATTERS(int)
DEFINE_INT_FORMATTERS(long) DEFINE_INT_FORMATTERS(long)
DEFINE_INT_FORMATTERS(unsigned) DEFINE_INT_FORMATTERS(unsigned)
DEFINE_INT_FORMATTERS(unsigned long) DEFINE_INT_FORMATTERS(unsigned long)
DEFINE_INT_FORMATTERS(unsigned long long)
template <typename Char> template <typename Char>
class BasicFormatter; class BasicFormatter;
@ -473,7 +490,7 @@ class BasicFormatter;
template <typename Char> template <typename Char>
class BasicWriter { class BasicWriter {
private: private:
enum { INLINE_BUFFER_SIZE = 500 }; enum { INLINE_BUFFER_SIZE = 512 };
mutable internal::Array<Char, INLINE_BUFFER_SIZE> buffer_; // Output buffer. mutable internal::Array<Char, INLINE_BUFFER_SIZE> buffer_; // Output buffer.
friend class BasicFormatter<Char>; friend class BasicFormatter<Char>;
@ -718,6 +735,25 @@ BasicWriter<Char> &BasicWriter<Char>::operator<<(
} }
break; break;
} }
case 'b': case 'B': {
UnsignedType n = abs_value;
bool print_prefix = f.hash_flag();
if (print_prefix) size += 2;
do {
++size;
} while ((n >>= 1) != 0);
Char *p = GetBase(PrepareFilledBuffer(size, f, sign));
n = abs_value;
const char *digits = "01";
do {
*p-- = digits[n & 0x1];
} while ((n >>= 1) != 0);
if (print_prefix) {
*p-- = f.type();
*p = '0';
}
break;
}
case 'o': { case 'o': {
UnsignedType n = abs_value; UnsignedType n = abs_value;
bool print_prefix = f.hash_flag(); bool print_prefix = f.hash_flag();

View File

@ -167,7 +167,6 @@ TEST(UtilTest, Increment) {
EXPECT_STREQ("129", s); EXPECT_STREQ("129", s);
Increment(s); Increment(s);
EXPECT_STREQ("130", s); EXPECT_STREQ("130", s);
EXPECT_STREQ("130", s);
s[1] = s[2] = '9'; s[1] = s[2] = '9';
Increment(s); Increment(s);
EXPECT_STREQ("200", s); EXPECT_STREQ("200", s);
@ -332,6 +331,15 @@ TEST(WriterTest, oct) {
EXPECT_EQ("70", str(Writer() << oct(070ul))); EXPECT_EQ("70", str(Writer() << oct(070ul)));
} }
TEST(WriterTest, bin) {
using fmt::bin;
EXPECT_EQ("1100101011111110", str(Writer() << bin(0xcafe)));
EXPECT_EQ("1011101010111110", str(Writer() << bin(0xbabeu)));
EXPECT_EQ("1101111010101101", str(Writer() << bin(0xdeadl)));
EXPECT_EQ("1011111011101111", str(Writer() << bin(0xbeeful)));
EXPECT_EQ("1111111111111111111111111111111111111111111111111111111111111111", str(Writer() << bin(0xffffffffffffffffull)));
}
TEST(WriterTest, hex) { TEST(WriterTest, hex) {
using fmt::hex; using fmt::hex;
fmt::IntFormatter<int, fmt::TypeSpec<'x'> > (*phex)(int value) = hex; fmt::IntFormatter<int, fmt::TypeSpec<'x'> > (*phex)(int value) = hex;
@ -343,6 +351,8 @@ TEST(WriterTest, hex) {
EXPECT_EQ("babe", str(Writer() << hex(0xbabeu))); EXPECT_EQ("babe", str(Writer() << hex(0xbabeu)));
EXPECT_EQ("dead", str(Writer() << hex(0xdeadl))); EXPECT_EQ("dead", str(Writer() << hex(0xdeadl)));
EXPECT_EQ("beef", str(Writer() << hex(0xbeeful))); EXPECT_EQ("beef", str(Writer() << hex(0xbeeful)));
EXPECT_EQ("beefbeefbeefbeef", str(Writer() << hex(0xbeefbeefbeefbeefull)));
EXPECT_EQ("ffffffffffffffff", str(Writer() << hex(0xffffffffffffffffull)));
} }
TEST(WriterTest, hexu) { TEST(WriterTest, hexu) {
@ -351,6 +361,7 @@ TEST(WriterTest, hexu) {
EXPECT_EQ("BABE", str(Writer() << hexu(0xbabeu))); EXPECT_EQ("BABE", str(Writer() << hexu(0xbabeu)));
EXPECT_EQ("DEAD", str(Writer() << hexu(0xdeadl))); EXPECT_EQ("DEAD", str(Writer() << hexu(0xdeadl)));
EXPECT_EQ("BEEF", str(Writer() << hexu(0xbeeful))); EXPECT_EQ("BEEF", str(Writer() << hexu(0xbeeful)));
EXPECT_EQ("FFFFFFFFFFFFFFFF", str(Writer() << hexu(0xffffffffffffffffull)));
} }
class Date { class Date {
@ -938,7 +949,7 @@ TEST(FormatterTest, FormatShort) {
TEST(FormatterTest, FormatInt) { TEST(FormatterTest, FormatInt) {
EXPECT_THROW_MSG(Format("{0:v") << 42, EXPECT_THROW_MSG(Format("{0:v") << 42,
FormatError, "unmatched '{' in format"); FormatError, "unmatched '{' in format");
CheckUnknownTypes(42, "doxX", "integer"); CheckUnknownTypes(42, "doxXbB", "integer");
} }
TEST(FormatterTest, FormatDec) { TEST(FormatterTest, FormatDec) {
@ -973,6 +984,9 @@ TEST(FormatterTest, FormatHex) {
EXPECT_EQ("90abcdef", str(Format("{0:x}") << 0x90abcdef)); EXPECT_EQ("90abcdef", str(Format("{0:x}") << 0x90abcdef));
EXPECT_EQ("12345678", str(Format("{0:X}") << 0x12345678)); EXPECT_EQ("12345678", str(Format("{0:X}") << 0x12345678));
EXPECT_EQ("90ABCDEF", str(Format("{0:X}") << 0x90ABCDEF)); EXPECT_EQ("90ABCDEF", str(Format("{0:X}") << 0x90ABCDEF));
EXPECT_EQ("10010001101000101011001111000", str(Format("{0:b}") << 0x12345678));
EXPECT_EQ("10010000101010111100110111101111", str(Format("{0:B}") << 0x90ABCDEF));
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
SPrintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN)); SPrintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN));
EXPECT_EQ(buffer, str(Format("{0:x}") << INT_MIN)); EXPECT_EQ(buffer, str(Format("{0:x}") << INT_MIN));
@ -986,6 +1000,8 @@ TEST(FormatterTest, FormatHex) {
EXPECT_EQ(buffer, str(Format("{0:x}") << LONG_MAX)); EXPECT_EQ(buffer, str(Format("{0:x}") << LONG_MAX));
SPrintf(buffer, "%lx", ULONG_MAX); SPrintf(buffer, "%lx", ULONG_MAX);
EXPECT_EQ(buffer, str(Format("{0:x}") << ULONG_MAX)); EXPECT_EQ(buffer, str(Format("{0:x}") << ULONG_MAX));
SPrintf(buffer, "%llx", ULLONG_MAX);
EXPECT_EQ(buffer, str(Format("{0:x}") << ULLONG_MAX));
} }
TEST(FormatterTest, FormatOct) { TEST(FormatterTest, FormatOct) {