util: add a helper function to split a key-value pair string

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2018-04-11 17:51:44 +10:00
parent 7d06ccc061
commit bd04826aa4
2 changed files with 116 additions and 0 deletions

View file

@ -560,4 +560,67 @@ strv_free(char **strv) {
free (strv);
}
struct key_value_double {
double key;
double value;
};
static inline ssize_t
kv_double_from_string(const char *string,
const char *pair_separator,
const char *kv_separator,
struct key_value_double **result_out)
{
char **pairs;
char **pair;
struct key_value_double *result = NULL;
ssize_t npairs = 0;
unsigned int idx = 0;
if (!pair_separator || pair_separator[0] == '\0' ||
!kv_separator || kv_separator[0] == '\0')
return -1;
pairs = strv_from_string(string, pair_separator);
if (!pairs)
return -1;
for (pair = pairs; *pair; pair++)
npairs++;
if (npairs == 0)
return -1;
result = zalloc(npairs * sizeof *result);
for (pair = pairs; *pair; pair++) {
char **kv = strv_from_string(*pair, kv_separator);
double k, v;
if (!kv || !kv[0] || !kv[1] || kv[2] ||
!safe_atod(kv[0], &k) ||
!safe_atod(kv[1], &v)) {
strv_free(kv);
goto error;
}
result[idx].key = k;
result[idx].value = v;
idx++;
strv_free(kv);
}
strv_free(pairs);
*result_out = result;
return npairs;
error:
strv_free(pairs);
free(result);
return -1;
}
#endif /* LIBINPUT_UTIL_H */

View file

@ -1292,6 +1292,58 @@ START_TEST(strsplit_test)
}
END_TEST
struct kvsplit_dbl_test {
const char *string;
const char *psep;
const char *kvsep;
ssize_t nresults;
struct {
double a;
double b;
} results[32];
};
START_TEST(kvsplit_double_test)
{
struct kvsplit_dbl_test tests[] = {
{ "1:2;3:4;5:6", ";", ":", 3, { {1, 2}, {3, 4}, {5, 6}}},
{ "1.0x2.3 -3.2x4.5 8.090909x-6.00", " ", "x", 3, { {1.0, 2.3}, {-3.2, 4.5}, {8.090909, -6}}},
{ "1:2", "x", ":", 1, {{1, 2}}},
{ "1:2", ":", "x", -1, {}},
{ "1:2", NULL, "x", -1, {}},
{ "1:2", "", "x", -1, {}},
{ "1:2", "x", NULL, -1, {}},
{ "1:2", "x", "", -1, {}},
{ "a:b", "x", ":", -1, {}},
{ "", " ", "x", -1, {}},
{ "1.2.3.4.5", ".", "", -1, {}},
{ NULL }
};
struct kvsplit_dbl_test *t = tests;
while (t->string) {
struct key_value_double *result = NULL;
ssize_t npairs;
npairs = kv_double_from_string(t->string,
t->psep,
t->kvsep,
&result);
ck_assert_int_eq(npairs, t->nresults);
for (ssize_t i = 0; i < npairs; i++) {
ck_assert_double_eq(t->results[i].a, result[i].key);
ck_assert_double_eq(t->results[i].b, result[i].value);
}
free(result);
t++;
}
}
END_TEST
static int open_restricted_leak(const char *path, int flags, void *data)
{
return *(int*)data;
@ -1528,6 +1580,7 @@ TEST_COLLECTION(misc)
litest_add_no_device("misc:parser", safe_atoi_base_8_test);
litest_add_no_device("misc:parser", safe_atod_test);
litest_add_no_device("misc:parser", strsplit_test);
litest_add_no_device("misc:parser", kvsplit_double_test);
litest_add_no_device("misc:time", time_conversion);
litest_add_no_device("misc:fd", fd_no_event_leak);