mirror of https://github.com/djcb/mu.git
* lib: add mu_str_parse_arglist + unit tests
This commit is contained in:
parent
2f5d6e246b
commit
59f855b39b
119
lib/mu-str.c
119
lib/mu-str.c
|
@ -840,3 +840,122 @@ mu_str_quoted_from_strv (const gchar **params)
|
|||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
read_key (const char *str, const char **val, GError **err)
|
||||
{
|
||||
const char *cur;
|
||||
GString *gstr;
|
||||
|
||||
cur = str;
|
||||
|
||||
gstr = g_string_sized_new (strlen(cur));
|
||||
while (*cur && *cur != ':') {
|
||||
g_string_append_c (gstr, *cur);
|
||||
++cur;
|
||||
}
|
||||
|
||||
if (*cur != ':' || gstr->len == 0) {
|
||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR,
|
||||
"expected: '<alphanum>+:' (%s)",
|
||||
str);
|
||||
g_string_free (gstr, TRUE);
|
||||
*val = NULL;
|
||||
return NULL;
|
||||
} else {
|
||||
*val = cur + 1;
|
||||
return g_string_free (gstr, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
read_val (const char *str, const char **endval, GError **err)
|
||||
{
|
||||
const char *cur;
|
||||
gboolean quoted;
|
||||
GString *gstr;
|
||||
|
||||
gstr = g_string_sized_new (strlen(str));
|
||||
|
||||
for (quoted = FALSE, cur = str; *cur; ++cur) {
|
||||
|
||||
if (*cur == '\\') {
|
||||
if (cur[1] != '"' && cur[1] != '\\') {
|
||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR,
|
||||
"invalid escaping");
|
||||
goto errexit;
|
||||
} else {
|
||||
++cur;
|
||||
g_string_append_c (gstr, *cur);
|
||||
continue;
|
||||
}
|
||||
} else if (*cur == '"') {
|
||||
quoted = !quoted;
|
||||
continue;
|
||||
} else if (isblank(*cur) && !quoted)
|
||||
break;
|
||||
else
|
||||
g_string_append_c (gstr, *cur);
|
||||
}
|
||||
|
||||
if (quoted) {
|
||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR,
|
||||
"error in quoting");
|
||||
goto errexit;
|
||||
}
|
||||
|
||||
*endval = cur;
|
||||
return g_string_free (gstr, FALSE);
|
||||
|
||||
errexit:
|
||||
g_string_free (gstr, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GHashTable*
|
||||
mu_str_parse_arglist (const char *args, GError **err)
|
||||
{
|
||||
GHashTable *hash;
|
||||
const char *cur;
|
||||
|
||||
g_return_val_if_fail (args, NULL);
|
||||
|
||||
hash = g_hash_table_new_full (
|
||||
g_str_hash,
|
||||
g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)g_free);
|
||||
|
||||
cur = args;
|
||||
while ((isblank(*cur)))
|
||||
++cur;
|
||||
|
||||
do {
|
||||
char *key, *val;
|
||||
const char *valstart, *valend;
|
||||
|
||||
key = read_key (cur, &valstart, err);
|
||||
if (!key)
|
||||
goto errexit;
|
||||
|
||||
val = read_val (valstart, &valend, err);
|
||||
if (!val)
|
||||
goto errexit;
|
||||
|
||||
g_print ("%s->%s\n", key, val);
|
||||
g_hash_table_insert (hash, key, val);
|
||||
|
||||
cur = valend;
|
||||
while ((isblank(*cur)))
|
||||
++cur;
|
||||
} while (*cur);
|
||||
|
||||
return hash;
|
||||
|
||||
errexit:
|
||||
g_hash_table_destroy (hash);
|
||||
return NULL;
|
||||
}
|
||||
|
|
15
lib/mu-str.h
15
lib/mu-str.h
|
@ -281,6 +281,21 @@ GSList* mu_str_to_list (const char *str, char sepa, gboolean strip);
|
|||
GSList* mu_str_esc_to_list (const char *str);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Parse a list of <key>:<value> arguments, where <value> supports
|
||||
* quoting and escaping.
|
||||
*
|
||||
* @param args a list of arguments
|
||||
* @param err receives error information
|
||||
*
|
||||
* @return a hash table with key->value, or NULL in case of
|
||||
* error. Free with g_hash_table_destroy.
|
||||
*/
|
||||
GHashTable* mu_str_parse_arglist (const char *args, GError **err)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
* free a GSList consisting of allocated strings
|
||||
*
|
||||
|
|
|
@ -129,6 +129,30 @@ test_mu_str_flatten (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse_arglist (void)
|
||||
{
|
||||
const char *args;
|
||||
GHashTable *hash;
|
||||
GError *err;
|
||||
|
||||
args = "cmd:find query:\"maildir:\\\"/sent items\\\"\" maxnum:500";
|
||||
|
||||
err = NULL;
|
||||
hash = mu_str_parse_arglist (args, &err);
|
||||
g_assert_no_error (err);
|
||||
g_assert (hash);
|
||||
|
||||
g_assert_cmpstr (g_hash_table_lookup (hash, "cmd"), ==,
|
||||
"find");
|
||||
g_assert_cmpstr (g_hash_table_lookup (hash, "query"), ==,
|
||||
"maildir:\"/sent items\"");
|
||||
g_assert_cmpstr (g_hash_table_lookup (hash, "maxnum"), ==,
|
||||
"500");
|
||||
|
||||
g_hash_table_destroy (hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
|
@ -403,9 +427,6 @@ test_mu_term_fixups (void)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
|
@ -443,6 +464,9 @@ main (int argc, char *argv[])
|
|||
g_test_add_func ("/mu-str/mu-str-to-list-strip",
|
||||
test_mu_str_to_list_strip);
|
||||
|
||||
g_test_add_func ("/mu-str/mu-str-esc-to-list",
|
||||
test_parse_arglist);
|
||||
|
||||
g_test_add_func ("/mu-str/mu-str-esc-to-list",
|
||||
test_mu_str_esc_to_list);
|
||||
|
||||
|
|
Loading…
Reference in New Issue