perf(mbyte): annotate pure functions #41251

This commit is contained in:
Justin M. Keyes
2026-08-10 04:27:49 -04:00
committed by GitHub
parent 2546741d1b
commit 5287a04be4

View File

@@ -405,6 +405,7 @@ int bomb_size(void)
// Remove all BOM from "s" by moving remaining text.
void remove_bom(char *s)
FUNC_ATTR_NONNULL_ALL
{
char *p = s;
@@ -444,6 +445,7 @@ int mb_get_class_tab(const char *p, const uint64_t *const chartab)
}
static bool prop_is_emojilike(const utf8proc_property_t *prop)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
return prop->boundclass == UTF8PROC_BOUNDCLASS_EXTENDED_PICTOGRAPHIC
|| prop->boundclass == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR;
@@ -455,6 +457,7 @@ static bool prop_is_emojilike(const utf8proc_property_t *prop)
/// When p_ambw is "double", return 2 for a character with East Asian Width
/// class 'A'(mbiguous).
int utf_char2cells(int c)
FUNC_ATTR_PURE
{
if (c < 0x80) {
return 1;
@@ -492,6 +495,7 @@ int utf_char2cells(int c)
/// Return the number of display cells character at "*p" occupies.
/// This doesn't take care of unprintable characters, use ptr2cells() for that.
int utf_ptr2cells(const char *p_in)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
const uint8_t *p = (const uint8_t *)p_in;
// Need to convert to a character number.
@@ -592,6 +596,7 @@ ret:
/// Like utf_ptr2cells(), but limit string length to "size".
/// For an empty string or truncated character returns 1.
int utf_ptr2cells_len(const char *p, int size)
FUNC_ATTR_PURE
{
// Need to convert to a wide character.
if (size > 0 && (uint8_t)(*p) >= 0x80) {
@@ -628,6 +633,7 @@ int utf_ptr2cells_len(const char *p, int size)
/// string.
/// @return The number of cells occupied by string `str`
size_t mb_string2cells(const char *str)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
size_t clen = 0;
@@ -645,7 +651,7 @@ size_t mb_string2cells(const char *str)
/// @param size maximum length of string. It will terminate on earlier NUL.
/// @return The number of cells occupied by string `str`
size_t mb_string2cells_len(const char *str, size_t size)
FUNC_ATTR_NONNULL_ARG(1)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ARG(1)
{
size_t clen = 0;
@@ -741,6 +747,7 @@ int utf_ptr2char(const char *const p_in)
// If byte sequence is illegal or incomplete, returns -1 and does not advance
// "s".
static int utf_safe_read_char_adv(const char **s, size_t *n)
FUNC_ATTR_NONNULL_ARG(2)
{
if (*n == 0) { // end of buffer
return 0;
@@ -780,6 +787,7 @@ static int utf_safe_read_char_adv(const char **s, size_t *n)
// Get character at **pp and advance *pp to the next character.
// Note: composing characters are skipped!
int mb_ptr2char_adv(const char **const pp)
FUNC_ATTR_NONNULL_ALL
{
int c = utf_ptr2char(*pp);
*pp += utfc_ptr2len(*pp);
@@ -789,6 +797,7 @@ int mb_ptr2char_adv(const char **const pp)
// Get character at **pp and advance *pp to the next character.
// Note: composing characters are returned as separate characters.
int mb_cptr2char_adv(const char **pp)
FUNC_ATTR_NONNULL_ALL
{
int c = utf_ptr2char(*pp);
*pp += utf_ptr2len(*pp);
@@ -799,6 +808,7 @@ int mb_cptr2char_adv(const char **pp)
/// by a space byte to be drawn correctly, and not merge with the space left of
/// the string.
bool utf_iscomposing_first(int c)
FUNC_ATTR_PURE
{
return c >= 128 && !utf8proc_grapheme_break(' ', c);
}
@@ -898,6 +908,7 @@ schar_T utfc_ptrlen2schar(const char *p, int len, int *firstc)
/// Caller must ensure there is space for `first_compose`
static schar_T schar_from_buf_first(const char *buf, size_t len, bool first_compose)
FUNC_ATTR_NONNULL_ALL
{
if (first_compose) {
char cbuf[MAX_SCHAR_SIZE];
@@ -935,6 +946,7 @@ int utf_ptr2len(const char *const p_in)
// "b" must be between 0 and 255!
// Returns 1 for an invalid first byte value.
int utf_byte2len(int b)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return utf8len_tab[b];
}
@@ -946,6 +958,7 @@ int utf_byte2len(int b)
// Returns number > "size" for an incomplete byte sequence.
// Never returns zero.
int utf_ptr2len_len(const char *p, int size)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int m;
@@ -1008,6 +1021,7 @@ int utfc_ptr2len(const char *const p)
/// Returns 0 for an empty string.
/// Returns 1 for an illegal char or an incomplete byte sequence.
int utfc_ptr2len_len(const char *p, int size)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (size < 1 || *p == NUL) {
return 0;
@@ -1053,6 +1067,7 @@ int utfc_ptr2len_len(const char *p, int size)
/// Determine how many bytes certain unicode codepoint will occupy
int utf_char2len(const int c)
FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
{
if (c < 0x80) {
return 1;
@@ -1076,6 +1091,7 @@ int utf_char2len(const int c)
/// must have room for at least 6 bytes
/// @return Number of bytes (1-6).
int utf_char2bytes(const int c, char *const buf)
FUNC_ATTR_NONNULL_ALL
{
if (c < 0x80) { // 7 bits
buf[0] = (char)c;
@@ -1125,6 +1141,7 @@ int utf_char2bytes(const int c, char *const buf)
/// Based on code from Markus Kuhn.
/// Returns false for negative values.
bool utf_iscomposing_legacy(int c)
FUNC_ATTR_PURE
{
const utf8proc_property_t *prop = utf8proc_get_property(c);
return prop->category == UTF8PROC_CATEGORY_MN || prop->category == UTF8PROC_CATEGORY_ME;
@@ -1222,6 +1239,7 @@ bool utf_printable(int c)
// 1: punctuation
// 2 or bigger: some class of word character.
int utf_class(const int c)
FUNC_ATTR_PURE
{
return utf_class_tab(c, curbuf->b_chartab);
}
@@ -1344,6 +1362,7 @@ int utf_class_tab(const int c, const uint64_t *const chartab)
}
bool utf_ambiguous_width(const char *p)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
// be quick if there is nothing to print or ASCII-only
if (p[0] == NUL || p[1] == NUL) {
@@ -1366,6 +1385,7 @@ bool utf_ambiguous_width(const char *p)
// Return the folded-case equivalent of "a", which is a UCS-4 character. Uses
// full case folding.
int utf_fold(int a)
FUNC_ATTR_PURE
{
if (a < 0x80) {
// be fast for ASCII
@@ -1454,6 +1474,7 @@ bool mb_isalpha(int a)
}
int utf_strnicmp(const char *s1, const char *s2, size_t n1, size_t n2)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
int c1, c2;
char buffer[6];
@@ -1649,7 +1670,7 @@ void mb_utflen(const char *s, size_t len, size_t *codepoints, size_t *codeunits)
}
ssize_t mb_utf_index_to_bytes(const char *s, size_t len, size_t index, bool use_utf16_units)
FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
size_t count = 0;
size_t clen;
@@ -1680,6 +1701,7 @@ ssize_t mb_utf_index_to_bytes(const char *s, size_t len, size_t index, bool use_
/// @return zero if s1 and s2 are equal (ignoring case), the difference between
/// two characters otherwise.
int mb_strnicmp(const char *s1, const char *s2, const size_t nn)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return utf_strnicmp(s1, s2, nn, nn);
}
@@ -1697,6 +1719,7 @@ int mb_strnicmp(const char *s1, const char *s2, const size_t nn)
///
/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2.
int mb_stricmp(const char *s1, const char *s2)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
return mb_strnicmp(s1, s2, MAXCOL);
}
@@ -1741,6 +1764,7 @@ void show_utf8(void)
/// @return true if boundclass bc always starts a new cluster regardless of what's before
/// false negatives are allowed (perf cost, not correctness)
static bool always_break(int bc)
FUNC_ATTR_CONST
{
return (bc == UTF8PROC_BOUNDCLASS_CONTROL);
}
@@ -1748,6 +1772,7 @@ static bool always_break(int bc)
/// @return true if bc2 always starts a cluster after bc1
/// false negatives are allowed (perf cost, not correctness)
static bool always_break_two(int bc1, int bc2)
FUNC_ATTR_CONST
{
// don't check for UTF8PROC_BOUNDCLASS_CONTROL for bc2 as it either has been checked by
// "always_break" on first iteration or when it was bc1 in the previous iteration
@@ -1763,6 +1788,7 @@ static bool always_break_two(int bc1, int bc2)
/// If "p" points to the NUL at the end of the string return 0.
/// Returns 0 when already at the first byte of a character.
int utf_head_off(const char *base_in, const char *p_in)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ARG(2)
{
if ((uint8_t)(*p_in) < 0x80) { // be quick for ASCII
return 0;
@@ -1850,6 +1876,7 @@ int utf_head_off(const char *base_in, const char *p_in)
/// Assumes caller already handles ascii. see `utfc_next`
StrCharInfo utfc_next_impl(StrCharInfo cur)
FUNC_ATTR_PURE
{
int32_t prev_code = cur.chr.value;
uint8_t *next = (uint8_t *)(cur.ptr + cur.chr.len);
@@ -2022,6 +2049,7 @@ bool utf_allow_break(int cc, int ncc)
/// @param[in,out] fp Source of the character to copy.
/// @param[in,out] tp Destination to copy to.
void mb_copy_char(const char **const fp, char **const tp)
FUNC_ATTR_NONNULL_ALL
{
const size_t l = (size_t)utfc_ptr2len(*fp);
@@ -2034,6 +2062,7 @@ void mb_copy_char(const char **const fp, char **const tp)
/// at the start of a character 0 is returned, otherwise the offset to the next
/// character. Can start anywhere in a stream of bytes.
int mb_off_next(const char *base, const char *p)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ARG(2)
{
int head_off = utf_head_off(base, p);
@@ -2159,6 +2188,7 @@ theend:
/// @return true if string "s" is a valid utf-8 string.
/// When "end" is NULL stop at the first NUL. Otherwise stop at "end".
bool utf_valid_string(const char *s, const char *end)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ARG(1)
{
const uint8_t *p = (uint8_t *)s;
@@ -2227,6 +2257,7 @@ void mb_check_adjust_col(void *win_)
///
/// @return a pointer to the character before "*p", if there is one.
char *mb_prevptr(char *line, char *p)
FUNC_ATTR_PURE
{
if (p > line) {
MB_PTR_BACK(line, p);
@@ -2237,6 +2268,7 @@ char *mb_prevptr(char *line, char *p)
/// Return the character length of "str". Each multi-byte character (with
/// following composing characters) counts as one.
int mb_charlen(const char *str)
FUNC_ATTR_PURE
{
const char *p = str;
int count;
@@ -2254,6 +2286,7 @@ int mb_charlen(const char *str)
/// Like mb_charlen() but for a string with specified length.
int mb_charlen_len(const char *str, int len)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
const char *p = str;
int count;
@@ -2314,6 +2347,7 @@ const char *mb_unescape(const char **const pp)
/// Skip the Vim specific head of a 'encoding' name.
char *enc_skip(char *p)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
if (strncmp(p, "2byte-", 6) == 0) {
return p + 6;
@@ -2330,7 +2364,7 @@ char *enc_skip(char *p)
///
/// @return an allocated string.
char *enc_canonize(char *enc)
FUNC_ATTR_NONNULL_RET
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
if (strcmp(enc, "default") == 0) {
// Use the default encoding as found by set_init_1().
@@ -2392,6 +2426,7 @@ char *enc_canonize(char *enc)
/// Search for an encoding alias of "name".
/// Returns -1 when not found.
static int enc_alias_search(const char *name)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
for (int i = 0; enc_alias_table[i].name != NULL; i++) {
if (strcmp(name, enc_alias_table[i].name) == 0) {
@@ -2511,6 +2546,7 @@ void *my_iconv_open(char *to, char *from)
// If resultlenp is not NULL, sets it to the result length in bytes.
static char *iconv_string(const vimconv_T *const vcp, const char *str, size_t slen,
size_t *unconvlenp, size_t *resultlenp)
FUNC_ATTR_NONNULL_ARG(1)
{
char *to;
size_t len = 0;
@@ -2618,6 +2654,7 @@ void f_iconv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
///
/// @return FAIL when conversion is not supported, OK otherwise.
int convert_setup(vimconv_T *vcp, char *from, char *to)
FUNC_ATTR_NONNULL_ARG(1)
{
return convert_setup_ext(vcp, from, true, to, true);
}
@@ -2626,6 +2663,7 @@ int convert_setup(vimconv_T *vcp, char *from, char *to)
/// "from" unicode charsets be considered utf-8. Same for "to".
int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, char *to,
bool to_unicode_is_utf8)
FUNC_ATTR_NONNULL_ARG(1)
{
int from_is_utf8;
int to_is_utf8;
@@ -2862,6 +2900,7 @@ static size_t cw_table_size = 0;
/// @param c The source character.
/// @return 1 or 2 when `c` is in the cellwidth table, 0 if not.
static int cw_value(int c)
FUNC_ATTR_PURE
{
if (cw_table == NULL) {
return 0;
@@ -2889,6 +2928,7 @@ static int cw_value(int c)
}
static int tv_nr_compare(const void *a1, const void *a2)
FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
const listitem_T *const li1 = tv_list_first(*(const list_T **)a1);
const listitem_T *const li2 = tv_list_first(*(const list_T **)a2);
@@ -3041,6 +3081,7 @@ void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// encoding options.
char *get_encoding_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
FUNC_ATTR_PURE
{
if (idx >= (int)ARRAY_SIZE(enc_canon_table)) {
return NULL;