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/>).
signature.asc
Description: PGP signature