FastFormat 0.5.8 is released, containing a fix to ensure that a replacement parameter with a maximum width of 0 truncates (completely) the resulting field. For example:
string_t sink;
ff::fmt(sink, "{0,,0}", "abc");
assert("" == sink);
Sunday, June 6, 2010
Wednesday, June 2, 2010
format_iterator on Dr Dobb's
Dr. Dobb's have just published a new article, "C++ and format_iterator", describing the design and implementation of the FastFormat library's format_iterator component.
The article describes how FastFormat's flexiblity, expressiveness and type-safety has been combined with the output iterator concept to produce the fastformat::format_iterator component. Applying STL-extension techniques described in Extended STL, volume 1, the format_iterator() component is able to create an output iterator that can receive arbitrate types, apply a format string or arbitrary complexity, and write to an arbitrary sink, as in:
#include <fastformat/ff.hpp>
#include <fastformat/iterators/format_iterator.hpp>
#include <fastformat/sinks/ostream.hpp>
int numbers[] = { -2, -1, 0, 1, 2 };
char const* strings[] = { "abc", "def", "ghi" };
std::string prefix = "\t";
char const* suffix = "\n";
std::copy(
numbers, numbers + 5
, ff::format_iterator(std::cout, "[{0}]"));
// outputs "[-2][-1][0][1][2]"
std::copy(
strings, strings + 3
, ff::format_iterator(std::cout, "{1}'{0}'{2}", prefix, suffix));
// outputs:
// 'abc'
// 'def'
// 'ghi'
This is the fourth article on the FastFormat library, following on from the introductory series of three published in ACCU's Overload magazine:
The article describes how FastFormat's flexiblity, expressiveness and type-safety has been combined with the output iterator concept to produce the fastformat::format_iterator component. Applying STL-extension techniques described in Extended STL, volume 1, the format_iterator() component is able to create an output iterator that can receive arbitrate types, apply a format string or arbitrary complexity, and write to an arbitrary sink, as in:
#include <fastformat/ff.hpp>
#include <fastformat/iterators/format_iterator.hpp>
#include <fastformat/sinks/ostream.hpp>
int numbers[] = { -2, -1, 0, 1, 2 };
char const* strings[] = { "abc", "def", "ghi" };
std::string prefix = "\t";
char const* suffix = "\n";
std::copy(
numbers, numbers + 5
, ff::format_iterator(std::cout, "[{0}]"));
// outputs "[-2][-1][0][1][2]"
std::copy(
strings, strings + 3
, ff::format_iterator(std::cout, "{1}'{0}'{2}", prefix, suffix));
// outputs:
// 'abc'
// 'def'
// 'ghi'
This is the fourth article on the FastFormat library, following on from the introductory series of three published in ACCU's Overload magazine:
Labels:
ACCU,
article,
DDJ,
Dr. Dobb's,
FastFormat,
format_iterator,
Overload
Wednesday, May 12, 2010
Beware of the \r\n gotcha on Windows
If (as I have just done) you decide to FastFormat to prepare intermediate text for output, and your program runs on Windows, beware of the writeln() and fmtln() API functions. Consider the following code
This occurs because the underlying C standard library expands each standard end-of-line (EOL) character \n to the Windows-specific EOL sequence \r\n.
Instead, use the *ln() functions on the output, as in:
std::string s;
ff::writeln(s, "hello"); // s => "hello\r\n"
ff::write(std::cout, s); // writes "hello\r\r\n"
This occurs because the underlying C standard library expands each standard end-of-line (EOL) character \n to the Windows-specific EOL sequence \r\n.
Instead, use the *ln() functions on the output, as in:
ff::write(s, "hello"); // s => "hello"
ff::writeln(std::cout, s); // writes "hello\r\n"
Remember that FastFormat "appends" to sinks
A user recently posted a note on the Help forum, suggesting that FastFormat was up to 100 times slower than MFC's CString::Format(). Thankfully that's not the case, and FastFormat appears to be faster than CString::Format() in even the simple case suggested.
The reason this appeared to be so was because the test program reused the same CString instance in each call to fastformat::fmt(), resulting in concatenation to a huge size. The fault here is no doubt mine, for not having made the nature of FastFormat's formatting more clear in the documentation. So I'll try and do so briefly now.
All FastFormat formatting is appending, and this is a deliberate design decision. In part, this is to achieve consistency between immediate sinks such as strings, and stream sinks (such as std::cout, stdout, ...). Also, it's useful to be able to break apart large or complex formatting operations into statements, without sacrificing performance or expressiveness. (Note: there'll always a small performance penalty for such things, but it will be insignificant in most cases where the size and complexity of the statement demands breaking up.) Consider the following example:
The same can be achieved as follows:
In real-world cases, such clarity may be worth paying a few more extra cycles for.
The reason this appeared to be so was because the test program reused the same CString instance in each call to fastformat::fmt(), resulting in concatenation to a huge size. The fault here is no doubt mine, for not having made the nature of FastFormat's formatting more clear in the documentation. So I'll try and do so briefly now.
All FastFormat formatting is appending, and this is a deliberate design decision. In part, this is to achieve consistency between immediate sinks such as strings, and stream sinks (such as std::cout, stdout, ...). Also, it's useful to be able to break apart large or complex formatting operations into statements, without sacrificing performance or expressiveness. (Note: there'll always a small performance penalty for such things, but it will be insignificant in most cases where the size and complexity of the statement demands breaking up.) Consider the following example:
std::string s;
ff::fmt(s, "{0};{1};{2}|{3};{4};{5}|{6};{7};{8}|{9};{10};{11}|", a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
The same can be achieved as follows:
std::string s;
ff::fmt(s, "{0};{1};{2}|", a0, a1, a2);
ff::fmt(s, "{0};{1};{2}|", a3, a4, a5);
ff::fmt(s, "{0};{1};{2}|", a6, a7, a8);
ff::fmt(s, "{0};{1};{2}|", a9, a10, a11);
In real-world cases, such clarity may be worth paying a few more extra cycles for.
Sunday, March 14, 2010
Sink creator function
Just started working on a creator function, called to_sink(), which will allow sinks to be generated in situ from free functions. A little like a bind, just not as complicated (I hope).
An example of use would be:
Hopefully I should have something releasable in the next week or so.
An example of use would be:
std::copy(files.begin(), files.end()
, ff::format_iterator(ff::to_sink(::OutputDebugString)
, "\t{0}\n"));, ff::format_iterator(ff::to_sink(::OutputDebugString)
Hopefully I should have something releasable in the next week or so.
Tuesday, March 9, 2010
FastFormat 0.5.4 released: VC++ 10 support
FastFormat now supports Visual C++ 10. Note that it requires STLSoft 1.9.96 (or later).
Monday, March 8, 2010
VC++ 10 support imminent
Currently adding VC++ support to STLSoft. Should have FastFormat up and working automatically.
Labels:
FastFormat,
STLSoft,
Visual C++,
Visual C++ 10
Subscribe to:
Posts (Atom)