.. This file is auto-generated by the Sphinx pre-build hook in
   ``documentation/source/conf.py`` from
   ``documentation/source/_data/patcher_objects.json`` and the notes in
   ``documentation/source/_data/patcher_notes/``.
   Do not edit by hand — re-run ``python yse.py dump-patcher-meta`` to
   refresh the JSON, then ``make html`` to re-render this page.

Strings and symbols
===================

Text, symbols and character codes.

10 objects. Every entry is
pulled directly from the engine source via the ``ADD_DESCRIPTION`` /
``INLET_DOC`` / ``OUTLET_DOC`` / ``PARAM_DOC`` macros (see
:file:`YseEngine/patcher/pObject.h`). The ``~`` prefix marks DSP /
audio-rate objects; ``.`` marks control-rate objects.

.. contents::
   :local:
   :depth: 1

``.atoi``
---------

Converts a message into the character codes of its text and holds them: 'hi' gives 104 105. A bang sends the held codes again, and the other two inlets add to them or replace them without sending.

:Kind: Control-rate

The message is converted as it stands, as text: an int digit by digit
(``123`` gives ``49 50 51``), a float including its decimal point, and a list
character by character with ``32`` (a space) between its items. Runs of
spaces count as one, and spaces at the ends are dropped.

The text is read as UTF-8, so an accented letter gives one code, not two:
``é`` gives ``233``. A byte that is not part of a valid UTF-8 character gives
its own value, 0 to 255. ``.spell`` reads text the same way.

**Inlets**

- Inlet 0 replaces the stored codes and sends them. A bang sends them again
  without converting anything.
- Inlet 1 adds codes to the end and sends nothing. Characters are added with
  no space between messages: ``a`` then ``b`` stores ``97 98``, while the one
  message ``a b`` gives ``97 32 98``.
- Inlet 2 replaces the stored codes and sends nothing.

An empty message on inlet 0 or inlet 2 clears the stored codes. Nothing is
sent while nothing is stored.

The codes leave together as one list. Use ``.iter`` to get them one at a
time.

**Limits**

At most 256 codes. A message that would take the total past 256 is refused
whole: the stored codes stay as they were, and nothing is logged.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, BANG, LIST
     - —
     - The message to convert. It replaces the stored codes and the codes are sent. A bang sends the stored codes again. An empty message clears them and sends nothing.
   * - 1
     - append
     - FLOAT, INT, LIST
     - at most 256 characters in total
     - Adds the codes of the message to the stored codes and sends nothing. Characters are added with no space between messages: 'a' then 'b' gives 97 98.
   * - 2
     - set
     - FLOAT, INT, LIST
     - at most 256 characters in total
     - Replaces the stored codes with the codes of the message and sends nothing. An empty message clears them.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - LIST
     - —
     - The stored codes as one list, in the order the characters appear: 'hi' leaves as 104 105.



``.combine``
------------

Joins the items held in its inlets into one symbol, with nothing between them. Each creation argument is an item and the starting value of its own inlet. By default inlet 0 sends and the other inlets only store.

:Kind: Control-rate

The creation arguments are the items. Each one gets an inlet and is that
inlet's starting value. The output is the items written one after another,
with nothing in between. To put a separator in, make it an item of its own:

.. code-block:: text

   [.combine synth / lead / note]   inlet 4 <- 60, then bang   =>   synth/lead/60

**What an inlet stores**

- A number is stored as its text.
- A list fills this item and the ones to its right, one token each. Tokens
  past the last item are dropped.
- An empty message clears the item. An item that was never set, or was
  cleared, adds nothing to the output.

When every item is empty, nothing is sent.

**Which inlets send**

By default inlet 0 stores and sends and the other inlets only store. Start
the arguments with ``triggers`` to change that:

- ``triggers -1``: every inlet sends.
- ``triggers <n>``: only inlet ``n`` sends.

A bang on inlet 0 always sends the current items. If ``triggers`` is not
followed by a whole number, or names an inlet that does not exist, the
problem is logged: ``triggers`` is then read as an item, or inlet 0 stays the
one that sends.

There is no option to pad numbers to a fixed width; use ``.sprintf`` with a
width (``%03d``) for that.

**Limits**

