conf: implement snd_config_add_before() and snd_config_add_after()

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2019-11-14 16:56:05 +01:00
parent 4724158c0a
commit 4c021697f1
3 changed files with 100 additions and 1 deletions

View File

@ -114,7 +114,9 @@ int snd_config_expand(snd_config_t *config, snd_config_t *root,
int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
snd_config_t *private_data, snd_config_t **result);
int snd_config_add(snd_config_t *config, snd_config_t *leaf);
int snd_config_add(snd_config_t *config, snd_config_t *child);
int snd_config_add_before(snd_config_t *before, snd_config_t *child);
int snd_config_add_after(snd_config_t *after, snd_config_t *child);
int snd_config_remove(snd_config_t *config);
int snd_config_delete(snd_config_t *config);
int snd_config_delete_compound_members(const snd_config_t *config);

View File

@ -86,6 +86,21 @@ static inline void list_add_tail(struct list_head *p, struct list_head *list)
list->prev = p;
}
/* list_insert - insert a new list entry between two known consecutive entries
* @p: the new entry to be inserted between prev and next
* @prev: the left-side entry
* @next: the right-side entry
*/
static inline void list_insert(struct list_head *p,
struct list_head *prev,
struct list_head *next)
{
next->prev = p;
p->next = next;
p->prev = prev;
prev->next = p;
}
/* list_del - delete the given list entry */
static inline void list_del(struct list_head *p)
{

View File

@ -1978,6 +1978,88 @@ int snd_config_add(snd_config_t *parent, snd_config_t *child)
return 0;
}
/**
* \brief Adds a child after another child configuration node.
* \param after Handle to the start configuration node.
* \param child Handle to the configuration node to be added.
* \return Zero if successful, otherwise a negative error code.
*
* This function makes the node \a child a child of the parent of
* the node \a after.
*
* The parent node then owns the child node, i.e., the child node gets
* deleted together with its parent.
*
* \a child must have an id.
*
* \par Errors:
* <dl>
* <dt>-EINVAL<dd>\a child does not have an id.
* <dt>-EINVAL<dd>\a child already has a parent.
* <dt>-EEXIST<dd>\a parent already contains a child node with the same
* id as \a child.
* </dl>
*/
int snd_config_add_after(snd_config_t *after, snd_config_t *child)
{
snd_config_iterator_t i, next;
snd_config_t *parent;
assert(after && child);
parent = after->parent;
assert(parent);
if (!child->id || child->parent)
return -EINVAL;
snd_config_for_each(i, next, parent) {
snd_config_t *n = snd_config_iterator_entry(i);
if (strcmp(child->id, n->id) == 0)
return -EEXIST;
}
child->parent = parent;
list_insert(&child->list, &after->list, after->list.next);
return 0;
}
/**
* \brief Adds a child before another child configuration node.
* \param before Handle to the start configuration node.
* \param child Handle to the configuration node to be added.
* \return Zero if successful, otherwise a negative error code.
*
* This function makes the node \a child a child of the parent of
* the node \a before.
*
* The parent node then owns the child node, i.e., the child node gets
* deleted together with its parent.
*
* \a child must have an id.
*
* \par Errors:
* <dl>
* <dt>-EINVAL<dd>\a child does not have an id.
* <dt>-EINVAL<dd>\a child already has a parent.
* <dt>-EEXIST<dd>\a parent already contains a child node with the same
* id as \a child.
* </dl>
*/
int snd_config_add_before(snd_config_t *before, snd_config_t *child)
{
snd_config_iterator_t i, next;
snd_config_t *parent;
assert(before && child);
parent = before->parent;
assert(parent);
if (!child->id || child->parent)
return -EINVAL;
snd_config_for_each(i, next, parent) {
snd_config_t *n = snd_config_iterator_entry(i);
if (strcmp(child->id, n->id) == 0)
return -EEXIST;
}
child->parent = parent;
list_insert(&child->list, before->list.prev, &before->list);
return 0;
}
/**
* \brief Removes a configuration node from its tree.
* \param config Handle to the configuration node to be removed.