Commit e0afc418 authored by vitaut's avatar vitaut

Merge pull request #4 from gcflymoto/master

Added support for binary modifier
parents 006a4619 9cc24166
...@@ -115,7 +115,7 @@ The general form of a *standard format specifier* is: ...@@ -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: ...@@ -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: ...@@ -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 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'``. | | none | The same as ``'d'``. |
+---------+----------------------------------------------------------+ +---------+----------------------------------------------------------+
...@@ -349,13 +355,13 @@ Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:: ...@@ -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
......
...@@ -369,6 +369,16 @@ class IntFormatter : public SpecT { ...@@ -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( ...@@ -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'>()); \
} \ } \
...@@ -718,6 +734,25 @@ BasicWriter<Char> &BasicWriter<Char>::operator<<( ...@@ -718,6 +734,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();
...@@ -1155,8 +1190,8 @@ class FormatInt { ...@@ -1155,8 +1190,8 @@ class FormatInt {
} }
explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {} explicit FormatInt(unsigned value) : str_(FormatDecimal(value)) {}
const char *c_str() const { return str_; } inline const char *c_str() const { return str_; }
std::string str() const { return str_; } inline std::string str() const { return str_; }
}; };
/** /**
......
...@@ -325,6 +325,15 @@ TEST(WriterTest, oct) { ...@@ -325,6 +325,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;
...@@ -336,6 +345,8 @@ TEST(WriterTest, hex) { ...@@ -336,6 +345,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) {
...@@ -344,6 +355,7 @@ TEST(WriterTest, hexu) { ...@@ -344,6 +355,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 {
...@@ -931,7 +943,7 @@ TEST(FormatterTest, FormatShort) { ...@@ -931,7 +943,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) {
...@@ -966,6 +978,9 @@ TEST(FormatterTest, FormatHex) { ...@@ -966,6 +978,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));
...@@ -979,6 +994,8 @@ TEST(FormatterTest, FormatHex) { ...@@ -979,6 +994,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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment