C8RTOMB(3) | Library Functions Manual | C8RTOMB(3)

# NAME

`c8rtomb` — Restartable UTF-8 to multibyte conversion

# LIBRARY

Standard C Library (libc, -lc)

# SYNOPSIS

`#include <uchar.h>`

size_t
`c8rtomb`(char * restrict s, char8_t c8, mbstate_t * restrict ps);

# DESCRIPTION

The `c8rtomb` function decodes UTF-8 and converts it to multibyte characters in the current locale, keeping state to remember incremental progress if restarted.

Each call to `c8rtomb` updates the conversion state ps with a UTF-8 code unit c8, writes up to `MB_CUR_MAX` bytes (possibly none) to s, and returns either the number of bytes written to s or `(size_t)-1` to denote error.

If s is a null pointer, no output is produced and ps is reset to the initial conversion state, as if the call had been `c8rtomb`(buf, `0`, ps); for some internal buffer buf.

If c8 is zero, `c8rtomb` discards any pending incomplete UTF-8 code unit sequence in ps, outputs a (possibly empty) shift sequence to restore the initial state followed by a NUL byte, and resets ps to the initial conversion state.

If ps is a null pointer, `c8rtomb` uses an internal mbstate_t object with static storage duration, distinct from all other mbstate_t objects (including those used by other functions such as mbrtoc8(3)), which is initialized at program startup to the initial conversion state.

# RETURN VALUES

The `c8rtomb` function returns the number of bytes written to s on success, or sets errno(2) and returns `(size_t)-1` on failure.

# EXAMPLES

Convert a UTF-8 code unit sequence to a multibyte string, NUL-terminate it (with any shift sequence needed to restore the initial state), and print it:

    char8_t c8[] = { 0xf0, 0x9f, 0x92, 0xa9 };
    char buf[(__arraycount(c8) + 1)*MB_LEN_MAX], *s = buf;
    size_t i;
    mbstate_t mbs = {0};    /* initial conversion state */

    for (i = 0; i < __arraycount(c8); i++) {
            size_t len;

            len = c8rtomb(s, c8[i], &mbs);
            if (len == (size_t)-1)
                    err(1, "c8rtomb");
            assert(len < sizeof(buf) - (s - buf));
            s += len;
    }
    len = c8rtomb(s, 0, &mbs);              /* NUL-terminate */
    if (len == (size_t)-1)
            err(1, "c16rtomb");
    assert(len <= sizeof(buf) - (s - buf));
    printf("%s\n", buf);

To avoid a variable-length array, this code uses `MB_LEN_MAX`, which is a constant upper bound on the locale-dependent `MB_CUR_MAX`.

# ERRORS

[`EILSEQ`]
  c8 is invalid as the next code unit in the conversion state ps.
[`EILSEQ`]
  The input cannot be encoded as a multibyte sequence in the current locale.
[`EIO`]
  An error occurred in loading the locale's character conversions.

# SEE ALSO

c16rtomb(3), c32rtomb(3), mbrtoc8(3), mbrtoc16(3), mbrtoc32(3), uchar(3)

The Unicode Standard, https://www.unicode.org/versions/Unicode15.0.0/UnicodeStandard-15.0.pdf, The Unicode Consortium, September 2022, Version 15.0 — Core Specification.

F. Yergeau, UTF-8, a transformation format of ISO 10646, Internet Engineering Task Force, RFC 3629, https://datatracker.ietf.org/doc/html/rfc3629, November 2003.

# HISTORY

The `c8rtomb` function first appeared in NetBSD 11.0.

# CAVEATS

The standard requires that passing zero as c8 unconditionally reset the conversion state and output a NUL byte:

If c8 is a null character, a null byte is stored, preceded by any shift sequence needed to restore the initial shift state; the resulting state described is the initial conversion state.

However, some implementations such as glibc 2.36 ignore this clause and, if the zero was preceded by a nonempty incomplete UTF-8 code unit sequence, fail with `EILSEQ` instead.

August 15, 2024 | NetBSD 11.0