Hi Bruno,

On 2026-02-25T08:09:46+0100, Bruno Haible wrote:
> Hi Alejandro,
> 
> > > Oh wait. Should we have called the new function stpnul() instead of 
> > > strnul()?
> > > Because it returns a pointer.
> > 
> > ... We have other
> > existing APIs that only have a variant that return an offset pointer,
> > and their name is str*(), strchr(3) being the canonical example.
> > stp*() would only be necessary where there's the two variants with the
> > same name.
> 
> OK for keeping strnul then.
> 
> Among the str* functions that return a pointer (strchr, strrchr, strdup,
> strpbrk, strstr), there is in particular strpbrk, which can be defined as
> 
>   char *
>   strpbrk (const char *s, const char *char_set)
>   {
>     size_t n = strcspn (s, char_set);
>     return s[n] ? (char *) &s[n] : NULL;
>   }
> 
> So, as I understand it,
>   - stpcspn would be a variant of strpbrk,
>   - but stpspn is not such a variant.

Your message prompted me to do some work in the manual pages, to clarify
the incestuous relationship between string APIs.  :)

> * If we add only the stpspn function, we'll have tricky-to-remember
>   differences between stpspn and strpbrk.

I've added the following text in strcspn(3):

            It is equivalent to

                (strpbrk(s, reject) ?: strnul(s)) ‐ s

stpspn(3) has no equivalence to anything else, and can only be
implemented with loops and byte operations.

Similarly, strpbrk(3) has no equivalence to anything else, and can only
be implemented with a loop.

> * Whereas if we add both the stpspn and stpcspn functions, we'll have
>   two functions stpcspn, strpbrk that are merely variants of each other.
> 
> Neither of which is super desirable.

