docs: Add documentation of the printf format
This commit is contained in:
@@ -981,6 +981,275 @@ unsafe fn inner_printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) ->
|
||||
Ok(w.written as c_int)
|
||||
}
|
||||
|
||||
/// Implementation of `printf` formatting function, generic over a `writer`
|
||||
///
|
||||
/// This implementation in currently compliant over C17 specification (lacking a few one from C23)
|
||||
/// and contains extensions as well.
|
||||
///
|
||||
/// # The Format Specification
|
||||
/// ```text
|
||||
/// %[conversion-flags][field-width][precision][length-modifier]<conversion-format>
|
||||
/// ```
|
||||
///
|
||||
/// <div class="warning">
|
||||
/// ※ : This symbol means it is not implemented yet, but it is defined in the C standard
|
||||
/// </div>
|
||||
///
|
||||
/// ## Conversion Flags
|
||||
/// Conversion flags are flags that modify the behavior of the [conversion
|
||||
/// format]. Each one can happen only once per format specifier. They are:
|
||||
///
|
||||
/// - `-`: The result of the conversion is left-justified within the field (by default it is
|
||||
/// right-justified).
|
||||
/// - `+`: The sign of signed conversions is always prepended to the result of the conversion (by
|
||||
/// default the result is preceded by minus **only** when it is negative).
|
||||
/// - ` `(space): If the result of a signed conversion does not start with a sign character, or is
|
||||
/// empty, space is prepended to the result.
|
||||
/// - It is ignored if `+` flag is present.
|
||||
/// - `#`: Alternative form of the conversion is performed. See the documentation for each
|
||||
/// [conversion format] for details.
|
||||
/// - `0`: For integer and floating-point number conversions, leading zeros are used to pad the
|
||||
/// field instead of space characters.
|
||||
/// - For integer numbers it is ignored if the precision is explicitly specified.
|
||||
/// - For other conversions using this flag results in undefined behavior.
|
||||
/// - It is ignored if `-` flag is present.
|
||||
///
|
||||
/// ## Field Width
|
||||
/// Specifies minimum field width. This makes the result to be padded (with spaces by default, with
|
||||
/// zeroes if `0` conversion flag is specified) if the converted value has fewer characters than the
|
||||
/// specified width. It can take three forms:
|
||||
///
|
||||
/// - `N` where N is a positive integer: Specifies the field width value of `N`.
|
||||
/// - `*`: The width is specified by an extra argument of type [`int`], which has to appear before
|
||||
/// the argument to be converted and the [precision] (if specified with `.*`).
|
||||
/// - If the value of e extra argument is negative, it is interpreted as with `-` [conversion
|
||||
/// flag], i.e. left-justified result.
|
||||
/// - `*P$` where P is a positive integer: The width is specified by an extra argument of type
|
||||
/// [`int`], which has to appear exactly at the position specified by `P`.
|
||||
/// - This is a popular extension of the C and POSIX standards.
|
||||
/// - If the value of e extra argument is negative, it is interpreted as with `-` [conversion
|
||||
/// flag], i.e. left-justified result.
|
||||
///
|
||||
/// ## Precision
|
||||
/// Specifies the precision of the conversion.
|
||||
///
|
||||
/// For integer [conversion formats], this specifies the number of digits to appear in the result.
|
||||
///
|
||||
/// For float point [conversion formats], this specifies the number of digits to appear after the
|
||||
/// decimal-point character.
|
||||
///
|
||||
/// It can take three forms:
|
||||
///
|
||||
/// - `.N` where N is a positive integer: Specifies the precision value of `N`.
|
||||
/// - `.*`: The precision is specified by an extra argument of type [`int`], which has to appear
|
||||
/// before the argument to be converted and after the the [field width] (if specified with `*`).
|
||||
/// - If the value of e extra argument is negative, it is interpreted as if the precision were
|
||||
/// omitted.
|
||||
/// - `.*P$` where P is a positive integer: The precision is specified by an extra argument of type
|
||||
/// [`int`], which has to appear exactly at the position specified by `P`.
|
||||
/// - This is an popular extension of the C and POSIX standards.
|
||||
/// - If the value of e extra argument is negative, it is interpreted as if the precision were
|
||||
/// omitted.
|
||||
///
|
||||
/// ## Length Modifier
|
||||
/// Specifies the size of the argument. In combination with the [conversion format], it specifies
|
||||
/// the type of the corresponding argument.
|
||||
///
|
||||
/// - `hh`: Byte size
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - `h`: Short size
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - `l`: Long size
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with character conversion format (`c`)
|
||||
/// - Works with string conversion format (`s`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - Works with float conversion formats (`f`, `F`, `e`, `E`, `a`, `A`, `g`, `G`) (C99)
|
||||
/// - `ll`: Long long size
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - `j`: Maximum width
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - `z`: Pointer width size
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - `t`: Pointer diff width
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - Works with written number conversion format (`n`)
|
||||
/// - `wN` (C23 ※): Specifies that the size should be N bits width version of the supported
|
||||
/// conversion format.
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - The supported values of `N` must be the same as the widths specified in `stdint.h`
|
||||
/// - `wfN` (C23 ※): Specifies that the size should be the fast N bits width version of the
|
||||
/// supported conversion format.
|
||||
/// - Works with integer conversion formats (`d`, `i`, `o`, `x`, `X`, `b`, `B`)
|
||||
/// - The supported values of `N` must be the same as the widths specified in `stdint.h`
|
||||
/// - `L`: Long double size
|
||||
/// - Works with float conversion formats (`f`, `F`, `e`, `E`, `a`, `A`, `g`, `G`)
|
||||
/// - `H` (C23 ※): _Decimal32 size
|
||||
/// - Works with float conversion formats (`f`, `F`, `e`, `E`, `a`, `A`, `g`, `G`)
|
||||
/// - `D` (C23 ※): _Decimal64 size
|
||||
/// - Works with float conversion formats (`f`, `F`, `e`, `E`, `a`, `A`, `g`, `G`)
|
||||
/// - `DD` (C23 ※): _Decimal128 size
|
||||
/// - Works with float conversion formats (`f`, `F`, `e`, `E`, `a`, `A`, `g`, `G`)
|
||||
///
|
||||
/// ## Conversion Format
|
||||
/// Specifies the conversion format as one of the following:
|
||||
///
|
||||
/// - `%`: Writes a percent symbol. The full conversion format must be `%%`.
|
||||
/// - `c`: Writes as single character
|
||||
/// - Without length modifier:
|
||||
/// - The argument is first converted to [`unsigned char`]
|
||||
/// - With `l` length modifier:
|
||||
/// - The argument is first converted to a character string as if by `%ls` with a array of 2
|
||||
/// [`wchar_t`] argument.
|
||||
/// - `s`: Writes a character string
|
||||
/// - The argument is a pointer to the first character
|
||||
/// - The [precision] specifies the maximum number of bytes to be written. If not specified,
|
||||
/// writes up to the first null character found.
|
||||
/// - `d` and `i`: Writes a decimal representation of a signed integer
|
||||
/// - The [precision] specifies the minimal number to appear (defaults to `1`).
|
||||
/// - If the precision is zero and the value to be written is also zero, the result is no
|
||||
/// characters written.
|
||||
/// - `u`: Writes the decimal representation of a unsigned integer
|
||||
/// - The [precision] specifies the minimal number to appear (defaults to `1`).
|
||||
/// - If the precision is zero and the value to be written is also zero, the result is no
|
||||
/// characters written.
|
||||
/// - `o`: Writes the octal representation of a unsigned integer.
|
||||
/// - The [precision] specifies the minimal number to appear (defaults to `1`).
|
||||
/// - If the precision is zero and the value to be written is also zero, the result is no
|
||||
/// characters written.
|
||||
/// - The alternative representation includes a leading `0`.
|
||||
/// - The types are the same as `u`
|
||||
/// - `x`: Writes the hexadecimal representation of a unsigned integer with lowercase characters.
|
||||
/// - The [precision] specifies the minimal number to appear (defaults to `1`).
|
||||
/// - If the precision is zero and the value to be written is also zero, the result is no
|
||||
/// characters written.
|
||||
/// - The alternative representation includes a leading `0x`.
|
||||
/// - The types are the same as `u`
|
||||
/// - `X`: Writes the hexadecimal representation of a unsigned integer with uppercase characters.
|
||||
/// - The [precision] specifies the minimal number to appear (defaults to `1`).
|
||||
/// - If the precision is zero and the value to be written is also zero, the result is no
|
||||
/// characters written.
|
||||
/// - The alternative representation includes a leading `0X`.
|
||||
/// - The types are the same as `u`.
|
||||
/// - `b` | `B` (C23 ※): Writes the binary representation of a unsigned integer.
|
||||
/// - The [precision] specifies the minimal number to appear (defaults to `1`).
|
||||
/// - If the precision is zero and the value to be written is also zero, the result is no
|
||||
/// characters written.
|
||||
/// - The alternative representation includes a leading `0b` and `0B`, respectively.
|
||||
/// - The types are the same as `u`.
|
||||
/// - `f` | `F`: Writes the decimal representation of a float point number.
|
||||
/// - The [precision] specifies the exact number of digits to appear after the decimal point
|
||||
/// character (defaults to `6`).
|
||||
/// - The alternative representation, the decimal point character is written even if no digits
|
||||
/// follow it.
|
||||
/// - `e` | `E`: Writes the float point number with the decimal exponential notation (\[-\]d.ddd
|
||||
/// **e**±dd | \[-\]d.ddd **E**±dd)
|
||||
/// - The [precision] specifies the exact number of digits to appear after the decimal point
|
||||
/// character (defaults to `6`).
|
||||
/// - The exponent contains at least two digits, more digits are used only if necessary.
|
||||
/// - If the value is zero, the exponent is also zero.
|
||||
/// - The alternative representation: decimal point character is written even if no digits follow
|
||||
/// it.
|
||||
/// - `a` | `A`: Writes the float point number with the hexadecimal exponential notation (\[-\]
|
||||
/// **0x**h.hhh **p**±d | \[-\] **0X**h.hhh **P**±d)
|
||||
/// - The [precision] specifies the exact number of digits to appear after the hexadecimal point
|
||||
/// character (defaults to `6`).
|
||||
/// - If the value is zero, the exponent is also zero.
|
||||
/// - The alternative representation: decimal point character is written even if no digits follow
|
||||
/// it.
|
||||
/// - `g` | `G`: Writes the float point number to decimal or decimal exponent notation depending on
|
||||
/// the value and the [precision].
|
||||
/// - Let `P` equal the precision if nonzero, `6` if the precision is not specified, or `1` if the
|
||||
/// precision is `0`. Then, if a conversion with style `E` would have an exponent of `X`:
|
||||
/// - If `P > X ≥ −4`, the conversion is with the format `f` and precision `P − 1 − X`.
|
||||
/// - Otherwise, the conversion is with the format `e` or `E` and precision `P − 1`.
|
||||
/// - Unless alternative representation is requested, the trailing zeros are removed. Also the
|
||||
/// decimal point character is removed if no fractional part is left.
|
||||
/// - `n`: Writes the number of characters written in the call into the argument pointer
|
||||
/// - It can not contain any [conversion flag], [field width], or [precision].
|
||||
/// - `p`: Writes an implementation defined character sequence defining a pointer.
|
||||
///
|
||||
/// ### Types
|
||||
/// The types expected by the format string can change with the [length modifier].
|
||||
///
|
||||
/// For the `c`:
|
||||
/// - Without length modifier: [`int`]
|
||||
/// - With `l` length modifier: [`wint_t`]
|
||||
///
|
||||
/// For the `s`:
|
||||
/// - Without length modifier: pointer to [`char`] (`char*`, `const char*`)
|
||||
/// - With `l` length modifier: pointer to [`wchar_t`] (`wchar_t*`, `const wchar_t*`)
|
||||
///
|
||||
/// For the `d` and `i`:
|
||||
/// - Without length modifier: [`int`]
|
||||
/// - With `hh` length modifier: [`signed char`]
|
||||
/// - With `h` length modifier: [`short`]
|
||||
/// - With `l` length modifier: [`long`]
|
||||
/// - With `ll` length modifier: [`long long`]
|
||||
/// - With `j` length modifier: [`intmax_t`]
|
||||
/// - With `z` length modifier: [`ssize_t`]
|
||||
/// - With `t` length modifier: [`ptrdiff_t`]
|
||||
///
|
||||
/// For the `u`, `o`, `x`, `X`, `b`, `B`:
|
||||
/// - Without length modifier: [`unsigned int`]
|
||||
/// - With `hh` length modifier: [`unsigned char`]
|
||||
/// - With `h` length modifier: [`unsigned short`]
|
||||
/// - With `l` length modifier: [`unsigned long`]
|
||||
/// - With `ll` length modifier: [`unsigned long long`]
|
||||
/// - With `j` length modifier: [`uintmax_t`]
|
||||
/// - With `z` length modifier: [`size_t`]
|
||||
/// - With `t` length modifier: [`unsigned ptrdiff_t`]
|
||||
///
|
||||
/// For the `f`, `F`, `e`, `E`, `a`, `A`, `g`, `G`:
|
||||
/// - Without length modifier: [`double`]
|
||||
/// - With `l` length modifier: [`double`]
|
||||
/// - With `L` length modifier: `long double`
|
||||
/// - With `H` length modifier (C23 ※): `_Decimal32`
|
||||
/// - With `D` length modifier (C23 ※): `_Decimal64`
|
||||
/// - With `DD` length modifier (C23 ※): `_Decimal128`
|
||||
///
|
||||
/// For the `n`
|
||||
/// - Without length modifier: pointer to [`int`] (`int*`)
|
||||
/// - With `hh` length modifier: pointer to [`signed char`] (`signed char*`)
|
||||
/// - With `h` length modifier: pointer to [`short`] (`short*`)
|
||||
/// - With `l` length modifier: pointer to [`long`] (`long*`)
|
||||
/// - With `ll` length modifier: pointer to [`long long`] (`long long*`)
|
||||
/// - With `j` length modifier: pointer to [`intmax_t`] (`intmax_t*`)
|
||||
/// - With `z` length modifier: pointer to [`ssize_t`] (`ssize_t*`)
|
||||
/// - With `t` length modifier: pointer to [`ptrdiff_t`] (`ptrdiff_t*`)
|
||||
///
|
||||
/// For the `p`, it must always be a pointer to [`void`] (`void*` | `const void*`)
|
||||
///
|
||||
/// [precision]: #precision
|
||||
/// [field width]: #field-width
|
||||
/// [length modifier]: #length-modifier
|
||||
/// [conversion format]: #conversion-format
|
||||
/// [`int`]: c_int
|
||||
/// [`unsigned char`]: c_uchar
|
||||
/// [`unsigned short`]: c_ushort
|
||||
/// [`unsigned int`]: c_uint
|
||||
/// [`unsigned long`]: c_ulong
|
||||
/// [`unsigned long long`]: c_ulonglong
|
||||
/// [`unsigned ptrdiff_t`]: ptrdiff_t
|
||||
/// [`wchar_t`]: wchar_t
|
||||
/// [`char`]: c_char
|
||||
/// [`signed char`]: c_schar
|
||||
/// [`short`]: c_short
|
||||
/// [`long`]: c_long
|
||||
/// [`long long`]: c_longlong
|
||||
/// [`double`]: c_double
|
||||
/// [`long double`]: c_longdouble
|
||||
/// [`void`]: c_void
|
||||
///
|
||||
/// # Safety
|
||||
/// Behavior is undefined if any of the following conditions are violated:
|
||||
/// - `format` must point to valid null-terminated string.
|
||||
/// - `ap` must follow the safety contract of variable arguments of C.
|
||||
pub unsafe fn printf<W: Write>(w: W, format: *const c_char, ap: VaList) -> c_int {
|
||||
inner_printf(w, format, ap).unwrap_or(-1)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user