At most 32 items of at most 64 characters each. An argument that is too long
is logged and the item left empty. A longer item arriving at an inlet is
ignored and the item keeps its value.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in0
     - FLOAT, INT, BANG, LIST
     - any
     - Hot. Stores the message as this inlet's item and sends the joined symbol. A number is stored as its text. A list fills this item and the ones to its right, one token each. An empty message clears this item. A bang sends the joined symbol, whichever inlets the triggers argument makes hot.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - ANY
     - any
     - The items joined with nothing between them, as one symbol. Nothing is sent while every item is empty.


**Parameters**

.. list-table::
   :header-rows: 1
   :widths: 22 18 18 42

   * - Name
     - Default
     - Range
     - Description
   * - items
     - —
     - optional 'triggers <n>' then up to 32 items of at most 64 characters
     - An optional 'triggers <n>' followed by the items, one inlet each. 'triggers -1' makes every inlet hot and 'triggers <n>' makes inlet n the only hot one; without it inlet 0 is hot. An item longer than 64 characters is logged and left empty.


``.fromsymbol``
---------------

Splits a symbol on its separator into a message: with separator /, voice/3/freq becomes 'voice 3 freq'. A result that is one number or the word bang leaves as an int, a float or a bang. The inverse of .tosymbol.

:Kind: Control-rate

Each token of the message is split on the separator, and the pieces leave as
an ordinary list. Spaces in the message separate pieces too. Empty pieces
are dropped, so ``a//b`` split on ``/`` gives ``a b``.

When the result is a single token, it leaves as the type it reads as: a
number leaves as an int or a float, and the word ``bang`` leaves as a bang.
Anything longer leaves as a list. An int, a float or a bang that arrives
passes through as it is.

**The separator**

The separator is the creation argument, and inlet 1 changes it. The default
is a single space, which only evens out the spacing and restores the type.
An empty separator splits a symbol into single characters, so ``1234``
gives ``1 2 3 4``. A separator is one token of at most 16 characters; a
longer one is ignored (and logged when it is the argument).

.. code-block:: text

   [.tosymbol /]  <- voice 3 freq   =>   voice/3/freq
   [.fromsymbol /] <- voice/3/freq  =>   voice 3 freq

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, BANG, LIST
     - —
     - The message to split. A bang, an int or a float passes through as it is.
   * - 1
     - separator
     - FLOAT, INT, LIST
     - one token, at most 16 characters
     - Sets the separator and sends nothing. A list sets its first token, a number its text. An empty message sets an empty separator. A separator longer than 16 characters is ignored.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - ANY
     - —
     - The split message. A one-token result leaves as an int, a float or a bang when it reads as one, and as a list otherwise.


**Parameters**

.. list-table::
   :header-rows: 1
   :widths: 22 18 18 42

   * - Name
     - Default
     - Range
     - Description
   * - separator
     -  
     - one token, at most 16 characters
     - The separator to split on. A single space when not given, which only evens out the spacing. Empty splits the symbol into single characters.


``.itoa``
---------

Converts character codes into the text they spell and holds it: 104 105 gives 'hi'. A bang sends the held text again, and the other two inlets add to it or replace it without sending. The inverse of .atoi.

:Kind: Control-rate

An int or a float gives one character (a float is truncated first), and a
list gives one character per code. The text is written as UTF-8, so
``.atoi`` after ``.itoa`` gives back the codes that went in, and ``.itoa``
after ``.atoi`` gives back the message.

The result is always a list, even when it reads as a number: ``49 50`` gives
the text ``12``. Send it through ``.fromsymbol`` to turn it into the int
``12``.

A token that is not a number, or a code that is not a character (negative,
above 1114111, or in the range 55296-57343), refuses the whole message.

**Inlets**

The three inlets work as on ``.atoi``: inlet 0 replaces and sends (a bang
sends again), inlet 1 adds and sends nothing, inlet 2 replaces and sends
nothing. An empty message on inlet 0 or inlet 2 clears the stored text. To
build a word one character at a time, send each code to inlet 1 and bang
inlet 0 when it is complete.

**Limits**

