On 2026-02-25T23:28:22+0100, Alejandro Colomar wrote:
> 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.
> 

Here's a table of several string functions, and their equivalences (when
they're trivial):


Complex functions
=================
        strpbrk(3)              // C89
        strspn(3)               // C89
        stprspn()
                strnul(s) - strrspn(s, accept)
        stprcspn()
                strnul(s) - strrcspn(s, reject)
        strsuffix()
        strdup(3)               // C23
        aprintf()
        strtok(3)               // C89
        strsep(3)               // GNU, BSD

        I ignored stuff that depends on the locale, such as strcoll(3).

Simple functions
================

Search
        strchr(3)               // C89
                memchr(s, c, strlen(s) + 1)
                strpbrk(s, (char [2]){c, '\0'})
        strrchr(3)              // C89
                memrchr(s, c, strlen(s) + 1)
        strnul(3)               // GNU
                s + strlen(s)
                strchr(s, '\0')
        strlen(3)               // C89
                strnul(s) ‐ s
        strchrnul(3)            // GNU, BSD
                strchr(s, c) ?: strnul(s)
                s + strcspn(s, (char [2]){c, '\0'})
        stpspn()
                s + strspn(s, accept)
        strcspn(3)              // C89
                stpcspn(s, reject)
        stpcspn()
                strpbrk(s, reject) ?: strnul(s)
        strrspn()
                strnul(s) - stprspn(s, accept)
        strrcspn()
                strnul(s) - stprcspn(s, reject)
        strstr(3)               // C89
                memmem(haystack, strlen(haystack), needle, strlen(needle))
        strprefix()
                strncmp(s, prefix, strlen(prefix)) ? NULL : s + strlen(prefix)
Comparison
        strcmp(3)               // C89
                memcmp(s1, s2, MIN(strlen(s1),strlen(s2))+1)
        streq(3)                // GNU
                strcmp(s1, s2) == 0
Copy
        stpcpy(3)               // POSIX.1-2008
                memset(mempcpy(dst, src, strlen(src)), '\0', 1)
                strcpy(dst, src) + strlen(dst)
        strcpy(3)               // C89
                stpcpy(dst, src), dst
        strcat(3)               // C89
                stpcpy(strnul(dst), src), dst
Dup
        strdupa(3)              // GNU
                strcpy(alloca(strlen(s) + 1), s)
Separate
        stpsep()
                strpbrk(s, delim) ? stpcpy(strpbrk(s, delim), "") + 1 : NULL
                strsep(&s, delim), s



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

Attachment: signature.asc
Description: PGP signature

Reply via email to