Commit 7cb93e5b authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Move string-splitting into a separate function


svn:r2263
parent 2c002b15
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -481,6 +481,46 @@ void smartlist_insert(smartlist_t *sl, int idx, void *val)
  }
}

/**
 * Split a string <b>str</b> along all occurences of <b>sep</b>, adding the
 * split strings, in order, to <b>sl</b>.  If <b>skipSpace</b> is true,
 * remove initial and trailing space from each entry.
 */
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
                           int skipSpace)
{
  const char *cp, *end, *next;
  int n = 0;

  tor_assert(sl && str && sep);

  cp = str;
  while (1) {
    if (skipSpace) {
      while (isspace(*cp)) ++cp;
    }
    end = strstr(cp,sep);
    if (!end) {
      end = strchr(cp,'\0');
      next = NULL;
    } else {
      next = end+strlen(sep);
    }

    if (skipSpace) {
      while (end > cp && isspace(*(end-1)))
        --end;
    }
    smartlist_add(sl, tor_strndup(cp, end-cp));
    ++n;
    if (!next)
      break;
    cp = next;
  }

  return n;
}

/* Splay-tree implementation of string-to-void* map
 */
struct strmap_entry_t {
+3 −0
Original line number Diff line number Diff line
@@ -158,6 +158,9 @@ void *smartlist_del(smartlist_t *sl, int idx);
void *smartlist_del_keeporder(smartlist_t *sl, int idx);
void smartlist_insert(smartlist_t *sl, int idx, void *val);
int smartlist_len(const smartlist_t *sl);
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,
  int skipSpace);

#define SMARTLIST_FOREACH(sl, type, var, cmd)                   \
  do {                                                          \
    int sl_idx, sl_len=smartlist_len(sl);                       \
+1 −34
Original line number Diff line number Diff line
@@ -128,39 +128,6 @@ static void config_free_lines(struct config_line_t *front) {
  }
}

/**
 * Given a list of comma-separated entries, each surrounded by optional
 * whitespace, insert copies of the entries (in order) into lst, without
 * their surrounding whitespace.
 */
static void parse_csv_into_smartlist(smartlist_t *lst, const char *val)
{
  const char *cp, *start, *end;

  cp = val;
  while (1) {
    while (isspace(*cp))
      ++cp;
    start = cp;
    end = strchr(cp, ',');
    if (!end)
      end = strchr(cp, '\0');
    for (cp=end-1; cp>=start && isspace(*cp); --cp)
      ;
    /* Now start points to the first nonspace character of an entry,
     * end points to the terminator of that entry,
     * and cp points to the last nonspace character of an entry. */
    tor_assert(start <= cp);
    tor_assert(cp <= end);
    tor_assert(*end == '\0' || *end == ',');
    tor_assert((!isspace(*start) && !isspace(*cp)) || start==cp);
    smartlist_add(lst, tor_strndup(start, cp-start+1));
    if (!*end)
      break;
    cp = end+1;
  }
}

/** Search the linked list <b>c</b> for any option whose key is <b>key</b>.
 * If such an option is found, interpret it as of type <b>type</b>, and store
 * the result in <b>arg</b>.  If the option is misformatted, log a warning and
@@ -202,7 +169,7 @@ static int config_compare(struct config_line_t *c, const char *key, config_type_
    case CONFIG_TYPE_CSV:
      if(*(smartlist_t**)arg == NULL)
        *(smartlist_t**)arg = smartlist_create();
      parse_csv_into_smartlist(*(smartlist_t**)arg, c->value);
      smartlist_split_string(*(smartlist_t**)arg, c->value, ",", 1);
      break;
    case CONFIG_TYPE_LINELIST:
      /* Note: this reverses the order that the lines appear in.  That's
+34 −0
Original line number Diff line number Diff line
@@ -550,6 +550,40 @@ test_util() {
  test_eq((void*)3,   smartlist_get(sl,3));
  test_eq((void*)4,   smartlist_get(sl,4));
  test_eq((void*)555, smartlist_get(sl,5));

  smartlist_clear(sl);
  smartlist_split_string(sl, "abc", ":", 0);
  test_eq(1, smartlist_len(sl));
  test_streq("abc", smartlist_get(sl, 0));
  smartlist_split_string(sl, "a::bc::", "::", 0);
  test_eq(4, smartlist_len(sl));
  test_streq("a", smartlist_get(sl, 1));
  test_streq("bc", smartlist_get(sl, 2));
  test_streq("", smartlist_get(sl, 3));
  smartlist_split_string(sl, "/def/  /ghijk", "/", 0);
  test_eq(8, smartlist_len(sl));
  test_streq("", smartlist_get(sl, 4));
  test_streq("def", smartlist_get(sl, 5));
  test_streq("  ", smartlist_get(sl, 6));
  test_streq("ghijk", smartlist_get(sl, 7));
  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
  smartlist_clear(sl);

  smartlist_split_string(sl, "a,bbd,cdef", ",", 1);
  test_eq(3, smartlist_len(sl));
  test_streq("a", smartlist_get(sl,0));
  test_streq("bbd", smartlist_get(sl,1));
  test_streq("cdef", smartlist_get(sl,2));
  smartlist_split_string(sl, " z <> zhasd <>  <> bnud<>   ", "<>", 1);
  test_eq(8, smartlist_len(sl));
  test_streq("z", smartlist_get(sl,3));
  test_streq("zhasd", smartlist_get(sl,4));
  test_streq("", smartlist_get(sl,5));
  test_streq("bnud", smartlist_get(sl,6));
  test_streq("", smartlist_get(sl,7));

  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));

  /* XXXX test older functions. */
  smartlist_free(sl);
}