shared: implement weston_parse_space_separated_list()

This will be useful for parsing config file entries that have several
items on key, like x,y coordinates or a list of flags. Code reading
custom color profiles from weston.ini will use this.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
This commit is contained in:
Pekka Paalanen 2025-07-29 15:55:02 +03:00 committed by Pekka Paalanen
parent 6ec30279f7
commit fe85ed48fc
3 changed files with 162 additions and 0 deletions

View file

@ -32,6 +32,7 @@ extern "C" {
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#define WESTON_CONFIG_FILE_ENV_VAR "WESTON_CONFIG_FILE"
@ -107,6 +108,20 @@ int weston_config_next_section(struct weston_config *config,
uint32_t
weston_config_get_binding_modifier(struct weston_config *config, uint32_t default_mod);
/** Container for an array of strings. */
struct weston_string_array {
/** Length of \c array. */
size_t len;
/** Pointer to an array of strings. */
char **array;
};
void
weston_string_array_fini(struct weston_string_array *strarr);
struct weston_string_array
weston_parse_space_separated_list(const char *str);
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,6 @@
/*
* Copyright © 2012 Kristian Høgsberg
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -33,8 +34,10 @@
#include <assert.h>
#include <errno.h>
#include <wayland-util.h>
#include <libweston/config-parser.h>
#include "string-helpers.h"
#include "xalloc.h"
static bool
handle_option(const struct weston_option *option, char *value)
@ -209,3 +212,71 @@ parse_options(const struct weston_option *options,
return j;
}
/** Free string array contents
*
* Does not free \c strarr itself but resets it.
*/
void
weston_string_array_fini(struct weston_string_array *strarr)
{
size_t i;
for (i = 0; i < strarr->len; i++)
free(strarr->array[i]);
free(strarr->array);
strarr->len = 0;
strarr->array = NULL;
}
static bool
is_space_for_split(char c)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
/** Split a string at spaces, tabs, CRs, LFs
*
* \param str An arbitrary string, can be empty but not NULL.
* \return An array of sub-strings. Must be finalized with
* weston_string_array_fini().
*
* Takes the given string, and splits it into items. Empty items are skipped.
* The items are returned in the array in the same order they appeared in the
* string. Spaces, tabs, newlines or carriage returns will not be present in
* the items as they cannot be escaped.
*/
struct weston_string_array
weston_parse_space_separated_list(const char *str)
{
struct wl_array arr;
const char *p = str;
char **item;
wl_array_init(&arr);
while (*p) {
const char *end = p;
while (*end && !is_space_for_split(*end))
end++;
size_t len = end - p;
if (len > 0) {
item = wl_array_add(&arr, sizeof *item);
*item = strndup(p, len);
abort_oom_if_null(*item);
}
p = end;
/* Skip whitespaces */
while (*p && is_space_for_split(*p))
p++;
}
return (struct weston_string_array){
.len = arr.size / sizeof *item,
.array = arr.data
};
}

View file

@ -1,5 +1,6 @@
/*
* Copyright © 2013 Intel Corporation
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -924,3 +925,78 @@ TEST(section_from_null)
return RESULT_OK;
}
TEST(parse_comma_separated_list)
{
const char *matter;
struct weston_string_array strarr;
matter = "";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 0);
matter = " ";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 0);
matter = " \t \t \t";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 0);
matter = "k";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 1);
test_assert_str_eq(strarr.array[0], "k");
weston_string_array_fini(&strarr);
matter = " k";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 1);
test_assert_str_eq(strarr.array[0], "k");
weston_string_array_fini(&strarr);
matter = "k ";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 1);
test_assert_str_eq(strarr.array[0], "k");
weston_string_array_fini(&strarr);
matter = " k ";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 1);
test_assert_str_eq(strarr.array[0], "k");
weston_string_array_fini(&strarr);
matter = "kissa kassi";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 2);
test_assert_str_eq(strarr.array[0], "kissa");
test_assert_str_eq(strarr.array[1], "kassi");
weston_string_array_fini(&strarr);
matter = "kissa\tkassi";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 2);
test_assert_str_eq(strarr.array[0], "kissa");
test_assert_str_eq(strarr.array[1], "kassi");
weston_string_array_fini(&strarr);
matter = " kissa\t kassi";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 2);
test_assert_str_eq(strarr.array[0], "kissa");
test_assert_str_eq(strarr.array[1], "kassi");
weston_string_array_fini(&strarr);
matter = " 4.556\ra bab c \nkoe\t";
strarr = weston_parse_space_separated_list(matter);
test_assert_u64_eq(strarr.len, 5);
test_assert_str_eq(strarr.array[0], "4.556");
test_assert_str_eq(strarr.array[1], "a");
test_assert_str_eq(strarr.array[2], "bab");
test_assert_str_eq(strarr.array[3], "c");
test_assert_str_eq(strarr.array[4], "koe");
weston_string_array_fini(&strarr);
return RESULT_OK;
}