At most 256 characters. A message that would take the total past 256 is
refused whole: the stored text stays as it was, and nothing is logged.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, BANG, LIST
     - —
     - The character codes to convert: an int, a float (truncated) or a list of them. They replace the stored text and the text is sent. A bang sends the stored text again. An empty message clears it and sends nothing.
   * - 1
     - append
     - FLOAT, INT, LIST
     - at most 256 characters in total
     - Adds the characters the codes spell to the stored text and sends nothing. Use it to build a word one character at a time, then bang inlet 0 to send it.
   * - 2
     - set
     - FLOAT, INT, LIST
     - at most 256 characters in total
     - Replaces the stored text with the characters the codes spell and sends nothing. An empty message clears it.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - LIST
     - —
     - The stored text as a list: 104 105 leaves as 'hi'. Always a list, even when the text reads as a number.



``.regexp``
-----------

Matches messages against a regular expression. Each match leaves with its capture groups, an optional substitution rewrites every match, and a message that does not match leaves the rightmost outlet unchanged.

:Kind: Control-rate

The first creation argument is the pattern. Everything after it, joined with
single spaces, is the substitution, which is optional:

.. code-block:: text

   [.regexp ^/synth/(\d+)/(\w+)$ %2]   <- /synth/3/freq
   outlet 2: /synth/3/freq   outlet 1: 3 freq   outlet 0: freq

The pattern is one token, so it cannot hold a space: write ``\s`` for any
whitespace or ``\x20`` for exactly one space.

**What is sent**

For each match, from left to right, the matched text leaves outlet 2 and
then its capture groups leave outlet 1 as one list. Outlet 1 stays silent
when the pattern has no groups, and a group that took no part in the match
is empty. After the last match, when a substitution is set, outlet 0 sends
the whole message with every match replaced.

A message the pattern matches nowhere leaves outlet 3 unchanged, and nothing
else is sent, so the object also works as a filter. An int or a float is
matched as the text that spells it.

In the substitution, ``%1`` to ``%9`` insert a capture group, ``%0`` the whole
match and ``%%`` a percent sign. A ``%`` before anything else is copied as
it is.

**Pattern syntax**

