[RFC v1 1/1] string: Add streq(), memeq(), wcseq(), wmemeq()

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Mon Sep 1 15:18:51 GMT 2025



On 01/09/25 11:33, Alejandro Colomar wrote:
> Hi Adhemerval,
> 
> On Mon, Sep 01, 2025 at 10:50:57AM -0300, Adhemerval Zanella Netto wrote:
>>
>>
>> On 30/08/25 15:47, Alejandro Colomar wrote:
>>> Hi,
>>>
>>> On Sat, Aug 30, 2025 at 08:46:10AM +0200, Alejandro Colomar wrote:
>>>> These inline functions serve the most common use case of the comparison
>>>> functions: test for equality.  It avoids the reversed return value that
>>>> confuses programmers.  Using these APIs will result in more readable
>>>> code, which in the end means safer code.
>>>
>>> I've built a glibc with these inline functions, and one with these
>>> implemented as macros.  The one with macros results in a smaller binary,
>>> so I guess I should implement them as macros.  Also, that removes the
>>> issue about bool/_Bool.
>>>
>>>
>>> Have a lovely night!
>>> Alex
>>>
>>>>
>>>> Signed-off-by: Alejandro Colomar <alx@kernel.org>
>>
>> Hi Alejandro,
>>
>> I am aware this is a RFC, but this patch triggered some CI issues [1], where
>> some old standard modes do not support '_Bool'.
> 
> Yup, I found some issues while running 'make check', although not in
> 'make'.  About the issues with _Bool, they seem to come from C++, not
> old versions of C.  AFAIK, _Bool is supported in GCC in every language
> version (except in pedantic C89 maybe?).

It is for C89 [1]:

:::: -std=c89 -D_GNU_SOURCE=1
In file included from ../include/string.h:60,
                 from ../inet/netinet/icmp6.h:22,
                 from ../include/netinet/icmp6.h:1,
                 from /tmp/cih_test_4ZNjF5.c:10:
../string/string.h:86:14: error: expected ';' before '_Bool'
   86 | static inline _Bool
      |              ^~~~~~
      |              ;
../string/string.h:172:14: error: expected ';' before '_Bool'
  172 | static inline _Bool
      |              ^~~~~~
      |              ;

[1] https://www.delorie.com/trybots/32bit/51367/inet-check-installed-headers-c.out

> 
> How would you proceed about bool?  I could add a macro, which would
> evaluate to an int instead of a bool, and would sovle this issue.
> However, I'm worried that this might burn that return type in stone,
> not allowing us to improve it.  I say a macro, because at least with
> a macro we'd have more chances of retrofitting a bool in the future,
> since there would be no function pointers around.

One option would to just enable these function for gnu89 or higher.

> 
> Should I do a bunch of #ifdef to check for __plusplus, or do you have
> a better way?  Ideally, I'd like to include <stdbool.h> form <string.h>,
> but the standard doesn't allow it.  (Note to self: propose to fix that
> in ISO C; standard headers should be allowed to include other standard
> headers.)  I think GCC should accept _Bool in C++ mode.  It would save
> us trouble.
> 
> Maybe a macro is fine for now?  Being a macro, we have more chances of
> improving it later.
> 
>> This is not a complete review, I am still not sure about these new functions.
>>
>> [1] https://www.delorie.com/trybots/32bit/51346/ 
> 
> I think that's not the right link, is it?

Oops, indeed. It is https://www.delorie.com/trybots/32bit/51367/

> 
> 
> Have a lovely day!
> Alex
> 
>>
>>>> ---
>>>>  string/string.h | 21 +++++++++++++++++++++
>>>>  wcsmbs/wchar.h  | 31 +++++++++++++++++++++++++++++++
>>>>  2 files changed, 52 insertions(+)
>>>>
>>>> diff --git a/string/string.h b/string/string.h
>>>> index df4d489556..7618c209dd 100644
>>>> --- a/string/string.h
>>>> +++ b/string/string.h
>>>> @@ -80,6 +80,16 @@ extern int memcmp (const void *__s1, const void *__s2, size_t __n)
>>>>  extern int __memcmpeq (const void *__s1, const void *__s2, size_t __n)
>>>>       __THROW __attribute_pure__ __nonnull ((1, 2));
>>>>  .
>>>> +#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)
>>>> +{
>>>> +  return __memcmpeq(__m1, __m2, __n) == 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Search N bytes of S for C.  */
>>>>  #ifdef __CORRECT_ISO_CPP_STRING_H_PROTO
>>>>  extern "C++"
>>>> @@ -155,6 +165,17 @@ extern char *strncat (char *__restrict __dest, const char *__restrict __src,
>>>>  /* Compare S1 and S2.  */
>>>>  extern int strcmp (const char *__s1, const char *__s2)
>>>>       __THROW __attribute_pure__ __nonnull ((1, 2));
>>>> +
>>>> +#ifdef __USE_GNU
>>>> +/* Compare S1 and S2 for equality.  */
>>>> +__attribute_pure__ __nonnull ((1, 2))
>>>> +static inline _Bool
>>>> +streq (const char *__s1, const char *__s2)
>>>> +{
>>>> +  return strcmp(__s1, __s2) == 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Compare N characters of S1 and S2.  */
>>>>  extern int strncmp (const char *__s1, const char *__s2, size_t __n)
>>>>       __THROW __attribute_pure__ __nonnull ((1, 2));
>>>> diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
>>>> index b31ca2d241..fe8899867f 100644
>>>> --- a/wcsmbs/wchar.h
>>>> +++ b/wcsmbs/wchar.h
>>>> @@ -129,6 +129,22 @@ extern wchar_t *wcsncat (wchar_t *__restrict __dest,
>>>>  /* Compare S1 and S2.  */
>>>>  extern int wcscmp (const wchar_t *__s1, const wchar_t *__s2)
>>>>       __THROW __attribute_pure__ __nonnull ((1, 2));
>>>> +
>>>> +#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)
>>>> +{
>>>> +  return wcscmp(__s1, __s2) == 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* 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));
>>>> @@ -283,6 +299,21 @@ 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__;
>>>>  
>>>> +#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)
>>>> +{
>>>> +  return wmemcmp(__m1, __m2, __n) == 0;
>>>> +}
>>>> +#endif
>>>> +
>>>>  /* Copy N wide characters of SRC to DEST.  */
>>>>  extern wchar_t *wmemcpy (wchar_t *__restrict __s1,
>>>>  			 const wchar_t *__restrict __s2, size_t __n) __THROW;
>>>> -- 
>>>> 2.50.1
>>>>
>>>
>>
> 



More information about the Libc-alpha mailing list