From 9dc946ba67a5d457ce00bf2853f624c3c7c344aa Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 26 Feb 2020 10:10:27 -0500 Subject: 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 + 2 files changed, 30 insertions(+) (limited to 'src/lib/encoding') diff --git a/src/lib/encoding/confline.c b/src/lib/encoding/confline.c index ff8bacba3c..eb1a4e30f0 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 inp beginning with the key header, 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 inp contains "H, A, B, H, C, + * H, D", this function will alter inp 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 cd343e0e99..ce0d6c6e17 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); -- cgit v1.2.3-54-g00ecf