- Literal characters, and ``.`` for any character.
- Character classes: ``[abc]``, ranges ``[a-z]``, negation ``[^0-9]``.
- ``\d \D \w \W \s \S``, inside a class or outside it.
- Escapes for the special characters (``\.``, ``\(``, ``\\`` …), ``\t \n
  \r``, and ``\xHH`` for a character by its hexadecimal code.
- ``^`` and ``$`` anchor to the start and end of the whole message.
- ``* + ?`` and ``{n}``, ``{n,}``, ``{n,m}``. They are greedy; add ``?``
  for the shortest match (``*?``).
- Alternation with ``|``.
- Capturing groups ``( )``, at most nine, and non-capturing ``(?: )``.

Backreferences, lookahead and lookbehind, named groups, ``\b`` and ``\B``,
``\A`` and ``\Z``, possessive quantifiers and inline flags are not
supported. Neither is a repeat of something that can match nothing, such as
``(a*)*``. Such a pattern is logged when the object is created, and the
object then sends every message out of outlet 3.

**Limits**

A pattern is at most 256 characters, a ``{n,m}`` count at most 64 and groups
nest at most 16 deep. A message longer than 512 characters leaves outlet 3
unmatched. A pattern that takes too long on one message stops searching
there; when nothing had matched yet, the message counts as unmatched. A
substitution result longer than 4096 characters is not sent. Safe on the
audio thread: matching never allocates memory and its time is bounded.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, LIST
     - any symbol
     - The message to match. A list is matched as its text, an int or a float as the text that spells it.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - substitution
     - LIST
     - symbol
     - The whole message with every match replaced by the substitution. Sent once, after the matches, and only when a substitution is set and something matched.
   * - 1
     - groups
     - LIST
     - symbol
     - The capture groups of one match, as a list, sent once per match. Silent when the pattern has no groups. A group that took no part in the match is empty.
   * - 2
     - match
     - LIST
     - symbol
     - One matched piece of text, sent once per match, left to right.
   * - 3
     - no match
     - LIST
     - symbol
     - The message, unchanged, when the pattern matches nowhere in it. Also receives every message while there is no pattern, or the pattern could not be compiled.


**Parameters**

.. list-table::
   :header-rows: 1
   :widths: 22 18 18 42

   * - Name
     - Default
     - Range
     - Description
   * - pattern
     - —
     - any pattern
     - The regular expression, as one token. Write \s or \x20 for a space.
   * - substitution
     - —
     - any text
     - Optional replacement text: everything after the pattern, joined with single spaces. %1-%9 insert a capture group, %0 the whole match and %% a percent sign. Without it, outlet 0 never sends.


``.spell``
----------

Spells a message out as the character codes of its text, sent as one list: 'hi' gives 104 105. Optional arguments pad a short result to a minimum length with a fill code.

:Kind: Control-rate

The message is spelled as it stands, by the same rules as ``.atoi``: an int
digit by digit, a float including its decimal point, a list character by
character with ``32`` between its items, and UTF-8 text one code per
character. Unlike ``.atoi`` it stores nothing and does not take a bang.

The two creation arguments pad a short result to a fixed length, which is
useful for fixed-width records:

.. code-block:: text

   [.spell 5]      <- hi   =>   104 105 32 32 32
   [.spell 5 48]   <- hi   =>   104 105 48 48 48

The first argument is the minimum number of codes (at most 256), the second
the fill code, 32 (a space) by default. A negative fill code is logged and
the default kept.

Nothing is sent when there is nothing to spell and no minimum. A message that
would spell to more than 256 codes sends nothing at all.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, LIST
     - any
     - The message to spell: an int digit by digit (123 gives 49 50 51), a float including its decimal point, a list character by character with 32 between its items.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - LIST
     - 0-1114111 per code, at most 256 codes
     - The codes as one list, in the order the characters appear: 'hi' leaves as 104 105. Nothing is sent when there is nothing to spell, or when the result would pass 256 codes.


**Parameters**

.. list-table::
   :header-rows: 1
   :widths: 22 18 18 42

   * - Name
     - Default
     - Range
     - Description
   * - size
     - 0
     - 0-256
     - The minimum number of codes to send. A shorter result is padded with the fill code. 0 means no minimum. Clamped to 256.
   * - fill
     - 32
     - 0-1114111
     - The code a short result is padded with: 32 (a space) by default, 48 for the character '0'. A negative code, or one above 1114111, is logged and the default kept.


``.sprintf``
------------

Builds a message from a format with printf-style placeholders: '.sprintf /voice/%d/freq' sends /voice/3/freq for a 3. Each placeholder has its own inlet; inlet 0 formats and sends, the others only store.

:Kind: Control-rate

The creation arguments are the format: text with placeholders in it. Each
placeholder gets one inlet, in order. Inlet 0 formats and sends; the other
inlets only store.

.. code-block:: text

   [.sprintf /voice/%d/%s]   inlet 1 <- freq   inlet 0 <- 3   =>   /voice/3/freq

**Placeholders**

- ``%d`` or ``%i``: an int. ``%ld`` and other ``l`` / ``h`` forms are read
  the same way.
- ``%f``: a float, with 6 decimals unless a precision is given.
- ``%s``: a word.
- ``%c``: an int written as the character with that code (1 to 255).
- ``%%``: a percent sign.

Between the ``%`` and the letter a placeholder may have, in this order: the
flags ``-`` (align left) and ``0`` (pad a number with zeros), a width of at
most 64, and a ``.precision`` of at most 9 (decimals for ``%f``, the most
characters for ``%s``). So ``%03d`` writes ``7`` as ``007`` and ``%.2f``
writes ``0.5`` as ``0.50``. Anything else after a ``%``, including a larger
width or precision, is logged and copied into the output as it was typed. A leading word ``symout`` is accepted and
dropped; it changes nothing.

**What an inlet stores**

- Every inlet takes an int, a float or a list, whatever its placeholder.
- A number sent to a ``%s`` is stored as its text. A word sent to a ``%d`` or
  ``%f`` is ignored and the previous value kept. A word sent to a ``%c``
  uses its first character.
- A list fills this placeholder and the ones to its right, one token each;
  tokens past the last placeholder are dropped.
- A bang on inlet 0 formats with the values stored so far.

A ``%d`` or ``%f`` that was never set writes ``0``; a ``%s`` or ``%c`` writes
nothing. A format with no placeholders sends the same text every time.
Without a format, nothing is sent.

``%f`` rounds a value exactly halfway between two decimals away from zero. A
value too large to write in full is written with an exponent.

**Limits**

At most 32 placeholders; more are logged and copied through as text. A word
for a ``%s`` is at most 64 characters; a longer one is ignored and the
previous value kept.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in0
     - FLOAT, INT, BANG, LIST
     - any
     - Hot. A bang, an int, a float or a list formats the message and sends it. When the format has placeholders this is also the first one's inlet: the value is stored first. A list fills this placeholder and the ones to its right, one token each.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - ANY
     - any
     - The formatted message, as text. Sent once per message on inlet 0, and never while there is no format.


**Parameters**

.. list-table::
   :header-rows: 1
   :widths: 22 18 18 42

   * - Name
     - Default
     - Range
     - Description
   * - format
     - —
     - printf-style format, at most 32 placeholders
     - The format: text with placeholders in it. Each placeholder gets one inlet, in order. Supports %d, %f, %s, %c and %%, with the - and 0 flags, a width and a .precision. Anything else after a % is logged and copied through as text.


``.tolower``
------------

Converts the letters A-Z in a message to lower case and leaves everything else as it was: other characters, spacing and tokens. Put it in front of a .route or .sel to make the match ignore case.

:Kind: Control-rate

Only the letters A-Z change. Letters outside ASCII (``É``, ``Ж``) are left
as they are, because their case depends on the language. Numbers,
punctuation and spacing are unchanged, so the tokens of the message stay
the same.

A bang, an int or a float passes through in its own type, and an empty
message is passed on as an empty message.

.. code-block:: text

   [.tolower] -> [.route play stop]   accepts Play, PLAY and play

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, BANG, LIST
     - any
     - The message to convert. In a list, every A-Z becomes a-z and every other character is unchanged. A bang, an int or a float passes through as it is.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - ANY
     - —
     - The converted message, as a list with the same tokens and spacing. A bang, an int or a float leaves in its own type.



``.tosymbol``
-------------

Joins the tokens of a message into one symbol, with the separator between them: with separator /, 'voice 3 freq' becomes voice/3/freq. A number or a bang becomes the text that spells it.

:Kind: Control-rate

A symbol is a message of one token (see :doc:`/patcher/messages`). This
object makes one by joining the tokens of a message with its separator, so
the result can be matched by ``.route`` as one item, or used as a name. A
bang becomes the word ``bang`` and a number becomes its text. The result
always leaves as a list.

Runs of spaces count as one, and spaces at the ends are dropped, so the
result never holds an empty token.

**The separator**

The separator is the creation argument, and inlet 1 changes it. The default
is a single space, which leaves the tokens apart and only turns numbers and
bangs into text. An empty separator joins the tokens with nothing between
them: ``1 2 3 4`` becomes ``1234``. A separator is one token of at most 16
characters; a longer one is ignored (and logged when it is the argument).

``.fromsymbol`` with the same separator turns the result back into the
original message.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, BANG, LIST
     - —
     - The message to convert. A list has its tokens joined with the separator. A bang becomes the word bang, and a number becomes its text.
   * - 1
     - separator
     - FLOAT, INT, LIST
     - one token, at most 16 characters
     - Sets the separator and sends nothing. A list sets its first token, a number its text. An empty message sets an empty separator. A separator longer than 16 characters is ignored.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - ANY
     - —
     - The result, always as a list. With a separator that is not a space, it is one token.


**Parameters**

.. list-table::
   :header-rows: 1
   :widths: 22 18 18 42

   * - Name
     - Default
     - Range
     - Description
   * - separator
     -  
     - one token, at most 16 characters
     - The separator placed between tokens. A single space when not given, which only evens out the spacing.


``.toupper``
------------

Converts the letters a-z in a message to upper case and leaves everything else as it was: other characters, spacing and tokens. The mirror of .tolower.

:Kind: Control-rate

Works like ``.tolower`` in the other direction: only the letters a-z
change, and everything else, including letters outside ASCII, is left as it
was.

**Inlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Accepts
     - Range
     - Description
   * - 0
     - in
     - FLOAT, INT, BANG, LIST
     - any
     - The message to convert. In a list, every a-z becomes A-Z and every other character is unchanged. A bang, an int or a float passes through as it is.


**Outlets**

.. list-table::
   :header-rows: 1
   :widths: 6 18 18 18 40

   * - #
     - Label
     - Type
     - Range
     - Description
   * - 0
     - out
     - ANY
     - —
     - The converted message, as a list with the same tokens and spacing. A bang, an int or a float leaves in its own type.



