diff --git a/doc/format.rst b/doc/format.rst index f01f6e0f..0f2ce367 100644 --- a/doc/format.rst +++ b/doc/format.rst @@ -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: diff --git a/format.h b/format.h index 11296a93..78eed074 100644 --- a/format.h +++ b/format.h @@ -149,6 +149,7 @@ template <> struct IntTraits : UnsignedIntTraits {}; 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::Type is used instead of T to avoid instantiating // the function for types smaller than int similarly to enable_if. template @@ -500,6 +502,13 @@ BasicFormatter &BasicFormatter::operator<<(const IntFormatter &f) { return *this; } +// The default formatting function. +template +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 - void FormatCustomArg(const void *arg, const FormatSpec &spec); + void FormatCustomArg(const void *arg, const FormatSpec &spec) { + BasicFormatter &f = *this; + Format(f, spec, *static_cast(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 -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 -void Formatter::FormatCustomArg(const void *arg, const FormatSpec &spec) { - BasicFormatter &f = *this; - Format(f, spec, *static_cast(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**::