Browse Source

Add code to read configuration lines from a string as well as a file

svn:r2676
Nick Mathewson 21 years ago
parent
commit
9d604ec615
3 changed files with 128 additions and 2 deletions
  1. 79 1
      src/common/util.c
  2. 1 0
      src/common/util.h
  3. 48 1
      src/or/test.c

+ 79 - 1
src/common/util.c

@@ -875,7 +875,7 @@ char *read_file_to_str(const char *filename, int bin) {
 int
 parse_line_from_file(char *line, size_t maxlen, FILE *f,
                      char **key_out, char **value_out) {
-  char *s, *key, *end, *value;
+  char *s;
 
 try_next_line:
   if(!fgets(line, maxlen, f)) {
@@ -883,6 +883,17 @@ try_next_line:
       return 0;
     return -1; /* real error */
   }
+  line[maxlen-1] = '\0';
+
+  s = parse_line_from_str(line, key_out, value_out);
+  if (!s)
+    return -1;
+  if (!*key_out)
+    goto try_next_line;
+
+  return 1;
+
+#if 0
 
   if((s = strchr(line,'#'))) /* strip comments */
     *s = 0; /* stop the line there */
@@ -920,6 +931,73 @@ try_next_line:
   log_fn(LOG_DEBUG,"got keyword '%s', value '%s'", key, value);
   *key_out = key, *value_out = value;
   return 1;
+#endif
+}
+
+
+/** DOCDOC.
+ *
+ * Return next line or end of string on success, NULL on failure.
+ */
+char *
+parse_line_from_str(char *line, char **key_out, char **value_out)
+{
+  char *key, *val, *cp;
+
+  tor_assert(key_out);
+  tor_assert(value_out);
+
+  *key_out = *value_out = key = val = NULL;
+  /* Skip until the first keyword. */
+  while (1) {
+    while (isspace(*line))
+      ++line;
+    if (*line == '#') {
+      while (*line && *line != '\n')
+        ++line;
+    } else {
+      break;
+    }
+  }
+
+  if (!*line) { /* End of string? */
+    *key_out = *value_out = NULL;
+    return line;
+  }
+
+  /* Skip until the next space. */
+  key = line;
+  while (*line && !isspace(*line) && *line != '#')
+    ++line;
+
+  /* Skip until the value */
+  while (*line == ' ' || *line == '\t')
+    *line++ = '\0';
+  val = line;
+
+  /* Find the end of the line. */
+  while (*line && *line != '\n' && *line != '#')
+    ++line;
+  if (*line == '\n')
+    cp = line++;
+  else {
+    cp = line-1;
+  }
+  while (cp>=val && isspace(*cp))
+    *cp-- = '\0';
+
+  if (*line == '#') {
+    do {
+      *line++ = '\0';
+    } while (*line && *line != '\n');
+    if (*line == '\n')
+      ++line;
+  }
+
+  *key_out = key;
+  *value_out = val;
+
+  return line;
 }
 
 /** Expand any homedir prefix on 'filename'; return a newly allocated

+ 1 - 0
src/common/util.h

@@ -92,6 +92,7 @@ int write_bytes_to_file(const char *fname, const char *str, size_t len,
                         int bin);
 char *read_file_to_str(const char *filename, int bin);
 int parse_line_from_file(char *line, size_t maxlen, FILE *f, char **key_out, char **value_out);
+char *parse_line_from_str(char *line, char **key_out, char **value_out);
 char *expand_filename(const char *filename);
 
 /* Net helpers */

+ 48 - 1
src/or/test.c

@@ -489,7 +489,7 @@ test_util(void) {
   int i;
   uint32_t u32;
   uint16_t u16;
-  char *cp;
+  char *cp, *k, *v;
 
   start.tv_sec = 5;
   start.tv_usec = 5000;
@@ -674,6 +674,53 @@ test_util(void) {
   test_eq(10L, tor_parse_long("10",10,0,100,NULL,NULL));
   test_eq(0L, tor_parse_long("10",10,50,100,NULL,NULL));
 
+  /* Test parse_line_from_str */
+  strlcpy(buf, "k v\n" " key    value with spaces   \n"  "keykey val\n"
+          "k2\n"
+          "k3 \n"  "\n" "   \n" "#comment\n"
+          "k4#a\n" "k5#abc\n" "k6 val #with comment\n", sizeof(buf));
+  cp = buf;
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "k");
+  test_streq(v, "v");
+  test_assert(!strcmpstart(cp, " key    value with"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "key");
+  test_streq(v, "value with spaces");
+  test_assert(!strcmpstart(cp, "keykey"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "keykey");
+  test_streq(v, "val");
+  test_assert(!strcmpstart(cp, "k2\n"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "k2");
+  test_streq(v, "");
+  test_assert(!strcmpstart(cp, "k3 \n"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "k3");
+  test_streq(v, "");
+  test_assert(!strcmpstart(cp, "\n   \n"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "k4");
+  test_streq(v, "");
+  test_assert(!strcmpstart(cp, "k5#abc"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "k5");
+  test_streq(v, "");
+  test_assert(!strcmpstart(cp, "k6"));
+
+  cp = parse_line_from_str(cp, &k, &v);
+  test_streq(k, "k6");
+  test_streq(v, "val");
+  test_streq(cp, "");
+
   /* XXXX test older functions. */
   smartlist_free(sl);
 }