[RFC v2 0/3] string: Add *eq() static inline functions
Alejandro Colomar
alx@kernel.org
Tue Sep 2 10:43:42 GMT 2025
Hi!
This second revision has some improvements:
- Add *caseeq[_l]() variants.
- Define a __bool macro that does the right thing:
- Expands to bool in C++.
- Expands to _Bool in C.
- But in too old GCC/Clang versions, expands to int, which at least
works compatibly, for an __always_inline function, in which we
don't have ABI issues.
- In non-GCC/Clang, it expands to _Bool, hoping that the compiler
has the type.
- I've parenthesized the function names. This is so that existing
macros in the wild won't break with our definition. (But they
already broke the contract about reserved identifiers, so we might
want to break them explicitly, so that they realize that they should
remove/rename their macros; opinions?)
<https://sourceware.org/glibc/manual/latest/html_node/Reserved-Names.html>
See the range-diff below for the code differences.
I have also gone through the entire glibc, replacing most uses of *cmp()
functions with the new *eq() ones, as a test, to check that `make` and
`make check` are happy with these definitions. It all seems good.
That's not included in this patch set, but I could if there's interest.
Of course, I should write proper tests, but that was easier for a quick
test.
Also, while checking existing tests for *cmp() functions, I realized
there's something that looks like a typo. That's in the 3rd patch in
this series. Please check if that's really a typo, or something
intended.
Have a lovely day!
Alex
Alejandro Colomar (3):
cdefs: Add __bool
string: Add streq,memeq,wcseq,wmemeq,strcaseeq[_l],wcscaseeq[_l] APIs
tests-mbwc/tst_funcs.h: Fix typo
localedata/tests-mbwc/dat_wcscmp.c | 2 +-
misc/sys/cdefs.h | 12 +++++++++
string/string.h | 21 +++++++++++++++
string/strings.h | 21 +++++++++++++++
wcsmbs/wchar.h | 42 ++++++++++++++++++++++++++++++
5 files changed, 97 insertions(+), 1 deletion(-)
Range-diff against v1:
-: ---------- > 1: 12a7d56cff cdefs: Add __bool
1: ee2d993975 ! 2: 839b4c991d string: Add streq(), memeq(), wcseq(), wmemeq()
@@ Metadata
Author: Alejandro Colomar <alx@kernel.org>
## Commit message ##
- string: Add streq(), memeq(), wcseq(), wmemeq()
+ string: Add streq,memeq,wcseq,wmemeq,strcaseeq[_l],wcscaseeq[_l] APIs
These inline functions serve the most common use case of the comparison
- functions: test for equality. It avoids the reversed return value that
+ functions: test for equality. They avoid the reversed return value that
confuses programmers. Using these APIs will result in more readable
code, which in the end means safer code.
@@ string/string.h: extern int memcmp (const void *__s1, const void *__s2, size_t _
+#ifdef __USE_GNU
+/* Compare N bytes of M1 and M2 for equality. */
+__attribute_pure__ __nonnull ((1, 2))
-+static inline _Bool
-+memeq (const void *__m1, const void *__m2, size_t __n)
++static __always_inline __bool
++(memeq) (const void *__m1, const void *__m2, size_t __n)
+{
+ return __memcmpeq(__m1, __m2, __n) == 0;
+}
@@ string/string.h: extern char *strncat (char *__restrict __dest, const char *__re
+#ifdef __USE_GNU
+/* Compare S1 and S2 for equality. */
+__attribute_pure__ __nonnull ((1, 2))
-+static inline _Bool
-+streq (const char *__s1, const char *__s2)
++static __always_inline __bool
++(streq) (const char *__s1, const char *__s2)
+{
+ return strcmp(__s1, __s2) == 0;
+}
@@ string/string.h: extern char *strncat (char *__restrict __dest, const char *__re
extern int strncmp (const char *__s1, const char *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
+ ## string/strings.h ##
+@@ string/strings.h: __extension__ extern int ffsll (long long int __ll)
+ extern int strcasecmp (const char *__s1, const char *__s2)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+
++#ifdef _USE_GNU
++/* Compare S1 and S2 for equality, ignoring case. */
++__attribute_pure__ __nonnull ((1, 2))
++static __always_inline __bool
++(strcaseeq) (const char *__s1, const char *__s2)
++{
++ return strcasecmp(__s1, __s2) == 0;
++}
++#endif
++
+ /* Compare no more than N chars of S1 and S2, ignoring case. */
+ extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2));
+@@ string/strings.h: extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
+ extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
+ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
+
++#ifdef _USE_GNU
++/* Compare S1 and S2 for equality, ignoring case,
++ using collation rules from LOC. */
++__attribute_pure__ __nonnull ((1, 2, 3))
++static __always_inline __bool
++(strcaseeq_l) (const char *__s1, const char *__s2, locale_t __loc)
++{
++ return strcasecmp_l(__s1, __s2, __loc) == 0;
++}
++#endif
++
+ /* Compare no more than N chars of S1 and S2, ignoring case, using
+ collation rules from LOC. */
+ extern int strncasecmp_l (const char *__s1, const char *__s2,
+
## wcsmbs/wchar.h ##
@@ wcsmbs/wchar.h: extern wchar_t *wcsncat (wchar_t *__restrict __dest,
/* Compare S1 and S2. */
@@ wcsmbs/wchar.h: extern wchar_t *wcsncat (wchar_t *__restrict __dest,
+#ifdef __USE_GNU
+/* Compare S1 and S2 for equality. */
+__attribute_pure__ __nonnull ((1, 2))
-+static inline
-+# ifdef __cplusplus
-+bool
-+# else
-+_Bool
-+# endif
-+wcseq (const wchar_t *__s1, const wchar_t *__s2)
++static __always_inline __bool
++(wcseq) (const wchar_t *__s1, const wchar_t *__s2)
+{
+ return wcscmp(__s1, __s2) == 0;
+}
@@ wcsmbs/wchar.h: extern wchar_t *wcsncat (wchar_t *__restrict __dest,
/* Compare N wide-characters of S1 and S2. */
extern int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
+@@ wcsmbs/wchar.h: extern int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
+ /* Compare S1 and S2, ignoring case. */
+ extern int wcscasecmp (const wchar_t *__s1, const wchar_t *__s2) __THROW;
+
++#ifdef _USE_GNU
++/* Compare S1 and S2 for equality, ignoring case. */
++__attribute_pure__ __nonnull ((1, 2))
++static __always_inline __bool
++(wcscaseeq) (const wchar_t *__s1, const wchar_t *__s2)
++{
++ return wcscasecmp(__s1, __s2) == 0;
++}
++#endif
++
+ /* Compare no more than N chars of S1 and S2, ignoring case. */
+ extern int wcsncasecmp (const wchar_t *__s1, const wchar_t *__s2,
+ size_t __n) __THROW;
+@@ wcsmbs/wchar.h: extern int wcsncasecmp (const wchar_t *__s1, const wchar_t *__s2,
+ extern int wcscasecmp_l (const wchar_t *__s1, const wchar_t *__s2,
+ locale_t __loc) __THROW;
+
++#ifdef _USE_GNU
++/* Compare S1 and S2 for equality, ignoring case,
++ using collation rules from LOC. */
++__attribute_pure__ __nonnull ((1, 2, 3))
++static __always_inline __bool
++(wcscaseeq_l) (const wchar_t *__s1, const wchar_t *__s2, locale_t __loc)
++{
++ return wcscasecmp_l(__s1, __s2, __loc) == 0;
++}
++#endif
++
+ extern int wcsncasecmp_l (const wchar_t *__s1, const wchar_t *__s2,
+ size_t __n, locale_t __loc) __THROW;
+ #endif
@@ wcsmbs/wchar.h: extern wchar_t *wmemchr (const wchar_t *__s, wchar_t __c, size_t __n)
extern int wmemcmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
__THROW __attribute_pure__;
@@ wcsmbs/wchar.h: extern wchar_t *wmemchr (const wchar_t *__s, wchar_t __c, size_t
+#ifdef __USE_GNU
+/* Compare N wide characters of M1 and M2 for equality. */
+__attribute_pure__ __nonnull ((1, 2))
-+static inline
-+# ifdef __cplusplus
-+bool
-+# else
-+_Bool
-+# endif
-+wmemeq (const wchar_t *__m1, const wchar_t *__m2, size_t __n)
++static __always_inline __bool
++(wmemeq) (const wchar_t *__m1, const wchar_t *__m2, size_t __n)
+{
+ return wmemcmp(__m1, __m2, __n) == 0;
+}
-: ---------- > 3: c40363ebbc tests-mbwc/tst_funcs.h: Fix typo
--
2.50.1
More information about the Libc-alpha
mailing list