Hi Paul,

There are other equality functions I've proposed for C2y:

        n3612, alx-0019r4 - add strpfx(), stppfx(), wcspfx(), and wcppfx()
        <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3612.txt>

        n3613, alx-0020r3 - add strsfx(), stpsfx(), wcssfx(), wcpsfx()
        <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3613.txt>

Ignoring the wide-string variants, that's:

        strpfx(), stppfx(), strsfx(), stpsfx()

The stp* variants return a pointer, while the str* variants return bool.
In the case of stppfx(), the pointer is to the first character after the
prefix in the string.  In the case of stpsfx(), the pointer is to the
first character in the suffix in the string.

stppfx() is useful for example for jumping over an optional prefix.
In shadow utils, we use it often as

        tty = stppfx(tty, "/dev/") ?: tty;

(although we have other uses too, of course.)

stpsfx() is useful for example for removing a suffix, although this is
less common.

        strcpy(stpsfx(s, sfx), "");

And of course, the stp* functions can be used for implementing the str*
variants, just by casting to bool.

The bool-returning variants are less necessary, but we found it would be
better to separate them, which would make grepping for different kinds
of code more easy, and also because someone could want to have prefix
and suffix callbacks that are compatible with streq().

Would you want to add these to the stringeq module?  Or maybe to
separate modules?  But these are quite related to streq(), so maybe they
could go in the same one.

I know you already have str_startswith() and str_endswith().  The issue
with those is that they're limited to returning a bool.  The pointers
are quite useful, IME.  And the reason we chose those names in the
committee --originally, the proposal was for stpprefix() and
strsuffix()-- is that those compacted names are usually avoided by users
as they know libc is more likely to take those.  Thus, there's less
existing code that would conflict with those names.  Plus, they're
consistent with the rest of libc.

Here are my implementations from shadow utils:

        alx@devuan:~/src/shadow/shadow/master$ grepc -tfd -h stppfx_ .
        inline const char *
        stppfx_(const char *s, const char *prefix)
        {
                if (strncmp(s, prefix, strlen(prefix)) != 0)
                        return NULL;

                return s + strlen(prefix);
        }
        alx@devuan:~/src/shadow/shadow/master$ grepc -tm -h stppfx .
        #define stppfx(s, prefix)                                             \
        ({                                                                    \
                const char  *p_;                                              \
                                                                              \
                p_ = stppfx_(s, prefix);                                      \
                                                                              \
                _Generic(s,                                                   \
                        const char *:                     p_,                 \
                        const void *:                     p_,                 \
                        char *:        const_cast(char *, p_),                \
                        void *:        const_cast(char *, p_)                 \
                );                                                            \
        })
        alx@devuan:~/src/shadow/shadow/master$ grepc -tfd -h strpfx .
        inline bool
        strpfx(const char *s, const char *prefix)
        {
                return stppfx(s, prefix);
        }
        alx@devuan:~/src/shadow/shadow/master$ grepc -tfd -h stpsfx_ .
        inline const char *
        stpsfx_(const char *str, const char *suffix)
        {
                ptrdiff_t  off;

                off = strlen(str) - strlen(suffix);
                if (off < 0)
                        return NULL;

                if (!streq(str + off, suffix))
                        return NULL;

                return str + off;
        }
        alx@devuan:~/src/shadow/shadow/master$ grepc -tm -h stpsfx .
        #define stpsfx(str, suffix)                                           \
        ({                                                                    \
                const char  *s_;                                              \
                                                                              \
                s_ = stpsfx_(str, suffix);                                    \
                                                                              \
                _Generic(str,                                                 \
                        const char *:                     s_,                 \
                        const void *:                     s_,                 \
                        char *:        const_cast(char *, s_),                \
                        void *:        const_cast(char *, s_)                 \
                );                                                            \
        })
        alx@devuan:~/src/shadow/shadow/master$ grepc -tfd -h strsfx .
        inline bool
        strsfx(const char *s, const char *suffix)
        {
                return stpsfx(s, suffix);
        }

Feel free to take those as-is, or do anything derived, or new; the GPL
license is good to me.

If you take those, please add

        Co-authored-by: Alejandro Colomar <a...@kernel.org>

or anything equivalent.

I can send patches myself if you prefer too.


Have a lovely night!
Alex

-- 
<https://www.alejandro-colomar.es>
Use port 80 (that is, <...:80/>).

Attachment: signature.asc
Description: PGP signature

Reply via email to