Here's a diff of the most relevant changes.  I've documented the
equivalences of functions to others, wherever possible.  This should
help clarify the tricky-to-remember differences you mentioned in the
first point.

        $ MANWIDTH=64 diffman-git 6c600ed9a9bc HEAD | grep -v ^-
        +++ HEAD:man/man3/stpcpy.3
        @@ -24,18 +24,10 @@ DESCRIPTION
              stpcpy() is similar to strcpy(3), but returns a pointer to
              the terminating null byte in dst.
         
        +     It is equivalent to both of the following expressions:
         
        +         memset(mempcpy(dst, src, strlen(src)), '\0', 1);
        +         strcpy(dst, src) + strlen(dst)
         
         RETURN VALUE
              This function returns a pointer to the terminating null
        +++ HEAD:man/man3/stpncpy.3
        @@ -36,23 +36,16 @@ DESCRIPTION
              ter sequence is truncated.  For the difference between the
              two functions, see RETURN VALUE.
         
        +     strncpy()
        +            It is equivalent to
         
        +                stpncpy(dst, src, dsize), dst
         
        +     stpncpy()
        +            It is equivalent to
         
        +                memset(mempcpy(dst, src, strnlen(src, dsize)), '\0',
        +                       dsize - strnlen(src, dsize))
         
         RETURN VALUE
              strncpy()
        +++ HEAD:man/man3/strchr.3
        @@ -18,10 +18,20 @@ DESCRIPTION
                     first occurrence of the character c in the string
                     s.
         
        +            It is equivalent to both of the following expres‐
        +            sions:
        +
        +                memchr(s, c, strlen(s) + 1)
        +                strpbrk(s, (char [2]){c, '\0'})
        +
              strrchr()
                     The strrchr() function returns a pointer to the
                     last occurrence of the character c in the string s.
         
        +            It is equivalent to
        +
        +                memrchr(s, c, strlen(s) + 1)
        +
         RETURN VALUE
              The strchr() and strrchr() functions return a pointer to
              the matched character or NULL if the character is not
        +++ HEAD:man/man3/strchrnul.3
        @@ -17,6 +17,11 @@ DESCRIPTION
              c is not found in s, then it returns a pointer to the null
              byte at the end of s.
         
        +     It is equivalent to both of the following expressions:
        +
        +         strchr(s, c) ?: strnul(s)
        +         s + strcspn(s, (char [2]){c, '\0'})
        +
         RETURN VALUE
              The strchrnul() function returns a pointer to the matched
              character, or a pointer to the null byte at the end of s
        @@ -38,6 +43,6 @@ HISTORY
              glibc 2.1.1, FreeBSD 10, NetBSD 8.
         
         SEE ALSO
        +     string(3), strchr(3), strnul(3), strcspn(3), strspn(3)
         
         Linux man‐pages (unreleased) (date)                strchrnul(3)
        +++ HEAD:man/man3/strcmp.3
        @@ -28,11 +28,19 @@ DESCRIPTION
         
                     •  a positive value if s1 is greater than s2.
         
        +            It is equivalent to
        +
        +                memcmp(s1, s2, MIN(strlen(s1),strlen(s2))+1)
        +
              strncmp()
                     The strncmp() function is similar, except it com‐
                     pares only the first (at most) n bytes of s1 and
                     s2.
         
        +            It is equivalent to
        +
        +                memcmp(s1, s2, MIN(MIN(strnlen(s1,n),strnlen(s2,n))+1, 
n))
        +
         RETURN VALUE
              The strcmp() and strncmp() functions return an integer
              less than, equal to, or greater than zero if s1 (or the
        +++ HEAD:man/man3/strcpy.3
        @@ -19,6 +19,10 @@ DESCRIPTION
                     programmer is responsible for allocating a destina‐
                     tion buffer large enough, that is, strlen(src) + 1.
         
        +            It is equivalent to
        +
        +                stpcpy(dst, src), dst
        +
              strcat()
                     This function catenates the string pointed to by
                     src, after the string pointed to by dst (overwrit‐
        @@ -27,23 +31,9 @@ DESCRIPTION
                     large enough, that is, strlen(dst) + strlen(src) +
                     1.
         
        +            It is equivalent to
         
        +                stpcpy(strnul(dst), src), dst
         
         RETURN VALUE
              These functions return dst.
        +++ HEAD:man/man3/strdupa.3
        @@ -19,10 +19,18 @@ DESCRIPTION
                     strdupa() is similar to strdup(3), but uses al‐
                     loca(3) to allocate the buffer.
         
        +            It is equivalent to
        +
        +                strcpy(alloca(strlen(s) + 1), s)
        +
              strndupa()
                     strndupa() is similar to strndupa(3), but uses al‐
                     loca(3) to allocate the buffer.
         
        +            It is equivalent to
        +
        +                strncat(strcpy(alloca(n + 1), ""), s, n)
        +
         RETURN VALUE
              On success, these macros return a pointer to the dupli‐
              cated string.
        +++ HEAD:man/man3/streq.3
        @@ -15,6 +15,10 @@ DESCRIPTION
              streq() determines whether the strings s1 and s2 are
              equal.
         
        +     It is equivalent to
        +
        +         strcmp(s1, s2) == 0
        +
         RETURN VALUE
              streq() returns true if and only if the strings s1 and s2
              are equal.
        +++ HEAD:man/man3/strlen.3
        @@ -16,6 +16,10 @@ DESCRIPTION
              pointed to by s, excluding the terminating null byte
              ('\0').
         
        +     It is equivalent to
        +
        +         strnul(s) ‐ s
        +
         RETURN VALUE
              The strlen() function returns the number of bytes in the
              string pointed to by s.
        +++ HEAD:man/man3/strncat.3
        @@ -22,16 +22,9 @@ DESCRIPTION
              enough, that is, the buffer size must be at least
              strlen(dst) + strnlen(src, ssize) + 1.
         
        +     It is equivalent to
         
        +         stpcpy(mempcpy(strnul(dst), src, strnlen(src, ssize)), ""), 
dst
         
         RETURN VALUE
              strncat() returns dst.
        +++ HEAD:man/man3/strnlen.3
        @@ -27,6 +27,10 @@ DESCRIPTION
              looks only at the first maxlen characters in the string
              pointed to by s and never beyond s[maxlen-1].
         
        +     It is equivalent to
        +
        +         (memchr(s, '\0', maxlen) ?: s + maxlen) ‐ s
        +
         RETURN VALUE
              The strnlen() function returns strlen(s), if that is less
              than maxlen, or maxlen if there is no null terminating
        +++ HEAD:man/man3/strnul.3
        @@ -16,6 +16,11 @@ DESCRIPTION
              strnul() calculates the position of the terminating null
              byte ('\0') in the string pointed to by s.
         
        +     It is equivalent to both of the following expressions:
        +
        +         s + strlen(s)
        +         strchr(s, '\0')
        +
         RETURN VALUE
              strnul() returns a pointer to the terminating null byte in
              the string pointed to by s.
        +++ HEAD:man/man3/strspn.3
        @@ -23,6 +23,10 @@ DESCRIPTION
                     initial segment of s which consists entirely of
                     bytes not in reject.
         
        +            It is equivalent to
        +
        +                (strpbrk(s, reject) ?: strnul(s)) ‐ s
        +
         RETURN VALUE
              The strspn() function returns the number of bytes in the
              initial segment of s which consist only of bytes from ac‐
        +++ HEAD:man/man3/strstr.3
        @@ -21,6 +21,10 @@ DESCRIPTION
              substring needle in the string haystack.  The terminating
              null bytes ('\0') are not compared.
         
        +     It is equivalent to
        +
        +         memmem(haystack, strlen(haystack), needle, strlen(needle))
        +
              The strcasestr() function is like strstr(), but ignores
              the case of both arguments.
         

Have a lovely night!
Alex

-- 
<https://www.alejandro-colomar.es>

Attachment: signature.asc
Description: PGP signature

Reply via email to