[tor-commits] [tor/master] Add a config_lines_partition() function to help with LINELIST_V.

dgoulet at torproject.org dgoulet at torproject.org
Mon Mar 30 17:37:37 UTC 2020


commit 9dc946ba67a5d457ce00bf2853f624c3c7c344aa
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Feb 26 10:10:27 2020 -0500

    Add a config_lines_partition() function to help with LINELIST_V.
    
    This function works a little bit like strsep(), to get a chunk of
    configuration lines with a given header.  We can use this to make
    hidden service config easier to parse.
---
 src/lib/encoding/confline.c | 29 ++++++++++++++++++++++++++
 src/lib/encoding/confline.h |  1 +
 src/test/test_util.c        | 51 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+)

diff --git a/src/lib/encoding/confline.c b/src/lib/encoding/confline.c
index ff8bacba3..eb1a4e30f 100644
--- a/src/lib/encoding/confline.c
+++ b/src/lib/encoding/confline.c
@@ -253,6 +253,35 @@ config_lines_dup_and_filter(const config_line_t *inp,
   return result;
 }
 
+/**
+ * Given a linelist <b>inp</b> beginning with the key <b>header</b>, find the
+ * next line with that key, and remove that instance and all following lines
+ * from the list.  Return the lines that were removed.  Operate
+ * case-insensitively.
+ *
+ * For example, if the header is "H", and <b>inp</b> contains "H, A, B, H, C,
+ * H, D", this function will alter <b>inp</b> to contain only "H, A, B", and
+ * return the elements "H, C, H, D" as a separate list.
+ **/
+config_line_t *
+config_lines_partition(config_line_t *inp, const char *header)
+{
+  if (BUG(inp == NULL))
+    return NULL;
+  if (BUG(strcasecmp(inp->key, header)))
+    return NULL;
+
+  /* Advance ptr until it points to the link to the next segment of this
+     list. */
+  config_line_t **ptr = &inp->next;
+  while (*ptr && strcasecmp((*ptr)->key, header)) {
+    ptr = &(*ptr)->next;
+  }
+  config_line_t *remainder = *ptr;
+  *ptr = NULL;
+  return remainder;
+}
+
 /** Return true iff a and b contain identical keys and values in identical
  * order. */
 int
diff --git a/src/lib/encoding/confline.h b/src/lib/encoding/confline.h
index cd343e0e9..ce0d6c6e1 100644
--- a/src/lib/encoding/confline.h
+++ b/src/lib/encoding/confline.h
@@ -50,6 +50,7 @@ const config_line_t *config_line_find(const config_line_t *lines,
                                       const char *key);
 const config_line_t *config_line_find_case(const config_line_t *lines,
                                            const char *key);
+config_line_t *config_lines_partition(config_line_t *inp, const char *header);
 int config_lines_eq(const config_line_t *a, const config_line_t *b);
 int config_count_key(const config_line_t *a, const char *key);
 void config_free_lines_(config_line_t *front);
diff --git a/src/test/test_util.c b/src/test/test_util.c
index fecd27909..234ae0674 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1850,6 +1850,56 @@ test_util_config_line_crlf(void *arg)
   tor_free(k); tor_free(v);
 }
 
+static void
+test_util_config_line_partition(void *arg)
+{
+  (void)arg;
+  config_line_t *lines = NULL, *orig, *rest = NULL;
+
+  config_line_append(&lines, "Header", "X");
+  config_line_append(&lines, "Item", "Y");
+  config_line_append(&lines, "Thing", "Z");
+
+  config_line_append(&lines, "HEADER", "X2");
+
+  config_line_append(&lines, "header", "X3");
+  config_line_append(&lines, "Item3", "Foob");
+
+  /* set up h2 and h3 to point to the places where we hope the headers will
+     be. */
+  config_line_t *h2 = lines->next->next->next;
+  config_line_t *h3 = h2->next;
+  tt_str_op(h2->key, OP_EQ, "HEADER");
+  tt_str_op(h3->key, OP_EQ, "header");
+
+  orig = lines;
+  rest = config_lines_partition(lines, "Header");
+  tt_ptr_op(lines, OP_EQ, orig);
+  tt_ptr_op(rest, OP_EQ, h2);
+  tt_str_op(lines->next->key, OP_EQ, "Item");
+  tt_str_op(lines->next->next->key, OP_EQ, "Thing");
+  tt_ptr_op(lines->next->next->next, OP_EQ, NULL);
+  config_free_lines(lines);
+
+  orig = lines = rest;
+  rest = config_lines_partition(lines, "Header");
+  tt_ptr_op(lines, OP_EQ, orig);
+  tt_ptr_op(rest, OP_EQ, h3);
+  tt_ptr_op(lines->next, OP_EQ, NULL);
+  config_free_lines(lines);
+
+  orig = lines = rest;
+  rest = config_lines_partition(lines, "Header");
+  tt_ptr_op(lines, OP_EQ, orig);
+  tt_ptr_op(rest, OP_EQ, NULL);
+  tt_str_op(lines->next->key, OP_EQ, "Item3");
+  tt_ptr_op(lines->next->next, OP_EQ, NULL);
+
+ done:
+  config_free_lines(lines);
+  config_free_lines(rest);
+}
+
 #ifndef DISABLE_PWDB_TESTS
 static void
 test_util_expand_filename(void *arg)
@@ -6379,6 +6429,7 @@ struct testcase_t util_tests[] = {
   UTIL_LEGACY(config_line_comment_character),
   UTIL_LEGACY(config_line_escaped_content),
   UTIL_LEGACY(config_line_crlf),
+  UTIL_TEST(config_line_partition, 0),
   UTIL_TEST_PWDB(expand_filename, 0),
   UTIL_LEGACY(escape_string_socks),
   UTIL_LEGACY(string_is_key_value),





More information about the tor-commits mailing list