typedef sz_status_t(*) sz_kernel_utf8_seek_t(sz_cptr_t, sz_size_t, sz_size_t, sz_cptr_t *, sz_stream_t); Splitting Unicode text into the units a human actually perceives is deceptively hard, and getting it wrong corrupts data.
A single emoji can be dozens of bytes and several codepoints yet one perceived character, CJK runs carry no spaces, and a period is not always the end of a sentence.
StringZilla ships the real algorithms — UAX-29 graphemes, words, and sentences, plus UAX-14 line-break opportunities — as lazy ranges that borrow from the source and yield one sz::string_view_t per segment with no per-segment allocation.
A string’s length is really three different numbers, and only the grapheme count matches what a user sees:
#include <stringzilla/stringzilla.hpp>
#include <cassert>
namespace sz = ashvardanian::stringzilla;
int main() {
sz::string_view_t family = "👨👩👧👦"; // one emoji, one perceived character
std::size_t codepoints = 0;
for (sz_rune_t r : family.utf8_runes()) (void)r, ++codepoints;
std::size_t graphemes = 0;
for (sz::string_view_t g : family.utf8_graphemes()) (void)g, ++graphemes;
assert(family.size() == 25); // 25 bytes on the wire
assert(codepoints == 7); // four people joined by three zero-width joiners
assert(graphemes == 1); // one grapheme cluster
return 0;
}This is exactly why truncating by bytes or codepoints tears emoji apart — it can slice a skin-tone modifier off its base, or split a flag in half. Iterating graphemes lets you cut on a real boundary:
sz::string_view_t msg = "🙏🏽👍🏿✨ thanks";
std::size_t cut = 0, seen = 0;
for (sz::string_view_t g : msg.utf8_graphemes()) { if (seen++ == 3) break; cut += g.size(); }
assert(msg.sub(0, cut) == "🙏🏽👍🏿✨"); // the three emoji keep their skin-tone modifiersWord and sentence boundaries are just as treacherous: contractions, CJK, decimals, and URLs all defeat naive splitting.
UAX-29 keeps can't whole while separating CJK ideographs that no space divides, and refuses to break a sentence inside $9.99:
sz::string_view_t phrase = "can't stop 北京!";
assert(*phrase.utf8_wordbreaks().begin() == "can't"); // apostrophe is interior; 北 and 京 split apart
sz::string_view_t prose = "She paid $9.99. Cheap.";
std::size_t sentences = 0;
for (sz::string_view_t s : prose.utf8_sentences()) (void)s, ++sentences;
assert(sentences == 2); // the dot inside $9.99 is not a sentence breakThe full family of ranges, each borrowing from the source and yielding sz::string_view_t segments, or sz_rune_t for runes.
Naming follows one rule: the bare name (newlines/whitespaces/delimiters) yields the separators the kernel finds, while split_* yields the content between them:
utf8_runes()— every codepoint as a decodedsz_rune_tUTF-32 scalar, with U+FFFD for ill-formed bytes and a truncated tail.utf8_graphemes()— UAX-29 grapheme clusters, the user-perceived characters.utf8_wordbreaks()— all UAX-29 word segments (words and the separators between them).utf8_sentences()— UAX-29 sentence boundaries.utf8_linebreaks()— UAX-14 line-break opportunities, both hard breaks and soft wrap points.utf8_split_newlines()/utf8_newlines()— content between the seven Unicode newlines (CRLF as one), or the newline runs themselves.utf8_split_whitespaces()/utf8_whitespaces()— content between Unicode “White_Space” runs (tokens), or the whitespace runs.utf8_split_delimiters()/utf8_delimiters()— content between any Unicode punctuation/symbol/separator, or the delimiter runs.
On any split_* range, .skip_empty() drops empty segments and .with_separators() interleaves segments and separators losslessly (concatenation reconstructs the input).
The utf8_wordbreaks, utf8_graphemes, utf8_sentences, and utf8_linebreaks ranges tile the input — every byte belongs to exactly one segment, with no gaps and no empty slices.
Because every range borrows and walks the buffer once, segmenting a multi-megabyte document into graphemes or words allocates nothing.
In C, sz_utf8_graphemes_best and its three tiling siblings write one length per segment, each segment starting where the previous one ended, so after a full batch the caller resumes at the sum of its lengths.
The newline, whitespace and delimiter finders write offsets and lengths of their matches, and after a full batch bytes_consumed ends exactly at the last match; otherwise it is the whole input. sz_utf8_decode_best treats the end of the text as the end of the input, decoding a truncated final sequence to one U+FFFD, so a caller feeding it chunks splits them at a rune boundary.
API
Types
sz_kernel_utf8_seek_tSignature of the kernels behind sz_utf8_seek_best.
sz_kernel_utf8_decode_tSignature of the kernels behind sz_utf8_decode_best.
typedef sz_status_t(*) sz_kernel_utf8_decode_t(sz_cptr_t, sz_size_t, sz_rune_t *, sz_size_t, sz_size_t *, sz_size_t *, sz_stream_t); sz_kernel_utf8_segmenter_tSignature of the tiling segmenters - graphemes, words, sentences, lines.
typedef sz_status_t(*) sz_kernel_utf8_segmenter_t(sz_cptr_t, sz_size_t, sz_size_t *, sz_size_t, sz_size_t *, sz_stream_t); Emits one length per segment and their count; each segment starts where the previous one ended.
sz_kernel_utf8_tokenizer_tSignature of the token kernels - newlines, whitespace, delimiters.
typedef sz_status_t(*) sz_kernel_utf8_tokenizer_t(sz_cptr_t, sz_size_t, sz_size_t *, sz_size_t *, sz_size_t, sz_size_t *, sz_size_t *, sz_stream_t); Emits parallel (offset, length) arrays for each match, their count, and a resume bytes_consumed.
Functions
sz_utf8_seek_bestSkip forward to the Nth UTF-8 character.
sz_status_t sz_utf8_seek_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t n,
sz_cptr_t *position,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_seekserialhaswellicelakeneonsve2rvvv128v128relaxedloongsonasxpowervsx
Skipping to character 1000, e.g. for pagination:
char const *position;
sz_utf8_seek_best(text, length, 1000, &position, capabilities, NULL);
if (!position) {
// String has fewer than 1000 characters
}Truncating to 280 characters, Twitter-style:
char const *end;
sz_utf8_seek_best(text, length, 280, &end, capabilities, NULL);
size_t truncated_bytes = end ? (end - text) : length;Parameters
text | in | String to be scanned. |
|---|---|---|
length | in | Number of bytes in the string. |
n | in | Number of UTF-8 characters to skip, 0-indexed, so n = 0 yields text. |
position | out | The Nth character, or NULL if the string has fewer than n characters. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_decode_bestUnpack a UTF-8 string into UTF-32 codepoints.
sz_status_t sz_utf8_decode_best(
sz_cptr_t text,
sz_size_t length,
sz_rune_t *runes,
sz_size_t runes_capacity,
sz_size_t *runes_count,
sz_size_t *bytes_consumed,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_decodeserialhaswellicelakeneonsve2rvvv128loongsonasxpowervsx
This function is designed for streaming-like decoding with smart iterators built on top of it. The iterator would unpack a continuous slice of UTF-8 text into UTF-32 codepoints in chunks, yielding them upstream - only one at a time. This avoids allocating large buffers for the entire UTF-32 string, which can be 4x the size of the UTF-8 input.
This functionality is similar to the simdutf library's UTF-8 to UTF-32 conversion routines, and leverages an assumption that the absolute majority of written text doesn't mix codepoints of every length in each register-sized chunk:
- English text and source code is predominantly 1-byte ASCII characters.
- Broader European languages with diacritics: mostly 2-byte characters, 1-byte punctuation.
- Chinese & Japanese mostly use 3-byte characters with rare 1- or 3-byte punctuation.
- Korean uses 3-byte characters with 1-byte spaces; word are 2-6 syllables or 6-16 bytes.
It's a different story for emoji-heavy texts, which can mix 4-byte characters more frequently.
Every backend shares one contract, the basis for every codepoint iterator built on it:
- Fill-or-drain: emits runes until
runes_capacityis reached ortextis exhausted, looping internally - one call fills the buffer however many byte-widths the text mixes. - Total and safe: never reads past
text + length; substitutes one U+FFFD per maximal ill-formed subpart (overlong, surrogate, out-of-range, or a stray byte) and resyncs. - Valid scalar values: every emitted rune is a Unicode scalar value (incl. U+FFFD), so callers may convert without re-validation.
End of text is end of input: a well-formed but truncated final sequence decodes to one U+FFFD over its maximal subpart and is consumed, so "a\xE2\x82" yields {'a', U+FFFD} over all 3 bytes. Only a full runes buffer stops early, so bytes_consumed falls short of length only when runes_count reaches runes_capacity, and then at a rune boundary. Callers decoding a stream in chunks split it at a rune boundary.
Parameters
text | in | UTF-8 string to unpack. |
|---|---|---|
length | in | Number of bytes in the string. |
runes | out | Buffer for UTF-32 codepoints, recommended to be at least 64 entries wide. |
runes_capacity | in | Capacity of the runes buffer, in sz_rune_t entries. |
runes_count | out | Number of runes unpacked. |
bytes_consumed | out | Bytes of text decoded, the offset the next call resumes at. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_*_find_kernel× 2Finds the UTF-8 runes kernel of kind, from the best of capabilities.
sz_status_t sz_utf8_runes_find_kernel(
sz_kernel_kind_t kind,
sz_capability_t capabilities,
sz_kernel_punned_t *kernel,
sz_capability_t *capability); | Symbol |
|---|
sz_utf8_runes_find_kernel |
sz_utf8_tokens_find_kernel |
Parameters
kind | in | The verb whose kernel to find. |
|---|---|---|
capabilities | in | The mask to pick the best capability from. |
kernel | out | The kernel, or null when none of capabilities has it. |
capability | out | The capability the kernel belongs to, or zero. |
Statuses
sz_missing_kernel_ksz_missing_library_kHeader-only.
sz_utf8_newlines_bestEnumerates every UTF-8 newline delimiter in a string.
sz_status_t sz_utf8_newlines_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *match_offsets,
sz_size_t *match_lengths,
sz_size_t matches_capacity,
sz_size_t *matches_count,
sz_size_t *bytes_consumed,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_newlinesserialhaswellicelakeneonsve2rvvv128loongsonasxpowervsx
Enumerates every newline delimiter in a single sweep: writes the byte offset and byte length of each match into the parallel match_offsets and match_lengths arrays, a "\r\n" CRLF being one match of length 2, and their number into matches_count. A caller resuming from text + *bytes_consumed after a full output obtains the identical remainder.
Here are all the UTF-8 newline characters we are looking for (7 characters + CRLF):
single-byte chars (4 total):
- U+000A for
"\n"(LINE FEED) - U+000B for
"\v"(VERTICAL TAB / LINE TABULATION) - U+000C for
"\f"(FORM FEED) - U+000D for
"\r"(CARRIAGE RETURN)
- U+000A for
double-byte chars (1 total):
- U+0085 for
0xC285(NEXT LINE)
- U+0085 for
triple-byte chars (2 total):
- U+2028 for
0xE280A8(LINE SEPARATOR) - U+2029 for
0xE280A9(PARAGRAPH SEPARATOR)
- U+2028 for
double-character sequence:
- U+000D U+000A for
"\r\n"that should be treated as a single new line!
- U+000D U+000A for
U+001C, U+001D, U+001E (FILE/GROUP/RECORD SEPARATOR) are not included. These are data structure delimiters used in formats like USV (Unicode Separated Values), not line breaks. Use sz_find_byte_best if you need to find these separators.
Parameters
text | in | String to be scanned. |
|---|---|---|
length | in | Number of bytes in the string. |
match_offsets | out | Delimiter start offsets, at least matches_capacity entries. |
match_lengths | out | Delimiter byte lengths, at least matches_capacity entries. |
matches_capacity | in | Capacity of the output arrays. |
matches_count | out | Number of delimiters written to the output arrays. |
bytes_consumed | out | Optional resume offset: once matches_count reaches matches_capacity, the end of the last match, or zero with no capacity; else length. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_whitespaces_bestEnumerates every UTF-8 whitespace delimiter in a string.
sz_status_t sz_utf8_whitespaces_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *match_offsets,
sz_size_t *match_lengths,
sz_size_t matches_capacity,
sz_size_t *matches_count,
sz_size_t *bytes_consumed,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_whitespacesserialhaswellicelakeneonsve2rvvv128loongsonasxpowervsx
Enumerates every whitespace delimiter in a single sweep, with the same contract as sz_utf8_newlines_best: writes the byte offset and byte length of each match into the parallel match_offsets and match_lengths arrays, their number into matches_count, and sets bytes_consumed to the resume offset. Each whitespace codepoint is one match: CR and LF are independent length-1 matches, as there is no CRLF merging in the whitespace set.
Implements the Unicode White_Space property, 25 characters in total. Per the Unicode standard, whitespace includes all newline characters plus horizontal spaces. Matches the behavior of ICU's u_isspace() and Python's str.isspace().
single-byte chars (6 total):
- U+0009 tab
"\t"(CHARACTER TABULATION) - U+000A
"\n"(LINE FEED - newline) - U+000B
"\v"(LINE TABULATION - newline) - U+000C
"\f"(FORM FEED - newline) - U+000D
"\r"(CARRIAGE RETURN - newline) - U+0020 (SPACE)
- U+0009 tab
double-byte chars (2 total):
- U+0085
0xC285(NEXT LINE - newline) - U+00A0
0xC2A0(NO-BREAK SPACE)
- U+0085
triple-byte chars (17 total):
- U+1680
0xE19A80(OGHAM SPACE MARK) - U+2000
0xE28080(EN QUAD) - U+2001
0xE28081(EM QUAD) - U+2002
0xE28082(EN SPACE) - U+2003
0xE28083(EM SPACE) - U+2004
0xE28084(THREE-PER-EM SPACE) - U+2005
0xE28085(FOUR-PER-EM SPACE) - U+2006
0xE28086(SIX-PER-EM SPACE) - U+2007
0xE28087(FIGURE SPACE) - U+2008
0xE28088(PUNCTUATION SPACE) - U+2009
0xE28089(THIN SPACE) - U+200A
0xE2808A(HAIR SPACE) - U+2028
0xE280A8(LINE SEPARATOR - newline) - U+2029
0xE280A9(PARAGRAPH SEPARATOR - newline) - U+202F
0xE280AF(NARROW NO-BREAK SPACE) - U+205F
0xE2819F(MEDIUM MATHEMATICAL SPACE) - U+3000
0xE38080(IDEOGRAPHIC SPACE)
- U+1680
The last one, the IDEOGRAPHIC SPACE (U+3000), is commonly used in East Asian typography, like Japanese formatted text or Chinese traditional poetry alignments.
Some implementations treat more codepoints as whitespace, but these are not included:
- U+001C, U+001D, U+001E, U+001F (FILE/GROUP/RECORD/UNIT SEPARATOR) are data structure delimiters for formats like USV (Unicode Separated Values). Only Java's
Character.isWhitespace()includes them; Unicode, ICU, and Python do not. - U+200B, U+200C, U+200D (ZERO WIDTH SPACE/NON-JOINER/JOINER) are Format characters, not whitespace. They have no width and affect rendering rather than spacing.
Parameters
text | in | String to be scanned. |
|---|---|---|
length | in | Number of bytes in the string. |
match_offsets | out | Delimiter start offsets, at least matches_capacity entries. |
match_lengths | out | Delimiter byte lengths, at least matches_capacity entries. |
matches_capacity | in | Capacity of the output arrays. |
matches_count | out | Number of delimiters written to the output arrays. |
bytes_consumed | out | Optional resume offset: once matches_count reaches matches_capacity, the end of the last match, or zero with no capacity; else length. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_delimiters_bestEnumerates every UTF-8 delimiter codepoint (punctuation, symbol, separator, whitespace).
sz_status_t sz_utf8_delimiters_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *match_offsets,
sz_size_t *match_lengths,
sz_size_t matches_capacity,
sz_size_t *matches_count,
sz_size_t *bytes_consumed,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_delimitersserialhaswellicelakeneonsve2rvvv128loongsonasxpowervsx
The general superset of sz_utf8_newlines_best and sz_utf8_whitespaces_best: every codepoint whose Unicode general category is a punctuation (P*), symbol (S*), or separator (Z*) is a delimiter. Shares the contract of sz_utf8_newlines_best: writes the byte offset and byte length of each match into the parallel match_offsets and match_lengths arrays, their number into matches_count, and sets bytes_consumed to the resume offset. A byte that does not begin a well-formed codepoint is skipped and never reported.
Parameters
text | in | String to be scanned. |
|---|---|---|
length | in | Number of bytes in the string. |
match_offsets | out | Delimiter start offsets, at least matches_capacity entries. |
match_lengths | out | Delimiter byte lengths, at least matches_capacity entries. |
matches_capacity | in | Capacity of the output arrays. |
matches_count | out | Number of delimiters written to the output arrays. |
bytes_consumed | out | Optional resume offset: once matches_count reaches matches_capacity, the end of the last match, or zero with no capacity; else length. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_wordbreaks_bestSegment UTF-8 text into UAX-29 words in a single pass.
sz_status_t sz_utf8_wordbreaks_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *lengths,
sz_size_t capacity,
sz_size_t *count,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_wordbreaksserialhaswellicelakeneonsve2rvvv128loongsonasxpowervsx
Walks the input left-to-right and writes the byte length of each word into lengths. Words are the spans between consecutive TR29 boundaries and tile the input: each starts where the previous one ended, the first at text. A call covers all of text unless it fills lengths, in which case it covers the sum of the lengths it wrote, and the caller resumes from text advanced by that sum.
Parameters
text | in | UTF-8 encoded text. |
|---|---|---|
length | in | Byte length of text. |
lengths | out | Word byte lengths, at least capacity entries. |
capacity | in | Capacity of lengths, in entries. |
count | out | Number of words written, at most capacity. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Notes
No zero-length words are emitted; length == 0 yields no words.
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_wordbreaks_find_kernelFinds the UTF-8 word break kernel of kind, from the best of capabilities.
sz_status_t sz_utf8_wordbreaks_find_kernel(
sz_kernel_kind_t kind,
sz_capability_t capabilities,
sz_kernel_punned_t *kernel,
sz_capability_t *capability); Parameters
kind | in | The verb whose kernel to find. |
|---|---|---|
capabilities | in | The mask to pick the best capability from. |
kernel | out | The kernel, or null when none of capabilities has it. |
capability | out | The capability the kernel belongs to, or zero. |
Statuses
sz_missing_kernel_ksz_missing_library_kHeader-only.
sz_utf8_graphemes_bestSegment UTF-8 text into UAX-29 grapheme clusters in a single pass.
sz_status_t sz_utf8_graphemes_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *lengths,
sz_size_t capacity,
sz_size_t *count,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_graphemesserialhaswellicelakeneonsve2
Walks the input left-to-right and writes the byte length of each grapheme cluster into lengths. Clusters are the spans between consecutive UAX-29 grapheme boundaries (GB1-GB999) and tile the input: each starts where the previous one ended, the first at text. A call covers all of text unless it fills lengths, in which case it covers the sum of the lengths it wrote, and the caller resumes from text advanced by that sum.
Parameters
text | in | UTF-8 encoded text. |
|---|---|---|
length | in | Byte length of text. |
lengths | out | Cluster byte lengths, at least capacity entries. |
capacity | in | Capacity of lengths, in entries. |
count | out | Number of clusters written, at most capacity. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Notes
No zero-length clusters are emitted; length == 0 yields no clusters.
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_graphemes_find_kernelFinds the UTF-8 grapheme kernel of kind, from the best of capabilities.
sz_status_t sz_utf8_graphemes_find_kernel(
sz_kernel_kind_t kind,
sz_capability_t capabilities,
sz_kernel_punned_t *kernel,
sz_capability_t *capability); Parameters
kind | in | The verb whose kernel to find. |
|---|---|---|
capabilities | in | The mask to pick the best capability from. |
kernel | out | The kernel, or null when none of capabilities has it. |
capability | out | The capability the kernel belongs to, or zero. |
Statuses
sz_missing_kernel_ksz_missing_library_kHeader-only.
sz_utf8_sentences_bestSegment UTF-8 text into UAX-29 sentences in a single pass.
sz_status_t sz_utf8_sentences_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *lengths,
sz_size_t capacity,
sz_size_t *count,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_sentencesserialhaswellicelakeneonsve2
Walks the input left-to-right and writes the byte length of each sentence into lengths. Sentences are the spans between consecutive UAX-29 sentence boundaries (SB1-SB998) and tile the input: each starts where the previous one ended, the first at text. A call covers all of text unless it fills lengths, in which case it covers the sum of the lengths it wrote, and the caller resumes from text advanced by that sum.
Parameters
text | in | UTF-8 encoded text. |
|---|---|---|
length | in | Byte length of text. |
lengths | out | Sentence byte lengths, at least capacity entries. |
capacity | in | Capacity of lengths, in entries. |
count | out | Number of sentences written, at most capacity. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Notes
- No zero-length sentences are emitted;
length== 0 yields no sentences. - Sentence segmentation is forward-only.
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_sentences_find_kernelFinds the UTF-8 sentence kernel of kind, from the best of capabilities.
sz_status_t sz_utf8_sentences_find_kernel(
sz_kernel_kind_t kind,
sz_capability_t capabilities,
sz_kernel_punned_t *kernel,
sz_capability_t *capability); Parameters
kind | in | The verb whose kernel to find. |
|---|---|---|
capabilities | in | The mask to pick the best capability from. |
kernel | out | The kernel, or null when none of capabilities has it. |
capability | out | The capability the kernel belongs to, or zero. |
Statuses
sz_missing_kernel_ksz_missing_library_kHeader-only.
sz_utf8_linebreaks_bestSegment UTF-8 text into UAX-14 line-break opportunities in one pass.
sz_status_t sz_utf8_linebreaks_best(
sz_cptr_t text,
sz_size_t length,
sz_size_t *lengths,
sz_size_t capacity,
sz_size_t *count,
sz_capability_t capabilities,
sz_stream_t stream); Backends
sz_utf8_linebreaksserialhaswellicelakeneonsve2
Walks the input left-to-right and writes the byte length of each line segment into lengths. Segments are the spans between consecutive UAX-14 break opportunities and tile the input: each starts where the previous one ended, the first at text. A call covers all of text unless it fills lengths, in which case it covers the sum of the lengths it wrote, and the caller resumes from text advanced by that sum.
This emits every wrap opportunity (both the mandatory LB4/LB5 hard breaks and the allowed soft-wrap points). To split only on the hard breaks (the str.splitlines behavior) use sz_utf8_newlines_best instead, which enumerates exactly the LB4/LB5 break positions.
Parameters
text | in | UTF-8 encoded text. |
|---|---|---|
length | in | Byte length of text. |
lengths | out | Segment byte lengths, at least capacity entries. |
capacity | in | Capacity of lengths, in entries. |
count | out | Number of segments written, at most capacity. |
capabilities | in | One device's capabilities, like sz_capabilities_enabled_cpu reports. |
stream | in | Null on the CPU, or the GPU stream of that device to queue on. |
Notes
- No zero-length segments are emitted;
length== 0 yields no segments. - Line segmentation is forward-only.
Statuses
sz_missing_kernel_kNo capability incapabilitieshas it.
sz_utf8_linebreaks_find_kernelFinds the UTF-8 line break kernel of kind, from the best of capabilities.
sz_status_t sz_utf8_linebreaks_find_kernel(
sz_kernel_kind_t kind,
sz_capability_t capabilities,
sz_kernel_punned_t *kernel,
sz_capability_t *capability); Parameters
kind | in | The verb whose kernel to find. |
|---|---|---|
capabilities | in | The mask to pick the best capability from. |
kernel | out | The kernel, or null when none of capabilities has it. |
capability | out | The capability the kernel belongs to, or zero. |
Statuses
sz_missing_kernel_ksz_missing_library_kHeader-only.