]> mj.ucw.cz Git - libucw.git/commitdiff
Added string functions for matching of prefixes and suffixes
authorMartin Mares <mj@ucw.cz>
Mon, 18 Apr 2011 20:48:21 +0000 (22:48 +0200)
committerMartin Mares <mj@ucw.cz>
Mon, 18 Apr 2011 20:48:21 +0000 (22:48 +0200)
ucw/Makefile
ucw/str-fix.c [new file with mode: 0644]
ucw/string.h
ucw/string.t

index 8d7877119810f7001f94d7c41e33fa933e5a031d..fab1a16ec48eae3e6db74fe09762f7d7e4e4de1d 100644 (file)
@@ -30,7 +30,7 @@ LIBUCW_MODS= \
        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 \
@@ -130,7 +130,7 @@ $(o)/ucw/bbuf.test: $(o)/ucw/bbuf-t
 $(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
diff --git a/ucw/str-fix.c b/ucw/str-fix.c
new file mode 100644 (file)
index 0000000..deb128e
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *     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
index 935da33b7c3f2f5f21f3bcfa0f0237608d321573..8cb3cd423de61fc999e89ac5cabe39a76f758f49 100644 (file)
@@ -2,7 +2,7 @@
  *     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.
@@ -42,4 +42,26 @@ const char *hex_to_mem(byte *dest, const char *src, uns max_bytes, uns flags);
 // 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
index 6173026cfac04a0e162cc9dcefab20c24502800b..8c1593790f6d98cdae8e817d34128938010d934d 100644 (file)
@@ -13,3 +13,87 @@ Out: 40 08 61 01 61
 
 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