mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 06:09:19 +00:00
Bug 1717448 - Add some documentation about using {fmt} in Gecko. r=nika
Differential Revision: https://phabricator.services.mozilla.com/D217300
This commit is contained in:
parent
a42519fc01
commit
8e311122f6
118
xpcom/docs/fmt-in-gecko.md
Normal file
118
xpcom/docs/fmt-in-gecko.md
Normal file
@ -0,0 +1,118 @@
|
||||
# `{fmt}` in Gecko
|
||||
|
||||
[`{fmt}`](https://fmt.dev/) is a library implementation of C++20's [`std::format`](https://en.cppreference.com/w/cpp/header/format) formatting API which enables type-informed string formatting. Unlike `printf` this format string style does not require specifying the types of each format parameter in the format string. For example, instead of:
|
||||
|
||||
```c++
|
||||
#include <mozilla/Sprintf.h>
|
||||
#include <inttypes.h>
|
||||
// ...
|
||||
char buf[1024];
|
||||
int64_t a = 123;
|
||||
uint64_t a = 456;
|
||||
auto literal = "A literal"_ns;
|
||||
mozilla::SprintfBuf(buf, 1024,
|
||||
"Formatting a number: %" PRId64
|
||||
" and another one: " PRIu64
|
||||
", and finally a string: %s",
|
||||
a, b, literal.get());
|
||||
```
|
||||
|
||||
one can do:
|
||||
|
||||
```c++
|
||||
#include <fmt/format.h>
|
||||
// ...
|
||||
char buf[1024];
|
||||
int64_t a = 123;
|
||||
uint64_t a = 456;
|
||||
auto literal = "A literal"_ns;
|
||||
fmt::format_to_n(res, 1024,
|
||||
FMT_STRING("Formatting a number: {} and another one: {} "
|
||||
"and finally a string: {}"),
|
||||
a, b, literal.get());
|
||||
```
|
||||
|
||||
|
||||
# User-defined types
|
||||
|
||||
Formatting a [user-defined type](https://fmt.dev/11.0/api/#formatting-user-defined-types) can be done once, and then used with all sorts of formatting function in `{fmt}`. Given an example object:
|
||||
|
||||
```c++
|
||||
struct POD {
|
||||
double mA;
|
||||
uint64_t mB;
|
||||
};
|
||||
```
|
||||
|
||||
one can write a custom formatter like so:
|
||||
|
||||
```c++
|
||||
auto format_as(POD aInstance) -> std::string {
|
||||
return fmt::format(FMT_STRING("POD: mA: {}, mB: {}"), aInstance.mA,
|
||||
aInstance.mB);
|
||||
}
|
||||
```
|
||||
|
||||
and use it as expected in a variety of ways:
|
||||
|
||||
```c++
|
||||
char bufFmt[1024] = {};
|
||||
|
||||
POD p{4.3, 8};
|
||||
auto [out, size] = fmt::format_to(bufFmt, "{}", p);
|
||||
*out = 0; // Write the null terminator
|
||||
|
||||
assert(!strcmp("POD: mA: 4.3, mB: 8", bufFmt));
|
||||
fmt::println(FMT_STRING("### debug: {}"), p);
|
||||
fmt::print(stderr, FMT_STRING("### debug to stderr {}\n"), p);
|
||||
MOZ_LOG_FMT(gLogModule, "Important: {}", p);
|
||||
```
|
||||
|
||||
# Formatting sequences
|
||||
|
||||
Containers that can work with with range-based for-loop can be formatted easily:
|
||||
|
||||
```c++
|
||||
nsTArray<uint8_t> array(4);
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
array.AppendElement((123 * 5 * (i+1)) % 255);
|
||||
}
|
||||
auto [out, size] = fmt::format_to(bufFmt, FMT_STRING("{:#04x}"), fmt::join(array, ", "));
|
||||
*out = 0; // Write the null terminator
|
||||
ASSERT_STREQ("0x69, 0xd2, 0x3c, 0xa5", bufFmt);
|
||||
```
|
||||
|
||||
# `MOZ_LOG` integration
|
||||
|
||||
`MOZ_LOG_FMT` is like `MOZ_LOG`, but takes an `{fmt}`-style format string:
|
||||
|
||||
```c++
|
||||
MOZ_LOG_FMT(gLogModule, "{}x{} = {}", 3, 3, 3*3);
|
||||
```
|
||||
|
||||
Unlike with `MOZ_LOG`, it is unnecessary to put an extra pair of parenthesis around the format and argument list.
|
||||
|
||||
# `ns*String` integration
|
||||
|
||||
It is possible to append an `{fmt}`-style format string to an `nsString` like so:
|
||||
|
||||
```c++
|
||||
nsCString aLovelyString("Here is a value: ");
|
||||
aLovelyString.AppendFmt(FMT_SRING("{}"), 4);
|
||||
|
||||
nsString aLovelyWideString(u"Here are two values: ");
|
||||
aLovelyString.AppendFmt(FMT_SRING(u"{}, {}"), 4, u"wide");
|
||||
```
|
||||
|
||||
Or directly use `nsFmt[C]String`:
|
||||
|
||||
```c++
|
||||
nsFmtCString str(FMT_STRING("{},{},{},{}"), 1, 1, 2, 3);
|
||||
nsFmtString str(FMT_STRING(u"{},{},{},{}"), 1, 1, 2, u"wide string");
|
||||
// use it as usual
|
||||
```
|
||||
|
||||
# Useful links
|
||||
|
||||
- The syntax of `{fmt}` format string: <https://fmt.dev/latest/syntax/>
|
||||
- The complete API of the library: <https://fmt.dev/latest/api/>
|
@ -38,3 +38,4 @@ Writing new XPCOM interfaces/classes
|
||||
xpidl
|
||||
writing-xpcom-interface
|
||||
cc-macros
|
||||
fmt-in-gecko.md
|
||||
|
@ -443,6 +443,12 @@ A basic interface is provided in the form of 2 macros and an enum class.
|
||||
| | * message: A printf-style message to output. Must be enclosed in |
|
||||
| | parentheses. |
|
||||
+----------------------------------------+----------------------------------------------------------------------------+
|
||||
| MOZ_LOG_FMT(module, level, message) | Outputs the given message if the module has the given log level enabled: |
|
||||
| | |
|
||||
| | * module: The log module to use. |
|
||||
| | * level: The log level of the message. |
|
||||
| | * message: An {fmt} style message to output. |
|
||||
+----------------------------------------+----------------------------------------------------------------------------+
|
||||
| MOZ_LOG_TEST(module, level) | Checks if the module has the given level enabled: |
|
||||
| | |
|
||||
| | * module: The log module to use. |
|
||||
|
@ -157,6 +157,7 @@ and members in classes or structs.
|
||||
"ns[C]String" -> "nsLiteral[C]String" [style=dashed];
|
||||
"nsAuto[C]StringN" -> "nsPromiseFlat[C]String";
|
||||
"nsAuto[C]StringN" -> "nsPrintfCString";
|
||||
"nsAuto[C]StringN" -> "nsFmtCString";
|
||||
|
||||
The following is a list of the most common concrete classes. Once you are
|
||||
familiar with them, see the appendix describing What Class to Use When.
|
||||
@ -186,6 +187,11 @@ familiar with them, see the appendix describing What Class to Use When.
|
||||
construct a 8-bit string from a printf-style format string and parameter
|
||||
list.
|
||||
|
||||
* ``nsFmtCString`` - derived from ``nsCString``, this string behaves like an
|
||||
``nsAutoCString``. The constructor takes parameters which allows it to
|
||||
construct a 8-bit string from an {fmt}-style format string and parameter
|
||||
list.
|
||||
|
||||
There are also a number of concrete classes that are created as a side-effect
|
||||
of helper routines, etc. You should avoid direct use of these classes. Let
|
||||
the string library create the class for you.
|
||||
@ -903,6 +909,7 @@ list between the ``SetCapacity()`` call and operations from the list):
|
||||
* ``AppendASCII()``
|
||||
* ``AppendLiteral()``
|
||||
* ``AppendPrintf()``
|
||||
* ``AppendFmt()``
|
||||
* ``AppendInt()``
|
||||
* ``AppendFloat()``
|
||||
* ``LossyAppendUTF16toASCII()``
|
||||
|
Loading…
x
Reference in New Issue
Block a user