base64 base224 \
sync \
qache \
- string str-esc str-split str-match str-imatch str-hex \
+ string str-esc str-split str-match str-imatch str-hex str-fix \
bbuf gary \
getopt \
strtonum \
$(o)/ucw/getopt.test: $(o)/ucw/getopt-t
$(o)/ucw/ff-unicode.test: $(o)/ucw/ff-unicode-t
$(o)/ucw/eltpool.test: $(o)/ucw/eltpool-t
-$(o)/ucw/string.test: $(o)/ucw/str-hex-t $(o)/ucw/str-esc-t
+$(o)/ucw/string.test: $(o)/ucw/str-hex-t $(o)/ucw/str-esc-t $(o)/ucw/str-fix-t
$(o)/ucw/sha1.test: $(o)/ucw/sha1-t $(o)/ucw/sha1-hmac-t
$(o)/ucw/trie-test.test: $(o)/ucw/trie-test
$(o)/ucw/asort-test.test: $(o)/ucw/asort-test
--- /dev/null
+/*
+ * UCW Library -- Matching Prefixes and Suffixes
+ *
+ * (c) 2011 Martin Mares <mj@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include "ucw/lib.h"
+#include "ucw/string.h"
+
+#include <string.h>
+
+int
+str_has_prefix(char *str, char *prefix)
+{
+ size_t pxlen = strlen(prefix);
+ return !strncmp(str, prefix, pxlen);
+}
+
+int
+str_has_suffix(char *str, char *suffix)
+{
+ size_t sxlen = strlen(suffix);
+ size_t len = strlen(str);
+
+ if (len < sxlen)
+ return 0;
+ else
+ return !strcmp(str + len - sxlen, suffix);
+}
+
+int
+str_hier_prefix(char *str, char *prefix, uns sep)
+{
+ while (*str && *prefix)
+ {
+ size_t sl=0, pl=0;
+ while (str[sl] && (uns) str[sl] != sep)
+ sl++;
+ while (prefix[pl] && (uns) prefix[pl] != sep)
+ pl++;
+ if (sl != pl || memcmp(str, prefix, sl))
+ return 0;
+ str += sl, prefix += pl;
+ if (!*str)
+ return !*prefix;
+ if (!*prefix)
+ return 1;
+ str++, prefix++;
+ }
+ return !*prefix;
+}
+
+int
+str_hier_suffix(char *str, char *suffix, uns sep)
+{
+ char *st = str + strlen(str);
+ char *sx = suffix + strlen(suffix);
+ while (st > str && sx > suffix)
+ {
+ size_t sl=0, pl=0;
+ while (st-sl > str && (uns) st[-sl-1] != sep)
+ sl++;
+ while (sx-pl > suffix && (uns) sx[-pl-1] != sep)
+ pl++;
+ if (sl != pl || memcmp(st-sl, sx-pl, sl))
+ return 0;
+ st -= sl, sx -= pl;
+ if (st == str)
+ return (sx == suffix);
+ if (sx == suffix)
+ return 1;
+ st--, sx--;
+ }
+ return (sx == suffix);
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ if (argc != 4)
+ return 1;
+
+ int ret;
+ switch (argv[1][0])
+ {
+ case 'p':
+ ret = str_has_prefix(argv[2], argv[3]);
+ break;
+ case 's':
+ ret = str_has_suffix(argv[2], argv[3]);
+ break;
+ case 'P':
+ ret = str_hier_prefix(argv[2], argv[3], '.');
+ break;
+ case 'S':
+ ret = str_hier_suffix(argv[2], argv[3], '.');
+ break;
+ default:
+ return 1;
+ }
+ printf("%s\n", (ret ? "YES" : "NO"));
+ return 0;
+}
+
+#endif
* UCW Library -- String Routines
*
* (c) 2006 Pavel Charvat <pchar@ucw.cz>
- * (c) 2007--2008 Martin Mares <mj@ucw.cz>
+ * (c) 2007--2011 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
// Bottom 8 bits of flags are an optional separator of bytes, the rest is:
#define MEM_TO_HEX_UPCASE 0x100
+/* str-fix.c */
+
+int str_has_prefix(char *str, char *prefix); /** Tests if @str starts with @prefix. **/
+int str_has_suffix(char *str, char *suffix); /** Tests if @str ends with @suffix. **/
+
+/**
+ * Let @str and @prefix be hierarchical names with components separated by
+ * a character @sep. Returns true if @str starts with @prefix, respecting
+ * component boundaries.
+ *
+ * For example, when @sep is '/' and @str is "/usr/local/bin", then:
+ * - "/usr/local" is a prefix
+ * - "/usr/local/" is a prefix, too
+ * - "/usr/loc" is not,
+ * - "/usr/local/bin" is a prefix,
+ * - "/usr/local/bin/" is not,
+ * - "/" is a prefix,
+ * - "" is a prefix,
+ **/
+int str_hier_prefix(char *str, char *prefix, uns sep);
+int str_hier_suffix(char *str, char *suffix, uns sep); /** Like @str_hier_prefix(), but for suffixes. **/
+
#endif
Run: ../obj/ucw/str-esc-t '\a\b\f\r\n\t\v\?\"'"\\'"
Out: 07 08 0c 0d 0a 09 0b 3f 22 27
+
+Name: prefix1
+Run: ../obj/ucw/str-fix-t p homo.sapiens.neanderthalensis homo.sap
+Out: YES
+
+Name: prefix2
+Run: ../obj/ucw/str-fix-t p homo.sapiens.neanderthalensis homo.sapiens.neanderthalensis
+Out: YES
+
+Name: prefix3
+Run: ../obj/ucw/str-fix-t p homo.sapiens.neanderthalensis ""
+Out: YES
+
+Name: prefix4
+Run: ../obj/ucw/str-fix-t p homo.sapiens.neanderthalensis homo.sapiens.neanderthalensisis
+Out: NO
+
+Name: suffix1
+Run: ../obj/ucw/str-fix-t s homo.sapiens.neanderthalensis ensis
+Out: YES
+
+Name: suffix2
+Run: ../obj/ucw/str-fix-t s homo.sapiens.neanderthalensis homo.sapiens.neanderthalensis
+Out: YES
+
+Name: suffix3
+Run: ../obj/ucw/str-fix-t s homo.sapiens.neanderthalensis ""
+Out: YES
+
+Name: suffix4
+Run: ../obj/ucw/str-fix-t s homo.sapiens.neanderthalensis ecce.homo.sapiens.neanderthalensis
+Out: NO
+
+Name: hier-prefix1
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis homo.sap
+Out: NO
+
+Name: hier-prefix2
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis homo.sapiens
+Out: YES
+
+Name: hier-prefix3
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis homo.sapiens.
+Out: YES
+
+Name: hier-prefix4
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis homo.sapiens.neanderthalensis
+Out: YES
+
+Name: hier-prefix5
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis homo.sapiens.neanderthalensis.
+Out: NO
+
+Name: hier-prefix6
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis ""
+Out: YES
+
+Name: hier-suffix1
+Run: ../obj/ucw/str-fix-t S homo.sapiens.neanderthalensis ensis
+Out: NO
+
+Name: hier-suffix2
+Run: ../obj/ucw/str-fix-t S homo.sapiens.neanderthalensis sapiens.neanderthalensis
+Out: YES
+
+Name: hier-suffix3
+Run: ../obj/ucw/str-fix-t S homo.sapiens.neanderthalensis .sapiens.neanderthalensis
+Out: YES
+
+Name: hier-suffix4
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis homo.sapiens.neanderthalensis
+Out: YES
+
+Name: hier-suffix5
+Run: ../obj/ucw/str-fix-t P homo.sapiens.neanderthalensis .homo.sapiens.neanderthalensis
+Out: NO
+
+Name: hier-suffix6
+Run: ../obj/ucw/str-fix-t S homo.sapiens.neanderthalensis ""
+Out: YES
+
+Name: hier-suffix7
+Run: ../obj/ucw/str-fix-t S homo.sapiens.neanderthalensis ecce.homo.sapiens.neanderthalensis
+Out: NO