---
name: "unicode_canonical"
section: "3"
platform: "linux"
package: "libcourier-unicode-dev"
version: "2.3.2-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/unicode_canonical"
---

# unicode\_canonical(3)

unicode canonical normalization and denormalization

## NAME

unicode\_canonical, unicode\_ccc, unicode\_decomposition\_init, unicode\_decomposition\_deinit, unicode\_decompose, unicode\_decompose\_reallocate\_size, unicode\_compose, unicode\_composition\_init, unicode\_composition\_deinit, unicode\_composition\_apply - unicode canonical normalization and denormalization

## SYNOPSIS

```
#include <courier-unicode.h>
```

**unicode\_canonical\_t unicode\_canonical(char32\_t** *c***);**

**uint8\_t unicode\_ccc(char32\_t** *c***);**

**void unicode\_decomposition\_init(unicode\_decomposition\_t \****info***, char32\_t \****string***, size\_t \****string\_size***, void \****arg***);**

**int unicode\_decompose(unicode\_decomposition\_t \****info***);**

**void unicode\_decomposition\_deinit(unicode\_decomposition\_t \****info***);**

**size\_t unicode\_decompose\_reallocate\_size(unicode\_decomposition\_t \****info***, const size\_t \****sizes***, size\_t** *n***);**

**int unicode\_compose(char32\_t \****string***, size\_t** *string\_size***, int** *flags***, size\_t \****new\_size***);**

**int unicode\_composition\_init(const char32\_t \****string***, size\_t** *string\_size***, int** *flags***, unicode\_composition\_t \****compositions***);**

**void unicode\_composition\_deinit(unicode\_composition\_t \****compositions***);**

**size\_t unicode\_composition\_apply(char32\_t \****string***, size\_t** *string\_size***, unicode\_composition\_t \****compositions***);**

## DESCRIPTION

These functions compose or decompose a Unicode string into a canonical or a compatible normalized form.

**unicode\_canonical**() looks up the character's **canonical and compatibility mapping**\[1\]. **unicode\_canonical**() returns a structure with the following fields:

*canonical\_chars*

A pointer to the canonical or equivalent representation of the character.

*n\_canonical\_chars*

Number of characters in the *canonical\_chars*.

*format*

A value of UNICODE\_CANONICAL\_FMT\_NONE indicates a canonical mapping, other values indicate a compatibility equivalent mapping.

A NULL *canonical\_chars* (with a 0 *n\_canonical\_chars*) indicates that the character has no canonical or compatibility equivalence.

**unicode\_ccc**() returns the character's canonical combining class value.

**unicode\_decomposition\_init**(), **unicode\_decompose**() and **unicode\_decomposition\_deinit**() implement a complete interface for decomposing a Unicode string:

```
unicode_decomposition_t info;
unicode_decomposition_init(&info, before, (size_t)-1, NULL);
info.decompose_flags=UNICODE_DECOMPOSE_FLAG_QC;
unicode_decompose(&info);
unicode_decomposition_deinit(&info);
```

