add support for binary type and test long longs more
This commit is contained in:
parent
eded10cf31
commit
e4ffc06875
@ -115,7 +115,7 @@ The general form of a *standard format specifier* is:
|
||||
sign: "+" | "-" | " "
|
||||
width: `integer`
|
||||
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
|
||||
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
|
||||
conversion. The alternate form is defined differently for different
|
||||
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
|
||||
``'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
|
||||
decimal-point character, even if no digits follow it. Normally, a
|
||||
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 |
|
||||
| | 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'``. |
|
||||
+---------+----------------------------------------------------------+
|
||||
|
||||
@ -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}'
|
||||
// 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;
|
||||
// Result: "int: 42; hex: 2a; oct: 52"
|
||||
// with 0x or 0 as prefix:
|
||||
Format("int: {0:d}; hex: {0:#x}; oct: {0:#o}") << 42;
|
||||
// Result: "int: 42; hex: 0x2a; oct: 052"
|
||||
Format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}") << 42;
|
||||
// Result: "int: 42; hex: 2a; oct: 52; bin: 101010"
|
||||
// with 0x or 0 or 0b as prefix:
|
||||
Format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}") << 42;
|
||||
// Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010"
|
||||
|
||||
.. ifconfig:: False
|
||||
|
||||
|
38
format.h
38
format.h
@ -369,6 +369,16 @@ class IntFormatter : public SpecT {
|
||||
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.
|
||||
*/
|
||||
@ -403,6 +413,12 @@ IntFormatter<int, AlignTypeSpec<TYPE_CODE> > pad(
|
||||
int value, unsigned width, wchar_t fill = ' ');
|
||||
|
||||
#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) { \
|
||||
return IntFormatter<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
|
||||
} \
|
||||
@ -433,6 +449,7 @@ DEFINE_INT_FORMATTERS(int)
|
||||
DEFINE_INT_FORMATTERS(long)
|
||||
DEFINE_INT_FORMATTERS(unsigned)
|
||||
DEFINE_INT_FORMATTERS(unsigned long)
|
||||
DEFINE_INT_FORMATTERS(unsigned long long)
|
||||
|
||||
template <typename Char>
|
||||
class BasicFormatter;
|
||||
@ -473,7 +490,7 @@ class BasicFormatter;
|
||||
template <typename Char>
|
||||
class BasicWriter {
|
||||
private:
|
||||
enum { INLINE_BUFFER_SIZE = 500 };
|
||||
enum { INLINE_BUFFER_SIZE = 512 };
|
||||
mutable internal::Array<Char, INLINE_BUFFER_SIZE> buffer_; // Output buffer.
|
||||
|
||||
friend class BasicFormatter<Char>;
|
||||
@ -718,6 +735,25 @@ BasicWriter<Char> &BasicWriter<Char>::operator<<(
|
||||
}
|
||||
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': {
|
||||
UnsignedType n = abs_value;
|
||||
bool print_prefix = f.hash_flag();
|
||||
|
@ -167,7 +167,6 @@ TEST(UtilTest, Increment) {
|
||||
EXPECT_STREQ("129", s);
|
||||
Increment(s);
|
||||
EXPECT_STREQ("130", s);
|
||||
EXPECT_STREQ("130", s);
|
||||
s[1] = s[2] = '9';
|
||||
Increment(s);
|
||||
EXPECT_STREQ("200", s);
|
||||
@ -332,6 +331,15 @@ TEST(WriterTest, oct) {
|
||||
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) {
|
||||
using fmt::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("dead", str(Writer() << hex(0xdeadl)));
|
||||
EXPECT_EQ("beef", str(Writer() << hex(0xbeeful)));
|
||||
EXPECT_EQ("beefbeefbeefbeef", str(Writer() << hex(0xbeefbeefbeefbeefull)));
|
||||
EXPECT_EQ("ffffffffffffffff", str(Writer() << hex(0xffffffffffffffffull)));
|
||||
}
|
||||
|
||||
TEST(WriterTest, hexu) {
|
||||
@ -351,6 +361,7 @@ TEST(WriterTest, hexu) {
|
||||
EXPECT_EQ("BABE", str(Writer() << hexu(0xbabeu)));
|
||||
EXPECT_EQ("DEAD", str(Writer() << hexu(0xdeadl)));
|
||||
EXPECT_EQ("BEEF", str(Writer() << hexu(0xbeeful)));
|
||||
EXPECT_EQ("FFFFFFFFFFFFFFFF", str(Writer() << hexu(0xffffffffffffffffull)));
|
||||
}
|
||||
|
||||
class Date {
|
||||
@ -938,7 +949,7 @@ TEST(FormatterTest, FormatShort) {
|
||||
TEST(FormatterTest, FormatInt) {
|
||||
EXPECT_THROW_MSG(Format("{0:v") << 42,
|
||||
FormatError, "unmatched '{' in format");
|
||||
CheckUnknownTypes(42, "doxX", "integer");
|
||||
CheckUnknownTypes(42, "doxXbB", "integer");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatDec) {
|
||||
@ -973,6 +984,9 @@ TEST(FormatterTest, FormatHex) {
|
||||
EXPECT_EQ("90abcdef", str(Format("{0:x}") << 0x90abcdef));
|
||||
EXPECT_EQ("12345678", str(Format("{0:X}") << 0x12345678));
|
||||
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];
|
||||
SPrintf(buffer, "-%x", 0 - static_cast<unsigned>(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));
|
||||
SPrintf(buffer, "%lx", 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) {
|
||||
|
Loading…
Reference in New Issue
Block a user