From ce0163e02dde4c2521a7db984338a5c280b1def6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 20 Dec 2007 16:09:32 +1100 Subject: [PATCH] Add string helpers (actually needed up previous checkin) --- string/_info.c | 35 +++++++++++++++++++++ string/string.h | 46 ++++++++++++++++++++++++++++ string/test/run.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 string/_info.c create mode 100644 string/string.h create mode 100644 string/test/run.c diff --git a/string/_info.c b/string/_info.c new file mode 100644 index 00000000..2d1709f7 --- /dev/null +++ b/string/_info.c @@ -0,0 +1,35 @@ +#include +#include +#include "config.h" + +/** + * string - string helper routines + * + * This is a grab bag of modules for string comparisons, designed to enhance + * the standard string.h. + * + * Example: + * #include "ccan/string.h" + * + * int main(int argc, char *argv[]) + * { + * if (argv[1] && streq(argv[1], "--verbose")) + * printf("verbose set\n"); + * if (argv[1] && strstarts(argv[1], "--")) + * printf("Some option set\n"); + * if (argv[1] && strends(argv[1], "cow-powers")) + * printf("Magic option set\n"); + * return 0; + * } + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) + /* Nothing. */ + return 0; + + return 1; +} diff --git a/string/string.h b/string/string.h new file mode 100644 index 00000000..f4997c69 --- /dev/null +++ b/string/string.h @@ -0,0 +1,46 @@ +#ifndef CCAN_STRING_H +#define CCAN_STRING_H +#include +#include + +/** + * streq - Are two strings equal? + * @a: first string + * @b: first string + * + * This macro is arguably more readable than "!strcmp(a, b)". + * + * Example: + * if (streq(str, "")) + * printf("String is empty!\n"); + */ +#define streq(a,b) (strcmp((a),(b)) == 0) + +/** + * strstarts - Does this string start with this prefix? + * @str: string to test + * @prefix: prefix to look for at start of str + * + * Example: + * if (strstarts(str, "foo")) + * printf("String %s begins with 'foo'!\n", str); + */ +#define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0) + +/** + * strends - Does this string end with this postfix? + * @str: string to test + * @postfix: postfix to look for at end of str + * + * Example: + * if (strends(str, "foo")) + * printf("String %s end with 'foo'!\n", str); + */ +static inline bool strends(const char *str, const char *postfix) +{ + if (strlen(str) < strlen(postfix)) + return false; + + return streq(str + strlen(str) - strlen(postfix), postfix); +} +#endif /* CCAN_STRING_H */ diff --git a/string/test/run.c b/string/test/run.c new file mode 100644 index 00000000..8e7b2d19 --- /dev/null +++ b/string/test/run.c @@ -0,0 +1,77 @@ +#include +#include +#include "string/string.h" +#include "tap.h" + +/* FIXME: ccanize */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) + +static char *substrings[] = { "far", "bar", "baz", "b", "ba", "z", "ar" }; + +static char *strdup_rev(const char *s) +{ + char *ret = strdup(s); + unsigned int i; + + for (i = 0; i < strlen(s); i++) + ret[i] = s[strlen(s) - i - 1]; + return ret; +} + +int main(int argc, char *argv[]) +{ + unsigned int i, j, n; + char *strings[ARRAY_SIZE(substrings) * ARRAY_SIZE(substrings)]; + + n = 0; + for (i = 0; i < ARRAY_SIZE(substrings); i++) { + for (j = 0; j < ARRAY_SIZE(substrings); j++) { + strings[n] = malloc(strlen(substrings[i]) + + strlen(substrings[j]) + 1); + sprintf(strings[n++], "%s%s", + substrings[i], substrings[j]); + } + } + + plan_tests(n * n * 5); + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + unsigned int k, identical = 0; + char *reva, *revb; + + /* Find first difference. */ + for (k = 0; strings[i][k]==strings[j][k]; k++) { + if (k == strlen(strings[i])) { + identical = 1; + break; + } + } + + if (identical) + ok1(streq(strings[i], strings[j])); + else + ok1(!streq(strings[i], strings[j])); + + /* Postfix test should be equivalent to prefix + * test on reversed string. */ + reva = strdup_rev(strings[i]); + revb = strdup_rev(strings[j]); + + if (!strings[i][k]) { + ok1(strstarts(strings[j], strings[i])); + ok1(strends(revb, reva)); + } else { + ok1(!strstarts(strings[j], strings[i])); + ok1(!strends(revb, reva)); + } + if (!strings[j][k]) { + ok1(strstarts(strings[i], strings[j])); + ok1(strends(reva, revb)); + } else { + ok1(!strstarts(strings[i], strings[j])); + ok1(!strends(reva, revb)); + } + } + } + return exit_status(); +} -- 2.39.2