common: New function split_fields.
authorWerner Koch <wk@gnupg.org>
Sat, 11 Jun 2016 10:09:48 +0000 (12:09 +0200)
committerWerner Koch <wk@gnupg.org>
Sat, 11 Jun 2016 10:09:48 +0000 (12:09 +0200)
* common/stringhelp.c (split_fields): New.
* common/t-stringhelp.c: Include assert.h.
(test_split_fields): New.
(main): Call test.

Signed-off-by: Werner Koch <wk@gnupg.org>
common/stringhelp.c
common/stringhelp.h
common/t-stringhelp.c

index 8b47a1c..0e96c9e 100644 (file)
@@ -1329,6 +1329,44 @@ strtokenize (const char *string, const char *delim)
 }
 
 
 }
 
 
+/* Split a string into space delimited fields and remove leading and
+ * trailing spaces from each field.  A pointer to each field is stored
+ * in ARRAY.  Stop splitting at ARRAYSIZE fields.  The function
+ * modifies STRING.  The number of parsed fields is returned.
+ * Example:
+ *
+ *   char *fields[2];
+ *   if (split_fields (string, fields, DIM (fields)) < 2)
+ *     return  // Not enough args.
+ *   foo (fields[0]);
+ *   foo (fields[1]);
+ */
+int
+split_fields (char *string, char **array, int arraysize)
+{
+  int n = 0;
+  char *p, *pend;
+
+  for (p = string; *p == ' '; p++)
+    ;
+  do
+    {
+      if (n == arraysize)
+        break;
+      array[n++] = p;
+      pend = strchr (p, ' ');
+      if (!pend)
+        break;
+      *pend++ = 0;
+      for (p = pend; *p == ' '; p++)
+        ;
+    }
+  while (*p);
+
+  return n;
+}
+
+
 \f
 /* Version number parsing.  */
 
 \f
 /* Version number parsing.  */
 
index d9225a3..b6f4167 100644 (file)
@@ -148,6 +148,10 @@ char **strsplit (char *string, char delim, char replacement, int *count);
 /* Tokenize STRING using the set of delimiters in DELIM.  */
 char **strtokenize (const char *string, const char *delim);
 
 /* Tokenize STRING using the set of delimiters in DELIM.  */
 char **strtokenize (const char *string, const char *delim);
 
+/* Split STRING into space delimited fields and store them in the
+ * provided ARRAY.  */
+int split_fields (char *string, char **array, int arraysize);
+
 /* Return True if MYVERSION is greater or equal than REQ_VERSION.  */
 int compare_version_strings (const char *my_version, const char *req_version);
 
 /* Return True if MYVERSION is greater or equal than REQ_VERSION.  */
 int compare_version_strings (const char *my_version, const char *req_version);
 
index b4a41ac..db0e811 100644 (file)
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <assert.h>
 #ifdef HAVE_PWD_H
 # include <pwd.h>
 #endif
 #ifdef HAVE_PWD_H
 # include <pwd.h>
 #endif
@@ -676,6 +677,82 @@ test_strtokenize (void)
     }
 }
 
     }
 }
 
+
+static void
+test_split_fields (void)
+{
+  struct {
+    const char *s;
+    int nfields;
+    const char *fields_expected[10];
+  } tv[] = {
+    {
+      "a bc cde fghi jklmn   foo ", 6,
+      { "a", "bc", "cde", "fghi", "jklmn", "foo", NULL }
+    },
+    {
+      " a bc  def ", 2,
+      { "a", "bc", "def", NULL }
+    },
+    {
+      " a bc  def ", 3,
+      { "a", "bc", "def", NULL }
+    },
+    {
+      " a bc  def ", 4,
+      { "a", "bc", "def", NULL }
+    },
+    {
+      "", 0,
+      { NULL }
+    }
+  };
+
+  int tidx;
+  char *fields[10];
+  int field_count_expected, nfields, field_count, i;
+  char *s2;
+
+  for (tidx = 0; tidx < DIM(tv); tidx++)
+    {
+      nfields = tv[tidx].nfields;
+      assert (nfields <= DIM (fields));
+
+      /* Count the fields.  */
+      for (field_count_expected = 0;
+           tv[tidx].fields_expected[field_count_expected];
+           field_count_expected ++)
+        ;
+      if (field_count_expected > nfields)
+        field_count_expected = nfields;
+
+      /* We need to copy s since split_fields modifies in place.  */
+      s2 = xstrdup (tv[tidx].s);
+      field_count = split_fields (s2, fields, nfields);
+
+      if (field_count != field_count_expected)
+        {
+          printf ("%s: tidx %d: expected %d, got %d\n",
+                  __func__, tidx, i, field_count_expected, field_count);
+          fail (tidx * 1000);
+        }
+      else
+        {
+          for (i = 0; i < field_count_expected; i ++)
+            if (strcmp (tv[tidx].fields_expected[i], fields[i]))
+              {
+                printf ("%s: tidx %d, field %d: expected '%s', got '%s'\n",
+                        __func__,
+                        tidx, i, tv[tidx].fields_expected[i], fields[i]);
+                fail (tidx * 1000 + i + 1);
+              }
+        }
+
+      xfree (s2);
+    }
+}
+
+
 static char *
 stresc (char *s)
 {
 static char *
 stresc (char *s)
 {
@@ -887,6 +964,7 @@ main (int argc, char **argv)
   test_make_absfilename_try ();
   test_strsplit ();
   test_strtokenize ();
   test_make_absfilename_try ();
   test_strsplit ();
   test_strtokenize ();
+  test_split_fields ();
   test_compare_version_strings ();
   test_format_text ();
 
   test_compare_version_strings ();
   test_format_text ();