Move str and c_str to the fmt namespace and document the API.

This commit is contained in:
Victor Zverovich 2013-01-13 07:50:28 -08:00
parent aba9e15021
commit de580f6930
2 changed files with 47 additions and 115 deletions

View File

@ -19,81 +19,9 @@ String Formatting
.. doxygenclass:: format::StringRef
:members:
.. ifconfig:: False
.. class:: Formatter
In addition, the :class:`Formatter` defines a number of methods that are
intended to be replaced by subclasses:
.. method:: parse(format_string)
Loop over the format_string and return an iterable of tuples
(*literal_text*, *field_name*, *format_spec*, *conversion*). This is used
by :meth:`vformat` to break the string into either literal text, or
replacement fields.
The values in the tuple conceptually represent a span of literal text
followed by a single replacement field. If there is no literal text
(which can happen if two replacement fields occur consecutively), then
*literal_text* will be a zero-length string. If there is no replacement
field, then the values of *field_name*, *format_spec* and *conversion*
will be ``None``.
.. method:: get_field(field_name, args, kwargs)
Given *field_name* as returned by :meth:`parse` (see above), convert it to
an object to be formatted. Returns a tuple (obj, used_key). The default
version takes strings of the form defined in :pep:`3101`, such as
"0[name]" or "label.title". *args* and *kwargs* are as passed in to
:meth:`vformat`. The return value *used_key* has the same meaning as the
*key* parameter to :meth:`get_value`.
.. method:: get_value(key, args, kwargs)
Retrieve a given field value. The *key* argument will be either an
integer or a string. If it is an integer, it represents the index of the
positional argument in *args*; if it is a string, then it represents a
named argument in *kwargs*.
The *args* parameter is set to the list of positional arguments to
:meth:`vformat`, and the *kwargs* parameter is set to the dictionary of
keyword arguments.
For compound field names, these functions are only called for the first
component of the field name; Subsequent components are handled through
normal attribute and indexing operations.
So for example, the field expression '0.name' would cause
:meth:`get_value` to be called with a *key* argument of 0. The ``name``
attribute will be looked up after :meth:`get_value` returns by calling the
built-in :func:`getattr` function.
If the index or keyword refers to an item that does not exist, then an
:exc:`IndexError` or :exc:`KeyError` should be raised.
.. method:: check_unused_args(used_args, args, kwargs)
Implement checking for unused arguments if desired. The arguments to this
function is the set of all argument keys that were actually referred to in
the format string (integers for positional arguments, and strings for
named arguments), and a reference to the *args* and *kwargs* that was
passed to vformat. The set of unused args can be calculated from these
parameters. :meth:`check_unused_args` is assumed to raise an exception if
the check fails.
.. method:: format_field(value, format_spec)
:meth:`format_field` simply calls the global :func:`format` built-in. The
method is provided so that subclasses can override it.
.. method:: convert_field(value, conversion)
Converts the value (returned by :meth:`get_field`) given a conversion type
(as in the tuple returned by the :meth:`parse` method). The default
version understands 's' (str), 'r' (repr) and 'a' (ascii) conversion
types.
.. doxygenfunction:: format::str
.. doxygenfunction:: format::c_str
.. _formatstrings:

View File

