util: return the number of elements from strv_from_string

Signed-off-by: Yinon Burgansky <51504-Yinon@users.noreply.gitlab.freedesktop.org>
This commit is contained in:
Yinon Burgansky 2022-10-05 18:20:06 +03:00
parent e8732802b7
commit eeae8906db
5 changed files with 91 additions and 103 deletions

View file

@ -879,18 +879,15 @@ out:
static bool
parse_value_line(struct quirks_context *ctx, struct section *s, const char *line)
{
char **strv;
const char *key, *value;
bool rc = false;
strv = strv_from_string(line, "=");
if (strv[0] == NULL || strv[1] == NULL || strv[2] != NULL) {
size_t nelem;
char **strv = strv_from_string(line, "=", &nelem);
if (!strv || nelem != 2)
goto out;
}
key = strv[0];
value = strv[1];
const char *key = strv[0];
const char *value = strv[1];
if (strlen(key) == 0 || strlen(value) == 0)
goto out;

View file

@ -176,32 +176,31 @@ parse_dimension_property(const char *prop, size_t *w, size_t *h)
bool
parse_calibration_property(const char *prop, float calibration_out[6])
{
int idx;
char **strv;
float calibration[6];
if (!prop)
return false;
strv = strv_from_string(prop, " ");
if (!strv)
return false;
bool rc = false;
for (idx = 0; idx < 6; idx++) {
size_t num_calibration;
char **strv = strv_from_string(prop, " ", &num_calibration);
if (!strv || num_calibration < 6)
goto out;
float calibration[6];
for (size_t idx = 0; idx < 6; idx++) {
double v;
if (strv[idx] == NULL || !safe_atod(strv[idx], &v)) {
strv_free(strv);
return false;
}
if (!safe_atod(strv[idx], &v))
goto out;
calibration[idx] = v;
}
strv_free(strv);
memcpy(calibration_out, calibration, sizeof(calibration));
rc = true;
return true;
out:
strv_free(strv);
return rc;
}
bool
@ -367,27 +366,19 @@ parse_evcode_string(const char *s, int *type_out, int *code_out)
bool
parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents)
{
char **strv = NULL;
bool rc = false;
size_t ncodes = 0;
size_t idx;
/* A randomly chosen max so we avoid crazy quirks */
struct input_event evs[32];
memset(evs, 0, sizeof evs);
strv = strv_from_string(prop, ";");
if (!strv)
goto out;
for (idx = 0; strv[idx]; idx++)
ncodes++;
if (ncodes == 0 || ncodes > ARRAY_LENGTH(evs))
size_t ncodes;
char **strv = strv_from_string(prop, ";", &ncodes);
if (!strv || ncodes == 0 || ncodes > ARRAY_LENGTH(evs))
goto out;
ncodes = min(*nevents, ncodes);
for (idx = 0; strv[idx]; idx++) {
for (size_t idx = 0; strv[idx]; idx++) {
char *s = strv[idx];
int type, code;
@ -434,24 +425,16 @@ out:
bool
parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops)
{
char **strv = NULL;
bool rc = false;
size_t count = 0;
size_t idx;
unsigned int props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */
strv = strv_from_string(prop, ";");
if (!strv)
goto out;
for (idx = 0; strv[idx]; idx++)
count++;
if (count == 0 || count > ARRAY_LENGTH(props))
size_t count;
char **strv = strv_from_string(prop, ";", &count);
if (!strv || count == 0 || count > ARRAY_LENGTH(props))
goto out;
count = min(*nprops, count);
for (idx = 0; strv[idx]; idx++) {
for (size_t idx = 0; strv[idx]; idx++) {
char *s = strv[idx];
unsigned int prop;

View file

@ -91,48 +91,55 @@ strv_from_argv(int argc, char **argv)
/**
* Return a null-terminated string array with the tokens in the input
* string, e.g. "one two\tthree" with a separator list of " \t" will return
* an array [ "one", "two", "three", NULL ].
* an array [ "one", "two", "three", NULL ] and num elements 3.
*
* Use strv_free() to free the array.
*
* Another example:
* result = strv_from_string("+1-2++3--4++-+5-+-", "+-", &nelem)
* result == [ "1", "2", "3", "4", "5", NULL ] and nelem == 5
*
* @param in Input string
* @param separators List of separator characters
* @param num_elements Number of elements found in the input string
*
* @return A null-terminated string array or NULL on errors
*/
char **
strv_from_string(const char *in, const char *separators)
strv_from_string(const char *in, const char *separators, size_t *num_elements)
{
const char *s, *word;
char **strv = NULL;
int nelems = 0, idx;
size_t l;
assert(in != NULL);
s = in;
const char *s = in;
size_t l, nelems = 0;
while (next_word(&s, &l, separators) != NULL)
nelems++;
if (nelems == 0)
if (nelems == 0) {
*num_elements = 0;
return NULL;
}
nelems++; /* NULL-terminated */
strv = zalloc(nelems * sizeof *strv);
idx = 0;
size_t strv_len = nelems + 1; /* NULL-terminated */
char **strv = zalloc(strv_len * sizeof *strv);
size_t idx = 0;
const char *word;
s = in;
while ((word = next_word(&s, &l, separators)) != NULL) {
char *copy = strndup(word, l);
if (!copy) {
strv_free(strv);
*num_elements = 0;
return NULL;
}
strv[idx++] = copy;
}
*num_elements = nelems;
return strv;
}

View file

@ -255,7 +255,7 @@ safe_atod(const char *str, double *val)
}
char **strv_from_argv(int argc, char **argv);
char **strv_from_string(const char *in, const char *separator);
char **strv_from_string(const char *in, const char *separator, size_t *num_elements);
char *strv_join(char **strv, const char *joiner);
static inline void
@ -291,33 +291,26 @@ kv_double_from_string(const char *string,
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)
size_t npairs;
char **pairs = strv_from_string(string, pair_separator, &npairs);
if (!pairs || npairs == 0)
goto error;
result = zalloc(npairs * sizeof *result);
for (pair = pairs; *pair; pair++) {
char **kv = strv_from_string(*pair, kv_separator);
for (size_t idx = 0; idx < npairs; idx++) {
char *pair = pairs[idx];
size_t nelem;
char **kv = strv_from_string(pair, kv_separator, &nelem);
double k, v;
if (!kv || !kv[0] || !kv[1] || kv[2] ||
if (!kv || nelem != 2 ||
!safe_atod(kv[0], &k) ||
!safe_atod(kv[1], &v)) {
strv_free(kv);
@ -326,7 +319,6 @@ kv_double_from_string(const char *string,
result[idx].key = k;
result[idx].value = v;
idx++;
strv_free(kv);
}

View file

@ -1070,39 +1070,48 @@ START_TEST(strsplit_test)
const char *string;
const char *delim;
const char *results[10];
const size_t nresults;
} tests[] = {
{ "one two three", " ", { "one", "two", "three", NULL } },
{ "one", " ", { "one", NULL } },
{ "one two ", " ", { "one", "two", NULL } },
{ "one two", " ", { "one", "two", NULL } },
{ " one two", " ", { "one", "two", NULL } },
{ "one", "\t \r", { "one", NULL } },
{ "one two three", " t", { "one", "wo", "hree", NULL } },
{ " one two three", "te", { " on", " ", "wo ", "hr", NULL } },
{ "one", "ne", { "o", NULL } },
{ "onene", "ne", { "o", NULL } },
{ NULL, NULL, { NULL }}
{ "one two three", " ", { "one", "two", "three", NULL }, 3 },
{ "one two\tthree", " \t", { "one", "two", "three", NULL }, 3 },
{ "one", " ", { "one", NULL }, 1 },
{ "one two ", " ", { "one", "two", NULL }, 2 },
{ "one two", " ", { "one", "two", NULL }, 2 },
{ " one two", " ", { "one", "two", NULL }, 2 },
{ "one", "\t \r", { "one", NULL }, 1 },
{ "one two three", " t", { "one", "wo", "hree", NULL }, 3 },
{ " one two three", "te", { " on", " ", "wo ", "hr", NULL }, 4 },
{ "one", "ne", { "o", NULL }, 1 },
{ "onene", "ne", { "o", NULL }, 1 },
{ "+1-2++3--4++-+5-+-", "+-", { "1", "2", "3", "4", "5", NULL }, 5 },
/* special cases */
{ "", " ", { NULL }, 0 },
{ " ", " ", { NULL }, 0 },
{ " ", " ", { NULL }, 0 },
{ "oneoneone", "one", { NULL} , 0 },
{ NULL, NULL, { NULL }, 0}
};
struct strsplit_test *t = tests;
while (t->string) {
char **strv;
int idx = 0;
strv = strv_from_string(t->string, t->delim);
while (t->results[idx]) {
size_t nelem;
char **strv = strv_from_string(t->string, t->delim, &nelem);
for (size_t idx = 0; idx < t->nresults; idx++)
ck_assert_str_eq(t->results[idx], strv[idx]);
idx++;
}
ck_assert_ptr_eq(strv[idx], NULL);
ck_assert_uint_eq(nelem, t->nresults);
/* When there are no elements validate return value is Null,
otherwise validate result array is Null terminated. */
if(t->nresults == 0)
ck_assert_ptr_null(strv);
else
ck_assert_ptr_null(strv[t->nresults]);
strv_free(strv);
t++;
}
/* Special cases */
ck_assert_ptr_eq(strv_from_string("", " "), NULL);
ck_assert_ptr_eq(strv_from_string(" ", " "), NULL);
ck_assert_ptr_eq(strv_from_string(" ", " "), NULL);
ck_assert_ptr_eq(strv_from_string("oneoneone", "one"), NULL);
}
END_TEST