against timing attacks, so it compares all the bytes every time. */
bool mem_equals_timing_safe(const void *p1, const void *p2, size_t size);
+size_t str_match(const char *p1, const char *p2) ATTR_PURE;
+static inline ATTR_PURE bool str_begins(const char *haystack, const char *needle)
+{
+ return needle[str_match(haystack, needle)] == '\0';
+}
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+/* GCC (and Clang) are known to have a compile-time strlen("literal") shortcut, and
+ an optimised strncmp(), so use that by default. Macro is multi-evaluation safe. */
+# define str_begins(h, n) (__builtin_constant_p(n) ? strncmp((h), (n), strlen(n))==0 : (str_begins)((h), (n)))
+#endif
+
static inline char *i_strchr_to_next(const char *str, char chr)
{
char *tmp = (char *)strchr(str, chr);
test_end();
}
+static void
+test_str_match(void)
+{
+ static const struct {
+ const char*s1, *s2; size_t match;
+ } tests[] = {
+#define MATCH_TEST(common, left, right) { common left, common right, sizeof(common)-1 }
+ MATCH_TEST("", "", ""),
+ MATCH_TEST("", "x", ""),
+ MATCH_TEST("", "", "x"),
+ MATCH_TEST("", "foo", "bar"),
+ MATCH_TEST("x", "", ""),
+ MATCH_TEST("x", "y", "z"),
+ MATCH_TEST("blahblahblah", "", ""),
+ MATCH_TEST("blahblahblah", "", "bar"),
+ MATCH_TEST("blahblahblah", "foo", ""),
+ MATCH_TEST("blahblahblah", "foo", "bar"),
+#undef MATCH_TEST
+ };
+
+ unsigned int i;
+
+ test_begin("str_match");
+ for (i = 0; i < N_ELEMENTS(tests); i++)
+ test_assert_idx(str_match(tests[i].s1, tests[i].s2) == tests[i].match, i);
+ test_end();
+
+ test_begin("i_strbegins");
+ for (i = 0; i < N_ELEMENTS(tests); i++) {
+ /* This is just 2 ways of wording the same test, but that also
+ sanity tests the match values above. */
+ test_assert_idx(str_begins(tests[i].s1, tests[i].s2) ==
+ (strncmp(tests[i].s1, tests[i].s2, strlen(tests[i].s2)) == 0), i);
+ test_assert_idx(str_begins(tests[i].s1, tests[i].s2) ==
+ (strlen(tests[i].s2) == tests[i].match), i);
+ }
+ test_end();
+}
+
void test_strfuncs(void)
{
test_p_strdup();
test_p_array_const_string_join();
test_mem_equals_timing_safe();
test_dec2str_buf();
+ test_str_match();
}