LibC: optimize strpbrk, str{,c}spn, strtok{,_r}

These matches are now detected with bitmasks instead of looping over the
second string
This commit is contained in:
Bananymous 2025-04-24 01:39:49 +03:00
parent 418678466c
commit 006a196e4a
1 changed files with 48 additions and 52 deletions

View File

@ -282,37 +282,39 @@ char* strstr(const char* haystack, const char* needle)
return nullptr; return nullptr;
} }
size_t strcspn(const char* s1, const char* s2) #define CHAR_UCHAR(ch) \
{ static_cast<unsigned char>(ch)
size_t i = 0;
for (; s1[i]; i++) #define CHAR_BITMASK(str) \
for (size_t j = 0; s2[j]; j++) uint32_t bitmask[0x100 / 32] {}; \
if (s1[i] == s2[j]) for (size_t i = 0; str[i]; i++) \
return i; bitmask[CHAR_UCHAR(str[i]) / 32] |= (1 << (CHAR_UCHAR(str[i]) % 32))
return i;
} #define CHAR_BITMASK_TEST(ch) \
(bitmask[CHAR_UCHAR(ch) / 32] & (1 << (CHAR_UCHAR(ch) % 32)))
char* strpbrk(const char* s1, const char* s2) char* strpbrk(const char* s1, const char* s2)
{ {
CHAR_BITMASK(s2);
for (size_t i = 0; s1[i]; i++) for (size_t i = 0; s1[i]; i++)
for (size_t j = 0; s2[j]; j++) if (CHAR_BITMASK_TEST(s1[i]))
if (s1[i] == s2[j]) return const_cast<char*>(&s1[i]);
return const_cast<char*>(s1 + i);
return nullptr; return nullptr;
} }
size_t strspn(const char* s1, const char* s2) size_t strspn(const char* s1, const char* s2)
{ {
size_t i = 0; CHAR_BITMASK(s2);
for (; s1[i]; i++) for (size_t i = 0;; i++)
{ if (s1[i] == '\0' || !CHAR_BITMASK_TEST(s1[i]))
bool found = false; return i;
for (size_t j = 0; s2[j] && !found; j++)
if (s1[i] == s2[j])
found = true;
if (!found)
break;
} }
size_t strcspn(const char* s1, const char* s2)
{
CHAR_BITMASK(s2);
for (size_t i = 0;; i++)
if (s1[i] == '\0' || CHAR_BITMASK_TEST(s1[i]))
return i; return i;
} }
@ -324,49 +326,43 @@ char* strtok(char* __restrict s, const char* __restrict sep)
char* strtok_r(char* __restrict str, const char* __restrict sep, char** __restrict state) char* strtok_r(char* __restrict str, const char* __restrict sep, char** __restrict state)
{ {
if (str) CHAR_BITMASK(sep);
{
while (*str)
{
bool found = false;
for (size_t i = 0; sep[i] && !found; i++)
if (*str == sep[i])
found = true;
if (!found)
break;
str++;
}
if (!*str) if (str)
*state = str;
if (*state == nullptr)
return nullptr;
str = *state;
for (; *str; str++)
if (!CHAR_BITMASK_TEST(*str))
break;
if (*str == '\0')
{ {
*state = nullptr; *state = nullptr;
return nullptr; return nullptr;
} }
*state = str;
}
if (!*state)
return nullptr;
str = *state;
for (size_t i = 0; str[i]; i++) for (size_t i = 0; str[i]; i++)
{ {
for (size_t j = 0; sep[j]; j++) if (!CHAR_BITMASK_TEST(str[i]))
{ continue;
if (str[i] == sep[j])
{
str[i] = '\0'; str[i] = '\0';
*state = str + i + 1; *state = str + i + 1;
return str; return str;
} }
}
}
*state = nullptr; *state = nullptr;
return str; return str;
} }
#undef CHAR_UCHAR
#undef CHAR_BITMASK
#undef CHAR_BITMASK_TEST
char* strsignal(int signum) char* strsignal(int signum)
{ {
static char buffer[128]; static char buffer[128];