**unicode\_decomposition\_init**() initializes a new unicode\_decomposition\_t structure, that gets passed in as its first parameter. The second parameter is a pointer to a Unicode string, with the number of characters in the string in the third parameter. A string size of -1 indicates a \\0-terminated string and calculates its *string\_size* (which does not include the trailing \\0. The last parameter is a void \*, an opaque pointer that gets stored in the initialized unicode\_decomposition\_t object:

| | | | | |
| --- | --- | --- | --- | --- |
| typedef struct unicode\_decomposition { |
|  | char32\_t | \**string*; |
|  | size\_t | *string\_size*; |
|  | int | *decompose\_flags*; |
|  | int | (\**reallocate)(* |
|  |  |  | struct unicode\_decomposition | \**info*, |
|  |  |  | const size\_t | \**offsets*, |
|  |  |  | const size\_t | \**sizes*, |
|  |  |  | size\_t | *n* |
|  |  | ); |
|  | void | \**arg*; |
| } unicode\_decomposition\_t; |

**unicode\_decompose**() proceeds and decomposes the *string* and replaces it with its decomposed *string* version.

unicode\_decomposition\_t's *string*, *string\_size* and *arg* are copies of **unicode\_decomposition\_init**'s parameters. **unicode\_decomposition\_init** initializes all other fields to their default values.

The *decompose\_flags* bitmask gets initialized to 0, and is a bit mask:

UNICODE\_DECOMPOSE\_FLAG\_QC

Check each character's appropriate “quick check” property and skip decomposing Unicode characters that would get re-composed by **unicode\_composition\_apply**().

UNICODE\_DECOMPOSE\_FLAG\_COMPAT

Perform a compatibility decomposition instead of a canonical decomposition.

*reallocate* is a pointer to a function that gets called to reallocate a larger *string*. **unicode\_decompose**() determines which characters in the *string* need decomposing and calls the *reallocate* function pointer zero or more times. Each call to *reallocate* passes information about where new characters will get inserted into the *string*.

*reallocate* only needs to grow the size of the buffer where *string* points so that it's big enough to hold a larger, decomposed string; then update *string* accordingly. *reallocate* should not update *string\_size* or make any changes to the existing *string*, that's **unicode\_decompose**()'s job (after *reallocate* returns).

The *reallocate* callback function receives the following parameters.

• A pointer to the unicode\_decomposition\_t and, notably, its *arg*.

• A pointer to the array of offset indexes in the *string* where new characters will get inserted in order to hold the decomposed string.

• A pointer to the array that holds the number of characters that get inserted each corresponding offset.

• The size of the two arrays.

*reallocate* must update the *string* if necessary to hold at least the number of characters that's the sum total of the initial *string\_size* and the sum total of al *sizes*.

**unicode\_decomposition\_init**() initializes the *reallocate* pointer to a default implementation that uses [**realloc**(3)](/realloc/3.md) and updates *string* with its return value. The application can use its own *reallocate* to handle this task on its own, and use **unicode\_decompose\_reallocate\_size** to compute the minimum string size:

```
size_t unicode_decompose_reallocate_size(unicode_decomposition_t *info,
                                         const size_t *sizes,
                                         size_t n)
{
    size_t i;
    size_t new_size=info->string_size;
    for (i=0; i<n; ++i)
        new_size += sizes[i];
    return new_size;
}
```

The *reallocate* function returns 0 on success and a non-0 error code to report a failure; and *unicode\_decompose*() does the same. The only error condition from *unicode\_decompose*() is a non-0 error code from the *reallocate* function. Otherwise: a successful decomposition results in *unicode\_decompose*() returning 0 and **unicode\_decomposition\_init**()'s *string* pointing to the decomposed string and *string\_size* giving the number of characters in the decomposed string.

**Note**\

*string\_size* does not include the trailing \\0 character. The input string also has its *string\_size* specified without counting its \\0 character. The default implementation of *reallocate* allocates an extra char32\_t ands sets it to a \\0. Therefore:

• If the Unicode string before decomposition has a trailing \\0 and no decomposition occurs, and no calls to *reallocate* takes place: the *string* in the unicode\_decomposition\_t is unchanged and it's still \\0-terminated.

• The default *reallocate* allocates an extra char32\_t ands sets it to a \\0; and it takes care of that for the decomposed string.

• An application that provides its own replacement *reallocate* is responsible for doing the same, if it wants the decomposed string to be \\0 terminated.

**Note**\

Multiple calls to the *reallocate* callback are possible. Each call to *reallocate* reflect the prior calls' decompositions. Example: the original string has five characters and the first call to *reallocate* had two offsets, at position 1 and 3, with a value of 1 for their both *sizes*. This effects transforming an original Unicode string "AAAAA" into "AXAAXAA" (with “A” representing unspecified characters in the original string, and “X” showing the two characters added in the first call to **reallocate**.

A second call to *varname* with am offset at position 4, and a size of 1, results in the updated string of "AXAAYXAA" (with “Y”) marking an unspecified character inserted by the second call.

**Note**\

Unicode string decomposition involves replacing a given Unicode character with one or more other characters. The sizes given to *reallocate* reflect the net addition to the Unicode string. For example: decomposing one Unicode character into three decomposed characters results in a call to *reallocate* reporting an insert of two more characters.

**Note**\

*offsets* actually report the indices of each Unicode character that's getting decomposed. A 1:1 decomposition of a Unicode Character gets reported as an additional *sizes* entry of 0.

**unicode\_decomposition\_deinit**() releases all resources and destroys the unicode\_decomposition\_t; it is no longer valid.

**Note**\

**unicode\_decomposition\_deinit**() does not [**free**(3)](/free/3.md) the *string*. The original string gets passed in to **unicode\_decomposition\_init**() and the decomposed string is left in the *string*.

The default implementation of the *reallocate* function assumes the *string* is a [**malloc**(3)](/malloc/3.md)-ed string, and **realloc**s it.

**Note**\

At this time **unicode\_decomposition\_deinit**() does nothing. All code should explicitly call it in order to remain forward-compatible (at the source level).

**unicode\_compose**() performs a canonical composition of a decomposed string. Its parameters are:

• A pointer to the decomposed Unicode string.

• The number of characters in the Unicode string. The Unicode string does not need to be \\0-terminated; if it is this number does not include it.

• A flags bitmask, which can have the following values:

UNICODE\_COMPOSE\_FLAG\_REMOVEUNUSED

Remove all combining marks after doing all canonical compositions. Normally any unused combining marks are left in place, in the combined text. This option removes them.

UNICODE\_COMPOSE\_FLAG\_ONESHOT

Perform canonical composition once per character, and do not attempt to combine any resulting combined characters again.

• A non-NULL pointer to a size\_t.

A successful composition sets this size\_t to the number of characters in the combined string, and returns 0. The combined string gets placed back into the *string* parameter, this string gets combined in place and this gives the size of the combined string.

**unicode\_compose**() returns a non-zero value to indicate an error.

**unicode\_composition\_init**(), **unicode\_composition\_apply**() and **unicode\_composition\_deinit**() implement a detailed interface for canonical composition of a decomposed Unicode string:

```
unicode_compositions_t compositions;
if (unicode_composition_init(str, strsize, flags, &compositions) == 0)
{
    size_t new_size=unicode_composition_apply(str, strsize, &compositions);
    unicode_composition_deinit(&compositions);
}
```

The first two parameters to both **unicode\_composition\_init**() and **unicode\_composition\_apply**() are the same: the Unicode string and the number of characters (not including any trailing \\0 character) in the Unicode string.

**unicode\_composition\_init**()'s additional parameters are: any optional flags (see **unicode\_compose()** for a list of available flags), and the address of a unicode\_composition\_t object. A non-0 return from **unicode\_composition\_init**() indicates an error. **unicode\_composition\_init**() indicates success by returning 0 and initializing the unicode\_composition\_t's object which contains a pointer to an array of pointers to of unicode\_compose\_info objects, and the number of pointers. **unicode\_composition\_init**() does not change the string; the only thing it does is initialize the unicode\_composition\_t object.

**unicode\_composition\_apply**() applies the compositions to the *string*, in place, and returns the new size of the *string* (also not including the \\0 byte, however it does append one if the composed string is smaller, so the composed string is \\0-terminated if the decomposed string was).

It is necessary to call **unicode\_composition\_deinit**() to free all memory that was allocated for the unicode\_composition\_t object:

| | | |
| --- | --- | --- |
| struct unicode\_compose\_info { |
|  | size\_t | *index*; |
|  | size\_t | *n\_composed*; |
|  | char32\_t | \**composition*; |
|  | size\_t | *n\_composition*; |
| }; |
|  |
| typedef struct { |
|  | struct unicode\_compose\_info | \*\**compositions*; |
|  | size\_t | *n\_compositions*; |
| } unicode\_composition\_t; |

*index* gives the character index in the *string* where each composition occurs. *n\_composed* gives the number of characters in the original string that get composed. The composed characters are the *composition*; and *n\_composition* gives the number of composed characters.

Effectively: at the *index* position in the original string, #*n\_composed* characters get removed and there are #*n\_composition* characters that replace them (always *n\_composed* or less).

**Note**\

The UNICODE\_COMPOSE\_FLAG\_REMOVEUNUSED flag has the effect of including the combining marks that did not get combined in the *n\_composed* count. It's possible that, in this case, *n\_composition* is 0. This indicates complete removal of the combining marks, without anything getting combined in their place.

**unicode\_composition\_init**() sets unicode\_composition\_t's *compositions* pointer to an array of pointers to unicode\_compose\_infos that are sorted according to their *index*. *n\_compositions* gives the number of pointers in the array, and is 0 if there are no compositions, the array is empty. The empty array gets interpreted accordingly when it gets passed to **unicode\_composition\_apply**() and **unicode\_composition\_deinit**(): nothing happens. **unicode\_composition\_apply**() simply returns the size of the unchanged *string*, and **unicode\_composition\_deinit**() does a pro-forma cleanup.

## SEE ALSO

**TR-15**\[2\], [**courier-unicode**(7)](/courier-unicode/7.md), [**unicode::canonical**(3)](/unicode::canonical/3.md).

## AUTHOR

**Sam Varshavchik**

Author

## NOTES

- 1\.

  canonical and compatibility mapping

  https://www.unicode.org/reports/tr15/tr15-54.html

- 2\.

  TR-15

  https://www.unicode.org/reports/tr15/tr15-54.html
