diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/_templates/layout.html | 2 | ||||
-rw-r--r-- | doc/api.rst | 115 | ||||
-rwxr-xr-x | doc/build.py | 2 | ||||
-rw-r--r-- | doc/index.rst | 50 | ||||
-rw-r--r-- | doc/syntax.rst | 17 | ||||
-rw-r--r-- | doc/usage.rst | 12 |
6 files changed, 128 insertions, 70 deletions
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html index ed19bcd3..d5f4b70d 100644 --- a/doc/_templates/layout.html +++ b/doc/_templates/layout.html @@ -84,7 +84,7 @@ <div class="jumbotron"> <div class="tb-container"> <h1>{fmt}</h1> - <p class="lead">Small, safe and fast formatting library</p> + <p class="lead">A modern formatting library</p> <div class="btn-group" role="group"> {% set name = 'fmt' if version.split('.')[0]|int >= 3 else 'cppformat' %} <a class="btn btn-success" diff --git a/doc/api.rst b/doc/api.rst index b5adf4b3..0834a874 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -10,12 +10,14 @@ The {fmt} library API consists of the following parts: facilities and a lightweight subset of formatting functions * :ref:`fmt/format.h <format-api>`: the full format API providing compile-time format string checks, output iterator and user-defined type support +* :ref:`fmt/ranges.h <ranges-api>`: additional formatting support for ranges + and tuples * :ref:`fmt/chrono.h <chrono-api>`: date and time formatting * :ref:`fmt/ostream.h <ostream-api>`: ``std::ostream`` support * :ref:`fmt/printf.h <printf-api>`: ``printf`` formatting All functions and types provided by the library reside in namespace ``fmt`` and -macros have prefix ``FMT_`` or ``fmt``. +macros have prefix ``FMT_``. .. _core-api: @@ -23,7 +25,8 @@ Core API ======== ``fmt/core.h`` defines the core API which provides argument handling facilities -and a lightweight subset of formatting functions. +and a lightweight subset of formatting functions. In the header-only mode +include ``fmt/format.h`` instead of ``fmt/core.h``. The following functions use :ref:`format string syntax <syntax>` similar to that of Python's `str.format @@ -49,7 +52,6 @@ participate in an overload resolution if the latter is not a string. .. doxygenfunction:: print(std::FILE *, const S&, Args&&...) .. doxygenfunction:: vprint(std::FILE *, string_view, format_args) -.. doxygenfunction:: vprint(std::FILE *, wstring_view, wformat_args) Named Arguments --------------- @@ -94,8 +96,11 @@ string checks, output iterator and user-defined type support. Compile-time Format String Checks --------------------------------- +Compile-time checks are supported for built-in and string types as well as +user-defined types with ``constexpr`` ``parse`` functions in their ``formatter`` +specializations. + .. doxygendefine:: FMT_STRING -.. doxygendefine:: fmt Formatting User-defined Types ----------------------------- @@ -107,32 +112,56 @@ template and implement ``parse`` and ``format`` methods:: struct point { double x, y; }; - namespace fmt { template <> - struct formatter<point> { - template <typename ParseContext> - constexpr auto parse(ParseContext &ctx) { return ctx.begin(); } + struct fmt::formatter<point> { + // Presentation format: 'f' - fixed, 'e' - exponential. + char presentation = 'f'; + + // Parses format specifications of the form ['f' | 'e']. + constexpr auto parse(format_parse_context& ctx) { + // [ctx.begin(), ctx.end()) is a character range that contains a part of + // the format string starting from the format specifications to be parsed, + // e.g. in + // + // fmt::format("{:f} - point of interest", point{1, 2}); + // + // the range will contain "f} - point of interest". The formatter should + // parse specifiers until '}' or the end of the range. In this example + // the formatter should parse the 'f' specifier and return an iterator + // pointing to '}'. + + // Parse the presentation format and store it in the formatter: + auto it = ctx.begin(), end = ctx.end(); + if (it != end && (*it == 'f' || *it == 'e')) presentation = *it++; + + // Check if reached the end of the range: + if (it != end && *it != '}') + throw format_error("invalid format"); + + // Return an iterator past the end of the parsed range: + return it; + } + // Formats the point p using the parsed format specification (presentation) + // stored in this formatter. template <typename FormatContext> - auto format(const point &p, FormatContext &ctx) { - return format_to(ctx.out(), "({:.1f}, {:.1f})", p.x, p.y); + auto format(const point& p, FormatContext& ctx) { + // ctx.out() is an output iterator to write to. + return format_to( + ctx.out(), + presentation == 'f' ? "({:.1f}, {:.1f})" : "({:.1e}, {:.1e})", + p.x, p.y); } }; - } Then you can pass objects of type ``point`` to any formatting function:: point p = {1, 2}; - std::string s = fmt::format("{}", p); + std::string s = fmt::format("{:f}", p); // s == "(1.0, 2.0)" -In the example above the ``formatter<point>::parse`` function ignores the -contents of the format string referred to by ``ctx.begin()`` so the object will -always be formatted in the same way. See ``formatter<tm>::parse`` in -:file:`fmt/chrono.h` for an advanced example of how to parse the format string and -customize the formatted output. - -You can also reuse existing formatters, for example:: +You can also reuse existing formatters via inheritance or composition, for +example:: enum class color {red, green, blue}; @@ -140,7 +169,7 @@ You can also reuse existing formatters, for example:: struct fmt::formatter<color>: formatter<string_view> { // parse is inherited from formatter<string_view>. template <typename FormatContext> - auto format(color c, FormatContext &ctx) { + auto format(color c, FormatContext& ctx) { string_view name = "unknown"; switch (c) { case color::red: name = "red"; break; @@ -180,6 +209,9 @@ You can also write a formatter for a hierarchy of classes:: fmt::print("{}", a); // prints "B" } +.. doxygenclass:: fmt::basic_format_parse_context + :members: + Output Iterator Support ----------------------- @@ -263,7 +295,7 @@ allocator:: template <typename ...Args> inline custom_string format(custom_allocator alloc, fmt::string_view format_str, - const Args & ... args) { + const Args& ... args) { return vformat(alloc, format_str, fmt::make_format_args(args...)); } @@ -278,21 +310,21 @@ Custom Formatting of Built-in Types It is possible to change the way arguments are formatted by providing a custom argument formatter class:: - using arg_formatter = - fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>>; + using arg_formatter = fmt::arg_formatter<fmt::buffer_range<char>>; // A custom argument formatter that formats negative integers as unsigned // with the ``x`` format specifier. class custom_arg_formatter : public arg_formatter { public: - custom_arg_formatter(fmt::format_context &ctx, - fmt::format_specs *spec = nullptr) - : arg_formatter(ctx, spec) {} + custom_arg_formatter(fmt::format_context& ctx, + fmt::format_parse_context* parse_ctx = nullptr, + fmt::format_specs* spec = nullptr) + : arg_formatter(ctx, parse_ctx, spec) {} using arg_formatter::operator(); auto operator()(int value) { - if (spec().type() == 'x') + if (specs() && specs()->type == 'x') return (*this)(static_cast<unsigned>(value)); // convert to unsigned and format return arg_formatter::operator()(value); } @@ -307,7 +339,7 @@ custom argument formatter class:: template <typename ...Args> inline std::string custom_format( - fmt::string_view format_str, const Args &... args) { + fmt::string_view format_str, const Args&... args) { return custom_vformat(format_str, fmt::make_format_args(args...)); } @@ -316,6 +348,31 @@ custom argument formatter class:: .. doxygenclass:: fmt::arg_formatter :members: +.. _ranges-api: + +Ranges and Tuple Formatting +=========================== + +The library also supports convenient formatting of ranges and tuples:: + + #include <fmt/ranges.h> + + std::tuple<char, int, float> t{'a', 1, 2.0f}; + // Prints "('a', 1, 2.0)" + fmt::print("{}", t); + + +NOTE: currently, the overload of ``fmt::join`` for iterables exists in the main +``format.h`` header, but expect this to change in the future. + +Using ``fmt::join``, you can separate tuple elements with a custom separator:: + + #include <fmt/ranges.h> + + std::tuple<int, char> t = {1, 'a'}; + // Prints "1, a" + fmt::print("{}", fmt::join(t, ", ")); + .. _chrono-api: Date and Time Formatting @@ -349,7 +406,7 @@ user-defined types that have overloaded ``operator<<``:: public: date(int year, int month, int day): year_(year), month_(month), day_(day) {} - friend std::ostream &operator<<(std::ostream &os, const date &d) { + friend std::ostream& operator<<(std::ostream& os, const date& d) { return os << d.year_ << '-' << d.month_ << '-' << d.day_; } }; diff --git a/doc/build.py b/doc/build.py index fb4f5469..e8f5f396 100755 --- a/doc/build.py +++ b/doc/build.py @@ -6,7 +6,7 @@ import errno, os, shutil, sys, tempfile from subprocess import check_call, check_output, CalledProcessError, Popen, PIPE from distutils.version import LooseVersion -versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0', '5.2.0', '5.2.1', '5.3.0', '6.0.0'] +versions = ['1.0.0', '1.1.0', '2.0.0', '3.0.2', '4.0.0', '4.1.0', '5.0.0', '5.1.0', '5.2.0', '5.2.1', '5.3.0', '6.0.0', '6.1.0'] def pip_install(package, commit=None, **kwargs): "Install package using pip." diff --git a/doc/index.rst b/doc/index.rst index 9480ff69..cbc9154d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,17 +1,18 @@ Overview ======== -**fmt** (formerly cppformat) is an open-source formatting library. -It can be used as a fast and safe alternative to printf and IOStreams. +**{fmt}** is an open-source formatting library providing a fast and safe +alternative to C stdio and C++ iostreams. .. raw:: html <div class="panel panel-default"> <div class="panel-heading">What users say:</div> <div class="panel-body"> - Thanks for creating this library. It’s been a hole in C++ for a long - time. I’ve used both boost::format and loki::SPrintf, and neither felt - like the right answer. This does. + Thanks for creating this library. It’s been a hole in C++ for + aa long time. I’ve used both <code>boost::format</code> and + <code>loki::SPrintf</code>, and neither felt like the right answer. + This does. </div> </div> @@ -20,12 +21,13 @@ It can be used as a fast and safe alternative to printf and IOStreams. Format API ---------- -The replacement-based Format API provides a safe alternative to ``printf``, -``sprintf`` and friends with comparable or `better performance -<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_. +The format API is similar in spirit to the C ``printf`` family of function but +is safer, simpler and serveral times `faster +<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_ +than common standard library implementations. The `format string syntax <syntax.html>`_ is similar to the one used by -`str.format <http://docs.python.org/3/library/stdtypes.html#str.format>`_ -in Python: +`str.format <http://docs.python.org/3/library/stdtypes.html#str.format>`_ in +Python: .. code:: c++ @@ -60,7 +62,7 @@ The Format API also supports positional arguments useful for localization: fmt::print("I'd rather be {1} than {0}.", "right", "happy"); Named arguments can be created with ``fmt::arg``. This makes it easier to track -what goes where when multiple values are being inserted: +what goes where when multiple arguments are being formatted: .. code:: c++ @@ -72,21 +74,10 @@ an alternative, slightly terser syntax for named arguments: .. code:: c++ + using namespace fmt::literals; fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.", "name"_a="World", "number"_a=42); -The ``_format`` suffix may be used to format string literals similar to Python: - -.. code:: c++ - - std::string message = "{0}{1}{0}"_format("abra", "cad"); - -Other than the placement of the format string on the left of the operator, -``_format`` is functionally identical to ``fmt::format``. In order to use the -literal operators, they must be made visible with the directive -``using namespace fmt::literals;``. Note that this brings in only ``_a`` and -``_format`` but nothing else from the ``fmt`` namespace. - .. _safety: Safety @@ -106,11 +97,10 @@ string", because the argument ``"forty-two"`` is a string while the format code .. code:: c++ - format(fmt("The answer is {:d}"), "forty-two"); + format(FMT_STRING("The answer is {:d}"), "forty-two"); reports a compile-time error for the same reason on compilers that support -relaxed ``constexpr``. See `here <api.html#c.fmt>`_ for how to enable -compile-time checks. +relaxed ``constexpr``. See `here <api.html#c.fmt>`_ for details. The following code @@ -178,13 +168,13 @@ The library is highly portable and relies only on a small set of C++11 features: * alias templates These are available since GCC 4.8, Clang 3.0 and MSVC 19.0 (2015). For older -compilers use fmt `version 4.x +compilers use {fmt} `version 4.x <https://github.com/fmtlib/fmt/releases/tag/4.1.0>`_ which continues to be maintained and only requires C++98. The output of all formatting functions is consistent across platforms. In particular, formatting a floating-point infinity always gives ``inf`` while the -output of ``printf`` is platform-dependent in this case. For example, +output of ``printf`` is platform-dependent. For example, .. code:: @@ -197,9 +187,9 @@ always prints ``inf``. Ease of Use ----------- -fmt has a small self-contained code base with the core library consisting of +{fmt} has a small self-contained code base with the core library consisting of just three header files and no external dependencies. -A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows +A permissive MIT `license <https://github.com/fmtlib/fmt#license>`_ allows using the library both in open-source and commercial projects. .. raw:: html diff --git a/doc/syntax.rst b/doc/syntax.rst index a6bddf6b..1f25dacf 100644 --- a/doc/syntax.rst +++ b/doc/syntax.rst @@ -101,11 +101,6 @@ The meaning of the various alignment options is as follows: | ``'>'`` | Forces the field to be right-aligned within the | | | available space (this is the default for numbers). | +---------+----------------------------------------------------------+ -| ``'='`` | Forces the padding to be placed after the sign (if any) | -| | but before the digits. This is used for printing fields | -| | in the form '+000000120'. This alignment option is only | -| | valid for numeric types. | -+---------+----------------------------------------------------------+ | ``'^'`` | Forces the field to be centered within the available | | | space. | +---------+----------------------------------------------------------+ @@ -154,9 +149,11 @@ conversions, trailing zeros are not removed from the result. *width* is a decimal integer defining the minimum field width. If not specified, then the field width will be determined by the content. -Preceding the *width* field by a zero (``'0'``) character enables -sign-aware zero-padding for numeric types. This is equivalent to a *fill* -character of ``'0'`` with an *alignment* type of ``'='``. +Preceding the *width* field by a zero (``'0'``) character enables sign-aware +zero-padding for numeric types. It forces the padding to be placed after the +sign or base (if any) but before the digits. This is used for printing fields in +the form '+000000120'. This option is only valid for numeric types and it has no +effect on formatting of infinity and NaN. The *precision* is a decimal number indicating how many digits should be displayed after the decimal point for a floating-point value formatted with @@ -264,6 +261,10 @@ The available presentation types for floating-point values are: | | ``'E'`` if the number gets too large. The | | | representations of infinity and NaN are uppercased, too. | +---------+----------------------------------------------------------+ +| ``'n'`` | Number. This is the same as ``'g'``, except that it uses | +| | the current locale setting to insert the appropriate | +| | number separator characters. | ++---------+----------------------------------------------------------+ | ``'%'`` | Fixed point as a percentage. This is similar to ``'f'``, | | | but the argument is multiplied by 100 and a percent sign | | | ``%`` is appended. | diff --git a/doc/usage.rst b/doc/usage.rst index e71629c5..dacb4f03 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -103,7 +103,17 @@ the previous section. Then compile the ``doc`` target/project, for example:: make doc This will generate the HTML documentation in ``doc/html``. - + +Conda +===== + +fmt can be installed on Linux, macOS and Windows with +`Conda <https://docs.conda.io/en/latest/>`__, using its +`conda-forge <https://conda-forge.org>`__ +`package <https://github.com/conda-forge/fmt-feedstock>`__, as follows:: + + conda install -c conda-forge fmt + Android NDK =========== |