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 static bool
parse_value_line(struct quirks_context *ctx, struct section *s, const char *line) parse_value_line(struct quirks_context *ctx, struct section *s, const char *line)
{ {
char **strv;
const char *key, *value;
bool rc = false; bool rc = false;
strv = strv_from_string(line, "="); size_t nelem;
if (strv[0] == NULL || strv[1] == NULL || strv[2] != NULL) { char **strv = strv_from_string(line, "=", &nelem);
if (!strv || nelem != 2)
goto out; goto out;
}
const char *key = strv[0];
key = strv[0]; const char *value = strv[1];
value = strv[1];
if (strlen(key) == 0 || strlen(value) == 0) if (strlen(key) == 0 || strlen(value) == 0)
goto out; goto out;

View file

@ -176,32 +176,31 @@ parse_dimension_property(const char *prop, size_t *w, size_t *h)
bool bool
parse_calibration_property(const char *prop, float calibration_out[6]) parse_calibration_property(const char *prop, float calibration_out[6])
{ {
int idx;
char **strv;
float calibration[6];
if (!prop) if (!prop)
return false; return false;
strv = strv_from_string(prop, " "); bool rc = false;
if (!strv)
return 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; double v;
if (strv[idx] == NULL || !safe_atod(strv[idx], &v)) { if (!safe_atod(strv[idx], &v))
strv_free(strv); goto out;
return false;
}
calibration[idx] = v; calibration[idx] = v;
} }
strv_free(strv);
memcpy(calibration_out, calibration, sizeof(calibration)); memcpy(calibration_out, calibration, sizeof(calibration));
rc = true;
return true; out:
strv_free(strv);
return rc;
} }
bool bool
@ -367,27 +366,19 @@ parse_evcode_string(const char *s, int *type_out, int *code_out)
bool bool
parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents) parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents)
{ {
char **strv = NULL;
bool rc = false; bool rc = false;
size_t ncodes = 0;
size_t idx;
/* A randomly chosen max so we avoid crazy quirks */ /* A randomly chosen max so we avoid crazy quirks */
struct input_event evs[32]; struct input_event evs[32];
memset(evs, 0, sizeof evs); memset(evs, 0, sizeof evs);
strv = strv_from_string(prop, ";"); size_t ncodes;
if (!strv) char **strv = strv_from_string(prop, ";", &ncodes);
goto out; if (!strv || ncodes == 0 || ncodes > ARRAY_LENGTH(evs))
for (idx = 0; strv[idx]; idx++)
ncodes++;
if (ncodes == 0 || ncodes > ARRAY_LENGTH(evs))
goto out; goto out;
ncodes = min(*nevents, ncodes); ncodes = min(*nevents, ncodes);
for (idx = 0; strv[idx]; idx++) { for (size_t idx = 0; strv[idx]; idx++) {
char *s = strv[idx]; char *s = strv[idx];
int type, code; int type, code;
@ -434,24 +425,16 @@ out:
bool bool
parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops) parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops)
{ {
char **strv = NULL;
bool rc = false; bool rc = false;
size_t count = 0;
size_t idx;
unsigned int props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */ unsigned int props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */
strv = strv_from_string(prop, ";"); size_t count;
if (!strv) char **strv = strv_from_string(prop, ";", &count);
goto out; if (!strv || count == 0 || count > ARRAY_LENGTH(props))
for (idx = 0; strv[idx]; idx++)
count++;
if (count == 0 || count > ARRAY_LENGTH(props))
goto out; goto out;
count = min(*nprops, count); count = min(*nprops, count);
for (idx = 0; strv[idx]; idx++) { for (size_t idx = 0; strv[idx]; idx++) {
char *s = strv[idx]; char *s = strv[idx];
unsigned int prop; 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 * 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 * 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. * 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 in Input string
* @param separators List of separator characters * @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 * @return A null-terminated string array or NULL on errors
*/ */
char ** 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); assert(in != NULL);
s = in;
const char *s = in;
size_t l, nelems = 0;
while (next_word(&s, &l, separators) != NULL) while (next_word(&s, &l, separators) != NULL)
nelems++; nelems++;
if (nelems == 0) if (nelems == 0) {
*num_elements = 0;
return NULL; return NULL;
}
nelems++; /* NULL-terminated */ size_t strv_len = nelems + 1; /* NULL-terminated */
strv = zalloc(nelems * sizeof *strv); char **strv = zalloc(strv_len * sizeof *strv);
idx = 0;
size_t idx = 0;
const char *word;
s = in; s = in;
while ((word = next_word(&s, &l, separators)) != NULL) { while ((word = next_word(&s, &l, separators)) != NULL) {
char *copy = strndup(word, l); char *copy = strndup(word, l);
if (!copy) { if (!copy) {
strv_free(strv); strv_free(strv);
*num_elements = 0;
return NULL; return NULL;
} }
strv[idx++] = copy; strv[idx++] = copy;
} }
*num_elements = nelems;
return strv; 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_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); char *strv_join(char **strv, const char *joiner);
static inline void static inline void
@ -291,33 +291,26 @@ kv_double_from_string(const char *string,
struct key_value_double **result_out) struct key_value_double **result_out)
{ {
char **pairs;
char **pair;
struct key_value_double *result = NULL; struct key_value_double *result = NULL;
ssize_t npairs = 0;
unsigned int idx = 0;
if (!pair_separator || pair_separator[0] == '\0' || if (!pair_separator || pair_separator[0] == '\0' ||
!kv_separator || kv_separator[0] == '\0') !kv_separator || kv_separator[0] == '\0')
return -1; return -1;
pairs = strv_from_string(string, pair_separator); size_t npairs;
if (!pairs) char **pairs = strv_from_string(string, pair_separator, &npairs);
return -1; if (!pairs || npairs == 0)
for (pair = pairs; *pair; pair++)
npairs++;
if (npairs == 0)
goto error; goto error;
result = zalloc(npairs * sizeof *result); result = zalloc(npairs * sizeof *result);
for (pair = pairs; *pair; pair++) { for (size_t idx = 0; idx < npairs; idx++) {
char **kv = strv_from_string(*pair, kv_separator); char *pair = pairs[idx];
size_t nelem;
char **kv = strv_from_string(pair, kv_separator, &nelem);
double k, v; double k, v;
if (!kv || !kv[0] || !kv[1] || kv[2] || if (!kv || nelem != 2 ||
!safe_atod(kv[0], &k) || !safe_atod(kv[0], &k) ||
!safe_atod(kv[1], &v)) { !safe_atod(kv[1], &v)) {
strv_free(kv); strv_free(kv);
@ -326,7 +319,6 @@ kv_double_from_string(const char *string,
result[idx].key = k; result[idx].key = k;
result[idx].value = v; result[idx].value = v;
idx++;
strv_free(kv); strv_free(kv);
} }

View file

@ -1070,39 +1070,48 @@ START_TEST(strsplit_test)
const char *string; const char *string;
const char *delim; const char *delim;
const char *results[10]; const char *results[10];
const size_t nresults;
} tests[] = { } tests[] = {
{ "one two three", " ", { "one", "two", "three", NULL } }, { "one two three", " ", { "one", "two", "three", NULL }, 3 },
{ "one", " ", { "one", NULL } }, { "one two\tthree", " \t", { "one", "two", "three", NULL }, 3 },
{ "one two ", " ", { "one", "two", NULL } }, { "one", " ", { "one", NULL }, 1 },
{ "one two", " ", { "one", "two", NULL } }, { "one two ", " ", { "one", "two", NULL }, 2 },
{ " one two", " ", { "one", "two", NULL } }, { "one two", " ", { "one", "two", NULL }, 2 },
{ "one", "\t \r", { "one", NULL } }, { " one two", " ", { "one", "two", NULL }, 2 },
{ "one two three", " t", { "one", "wo", "hree", NULL } }, { "one", "\t \r", { "one", NULL }, 1 },
{ " one two three", "te", { " on", " ", "wo ", "hr", NULL } }, { "one two three", " t", { "one", "wo", "hree", NULL }, 3 },
{ "one", "ne", { "o", NULL } }, { " one two three", "te", { " on", " ", "wo ", "hr", NULL }, 4 },
{ "onene", "ne", { "o", NULL } }, { "one", "ne", { "o", NULL }, 1 },
{ NULL, NULL, { NULL }} { "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; struct strsplit_test *t = tests;
while (t->string) { while (t->string) {
char **strv; size_t nelem;
int idx = 0; char **strv = strv_from_string(t->string, t->delim, &nelem);
strv = strv_from_string(t->string, t->delim);
while (t->results[idx]) { for (size_t idx = 0; idx < t->nresults; idx++)
ck_assert_str_eq(t->results[idx], strv[idx]); ck_assert_str_eq(t->results[idx], strv[idx]);
idx++;
} ck_assert_uint_eq(nelem, t->nresults);
ck_assert_ptr_eq(strv[idx], NULL);
/* 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); strv_free(strv);
t++; 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 END_TEST