Merge pull request #4 from gcflymoto/master

Added support for binary modifier
This commit is contained in:
vitaut 2013-11-14 07:57:16 -08:00
commit e0afc418b3
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: "+" | "-" | " "
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 lower-case 0b if a prefix is requested. |
+---------+----------------------------------------------------------+
| ``'B'`` | Binary format. Outputs the number in base 2, using |
| | a upper-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

View File

@ -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'>()); \
} \
@ -718,6 +734,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();
@ -1155,8 +1190,8 @@ class FormatInt {
}
explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {}
const char *c_str() const { return str_; }
std::string str() const { return str_; }
inline const char *c_str() const { return str_; }
inline std::string str() const { return str_; }
};
/**

View File

@ -325,6 +325,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;
@ -336,6 +345,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) {
@ -344,6 +355,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 {
@ -931,7 +943,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) {
@ -966,6 +978,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));
@ -979,6 +994,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) {