@ -149,6 +149,7 @@ template <>
struct IntTraits<unsigned long> : UnsignedIntTraits<unsigned long> {};
class ArgInserter;
class FormatterProxy;
}
/**
@ -287,6 +288,7 @@ class IntFormatter : public SpecT {
T value() const { return value_; }
};
// Returns an integer formatter that formats value in the octal base.
// internal::IntTraits<T>::Type is used instead of T to avoid instantiating
// the function for types smaller than int similarly to enable_if.
template <typename T>
@ -500,6 +502,13 @@ BasicFormatter &BasicFormatter::operator<<(const IntFormatter<T, Spec> &f) {
return *this;
}
// The default formatting function.
template <typename T>
void Format(BasicFormatter &f, const FormatSpec &spec, const T &value) {
std::ostringstream os;
os << value;
f.Write(os.str(), spec);
}
/**
\rst
@ -635,6 +644,7 @@ class Formatter : public BasicFormatter {
int next_arg_index_;
friend class internal::ArgInserter;
friend class internal::FormatterProxy;
void Add(const Arg &arg) {
args_.push_back(&arg);
@ -644,7 +654,10 @@ class Formatter : public BasicFormatter {
// Formats an argument of a custom type, such as a user-defined class.
template <typename T>
void FormatCustomArg(const void *arg, const FormatSpec &spec);
void FormatCustomArg(const void *arg, const FormatSpec &spec) {
BasicFormatter &f = *this;
Format(f, spec, *static_cast<const T*>(arg));
}
unsigned ParseUInt(const char *&s) const;
@ -674,8 +687,24 @@ class Formatter : public BasicFormatter {
internal::ArgInserter operator()(StringRef format);
};
std::string str(internal::FormatterProxy p);
const char *c_str(internal::FormatterProxy p);
namespace internal {
using format::str;
using format::c_str;
struct FormatterProxy {
Formatter *formatter;
explicit FormatterProxy(Formatter *f) : formatter(f) {}
Formatter *Format() {
formatter->CompleteFormatting();
return formatter;
}
};
// This is a transient object that normally exists only as a temporary
// returned by one of the formatting functions. It stores a reference
// to a formatter and provides operator<< that feeds arguments to the
@ -718,16 +747,6 @@ class ArgInserter {
void ResetFormatter() const { formatter_ = 0; }
struct Proxy {
Formatter *formatter;
explicit Proxy(Formatter *f) : formatter(f) {}
Formatter *Format() {
formatter->CompleteFormatting();
return formatter;
}
};
public:
~ArgInserter() {
if (formatter_)
@ -741,47 +760,32 @@ class ArgInserter {
return *this;
}
operator Proxy() {
operator FormatterProxy() {
Formatter *f = formatter_;
formatter_ = 0;
return Proxy(f);
return FormatterProxy(f);
}
operator StringRef() {
const Formatter *f = Format();
return StringRef(f->c_str(), f->size());
}
// Performs formatting and returns a std::string with the output.
friend std::string str(Proxy p) {
return p.Format()->str();
}
// Performs formatting and returns a C string with the output.
friend const char *c_str(Proxy p) {
return p.Format()->c_str();
}
};
std::string str(ArgInserter::Proxy p);
const char *c_str(ArgInserter::Proxy p);
}
using format::internal::str;
using format::internal::c_str;
// The default formatting function.
template <typename T>
void Format(BasicFormatter &f, const FormatSpec &spec, const T &value) {
std::ostringstream os;
os << value;
f.Write(os.str(), spec);
/**
Returns the content of the output buffer as an `std::string`.
*/
inline std::string str(internal::FormatterProxy p) {
return p.Format()->str();
}
template <typename T>
void Formatter::FormatCustomArg(const void *arg, const FormatSpec &spec) {
BasicFormatter &f = *this;
Format(f, spec, *static_cast<const T*>(arg));
/**
Returns a pointer to the output buffer content with terminating null
character appended.
*/
inline const char *c_str(internal::FormatterProxy p) {
return p.Format()->c_str();
}
inline internal::ArgInserter Formatter::operator()(StringRef format) {
@ -872,8 +876,8 @@ class TempFormatter : public internal::ArgInserter {
literal text and replacement fields surrounded by braces ``{}``.
The formatter object replaces the fields with formatted arguments
and stores the output in a memory buffer. The content of the buffer can
be converted to ``std::string`` with :meth:`str` or accessed as a C string
with :meth:`c_str`.
be converted to ``std::string`` with :cpp:func:`format::str()` or
accessed as a C string with :cpp:func:`format::c_str()`.
**Example**::