summaryrefslogtreecommitdiffstats
path: root/llvm/docs/ProgrammersManual.rst
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/docs/ProgrammersManual.rst')
-rw-r--r--llvm/docs/ProgrammersManual.rst130
1 files changed, 130 insertions, 0 deletions
diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst
index 9c3b424cf97..b3013394831 100644
--- a/llvm/docs/ProgrammersManual.rst
+++ b/llvm/docs/ProgrammersManual.rst
@@ -263,6 +263,136 @@ almost never be stored or mentioned directly. They are intended solely for use
when defining a function which should be able to efficiently accept concatenated
strings.
+.. _formatting_strings:
+
+Formatting strings (the ``formatv`` function)
+---------------------------------------------
+While LLVM doesn't necessarily do a lot of string manipulation and parsing, it
+does do a lot of string formatting. From diagnostic messages, to llvm tool
+outputs such as ``llvm-readobj`` to printing verbose disassembly listings and
+LLDB runtime logging, the need for string formatting is pervasive.
+
+The ``formatv`` is similar in spirit to ``printf``, but uses a different syntax
+which borrows heavily from Python and C#. Unlike ``printf`` it deduces the type
+to be formatted at compile time, so it does not need a format specifier such as
+``%d``. This reduces the mental overhead of trying to construct portable format
+strings, especially for platform-specific types like ``size_t`` or pointer types.
+Unlike both ``printf`` and Python, it additionally fails to compile if LLVM does
+not know how to format the type. These two properties ensure that the function
+is both safer and simpler to use than traditional formatting methods such as
+the ``printf`` family of functions.
+
+Simple formatting
+^^^^^^^^^^^^^^^^^
+
+A call to ``formatv`` involves a single **format string** consisting of 0 or more
+**replacement sequences**, followed by a variable length list of **replacement values**.
+A replacement sequence is a string of the form ``{N[[,align]:style]}``.
+
+``N`` refers to the 0-based index of the argument from the list of replacement
+values. Note that this means it is possible to reference the same parameter
+multiple times, possibly with different style and/or alignment options, in any order.
+
+``align`` is an optional string specifying the width of the field to format
+the value into, and the alignment of the value within the field. It is specified as
+an optional **alignment style** followed by a positive integral **field width**. The
+alignment style can be one of the characters ``-`` (left align), ``=`` (center align),
+or ``+`` (right align). The default is right aligned.
+
+``style`` is an optional string consisting of a type specific that controls the
+formatting of the value. For example, to format a floating point value as a percentage,
+you can use the style option ``P``.
+
+Custom formatting
+^^^^^^^^^^^^^^^^^
+
+There are two ways to customize the formatting behavior for a type.
+
+1. Provide a template specialization of ``llvm::format_provider<T>`` for your
+ type ``T`` with the appropriate static format method.
+
+ .. code-block:: c++
+
+ namespace llvm {
+ template<>
+ struct format_provider<MyFooBar> {
+ static void format(const MyFooBar &V, raw_ostream &Stream, StringRef Style) {
+ // Do whatever is necessary to format `V` into `Stream`
+ }
+ };
+ void foo() {
+ MyFooBar X;
+ std::string S = formatv("{0}", X);
+ }
+ }
+
+ This is a useful extensibility mechanism for adding support for formatting your own
+ custom types with your own custom Style options. But it does not help when you want
+ to extend the mechanism for formatting a type that the library already knows how to
+ format. For that, we need something else.
+
+2. Provide a **format adapter** with a non-static format method.
+
+ .. code-block:: c++
+
+ namespace anything {
+ struct format_int_custom {
+ int N;
+ explicit format_int_custom(int N) : N(N) {}
+ void format(llvm::raw_ostream &Stream, StringRef Style) {
+ // Do whatever is necessary to format ``N`` into ``Stream``
+ }
+ };
+ }
+ namespace llvm {
+ void foo() {
+ std::string S = formatv("{0}", anything::format_int_custom(42));
+ }
+ }
+
+ If the search for a specialization of ``format_provider<T>`` for the given type
+ fails, ``formatv`` will subsequently check the argument for an instance method
+ named ``format`` with the signature described above. If so, it will call the
+ ``format`` method on the argument passing in the specified style. This allows
+ one to provide custom formatting of any type, including one which already has
+ a builtin format provider.
+
+``formatv`` Examples
+^^^^^^^^^^^^^^^^^^^^
+Below is intended to provide an incomplete set of examples demonstrating
+the usage of ``formatv``. More information can be found by reading the
+doxygen documentation or by looking at the unit test suite.
+
+
+.. code-block:: c++
+
+ std::string S;
+ // Simple formatting of basic types and implicit string conversion.
+ S = formatv("{0} ({1:P})", 7, 0.35); // S == "7 (35.00%)"
+
+ // Out-of-order referencing and multi-referencing
+ outs() << formatv("{0} {2} {1} {0}", 1, "test", 3); // prints "1 3 test 1"
+
+ // Left, right, and center alignment
+ S = formatv("{0,7}", 'a'); // S == " a";
+ S = formatv("{0,-7}", 'a'); // S == "a ";
+ S = formatv("{0,=7}", 'a'); // S == " a ";
+ S = formatv("{0,+7}", 'a'); // S == " a";
+
+ // Custom styles
+ S = formatv("{0:N} - {0:x} - {1:E}", 12345, 123908342); // S == "12,345 - 0x3039 - 1.24E8"
+
+ // Adapters
+ S = formatv("{0}", fmt_align(42, AlignStyle::Center, 7)); // S == " 42 "
+ S = formatv("{0}", fmt_repeat("hi", 3)); // S == "hihihi"
+ S = formatv("{0}", fmt_pad("hi", 2, 6)); // S == " hi "
+
+ // Ranges
+ std::vector<int> V = {8, 9, 10};
+ S = formatv("{0}", make_range(V.begin(), V.end())); // S == "8, 9, 10"
+ S = formatv("{0:$[+]}", make_range(V.begin(), V.end())); // S == "8+9+10"
+ S = formatv("{0:$[ + ]@[x]}", make_range(V.begin(), V.end())); // S == "0x8 + 0x9 + 0xA"
+
.. _error_apis:
Error handling
OpenPOWER on IntegriCloud